/* ============================================================================
   animations.css — the motion system.

   Three rules hold throughout:
   1. Only compositor-friendly properties animate (transform/translate/scale/
      rotate/opacity/filter/clip-path). Nothing animates width, height, top
      or left, so no frame triggers layout.
   2. Every effect has a defined FINAL STATE that is reached instantly when
      motion is off. Reduced motion must never leave content invisible.
   3. Durations come from the --d-* scale, which collapses to ~0 when the
      visitor (or their OS) asks for less motion.
   ========================================================================= */

/* ---------------------------------------------------------------- REVEALS
   JS adds .is-in when the element enters the viewport. The start state is
   only applied when JS is present (html.js), so a no-JS visitor sees
   everything immediately. */
.js [data-reveal] {
  opacity: 0;
  transition:
    opacity var(--d-slow) var(--e-out),
    translate var(--d-slow) var(--e-out),
    scale var(--d-slow) var(--e-out),
    rotate var(--d-slow) var(--e-out),
    clip-path var(--d-scene) var(--e-out),
    filter var(--d-slow) var(--e-out);
  transition-delay: var(--delay, 0ms);
  will-change: opacity, translate;
}

.js [data-reveal='up']     { translate: 0 2.6rem; }
.js [data-reveal='down']   { translate: 0 -2rem; }
.js [data-reveal='left']   { translate: 2.6rem 0; }
.js [data-reveal='right']  { translate: -2.6rem 0; }
.js [data-reveal='scale']  { scale: 0.92; }
.js [data-reveal='blur']   { filter: blur(14px); translate: 0 1.4rem; }
.js [data-reveal='tilt']   { translate: 0 2.4rem; rotate: -1.4deg; scale: 0.97; }
.js [data-reveal='wipe']   { clip-path: inset(0 0 100% 0); translate: 0 1rem; }
.js [data-reveal='iris']   { clip-path: inset(18% 18% 18% 18% round 28px); scale: 1.06; }
.js [data-reveal='fade']   { /* opacity only */ }

.js [data-reveal].is-in {
  opacity: 1;
  translate: 0 0;
  scale: 1;
  rotate: 0deg;
  filter: none;
  clip-path: inset(0 0 0 0 round 0);
  will-change: auto;
}
.js [data-reveal='iris'].is-in { clip-path: inset(0 0 0 0 round 22px); }

/* Stagger: --i is the child index, set in markup or by JS. */
.js [data-stagger] > * {
  --delay: calc(var(--i, 0) * var(--step, 85ms));
}

/* ------------------------------------------------------------ SPLIT TEXT
   A heading is split into word spans by JS. The parent keeps the full
   readable string for assistive tech (aria-label), and the spans are
   aria-hidden, so a screen reader hears one sentence, not a word salad. */
.split { display: inline; }
.split .word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  /* padding keeps descenders (g, y, p) from being clipped by overflow */
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.split .word > span {
  display: inline-block;
  translate: 0 110%;
  rotate: 2deg;
  transition: translate var(--d-scene) var(--e-out),
              rotate var(--d-scene) var(--e-out);
  transition-delay: calc(var(--wi, 0) * 55ms + var(--delay, 0ms));
}
.split.is-in .word > span { translate: 0 0; rotate: 0deg; }

/* --------------------------------------------------------------- COUNTERS */
.count { font-variant-numeric: tabular-nums lining-nums; }

/* -------------------------------------------------------------- PRELOADER */
.preloader {
  position: fixed;
  inset: 0;
  z-index: var(--z-preloader);
  display: grid;
  place-items: center;
  background: var(--surface-0);
  transition: opacity var(--d-slow) var(--e-soft),
              visibility 0s linear var(--d-slow);
}
.preloader[data-done='true'] {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.preloader-inner { display: grid; justify-items: center; gap: var(--sp-m); }
.preloader svg { inline-size: clamp(180px, 34vw, 280px); block-size: auto; }

/* The emblem's strokes draw themselves on */
.preloader .draw {
  stroke-dasharray: var(--len, 400);
  stroke-dashoffset: var(--len, 400);
  animation: draw-on 1.5s var(--e-out) forwards;
  animation-delay: calc(var(--d, 0) * 1ms);
}
@keyframes draw-on { to { stroke-dashoffset: 0; } }

.preloader-bar {
  inline-size: clamp(140px, 30vw, 230px);
  block-size: 2px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}
.preloader-bar i {
  display: block;
  block-size: 100%;
  inline-size: 100%;
  background: var(--spectrum);
  transform-origin: left;
  scale: var(--p, 0) 1;
  transition: scale 260ms var(--e-soft);
}
.preloader-word {
  font-size: var(--t-xs);
  letter-spacing: var(--track-widest);
  text-transform: uppercase;
  color: var(--text-3);
}

/* ----------------------------------------------------------- CUSTOM CURSOR
   Pointer-enhancement only: it appears solely for fine pointers, it never
   replaces the real cursor on controls, and it is aria-hidden. */
.cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--z-cursor);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--d-base) var(--e-soft);
  mix-blend-mode: difference;
}
.cursor-dot,
.cursor-ring {
  position: absolute;
  border-radius: 50%;
  translate: -50% -50%;
}
.cursor-dot {
  inline-size: 7px;
  block-size: 7px;
  background: #fff;
}
.cursor-ring {
  inline-size: 40px;
  block-size: 40px;
  border: 1px solid rgb(255 255 255 / 60%);
  transition: inline-size var(--d-base) var(--e-spring),
              block-size var(--d-base) var(--e-spring),
              border-color var(--d-base) var(--e-soft),
              background-color var(--d-base) var(--e-soft);
}
body[data-cursor='on'] .cursor { opacity: 1; }
body[data-cursor='on'][data-cursor-state='link'] .cursor-ring {
  inline-size: 68px;
  block-size: 68px;
  background: rgb(255 255 255 / 14%);
}
body[data-cursor='on'][data-cursor-state='drag'] .cursor-ring {
  inline-size: 84px;
  block-size: 84px;
}
.cursor-label {
  position: absolute;
  translate: -50% -50%;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #fff;
  opacity: 0;
  transition: opacity var(--d-fast) var(--e-soft);
  white-space: nowrap;
}
body[data-cursor-state='drag'] .cursor-label { opacity: 1; }

@media (hover: none), (pointer: coarse) {
  .cursor { display: none; }
}

/* ------------------------------------------------------------ SCROLL RAIL
   A progress indicator plus chapter markers, as the storytelling pattern
   requires. It is decorative duplication of the nav, so it is aria-hidden
   and not focusable. */
.scroll-rail {
  position: fixed;
  inset: 50% 1.4rem auto auto;
  translate: 0 -50%;
  z-index: var(--z-sticky);
  display: none;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.9rem;
}
@media (width >= 80rem) { .scroll-rail { display: flex; } }

.rail-item {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--text-3);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.rail-item i {
  display: block;
  inline-size: 26px;
  block-size: 2px;
  border-radius: 2px;
  background: currentColor;
  opacity: 0.45;
  transition: inline-size var(--d-base) var(--e-out),
              opacity var(--d-base) var(--e-soft);
}
.rail-item span {
  opacity: 0;
  translate: 6px 0;
  transition: opacity var(--d-base) var(--e-soft), translate var(--d-base) var(--e-out);
}
.rail-item[data-active='true'] { color: var(--accent); }
.rail-item[data-active='true'] i { inline-size: 46px; opacity: 1; }
.rail-item[data-active='true'] span { opacity: 1; translate: 0 0; }

.progress-top {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: calc(var(--z-header) + 1);
  block-size: 2px;
  background: var(--spectrum);
  transform-origin: left;
  scale: var(--p, 0) 1;
}

/* ------------------------------------------------------------- PARALLAX
   --py is written by JS from the scroll position. Translation only. */
[data-parallax] { will-change: translate; }
[data-parallax] > * { translate: 0 var(--py, 0px); }

/* Ken Burns drift on a hero still */
.kenburns {
  animation: kenburns 26s var(--e-soft) infinite alternate;
  transform-origin: var(--kb-origin, 50% 50%);
}
@keyframes kenburns {
  from { scale: 1.02; translate: 0 0; }
  to   { scale: 1.14; translate: -1.2% -1.4%; }
}

/* ---------------------------------------------------------------- MARQUEE */
.marquee {
  display: flex;
  overflow: hidden;
  user-select: none;
  gap: var(--mq-gap, 3rem);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee ul {
  display: flex;
  flex: none;
  gap: var(--mq-gap, 3rem);
  min-width: 100%;
  align-items: center;
  animation: marquee var(--mq-dur, 42s) linear infinite;
}
.marquee:hover ul,
.marquee:focus-within ul { animation-play-state: paused; }
@keyframes marquee {
  to { translate: calc(-100% - var(--mq-gap, 3rem)) 0; }
}

/* ------------------------------------------------------------------- TILT
   --rx/--ry written by JS on pointer move. */
.tilt {
  transform-style: preserve-3d;
  transition: rotate var(--d-base) var(--e-out), scale var(--d-base) var(--e-out);
}
.tilt-inner {
  transform: perspective(1100px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform var(--d-base) var(--e-out);
}

/* ---------------------------------------------------------------- AURORA
   Slow drifting colour fields behind dark sections. Purely decorative. */
.aurora {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  opacity: var(--aurora-op, 0.5);
}
.aurora i {
  position: absolute;
  display: block;
  inline-size: 46vw;
  block-size: 46vw;
  min-inline-size: 320px;
  min-block-size: 320px;
  border-radius: 50%;
  filter: blur(90px);
  opacity: 0.4;
  mix-blend-mode: screen;
}
:root[data-theme='light'] .aurora i { mix-blend-mode: multiply; opacity: 0.22; }
.aurora i:nth-child(1) {
  background: var(--accent);
  inset: -12% auto auto -8%;
  animation: drift-a 24s var(--e-soft) infinite alternate;
}
.aurora i:nth-child(2) {
  background: var(--sp-6);
  inset: auto -10% -18% auto;
  animation: drift-b 30s var(--e-soft) infinite alternate;
}
.aurora i:nth-child(3) {
  background: var(--gold);
  inset: 30% 20% auto auto;
  animation: drift-c 36s var(--e-soft) infinite alternate;
  opacity: 0.22;
}
@keyframes drift-a { to { translate: 16% 12%; scale: 1.2; } }
@keyframes drift-b { to { translate: -14% -10%; scale: 1.15; } }
@keyframes drift-c { to { translate: -20% 16%; scale: 0.88; } }

/* --------------------------------------------------------- MAGNETIC BUTTON
   --mxp/--myp written by JS; tiny pull, never more than a few pixels. */
.magnet { transition: translate var(--d-base) var(--e-spring); }
.magnet[data-pull] { translate: var(--mxp, 0) var(--myp, 0); }

/* ------------------------------------------------------------ SHIMMER/GLOW */
.glow-line {
  position: relative;
  overflow: hidden;
}
.glow-line::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, var(--accent-glow), transparent);
  translate: -100% 0;
  animation: sweep 5.5s var(--e-soft) infinite;
}
@keyframes sweep {
  0%, 55% { translate: -100% 0; }
  100% { translate: 100% 0; }
}

/* --------------------------------------------------------- SCROLL HINT */
.scroll-hint {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  font-size: 10px;
  letter-spacing: var(--track-widest);
  text-transform: uppercase;
  color: var(--text-2);
}
.scroll-hint i {
  inline-size: 1px;
  block-size: 54px;
  background: linear-gradient(var(--accent), transparent);
  position: relative;
  overflow: hidden;
}
.scroll-hint i::after {
  content: '';
  position: absolute;
  inset: 0 auto auto 0;
  inline-size: 100%;
  block-size: 40%;
  background: var(--accent);
  animation: hint-run 2.4s var(--e-soft) infinite;
}
@keyframes hint-run {
  0% { translate: 0 -100%; }
  100% { translate: 0 250%; }
}

/* --------------------------------------------------------- IMAGE LOADING
   LQIP: the tiny blurred placeholder sits behind the real image and fades
   out once it decodes. Prevents both a flash of empty box and layout shift. */
.img-wrap {
  position: relative;
  overflow: hidden;
  background-size: cover;
  background-position: center;
}
.img-wrap img {
  opacity: 0;
  transition: opacity var(--d-slow) var(--e-soft);
}
.img-wrap img.is-loaded { opacity: 1; }
.img-wrap::before {
  content: '';
  position: absolute;
  inset: 0;
  backdrop-filter: blur(18px);
  transition: opacity var(--d-slow) var(--e-soft);
}
.img-wrap.is-ready::before { opacity: 0; }

/* ============================================================================
   REDUCED MOTION — the final-state contract.

   Everything above resolves to its finished, readable state. Content is
   never left hidden, mid-transition or dependent on an animation that will
   not run. Looping ambient animations stop entirely.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .js [data-reveal],
  .js [data-reveal].is-in {
    opacity: 1 !important;
    translate: none !important;
    scale: none !important;
    rotate: none !important;
    filter: none !important;
    clip-path: none !important;
  }
  .split .word > span { translate: none !important; rotate: none !important; }
  .kenburns { animation: none !important; scale: 1 !important; translate: none !important; }
  .aurora i { animation: none !important; }
  .marquee ul { animation: none !important; }
  .access-fab::after { animation: none !important; opacity: 0 !important; }
  .glow-line::after { animation: none !important; opacity: 0 !important; }
  .scroll-hint i::after { animation: none !important; }
  .preloader .draw { animation: none !important; stroke-dashoffset: 0 !important; }
  [data-parallax] > * { translate: none !important; }
  .cursor { display: none !important; }
  .tilt-inner { transform: none !important; }
}

/* The in-page toggle mirrors the OS setting exactly. */
:root[data-motion='off'] *,
:root[data-motion='off'] *::before,
:root[data-motion='off'] *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
  scroll-behavior: auto !important;
}
:root[data-motion='off'] .js [data-reveal],
:root[data-motion='off'] .js [data-reveal].is-in {
  opacity: 1 !important;
  translate: none !important;
  scale: none !important;
  rotate: none !important;
  filter: none !important;
  clip-path: none !important;
}
:root[data-motion='off'] .split .word > span { translate: none !important; rotate: none !important; }
:root[data-motion='off'] .kenburns { animation: none !important; scale: 1 !important; }
:root[data-motion='off'] .aurora i,
:root[data-motion='off'] .marquee ul,
:root[data-motion='off'] .access-fab::after,
:root[data-motion='off'] .glow-line::after,
:root[data-motion='off'] .scroll-hint i::after { animation: none !important; }
:root[data-motion='off'] [data-parallax] > * { translate: none !important; }
:root[data-motion='off'] .cursor { display: none !important; }
:root[data-motion='off'] .tilt-inner { transform: none !important; }

/* ============================================================================
   ACCESS TOOLBAR PREFERENCES
   Each is a documented, reversible change to presentation only.
   ========================================================================= */

/* -- larger text: scales the whole type ramp, zoom-safe */
:root[data-textsize='l']  { font-size: 112.5%; }
:root[data-textsize='xl'] { font-size: 125%; }

/* -- generous line spacing (helps dyslexic and low-vision readers) */
:root[data-spacing='on'] body {
  line-height: 1.9;
  letter-spacing: 0.035em;
  word-spacing: 0.14em;
}
:root[data-spacing='on'] p { margin-block-end: 1.2em; }

/* -- high contrast: pushes text to the extremes and removes soft fills.
   The site is light-only, so this is a light high-contrast scheme: pure
   black on pure white, hard borders, no translucency and no decoration. */
:root[data-contrast='on'] {
  --text-1: #000000;
  --text-2: #15191d;
  --text-3: #262c32;
  --surface-0: #ffffff;
  --surface-1: #ffffff;
  --surface-2: #f0f0f0;
  --surface-3: #e4e4e4;
  --surface-bar: #ffffff;
  --line: #4a4a4a;
  --line-strong: #2b2b2b;
  --accent: #14480a;
  --accent-quiet: #0b2e05;
  --gold: #4a3608;
  --rule: #4a3608;
  --star: #5a4208;
  --focus: #000000;
  --navy-900: #000000;
  --navy-700: #101820;
  --on-dark-2: #f2f2f2;
  --shadow-1: 0 0 0 1px #2b2b2b;
  --shadow-2: 0 0 0 1px #2b2b2b;
  --shadow-3: 0 0 0 2px #2b2b2b;
  --shadow-card: 0 0 0 2px #2b2b2b;
}
:root[data-contrast='on'] .aurora,
:root[data-contrast='on'] .grain { display: none; }
:root[data-contrast='on'] .glass,
:root[data-contrast='on'] .booking {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: var(--surface-1);
  border: 2px solid var(--line-strong);
}
/* Text over photography needs a solid plate rather than a shadow. */
:root[data-contrast='on'] .hero-a .hero-scrim { background: rgb(0 0 0 / 82%) !important; }
:root[data-contrast='on'] .panel::after,
:root[data-contrast='on'] .tour-media::after { background: rgb(0 0 0 / 70%) !important; }
:root[data-contrast='on'] :is(.hero-a h1, .hero-a .hero-lede, .award b, .award span span,
  .panel h3, .panel p, .tour-over h3, .tour-over p, .cta-inner .sec-title, .cta-inner .lede) {
  text-shadow: none !important;
  color: #ffffff !important;
}

/* -- underline every link, for readers who need links to be unmistakable */
:root[data-links='on'] a:not(.btn):not(.brand):not(.chrome-btn) {
  text-decoration: underline !important;
  text-decoration-thickness: 2px !important;
  text-underline-offset: 0.2em;
}

/* -- hide decorative imagery entirely (bandwidth, distraction, motion) */
:root[data-images='off'] .media-img,
:root[data-images='off'] .aurora,
:root[data-images='off'] .grain { display: none !important; }
:root[data-images='off'] .img-wrap,
:root[data-images='off'] .card-media,
:root[data-images='off'] .hero-media {
  background: var(--surface-2) !important;
  background-image: repeating-linear-gradient(
    45deg, transparent, transparent 11px,
    color-mix(in srgb, var(--text-3) 22%, transparent) 11px,
    color-mix(in srgb, var(--text-3) 22%, transparent) 12px
  ) !important;
}

/* -- reading guide: a dimming mask with a clear band at the pointer */
.reading-guide {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  pointer-events: none;
  display: none;
  background: rgb(0 0 0 / 62%);
  -webkit-mask-image: linear-gradient(
    to bottom,
    #000 0,
    #000 calc(var(--guide-y, 50vh) - 5.5rem),
    transparent calc(var(--guide-y, 50vh) - 5.5rem),
    transparent calc(var(--guide-y, 50vh) + 5.5rem),
    #000 calc(var(--guide-y, 50vh) + 5.5rem),
    #000 100%
  );
  mask-image: linear-gradient(
    to bottom,
    #000 0,
    #000 calc(var(--guide-y, 50vh) - 5.5rem),
    transparent calc(var(--guide-y, 50vh) - 5.5rem),
    transparent calc(var(--guide-y, 50vh) + 5.5rem),
    #000 calc(var(--guide-y, 50vh) + 5.5rem),
    #000 100%
  );
}
:root[data-guide='on'] .reading-guide { display: block; }
