/* ==========================================================================
   Tiniri Camp — THE ARRIVAL
   The hero, rebuilt as a piece of film.

   Loaded only on the homepage, after custom.css. Nothing in here is required
   for the page to work: remove the two tags in index.html and the hero falls
   straight back to the single photograph it was before.

   The stage is built by /hero.js. This file is the look; that file is the
   choreography.
   ========================================================================== */

:root {
  --tin-ink:       #07070A;
  --tin-gold:      #D4AF37;
  --tin-gold-lit:  #F3DFA2;
  --tin-cream:     #F2E6C4;
  --tin-ease:      cubic-bezier(.22, 1, .36, 1);
  --tin-fade:      1500ms;
}

/* --------------------------------------------------------------------------
   1. THE STAGE
   One element behind everything in the hero, holding four plates: the camp
   photograph at the bottom, two video layers that hand over to one another
   above it, and the light on top of both.
   -------------------------------------------------------------------------- */

#tin-stage {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  background: var(--tin-ink);
  pointer-events: none;
  /* The film never repaints anything outside the hero. */
  contain: paint;
}

/* Everything the export used to paint behind the hero — the still, the two
   gradient washes — is now the stage's job. Hidden by stylesheet rather than
   by inline style, so a React re-render cannot quietly bring it back. */
[data-tin-hidden] { display: none !important; }

/* The moving plate. Inset past the edges so a parallax nudge can never
   expose a seam. */
#tin-film {
  position: absolute;
  inset: -3%;
  will-change: transform;
  transform: translate3d(0, 0, 0) scale(1.04);
}

/* A grade, not a filter effect: a little more contrast and warmth than the
   camera gave, and none of the sepia that used to turn the sky to mud.

   It sits on the plates rather than on #tin-film, which is the element that
   actually moves. A filter on a moving element is re-rasterised every single
   frame at full viewport size; on a filtered child of a moving parent the
   browser keeps one texture and simply pushes it around. Same picture, an
   order of magnitude less work. */
/* The grade sits on the photograph only. It used to sit on the video layer
   as well, which meant the browser re-filtered every frame of a full-screen
   1920 video sixty times a second — the single biggest cause of the stutter
   on a mid-range phone. The clip is graded in the encode instead, where it
   costs nothing to play. */
#tin-camp { filter: contrast(1.06) saturate(1.07) brightness(.97); }

.tin-plate {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 52%;
  display: block;
}

/* The camp itself — the real photograph, always there underneath. If the
   video is blocked, refused, or switched off for data or motion reasons,
   this is what the visitor sees, and it is the picture the site had before. */
#tin-camp {
  transform: scale(1.02);
  will-change: opacity;
}

/* The chapters live in their own wrapper. The dissolve BETWEEN chapters is
   a transition on each plate; the dissolve into the camp on scroll is a
   value written to the wrapper every frame. Two effects, two elements — on
   one element the second would cancel the first. */
#tin-videos { position: absolute; inset: 0; }

/* The incoming plate fades up over the outgoing one, which is only dropped
   once the new one is solid. Fading both at once would dip to grey through
   the middle of every join. */
.tin-v {
  opacity: 0;
  transition: opacity var(--tin-fade) linear;
}
.tin-v.is-live { opacity: 1; }

/* The whole film arrives out of black once, on load. */
#tin-film { opacity: 0; transition: opacity 1800ms var(--tin-ease); }
#tin-stage.is-lit #tin-film { opacity: 1; }

/* --------------------------------------------------------------------------
   2. THE LIGHT
   Four passes, each doing one job. Together they are the difference between
   a video playing on a page and a photograph you want to stand inside.
   -------------------------------------------------------------------------- */

.tin-light { position: absolute; inset: 0; pointer-events: none; }

/* Warmth gathered along the horizon, where the sun actually is. */
#tin-glow {
  inset: auto auto auto 50%;
  top: 56%;
  width: 150%; height: 78%;
  transform: translate(-50%, -50%);
  mix-blend-mode: screen;
  background: radial-gradient(50% 50% at 50% 50%,
    rgba(233, 158, 66, .20) 0%,
    rgba(226, 130, 48, .07) 42%,
    transparent 72%);
}

/* A slow wash across the frame, as though the sun were catching the lens.
   26 seconds is long enough that nobody sees it move and everybody feels it. */
#tin-leak {
  mix-blend-mode: screen;
  opacity: .5;
  background: radial-gradient(60% 50% at 18% 28%,
    rgba(255, 206, 128, .16), transparent 70%);
  animation: tin-leak 26s ease-in-out infinite alternate;
}
@keyframes tin-leak {
  from { transform: translate3d(-6%, 2%, 0) scale(1);    opacity: .34; }
  to   { transform: translate3d(10%, -4%, 0) scale(1.22); opacity: .62; }
}

/* Top: so the navigation and the logo hold against a bright sky.
   Bottom: so the frame arrives at the page's own black with no visible edge
   where the hero stops and the booking card begins. */
#tin-scrim-top {
  inset: 0 0 auto 0; height: 48%;
  background: linear-gradient(to bottom,
    rgba(6, 6, 9, .80) 0%, rgba(6, 6, 9, .34) 36%, transparent 100%);
}
#tin-scrim-bot {
  inset: auto 0 0 0; height: 66%;
  background: linear-gradient(to top,
    #0A0A0B 0%, rgba(10, 10, 11, .90) 14%,
    rgba(14, 10, 7, .46) 46%, transparent 100%);
}

/* The corners pulled down, so the eye goes where the light is. */
#tin-vig {
  background: radial-gradient(122% 96% at 50% 44%,
    transparent 40%, rgba(4, 4, 6, .30) 74%, rgba(4, 4, 6, .62) 100%);
}

/* Deepened on scroll, so the booking card reads against it. Driven by JS. */
#tin-dim { background: #07070A; opacity: 0; }

/* --------------------------------------------------------------------------
   3. THE COMPOSITION
   The hero was a 100svh frame with its subject in the top third and roughly
   five hundred pixels of empty dune beneath it before the booking card cut
   in. The subject moves to the optical centre; the card stops eating the
   picture.
   -------------------------------------------------------------------------- */

/* The logo, the tagline, and everything under them. */
html.tin-stage-on .tin-hero-content {
  justify-content: center !important;
  padding-top: 0 !important;
  /* Not a round number of viewport heights: this is the room the bottom band
     occupies. Reserving it here is what stops the tagline and the chapter
     rail landing on top of one another on a laptop, where the hero is only
     about seven hundred pixels tall. */
  padding-bottom: clamp(150px, 24vh, 280px) !important;
  will-change: opacity, transform;
}

/* The booking card used to be pulled 512px over the hero. This file reduced
   that to 192px; custom.css §36 now removes it entirely, because the card has
   its own section and the hero keeps its whole photograph. Both rules had the
   same specificity and this file loads second, so the old value was quietly
   winning — the override has to be here, or nowhere. */

/* A soft pool of shade under the mark, so thin gold type never has to sit
   directly on bright sand. It is a light, not a box: nothing has an edge. */
#tin-pool {
  position: absolute;
  left: 50%; top: 44%;
  width: min(1180px, 92vw); height: min(720px, 66vh);
  transform: translate(-50%, -50%);
  z-index: 19;
  pointer-events: none;
  background: radial-gradient(48% 44% at 50% 50%,
    rgba(5, 5, 8, .50) 0%, rgba(5, 5, 8, .26) 46%, transparent 74%);
}

/* --------------------------------------------------------------------------
   4. THE BOTTOM BAND
   Three things on one baseline: which piece of film is playing, the way in,
   and where this place actually is. A frame for the picture.
   -------------------------------------------------------------------------- */

.tin-band {
  position: absolute;
  z-index: 26;
  bottom: clamp(118px, 17vh, 210px);
}

/* A short window — a 13-inch laptop, or a browser with three toolbars — has
   perhaps 620px of hero. Everything draws in. */
@media (max-height: 760px) {
  .tin-band { bottom: clamp(86px, 13vh, 128px); }
  html.tin-stage-on .tin-hero-content { padding-bottom: clamp(120px, 18vh, 170px) !important; }
  html.tin-stage-on .tin-hero-cue { bottom: clamp(80px, 12vh, 120px) !important; }
}

/* -- The chapter rail was removed with the three-clip version ----------- */

/* -- Where this is, and what people said --------------------------------- */
#tin-meta {
  right: clamp(20px, 4.5vw, 72px);
  text-align: right;
  display: flex;
  flex-direction: column;
  gap: 9px;
  pointer-events: auto;
}
#tin-meta .tin-place {
  font-family: var(--font-tenor), inherit;
  font-size: 10px;
  letter-spacing: .42em;
  text-transform: uppercase;
  color: rgba(242, 230, 196, .70);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .7), 0 2px 24px rgba(0, 0, 0, .8);
  margin: 0;
}
#tin-meta .tin-score {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  font-size: 11px;
  letter-spacing: .10em;
  color: rgba(242, 230, 196, .82);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .7);
  text-decoration: none;
  transition: color .4s var(--tin-ease);
}
#tin-meta .tin-score:hover { color: var(--tin-gold-lit); }
#tin-meta .tin-stars { color: var(--tin-gold); letter-spacing: .12em; }
#tin-meta .tin-count { opacity: .62; font-size: 10px; letter-spacing: .16em; }

/* The whole band arrives after the mark has settled, never with it. */
.tin-band {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 1.5s var(--tin-ease) 1.1s, transform 1.5s var(--tin-ease) 1.1s;
}
#tin-stage.is-lit ~ .tin-band,
.tin-band.is-in { opacity: 1; transform: none; }

/* -- The way in ---------------------------------------------------------- */
/* The export's scroll cue sat at the very bottom of the hero, behind the
   booking card, where nobody ever saw it. It joins the band. */
html.tin-stage-on .tin-hero-cue {
  bottom: clamp(124px, 18vh, 220px) !important;
}

/* --------------------------------------------------------------------------
   5. SMALLER SCREENS
   Most desert-camp bookings start on a phone, and a phone is where a
   full-bleed video hero is most likely to be either beautiful or a disaster.
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  /* The label is the first thing to go: the bars still say where you are. */
  #tin-meta .tin-place { font-size: 9px; letter-spacing: .30em; }
}

@media (max-width: 640px) {
  .tin-band { bottom: clamp(108px, 16vh, 160px); }

  /* Side by side at this width the two ends of the band collide. Stacked
     and centred, they read as one caption under the picture. */
  #tin-meta {
    left: 50%; right: auto;
    /* `translate`, not `transform`: the band's own entrance animation owns
       `transform`, and its selector (#tin-stage.is-lit ~ .tin-band) outranks
       this one — which is why the caption was landing against the right edge
       of the phone instead of under the middle of the picture. The two
       properties compose, so the rise still plays and the centring holds. */
    translate: -50% 0;
    align-items: center;
    text-align: center;
    bottom: clamp(92px, 14vh, 140px);
    gap: 7px;
    max-width: calc(100vw - 36px);
  }
  #tin-meta .tin-place { text-wrap: balance; }
  /* "60 Google reviews" was wrapping mid-phrase and throwing the rating row
     off centre. There is room for it on one line once it is allowed to use it. */
  #tin-meta .tin-score {
    justify-content: center;
    flex-wrap: nowrap;
    white-space: nowrap;
    gap: 7px;
  }
  #tin-meta .tin-count { letter-spacing: .10em; }

  html.tin-stage-on .tin-hero-cue { display: none !important; }

  /* The card can come closer on a phone: there is less picture to protect
     and the form is what the visitor came for. */
  html.tin-stage-on section[class*="-mt-64"] { margin-top: -4rem !important; }

  #tin-pool { width: 120vw; height: 58vh; top: 42%; }

  /* A video sized for a 16:9 desktop frame shows only its middle on a tall
     phone. Biasing downward keeps the dune, not the empty sky. */
  .tin-plate { object-position: 50% 58%; }
}

/* --------------------------------------------------------------------------
   6. WHEN THE FILM SHOULD NOT PLAY
   Reduced motion, a metered connection, or a browser that refuses to
   autoplay. In every case the camp photograph stands alone, which is what
   the hero was before — so there is no broken state to fall into.
   -------------------------------------------------------------------------- */

html.tin-no-film .tin-v,
html.tin-no-film #tin-leak { display: none !important; }
html.tin-no-film #tin-film { animation: none !important; }

@media (prefers-reduced-motion: reduce) {
  #tin-leak { animation: none !important; opacity: .38 !important; }
  #tin-film, .tin-v, .tin-band { transition-duration: .01ms !important; }
  .tin-band { opacity: 1 !important; transform: none !important; }
}

/* --------------------------------------------------------------------------
   7. PRINT
   -------------------------------------------------------------------------- */
@media print {
  #tin-stage, .tin-band { display: none !important; }
}

/* --------------------------------------------------------------------------
   8. THE LOADING SCREEN
   Measured on the live site: the page itself is ready in under a second, and
   the black screen over it stays for nearly seven. That is a long time to
   ask someone who found you through a search result to wait, and it is the
   one part of the site no visitor ever sees twice.

   The intro keeps its moment — long enough for the tent to draw itself — and
   then hands over, with the hero already painted underneath. hero.js adds
   the class once the camp photograph has actually decoded, so there is never
   a frame of nothing.
   -------------------------------------------------------------------------- */
/* The selector has to name the loading screen and nothing else.

   It used to be `div.fixed[class*="z-[100]"][class*="inset-0"]`, which is
   also, exactly, the mobile menu panel — so opening the menu on a phone
   mounted a full-screen overlay that this rule then held at opacity 0 with
   pointer-events: none. The menu was there the whole time, invisible and
   swallowing every tap. That is why the menu did not work on a phone.

   The loading screen centres one mark (`items-center justify-center`) and
   contains no links; the menu is a column of them (`flex-col`). Matching on
   those is plain attribute selection, so it holds in every browser — no
   :has(), nothing to fall back from. */
html.tin-ready div.fixed[class*="z-[100]"][class*="inset-0"][class*="items-center"][class*="justify-center"]:not([class*="flex-col"]) {
  opacity: 0 !important;
  pointer-events: none !important;
  transition: opacity 800ms var(--tin-ease) !important;
}
/* The page's own content is held at opacity 0 until React reveals it. If the
   curtain goes early, this has to go with it, or the visitor gets an empty
   screen instead of a shorter wait. */
html.tin-ready body > div[class*="transition-opacity"][class*="duration-1000"] {
  opacity: 1 !important;
}
@media (prefers-reduced-motion: reduce) {
  html.tin-ready div.fixed[class*="z-[100]"][class*="inset-0"][class*="items-center"][class*="justify-center"]:not([class*="flex-col"]) { transition-duration: .01ms !important; }
}

/* --------------------------------------------------------------------------
   9. THE WHITE CIRCLE
   The export's scroll cue is a 96px ring with a one-pixel arrow inside it and
   a label that only appears on hover. Over pale sand the gold ring reads as
   plain white, and what the visitor sees is an unexplained circle floating in
   the middle of the photograph. On a phone there is no hover, so the label
   never arrives to explain it.

   The ring and the arrow are removed. In their place: a hairline with a drop
   of light travelling down it. It says "there is more below" without putting
   a shape on top of the picture.
   -------------------------------------------------------------------------- */
html.tin-stage-on .tin-hero-cue button > div { display: none !important; }
html.tin-stage-on .tin-hero-cue button {
  width: 34px !important;
  height: 64px !important;
  position: relative;
  background: none;
  border: 0;
}
html.tin-stage-on .tin-hero-cue button::before {
  content: "";
  position: absolute;
  left: 50%; top: 0;
  width: 1px; height: 100%;
  transform: translateX(-50%);
  background: linear-gradient(to bottom,
    rgba(212, 175, 55, 0), rgba(212, 175, 55, .45) 55%, rgba(212, 175, 55, 0));
}
html.tin-stage-on .tin-hero-cue button::after {
  content: "";
  position: absolute;
  left: 50%; top: 0;
  width: 1px; height: 16px;
  transform: translateX(-50%);
  background: linear-gradient(to bottom, rgba(243, 223, 162, 0), #F3DFA2);
  box-shadow: 0 0 8px rgba(212, 175, 55, .8);
  animation: tin-drop 2.6s cubic-bezier(.45, 0, .2, 1) infinite;
}
@keyframes tin-drop {
  0%   { transform: translate(-50%, -18px); opacity: 0; }
  22%  { opacity: 1; }
  72%  { opacity: 1; }
  100% { transform: translate(-50%, 58px);  opacity: 0; }
}
html.tin-stage-on .tin-hero-cue button:hover::before { background: linear-gradient(to bottom,
  rgba(212,175,55,0), rgba(212,175,55,.75) 55%, rgba(212,175,55,0)); }

/* The label was invisible until hover, which on a phone means never. */
html.tin-stage-on .tin-hero-cue button span {
  opacity: .72 !important;
  bottom: -24px !important;
  transform: none !important;
  font-size: 10px !important;
  letter-spacing: .42em !important;
  text-indent: .42em;
  color: rgba(212, 175, 55, .8) !important;
  white-space: nowrap;
  transition: opacity .4s var(--tin-ease);
}
html.tin-stage-on .tin-hero-cue button:hover span { opacity: 1 !important; }

@media (prefers-reduced-motion: reduce) {
  html.tin-stage-on .tin-hero-cue button::after { animation: none; top: 24px; }
}
