/* Mountain environment: a fixed, inert, full-viewport landscape behind every page.
   Scoped to body.mountains / .mtn-*. light-dark() follows the site's own color-scheme, so the manual
   theme toggle themes it. Colours are Mount's low-chroma navy (dark) and pale blue-grey (light). */
body.mountains {
  background: transparent; /* html paints the same --void; the scene blends into it */
}

.mtn-scene {
  --mtn-c-far: light-dark(#edf1f8, #1c2946);
  --mtn-c-mid: light-dark(#e6ecf4, #16233f);
  --mtn-c-near: light-dark(#dce5f0, #101c38);
  --mtn-plane: light-dark(rgba(52, 74, 118, 0.04), rgba(2, 5, 14, 0.4));
  --mtn-rim: light-dark(rgba(40, 64, 130, 0.12), rgba(127, 156, 245, 0.3));
  position: fixed;
  inset: 0;
  overflow: hidden; /* clips only this decorative layer */
  z-index: -1;
  opacity: 0.72;
  pointer-events: none;
  user-select: none;
  /* Quieter luminance where the reading column lives; the outer flanks keep full strength. */
  --mtn-veil: linear-gradient(90deg, #000 0, rgba(0, 0, 0, 0.7) 14%, rgba(0, 0, 0, 0.6) 50%, rgba(0, 0, 0, 0.7) 86%, #000 100%);
  -webkit-mask-image: var(--mtn-veil);
  mask-image: var(--mtn-veil);
}

/* Layers overscan vertically so the full-span offsets (far 0..24px, near +72..-48px) never expose an
   edge. The static pose (noJS, reduced, hidden) is the initial one: far 0, near +72. */
.mtn-scene > div.mtn-far,
.mtn-scene > div.mtn-near {
  position: absolute;
  inset: -96px -12px; /* 12px horizontal overscan for the camera; the art box below compensates */
}
.mtn-scene > div.mtn-far {
  transform: translate3d(0, var(--mtn-far-y, 0px), 0);
  translate: var(--mtn-fx, 0px) var(--mtn-fy, 0px);
}
.mtn-scene > div.mtn-near {
  transform: translate3d(0, var(--mtn-near-y, 72px), 0);
  translate: var(--mtn-nx, 0px) var(--mtn-ny, 0px);
}

/* The art keeps its original canvas (viewport + 96px, starting 48px above the viewport) inside the
   larger movement envelope of the outer layers. */
.mtn-ridge {
  position: absolute;
  inset: 48px auto auto 12px;
  display: block;
  width: calc(100% - 24px);
  height: calc(100% - 96px);
  overflow: visible; /* ridges continue sideways beyond the art box */
}

/* Two compositions: wide for landscape/desktop, tall for portrait phones and tablets. */
.mtn-tall { display: none; }
@media (max-aspect-ratio: 5/4) and (max-width: 899px) {
  .mtn-wide { display: none; }
  .mtn-tall { display: block; }
  .mtn-scene {
    --mtn-veil: linear-gradient(90deg, rgba(0, 0, 0, 0.92) 0, rgba(0, 0, 0, 0.66) 24%, rgba(0, 0, 0, 0.62) 76%, rgba(0, 0, 0, 0.92) 100%);
  }
}

.mtn-s-far { stop-color: var(--mtn-c-far); }
.mtn-s-mid { stop-color: var(--mtn-c-mid); }
.mtn-s-near { stop-color: var(--mtn-c-near); }
.mtn-s-plane { stop-color: var(--mtn-plane); }
.mtn-rim {
  fill: none;
  stroke: var(--mtn-rim);
  stroke-width: 1.2;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* Living valley. Arrival: one finite layered settle on the outer layers (individual translate, so the
   scroll transform is untouched) while the existing rims sketch in (JS adds a temporary pathLength=1 and
   data-intro; clearing it restores the full solid rim). Camera: mouse depth, transition only while data-cam. */
@media (prefers-reduced-motion: no-preference) {
  .mtn-scene[data-intro] > div.mtn-far { animation: mtn-far-in 640ms cubic-bezier(0.16, 1, 0.3, 1) 1 both; }
  .mtn-scene[data-intro] > div.mtn-near { animation: mtn-near-in 800ms cubic-bezier(0.16, 1, 0.3, 1) 1 both; }
  .mtn-scene[data-intro] .mtn-rim {
    stroke-dasharray: 1;
    animation: mtn-draw 640ms cubic-bezier(0.16, 1, 0.3, 1) 1 both;
  }
  .mtn-scene[data-intro] > div.mtn-near .mtn-rim { animation-duration: 700ms; }
  .mtn-scene[data-cam] > div.mtn-far,
  .mtn-scene[data-cam] > div.mtn-near { transition: translate 140ms ease-out; }
}

@keyframes mtn-far-in {
  from { translate: 0 10px; opacity: 0.4; }
  to { translate: 0 0; opacity: 1; }
}

@keyframes mtn-near-in {
  from { translate: 0 20px; opacity: 0.4; }
  to { translate: 0 0; opacity: 1; }
}

@keyframes mtn-draw {
  from { stroke-dashoffset: 1; }
  to { stroke-dashoffset: 0; }
}

/* Enlarged text (JS sets data-big): even quieter, still visible. */
.mtn-scene[data-big] { opacity: 0.6; }

/* Build arrival: one short phrase on Mount's own landing grammar (cubic-bezier(0.16, 1, 0.3, 1),
   ~420ms vs the 450ms land). mountains.js sets data-mtn="go" once and removes it afterwards. Text is
   never faded: entries only settle 8px, 70ms apart; the heading rule gets one fine accent sweep. */
.front-projects .section-head { position: relative; }
.front-projects .section-head::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: light-dark(#2f56d6, #7f9cf5);
  transform: scaleX(0);
  transform-origin: left;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .front-projects[data-mtn="go"] .section-head::after { animation: mtn-sweep 420ms cubic-bezier(0.16, 1, 0.3, 1) 1; }
  .front-projects[data-mtn="go"] .build-entry { animation: mtn-settle 420ms cubic-bezier(0.16, 1, 0.3, 1) 1 backwards; }
  .front-projects[data-mtn="go"] .build-entry:nth-child(2) { animation-delay: 70ms; }
  .front-projects[data-mtn="go"] .build-entry:nth-child(3) { animation-delay: 140ms; }
}

@keyframes mtn-sweep {
  0% { transform: scaleX(0); opacity: 1; }
  65% { transform: scaleX(1); opacity: 1; }
  100% { transform: scaleX(1); opacity: 0; }
}

@keyframes mtn-settle {
  from { transform: translateY(8px); }
  to { transform: none; }
}

@media (forced-colors: active) {
  .mtn-scene { display: none; }
}
