/* ==========================================================================
   Arsh Villa
   No type, no chrome. The footage carries the whole page, so the only
   interface is a thin depth indicator and a scroll cue — both wordless.
   ========================================================================== */

:root{
  --ink:   #14170F;
  --ivory: #F6F2E9;
  --pool:  #57ABA6;

  --gut: clamp(1.25rem, 4vw, 3.5rem);
  /* 50.5s of footage. Roughly 22vh of scroll per second of walking. */
  --tour-len: 1120vh;
}

*,*::before,*::after{ box-sizing:border-box; }

html{ background:var(--ink); }

body{
  margin:0;
  background:var(--ink);
  overflow-x:hidden;
  /* stops Chrome's pull-to-refresh firing when you flick up at the gate */
  overscroll-behavior-y:none;
}

/* A thumb flick travels much further than a mouse wheel, so the same page
   length burns through the walk far too quickly on a phone. Stretching the
   scroll track means the same flick advances less footage — the walk slows
   down without touching playback or the easing.

   Stated in pixels rather than vh on purpose. The stage is one viewport tall,
   so `12000px + one viewport` leaves exactly 12000px of travel — the same
   thumb distance for the whole walk on a small phone and a tall one alike.
   In vh the travel would swing by thousands of pixels between the two. */
@media (pointer: coarse){
  :root{ --tour-len: calc(12000px + 100lvh); }
}

img,video{ display:block; max-width:100%; }

:focus-visible{
  outline:2px solid var(--pool);
  outline-offset:3px;
}

/* ==========================================================================
   Holding screen
   ========================================================================== */

.boot{
  position:fixed; inset:0;
  z-index:20;
  display:grid;
  place-content:center;
  background:var(--ink);
  transition:opacity .7s ease;
}

.boot.is-done{ opacity:0; pointer-events:none; }

.boot__bar{
  display:block;
  width:clamp(7rem, 18vw, 11rem);
  height:1px;
  background:rgba(246,242,233,.18);
  overflow:hidden;
}

.boot__fill{
  display:block;
  height:100%;
  width:0;
  background:var(--pool);
  transition:width .35s ease;
}

html:not(.js) .boot,
html.reduced .boot{ display:none; }

/* ==========================================================================
   The walk
   ========================================================================== */

.tour{
  position:relative;
  height:var(--tour-len);
}

/* Height must be the LARGE viewport, not the small one.

   On mobile Chrome the URL bar retracts the moment you scroll, and the visible
   area grows. 100svh sizes to the bar-visible height, so once the bar slides
   away the sticky stage is shorter than the screen and leaves a black band at
   the bottom. 100vh maps to the bar-hidden height, so the stage is never
   shorter than what you can see — worst case a sliver sits behind the bar
   before the first scroll, which the footage covers anyway. */
.tour__stage{
  position:sticky;
  top:0;
  height:100vh;
  height:100lvh;
  overflow:hidden;
  background:var(--ink);
}

.tour__video{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
}

/* ==========================================================================
   Greeting
   No scrim behind it — a scrim would dim the footage. Legibility comes from
   a shadow cast by the glyphs themselves, so the video is untouched except
   for a soft halo hugging each letter.
   ========================================================================== */

.hail{
  position:absolute;
  left:50%;
  top:58%;
  transform:translate(-50%, -50%);
  z-index:4;
  width:min(90vw, 46rem);
  text-align:center;
  pointer-events:none;
  transition:opacity .45s ease, transform .45s ease;
}

.hail.is-gone{
  opacity:0;
  transform:translate(-50%, calc(-50% - 18px));
}

.hail__pre{
  margin:0 0 .85rem;
  font-family:'Jost', system-ui, sans-serif;
  font-weight:300;
  font-size:clamp(.7rem, 1.5vw, .85rem);
  letter-spacing:.42em;
  text-indent:.42em;
  text-transform:uppercase;
  color:var(--ivory);
  text-shadow:0 1px 3px rgba(10,12,8,.7), 0 2px 22px rgba(10,12,8,.55);
}

.hail__name{
  margin:0;
  font-family:'Bodoni Moda', Georgia, serif;
  font-weight:400;
  font-size:clamp(2.6rem, 8vw, 6rem);
  line-height:1;
  letter-spacing:-.015em;
  color:var(--ivory);
  text-shadow:0 2px 5px rgba(10,12,8,.6), 0 4px 34px rgba(10,12,8,.5);
}

/* ==========================================================================
   Area name
   Sits where the watermark used to be — lower right. Like the greeting it
   gets no backing plate; the shadow on the glyphs does the work.
   ========================================================================== */

/* left/top are set by script; these are the pre-script fallback */
.marks{
  position:absolute;
  left:auto; right:8%;
  top:auto;  bottom:15%;
  z-index:4;
  pointer-events:none;
}

.marks.is-placed{ right:auto; bottom:auto; }

/* Two modes. Parked in the corner it hangs off its own right edge, so a long
   name grows inwards. Pinned to the watermark it centres on that point. */
.mark{
  position:absolute;
  right:0;
  bottom:0;
  margin:0;
  white-space:nowrap;
  font-family:'Jost', system-ui, sans-serif;
  font-weight:700;
  font-size:clamp(.95rem, 1.9vw, 1.35rem);
  letter-spacing:.26em;
  text-indent:.26em;
  text-transform:uppercase;
  color:#FFFFFF;
  text-shadow:
    0 1px 2px rgba(8,10,6,.9),
    0 2px 10px rgba(8,10,6,.8),
    0 4px 30px rgba(8,10,6,.7);
  /* Every name sits at the identical pinned point, so a plain crossfade would
     show two overlapping while both are mid-fade — briefly unreadable at
     every room boundary. Fading out is quick and starts first; fading in
     waits until the outgoing name has fully cleared, so only one is ever on
     screen at once. */
  opacity:0;
  transition:opacity .16s ease;
}

.marks.is-placed .mark{
  right:auto;
  bottom:auto;
  left:50%;
  top:50%;
  transform:translate(-50%, -50%);
}

.mark.is-lit{
  opacity:1;
  transition:opacity .4s ease .16s;
}

/* ==========================================================================
   Depth indicator — seven rooms on a rail, no labels
   ========================================================================== */

.depth{
  position:absolute;
  right:var(--gut);
  top:50%;
  transform:translateY(-50%);
  z-index:4;
  filter:drop-shadow(0 1px 6px rgba(16,19,13,.55));
}

.depth__rail{
  position:absolute;
  left:50%; top:4px; bottom:4px;
  width:1px;
  margin-left:-.5px;
  background:rgba(246,242,233,.3);
}

.depth__bead{
  position:absolute;
  left:50%;
  width:7px; height:7px;
  margin-left:-3.5px;
  border-radius:50%;
  background:var(--pool);
  box-shadow:0 0 0 3px rgba(87,171,166,.25);
  transform:translateY(-50%);
}

.depth__list{
  list-style:none;
  margin:0; padding:0;
  display:grid;
  gap:1.4rem;
}

.depth__tick{
  display:grid;
  place-items:center;
  width:9px; height:9px;
}

.depth__tick span{
  width:3px; height:3px;
  border-radius:50%;
  background:rgba(246,242,233,.55);
  transition:background .3s ease, transform .3s ease;
}

.depth__tick.is-past span{ background:rgba(246,242,233,.85); }

.depth__tick.is-here span{
  background:var(--ivory);
  transform:scale(1.5);
}

/* ==========================================================================
   Scroll cue — a line that falls, then gets out of the way
   ========================================================================== */

.cue{
  position:absolute;
  left:50%;
  bottom:clamp(2rem, 6vh, 3.25rem);
  z-index:4;
  width:1px; height:2.75rem;
  margin-left:-.5px;
  overflow:hidden;
  background:rgba(246,242,233,.22);
  transition:opacity .6s ease;
}

.cue::after{
  content:'';
  position:absolute;
  left:0; top:0;
  width:100%; height:45%;
  background:var(--ivory);
  animation:fall 2.3s cubic-bezier(.7,0,.3,1) infinite;
}

@keyframes fall{
  0%      { transform:translateY(-110%); }
  55%,100%{ transform:translateY(240%);  }
}

.cue.is-gone{ opacity:0; }

/* ==========================================================================
   Contact — the closing detail, once the garden has settled in
   Bottom centre: clear of the depth rail (right side on desktop, a bar along
   the bottom on narrow screens) and clear of the area name (right-anchored).
   Same rule as everything else here — no backing plate, just a shadow.
   ========================================================================== */

.contact{
  position:absolute;
  left:50%;
  bottom:9%;
  transform:translateX(-50%);
  z-index:4;
  margin:0;
  text-align:center;
  white-space:nowrap;
  font-family:'Jost', system-ui, sans-serif;
  font-weight:400;
  font-size:clamp(.78rem, 1.5vw, .95rem);
  letter-spacing:.06em;
  color:var(--ivory);
  text-shadow:
    0 1px 2px rgba(8,10,6,.9),
    0 2px 10px rgba(8,10,6,.8),
    0 4px 26px rgba(8,10,6,.7);
  opacity:0;
  pointer-events:none;
  transition:opacity .8s ease;
}

.contact.is-on{ opacity:1; }

/* ==========================================================================
   Stills fallback (reduced motion / no JS)
   ========================================================================== */

.stills{ display:none; }

html:not(.js) .tour,
html.reduced .tour{ display:none; }

html:not(.js) .stills,
html.reduced .stills{
  display:grid;
  gap:1px;
  background:var(--ink);
}

.stills img{ width:100%; height:auto; }

/* ==========================================================================
   Narrow screens — the rail lies down along the bottom
   ========================================================================== */

@media (max-width: 700px){
  .depth{
    top:auto;
    right:auto;
    left:var(--gut);
    right:var(--gut);
    /* clear of the home indicator on notched phones */
    bottom:calc(1.75rem + env(safe-area-inset-bottom, 0px));
    transform:none;
  }
  .depth__rail{
    left:0; right:0; top:50%;
    width:auto; height:1px;
    margin-left:0; margin-top:-.5px;
    bottom:auto;
  }
  .depth__bead{
    top:50%;
    margin-left:0;
    transform:translate(-50%,-50%);
  }
  .depth__list{
    grid-auto-flow:column;
    grid-auto-columns:1fr;
    gap:0;
    justify-items:center;
  }
  .cue{ display:none; }
}

/* ==========================================================================
   Upright screens
   The video fills the screen at every viewport — portrait included. Phones get
   their own master, cropped from the full-resolution file rather than from the
   small one, so the narrow slice a tall screen shows is made of real pixels
   instead of a heavily upscaled strip.

   Nothing to override here: the default full-bleed rule already covers it. The
   old letterboxed band is gone.
   ========================================================================== */

@media (max-width: 700px){
  .hail{ width:min(86vw, 30rem); }
  .hail__pre{ font-size:.62rem; letter-spacing:.34em; text-indent:.34em; margin-bottom:.6rem; }
  .hail__name{ font-size:clamp(2.1rem, 11vw, 3.4rem); }

  /* the name now sits on the footage itself, so it needs a denser shadow than
     it did floating on the dark ground */
  .mark{
    font-size:.82rem;
    letter-spacing:.24em;
    text-indent:.24em;
    text-shadow:
      0 1px 2px rgba(8,10,6,.95),
      0 2px 8px rgba(8,10,6,.9),
      0 3px 18px rgba(8,10,6,.8),
      0 6px 38px rgba(8,10,6,.6);
  }
  .marks{ right:6%; bottom:12%; }

  /* clear of the depth bar (bottom:1.75rem) and the area name (bottom:12%) */
  .contact{
    bottom:21%;
    font-size:.72rem;
    letter-spacing:.03em;
    white-space:normal;
    width:88vw;
  }
}

/* ==========================================================================
   Reduced motion
   ========================================================================== */

@media (prefers-reduced-motion: reduce){
  .cue::after{ animation:none; }
}
