:root {
  color-scheme: dark;
  --warm: #f4c97a;
  --ink: #f6efe1;
  --paper: #1a140d;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: #0a0805;
  color: var(--ink);
  font-family: Georgia, "Times New Roman", serif;
  overflow-x: hidden;
  /* Block iOS/Android pull-to-refresh and rubber-band overscroll. Without
     this, a downward swipe at the top of the page reloads the site on
     mobile Safari/Chrome. */
  overscroll-behavior-y: none;
  overscroll-behavior-x: none;
  /* Allow vertical pan (drives the walk) but suppress double-tap zoom and
     other gesture-based delays on touch devices. */
  touch-action: pan-y;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  /* Hide the scrollbar for a clean look — the page still scrolls (drives the
     walk); only the bar's visuals are removed. */
  scrollbar-width: none;
  /* Firefox */
  -ms-overflow-style: none;
  /* legacy Edge/IE */
}

html::-webkit-scrollbar,
body::-webkit-scrollbar {
  width: 0;
  height: 0;
  display: none;
  /* Chrome, Edge, Safari */
}

/* Canvas pinned full-viewport, behind everything. 100dvh tracks the
   *current* viewport on mobile, so the canvas doesn't jump when the
   iOS URL bar collapses/expands. */
#scene {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  display: block;
  z-index: 0;
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
}

/* ─── Scene wrapper ─── */
#scene-wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  isolation: isolate;
  /* confines blend modes to this stacking context */
}

/* ─── Grain overlay ─── */
#scene-wrapper::after {
  content: "";
  position: fixed;
  /* fixed so it covers the full viewport regardless of scroll */
  inset: -50%;
  /* oversized so translated edges never bleed into view */
  width: 200%;
  height: 200%;
  pointer-events: none;
  z-index: 9998;
  /* below preloader (which sits at 9999+), above canvas */

  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='grain'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23grain)'/%3E%3C/svg%3E");

  opacity: 0.09;
  /* tweak between 0.05–0.15 to taste */
  mix-blend-mode: overlay;
  /* try: soft-light, screen, or normal */

  animation: grain-shift 0.35s steps(1) infinite;
  will-change: transform;
}

/* ─── Grain animation — random jumps give it the film-flicker feel ─── */
@keyframes grain-shift {
  0% {
    transform: translate(0%, 0%);
  }

  10% {
    transform: translate(-5%, -10%);
  }

  20% {
    transform: translate(-15%, 5%);
  }

  30% {
    transform: translate(7%, -25%);
  }

  40% {
    transform: translate(-5%, 25%);
  }

  50% {
    transform: translate(-15%, 10%);
  }

  60% {
    transform: translate(15%, 0%);
  }

  70% {
    transform: translate(0%, 15%);
  }

  80% {
    transform: translate(3%, 35%);
  }

  90% {
    transform: translate(-10%, 10%);
  }

  100% {
    transform: translate(0%, 0%);
  }
}

/* Invisible tall element that gives us scroll distance.
   The real animation is driven by scrollY; the page itself just needs to be tall. */
#scroll-track {
  position: relative;
  width: 100%;
  /* 520vh — long scroll room so each notch moves the camera only a little:
     a slower, more deliberate walk. Raise for slower, lower for faster. */
  height: 520vh;
  pointer-events: none;
  z-index: 1;
}

/* Cursor hint, fades out after first scroll */
#hint {
  position: fixed;
  bottom: 6vh;
  left: 50%;
  transform: translateX(-50%);
  font-size: 13px;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: rgba(246, 239, 225, 0.6);
  z-index: 5;
  pointer-events: none;
  transition: opacity 1.2s ease;
  text-align: center;
}

#hint.gone {
  opacity: 0;
}

/* Keep the scroll hint hidden while the preloader is up. The opacity
   transition above gives it a soft fade-in once the grove is unveiled. */
html.env-loading #hint {
  opacity: 0;
}

/* Desktop vs touch variants. Default = desktop wording; touch devices
   swap in the swipe-up icon via the @media block below. */
.hint-mobile {
  display: none;
}

.hint-mobile-text {
  display: block;
  margin-top: 8px;
  font-size: 11px;
  letter-spacing: 0.28em;
}

.swipe-icon {
  display: block;
  width: 32px;
  height: 56px;
  margin: 0 auto;
  color: rgba(246, 239, 225, 0.75);
  filter: drop-shadow(0 0 6px rgba(244, 201, 122, 0.35));
}

.swipe-icon .swipe-finger {
  transform-origin: center;
  animation: swipe-up 1.8s cubic-bezier(0.45, 0, 0.2, 1) infinite;
}

@keyframes swipe-up {
  0% {
    transform: translateY(0);
    opacity: 0;
  }

  18% {
    opacity: 1;
  }

  85% {
    opacity: 0.05;
  }

  100% {
    transform: translateY(-36px);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .swipe-icon .swipe-finger {
    animation: none;
    opacity: 1;
  }
}

/* Touch devices (phones, tablets, touchscreens) — show the gesture
   icon instead of the desktop wording. pointer: coarse catches touch
   input regardless of viewport width (so iPads work too). */
@media (pointer: coarse) {
  .hint-desktop {
    display: none;
  }

  .hint-mobile {
    display: inline-block;
  }
}

/* Modal */
#modal {
  position: fixed;
  inset: 0;
  height: 100vh;
  height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 6, 4, 0.78);
  backdrop-filter: blur(6px);
  z-index: 10;
  opacity: 1;
  transition: opacity 0.5s ease;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

#modal.hidden {
  opacity: 0;
  pointer-events: none;
}

#modal-card {
  position: relative;
  width: min(440px, 88vw);
  background: var(--paper);
  border: 1px solid rgba(244, 201, 122, 0.25);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6),
    0 0 60px rgba(244, 201, 122, 0.08);
  padding: 36px 32px 28px;
  border-radius: 4px;
}

#modal-card h2 {
  margin: 0 0 6px;
  font-weight: 400;
  font-size: 26px;
  color: var(--warm);
  letter-spacing: 0.02em;
}

.modal-sub {
  margin: 0 0 18px;
  font-style: italic;
  color: rgba(246, 239, 225, 0.6);
  font-size: 14px;
}

/* Stone gallery — two photographs of the talisman shown together
   inside the journal modal. Slightly tilted like keepsake polaroids. */
.stone-gallery {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 14px;
  margin: 4px 0 10px;
  perspective: 600px;
}

.stone-photo {
  margin: 0;
  width: 46%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: 3px;
  border: 1px solid rgba(244, 201, 122, 0.28);
  background: rgba(0, 0, 0, 0.4);
  box-shadow:
    0 10px 26px rgba(0, 0, 0, 0.55),
    0 0 22px rgba(244, 201, 122, 0.08),
    inset 0 0 30px rgba(0, 0, 0, 0.35);
  transition: transform 0.45s ease, box-shadow 0.45s ease, border-color 0.45s ease;
}

.stone-photo:first-child {
  transform: rotate(-2.4deg) translateY(2px);
}

.stone-photo:last-child {
  transform: rotate(2deg) translateY(-2px);
}

.stone-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.85) contrast(1.05) brightness(0.95) sepia(0.08);
  transition: filter 0.45s ease, transform 0.6s ease;
}

.stone-gallery:hover .stone-photo {
  transform: rotate(0) translateY(0);
  border-color: rgba(244, 201, 122, 0.55);
  box-shadow:
    0 14px 34px rgba(0, 0, 0, 0.6),
    0 0 36px rgba(244, 201, 122, 0.18),
    inset 0 0 30px rgba(0, 0, 0, 0.35);
}

.stone-gallery:hover .stone-photo img {
  filter: saturate(1) contrast(1.06) brightness(1) sepia(0);
  transform: scale(1.04);
}

.stone-caption {
  margin: 0 0 20px;
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(246, 239, 225, 0.45);
}

#modal-close {
  position: absolute;
  top: 10px;
  right: 14px;
  background: none;
  border: 0;
  color: rgba(246, 239, 225, 0.6);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
}

#modal-close:hover {
  color: var(--warm);
}

#journal-form label {
  display: block;
  margin-bottom: 16px;
}

#journal-form span {
  display: block;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* color: rgba(246, 239, 225, 0.55); */
  margin-bottom: 6px;
}

#journal-form input,
#journal-form textarea,
#journal-form select {
  width: 100%;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(244, 201, 122, 0.2);
  color: var(--ink);
  font-family: inherit;
  font-size: 15px;
  padding: 10px 12px;
  border-radius: 2px;
  resize: vertical;
}

#journal-form input:focus,
#journal-form textarea:focus,
#journal-form select:focus {
  outline: none;
  border-color: var(--warm);
  background: rgba(244, 201, 122, 0.06);
}

/* Dropdown — custom chevron + native arrow off, so it matches the rest. */
#journal-form select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: 36px;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23f4c97a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>"),
    linear-gradient(rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.03));
  background-repeat: no-repeat;
  background-position: right 12px center, 0 0;
  background-size: 12px 8px, auto;
  cursor: pointer;
}

#journal-form select option {
  background: var(--paper);
  color: var(--warm);
}

/* Subtle "(optional)" tag next to the label */
#journal-form span .opt {
  font-style: normal;
  text-transform: none;
  letter-spacing: 0.04em;
  color: rgba(246, 239, 225, 0.35);
  font-size: 11px;
  margin-left: 6px;
}

/* Helper line under each label */
#journal-form .field-hint {
  margin: 0 0 8px;
  font-style: italic;
  font-size: 12px;
  color: rgba(246, 239, 225, 0.45);
}

/* Custom select — replaces the native dropdown so we can show
   icon + title + description per option, matching the design. Wrapped
   in a <div> (not <label>) because labels forward synthetic clicks to
   their first labelable control, which reopens the menu after select. */
.custom-select-field {
  display: block;
  margin-bottom: 16px;
}

.custom-select {
  position: relative;
}

.custom-select-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(244, 201, 122, 0.2);
  color: var(--ink);
  font-family: inherit;
  font-size: 15px;
  border-radius: 2px;
  cursor: pointer;
  text-align: left;
}

.custom-select-trigger:hover,
.custom-select-trigger[aria-expanded="true"] {
  border-color: var(--warm);
  background: rgba(244, 201, 122, 0.06);
}

.custom-select-label {
  color: rgba(246, 239, 225, 0.55);
}

.custom-select-label.has-value {
  color: var(--ink);
}

.custom-select-chevron {
  width: 12px;
  height: 8px;
  color: var(--warm);
  transition: transform 0.2s ease;
  flex-shrink: 0;
}

.custom-select-trigger[aria-expanded="true"] .custom-select-chevron {
  transform: rotate(180deg);
}

/* Override the bare list styles from earlier so the menu sits below the
   trigger as an absolutely-positioned panel. */
.custom-select .dropdown-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 5;
  max-height: 320px;
  overflow-y: auto;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}

.custom-select .dropdown-menu.hidden {
  display: none;
}

/* Submit button — sits inline with a small stone icon */
#submit-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

.submit-icon {
  width: 14px;
  height: 14px;
  color: var(--warm);
  flex-shrink: 0;
  /* Optical-align with the cap height of the uppercase button text. */
  position: relative;
  top: -1px;
}

/* Footer text under the submit button */
.form-footer {
  margin: 14px 0 0;
  text-align: center;
  font-style: italic;
  font-size: 12px;
  line-height: 1.5;
  color: rgba(246, 239, 225, 0.4);
}

#submit-btn {
  width: 100%;
  margin-top: 6px;
  padding: 12px;
  background: transparent;
  border: 1px solid var(--warm);
  color: var(--warm);
  font-family: inherit;
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.2s ease;
}

#submit-btn:hover {
  background: rgba(244, 201, 122, 0.12);
}

#form-thanks {
  text-align: center;
  margin: 18px 0 0;
}

.thanks-line {
  font-style: italic;
  color: var(--warm);
  margin: 0 0 14px;
}

/* Cue that fades in when the user reaches the clearing */
#talisman-cue {
  position: fixed;
  bottom: 8vh;
  left: 50%;
  transform: translateX(-50%);
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--warm);
  text-shadow: 0 0 18px rgba(244, 201, 122, 0.6);
  z-index: 4;
  pointer-events: none;
  opacity: 1;
  transition: opacity 1.4s ease;
}

#talisman-cue.hidden {
  display: block;
  opacity: 0;
}

/* Tooltip pinned to the talisman — JS writes --tx/--ty each frame so it
   tracks the gem's screen position. Pill label sits above-left, with a
   curved arrow swooping down to the gem. */
#talisman-tooltip {
  position: fixed;
  left: 0;
  top: 0;
  --tx: -9999px;
  --ty: -9999px;
  transform: translate3d(var(--tx), var(--ty), 0) translate(-100%, -100%);
  z-index: 5;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.8s ease;
  color: var(--warm);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}

#talisman-tooltip.hidden {
  opacity: 0;
}

#talisman-tooltip .tooltip-label {
  display: inline-block;
  padding: 8px 14px;
  border: 1px solid rgba(244, 201, 122, 0.45);
  border-radius: 999px;
  background: rgba(8, 6, 4, 0.55);
  backdrop-filter: blur(4px);
  font-size: 11px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--warm);
  text-shadow: 0 0 12px rgba(244, 201, 122, 0.5);
  box-shadow:
    0 6px 18px rgba(0, 0, 0, 0.45),
    0 0 22px rgba(244, 201, 122, 0.18);
  animation: tooltip-breathe 2.6s ease-in-out infinite;
}

#talisman-tooltip .tooltip-arrow {
  width: 44px;
  height: 44px;
  margin-right: 6px;
  filter: drop-shadow(0 0 6px rgba(244, 201, 122, 0.55));
  animation: tooltip-nudge 2.6s ease-in-out infinite;
}

@keyframes tooltip-breathe {

  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(-3px);
  }
}

@keyframes tooltip-nudge {

  0%,
  100% {
    transform: translate(0, 0);
  }

  50% {
    transform: translate(3px, 3px);
  }
}

@media (prefers-reduced-motion: reduce) {

  #talisman-tooltip .tooltip-label,
  #talisman-tooltip .tooltip-arrow {
    animation: none;
  }
}

/* Audio toggle button — offset by the iOS safe-area inset so it never
   tucks under the notch / status bar. */
#audio-toggle {
  position: fixed;
  top: calc(18px + env(safe-area-inset-top));
  right: calc(18px + env(safe-area-inset-right));
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(244, 201, 122, 0.25);
  background: rgba(8, 6, 4, 0.5);
  color: rgba(246, 239, 225, 0.5);
  font-size: 16px;
  cursor: pointer;
  /* Sits above the preloader (z:50) so it's reachable while the curtain
     is still up. */
  z-index: 60;
  transition: color 0.2s ease, border-color 0.2s ease;
  -webkit-tap-highlight-color: transparent;
}

#audio-toggle:hover,
#audio-toggle.on {
  color: var(--warm);
  border-color: var(--warm);
}

/* Studio link — small pill button in the bottom-right, opens an external page */
#studio-link {
  position: fixed;
  bottom: calc(18px + env(safe-area-inset-bottom));
  right: calc(18px + env(safe-area-inset-right));
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid rgba(244, 201, 122, 0.28);
  background: rgba(8, 6, 4, 0.5);
  color: rgba(246, 239, 225, 0.65);
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  /* Sits above the preloader (z:50) so it's visible/clickable while the
     curtain is still up. */
  z-index: 60;
  backdrop-filter: blur(6px);
  transition: color 0.25s ease, border-color 0.25s ease, background 0.25s ease, box-shadow 0.25s ease;
  -webkit-tap-highlight-color: transparent;
}

#studio-link:hover,
#studio-link:focus-visible {
  color: var(--warm);
  border-color: var(--warm);
  background: rgba(244, 201, 122, 0.08);
  box-shadow: 0 0 22px rgba(244, 201, 122, 0.18);
  outline: none;
}

/* Developer mode toggle — wider, with a text label */
#devmode-toggle,
#devmode-vertical {
  position: fixed;
  top: 18px;
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid rgba(244, 201, 122, 0.25);
  background: rgba(8, 6, 4, 0.5);
  color: rgba(246, 239, 225, 0.5);
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  z-index: 6;
  transition: color 0.2s ease, border-color 0.2s ease;
}

#devmode-toggle {
  right: 64px;
}

#devmode-vertical {
  right: 195px;
}

#devmode-toggle:hover,
#devmode-toggle.on,
#devmode-vertical:hover,
#devmode-vertical.on {
  color: var(--warm);
  border-color: var(--warm);
}

.hidden {
  display: none;
}

/* Object rotation editor — visible only when an editable object is selected
   in dev mode. Read live degree values; Copy emits a paste-ready snippet. */
#dev-rot-panel {
  position: fixed;
  top: 64px;
  right: 18px;
  width: 220px;
  padding: 12px 14px;
  background: rgba(8, 6, 4, 0.78);
  border: 1px solid rgba(244, 201, 122, 0.35);
  border-radius: 8px;
  color: var(--ink);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12px;
  z-index: 7;
  backdrop-filter: blur(6px);
}

#dev-rot-panel[hidden] {
  display: none;
}

#dev-rot-name {
  font-family: Georgia, serif;
  font-size: 14px;
  color: var(--warm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 8px;
  word-break: break-all;
}

.dev-rot-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 3px 0;
  border-bottom: 1px dashed rgba(244, 201, 122, 0.15);
}

.dev-rot-row label {
  color: rgba(246, 239, 225, 0.55);
}

.dev-rot-row input[type="number"] {
  width: 100px;
  padding: 4px 6px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(244, 201, 122, 0.18);
  color: var(--ink);
  font-family: inherit;
  font-size: 12px;
  text-align: right;
  border-radius: 2px;
}

.dev-rot-row input[type="number"]:focus {
  outline: none;
  border-color: var(--warm);
  background: rgba(244, 201, 122, 0.08);
}

.dev-rot-hint {
  margin: 8px 0 10px;
  font-family: Georgia, serif;
  font-size: 11px;
  font-style: italic;
  color: rgba(246, 239, 225, 0.5);
  line-height: 1.4;
}

#dev-select {
  width: 100%;
  margin-bottom: 10px;
  padding: 6px 8px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  border: 1px solid rgba(244, 201, 122, 0.25);
  border-radius: 3px;
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
}

#dev-select:focus {
  outline: none;
  border-color: var(--warm);
  background: rgba(244, 201, 122, 0.06);
}

.dev-mode-row {
  display: flex;
  gap: 4px;
  margin: 8px 0 10px;
}

.dev-mode-btn {
  flex: 1;
  padding: 5px 0;
  background: transparent;
  border: 1px solid rgba(244, 201, 122, 0.25);
  color: rgba(246, 239, 225, 0.55);
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  border-radius: 3px;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.dev-mode-btn:hover {
  color: var(--warm);
  border-color: var(--warm);
}

.dev-mode-btn.active {
  background: rgba(244, 201, 122, 0.18);
  border-color: var(--warm);
  color: var(--warm);
}

.dev-section-label {
  margin: 10px 0 4px;
  font-family: Georgia, serif;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(246, 239, 225, 0.45);
}

#dev-rot-copy,
#dev-rot-close,
#dev-sync-toggle {
  width: 100%;
  margin-top: 6px;
  padding: 8px;
  background: transparent;
  border: 1px solid var(--warm);
  color: var(--warm);
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  border-radius: 3px;
  transition: background 0.2s ease;
}

#dev-rot-close {
  border-color: rgba(246, 239, 225, 0.4);
  color: rgba(246, 239, 225, 0.7);
}

#dev-rot-copy:hover {
  background: rgba(244, 201, 122, 0.12);
}

#dev-rot-close:hover {
  background: rgba(255, 255, 255, 0.06);
}

#dev-sync-toggle:hover {
  background: rgba(244, 201, 122, 0.12);
}

#dev-sync-toggle.on {
  background: rgba(244, 201, 122, 0.18);
  color: var(--warm);
}

#dev-sync-toggle:disabled {
  cursor: not-allowed;
  color: rgba(246, 239, 225, 0.4);
  border-color: rgba(246, 239, 225, 0.2);
  background: transparent;
}

/* While the grove loads, freeze the page at the top so any scrolling during
   the preloader can't carry into the walk. Lifted in main.js when ready. */
html.env-loading,
html.env-loading body {
  overflow: hidden;
}

/* Preloader — full-viewport curtain held over the canvas until every
   Three.js loader finishes. Fades out via the .done class set in main.js. */
#preloader {
  position: fixed;
  inset: 0;
  height: 100vh;
  height: 100dvh;
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #0a0805;
  /* shown only until the video starts painting */
  opacity: 1;
  transition: opacity 0.8s ease;
}

#preloader.done {
  opacity: 0;
  pointer-events: none;
}

#preloader-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* fill the viewport, centre-cropped, no distortion */
  display: block;
  border: 0;
  background: #0a0805;
  pointer-events: none;
}

#preloader-text {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 7vh;
  text-align: center;
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(246, 239, 225, 0.82);
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.85);
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.8s ease;
}

#preloader-text.hidden {
  opacity: 0;
}

/* "Click to enter the grove" CTA — sits above the glowing button and fades
   in at the same time as the button (~12s into the preloader). */
#enter-cta {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(50% - 130px);
  text-align: center;
  margin: 0;
  font-family: Georgia, serif;
  font-style: italic;
  font-size: 15px;
  letter-spacing: 0.18em;
  color: #ffffff;
  text-shadow:
    0 0 18px rgba(255, 255, 255, 0.4),
    0 1px 12px rgba(0, 0, 0, 0.7);
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.2s ease;
  z-index: 11;
}

#enter-cta.visible {
  opacity: 1;
}

/* === First Light Button ===
   Drop this button over your grove image.
   Parent must be position:relative and overflow:hidden.
*/

.first-light-btn {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 72px;
  height: 72px;
  border-radius: 50%;
  border: none;
  background: transparent;
  cursor: pointer;
  outline: none;
  padding: 0;
  z-index: 10;
}

/* inner glow core — cool white → pale aqua → cyan, diffusing smoothly to
   transparent. Stops follow #ffffff → #eaf7ff → #9fe0ee → #3aa8c8. */
.light-core {
  position: absolute;
  inset: -28px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(234, 247, 255, 0.82) 18%,
      rgba(159, 224, 238, 0.55) 42%,
      rgba(58, 168, 200, 0.32) 65%,
      rgba(58, 168, 200, 0.10) 85%,
      transparent 100%);
  animation: pulse-core 3.2s ease-in-out infinite;
}

/* first halo ring */
.light-ring-1 {
  position: absolute;
  inset: -18px;
  border-radius: 50%;
  background: radial-gradient(circle,
      rgba(234, 247, 255, 0.26) 0%,
      rgba(170, 210, 255, 0.12) 50%,
      transparent 75%);
  animation: pulse-ring 3.2s ease-in-out infinite;
}

/* second halo ring */
.light-ring-2 {
  position: absolute;
  inset: -38px;
  border-radius: 50%;
  background: radial-gradient(circle,
      rgba(234, 247, 255, 0.13) 0%,
      rgba(140, 190, 240, 0.06) 55%,
      transparent 75%);
  animation: pulse-ring 3.2s ease-in-out infinite 0.4s;
}

/* rotating conic rays — sized 1.5x the original and softened with a blur
   so the beams read as diffuse shafts of light, not hard slices. */
.light-rays {
  position: absolute;
  inset: -63px;
  border-radius: 50%;
  animation: spin-rays 12s linear infinite;
}

.light-rays::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  filter: blur(8px);
  background: conic-gradient(transparent 0deg,
      rgba(234, 247, 255, 0.22) 8deg,
      transparent 18deg,
      transparent 45deg,
      rgba(234, 247, 255, 0.15) 53deg,
      transparent 63deg,
      transparent 90deg,
      rgba(234, 247, 255, 0.19) 98deg,
      transparent 108deg,
      transparent 135deg,
      rgba(234, 247, 255, 0.13) 143deg,
      transparent 153deg,
      transparent 180deg,
      rgba(234, 247, 255, 0.21) 188deg,
      transparent 198deg,
      transparent 225deg,
      rgba(234, 247, 255, 0.16) 233deg,
      transparent 243deg,
      transparent 270deg,
      rgba(234, 247, 255, 0.20) 278deg,
      transparent 288deg,
      transparent 315deg,
      rgba(234, 247, 255, 0.14) 323deg,
      transparent 333deg,
      transparent 360deg);
}

/* hover intensifies the pulse */
.first-light-btn:hover .light-core {
  animation: pulse-core-hover 1.6s ease-in-out infinite;
}

.first-light-btn:hover .light-ring-1,
.first-light-btn:hover .light-ring-2 {
  animation-duration: 1.6s;
}

/* click bloom transition */
.transition-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 20;
  opacity: 0;
}

.transition-overlay.active {
  animation: bloom-out 1.6s ease-out forwards;
}

/* keyframes */
@keyframes pulse-core {

  0%,
  100% {
    opacity: 0.82;
    transform: scale(1);
  }

  50% {
    opacity: 1;
    transform: scale(1.12);
  }
}

@keyframes pulse-ring {

  0%,
  100% {
    opacity: 0.6;
    transform: scale(0.95);
  }

  50% {
    opacity: 1;
    transform: scale(1.08);
  }
}

@keyframes pulse-core-hover {

  0%,
  100% {
    opacity: 0.9;
    transform: scale(1.05);
  }

  50% {
    opacity: 1;
    transform: scale(1.2);
  }
}

@keyframes spin-rays {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

@keyframes bloom-out {
  0% {
    opacity: 0;
    background: radial-gradient(circle at 50% 50%, rgba(234, 247, 255, 0) 0%, transparent 20%);
  }

  30% {
    opacity: 1;
    background: radial-gradient(circle at 50% 50%, rgba(234, 247, 255, 0.95) 0%, rgba(159, 224, 238, 0.6) 25%, transparent 55%);
  }

  70% {
    opacity: 1;
    background: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 1) 0%, rgba(234, 247, 255, 0.95) 40%, transparent 75%);
  }

  100% {
    opacity: 1;
    background: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 1) 100%);
  }
}

/* Preloader integration — the reference doesn't gate visibility, but the
   button must stay hidden until ~12s into the intro and become inert
   while invisible. Two-line override; rest of the styling stays untouched. */
#preloader-enter {
  opacity: 0;
  pointer-events: none;
  transition: opacity 1.2s ease;
}

#preloader-enter.visible {
  opacity: 1;
  pointer-events: auto;
}

/* Diagnostic overlay (shown when something goes wrong) */
#diag {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: rgba(8, 6, 4, 0.92);
  color: var(--ink);
  z-index: 100;
  text-align: center;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

#diag[hidden] {
  display: none !important;
}

#diag h3 {
  font-family: Georgia, serif;
  font-weight: 400;
  color: var(--warm);
  font-size: 22px;
  margin: 0 0 16px;
  letter-spacing: 0.05em;
}

#diag pre {
  max-width: 720px;
  width: 100%;
  text-align: left;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(244, 201, 122, 0.18);
  padding: 14px 16px;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0 0 14px;
  color: rgba(246, 239, 225, 0.85);
}

.diag-tip {
  max-width: 640px;
  font-family: Georgia, serif;
  font-size: 14px;
  font-style: italic;
  color: rgba(246, 239, 225, 0.65);
  margin: 0;
}

/* ─── Mobile-only tweaks ───────────────────────────────────────────────
   On phones the hint/cue need extra clearance for the iOS home indicator,
   and the modal needs a bit more breathing room around the keyboard. */
@media (max-width: 640px) {
  #hint {
    bottom: calc(6vh + env(safe-area-inset-bottom));
    font-size: 12px;
  }

  #talisman-cue {
    bottom: calc(8vh + env(safe-area-inset-bottom));
  }

  #modal-card {
    width: min(440px, 92vw);
    padding: 28px 22px 22px;
    max-height: 90dvh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }

  #modal-card h2 {
    font-size: 22px;
  }

  .stone-gallery {
    gap: 10px;
    margin: 2px 0 8px;
  }

  .stone-caption {
    font-size: 10px;
    letter-spacing: 0.24em;
    margin-bottom: 16px;
  }

  /* 16px keeps iOS Safari from auto-zooming the viewport on focus. */
  #journal-form input,
  #journal-form textarea,
  .custom-select-trigger {
    font-size: 16px;
  }

  /* Larger tap targets on mobile — modal close and submit button were
     under the 44px WCAG minimum on small screens. */
  #modal-close {
    font-size: 30px;
    padding: 8px 12px;
    top: 6px;
    right: 8px;
  }
  #submit-btn {
    padding: 14px;
    min-height: 48px;
  }

  /* The absolutely-positioned dropdown panel was overflowing the modal
     edge on narrow screens. Cap its height to the viewport so it scrolls
     internally instead of clipping. */
  .custom-select .dropdown-menu {
    max-height: 50dvh;
  }

  #preloader-text {
    bottom: calc(7vh + env(safe-area-inset-bottom));
    font-size: 11px;
    letter-spacing: 0.28em;
  }

  #preloader-enter {
    bottom: calc(12vh + env(safe-area-inset-bottom));
    font-size: 12px;
    letter-spacing: 0.28em;
    padding: 12px 22px;
  }
}

.dropdown-menu {
  list-style: none;
  padding: 0;
  margin: 0;
  background: var(--paper);
  border: 1px solid rgba(244, 201, 122, 0.25);
}

.dropdown-menu li {
  display: flex;
  align-items: center;
  /* Vertically centers the icon with the text line */
  gap: 12px;
  /* Spaces out the icon from the text content */
  padding: 12px 16px;
  cursor: pointer;
  transition: background 0.2s ease;
}

.dropdown-menu li:hover {
  background: rgba(244, 201, 122, 0.06);
}

/* Color matching for icons */
.option-icon {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: var(--warm);
  stroke-width: 1.5;
  flex-shrink: 0;
  /* Prevents the icon from squeezing on narrow screens */
}

/* Inner block aligning text components inline */
.option-content {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 6px;
  font-size: 14px;
}

.option-title {
  font-weight: 600;
  color: var(--warm);
}

.option-dash {
  color: rgba(246, 239, 225, 0.4);
}

.option-desc {
  font-style: italic;
  color: rgba(246, 239, 225, 0.65);
  /* Softer tone for descriptions */
}