/* =====================================================================
   TASHI
   Palette from Susana's reference card. Creamy and warm, with orange
   used sparingly and never as a surface.
   ===================================================================== */

:root{
  --vanilla:#F1EADA;   /* the page */
  --sand:#CEC1A8;      /* second surface */
  --tobacco:#B59E7D;   /* the big display letters */
  --mountain:#AAA396;  /* the cool partner, hovers and rules */
  --mahogany:#584738;  /* all type, the dark sections */
  --orange:#C8562A;    /* the ball, the bag, nothing else */

  --ink:var(--mahogany);
  --ink-dim:rgba(88,71,56,.82);   /* was .62: 3:1 on vanilla; .82 measures 4.8:1 (Lighthouse, 29 Sep) */
  --hair:rgba(88,71,56,.18);

  --display:'Michroma', system-ui, -apple-system, sans-serif;
  /* One face, used in one place: the hero word. Michroma is square and
     rigid, which is the opposite of a word that bounces. The rest of the
     shop stays Michroma and stays calm. */
  --playful:'Fredoka', 'Comic Sans MS', system-ui, sans-serif;
  --ui:'Inter Tight', system-ui, -apple-system, sans-serif;
  --gutter:clamp(20px, 4.4vw, 68px);
  --nav-h:70px;
}

*{box-sizing:border-box;}
/* Deliberately NOT smooth: scroll-behavior breaks scroll-linked
   interactions like the loop below. */
html{scroll-behavior:auto;}
body{
  margin:0;background:var(--vanilla);color:var(--ink);
  font-family:var(--ui);-webkit-font-smoothing:antialiased;
}

/* ---- grain -----------------------------------------------------------
   Stops the cream reading as flat digital fill and ties the video panel
   to the paper around it. No image, no request. */
.grain{
  position:fixed;inset:-120%;z-index:60;pointer-events:none;
  opacity:.30;mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  animation:grainShift 700ms steps(1) infinite;
}
@keyframes grainShift{
  0%{transform:translate(0,0);}      25%{transform:translate(-2%,1%);}
  50%{transform:translate(1%,-2%);}  75%{transform:translate(-1%,-1%);}
}
/* the page at rest (index.html, 12 s with no hand, scroll or key): the
   grain holds its last offset rather than keep the GPU awake */
.is-still .grain{animation-play-state:paused;}

/* ---- nav: glass over cream ------------------------------------------- */
.nav{
  /* 28 Sep, her QA: glass. A frosted bar floating inside the page's
     margins, not a strip across the top: white sheen brightest at its top
     edge, a thin white rim, a soft shadow under it. Still 70px of room
     (--nav-h) with the gap above. */
  position:fixed;top:12px;left:var(--gutter);right:var(--gutter);height:56px;z-index:40;
  /* mark stays on the left, everything else is pushed to the right by the
     auto margin on .nav__rooms */
  display:flex;align-items:center;justify-content:flex-start;
  gap:clamp(20px,3vw,44px);padding:0 clamp(18px,2vw,28px);border-radius:18px;
  /* 2 Oct, her QA: "the nav bar could also be a little bit more like glass": thinner white, more blur
     and colour through it, a brighter rim. --nav-glass is a dial (D); 0.58 was the 28 Sep bar. */
  --nav-glass:.44;
  background:linear-gradient(180deg,rgba(255,255,255,var(--nav-glass)),rgba(255,255,255,calc(var(--nav-glass) * .38)));
  backdrop-filter:blur(24px) saturate(1.6);
  -webkit-backdrop-filter:blur(24px) saturate(1.6);
  border:1px solid rgba(255,255,255,.7);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),inset 0 -1px 0 rgba(255,255,255,.18),0 12px 34px -16px rgba(58,43,32,.3);
}
.nav__mark{
  display:flex;align-items:center;gap:10px;
  font-family:var(--display);font-weight:400;font-size:15px;
  letter-spacing:.22em;text-transform:uppercase;color:var(--mahogany);text-decoration:none;
}
.nav__dot{width:11px;height:11px;border-radius:50%;background:var(--orange);flex:none;}
.nav__rooms{display:flex;gap:clamp(16px,2.2vw,34px);margin-left:auto;}
.nav__link{
  font-size:12px;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(88,71,56,.62);text-decoration:none;padding:6px 0;
  border-bottom:1px solid transparent;transition:color .25s,border-color .25s;
}
.nav__link:hover{color:var(--mahogany);border-bottom-color:var(--tobacco);}
.nav__cart{
  display:flex;align-items:center;gap:9px;
  font-size:12px;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(88,71,56,.62);text-decoration:none;
}
.nav__count{
  min-width:20px;height:20px;border-radius:10px;background:var(--orange);
  color:var(--vanilla);font-size:11px;letter-spacing:0;
  display:grid;place-items:center;padding:0 6px;
}

/* ---- hero: big letters, dog in the middle ----------------------------
   The word runs full width behind a narrow video column, so the letters
   emerge either side of him. No cutout needed: the panel is the crop. */
.hero{
  position:relative;height:100svh;min-height:660px;overflow:hidden;
  perspective:1600px;perspective-origin:50% 46%;
  /* Turned over to match the reference, which is 78% near-white and 18%
     near-black. A dark word only reads as dark against a light field, and
     the shop below the fold is already cream, so the page stops changing
     temperature halfway down. */
  background:
    radial-gradient(88% 70% at 50% 62%,
      rgba(255,249,236,.95) 0%, rgba(244,236,220,.5) 42%, rgba(233,222,199,0) 74%),
    linear-gradient(168deg, #EFE7D6 0%, #E8DFCB 46%, #DCD0B7 100%);
}

/* ---- the sun ----------------------------------------------------------
   A warm disc behind him, and the reason the letters look backlit.

   The light source is a real object in the stack rather than a glow
   painted on top: it sits UNDER the type, and the type's own fill
   carries a second radial gradient centred on the same point. Where a
   letter crosses the sun it brightens; away from it, it falls back to
   the faint tan. That difference across a single letter is what the eye
   reads as light coming from behind.

   The blur is what stops it reading as a printed circle. It is static
   after the intro, so it rasterises once. */
.hero__sun{
  position:absolute;left:50%;top:57%;z-index:0;
  width:min(58vh,580px);aspect-ratio:1;
  transform:translate(-50%,-50%);border-radius:50%;
  pointer-events:none;
  /* Seven bands rather than one smooth falloff, each held flat across its
     own ring and handed over in 1.5%, so the disc reads as a little sun
     with rings instead of a haze. One hue family the whole way out: cream,
     butter, amber, then burnt.

     He is 650px wide and stands on this same centre, so the inner rings
     are hidden behind him. The disc is sized so the banding starts at
     about 60% of the radius, which is where his silhouette ends and the
     first visible ring begins. */
  /* 28 Sep, her QA: a little bigger (42vh became 58vh) and feathered, so
     it blends into the page instead of showing its rings' edges. Same
     colours, handed over gradually now rather than in 1.5% steps, and a
     wider blur. */
  background:radial-gradient(circle at 50% 50%,
    rgba(255,226,158,.56)  0%,  rgba(255,226,158,.52) 22%,
    rgba(253,210,132,.44) 38%,  rgba(248,188,102,.33) 52%,
    rgba(238,162,76,.21)  66%,  rgba(222,134,58,.10)  80%,
    rgba(200,108,46,.03)  91%,  rgba(200,108,46,0)   100%);
  filter:blur(26px);
  opacity:0;animation:fade 2.4s ease .25s forwards;
}

/* 28 Sep: for one afternoon this disc held Componentry's Dither Prism
   (WebGL). It fought the other effects, and she asked for these painted
   rings back. The port is kept in _effects-library/sources/componentry-
   dither-prism-hero/ (tashi-port-*). */

/* ---- left column: the type block --------------------------------- */
/* The shop's own name, small, under him. The big word at the top is the
   statement; this is the signature, and it is set in the shop's face
   rather than the playful one so the two do not compete. */
.hero__sig{
  position:absolute;left:50%;bottom:clamp(118px,16vh,168px);z-index:5;
  transform:translateX(-50%);margin:0;
  font-family:var(--display);font-weight:400;
  font-size:clamp(17px,2.4vw,34px);letter-spacing:.42em;text-indent:.42em;
  text-transform:uppercase;color:rgba(88,71,56,.6);white-space:nowrap;
  opacity:0;animation:fade 1.3s ease .9s forwards;
}

/* A single row along the floor of the frame: line and primary action on
   the left, secondary on the right. Nothing sits in the middle third any
   more, which is what gives the word and the dog the whole centre. */
.hero__bar{
  position:absolute;left:var(--gutter);right:var(--gutter);
  bottom:clamp(64px,9vh,96px);z-index:5;
  display:flex;align-items:flex-end;justify-content:space-between;gap:24px;
  opacity:0;transform:translateY(16px);
  animation:rise 1.05s cubic-bezier(.22,1,.36,1) .7s forwards;
}
/* 28 Sep, second pass (her QA: "two words in a little corner ... make it
   look more editorial"). The claim is set large in the shop's own face,
   the button under it; the two quieter sentences stand on the right
   under a hairline. Both sit on the floor of the frame. */
.hero__bar__left{display:flex;flex-direction:column;align-items:flex-start;gap:26px;}
.hero__line{
  margin:0;font-family:var(--display);font-weight:400;
  font-size:clamp(24px,2.7vw,42px);line-height:1.08;letter-spacing:-.02em;
  color:var(--mahogany);
}
.hero__arc{
  margin:0;max-width:26ch;font-size:15px;line-height:1.65;
  color:rgba(88,71,56,.84);text-wrap:pretty;
  padding-top:16px;border-top:1px solid rgba(88,71,56,.3);
}
/* His name, twice. One warm layer behind him, one in white crossing his
   chest in front. The overlap is the point: he is inside his own name. */
/* Architectural. The letters are stretched vertically so they read as a
   structure he is standing against.

   TWO copies, and the second one is the whole trick. The solid copy sits
   behind him. A very faint copy sits IN FRONT, in the same place, so the
   word appears to continue across his body. That is what makes him read
   as being INSIDE the word rather than merely in front of it — the
   "in between" quality in the Bluebird reference. Push --veil past about
   0.2 and the illusion collapses into an overlay. */
.hero__name{
  /* he and the word share one centre, so he hides the middle of it and
     the same amount of type clears him on either side */
  position:absolute;left:50%;top:27%;margin:0;text-align:center;
  /* translateZ puts the word on a further plane for real. It renders
     smaller from back there, at 1600/(1600+380) = 0.81, so the type size
     below is divided by that to land at the intended size on screen. */
  /* 1.36 is about as far as a round face will stretch before the bowls
     go visibly ovoid. The square one took 1.62. */
  transform:translate(-50%,-50%) translateZ(-380px) scaleY(1.36);
  /* 700 here as well as on the axis below. The material layer draws the
     letters on a canvas, and a canvas only reads font-weight: at 400 it cut
     the thin Fredoka out of renders modelled on the heavy one (28 Sep). */
  font-family:var(--playful);font-weight:700;
  /* Fredoka is variable on both axes. Heaviest weight, and width left at
     100 rather than opened up: a narrower letter at the same word width
     is a TALLER letter, which is where the size comes from. */
  font-variation-settings:'wdth' 100,'wght' 700;
  /* Grigoletto's values, read off the file: tracking -4%, line-height 1.
     Ours was +0.005em, which is why the letters read as separate rather
     than as one mass. */
  /* Five letters instead of seven, so each one is 40% bigger for the same
     total width: 34.9vw with 0.10em of tracking spans the frame exactly.
     The wider slots also matter for what comes next, because a fatter
     letter shows more of whatever material is revealed inside it. */
  /* Down from 34.9vw. At 1440 that ran the word a little past the frame,
     and on a wide window it filled the whole thing edge to edge. 27vw
     lands it at about 78%, which leaves the frame some air. */
  font-size:clamp(110px,27vw,468px);line-height:1;letter-spacing:.10em;
  text-transform:uppercase;pointer-events:none;white-space:nowrap;
  opacity:0;animation:fade 1.6s ease .2s forwards;
}
/* Behind him. The fill is a vertical gradient CLIPPED TO THE LETTERS —
   solid at the top, dissolving toward the bottom — which is the actual
   technique in the Bluebird file, not a flat low-alpha colour. Their
   stops: solid to 83.395%, transparent by 104.81%. */
.hero__name--back{
  z-index:1;
  color:transparent;
  /* The fill is held here as a custom property rather than applied here,
     because the word is split into per-letter spans and each letter has
     to carry its own slice of it. js/letter-warp.js sets background-size
     to the whole word and offsets each letter, so the seven slices line
     back up into one continuous gradient.

     Backlight first, the Bluebird vertical fade underneath it. The radial
     is squashed vertically because the element is scaled on Y: it comes
     out round on screen, sitting over the sun. */
  --fill:
    radial-gradient(62% 226% at 50% 48%,
      rgba(48,34,25,.97)  0%,
      rgba(52,38,28,.95) 40%,
      rgba(58,43,32,.93) 74%,
      rgba(62,47,35,.92) 100%),
    linear-gradient(180deg,
      rgba(58,43,32,.06) 0%, rgba(58,43,32,0) 100%);
  /* a little bloom off the glyph edges, following their alpha */
  /* two pixels of blur is invisible as blur at this size, but it leaves
     the letters fractionally softer than his fur, and that difference in
     edge sharpness is what the eye actually reads as distance */
  /* no bloom on a dark word: a glow around it on a light field reads as a
     printing fault rather than as light */
  filter:blur(1px);
}
/* The material layer, over the cream letters and under the clouds.

   It started on mix-blend-mode:screen, on the theory that the renders are
   bright letters on pure black and screen makes black disappear for free.
   That was wrong in practice: screen only ever lightens, the cream letters
   are already near-white, and the material had nothing left to lighten. So
   every source now carries its own alpha, cut from its own luminance, and
   the material REPLACES the letter rather than brightening it. Which is
   what the reference does too: their flat letters are black and the
   uncovered patch shows the material instead of tinting it. */
/* width and height are not optional here. A canvas is a replaced element,
   and inset:0 does NOT stretch a replaced element: it shows at the size of
   its backing store. The backing store is the hero times devicePixelRatio,
   so on any Retina screen the material came out at twice the size, the
   giant letters of 1 Sep. It looked right on a 1x test window, which is
   why it survived. */
.hero__mat{
  position:absolute;inset:0;width:100%;height:100%;z-index:1;pointer-events:none;
}

/* One letter. inline-block because transform does nothing to a plain
   inline box, and will-change because every one of these is animated on
   its own spring every frame the ball is on screen. */
.ltr{display:inline-block;will-change:transform;}
.hero__name--back .ltr{
  background-image:var(--fill);
  -webkit-background-clip:text;
          background-clip:text;
  color:transparent;
}
/* Once the material layer is drawing, the word IS the material, so the
   brown fill goes. The letters stay in the layout: the material and the
   cut are both placed from their boxes. */
.hero.mat-live .hero__name--back .ltr{background-image:none;}
/* The veil sits a few pixels off the split letters (it is plain text, they
   are separate boxes). On the brown word that disappeared into the dark
   letters; on a material it reads as a grey shadow beside every letter.
   Off while the material plays. */
.hero.mat-live .hero__name--veil{visibility:hidden;}
/* the veil: same word, same place, in front of him */
.hero__name--veil{
  z-index:4;
  color:rgba(58,43,32, var(--veil, .10));
  mix-blend-mode:multiply;
}
.btn{
  display:inline-flex;align-items:center;gap:9px;
  padding:13px 22px;border-radius:100px;text-decoration:none;
  font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  border:1px solid transparent;transition:background .28s,color .28s,border-color .28s;
}
.btn--fill{background:var(--mahogany);color:var(--vanilla);}
.btn--fill:hover{background:#43342A;}
.btn--ghost{border-color:rgba(88,71,56,.34);color:rgba(88,71,56,.86);}
.btn--ghost:hover{border-color:var(--mahogany);color:var(--mahogany);}
.btn i{font-style:normal;transition:transform .28s cubic-bezier(.22,1,.36,1);}
.btn:hover i{transform:translateX(4px);}

/* ---- right: Tashi, big enough to break the frame ------------------ */
.stage{
  /* the intro fade lives here, not on the sprite: a forwards-filled
     animation would outrank the inline opacity the swap needs */
  opacity:0;animation:fade 1.2s ease .1s forwards;
  /* Centred inside the right 60% band: that band spans 40%-100%,
     so its middle is 70% across. He needs room on both sides of
     him for the ball to move. */
  /* Middle band. He is no longer the hero of the frame, the word is, so
     he sits between the word above and his own name below rather than
     standing on the floor of it. */
  position:absolute;left:50%;top:59%;z-index:3;
  transform:translate(-50%,-50%);
  height:min(44svh,430px);aspect-ratio:420 / 488;
  pointer-events:none;
}
.stage.ball-on{cursor:none;}
/* the ball is the cursor on the whole page (her QA, 29 Sep): no arrow, no hand, no resize arrows beside it */
html.ball-on,html.ball-on *{cursor:none !important;}
.sprite{
  position:absolute;inset:0;
  background-repeat:no-repeat;
  /* size and position are driven by js/sprite-scrub.js */
  filter:drop-shadow(-18px 26px 40px rgba(12,6,3,.5));
}
.sprite--sweep{
  background-image:url('../assets/character/tashi-sprite.webp');
}
/* iPhone and iPad (every browser there is WebKit): the drop-shadow is cut off at the edge of his
   picture's box, and the cut showed as a darker rectangle around him (her phone, 29 Sep: "Tashi is
   very stuck on that box"; measured 20 to 25% darker inside the edge by his tail and paws). There
   a soft oval under his paws stands in for it. Desktop browsers let the shadow fade and keep it. */
@supports (-webkit-touch-callout: none){
  .sprite{filter:none;}
  .stage::before{
    content:"";position:absolute;left:14%;right:14%;bottom:-1%;height:10%;border-radius:50%;
    background:radial-gradient(closest-side,rgba(40,24,12,.34),rgba(40,24,12,.12) 60%,rgba(40,24,12,0));
    pointer-events:none;
  }
}

/* The ball's own tail, under the ball and over everything else. Its own
   canvas because it must NOT be clipped to the letters the way the
   material layer is. */
.comet{
  /* same trap as .hero__mat: without the size, twice the size on Retina */
  position:fixed;inset:0;width:100%;height:100%;z-index:44;pointer-events:none;
}
.ball{
  position:fixed;top:0;left:0;
  /* 28 Sep, her: smaller, it is the cursor on the whole site (was 86) */
  width:60px;height:60px;margin:-30px 0 0 -30px;
  z-index:45;pointer-events:none;
  /* The stale-paint fix (29 Sep, her "i keep losing the ball", reproduced): switching the ball from
     invisible to visible made the browser keep painting it where it first appeared (the top-left
     corner, or full size) and ignore its later moves until a click. So it never switches: it is
     always visible, and "away" means parked off screen. */
  will-change:transform;transform:translate(-400px,-400px);
  background:url('../assets/ball/ball.png') center/contain no-repeat;
  filter:drop-shadow(0 10px 20px rgba(12,6,3,.5));
}
.ball.is-live{}   /* kept as a hook; the ball is never hidden by opacity (see .ball) */

.hero__cue{
  position:absolute;left:var(--gutter);bottom:26px;z-index:3;
  display:flex;align-items:center;gap:11px;
  font-size:10px;letter-spacing:.3em;text-transform:uppercase;
  color:rgba(88,71,56,.46);text-decoration:none;
  opacity:0;animation:fade 1s ease 1.5s forwards;
}
.hero__cue i{display:block;width:46px;height:1px;background:rgba(241,234,218,.28);}
.hero__cue.is-gone{opacity:0;transition:opacity .5s;}

@keyframes rise{to{opacity:1;transform:translateY(0);} }
@keyframes fade{to{opacity:1;} }

/* ---- the shop: walk, eat, rest --------------------------------------- */
/* 28 Sep. The four room tiles became three objects, one for each part of
   his day, each given a great deal of room: a shop that can afford to
   leave most of the page empty reads as expensive (costly signalling, and
   Crawford's "space is a signal").

   Built the way the Pavonia pieces are: the picture holds still on one
   side while the words change beside it. Each object has three steps,
   the room it lives in, what it is made of, and the object alone, and up
   to three pictures to match. An object with fewer pictures keeps the one
   it has while its words move on. js/shop.js flips the steps from
   IntersectionObserver alone: no scroll handler, no animation loop. */
/* 29 Sep, her third pass: scroll moves him, a click changes the picture. A piece is
   pinned for its film (--film-h) and a short rest after it (--hold-h), in vh; the
   materials and the object come by click, so they no longer need scroll of their own. */
/* 29 Sep, later: his film now plays by itself when the picture lands, so the scroll no longer
   needs a stretch to play it (--film-h 0); the picture rests a little longer instead (--hold-h). */
.shop{background:var(--vanilla);--pic-w:60;--film-h:0;--hold-h:30;}   /* 60 felt stuck (her QA, 29 Sep) */
/* --step-h was 85 on the first build: the walk, one picture for three
   steps, then held the screen for over two screens of scrolling, and it
   read as the end of the page (Susana, 28 Sep: "where is the rest?") */
.eyebrow{
  font-size:11px;letter-spacing:.32em;text-transform:uppercase;
  color:var(--ink-dim);margin:0 0 clamp(24px,4.5vh,50px);
}
/* The opening, 28 Sep second pass (her QA: "a UI pass" and new words). An
   editorial split under a hairline: the belief as a statement on the
   left, the plain explanation on the right, meeting on one baseline. */
.shop__head{
  min-height:78vh;display:flex;flex-direction:column;justify-content:center;
  padding:16vh max(var(--gutter),8vw) 12vh;
}
.shop__intro{
  display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);
  gap:clamp(32px,6vw,110px);align-items:end;
  border-top:1px solid var(--hair);padding-top:clamp(28px,5vh,56px);
}
.shop__title{
  font-family:var(--display);font-weight:400;
  font-size:clamp(32px,4.4vw,70px);line-height:1.02;letter-spacing:-.03em;margin:0;max-width:15ch;
}
.shop__lede{font-size:15px;line-height:1.75;color:rgba(88,71,56,.82);margin:0;max-width:38ch;text-wrap:pretty;}
@media (max-width:820px){ .shop__intro{grid-template-columns:1fr;} }

/* the sections the buttons jump to land their top edge on the nav's */
section[id]{scroll-margin-top:var(--nav-h);}

/* the stage is pinned for the rest only; with a film, for the film and the rest */
.piece{position:relative;height:calc(100vh + var(--hold-h) * 1vh);}
/* a room that is a film gets its own stretch of scroll, in which the scroll plays it (js/shop.js) */
.piece.has-film{height:calc(100vh + (var(--film-h) + var(--hold-h)) * 1vh);}
/* the Rest piece stays pinned a stretch longer: the scroll that walks him out (js/shop.js, 29 Sep) */
#rest{--hold-h:20;--leave-h:150;}
/* her QA, 29 Sep: the bed "looks very big at the beginning, and there's almost no space coming in":
   the Rest picture is wider (70%), so more of the room and of his walk shows; its words sit closer in */
#rest .piece__card{padding:0 max(var(--gutter),3.5vw);}
/* while the scroll walks him out: the glass bars and the arrow step aside (a click there did nothing),
   and the line along the foot shows how far out he is, so the scroll reads as moving him */
.piece.is-leaving .piece__bars,.piece.is-leaving .piece__replay{opacity:0;pointer-events:none;}
.piece.is-leaving .piece__line{pointer-events:none;}   /* a short rest, then the scroll walks him out: room for his pace (her QA) */
.piece.has-leave{height:calc(100vh + (var(--film-h) + var(--hold-h) + var(--leave-h)) * 1vh);}
/* a jump to an object lands with its picture already pinned; section[id]
   above would stop it a nav's height short, and it outranks a lone class */
.shop .piece{scroll-margin-top:0;}
.piece__stage{position:sticky;top:0;height:100vh;display:flex;align-items:stretch;overflow:hidden;}
.piece--flip .piece__stage{flex-direction:row-reverse;}
/* Whatever the window, the bowls' whole stand stays in (her QA: "make it
   fit"). Their room is the widest picture; on a screen too tall for the
   68% column to hold it at full height, it is fitted instead of filled. */
/* the room picture is 16:9 now (him at the bowls): cover fits on most screens; only a tall window letterboxes it on cream */
/* only the room and its film: the materials picture fills its frame like the others (29 Sep) */
@media (max-aspect-ratio:160/100){ #eat .piece__pics img:first-child, #eat .piece__film{object-fit:contain;} }
/* The picture is the height of the section, flush to the outer edge (her
   ask, 28 Sep, after a pass where it floated smaller in the middle). The
   rooms are wider than this column, so each is aimed at its object with
   --focus, and the column is 60% wide, so the bed, the bowls and him on
   the walk all stay whole; only the room around them is trimmed. */
.piece__pics{
  position:relative;flex:none;margin:0;
  width:calc(var(--pic-w) * 1vw);height:100vh;background:var(--vanilla);
}
.piece__pics img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:var(--focus,50% 50%);
  opacity:0;transition:opacity .9s ease;
}
.piece__pics img.is-on{opacity:1;}
/* The object alone. When the web copy was made its paper was flattened
   to the page's own cream (the paper's light fitted from the empty border
   and divided out), so it sits in the page rather than on a white card,
   small, with the room around it that the scene had. No edge fade: the
   object stays hard-edged. */
/* bigger (her QA): no padding now, the object alone fills its column's
   height; its paper is the page's cream, so the frame never shows */
.piece__pics img.is-cutout{object-fit:contain;padding:0;}
/* 3 Oct, her QA ("Click for the materials ... not the same as the two previous ones, on the leash"): the Walk box stands
   taller than the Bed and the Bowls and its lid ran up under the words; room above it, as the other two have */
#walk .piece__pics img.is-cutout{padding:11% 3% 0;box-sizing:border-box;}
/* The room as a short film (the Rest: he trots in and settles). It lies
   over the room picture, framed exactly like it, and fades away when it
   ends, onto that picture, which is its own last frame. Under the ripple
   and the dots. */
.piece__film{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:var(--focus,50% 50%);z-index:1;pointer-events:none;
  opacity:1;transition:opacity .6s ease;
}
.piece__film.is-done{opacity:0;}
/* him walking out, driven by the scroll; above the arrival film, shown only while he is leaving */
.piece__leave{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:var(--focus,50% 50%);
  z-index:2;pointer-events:none;opacity:0;}
.piece__leave.is-on{opacity:1;}
/* The circle arrow that plays his film again, floating like the cue, a full 44px to press; and
   the thin line along the foot of the picture (29 Sep, her "a little arrow or something like
   scrub to control it"): it fills as he plays, and dragging it moves him back and forth. */
.piece__replay{position:absolute;right:10px;bottom:16px;z-index:4;width:44px;height:44px;padding:0;border:0;background:none;
  display:flex;align-items:center;justify-content:center;color:#FFF9F0;cursor:pointer;
  filter:drop-shadow(0 1px 3px rgba(30,20,12,.7)) drop-shadow(0 0 8px rgba(30,20,12,.35));
  opacity:0;visibility:hidden;transition:opacity .4s ease,visibility 0s linear .4s;}
.piece__replay[data-on="1"]{opacity:1;visibility:visible;transition:opacity .4s ease;}
.piece__replay svg{width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.piece__replay:focus-visible{outline:2px solid #FFF9F0;outline-offset:-4px;border-radius:50%;}
.piece__line{position:absolute;left:16px;right:16px;bottom:0;height:20px;z-index:4;cursor:ew-resize;touch-action:none;
  --p:0;opacity:0;visibility:hidden;transition:opacity .4s ease,visibility 0s linear .4s;}
.piece__line[data-on="1"]{opacity:1;visibility:visible;transition:opacity .4s ease;}
.piece__line::before{content:"";position:absolute;left:0;right:0;top:9px;height:2px;border-radius:2px;
  background:rgba(255,249,240,.38);box-shadow:0 0 6px rgba(30,20,12,.35);}
.piece__line-fill{position:absolute;left:0;top:9px;height:2px;border-radius:2px;width:calc(var(--p) * 100%);background:#FFF9F0;}
.piece__line-knob{position:absolute;top:10px;left:calc(var(--p) * 100%);width:12px;height:12px;margin:-6px 0 0 -6px;border-radius:50%;
  background:#FFF9F0;box-shadow:0 1px 4px rgba(30,20,12,.55);transition:transform .2s ease;}
.piece__line:hover .piece__line-knob,.piece__line:active .piece__line-knob{transform:scale(1.35);}
/* the ripple between two pictures (js/ripple.js): over both, only while a
   change is under way */
.piece__ripple{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;visibility:hidden;z-index:2;}
/* The three steps as glass prisms (29 Sep, her ask: "not a pill, but three
   glass-prism little bars ... an indicator that activates every time
   someone clicks"). They stand at the picture's inner edge, one per step:
   the room, the materials, the object. The one showing is taller and holds
   the light; a click sends a glint through it; during the first tour the
   light rises in it as the time passes (--dwell). Their name shows on
   hover or focus. */
.piece__bars{position:absolute;left:50%;bottom:22px;transform:translateX(-50%);z-index:5;display:flex;flex-direction:row;align-items:center;gap:8px;}
.piece__bar{
  position:relative;display:block;width:26px;height:7px;padding:0;border:0;border-radius:5px;cursor:pointer;
  background:linear-gradient(115deg,rgba(255,255,255,.64) 0%,rgba(255,255,255,.14) 48%,rgba(255,255,255,.42) 100%);
  backdrop-filter:blur(10px) saturate(1.3);-webkit-backdrop-filter:blur(10px) saturate(1.3);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.72),inset 1px 0 2px rgba(255,255,255,.9),0 8px 18px -8px rgba(40,28,20,.55);
  transition:width .45s cubic-bezier(.2,.8,.2,1),box-shadow .35s ease;
}
/* the glass itself: a faint spectrum along its edge, and the glint band waiting above it */
.piece__bar-fill{
  position:absolute;inset:0;border-radius:inherit;overflow:hidden;pointer-events:none;
  background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.95) 50%,transparent 100%) -140% 0/55% 100% no-repeat;
}
.piece__bar-fill::before{
  content:"";position:absolute;inset:0;border-radius:inherit;mix-blend-mode:screen;opacity:.35;transition:opacity .35s ease;
  background:linear-gradient(90deg,rgba(255,140,140,0) 0%,rgba(255,196,120,.55) 28%,rgba(170,235,190,.45) 50%,rgba(140,200,255,.55) 72%,rgba(200,150,255,0) 100%);
}
/* the light that rises while the tour waits on this step */
.piece__bar-fill::after{
  content:"";position:absolute;inset:0;border-radius:inherit;background:rgba(255,250,240,.8);
  transform:scaleY(0);transform-origin:bottom center;
}
.piece__bar[aria-current="step"]{
  width:44px;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.95),inset 1px 0 3px rgba(255,255,255,1),0 0 18px rgba(255,246,228,.85),0 10px 22px -8px rgba(40,28,20,.55);
}
.piece__bar[aria-current="step"] .piece__bar-fill::before{opacity:.85;}
.piece__bar.is-timing .piece__bar-fill::after{animation:bar-rise var(--dwell,4.2s) linear both;}
@keyframes bar-rise{from{transform:scaleY(0);}to{transform:scaleY(1);}}
@keyframes bar-rise-x{from{transform:scaleX(0);}to{transform:scaleX(1);}}
.piece__bar.is-glint .piece__bar-fill{animation:bar-glint .75s cubic-bezier(.3,.6,.3,1);}
@keyframes bar-glint{from{background-position:-140% 0;}to{background-position:240% 0;}}
.piece__bar:hover{box-shadow:inset 0 0 0 1px rgba(255,255,255,.95),inset 1px 0 3px rgba(255,255,255,1),0 0 12px rgba(255,246,228,.6),0 8px 18px -8px rgba(40,28,20,.55);}
.piece__bar:focus-visible{outline:2px solid var(--mahogany);outline-offset:3px;}
/* the step's name, on hover or focus, on a small glass chip beside the bar */
.piece__bar-label{
  position:absolute;top:50%;transform:translateY(-50%);white-space:nowrap;pointer-events:none;
  font:500 10px/1 var(--ui);letter-spacing:.22em;text-transform:uppercase;color:#FFF9F0;
  text-shadow:0 1px 10px rgba(30,20,12,.75),0 0 2px rgba(30,20,12,.55);   /* no chip: she moved away from pills, 29 Sep */
  opacity:0;transition:opacity .25s ease;
}
.piece__bar-label{top:auto;bottom:calc(100% + 10px);left:50%;transform:translateX(-50%);}
/* a bar is 7px to the eye and 45px to the thumb (WCAG target size) */
.piece__bar::before{content:"";position:absolute;left:-4px;right:-4px;top:-19px;bottom:-19px;}
.piece__bar:hover .piece__bar-label,.piece__bar:focus-visible .piece__bar-label{opacity:1;}
/* a click on the picture shows the next picture (her ask, 29 Sep: scroll moves him, click changes the picture) */
.piece__pics.is-browsable{cursor:pointer;}
.piece__ripple.is-on{visibility:visible;}

/* ---- the cue at the top of a picture (29 Sep) ----------------------------
   Her ask: "a little thing on the top that starts blinking and says scroll
   to discover". Two moods on one spot under the nav: "Scroll to discover"
   with his paw steps while the film is still to play (scroll moves him),
   then "Click for the materials" with a tap ring once he has settled (a
   click changes the picture). js/shop.js sets data-mode.
   Her pick: 2, the paw steps, and NO PILL ("I really want to move away
   from pill"): it floats like the Umbral cloud did, a small word and the
   steps under it, light with a soft dark halo so it reads on any picture.
   (A glass capsule came first, then a slim pill; both refused.) The other
   five icons stay on the dial "Scroll cue" (press D) and in
   _design/scroll-cues.html. Heat: the animations exist only while a cue
   shows, and rest after a few rounds. */
/* a picture is scrubbed sideways, never dragged out of the page (js/shop.js) */
.piece__pics{-webkit-user-select:none;user-select:none;}
.piece__pics img,.piece__pics video{-webkit-user-drag:none;}
.piece__cue{position:absolute;left:var(--cue-x,50%);top:calc(var(--nav-h) + 20px);z-index:4;margin:0;pointer-events:none;}   /* --cue-x per piece keeps it off his head */
.piece__cue-scroll,.piece__cue-click{
  position:absolute;left:0;top:0;transform:translate(-50%,-6px);
  display:flex;flex-direction:column;align-items:center;gap:10px;white-space:nowrap;
  opacity:0;visibility:hidden;transition:opacity .5s ease,transform .5s ease,visibility 0s linear .5s;
}
.piece__cue[data-mode="scroll"] .piece__cue-scroll,
.piece__cue[data-mode="click"] .piece__cue-click{opacity:1;visibility:visible;transform:translate(-50%,0);transition:opacity .5s ease,transform .5s ease;}
.piece__cue-word{
  display:block;white-space:nowrap;font:500 10.5px/1 var(--ui);letter-spacing:.24em;text-transform:uppercase;color:#FFF9F0;
  text-shadow:0 1px 10px rgba(30,20,12,.75),0 0 2px rgba(30,20,12,.55);
}
.piece__cue[data-mode="scroll"] .piece__cue-scroll .piece__cue-word{animation:cue-blink 1.8s ease-in-out 6;}
/* the click cue is louder and keeps blinking while it shows (her ask: "something a little bit more obvious") */
.piece__cue-click .piece__cue-word{font-size:12.5px;letter-spacing:.2em;}
.piece__cue[data-mode="click"] .piece__cue-click .piece__cue-word{animation:cue-blink 1.6s ease-in-out infinite;}
@keyframes cue-blink{0%,100%{opacity:1;}50%{opacity:.4;}}
/* on the paper pictures (the object, the materials) the cue is ink: the light
   word's dark halo read as a smudge on cream (29 Sep). js/shop.js sets data-tone */
.piece__cue[data-tone="paper"] .piece__cue-word,
.piece__cue[data-tone="paper"] .piece__cue-icon,
.piece__cue[data-tone="paper"] .cue-tap{color:var(--mahogany);text-shadow:none;filter:none;}
.piece__cue-icon{display:flex;flex-direction:column;align-items:center;gap:6px;color:#FFF9F0;
  filter:drop-shadow(0 1px 3px rgba(30,20,12,.7)) drop-shadow(0 0 8px rgba(30,20,12,.35));}
/* 1 puffs: the Umbral cue, little clouds drifting down, each glowing in turn */
.cue-puffs{display:flex;flex-direction:column;align-items:center;gap:5px;}
.cue-puffs i{display:block;border-radius:50%;opacity:.25;filter:blur(.7px);
  background:radial-gradient(ellipse at center,#FFFCF6,rgba(250,236,214,.62) 42%,rgba(250,236,214,0) 72%);}
.cue-puffs i:nth-child(1){width:14px;height:6px;}
.cue-puffs i:nth-child(2){width:20px;height:8px;}
.cue-puffs i:nth-child(3){width:27px;height:10px;}
.cue-puffs i:nth-child(4){width:35px;height:13px;}
[data-mode="scroll"] .cue-puffs i{animation:cue-puff 2s ease-out 7;}
[data-mode="scroll"] .cue-puffs i:nth-child(2){animation-delay:.4s;}
[data-mode="scroll"] .cue-puffs i:nth-child(3){animation-delay:.8s;}
[data-mode="scroll"] .cue-puffs i:nth-child(4){animation-delay:1.2s;}
@keyframes cue-puff{0%{opacity:.25;transform:translate(0,-6px) scaleX(.8);}18%{opacity:1;transform:translate(1px,0) scaleX(1);}55%{opacity:.45;transform:translate(-2px,5px) scaleX(1.2);}100%{opacity:.25;transform:translate(0,8px) scaleX(1.35);}}
.cue-chev{display:block;width:18px;height:11px;opacity:.55;}
.cue-chev path{fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;}
[data-mode="scroll"] .cue-chev{animation:cue-chev 2s ease-out 1.9s 7;}
@keyframes cue-chev{0%{opacity:.45;transform:translateY(-2px);}18%{opacity:1;transform:translateY(3px);}55%,100%{opacity:.45;transform:translateY(0);}}
/* 2 paws: his footsteps walking down, lighting one after another */
.cue-paws{display:grid;grid-template-columns:repeat(2,15px);column-gap:8px;row-gap:2px;}
.cue-paws svg{display:block;width:15px;height:15px;fill:currentColor;opacity:.85;}
.cue-paws svg:nth-child(odd){grid-column:1;transform:rotate(-14deg);}
.cue-paws svg:nth-child(even){grid-column:2;transform:rotate(14deg);margin-top:8px;}
[data-mode="scroll"] .cue-paws svg{animation:cue-step 2.4s ease-in-out 6 backwards;}
[data-mode="scroll"] .cue-paws svg:nth-child(2){animation-delay:.4s;}
[data-mode="scroll"] .cue-paws svg:nth-child(3){animation-delay:.8s;}
[data-mode="scroll"] .cue-paws svg:nth-child(4){animation-delay:1.2s;}
@keyframes cue-step{0%,100%{opacity:.14;}14%{opacity:1;}44%{opacity:.14;}}
/* 3 ball: the site's own ball, bouncing down */
.cue-ball{position:relative;display:block;width:22px;height:36px;}
.cue-ball b{position:absolute;left:4px;top:0;width:14px;height:14px;background:url('../assets/ball/ball.png') center/contain no-repeat;}
.cue-ball i{position:absolute;left:5px;bottom:1px;width:12px;height:3px;border-radius:50%;background:rgba(40,26,16,.5);filter:blur(1px);opacity:.4;}
[data-mode="scroll"] .cue-ball b{animation:cue-bounce 1.3s cubic-bezier(.45,0,.55,1) 9;}
[data-mode="scroll"] .cue-ball i{animation:cue-shadow 1.3s cubic-bezier(.45,0,.55,1) 9;}
@keyframes cue-bounce{0%,100%{transform:translateY(0) scale(1);}46%{transform:translateY(19px) scale(1);}52%{transform:translateY(20px) scale(1.14,.84);}58%{transform:translateY(18px) scale(.96,1.04);}}
@keyframes cue-shadow{0%,100%{transform:scaleX(.55);opacity:.35;}52%{transform:scaleX(1.15);opacity:.9;}}
/* 4 face: a little Tashi, caramel ears and patches, who blinks and nods down */
.cue-face{display:block;width:32px;height:28px;overflow:visible;}
.cue-face .head{fill:#FFF9F0;}
.cue-face .ear{fill:#C8955B;}
.cue-face .patch{fill:#DDB27E;}
.cue-face .eyes ellipse,.cue-face .nose{fill:#33241A;}
.cue-face .smile{fill:none;stroke:#33241A;stroke-width:1.2;stroke-linecap:round;}
.cue-face .eyes{transform-box:fill-box;transform-origin:center;}
[data-mode="scroll"] .cue-face{animation:cue-nod 2.6s ease-in-out 6;}
[data-mode="scroll"] .cue-face .eyes{animation:cue-wink 2.6s ease-in-out 6;}
@keyframes cue-wink{0%,38%,50%,100%{transform:scaleY(1);}44%{transform:scaleY(.12);}}
@keyframes cue-nod{0%,100%{transform:translateY(0);}62%{transform:translateY(5px);}80%{transform:translateY(2px);}}
/* 5 twinkle: three small stars lighting down */
.cue-stars{display:flex;flex-direction:column;align-items:center;gap:3px;}
.cue-stars svg{display:block;fill:currentColor;opacity:.2;}
.cue-stars svg:nth-child(1){width:8px;height:8px;}
.cue-stars svg:nth-child(2){width:11px;height:11px;}
.cue-stars svg:nth-child(3){width:15px;height:15px;}
[data-mode="scroll"] .cue-stars svg{animation:cue-twinkle 1.8s ease-in-out 8;}
[data-mode="scroll"] .cue-stars svg:nth-child(2){animation-delay:.3s;}
[data-mode="scroll"] .cue-stars svg:nth-child(3){animation-delay:.6s;}
@keyframes cue-twinkle{0%,100%{opacity:.18;transform:scale(.7) rotate(0deg);}24%{opacity:1;transform:scale(1.12) rotate(45deg);}50%{opacity:.18;transform:scale(.7) rotate(90deg);}}
/* 6 mouse: the plain one, a wheel rolling down */
.cue-mouse{position:relative;display:block;width:16px;height:25px;border:1.5px solid currentColor;border-radius:9px;box-sizing:border-box;}
.cue-mouse i{position:absolute;left:50%;top:5px;width:3px;height:5px;margin-left:-1.5px;border-radius:2px;background:currentColor;}
[data-mode="scroll"] .cue-mouse i{animation:cue-wheel 1.6s ease-in-out 9;}
@keyframes cue-wheel{0%{opacity:0;transform:translateY(-2px);}25%{opacity:1;}75%,100%{opacity:0;transform:translateY(8px);}}
/* the click cue: a tap ring */
.cue-tap{position:relative;display:block;width:26px;height:26px;color:#FFF9F0;filter:drop-shadow(0 1px 3px rgba(30,20,12,.7)) drop-shadow(0 0 8px rgba(30,20,12,.35));}
.cue-tap::before{content:"";position:absolute;left:50%;top:50%;width:6px;height:6px;margin:-3px 0 0 -3px;border-radius:50%;background:currentColor;}
.cue-tap i{position:absolute;inset:0;border-radius:50%;border:1.5px solid currentColor;opacity:0;}
[data-mode="click"] .cue-tap i{animation:cue-tap 1.6s ease-out infinite;}
/* at rest the "Click for" cue stops pulsing and stays fully visible; the
   next hand movement or scroll starts it again */
.is-still .piece__cue[data-mode="click"] .piece__cue-click .piece__cue-word,
.is-still .piece__cue[data-mode="click"] .cue-tap i{animation:none;}
@keyframes cue-tap{0%{opacity:.9;transform:scale(.3);}70%,100%{opacity:0;transform:scale(1.1);}}
.piece__card{
  flex:1;align-self:center;
  padding:0 max(var(--gutter),6vw);max-width:calc(36ch + 12vw);
}
/* 28 Sep, her QA on the words beside each object: the sentences were set
   in the wide display face and read heavy, and nothing explained the
   object. Now: a number and the room, the name large over a hairline,
   the sentences in the reading face, and the materials step as a spec
   list (what each part is made of) with one line under it. */
.piece__room{
  display:flex;align-items:baseline;gap:14px;margin:0 0 22px;
  font-size:11px;letter-spacing:.34em;text-transform:uppercase;color:var(--ink-dim);
}
.piece__room span{font-family:var(--display);letter-spacing:.06em;color:var(--mahogany);}   /* tobacco read 2.1:1 on vanilla */
.piece__name{
  font-family:var(--display);font-weight:400;
  font-size:clamp(34px,3.5vw,56px);line-height:1;letter-spacing:-.025em;
  margin:0 0 28px;padding-bottom:28px;border-bottom:1px solid var(--hair);
}
/* the three texts share one cell and take turns; the tallest (the spec
   list) sets the height, so nothing below them jumps */
.piece__steps{display:grid;align-items:start;margin:0 0 34px;}
.piece__step{
  grid-area:1 / 1;margin:0;
  opacity:0;visibility:hidden;transform:translateY(10px);
  /* leaving: quick, so two texts never sit on top of each other */
  transition:opacity .28s ease,transform .5s ease,visibility 0s .28s;
}
/* arriving: after the old one has gone */
.piece__step.is-on{opacity:1;visibility:visible;transform:none;
  transition:opacity .55s ease .28s,transform .8s cubic-bezier(.22,1,.36,1) .28s,visibility 0s .28s;}
.piece__lead{font-size:clamp(17px,1.35vw,20px);line-height:1.6;color:var(--mahogany);max-width:30ch;}
.piece__specs{margin:0 0 18px;}
.piece__specs div{
  display:grid;grid-template-columns:7.5em 1fr;gap:16px;align-items:baseline;
  padding:12px 0;border-top:1px solid var(--hair);
}
.piece__specs div:last-child{border-bottom:1px solid var(--hair);}
.piece__specs dt{font-size:10px;letter-spacing:.28em;text-transform:uppercase;color:var(--ink-dim);}   /* tobacco read 2.1:1 */
.piece__specs dd{margin:0;font-size:15px;line-height:1.5;color:var(--mahogany);}
.piece__note{margin:0;font-size:14px;line-height:1.7;color:var(--ink-dim);max-width:36ch;}   /* 4.8:1 (was 4.3) */
.piece__buy{display:flex;align-items:center;gap:24px;}
/* Add to bag is the hero's own button now, filled, not an underlined word */
.piece__add{cursor:pointer;font-family:var(--ui);}
.piece__add:focus-visible{outline:2px solid var(--mahogany);outline-offset:4px;}
/* the price, beside Add to bag */
.piece__price{margin:0;font:400 clamp(20px,1.6vw,26px)/1 var(--display);letter-spacing:.04em;color:var(--mahogany);}
/* the display face has no euro sign: it borrows the reading face's */
.piece__cur{font-family:var(--ui);font-weight:400;margin-right:.1em;}
/* the invisible marks that turn the steps */
.piece__mark{position:absolute;left:0;width:1px;height:1px;pointer-events:none;}

/* the room you jumped to answers once, the way the tiles did on hover */
.piece:target .piece__name{animation:room-land 1.8s cubic-bezier(.22,1,.36,1);}
@keyframes room-land{
  0%,35%{color:var(--orange);transform:translateX(16px);}
  100%{color:var(--ink);transform:none;}
}

/* the bag answers when something goes in */
.nav__count.is-bump{animation:bag-bump .55s cubic-bezier(.22,1,.36,1);}
@keyframes bag-bump{40%{transform:scale(1.4);}}

/* ---- the rule --------------------------------------------------------- */
.rule{
  background:var(--sand);color:var(--mahogany);
  padding:clamp(64px,11vh,140px) var(--gutter);
}
.rule__big{
  font-family:var(--display);font-weight:400;
  font-size:clamp(30px,5.2vw,86px);line-height:1.04;letter-spacing:-.03em;
  margin:0 0 clamp(24px,4vh,44px);max-width:11ch;
}
.rule__body{max-width:52ch;font-size:15px;line-height:1.72;color:var(--mahogany);margin:0;}   /* 4.9:1 on sand (was 3.3) */
.mats{display:flex;flex-wrap:wrap;gap:9px;margin-top:clamp(28px,4.5vh,56px);}
.mat{
  font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  padding:9px 15px;border:1px solid rgba(88,71,56,.26);border-radius:100px;
  color:var(--mahogany);   /* 4.9:1 on sand (was 3.2) */
}

/* ---- footer: the studio's standard one (29 Sep, her QA: "the footer should include the
   usual footer information created by Spectralmoon ... agent-ready and accessibility-ready.
   That's our standard") --------------------------------------------------------------------
   Built as on Thunupa: the shop's columns, the four standards (a row on a desktop, a 2 x 2 of
   tiles on a phone), and the signature with the studio's own sigil. Every small word here is
   vanilla at 80% or more on mahogany, which measures 4.6:1 and up. */
footer.site{background:var(--mahogany);color:var(--vanilla);padding:clamp(64px,10vh,112px) var(--gutter) 28px;}
.site-inner{display:grid;grid-template-columns:1.6fr repeat(3,1fr);gap:48px;max-width:1320px;margin:0 auto;}
.site-name{font-family:var(--display);font-weight:400;font-size:clamp(30px,3.4vw,52px);line-height:1;letter-spacing:-.03em;margin:0 0 16px;}
.site-note{font-size:15px;line-height:1.65;margin:0;max-width:40ch;color:rgba(241,234,218,.88);}
.site-label{font-family:var(--display);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:rgba(241,234,218,.82);margin:0 0 18px;}
.site-list{list-style:none;margin:0;padding:0;display:grid;gap:11px;}
.site-list a{font-size:15px;color:var(--vanilla);text-decoration:none;border-bottom:1px solid rgba(241,234,218,.3);padding-bottom:2px;transition:border-color .2s;}
.site-list a:hover{border-bottom-color:var(--vanilla);}
.site-list a:focus-visible,.site-sig:focus-visible{outline:2px solid var(--vanilla);outline-offset:4px;border-radius:3px;}
.site-quietline{font-size:15px;color:rgba(241,234,218,.82);}
.site-standards{list-style:none;margin:56px auto 0;padding:18px 0;max-width:1320px;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  border-top:1px solid rgba(241,234,218,.16);border-bottom:1px solid rgba(241,234,218,.16);}
.site-standards li{display:flex;flex-direction:column;gap:6px;padding:4px 20px;border-left:1px solid rgba(241,234,218,.16);}
.site-standards li:first-child{border-left:0;padding-left:0;}
.site-standards b{font-family:var(--display);font-weight:400;font-size:16px;line-height:1.2;color:var(--vanilla);}
.site-standards span{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:rgba(241,234,218,.82);}
.site-base{display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;max-width:1320px;margin:36px auto 0;}
.site-sig{display:inline-flex;align-items:center;gap:12px;min-height:44px;color:rgba(241,234,218,.88);text-decoration:none;font-size:13px;}
.site-sig .sigil{width:44px;height:44px;flex:none;color:var(--vanilla);}   /* below ~44 the fish and the crescent read as a blob */
.site-sig b{font-weight:500;color:var(--vanilla);}
.site-sig:hover{color:var(--vanilla);}
.site-fine{margin:0;font-size:12px;letter-spacing:.02em;color:rgba(241,234,218,.82);}
@media (max-width:980px){ .site-inner{grid-template-columns:1fr 1fr;gap:36px;} .site-col--mark{grid-column:1 / -1;} }
@media (max-width:560px){
  footer.site{padding:64px 24px 28px;}
  .site-inner{grid-template-columns:1fr;gap:30px;}
  .site-list a{display:inline-block;padding:12px 0 10px;}   /* a full thumb to tap */
  .site-standards{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;border:0;padding:0;margin-top:40px;}
  .site-standards li,.site-standards li:first-child{border:1px solid rgba(241,234,218,.18);border-radius:14px;padding:14px 14px 12px;
    min-height:92px;justify-content:center;background:rgba(241,234,218,.04);}
  .site-standards b{font-size:14px;}
  .site-standards span{font-size:9px;letter-spacing:.14em;}
  .site-base{margin-top:40px;flex-direction:column;align-items:flex-start;gap:14px;}
}

/* the keyboard's way past the hero: out of sight until it has focus */
.skip{position:absolute;left:16px;top:-64px;z-index:100;padding:12px 16px;border-radius:6px;background:var(--mahogany);color:var(--vanilla);
  font-size:14px;text-decoration:none;transition:top .2s ease;}
.skip:focus{top:12px;outline:2px solid var(--vanilla);outline-offset:2px;}

/* ---- responsive -------------------------------------------------------- */
@media (max-width:820px){
  .nav__rooms{display:none;}
  /* the rooms carried the auto margin; with them hidden the bag takes it */
  .nav__cart{margin-left:auto;}
  .hero__word{font-size:clamp(96px,34vw,220px);}
  /* The phone hero, 29 Sep (her QA: "Fetch on mobile looks tiny", and the small print ran over his
     legs). FETCH nearly edge to edge and about 40% taller: tighter tracking, a bigger size, a little
     more stretch (js/material-reveal.js reads the stretch, so the materials follow). He is a little
     smaller, and his feet stand just above the words instead of behind them; his head still covers
     the foot of the word, so he stays inside it. */
  /* second pass on her phone (29 Sep, "still kind of small, it should be taller"): stretch 2 and no
     tracking; the word's middle never rises past the nav (its half height is about 30vw at this size) */
  /* 3 Oct, her QA "FETCH must span the full phone width": 37vw left ~16 px each side, 39vw leaves ~6 (half height ~31.6vw).
     The shop is Tashi again (her call, 3 Oct evening) but the hero word stays FETCH: its six materials are renders of FETCH */
  .hero__name{top:max(24%,calc(var(--nav-h) + 12px + 31.6vw));font-size:clamp(120px,39vw,264px);letter-spacing:0;
    transform:translate(-50%,-50%) translateZ(-380px) scaleY(2);}
  /* her phone shows about 650px of page: the nav, the word, him and all the words cannot stack in
     that. The small print leaves the hero on phones (the shop's opening says it again a screen
     below), and he stands from just under the middle of the word down to the words, never taller
     than 44% of the screen; so the top half of FETCH always reads above his head. */
  .hero__arc{display:none;}
  /* 3 Oct (evening), her phone QA: "I wish it could be taller or bigger": he starts higher in the word and stands lower */
  .stage{width:auto;height:auto;aspect-ratio:420 / 488;max-height:52svh;
    top:calc(max(24%,calc(var(--nav-h) + 12px + 31.6vw)) - 14px);
    bottom:calc(clamp(64px,9vh,96px) + 112px);transform:translateX(-50%);}
  /* his name keeps its place on the bottom row, opposite "Scroll", clear of the words */
  .hero__sig{left:auto;right:var(--gutter);bottom:24px;transform:none;font-size:12px;}
  .hero__bar{flex-direction:column;align-items:flex-start;gap:13px;}
  .hero__bar__left{flex-direction:column;align-items:flex-start;gap:12px;}
  .hero__arc{white-space:normal;}
  /* no pinning on a phone: the picture, then every step, one under the other */
  .piece{height:auto;}
  .piece__stage,.piece--flip .piece__stage{position:static;height:auto;flex-direction:column;overflow:visible;}
  .piece__pics{width:100%;height:auto;aspect-ratio:var(--ratio,1.5);}
  /* Bigger on a phone (her real phone, 29 Sep: "the image looks super small"): a square as wide as
     the screen, half as tall again as before. Sideways drags belong to the picture (they move him in
     his film, js/shop.js), up and down stays the page's. */
  .piece__pics{aspect-ratio:4 / 5;touch-action:pan-y;}   /* taller still (her "it feels just like a little stripe") */
  /* the square is filled, never letterboxed (the Bowls' desktop rule letterboxes tall windows) */
  #eat .piece__pics img:first-child,#eat .piece__film{object-fit:cover;}
  .piece__replay{right:6px;bottom:18px;}
  .piece__card{padding:8vh var(--gutter) 12vh;max-width:none;}
  .piece__steps{display:flex;flex-direction:column;gap:22px;}
  .piece__step{opacity:1;visibility:visible;transform:none;}
  .piece__mark{display:none;}
  .piece.has-film,.piece.has-leave{height:auto;}
  .piece__leave{display:none;}
  .piece__bars{bottom:30px;}   /* above the line */
  .piece__bar-label{display:none;}
  /* phones: just under the picture, on the page, so it never covers him or hides under the nav */
  .piece__cue{left:50%;top:calc(100% + 14px);}
  .piece__cue-word,.piece__cue-icon,.cue-tap{color:var(--mahogany);text-shadow:none;filter:none;}
  /* 3 Oct, her QA: the ball bigger on phones (was 44); that evening, her phone: "the ball looks gigantic" at 64 */
  .ball{width:50px;height:50px;margin:-25px 0 0 -25px;}
  /* 3 Oct (evening), her phone QA: the sheet's Scroll sat on the price ("it doesn't have anything to do with that"), and "Tap for
     the materials" stood huge under the nav ("a small letter placed somewhere else"): no Scroll there on a phone, and the tap
     cue is a small line of type at the foot of the picture */
  .journey__next{display:none;}
}
@media (prefers-reduced-motion:reduce){
  .piece__bar,.piece__bar-fill,.piece__bar-fill::after{transition:none;animation:none !important;}
  .piece__cue *{animation:none !important;}
  .cue-puffs i,.cue-paws svg,.cue-stars svg{opacity:.8;}
  .cue-tap i{opacity:.7;}
  .grain{animation:none;}
  .loop{height:auto;}
  .loop__stage{position:static;height:auto;overflow:visible;}
  .loop__item{position:static;transform:none !important;opacity:1 !important;margin-bottom:40px;}
  .hero__word,.hero__claim,.hero__sub,.hero__cue{animation:none;opacity:1;transform:none;}
  .hero__word{transform:translateY(-52%);}
  html{scroll-behavior:auto;}
}


/* =====================================================================
   THE CASCADE
   His name again and again, each one smaller, stepping down the left.
   Each is a section head; the copy sits beside it. The shrinking is the
   navigation: you can feel how far down the page you are by how small
   his name has become.
   ===================================================================== */
.cascade{background:var(--vanilla);padding:clamp(50px,9vh,110px) 0 clamp(40px,7vh,90px);}

.step{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,26ch);
  align-items:center;gap:clamp(28px,5vw,80px);
  padding:clamp(20px,3.4vh,44px) var(--gutter);
  border-top:1px solid var(--hair);
}
.step:last-child{border-bottom:1px solid var(--hair);}

.step__name{
  margin:0;font-family:var(--display);font-weight:700;
  line-height:.82;letter-spacing:.005em;text-transform:uppercase;
  transition:color .4s ease;
}
.step__body{display:flex;flex-direction:column;gap:9px;}
.step__label{
  font-size:11px;letter-spacing:.3em;text-transform:uppercase;color:var(--mountain);
}
.step__text{margin:0;font-size:14px;line-height:1.72;color:rgba(88,71,56,.8);}

/* Each step is a size and a colour from the system, largest first. */
.step--1 .step__name{font-size:clamp(72px,15vw,236px);color:var(--tobacco);}
.step--2 .step__name{font-size:clamp(58px,11.5vw,182px);color:var(--mountain);}
.step--3 .step__name{font-size:clamp(46px,8.6vw,138px);color:var(--sand);}
.step--4 .step__name{font-size:clamp(36px,6.4vw,102px);color:var(--mahogany);}
.step--5 .step__name{font-size:clamp(28px,4.6vw,74px);color:var(--orange);}

@media (max-width:820px){
  .step{grid-template-columns:1fr;gap:12px;}
}


/* =====================================================================
   THE PANELS
   Five bands, each carrying his name at its own size. They stack and
   scroll normally: nothing flies, nothing shrinks as it goes.

   The motion is inside the word, using the two-copy clip from the Motion
   Type Lab study file: a hollow copy underneath drawn with
   -webkit-text-stroke, and a solid copy on top clipped by inset() tied
   to scroll. The wipe crosses each letter in turn, so it reads as
   T-A-S-H-I lighting one after another, but it is continuous rather than
   five separate steps, and it runs backwards when you scroll up.

   Weight rides the same progress value. One progress function, several
   things driven from it.
   ===================================================================== */
.panels{background:var(--vanilla);padding:clamp(30px,6vh,80px) 0;}

.panel{
  min-height:80svh;display:flex;align-items:center;
  padding:0 var(--gutter);gap:clamp(24px,5vw,72px);
}
.panel__word{position:relative;display:inline-block;}
.panel__word > *{
  margin:0;line-height:.84;white-space:nowrap;
  font-family:var(--display);
  font-size:calc(clamp(56px,10vw,152px) * var(--size,1));
  font-variation-settings:'wght' var(--wght,400);
  text-transform:uppercase;letter-spacing:.005em;
}
/* hollow copy */
.panel__outline{
  color:transparent;
  /* Michroma has no weight axis, so --wght cannot thicken the word the
     way a variable face did. The same progress value drives the stroke
     instead: the outline firms up as the fill crosses it. */
  -webkit-text-stroke:calc(1px + (var(--wght,380) - 380) * 0.0032px) var(--hue,#B59E7D);
}
/* solid copy, clipped by --p */
.panel__fill{
  position:absolute;inset:0;
  color:var(--hue,#B59E7D);
  clip-path:inset(0 calc(100% - var(--p,0) * 100%) 0 0);
}
.panel__aside{
  display:flex;flex-direction:column;gap:8px;max-width:26ch;flex:none;
}
.panel__label{
  font-size:11px;letter-spacing:.3em;text-transform:uppercase;color:var(--mountain);
}
.panel__text{margin:0;font-size:14px;line-height:1.72;color:rgba(88,71,56,.8);}

.panel:nth-child(1) .panel__word{--hue:var(--tobacco);  --size:1.00;}
.panel:nth-child(2) .panel__word{--hue:var(--mountain); --size:0.58;}
.panel:nth-child(3) .panel__word{--hue:var(--mahogany); --size:1.34;}
.panel:nth-child(4) .panel__word{--hue:var(--sand);     --size:0.76;}
.panel:nth-child(5) .panel__word{--hue:var(--orange);   --size:1.10;}

.panel:nth-child(even){justify-content:flex-end;flex-direction:row-reverse;}

@media (max-width:820px){
  .panel{flex-direction:column;align-items:flex-start;justify-content:center;gap:14px;min-height:64svh;}
  .panel:nth-child(even){flex-direction:column;align-items:flex-start;}
  .panel__word > *{font-size:calc(clamp(44px,12vw,92px) * var(--size,1));}
}
@media (prefers-reduced-motion:reduce){
  .panel__fill{clip-path:none;}
  .piece:target .piece__name{animation-name:room-land-still;}
  .piece__pics img,.piece__step{transition:none;}
  @keyframes room-land-still{ 0%,35%{color:var(--orange);} 100%{color:var(--ink);} }
}


/* =====================================================================
   CLOUD BAND
   A WebGL2 cloud field. Until 28 Sep it was a band across the top of
   the hero, fading out before his body; now it drifts over the whole
   hero (her ask, the day the WebGL sun glow went: "add that to the whole
   hero section") and thins out only at the very bottom, into the page.
   It sits ABOVE the giant name and BELOW him, so the order reads:
   letters, then weather, then the dog.
   ===================================================================== */
.clouds{
  position:absolute;top:0;left:0;right:0;height:100%;
  z-index:2;pointer-events:none;overflow:hidden;
  -webkit-mask-image:linear-gradient(180deg,
    rgba(0,0,0,.45) 0%, #000 14%, #000 80%, transparent 100%);
          mask-image:linear-gradient(180deg,
    rgba(0,0,0,.45) 0%, #000 14%, #000 80%, transparent 100%);
}
.clouds canvas{position:absolute;inset:0;width:100%;height:100%;}


/* ==== 29 Sep, her structure: two panels for every object (js/shop.js) =========
   "It's getting really difficult with the whole scroll, scrubbing, and changing
   pages." No pinned rooms now: the story panel (his film, the whole frame in view,
   the why beside it) and the product panel (the object and its materials in one
   picture, the details beside it).
   Second pass, her QA the same evening: "a big panel on the left, left-aligned,
   with just a little bit of text to the right ... a 70/30 sort of thing" and "I
   just don't want it to be confined to a little box". So on a wide screen both
   panels run 70/30: the film or picture flush to the edge of the page, no
   rounded card, no shadow, the words in the narrow column. The picture of the
   object is as tall as the screen. */
.shop .piece{height:auto;padding:clamp(72px,13vh,150px) 0 0;}
.piece__story{--r:1.7778;}
#walk .piece__story{--r:1;}
.piece__screen{
  position:relative;margin:0 auto;width:100%;aspect-ratio:var(--r,1.7778);
  overflow:hidden;background:#d8c6ab;touch-action:pan-y;
}
.piece__screen .piece__film{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:1;}
.piece__screen .piece__cue{top:18px;left:50%;}
.piece__product .piece__pics{border-radius:0;overflow:hidden;}
.piece__product .piece__cue{top:16px;left:50%;}
.piece__text .piece__lead{margin:0 0 14px;max-width:44ch;}
.piece__text > .piece__note{margin:0 0 22px;max-width:44ch;}
.piece__text .piece__specs{margin-bottom:14px;}
.piece__why .piece__lead{margin:0 0 12px;}

@media (min-width:821px){
  /* the picture's column: 70% of the page, but never taller than the screen can show whole */
  .piece__story,.piece__product{
    display:grid;align-items:center;gap:clamp(36px,4.5vw,80px);
    width:100%;margin:0;padding-right:max(var(--gutter),4vw);
    grid-template-columns:minmax(0,70vw) minmax(0,1fr);
  }
  /* Third pass, her QA: "it feels like the video is just dancing there without any structure ...
     almost like a whole section". The film is a section now: 70% of the page wide and the full
     height of the screen, edge to edge, top to bottom; the wheel glides it squarely into view. */
  .piece__screen{aspect-ratio:auto;height:100svh;}
  .piece__screen .piece__film{object-position:var(--focus,50% 50%);}
  .piece__product{margin-top:clamp(72px,14vh,160px);}
  .piece__why{margin:0;max-width:34ch;text-align:left;}
  .piece__why .piece__room{justify-content:flex-start;}
  .piece__text{max-width:44ch;}
  /* the narrow column: each spec's name above its words, not squeezed beside them */
  .piece__text .piece__specs div{grid-template-columns:1fr;gap:4px;}
  .piece__product .piece__pics{width:100%;height:100svh;aspect-ratio:auto;}
  /* the Bowls: the picture on the right, flush to that edge */
  .piece--flip .piece__product{grid-template-columns:minmax(0,1fr) minmax(0,70vw);padding-right:0;padding-left:max(var(--gutter),4vw);}
  .piece--flip .piece__product .piece__pics{order:2;}
}
@media (max-width:820px){
  .shop .piece{padding-top:64px;}
  .piece__story,.piece__product{width:auto;}
  .piece__why,.piece__text{padding:0 var(--gutter);}
  .piece__why{margin:28px 0 0;}
  .piece__product{display:grid;grid-template-columns:1fr;gap:28px;margin-top:48px;}
  .piece__product .piece__pics{width:auto;height:auto;aspect-ratio:1;}
}

/* ==== 29 Sep, her UI pass: a chapter between the objects, and left, right, left, right ====
   Her QA: "the divisions ... should be better ... there should be something, or text, to kind
   of break it" and "left, right, left, right", with Serif Studio's rule that white space is what
   reads as luxury. So each object opens with a quiet chapter in a great deal of room (its number,
   the room in the display face, the object's name over a short hairline), and every film sits on
   the left, every product on the right, the whole way down. */
.shop .piece{padding-top:0;}
.piece__chapter{
  display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:clamp(120px,24vh,260px) var(--gutter) clamp(96px,18vh,200px);
}
.piece__chapter p{margin:0;}
.piece__chapter-num{font-family:var(--display);font-size:12px;letter-spacing:.3em;color:var(--mahogany);}
.piece__chapter-room{
  font-family:var(--display);font-weight:400;color:#937B5E;   /* tobacco, deepened to 3.35:1 for large text */
  font-size:clamp(56px,9vw,150px);line-height:1;letter-spacing:-.03em;margin:22px 0 30px !important;
}
.piece__chapter-obj{
  font-size:11px;letter-spacing:.34em;text-transform:uppercase;color:var(--ink-dim);
  padding-top:26px;position:relative;
}
.piece__chapter-obj::before{content:"";position:absolute;top:0;left:50%;width:48px;height:1px;margin-left:-24px;background:var(--hair);}
/* 3 Oct: the ending's chapter title is a line, not one word ("A happy dog brings a happy life.") */
.piece__chapter--line .piece__chapter-room{font-size:clamp(34px,5.2vw,88px);line-height:1.04;letter-spacing:-.02em;max-width:15ch;}
.ending{position:relative;}
/* the chapter says the room, so the film's column does not repeat it */
.piece__why .piece__room{display:none;}
@media (min-width:821px){
  /* every product on the right, flush to that edge, after a long breath */
  .piece__product,.piece--flip .piece__product{
    grid-template-columns:minmax(0,1fr) minmax(0,70vw);padding-right:0;padding-left:max(var(--gutter),4vw);
    margin-top:clamp(120px,22vh,240px);
  }
  /* the Bed's words run taller than the screen: the picture holds still beside them while they pass */
  .piece__product .piece__pics{order:2;position:sticky;top:0;align-self:start;}
  .piece__product .piece__text{justify-self:end;}
}
@media (max-width:820px){
  .piece__chapter{padding:clamp(96px,16vh,140px) var(--gutter) 56px;}
  .piece__product{margin-top:72px;}
}

/* Her QA, 29 Sep: "the video of rest is too high and short, you are missing a part of the room".
   A full-height 70% cell cut the sides off the wide films. The two wide films (Rest, Eat) keep
   their own 16:9 frame now, the whole room in view: as wide as the screen's height allows, up to
   78% of the page, so on a laptop it is nearly the full height. The Walk (square) stays as it was. */
@media (min-width:821px){
  #rest .piece__story,#eat .piece__story{grid-template-columns:minmax(0,min(75vw,calc(100svh * 1.7778))) minmax(0,1fr);}
  #rest .piece__screen,#eat .piece__screen{height:auto;aspect-ratio:16 / 9;}
}

/* Her QA, 29 Sep: "the text ... is not showing in one vh". The words beside the object fit one
   screen now: the picture's column is 66% (it still reads as 70/30), the name and the sentences
   are a size smaller and scale with the screen's height, and the specs sit in two columns. */
@media (min-width:821px){
  .piece__product,.piece--flip .piece__product{grid-template-columns:minmax(0,1fr) minmax(0,66vw);gap:clamp(32px,3.5vw,64px);}
  .piece__product .piece__text{max-width:48ch;padding:calc(var(--nav-h) + 8px) 0 16px;}
  .piece__product .piece__name{font-size:clamp(30px,min(3vw,6.4vh),50px);margin:0 0 min(20px,2.8vh);padding-bottom:min(20px,2.8vh);}
  .piece__product .piece__text .piece__lead{font-size:clamp(15px,min(1.2vw,2.5vh),18px);line-height:1.5;margin:0 0 min(12px,1.7vh);max-width:none;}
  .piece__product .piece__text > .piece__note{font-size:13.5px;line-height:1.6;margin:0 0 min(18px,2.4vh);max-width:none;}
  .piece__product .piece__specs{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;margin:0 0 min(16px,2.2vh);border-bottom:1px solid var(--hair);}
  .piece__product .piece__specs div{grid-template-columns:1fr;gap:2px;padding:min(10px,1.4vh) 0;}
  .piece__product .piece__specs div:last-child{border-bottom:0;}
  .piece__product .piece__specs dd{font-size:14px;line-height:1.4;}
}

/* ==== 29 Sep, her QA: "they are dancing ... more structured or tucked in" ==================
   Measured at her 1470 x 713: three window widths (1103, 1029, 970), films bleeding off one edge
   and products off the other, and the product window had no edge at all (its cream is the page's
   cream), so the bed floated. Nothing shared a line. Tucked (.shop[data-frame="tucked"]):
   - every window sits inside the nav's own margins (the gutter) with the nav's 18px corners,
     so the nav, the films and the products all share the same two outer lines;
   - every panel is one screen tall and holds its window between the same top line (under the
     nav) and bottom line, the words beside it on those lines too;
   - the product window gets a hairline frame, so it reads as a window, not a floating object;
   - the glass bars sit inside that frame in dark glass (her QA: "so lost at the bottom they
     don't even appear", and white glass disappeared on cream).
   The earlier open layout is ?frame=open, to compare. */
@media (min-width:821px){
  .shop[data-frame="tucked"]{--H:calc(100svh - var(--nav-h) - 64px);--frame-r:18px;}
  .shop[data-frame="tucked"] .piece__story,
  .shop[data-frame="tucked"] .piece__product,
  .shop[data-frame="tucked"] .piece--flip .piece__product{
    min-height:100svh;box-sizing:border-box;margin:0;
    padding:calc(var(--nav-h) + 28px) var(--gutter) 36px;
    gap:clamp(40px,4.5vw,80px);align-items:center;
  }
  /* the films: the wide ones whole at 16:9, the square Walk as tall as the frame */
  .shop[data-frame="tucked"] .piece__story,
  .shop[data-frame="tucked"] #rest .piece__story,
  .shop[data-frame="tucked"] #eat .piece__story{grid-template-columns:minmax(0,min(66vw,calc(var(--H) * 1.7778))) minmax(0,1fr);}
  .shop[data-frame="tucked"] #walk .piece__story{grid-template-columns:minmax(0,min(66vw,calc(var(--H) * 1.4))) minmax(0,1fr);}
  .shop[data-frame="tucked"] .piece__screen,
  .shop[data-frame="tucked"] #rest .piece__screen,
  .shop[data-frame="tucked"] #eat .piece__screen{height:auto;aspect-ratio:16 / 9;border-radius:var(--frame-r);}
  .shop[data-frame="tucked"] #walk .piece__screen{aspect-ratio:auto;height:var(--H);}
  /* the why: a caption on the film's bottom line */
  .shop[data-frame="tucked"] .piece__story{align-items:end;}   /* film and caption share the bottom line */
  .shop[data-frame="tucked"] .piece__why{align-self:end;margin:0;padding-bottom:4px;}
  /* the products: the window on the right, framed, as tall as the frame */
  .shop[data-frame="tucked"] .piece__product,
  .shop[data-frame="tucked"] .piece--flip .piece__product{grid-template-columns:minmax(0,1fr) minmax(0,60vw);}
  .shop[data-frame="tucked"] .piece__product .piece__pics{position:relative;top:auto;align-self:center;height:var(--H);border-radius:var(--frame-r);}
  .shop[data-frame="tucked"] .piece__product .piece__pics::after{
    content:"";position:absolute;inset:0;border-radius:inherit;border:1px solid var(--hair);pointer-events:none;z-index:6;}
  .shop[data-frame="tucked"] .piece__product .piece__text{padding:0;justify-self:start;}
  /* the bars on paper: dark glass, the name in ink */
  .shop[data-frame="tucked"] .piece__product .piece__bars{bottom:20px;}
  .shop[data-frame="tucked"] .piece__product .piece__bar{
    background:linear-gradient(115deg,rgba(88,71,56,.30),rgba(88,71,56,.14) 48%,rgba(88,71,56,.26));
    box-shadow:inset 0 0 0 1px rgba(88,71,56,.38),0 6px 14px -8px rgba(40,28,20,.45);}
  .shop[data-frame="tucked"] .piece__product .piece__bar[aria-current="step"]{
    background:linear-gradient(115deg,rgba(88,71,56,.78),rgba(88,71,56,.58) 48%,rgba(88,71,56,.72));
    box-shadow:inset 0 0 0 1px rgba(88,71,56,.9),0 8px 18px -8px rgba(40,28,20,.5);}
  .shop[data-frame="tucked"] .piece__product .piece__bar-label{color:var(--mahogany);text-shadow:none;}
}

/* ==== 29 Sep, the Spector effects, tried on Tashi (js/fx.js; her ask: "try all the option") ====== */
/* 1. chapter reveal: the word rises from behind its line, then the number and the name */
.piece__chapter-room{overflow:hidden;padding:.06em .04em .1em;}
.piece__chapter-room span{display:inline-block;}
.fx .piece__chapter-room span{transform:translateY(110%);transition:transform 1.1s cubic-bezier(.22,1,.36,1);}
.fx .piece__chapter-num,.fx .piece__chapter-obj{opacity:0;transform:translateY(12px);transition:opacity .9s ease,transform 1.1s cubic-bezier(.22,1,.36,1);}
.fx .piece__chapter.is-in .piece__chapter-room span{transform:none;transition-delay:.12s;}
.fx .piece__chapter.is-in .piece__chapter-num{opacity:1;transform:none;}
.fx .piece__chapter.is-in .piece__chapter-obj{opacity:1;transform:none;transition-delay:.24s;}
/* 2. word fill: a soft tone (mahogany at 66%, 3.3:1, still passes as large type) to ink */
.fx .fx-word{color:rgb(140,126,111);transition:color .5s ease;}
.fx .fx-word.is-lit{color:var(--mahogany);}
/* 3. specs to materials: the picture leans in on the material under the pointer */
.piece__pics img:last-of-type{transition:opacity .9s ease,transform .9s cubic-bezier(.22,1,.36,1);}
.piece__specs [data-look]{cursor:default;transition:background-color .3s ease;}
@media (hover:hover){ .piece__specs [data-look]:hover dd{color:var(--ink);} .piece__specs [data-look]:hover dt{color:var(--mahogany);} }

/* 4. The materials (her QA, 29 Sep, after a lightbox that was not what she meant: "Apple style"). One
   list, two shapes. A desktop: a row that grows under the pointer, the words showing as it opens.
   A phone: tall, solid cards side by side, the picture on top and every word on the card at a
   size you can read; the next card peeks in from the right, and a swipe goes from one to the
   next. No clicking, no dots or numbers: the peek is the pagination. The earlier versions are in
   _qa/ (style-v112-with-lightbox.css, index-v112-with-lightbox.html, lightbox-v1.js). */
.swatches{list-style:none;margin:clamp(36px,6vh,64px) 0 0;padding:0;display:flex;gap:10px;height:clamp(300px,50vh,460px);}
.swatches:focus-visible{outline:2px solid var(--mahogany);outline-offset:6px;border-radius:20px;}
.swatch{position:relative;flex:1 1 0;min-width:0;margin:0;border-radius:18px;overflow:hidden;background:#e7dcc6;
  transition:flex-grow .7s cubic-bezier(.22,1,.36,1);}
.swatch__pic{position:absolute;inset:0;margin:0;}
.swatch__pic img{width:100%;height:100%;object-fit:cover;display:block;transition:transform 1.2s cubic-bezier(.22,1,.36,1);}
.swatch__pic::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(40,26,16,0) 38%,rgba(40,26,16,.7));pointer-events:none;}
.swatch__body{position:absolute;left:0;right:0;bottom:0;z-index:1;padding:18px;color:#FFF9F0;}
.swatch__name{margin:0;font-family:var(--display);font-weight:400;font-size:clamp(13px,1.05vw,17px);letter-spacing:.02em;line-height:1.25;}   /* wraps, never cut */
.swatch__text{max-height:0;opacity:0;overflow:hidden;transition:max-height .6s cubic-bezier(.22,1,.36,1),opacity .4s ease;}
.swatch__text p{margin:10px 0 0;font-size:14px;line-height:1.55;max-width:40ch;}
.swatch__text .swatch__found{font-size:10px;letter-spacing:.22em;text-transform:uppercase;opacity:.85;}
.swatch:hover{flex-grow:3.4;}
.swatch:hover .swatch__pic img{transform:scale(1.04);}
.swatch:hover .swatch__text{max-height:220px;opacity:1;transition-delay:.15s;}

@media (max-width:820px){
  /* the cards run to the screen's edges; the first lines up with the words above */
  .swatches{height:auto;gap:12px;margin-left:calc(-1 * var(--gutter));margin-right:calc(-1 * var(--gutter));
    padding:4px var(--gutter) 8px;overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;scroll-padding-inline:var(--gutter);scrollbar-width:none;-webkit-overflow-scrolling:touch;}
  .swatches::-webkit-scrollbar{display:none;}
  .swatch{flex:0 0 84%;height:min(76svh,660px);display:flex;flex-direction:column;background:var(--vanilla);
    scroll-snap-align:start;box-shadow:0 22px 44px -30px rgba(40,24,12,.55);transition:none;}
  .swatch:last-child{margin-right:var(--gutter);}
  .swatch:hover{flex-grow:0;}
  .swatch__pic{position:relative;inset:auto;flex:1 1 58%;min-height:0;}
  .swatch__pic::after{display:none;}
  .swatch:hover .swatch__pic img{transform:none;}
  .swatch__body{position:relative;flex:0 0 auto;padding:22px 22px 24px;color:var(--mahogany);}
  .swatch__name{font-size:24px;letter-spacing:-.01em;white-space:normal;}
  .swatch__text{max-height:none;opacity:1;overflow:visible;}
  .swatch__text p{margin:12px 0 0;font-size:16px;line-height:1.6;color:var(--mahogany);}
  .swatch__text .swatch__found{margin-top:14px;font-size:10px;color:var(--ink-dim);opacity:1;}
}

/* 5. the footer ends on his name, oversized and cut by the bottom edge (decoration: a pseudo
   element, so it is not read twice and not measured as text) */
footer.site{overflow:hidden;}
footer.site::after{
  content:"TASHI";display:block;text-align:center;white-space:nowrap;pointer-events:none;
  font-family:var(--display);font-size:19.5vw;line-height:.8;letter-spacing:-.04em;
  color:rgba(241,234,218,.09);margin:clamp(40px,7vh,80px) calc(-1 * var(--gutter)) -.2em;
}

@media (prefers-reduced-motion:reduce){
  .swatch,.swatch img,.swatch__name,.swatch__line,.piece__pics img:last-of-type{transition:none;}
}

/* ==== the caption beside his film, four ways (her QA: "the info there at the bottom does not read
   well, give me other options"). ?why=top | centre | split | bottom. Her pick, 29 Sep: split ("split reads best, keep that one"). ======== */
@media (min-width:821px){
  .shop[data-frame="tucked"] .piece__story{align-content:center;}           /* the row is the film's height */
  .shop[data-frame="tucked"] .piece__why{max-width:30ch;}
  .shop[data-frame="tucked"] .piece__why .piece__lead{font-size:clamp(18px,1.5vw,22px);line-height:1.5;margin:0 0 16px;}
  .shop[data-frame="tucked"][data-why="top"] .piece__why{align-self:start;padding:6px 0 0;}
  .shop[data-frame="tucked"][data-why="centre"] .piece__why{align-self:center;padding:0;}
  .shop[data-frame="tucked"][data-why="bottom"] .piece__why{align-self:end;}
  /* split: the lead on the film's top line, the note on its bottom line */
  .shop[data-frame="tucked"][data-why="split"] .piece__why{align-self:stretch;display:flex;flex-direction:column;justify-content:space-between;padding:6px 0 4px;}
  .shop[data-frame="tucked"][data-why="split"] .piece__why .piece__lead{font-family:var(--display);font-size:clamp(17px,1.45vw,22px);line-height:1.45;letter-spacing:-.01em;}
  .shop[data-frame="tucked"][data-why="split"] .piece__why .piece__note{padding-top:14px;border-top:1px solid var(--hair);}
  /* top: a short rule above, so it reads as the start of the story */
  .shop[data-frame="tucked"][data-why="top"] .piece__why::before{content:"";display:block;width:40px;height:1px;background:var(--mahogany);opacity:.5;margin:0 0 22px;}
}

/* ==== 29 Sep, the 390 px phone pass ==============================================================
   - the glass bars: dark glass on every screen, not only the desktop frame (white glass vanished
     on the cream of the phone's product picture too);
   - the swatches: on a phone the name and its line stack at the foot of the tile instead of
     overlapping;
   - the footer's TASHI: a little stronger on a phone, where it is small. */
.piece__product .piece__bar{
  background:linear-gradient(115deg,rgba(88,71,56,.30),rgba(88,71,56,.14) 48%,rgba(88,71,56,.26));
  box-shadow:inset 0 0 0 1px rgba(88,71,56,.38),0 6px 14px -8px rgba(40,28,20,.45);}
.piece__product .piece__bar[aria-current="step"]{
  background:linear-gradient(115deg,rgba(88,71,56,.78),rgba(88,71,56,.58) 48%,rgba(88,71,56,.72));
  box-shadow:inset 0 0 0 1px rgba(88,71,56,.9),0 8px 18px -8px rgba(40,28,20,.5);}
.piece__product .piece__bar-label{color:var(--mahogany);text-shadow:none;}
@media (max-width:820px){
  footer.site::after{color:rgba(241,234,218,.14);}
}

/* The ball as the page's cursor (her QA, 29 Sep: "i keep losing the ball on desktop"). It never
   switched off in testing; it disappeared into the pictures: 25 px of orange over warm orange-brown
   films, with no arrow beside it. Past the hero it is bigger now (62%, about 37 px) and carries a
   thin cream rim, so it stands apart from any picture. The hero keeps its own look. */
.ball.is-page{filter:drop-shadow(0 0 1.2px rgba(255,249,240,1)) drop-shadow(0 0 1.2px rgba(255,249,240,1)) drop-shadow(0 8px 14px rgba(12,6,3,.45));}

/* ==== the rooms on a phone: a hamburger in the nav, and from there the radial (js/radial.js) =====
   Her picks, 29 Sep: "Rest, Eat, Walk", "Classic hamburger", "from there radial". The three lines
   sit beside Bag; a tap turns them into an X and fans the rooms under them in a quarter circle,
   round glass like the nav, over a soft veil. No pills. Desktop never sees it. */
.nav__menu{display:none;}
@media (max-width:820px){
  .nav__menu{display:flex;flex-direction:column;justify-content:center;align-items:center;gap:5px;
    width:44px;height:44px;margin:0 -12px 0 -6px;padding:0;border:0;background:none;cursor:pointer;color:var(--mahogany);}
  .nav__menu span{display:block;width:20px;height:1.6px;border-radius:1px;background:currentColor;
    transition:transform .45s cubic-bezier(.22,1,.36,1),opacity .25s ease;}
  .nav__menu[aria-expanded="true"] span:nth-child(1){transform:translateY(6.6px) rotate(45deg);}
  .nav__menu[aria-expanded="true"] span:nth-child(2){opacity:0;}
  .nav__menu[aria-expanded="true"] span:nth-child(3){transform:translateY(-6.6px) rotate(-45deg);}
  .nav__menu:focus-visible{outline:2px solid var(--mahogany);outline-offset:2px;border-radius:10px;}
}
.radial-veil{position:fixed;inset:0;z-index:38;background:rgba(241,234,218,.55);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);opacity:0;visibility:hidden;
  transition:opacity .35s ease,visibility 0s linear .35s;}
.radial{position:fixed;left:var(--ax,90%);top:var(--ay,40px);z-index:41;width:0;height:0;visibility:hidden;}
html.radial-open .radial-veil{opacity:1;visibility:visible;transition:opacity .35s ease;}
html.radial-open .radial{visibility:visible;}
.radial__item{
  position:absolute;left:0;top:0;width:66px;height:66px;margin:-33px 0 0 -33px;border-radius:50%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;text-decoration:none;
  color:var(--mahogany);
  background:linear-gradient(180deg,rgba(255,255,255,.86),rgba(255,255,255,.58));
  backdrop-filter:blur(14px) saturate(1.25);-webkit-backdrop-filter:blur(14px) saturate(1.25);
  border:1px solid rgba(255,255,255,.8);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),0 14px 30px -14px rgba(58,43,32,.5);
  opacity:0;transform:scale(.35);
  transition:transform .55s cubic-bezier(.34,1.4,.5,1) calc(var(--i) * 50ms),opacity .3s ease calc(var(--i) * 50ms);}
.radial__n{font-family:var(--display);font-size:9px;letter-spacing:.08em;opacity:.8;}
.radial__name{font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;font-weight:500;}
html.radial-open .radial__item{opacity:1;}
/* a quarter circle down and to the left of the three lines, 136 px out, clear of the nav */
html.radial-open .radial__item:nth-child(1){transform:translate(0,136px);}
html.radial-open .radial__item:nth-child(2){transform:translate(-68px,118px);}
html.radial-open .radial__item:nth-child(3){transform:translate(-118px,68px);}
.radial__item[aria-current]{background:var(--mahogany);color:var(--vanilla);border-color:rgba(88,71,56,.9);}
.radial__item:focus-visible{outline:2px solid var(--mahogany);outline-offset:3px;}
@media (min-width:821px){ .radial,.radial-veil{display:none;} }
@media (prefers-reduced-motion:reduce){
  .radial__item,.nav__menu span{transition:opacity .2s ease;}
  html.radial-open .radial__item{transform:none;}
  html.radial-open .radial__item:nth-child(1){transform:translate(0,136px);}
  html.radial-open .radial__item:nth-child(2){transform:translate(-68px,118px);}
  html.radial-open .radial__item:nth-child(3){transform:translate(-118px,68px);}
}

/* Her QA, 29 Sep (phone): "this part seems like it needs more space under 55". The Walk set's
   Add to bag sat right on the edge of the One rule section. The shop now ends with the same air
   the chapters open with. */
.shop{padding-bottom:clamp(120px,20vh,220px);}
@media (max-width:820px){ .shop{padding-bottom:clamp(104px,16vh,160px);} }

/* Her phone QA, 29 Sep: "make the video with Tashi bigger ... it reads so small compared to all the
   text". On a phone the wide films were 390 x 219. Now square, 390 x 390, cropped around him (checked
   on frames: the Bowls whole at every moment; the Bed and his settle whole, he walks in and out at the
   edge of the square). The Walk was square already. Desktop unchanged. */
@media (max-width:820px){
  #rest .piece__screen,#eat .piece__screen{aspect-ratio:1 / 1;}   /* the element carries its own --r, so the shape is set here */
  #rest .piece__film{object-position:35% 50%;}
  #eat .piece__film{object-position:46% 50%;}
}

/* On a phone his film plays by itself and you scroll past (js/shop.js, her call 29 Sep): the thin
   line along its foot shows where he is, a gauge, not a handle; the circle arrow plays it again. */
@media (pointer:coarse){
  .piece__screen .piece__line{pointer-events:none;}
}

/* Her desktop QA, 30 Sep: "a little bit too much space ... it took literally 3 times to get to the
   next part". Each object took about 2,000 px (nearly three screens at 713). Now about a third less:
   the shop's opening is no longer held to 78% of the screen, the chapters breathe less, and the film
   and product panels are only as tall as what they show (no longer a full screen each). */
.shop__head{min-height:0;padding:clamp(72px,12vh,130px) max(var(--gutter),8vw) clamp(32px,5vh,60px);}
.piece__chapter{padding:clamp(72px,12vh,140px) var(--gutter) clamp(40px,7vh,80px);}
@media (min-width:821px){
  .shop[data-frame="tucked"] .piece__story,
  .shop[data-frame="tucked"] .piece__product,
  .shop[data-frame="tucked"] .piece--flip .piece__product{min-height:0;padding-top:24px;padding-bottom:24px;}
  .shop[data-frame="tucked"] .piece__product,
  .shop[data-frame="tucked"] .piece--flip .piece__product{margin-top:clamp(24px,5vh,56px);}
}
.shop{padding-bottom:clamp(80px,12vh,150px);}

/* ---- The journey (1 Oct 2026): his walk to the Bed, played by the page scroll (js/journey.js) ----
   Edge to edge and frameless (Gate 2: the walk leaves the grid; the product panels stay tucked).
   Inside: the sticky picture, the run (the scroll that holds the room still, then plays him), the
   Bed's sheet, and the reveal stretch. All lengths are dials in % of a screen.
   - Big screens with a pointer (.has-reveal, 2 Oct): the sheet is sticky UNDER him; one screen after
     the walk his frame and the words shatter, then the sand sweeps down and the Bed shows through
     (her ask: the studio site's transition into Websites). It clicks into place at the end (snap).
   - Phones and no WebGL: the sheet rises over his last frame and clicks into place (snap). */
/* 2 Oct, her QA: the snap pulled her back after small movements; the Bed now holds by itself (js/journey.js) */
.journey{--j-lead:50;--j-length:520;--j-rest:60;--j-hold:100;--j-reveal:110;--j-why:0;position:relative;
  width:100vw;margin-left:calc(50% - 50vw);}
.journey__pin{position:sticky;top:0;z-index:2;height:100vh;height:100svh;overflow:hidden;background:var(--vanilla);}
.journey__poster,.journey__film,.journey__fx{position:absolute;inset:0;width:100%;height:100%;display:block;}
.journey__poster{object-fit:cover;}
.journey[data-fit="contain"] .journey__poster{object-fit:contain;}
.journey__film{opacity:0;}
.journey.is-live .journey__film{opacity:1;}
.journey__fx{display:none;}
/* the cue (2 Oct, her QA): at the bottom the whole way, in glass like the nav, the paws glass too */
.journey__cue{left:50%;top:auto;bottom:clamp(22px,5vh,48px);}
/* 2 Oct, her QA: no pill around them. The paws themselves are glass, like little buttons: a glass fill
   (#paw-glass in the page, bright at the top left), a bright rim and a soft shadow under each. Every scroll
   cue on the site wears them, and every scroll cue sits at the BOTTOM of its picture (her rule). */
.journey__cue .piece__cue-scroll,.journey__cue .piece__cue-click{top:auto;bottom:0;}
.piece__cue-icon:has(.cue-paws){filter:none;}
.cue-paws{grid-template-columns:repeat(2,19px);column-gap:9px;row-gap:3px;}
.cue-paws svg{width:19px;height:19px;fill:url(#paw-glass);stroke:rgba(255,255,255,.95);stroke-width:.9;
  filter:drop-shadow(0 1px 1.2px rgba(40,24,12,.45)) drop-shadow(0 0 6px rgba(255,255,255,.35));}
@media (min-width:821px){   /* phones keep their cue under the film */
  .piece__cue:not(.journey__cue):not(.journey__next){top:0;bottom:0;}
  .piece__cue:not(.journey__cue):not(.journey__next) .piece__cue-click{top:calc(var(--nav-h) + 20px);}
  .piece__cue:not(.journey__cue):not(.journey__next) .piece__cue-scroll{top:auto;bottom:clamp(20px,4vh,36px);}
}
/* below the Bed: the paws again, to go on to the next room */
.journey__next{position:absolute;left:50%;bottom:clamp(16px,3vh,32px);top:auto;z-index:4;}
.journey__next .piece__cue-scroll{top:auto;bottom:0;opacity:1;visibility:visible;transform:translate(-50%,0);}
.journey__next .piece__cue-word{color:var(--mahogany);text-shadow:none;}
.journey__next .cue-paws svg{stroke:rgba(88,71,56,.55);filter:drop-shadow(0 1px 1.2px rgba(40,24,12,.3));}
.journey__next .cue-paws svg,.journey__next .piece__cue-word{animation:cue-step 2.4s ease-in-out infinite backwards;}
.journey__next .cue-paws svg:nth-child(2){animation-delay:.4s;}
.journey__next .cue-paws svg:nth-child(3){animation-delay:.8s;}
.journey__next .cue-paws svg:nth-child(4){animation-delay:1.2s;}
.journey__next .piece__cue-word{animation:cue-blink 1.8s ease-in-out infinite;}
.is-still .journey__next *{animation-play-state:paused !important;}
.journey__cue[data-mode="scroll"] .cue-paws svg,
.journey__cue[data-mode="scroll"] .piece__cue-scroll .piece__cue-word{animation-iteration-count:infinite;}
.is-still .journey__cue .cue-paws svg,.is-still .journey__cue .piece__cue-word{animation-play-state:paused;}   /* the heat rule */
.journey__run{height:calc((var(--j-lead) + var(--j-length) + var(--j-rest)) * 1vh);
  height:calc((var(--j-lead) + var(--j-length) + var(--j-rest)) * 1svh);}
.journey__reveal{height:0;}
/* the why, over his last frame: a vanilla ground rises from the bottom-left so the ink reads on the floor */
.journey__ground{position:absolute;left:0;right:0;bottom:0;height:56%;pointer-events:none;opacity:var(--j-why);
  background:linear-gradient(to top,rgba(241,234,218,.94) 0%,rgba(241,234,218,.8) 34%,rgba(241,234,218,0) 100%);}
.journey__why{position:absolute;left:var(--gutter);bottom:clamp(28px,9vh,96px);max-width:min(560px,calc(100% - 2 * var(--gutter)));
  opacity:var(--j-why);transform:translateY(calc((1 - var(--j-why)) * 18px));pointer-events:none;}
.journey__why .piece__lead{margin:0 0 .6em;}
.journey__why .piece__note{margin:0;max-width:46ch;}
/* 3 Oct (afternoon), her QA, twice: first "the whole whitening makes it look like it's really low-res", then of the card that
   replaced it: "I also don't like the box style ... make him go to the right more, the whole image, and to the left there is
   a whole width where Tashi is saying this in a very editorial, beautiful way". THE SPLIT: as the words come (--j-why 0 to 1,
   by the scroll, after his pause) the film slides right and shows its middle; the left --j-split of the screen opens on the
   paper, and the words stand in it, large. Nothing is washed, shrunk or boxed: the film keeps every pixel it shows.
   Phones (a tall screen): the same, upward, the words in the paper below him. */
.journey__ground{display:none;}
.journey{--j-split:.42;}
/* the half screen's stop on touch screens (js/journey.js places it at the full split) */
.journey__stop{position:absolute;left:0;width:1px;height:1px;pointer-events:none;visibility:hidden;}
@media (pointer:coarse){
  html{scroll-snap-type:y proximity;}
  .journey__stop{scroll-snap-align:start;scroll-snap-stop:always;}
}
.journey__poster,.journey__film{
  transform:translateX(calc(var(--j-why, 0) * var(--j-split) * 50%));
  clip-path:inset(0 calc(var(--j-why, 0) * var(--j-split) * 50%));
  transition:transform .4s cubic-bezier(.22,1,.36,1),clip-path .4s cubic-bezier(.22,1,.36,1);}   /* a scroll that was ahead never snaps it */
.journey__why{left:0;top:var(--nav-h);bottom:0;width:calc(var(--j-split) * 100%);max-width:none;box-sizing:border-box;
  display:flex;flex-direction:column;justify-content:center;gap:clamp(14px,1.6vw,26px);
  padding:0 clamp(24px,3.6vw,72px) var(--nav-h) var(--gutter);
  opacity:clamp(0, calc((var(--j-why, 0) - .25) * 1.6), 1);
  transform:translateY(calc((1 - var(--j-why, 0)) * 26px));}
.journey__why .piece__lead{font-family:var(--display);font-size:clamp(22px,2.35vw,44px);line-height:1.22;letter-spacing:-.015em;
  color:#3A2A1F;max-width:17ch;margin:0;text-wrap:balance;}
.journey__why .piece__note{font-size:clamp(14px,1.05vw,17px);line-height:1.6;color:var(--ink-dim);max-width:34ch;margin:0;
  opacity:clamp(0, calc((var(--j-why, 0) - .55) * 2.4), 1);}
@media (max-aspect-ratio:4/5){
  /* 3 Oct (night), her phone QA ("Tashi looks huge ... you never really get to see the full bed") and her pick, the 4:5 window
     ("this blue line looks much better"): on a phone the film is a 4:5 box at the top (js/journey.js 'p' films), the paper
     below it holds the Scroll cue and then the words. The film never moves on a phone (no sliding, no clipping: smoother) */
  .journey{--j-film:min(calc(100vw * 1.25), calc(100svh - 210px));}
  .journey__poster,.journey__film{transition:none;transform:none;clip-path:none;bottom:auto;height:var(--j-film);}
  .journey__why{top:var(--j-film);right:0;bottom:0;width:auto;height:auto;
    padding:clamp(14px,2.6vh,24px) var(--gutter) clamp(16px,3vh,28px);justify-content:center;
    transform:translateY(calc((1 - var(--j-why, 0)) * 14px));}
  .journey__why .piece__lead{font-size:clamp(18px,5.2vw,24px);max-width:24ch;}
  .journey__why .piece__note{font-size:13.5px;max-width:none;}
  .journey__pin{background:rgb(240,234,218);}   /* the films' own paper, decoded (the page's is one step lighter): no seam */
  .journey .journey__cue{bottom:auto;top:calc(var(--j-film) + 128px);}
  .journey .journey__cue::before{display:none;}
  .journey .journey__cue .piece__cue-word{color:var(--mahogany);text-shadow:none;}
  .journey .journey__cue .cue-paws svg{stroke:rgba(88,71,56,.6);filter:drop-shadow(0 1px 1.2px rgba(40,24,12,.3));}
}
/* the Bed's sheet: one screen, the product panel in the middle of what the nav leaves */
.journey__sheet{position:relative;z-index:3;background:var(--vanilla);
  min-height:100vh;min-height:100svh;box-sizing:border-box;padding-top:var(--nav-h);
  display:flex;flex-direction:column;justify-content:center;
  scroll-snap-align:start;box-shadow:0 -28px 60px -40px rgba(58,43,32,.45);}
.shop .journey__sheet .piece__product{margin-top:0;}   /* the tucked layout's own margin pushed it 26 px past the screen */
.shop[data-frame="tucked"] .piece--flip .journey__sheet .piece__product{margin-top:0;}   /* the Bowls too: its flip margin made the panel 21 px taller than her screen */
/* big screens: the Bed waits under him, then the shatter and the sand reveal it */
.journey.has-reveal .journey__run{height:calc((var(--j-lead) + var(--j-length)) * 1vh);
  height:calc((var(--j-lead) + var(--j-length)) * 1svh);}
.journey.has-reveal .journey__sheet{position:sticky;top:0;z-index:1;height:100vh;height:100svh;box-shadow:none;scroll-snap-align:none;}
.journey.has-reveal .journey__reveal{height:calc(var(--j-reveal) * 1vh);height:calc(var(--j-reveal) * 1svh);scroll-snap-align:end;}
.journey.is-zooming .journey__fx{display:block;z-index:5;}   /* 2 Oct: the click zoom into the Bed (js/zoom-transition.js) */
.journey.is-zooming .journey__cue{visibility:hidden;}
.journey.is-clickable .journey__pin{cursor:pointer;}
.journey.is-shattering .journey__pin{background:transparent;}
.journey.is-shattering .journey__fx{display:block;}
.journey.is-shattering .journey__film,.journey.is-shattering .journey__poster,
.journey.is-shattering .journey__why,.journey.is-shattering .journey__ground,.journey.is-shattering .journey__cue{visibility:hidden;}
/* 2 Oct, a visitor's QA (her friend): "the scroll is barely visible, people don't know what to do". The word and the
   glass paws grow (dial "Cue size"), and on the film a soft shadow pools under the cue, a halo with no edge, not a
   pill (dial "Cue shadow"), so it reads over his white fur and on the bright floor alike; light words on phones too. */
:root{--cue-size:1.6;--cue-halo:1;}
.piece__cue-word{font-size:calc(10.5px * var(--cue-size));}
.piece__cue-click .piece__cue-word{font-size:calc(12.5px * var(--cue-size));}
.cue-paws{grid-template-columns:repeat(2,calc(19px * var(--cue-size)));column-gap:calc(9px * var(--cue-size));}
.cue-paws svg{width:calc(19px * var(--cue-size));height:calc(19px * var(--cue-size));}
.journey__cue::before{content:'';position:absolute;left:0;bottom:-44px;width:calc(230px * var(--cue-size));height:calc(150px * var(--cue-size));
  transform:translateX(-50%);pointer-events:none;opacity:0;transition:opacity .5s ease;
  background:radial-gradient(ellipse 50% 50% at 50% 55%,rgba(26,16,8,.46),rgba(26,16,8,.2) 52%,rgba(26,16,8,0) 100%);}
.journey__cue[data-mode]::before{opacity:var(--cue-halo);}
.journey__cue .piece__cue-word{color:#FFF9F0;font-weight:600;text-shadow:0 1px 2px rgba(20,12,6,.75),0 0 14px rgba(20,12,6,.6);}
.journey__cue .cue-paws svg{filter:drop-shadow(0 1px 2px rgba(20,12,6,.8)) drop-shadow(0 0 9px rgba(20,12,6,.4));}
/* 2 Oct, the same visitor: "once you are done with the clicking in the Bed, you cannot come back ... a Go back button".
   On the Bed's panel, top left under the nav: the Bed zooms back out into his last frame (js/journey.js). Words, no pill. */
.journey__back{position:absolute;top:calc(var(--nav-h) + 14px);left:var(--gutter);z-index:5;display:inline-flex;align-items:center;gap:.7em;
  min-height:44px;padding:0 4px;border:0;background:none;color:var(--mahogany);cursor:pointer;
  font:600 12.5px/1 var(--ui);letter-spacing:.2em;text-transform:uppercase;}
.journey__back span{font-size:1.35em;letter-spacing:0;transition:transform .3s ease;}
.journey__back:hover span,.journey__back:focus-visible span{transform:translateX(-4px);}
.journey__back:hover,.journey__back:focus-visible{text-decoration:underline;text-underline-offset:.45em;text-decoration-thickness:1px;}
.journey__back:focus-visible{outline:2px solid var(--mahogany);outline-offset:4px;border-radius:4px;}
/* the paws on the film never fade below a third, so the trail is always there (same QA) */
.journey__cue[data-mode="scroll"] .cue-paws svg{animation-name:cue-step-film;}
@keyframes cue-step-film{0%,100%{opacity:.38;}14%{opacity:1;}44%{opacity:.38;}}
/* phones, and any screen where the whole frame shows with cream bands (data-fit="contain"): the cue stands on the paper
   under the film, so it is ink, no shadow pool (a dark halo reads as a smudge on cream, 29 Sep) */
.journey[data-fit="contain"] .journey__cue::before{display:none;}
.journey[data-fit="contain"] .journey__cue .piece__cue-word{color:var(--mahogany);text-shadow:none;}
.journey[data-fit="contain"] .journey__cue .cue-paws svg{stroke:rgba(88,71,56,.6);filter:drop-shadow(0 1px 1.2px rgba(40,24,12,.3));}
/* 2 Oct, her QA (it sat on top of "The Bed" on a laptop): big screens carry it inside the picture's frame, top left */
.journey__back.is-in-frame{top:14px;left:18px;z-index:7;}
/* phones: no Back to Tashi (her QA, 3 Oct: "it is a desktop thing"); scrolling up takes you back to him */
@media (max-width:820px){
  .journey__back{display:none;}
}

/* 3 Oct (evening), her phone QA: "Tap for the materials" stood huge under the nav ("a small letter placed somewhere else"):
   on a phone it is one small line of type at the foot of the picture, left, beside nothing. Last in the file on purpose: the
   product panel's own cue rules above would win otherwise */
@media (max-width:820px){
  .piece__product .piece__pics .piece__cue,.piece__product .piece__cue{top:auto;bottom:8px;left:var(--gutter);}
  .piece__product .piece__cue[data-mode] .piece__cue-click,.piece__product .piece__cue .piece__cue-click{position:static;transform:none;}
  .piece__product .piece__cue[data-mode] .piece__cue-word,.piece__product .piece__cue .piece__cue-word{font-size:10.5px;letter-spacing:.22em;color:var(--ink-dim);animation:none;text-shadow:none;}
  .piece__product .piece__cue .cue-tap{display:none;}
}

/* 3 Oct (night), her phone QA: "the navbar has to disappear because it's blocking the image ... just put the three bars" and of
   the fan of round rooms, "three circles ... just keep the three bars". Past the hero a phone keeps only the three lines, on a
   small glass square; they open a plain list card: 01 Rest, 02 Eat, 03 Walk and the Bag. Last in the file on purpose */
@media (max-width:820px){
  .nav,.nav > *{transition:background-color .3s ease,border-color .3s ease,box-shadow .3s ease,opacity .3s ease,visibility 0s linear 0s;}
  html.nav-min .nav{background:none;border-color:transparent;box-shadow:none;backdrop-filter:none;-webkit-backdrop-filter:none;pointer-events:none;}
  html.nav-min .nav > :not(.nav__menu){opacity:0;visibility:hidden;transition:opacity .3s ease,visibility 0s linear .3s;}
  html.nav-min .nav__menu{pointer-events:auto;margin-right:-10px;border-radius:14px;
    background:linear-gradient(180deg,rgba(255,255,255,.62),rgba(255,255,255,.34));
    backdrop-filter:blur(18px) saturate(1.5);-webkit-backdrop-filter:blur(18px) saturate(1.5);
    border:1px solid rgba(255,255,255,.75);box-shadow:0 10px 26px -14px rgba(58,43,32,.45);}
  .radial{left:auto;right:var(--gutter);top:calc(var(--nav-h) + 6px);width:min(232px,calc(100vw - 2 * var(--gutter)));height:auto;
    display:flex;flex-direction:column;padding:6px;border-radius:18px;
    background:linear-gradient(180deg,rgba(255,255,255,.86),rgba(255,255,255,.66));
    backdrop-filter:blur(18px) saturate(1.3);-webkit-backdrop-filter:blur(18px) saturate(1.3);
    border:1px solid rgba(255,255,255,.8);box-shadow:0 22px 50px -24px rgba(58,43,32,.5);
    opacity:0;transform:translateY(-6px);transition:opacity .25s ease,transform .3s cubic-bezier(.22,1,.36,1),visibility 0s linear .3s;}
  html.radial-open .radial{opacity:1;transform:none;transition:opacity .25s ease,transform .3s cubic-bezier(.22,1,.36,1);}
  .radial__item,html.radial-open .radial__item,html.radial-open .radial__item:nth-child(n){position:static;width:auto;height:auto;margin:0;
    flex-direction:row;justify-content:flex-start;align-items:baseline;gap:14px;padding:15px 16px;border-radius:12px;
    background:none;border:0;box-shadow:none;backdrop-filter:none;-webkit-backdrop-filter:none;opacity:1;transform:none;transition:background-color .2s ease;}
  .radial__item + .radial__item{border-top:1px solid var(--hair);border-radius:0;}
  .radial__n{font-size:10px;min-width:18px;}
  .radial__name{font-size:13px;letter-spacing:.2em;}
  .radial__item[aria-current]{background:rgba(88,71,56,.08);color:var(--mahogany);}
  .radial__item--home{align-items:center;gap:12px;}
  .radial__dot{width:10px;height:10px;border-radius:50%;background:var(--orange);flex:none;margin:0 4px 0 4px;}
  .radial__item--home .radial__name{font-family:var(--display);font-size:13px;letter-spacing:.22em;}
  .radial__item--bag .radial__count{min-width:20px;height:20px;border-radius:10px;background:var(--orange);color:var(--vanilla);
    font-family:var(--ui);font-size:11px;letter-spacing:0;opacity:1;display:grid;place-items:center;padding:0 6px;align-self:center;}
}

/* 3 Oct (night), her QA: "my phone got super hot". The paper grain is a layer three and a half screens big, blended (multiply)
   over everything and stepped every 0.7 s: on a phone that is a whole-screen blend on every scrolled frame. Phones go without it */
@media (pointer:coarse){ .grain{display:none;} }

