/* TRACE · the room (landing-room branch): one pinned stage the page scrolls through.
   The picture is js/room/room.js; this file holds the words around it, the labels, the
   photo and the DM at the end. Same tokens as landing.css: paper, ink, olive; orange only
   ever means a route. */

.room{position:relative;--room-total:14.1;height:calc((var(--room-total) + 1) * 100vh)}
/* the menu's links land at points along the story (screens from its top) */
.room-at{position:absolute;left:0;width:1px;height:1px;top:calc(var(--at) * 100vh);scroll-margin-top:0;pointer-events:none}
/* The stage, and the picture filling it, are as tall as the screen can get (lvh): a fixed
   size, so the picture is never drawn again while a phone's browser bar grows and shrinks and
   never leaves a strip of bare paper under it (Nam 01-10, iPhone). Only what sits at the
   bottom (the card, the cue, the chat) rides up by --bar, the part of the screen the bar
   covers right now. (A dvh stage with an lvh picture clipped inside it made Safari on an
   iPhone 12 Pro show the picture as bare paper every few frames while scrolling) */
.room-stage{position:sticky;top:0;height:100vh;height:100lvh;overflow:hidden;background:var(--paper);isolation:isolate;--bar:0px}
@supports (height:100dvh){.room-stage{--bar:max(0px,calc(100lvh - 100dvh))}}
.room-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;opacity:0;transition:opacity 1.1s var(--ease)}
.room.ready .room-canvas{opacity:1}
/* Nothing frosted over the picture: it redraws every frame, and a blur behind glass is done
   again with it, a whole-screen cost an older phone cannot pay (Nam 01-10, iPhone X: "giật").
   The bar, the card, the readout and the cue sit on plain paper instead */
.site-head.scrolled{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgba(241,237,227,.96)}
.room-steps .swatches button{-webkit-backdrop-filter:none;backdrop-filter:none}
/* the frame rate the page measures, when the address ends in ?fps */
.room-fps{position:absolute;z-index:9;left:10px;right:10px;top:calc(var(--head-h) + 8px);padding:3px 7px;border-radius:6px;background:rgba(20,22,18,.72);color:#fff;
  font:500 11px/1.35 ui-monospace,Menlo,monospace;pointer-events:none;width:max-content;max-width:calc(100% - 20px)}
.room-loading{position:absolute;left:66%;top:52%;width:12px;height:12px;margin:-6px;border-radius:50%;background:var(--route);
  animation:pulse 1.4s var(--ease-io) infinite;transition:opacity .5s}
.room.ready .room-loading{display:none}
@keyframes pulse{0%,100%{transform:scale(.6);opacity:.35}50%{transform:scale(1);opacity:1}}
/* no WebGL (or no script): no story to scroll through. The first screen's words over the
   photograph, then the DM, as plain blocks */
.room.no3d,html:not(.js) .room{height:auto}
.room.no3d .room-stage,html:not(.js) .room-stage{position:relative;height:auto;overflow:visible;background:none}
.room.no3d .room-canvas,.room.no3d .room-loading,.room.no3d .room-copy,.room.no3d .room-cue,.room.no3d .room-hud,.room.no3d .room-leaders,
.room.no3d .room-label,.room.no3d .room-photo,.room.no3d .room-flash,
html:not(.js) .room-canvas,html:not(.js) .room-loading,html:not(.js) .room-copy,html:not(.js) .room-cue,html:not(.js) .room-hud,
html:not(.js) .room-leaders,html:not(.js) .room-label,html:not(.js) .room-photo,html:not(.js) .room-flash{display:none}
.room.no3d .room-hero,html:not(.js) .room-hero{position:relative;inset:auto;top:auto;transform:none;margin:0;width:auto;max-width:720px;
  padding:calc(var(--head-h) + 64px) var(--gutter) 48px;opacity:1 !important;visibility:visible !important}
.room.no3d .room-hero::before,html:not(.js) .room-hero::before{display:none}
.room.no3d .room-stage::before,html:not(.js) .room-stage::before{content:"";display:block;order:2;height:min(70vh,620px);margin:0 var(--gutter);border-radius:20px;
  background:url("../assets/photos/angle-1000.jpg") center 60%/cover}
.room.no3d .room-stage,html:not(.js) .room-stage{display:flex;flex-direction:column}
.room.no3d .room-hero,html:not(.js) .room-hero{order:1}
.room.no3d .room-chat,html:not(.js) .room-chat{order:3;position:relative;inset:auto;opacity:1;transform:none;visibility:visible;pointer-events:auto;
  padding:clamp(56px,8vw,120px) var(--gutter)}
.room.no3d .chat-msg,html:not(.js) .chat-msg{opacity:1;transform:none}
.room.no3d .chat-shot,html:not(.js) .chat-shot{background:url("../assets/photos/angle-1000.jpg") center/cover}

/* ------------------------------------------------------------ the first screen, at the door */
/* (centred under the bar by its transform; room.js lifts it away with `translate`, never this) */
.room-hero{position:absolute;z-index:3;left:var(--gutter);top:50%;width:min(680px,44vw);margin-top:calc(var(--head-h) / 2);
  transform:translateY(-50%);will-change:opacity,translate}
.room-hero>*{position:relative}
.room-hero.away{visibility:hidden}
.room-hero h1{font-size:clamp(46px,5.4vw,84px);line-height:.98}
.room-hero .lede{max-width:24em}
.room-hero .cta-row{margin-top:30px}
/* the hero rises on first paint (landing.css's .hero rule, for this block) */
.js .room-hero .eyebrow,.js .room-hero h1,.js .room-hero .lede,.js .room-hero .cta-row{animation:rise 1.1s var(--ease) both}
.js .room-hero h1{animation-delay:80ms}
.js .room-hero .lede{animation-delay:160ms}
.js .room-hero .cta-row{animation-delay:240ms}
/* the words sit on the hallway's paper; a soft wash keeps them clear of any line behind */
.room-hero::before{content:"";position:absolute;inset:-60px -80px -60px calc(-1 * var(--gutter));z-index:-1;pointer-events:none;
  background:radial-gradient(closest-side,rgba(241,237,227,.92),rgba(241,237,227,.75) 60%,rgba(241,237,227,0))}

/* ------------------------------------------------------------ the card of words */
.room-copy{position:absolute;z-index:3;left:var(--gutter);top:50%;width:min(390px,30vw);transform:translateY(-50%);pointer-events:none;
  opacity:0;transition:opacity .5s var(--ease)}
.room-copy.show{opacity:1}
/* the drawing runs behind the words: a paper wash keeps them clear (not on phones: a card there) */
.room-copy::before{content:"";position:absolute;inset:-70px -90px -70px calc(-1 * var(--gutter) - 120px);z-index:-1;pointer-events:none;
  background:radial-gradient(closest-side,rgba(241,237,227,.94),rgba(241,237,227,.78) 55%,rgba(241,237,227,0))}
.room-copy.show .room-bars,.room-copy.show li[data-pos="on"] a,.room-copy.show li[data-pos="on"] button{pointer-events:auto}
.room-bars{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px;width:250px;margin:-10px 0 18px}
.room-bars button{display:block;height:24px;margin:0;padding:10.5px 0;border:0;background:none;cursor:pointer;-webkit-tap-highlight-color:transparent}
.room-bars button:focus-visible{outline-offset:1px}
.room-bars i{display:block;position:relative;height:3px;border-radius:2px;background:var(--rule);overflow:hidden;transition:transform .2s var(--ease)}
.room-bars i::after{content:"";position:absolute;inset:0;background:var(--ink-2);transform-origin:left center;transform:scaleX(var(--f,0))}
@media (hover:hover){.room-bars button:hover i{transform:scaleY(1.7)}}
.room-steps{list-style:none;margin:0;padding:0;display:grid}
.room-steps li{grid-area:1 / 1;transition:opacity .45s var(--ease),transform .7s var(--ease)}
.room-steps li[data-pos="past"]{opacity:0;transform:translateY(-18px);pointer-events:none}
.room-steps li[data-pos="next"]{opacity:0;transform:translateY(18px);pointer-events:none}
.room-steps li[data-pos="on"]{opacity:1;transform:none;transition-delay:.1s}
.room-steps .step-no{font-size:12px;letter-spacing:.24em;text-transform:uppercase;color:var(--ink-3)}
.room-steps h3{font-size:clamp(28px,2.9vw,44px);line-height:1.08;letter-spacing:-.02em;margin-top:14px;max-width:12em;text-wrap:balance}
.room-steps .sub{font-size:16px;margin-top:14px}
.room-go{color:var(--olive);text-underline-offset:4px;text-decoration-color:rgba(70,84,60,.35)}
.room-go:hover{text-decoration-color:currentColor}
.room-steps .swatches{justify-content:flex-start;margin-top:20px;max-width:360px}

/* ------------------------------------------------------------ "scroll to step in"
   A pill on paper (Nam 01-10: it sank into the drawing): the mouse's wheel turning (a finger
   swiping on touch), the words in full ink, a chevron that keeps dropping */
.room-cue{position:absolute;z-index:4;left:50%;bottom:calc(28px + var(--bar,0px));display:flex;align-items:center;gap:11px;padding:9px 16px 9px 13px;border-radius:999px;
  background:rgba(246,243,235,.97);
  box-shadow:0 0 0 1px rgba(32,36,28,.16),0 14px 30px -16px rgba(32,36,28,.5);color:var(--ink);pointer-events:none;
  opacity:0;transform:translate(-50%,10px);transition:opacity .4s var(--ease),transform .55s var(--ease)}
.room-cue.show{opacity:1;transform:translate(-50%,0)}
.room-cue .cue-glyph{width:17px;height:25px;flex:none}
.room-cue .cue-swipe{width:20px}
.room-cue .cue-text{font-size:12px;letter-spacing:.2em;text-transform:uppercase;white-space:nowrap;color:var(--ink)}
.cue-down{width:15px;height:15px;flex:none;fill:none;stroke:var(--olive);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
@media (prefers-reduced-motion:no-preference){
  .room-cue.show .cue-wheel{animation:cue-wheel 1.7s var(--ease-io) infinite}
  .room-cue.show .cue-tip{animation:cue-tip 1.9s var(--ease-io) infinite}
  .room-cue.show .cue-chev{animation:cue-chev 1.9s var(--ease-io) infinite}
  .room-cue.show .cue-down{animation:cue-drop 1.7s var(--ease-io) infinite}
  .room-cue.show{animation:cue-breathe 3.4s var(--ease-io) 1s infinite}
}
@keyframes cue-drop{0%{transform:translateY(-3px);opacity:.25}45%{transform:translateY(2px);opacity:1}100%{transform:translateY(4px);opacity:0}}
@keyframes cue-breathe{0%,100%{box-shadow:0 0 0 1px rgba(32,36,28,.16),0 14px 30px -16px rgba(32,36,28,.5)}50%{box-shadow:0 0 0 1px rgba(70,84,60,.45),0 14px 30px -16px rgba(32,36,28,.5)}}

/* ------------------------------------------------------------ the GPX readout */
.room-hud{position:absolute;z-index:2;left:0;top:0;display:flex;gap:10px;align-items:baseline;white-space:nowrap;
  padding:7px 11px;border-radius:10px;background:rgba(241,237,227,.95);
  box-shadow:0 0 0 1px var(--rule),0 8px 20px -12px rgba(32,36,28,.4);font-size:12px;color:var(--ink-2);
  font-variant-numeric:tabular-nums;opacity:0;transition:opacity .4s;pointer-events:none;will-change:transform}
.room-hud b{font-weight:500;color:var(--ink);font-size:13px}
.room-hud .hud-ll{color:var(--ink-3)}
.room-hud.show{opacity:1}

/* ------------------------------------------------------------ the wide view's two labels */
.room-leaders{position:absolute;inset:0;z-index:2;width:100%;height:100%;pointer-events:none;opacity:0;overflow:visible}
.room-leaders path{fill:none;stroke:var(--graphite);stroke-width:1;stroke-dasharray:3 3;opacity:.7}
.room-leaders circle{fill:var(--paper);stroke:var(--graphite);stroke-width:1.2}
.room-label{position:absolute;z-index:2;left:0;top:0;padding:6px 12px 6px;border-radius:999px;background:rgba(241,237,227,.92);
  box-shadow:0 0 0 1px var(--rule);font-size:11.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--ink);white-space:nowrap;
  opacity:0;pointer-events:none;will-change:transform}

/* ------------------------------------------------------------ the photo, and its flash */
.room-photo{position:absolute;z-index:4;left:0;top:0;width:100%;height:100%;transform-origin:0 0;border-radius:0;visibility:hidden;pointer-events:none;
  box-shadow:0 30px 60px -30px rgba(32,36,28,.45),0 0 0 1px rgba(32,36,28,.08);will-change:transform}
.room-flash{position:absolute;inset:0;z-index:5;background:#fff;opacity:0;pointer-events:none}
.room.flash .room-flash{animation:room-flash .6s ease-out both}
@keyframes room-flash{0%{opacity:0}12%{opacity:.85}100%{opacity:0}}

/* ------------------------------------------------------------ the DM */
.room-chat{--in:0;position:absolute;inset:0 0 var(--bar,0px);z-index:3;display:grid;grid-template-columns:auto minmax(0,440px);justify-content:center;align-items:center;
  gap:clamp(40px,6vw,110px);padding:calc(var(--head-h) + 24px) var(--gutter) 32px;pointer-events:none;
  opacity:var(--in);transform:translateY(calc((1 - var(--in)) * 36px))}
.room-chat.on{pointer-events:auto}
.room-chat:not(.on){visibility:hidden}
.chat-phone{position:relative;display:flex;flex-direction:column;width:min(330px,80vw);height:min(560px,calc(100svh - var(--head-h) - 80px));
  border-radius:44px;background:#FBF9F4;padding:14px 12px 12px;
  box-shadow:0 0 0 1.5px var(--graphite),0 0 0 9px #F6F3EC,0 0 0 10.5px var(--graphite),0 50px 80px -40px rgba(32,36,28,.55)}
.chat-head{display:flex;align-items:center;gap:10px;padding:10px 8px 12px;border-bottom:1px solid var(--rule)}
.chat-ava{display:grid;place-items:center;width:36px;height:36px;border-radius:50%;background:var(--olive);color:var(--cream);flex:none}
.chat-ava svg{width:24px;height:auto;aspect-ratio:879/104}
.chat-who{display:grid;line-height:1.2}
.chat-who b{font-weight:500;font-size:14.5px;color:var(--ink)}
.chat-who span{font-size:11.5px;color:var(--ink-3)}
/* the thread measures itself (a size container): what it shows is fitted to its own height, on any
   phone and either way Safari's bar is (Nam 01-10, iPhone 12 Pro: the photo spilled out over the
   header when the thread was shorter than its messages) */
.chat-thread{position:relative;flex:1;display:flex;flex-direction:column;justify-content:flex-start;gap:6px;padding:14px 4px 10px;overflow:hidden;container-type:size}
.chat-msg{max-width:82%;margin:0;padding:9px 13px;border-radius:20px;font-size:14px;line-height:1.35;
  opacity:0;transform:translateY(10px) scale(.96);transform-origin:right bottom;transition:opacity .35s var(--ease),transform .5s var(--ease)}
.chat-msg.in{opacity:1;transform:none}
.chat-msg.me{align-self:flex-end;background:var(--olive);color:var(--cream);border-bottom-right-radius:6px}
.chat-msg.them{align-self:flex-start;background:#ECE7DB;color:var(--ink);border-bottom-left-radius:6px;transform-origin:left bottom}
/* the photo takes what the words leave: about 200 px of the thread's height go to three messages */
.chat-msg.photo{padding:0;background:none;width:min(96%,calc((100cqh - 200px) * var(--shot-ar,1.6)));max-width:none;opacity:1;transform:none}
.chat-shot{display:block;width:100%;aspect-ratio:var(--shot-ar,1.6);border-radius:14px}
@media (max-width:900px){.room{--shot-ar:.8}.chat-msg.photo{width:min(64%,calc((100cqh - 200px) * .8))}}
/* a short phone: one message fewer, so the photo and TRACE's answer still fit */
/* a shorter thread lets the words go before the photo shrinks: first the thanks, then (very
   short: an iPhone SE with Safari's bar out) the caption too; the photo and TRACE's answer stay */
@container (max-height:370px){.chat-msg[data-msg="2"]{display:none}.chat-msg.photo{width:min(64%,calc((100cqh - 148px) * var(--shot-ar,.8)))}}
@container (max-height:250px){.chat-msg[data-msg="1"]{display:none}.chat-msg.photo{width:min(64%,calc((100cqh - 94px) * var(--shot-ar,.8)))}}
/* TRACE's answer and its typing dots share one place (the two are never shown together), so the
   dots take no room of their own */
.chat-turn{display:grid}
.chat-turn>*{grid-area:1 / 1;justify-self:start;align-self:start}
.chat-typing{display:flex;gap:4px;margin:0;padding:11px 13px;border-radius:20px;background:#ECE7DB;opacity:0;transition:opacity .3s}
.chat-typing i{width:6px;height:6px;border-radius:50%;background:var(--ink-3);animation:typing 1.2s var(--ease-io) infinite}
.chat-typing i:nth-child(2){animation-delay:.15s}
.chat-typing i:nth-child(3){animation-delay:.3s}
@keyframes typing{0%,60%,100%{transform:none;opacity:.5}30%{transform:translateY(-3px);opacity:1}}
/* the dots show while TRACE "types", then give way to its answer */
.chat-typing.in{opacity:0}
.room-chat.typing .chat-typing{opacity:1}
.chat-input{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:6px 2px 2px;height:46px;padding:0 8px 0 18px;border-radius:999px;
  border:1px solid rgba(32,36,28,.2);color:var(--ink-3);font-size:14px;text-decoration:none;transition:border-color .25s,color .25s}
.chat-input svg{width:30px;height:30px;padding:6px;border-radius:50%;background:var(--olive);fill:var(--cream);flex:none}
.chat-input:hover{border-color:var(--olive);color:var(--ink)}
.chat-cta h2{font-size:clamp(34px,3.6vw,56px)}
.chat-cta .cta-handle{margin-top:18px;font-size:13.5px;color:var(--ink-3)}
.chat-cta .cta-handle a{color:var(--ink);text-underline-offset:3px;text-decoration-color:rgba(32,36,28,.3)}
/* the page ends here: the data credits the footer used to carry */
.chat-fine{position:absolute;left:var(--gutter);right:var(--gutter);bottom:14px;margin:0;text-align:center;font-size:11.5px;line-height:1.4;color:var(--ink-3);opacity:.8}

/* ------------------------------------------------------------ the DM button, made to be pressed
   (Nam 01-10: "tempting hơn"): a paper plane in a cream chip, a ring that breathes out of the
   button, a light that passes over it now and then; on hover the plane takes off and comes
   round again. Olive, never orange (orange is a route). Still for reduced motion */
.btn-dm{position:relative;isolation:isolate;gap:12px;padding:0 7px 0 24px}
.btn-dm::before{content:"";position:absolute;inset:0;border-radius:inherit;border:1.5px solid var(--olive);opacity:0;pointer-events:none;z-index:-1}
.btn-dm-shine{position:absolute;inset:0;border-radius:inherit;overflow:hidden;pointer-events:none}
.btn-dm-shine::before{content:"";position:absolute;top:0;bottom:0;left:0;width:34%;
  background:linear-gradient(100deg,rgba(255,255,255,0),rgba(255,255,255,.26),rgba(255,255,255,0));transform:translateX(-130%) skewX(-18deg)}
.btn-dm-plane{display:grid;place-items:center;width:36px;height:36px;border-radius:50%;background:var(--cream);color:var(--olive-2);flex:none;overflow:hidden}
.btn-dm-plane svg{width:17px;height:17px;fill:currentColor;stroke:var(--cream);stroke-width:1.2;stroke-linecap:round;transform:translate(-1px,1px)}
.chat-cta .btn-dm{height:56px;font-size:16.5px;padding-left:28px}
.chat-cta .btn-dm .btn-dm-plane{width:42px;height:42px}
@media (prefers-reduced-motion:no-preference){
  .btn-dm::before{animation:dm-ring 2.8s cubic-bezier(.25,.6,.3,1) infinite}
  .btn-dm-shine::before{animation:dm-shine 4.4s var(--ease-io) 1.2s infinite}
  .btn-dm-plane svg{animation:dm-hop 2.8s var(--ease-io) infinite}
  .btn-dm:hover::before{animation:none}
  .btn-dm:hover .btn-dm-plane svg{animation:dm-send .95s var(--ease) infinite}
}
/* (a button out of sight keeps still: the hero's once the door is behind, the chat's until it
   comes up) */
.room-hero.away .btn-dm::before,.room-hero.away .btn-dm-shine::before,.room-hero.away .btn-dm-plane svg,
.room-chat:not(.on) .btn-dm::before,.room-chat:not(.on) .btn-dm-shine::before,.room-chat:not(.on) .btn-dm-plane svg{animation:none}
@keyframes dm-ring{0%{opacity:.55;transform:scale(1)}80%,100%{opacity:0;transform:scale(1.07,1.42)}}
@keyframes dm-shine{0%{transform:translateX(-130%) skewX(-18deg)}32%,100%{transform:translateX(330%) skewX(-18deg)}}
@keyframes dm-hop{0%,68%,100%{transform:translate(-1px,1px) rotate(0)}76%{transform:translate(2px,-2px) rotate(-12deg)}86%{transform:translate(-1px,1px) rotate(0)}}
@keyframes dm-send{0%{transform:translate(-1px,1px);opacity:1}42%{transform:translate(17px,-17px);opacity:0}43%{transform:translate(-17px,17px);opacity:0}100%{transform:translate(-1px,1px);opacity:1}}
/* the phone's message box: a caret waiting, the send button nudging */
.chat-typed{display:inline-flex;align-items:center}
.chat-caret{display:inline-block;width:1.5px;height:1.05em;margin-left:3px;background:var(--olive);opacity:0}
.chat-input svg{transition:transform .35s var(--ease)}
.chat-input:hover svg{transform:translate(2px,-1px) rotate(-8deg)}
@media (prefers-reduced-motion:no-preference){
  .room-chat.on .chat-caret{animation:caret 1.05s steps(1) infinite}
  .room-chat.on .chat-input svg{animation:send-nudge 2.8s var(--ease-io) .6s infinite}
  .room-chat.on .chat-input:hover svg{animation:none}
}
@keyframes caret{0%,49%{opacity:1}50%,100%{opacity:0}}
@keyframes send-nudge{0%,62%,100%{transform:none}72%{transform:scale(1.14) rotate(-10deg)}84%{transform:none}}

/* ------------------------------------------------------------ the phone menu: the journey
   A card under the bar (not a full-width sheet, not a list of rows with chevrons): the five
   chapters, the one you are in lit olive; Instagram, VI · EN (narrowest phones) and the 3D
   preview (laptops) at its foot. The page behind is not dimmed, so the bar stays as it is */
.sh-menu.sh-journey{inset:calc(var(--head-h) + 8px) max(12px,env(safe-area-inset-right)) auto auto;width:min(330px,calc(100vw - 24px));
  padding:16px 12px 10px;border-radius:22px;background:rgba(247,244,237,.98);
  box-shadow:0 0 0 1px rgba(32,36,28,.09),0 30px 60px -26px rgba(32,36,28,.5),0 8px 18px -12px rgba(32,36,28,.25);
  transform-origin:calc(100% - 26px) -10px}
.sh-journey::backdrop{background:transparent}
.shj-head{margin:0 12px 8px;font-size:11px;letter-spacing:.24em;text-transform:uppercase;color:#686D61}
.sh-journey nav{display:grid;gap:2px}
.sh-journey nav a{position:relative;display:flex;align-items:center;gap:14px;min-height:48px;padding:0 14px;border:0;border-radius:14px;
  font-size:19px;letter-spacing:-.01em;color:#20241C;transition:background-color .2s,color .2s}
.sh-journey nav a::after{content:"";width:6px;height:6px;margin-left:auto;margin-right:0;border:0;border-radius:50%;background:#46543C;transform:scale(0);opacity:1;transition:transform .3s cubic-bezier(.22,.8,.18,1)}
.sh-journey nav a i{font-style:normal;width:22px;font-size:11.5px;letter-spacing:.12em;color:#8C9185;font-variant-numeric:tabular-nums}
.sh-journey nav a[data-on]{background:rgba(70,84,60,.1)}
.sh-journey nav a[data-on] i{color:#46543C}
.sh-journey nav a[data-on]::after{transform:scale(1)}
@media (hover:hover){.sh-journey nav a:hover{background:rgba(32,36,28,.05)}.sh-journey nav a[data-on]:hover{background:rgba(70,84,60,.14)}}
.shj-foot{display:flex;flex-wrap:wrap;align-items:center;gap:6px 16px;margin:10px 4px 0;padding:12px 10px 4px;border-top:1px solid rgba(32,36,28,.09);font-size:13.5px;color:#4A5043}
.shj-foot a{color:inherit;text-decoration:none}
.shj-foot a[data-ig]{text-decoration:underline;text-decoration-color:rgba(32,36,28,.25);text-underline-offset:3px}
.shj-foot .sh-m-preview{margin-left:auto}
.shj-lang{display:none;margin-left:auto}
@media (max-width:359px){.shj-lang{display:flex}}
@media (max-width:599px){.sh-menu.sh-journey{left:max(12px,env(safe-area-inset-left));right:max(12px,env(safe-area-inset-right));width:auto}}
@media (prefers-reduced-motion:no-preference){
  .sh-journey:popover-open,.sh-journey.open{animation:shj-in .32s cubic-bezier(.22,.8,.18,1)}
  .sh-journey:popover-open nav a,.sh-journey.open nav a{animation:shj-item .42s cubic-bezier(.22,.8,.18,1) both;animation-delay:calc(60ms + var(--i) * 38ms)}
}
@keyframes shj-in{from{opacity:0;transform:translateY(-10px) scale(.96)}}
@keyframes shj-item{from{opacity:0;transform:translateY(8px)}}

/* ------------------------------------------------------------ phones */
@media (max-width:900px){
  .room-hero{top:calc(var(--head-h) + 14px);right:var(--gutter);width:auto;margin:0;transform:none}
  .room-hero h1{font-size:clamp(38px,10.6vw,54px)}
  .room-hero .lede{margin-top:14px;font-size:15.5px}
  .room-hero .cta-row{margin-top:18px}
  .room-hero::before{inset:-40px -30px -30px -30px}
  .room-copy::before{display:none}
  .room-copy{inset:auto 12px calc(12px + var(--bar,0px));top:auto;transform:none;width:auto;padding:14px 16px 16px;border-radius:18px;
    background:rgba(241,237,227,.97);box-shadow:0 0 0 1px var(--rule),0 16px 34px -20px rgba(32,36,28,.45)}
  .room-bars{width:190px;gap:5px;margin:-10px 0 2px}
  .room-steps h3{font-size:21px;margin-top:6px}
  .room-steps .sub{font-size:14px;margin-top:5px}
  .room-steps .swatches{margin-top:12px;flex-wrap:nowrap;gap:6px}
  .room-steps .swatches button{height:32px;font-size:12px;padding:0 10px 0 5px;gap:7px}
  .room-steps .swatches i{width:16px;height:16px}
  .room-cue{bottom:calc(22px + var(--bar,0px))}
  .room-hud .hud-ll{display:none}
  /* (the button gets room to breathe: Nam 01-10 "đỡ chật") */
  .room-chat{grid-template-columns:minmax(0,1fr);justify-items:center;align-content:center;gap:28px;padding:calc(var(--head-h) + 12px) 16px 22px}
  .chat-phone{width:min(330px,86vw);height:min(560px,calc(100svh - var(--head-h) - 186px));border-radius:36px}
  /* (a lighter frame round the thread, so the photo gets the room) */
  .chat-head{padding:6px 6px 9px;gap:9px}
  .chat-ava{width:30px;height:30px}
  .chat-ava svg{width:20px}
  .chat-who b{font-size:14px}
  .chat-msg{font-size:13.5px;padding:8px 12px}
  .chat-input{height:42px;margin:4px 2px 2px}
  .chat-input svg{width:28px;height:28px}
  .chat-cta{text-align:center}
  .chat-cta .eyebrow,.chat-cta h2,.chat-cta .sub{display:none}
  .chat-cta .cta-row{justify-content:center;margin-top:0}
  .chat-cta .btn-dm{height:54px;font-size:15.5px;padding:0 8px 0 30px;gap:16px}
  .chat-cta .btn-dm .btn-dm-plane{width:38px;height:38px}
  .chat-cta .cta-handle{margin-top:18px}
  .chat-fine{bottom:8px;font-size:10px}
}
@media (max-width:360px){.room-steps .swatches button{padding:0 8px 0 5px}}
/* a short phone (an SE with Safari's bar out): the handle goes, the gaps close, the chat grows */
@media (max-width:900px) and (max-height:620px){
  .room-chat{gap:18px}
  .chat-cta .cta-handle{display:none}
  .chat-phone{height:min(560px,calc(100svh - var(--head-h) - 128px))}
}
@media (prefers-reduced-motion:reduce){
  .room.flash .room-flash{animation:none}
  .chat-msg,.room-steps li{transition:opacity .2s}
  .js .room-hero .eyebrow,.js .room-hero h1,.js .room-hero .lede,.js .room-hero .cta-row{animation:none}
}

/* ------------------------------------------------------------ a piece up close (js/room/viewer.js)
   "Xem 3D" on each product's card, on the line of its kicker; the wide view's labels are buttons
   once they are in full view; a mouse over a piece gets the hand and a small pill beside it */
.room-steps .step-no{display:flex;align-items:center;gap:12px;min-height:30px}
.room-view{display:inline-flex;align-items:center;gap:6px;flex:none;height:30px;margin:-4px 0 -4px 6px;padding:0 13px 0 9px;border-radius:999px;
  border:1px solid rgba(70,84,60,.38);background:rgba(246,243,235,.92);color:var(--olive-2);font:400 12.5px/1 var(--sans);letter-spacing:.02em;
  text-transform:none;white-space:nowrap;cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:background-color .25s,border-color .25s,color .25s,transform .3s var(--ease)}
.room-view svg,.room-label-ico,.room-pick-ico{width:15px;height:15px;flex:none;fill:none;stroke:currentColor;stroke-width:1.4;stroke-linejoin:round;stroke-linecap:round}
.room-view svg{transition:transform .5s var(--ease)}
.room-view:hover{background:var(--olive);border-color:var(--olive);color:var(--cream)}
.room-view:hover svg{transform:rotate(-30deg)}
.room-view:active{transform:scale(.96)}
.room-view:focus-visible{outline-offset:2px;border-radius:999px}
@media (prefers-reduced-motion:no-preference){
  .room-steps li[data-pos="on"] .room-view{animation:view-in .7s var(--ease) .35s both}
}
@keyframes view-in{from{opacity:0;transform:translateX(-6px)}}
/* the wide view's labels, as buttons */
button.room-label{display:inline-flex;align-items:center;gap:7px;margin:0;border:0;font:inherit;font-size:11.5px;letter-spacing:.2em;cursor:pointer;
  transition:background-color .25s,color .25s,box-shadow .25s}
.room-label-ico{width:13px;height:13px;opacity:.55;transition:opacity .25s}
.room-label.live{pointer-events:auto}
.room-label.live:hover{background:var(--olive);color:var(--cream);box-shadow:0 0 0 1px var(--olive)}
.room-label.live:hover .room-label-ico{opacity:1}
/* beside the pointer, over a piece */
.room-pick{position:absolute;z-index:5;left:0;top:0;display:flex;align-items:center;gap:7px;padding:7px 13px 7px 10px;border-radius:999px;
  background:rgba(32,36,28,.88);color:var(--cream);font-size:12.5px;line-height:1;white-space:nowrap;pointer-events:none;opacity:0;
  transition:opacity .18s;will-change:transform}
.room-pick.show{opacity:1}
.room-pick b{font-weight:400}
.room-pick [lang]{color:rgba(243,239,228,.66)}
.room-pick [lang]::before{content:"·";margin-right:7px}
@media (max-width:900px){
  .room-view{height:28px;margin-left:auto;padding:0 11px 0 8px;font-size:12px}
  .room-steps .step-no{min-height:28px}
}
.room-view.is-busy svg{animation:view-busy .9s linear infinite}
@keyframes view-busy{to{transform:rotate(360deg)}}

/* ------------------------------------------------------------ a phone on its side
   Wider than tall and short (Nam 04-10: the hero ran over the picture, the card hid half of it,
   the chat had no room left for its photo): laid out as on a computer, the words on the paper at
   the left and the picture at the right (room.js frames it so), all of it smaller, for a screen
   320 to 430 px tall. The same query as the product viewer's column (viewer.css), room.js,
   main.js and trail.js. Centred in what the bar leaves; Safari's own bar (--bar) taken off; the
   words clear of the notch, on whichever side it is (as the bar is: --head-pad) */
@media (max-width:900px) and (orientation:landscape) and (max-height:500px){
  .room-hero{left:max(var(--gutter),env(safe-area-inset-left));top:calc(50% - var(--bar,0px) / 2);right:auto;width:min(400px,47vw);margin-top:calc(var(--head-h) / 2);transform:translateY(-50%)}
  .room-hero .eyebrow{font-size:10.5px;margin-bottom:12px}
  .room-hero h1{font-size:clamp(28px,9.6vh,40px)}
  .room-hero .lede{margin-top:10px;font-size:14px;line-height:1.45}
  .room-hero .cta-row{margin-top:16px}
  .room-hero .btn-dm{height:44px;font-size:14.5px;padding-left:20px}
  .room-hero .btn-dm-plane{width:32px;height:32px}
  .room-hero::before{inset:-40px -50px -40px calc(-1 * var(--gutter))}
  /* the card of words: no card, the words on the paper beside the picture */
  .room-copy{inset:auto;left:max(var(--gutter),env(safe-area-inset-left));top:calc(50% - var(--bar,0px) / 2);width:min(330px,40vw);margin-top:calc(var(--head-h) / 2);transform:translateY(-50%);
    padding:0;border-radius:0;background:none;box-shadow:none}
  /* (the wash runs on past the screen's left edge, so what the camera leaves there sinks under the paper) */
  .room-copy::before{display:block;inset:-50px -60px -50px calc(-1 * var(--gutter) - 140px)}
  .room-bars{margin:-10px 0 8px}
  .room-steps .step-no{font-size:11px;letter-spacing:.2em}
  .room-steps h3{font-size:clamp(18px,6vh,22px)}
  .room-steps .sub{font-size:13.5px;margin-top:6px}
  .room-view{margin-left:6px}
  .room-steps .swatches{flex-wrap:wrap}
  /* "scroll to step in": under the doorway, clear of the words */
  .room-cue{left:70%;bottom:calc(14px + var(--bar,0px))}
  /* the end: the phone and its words side by side; in the thread the photo and TRACE's answer */
  .room-chat{grid-template-columns:auto minmax(0,340px);justify-items:normal;align-content:normal;gap:clamp(22px,5vw,48px);
    padding:calc(var(--head-h) + 8px) max(var(--gutter),env(safe-area-inset-right)) 24px max(var(--gutter),env(safe-area-inset-left))}
  .chat-phone{width:min(320px,max(42vw,262px));height:calc(100svh - var(--head-h) - 48px);padding:10px;border-radius:28px}
  .chat-head{padding:2px 6px 7px}
  .chat-ava{width:26px;height:26px}
  .chat-ava svg{width:17px}
  .chat-thread{padding:10px 4px 8px}
  .chat-msg[data-msg="1"],.chat-msg[data-msg="2"]{display:none}
  .chat-msg.photo{width:min(96%,calc((100cqh - 64px) * var(--shot-ar,1.6)))}
  @container (max-height:130px){.chat-turn{display:none}.chat-msg.photo{width:min(96%,calc(100cqh * var(--shot-ar,1.6)))}}
  .chat-input{height:38px;white-space:nowrap}
  .chat-input svg{width:26px;height:26px;padding:5px}
  .chat-cta{text-align:left}
  .chat-cta .eyebrow{display:block;margin-bottom:10px;font-size:11px}
  .chat-cta h2{display:block;font-size:clamp(22px,7.4vh,30px)}
  .chat-cta .cta-row{justify-content:flex-start;margin-top:18px}
  .chat-cta .btn-dm{height:48px;font-size:15px;padding:0 7px 0 22px;gap:12px}
  .chat-cta .btn-dm .btn-dm-plane{width:34px;height:34px}
  .chat-cta .cta-handle{display:block;margin-top:12px;font-size:12.5px}
  .chat-fine{bottom:6px}
}

/* ------------------------------------------------------------ the journey rail (js/room/trail.js)
   The page's scrollbar, drawn as the course the story starts from: VMM 100 Miles' height profile on
   its side down the right edge, in pencil; the part already scrolled in route orange; a checkpoint
   where each chapter's picture is done, the last chapter (the DM) the chequered finish; a dot where
   the page is. On a computer it takes the browser's own scrollbar's place (hidden from the first
   paint, by the class the head's script sets, so nothing shifts); on touch it only shows while the
   page moves, and nothing on it is touched */
html.has-trail{scrollbar-width:none}
html.has-trail::-webkit-scrollbar{width:0;height:0;display:none}
.trail{position:fixed;z-index:45;right:0;top:calc(var(--head-h) + 18px);bottom:18px;width:34px;cursor:pointer;touch-action:none;
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;opacity:0;transition:opacity .5s var(--ease)}
.trail.on{opacity:1}
.trail svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none}
.trail-base{fill:none;stroke:var(--graphite);stroke-opacity:.4;stroke-width:1.2;stroke-linejoin:round;stroke-linecap:round;transition:stroke-opacity .25s}
.trail-run{fill:none;stroke:var(--route);stroke-width:2.2;stroke-linejoin:round;stroke-linecap:round;stroke-dasharray:0 100000}
/* the marks: grown under the pointer (the start a ring, each chapter a checkpoint, the finish a flag) */
.trail-start,.trail-cp,.trail-finish{transform-box:fill-box;transform-origin:center;transition:transform .3s var(--ease),stroke .3s,stroke-opacity .3s}
.trail-start{fill:var(--paper);stroke:var(--graphite);stroke-opacity:.55;stroke-width:1.2}
.trail-cp{fill:var(--paper);stroke:var(--graphite);stroke-opacity:.62;stroke-width:1.3}
.trail-cp.past{stroke:var(--route);stroke-opacity:1}
.trail-finish rect{fill:var(--graphite);fill-opacity:.62}
.trail-finish .trail-flag{fill:var(--paper);fill-opacity:1;stroke:var(--graphite);stroke-opacity:.62;stroke-width:.8}
.trail-cp.hot,.trail-start.hot{transform:scale(1.5)}
.trail-finish.hot{transform:scale(1.35)}
/* the page, where it is (a dot on the route: orange, ringed with paper) */
.trail-dot,.trail-ghost{position:absolute;left:0;top:0;border-radius:50%;pointer-events:none;will-change:transform}
.trail-dot{width:11px;height:11px;margin:-5.5px 0 0 -5.5px;background:var(--route);box-shadow:0 0 0 2px var(--paper),0 1px 5px rgba(32,36,28,.35);
  transition:width .2s var(--ease),height .2s var(--ease),margin .2s var(--ease)}
.trail.drag .trail-dot{width:15px;height:15px;margin:-7.5px 0 0 -7.5px}
/* where a click would land */
.trail-ghost{width:9px;height:9px;margin:-4.5px 0 0 -4.5px;box-sizing:border-box;border:1.5px solid var(--graphite);background:var(--paper);opacity:0;transition:opacity .15s}
.trail.hover:not(.drag) .trail-ghost{opacity:1}
.trail.hover .trail-base{stroke-opacity:.62}
/* the chapter: beside the dot while the page moves, beside the pointer over the line */
.trail-pill{position:absolute;right:calc(100% + 4px);top:0;display:flex;align-items:baseline;gap:8px;margin:0;padding:7px 12px 7px 11px;border-radius:999px;
  background:rgba(246,243,235,.97);box-shadow:0 0 0 1px var(--rule),0 8px 20px -12px rgba(32,36,28,.4);
  font-size:12.5px;line-height:1;color:var(--ink);white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .25s;will-change:transform}
.trail-pill b{font-weight:500;font-size:11px;letter-spacing:.12em;color:var(--ink-3);font-variant-numeric:tabular-nums}
.trail-pill b:empty{display:none}
.trail.talk .trail-pill{opacity:1}
html.trail-drag,html.trail-drag *{cursor:grabbing !important}
/* touch: a sign of where the page is, only while it moves, ending above a phone's card of words */
.trail.passive{width:16px;bottom:calc(var(--card,0px) + 14px);pointer-events:none;cursor:default}
.trail.passive.on:not(.moving){opacity:0}
.trail.passive .trail-pill,.trail.passive .trail-ghost{display:none}
.trail.passive .trail-dot{width:8px;height:8px;margin:-4px 0 0 -4px;box-shadow:0 0 0 1.5px var(--paper),0 1px 4px rgba(32,36,28,.3)}
/* (too short to read, a very short screen: the phone's own sign instead; still laid out, so a turn back finds its height) */
.trail.short{visibility:hidden}
/* the pencil draws the line in, the marks come one after another, then the route and the dot */
@media (prefers-reduced-motion:no-preference){
  .trail:not(.ready) .trail-base{stroke-dasharray:var(--len,2000) var(--len,2000);stroke-dashoffset:var(--len,2000);transition:stroke-dashoffset 1.7s var(--ease-io) .1s}
  .trail.on:not(.ready) .trail-base{stroke-dashoffset:0}
  .trail:not(.ready) .trail-cp,.trail:not(.ready) .trail-start,.trail:not(.ready) .trail-finish{transform:scale(0)}
  .trail.on:not(.ready) .trail-start{transform:scale(1);transition:transform .4s var(--ease) .1s}
  .trail.on:not(.ready) .trail-cp{transform:scale(1);transition:transform .5s var(--ease) calc(.45s + var(--i) * .17s)}
  .trail.on:not(.ready) .trail-finish{transform:scale(1);transition:transform .45s var(--ease) 1.6s}
  .trail:not(.ready) .trail-dot,.trail:not(.ready) .trail-run{opacity:0}
  .trail.on:not(.ready) .trail-dot,.trail.on:not(.ready) .trail-run{opacity:1;transition:opacity .5s var(--ease) .5s}
}
/* the viewer covers the page, and the rail with it */
html.pv-open .trail{opacity:0;pointer-events:none}
@media print{.trail{display:none}}
