/* The landing's opening scene (partials/hero.gohtml, brought to life by
 * hero.js): what the night and the day share. The forest is laid out here
 * and painted from custom properties that night.css and day.css set on
 * .sb-hero, the scene's own picture colours rather than theme tokens: each
 * theme gets a picture of its own. Only the foot of the scene reads a
 * token, where it dissolves into the page.
 *
 * The scene is one landscape shot, composed in a frame 1600 units wide and
 * 1000 tall and scaled to fit its height: --u is a unit's length (set with
 * the title's layout, landing.css), and the frame's middle is the scene's.
 * A screen wider than 16:10 sees more at the sides, a narrower one less;
 * the sky and the wood carry on past the frame for it. Above the frame is
 * --band, more sky, for the header to sit on where the shot is not the
 * whole screen. So a thing at (x, y) in the frame sits at
 * left: calc(50% + (x - 800) * var(--u)), top: calc(var(--band) + y * var(--u)).
 * Where a part is placed, its place is given as unitless custom properties
 * in frame units (--fx, --fy, --fw, --fh). */

.sb-hero {
  position: absolute;
  inset: 0;
  /* Its own stacking context, under everything else in the title: the
   * welcome's blank page covers all of it, overlays and all. */
  z-index: 0;
  isolation: isolate;
  overflow: hidden;
  background: var(--sky);
}

/* Where the scene is a shot rather than the whole screen (landing.css), it
 * is the frame and the band above it, and the words follow it. */
@media (max-aspect-ratio: 6/5) {
  .sb-hero {
    position: relative;
    inset: auto;
    justify-self: stretch;
    height: calc(var(--band) + 1000 * var(--u));
  }
}

/* Each scene's own parts show only in its theme. Night is the default, so
 * a page without script (and so without data-theme) is the night. */
:root[data-theme="day"] .sb-hero [data-scene="night"],
:root:not([data-theme="day"]) .sb-hero [data-scene="day"] {
  display: none;
}

/* The near ground runs out into the page. */
.sb-hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  z-index: 5;
  height: var(--foot-height, 18%);
  pointer-events: none;
  background: linear-gradient(transparent var(--foot-clear, 0%), color-mix(in oklab, var(--color-bg) 60%, transparent) 60%, var(--color-bg));
}

.nt-sky,
.dy-sky,
.hero-land {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The scene's drawings are sized by the frame, some wider than the screen
 * (the ridges, the stars), not held to it as other pictures are. */
.sb-hero svg {
  max-width: none;
}

/* ---- The land ---------------------------------------------------------------- *
 * The ridges share one frame of their own (1600x500 ridge units, 1.28 of
 * the scene's units each) standing on the foot of the scene, so they line
 * up at any screen size; the wood runs on past it at the sides (scene.go).
 * Under each ridge lie its trees' crowns in the rim colour, and the ridge
 * itself is shifted down and away from the light, so a lit edge shows along
 * the tops and the sides of the crowns that face the moon or the sun (both
 * hang upper right). */
.hero-ridge,
.hero-mist {
  position: absolute;
  bottom: 0;
}
.hero-ridge {
  left: calc(50% - 1024 * var(--u));
  width: calc(2048 * var(--u));
  height: calc(640 * var(--u));
  overflow: visible;
}
.hero-ridge--far .hero-ridge__rim { fill: var(--far-rim); }
.hero-ridge--mid .hero-ridge__rim { fill: var(--mid-rim); }
.hero-ridge--near .hero-ridge__rim { fill: var(--near-rim); }
.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
/* Bands of mist drifting a tile's width at a time, so the loop is seamless:
 * --fy is the band's foot above the frame's, --fh its height, --fw a tile. */
.hero-mist {
  --fw: 761;
  --tile: calc(var(--fw) * var(--u));
  left: calc(-1 * var(--tile));
  bottom: calc(var(--fy) * var(--u));
  width: calc(100% + 2 * var(--tile));
  height: calc(var(--fh) * var(--u));
  background: radial-gradient(ellipse 50% 50% at 50% 50%, var(--mist), transparent) 0 0 / var(--tile) 100% repeat-x;
  animation: hero-mist 120s linear infinite;
}
.hero-mist--far { --fy: 250; --fh: 220; }
.hero-mist--near { --fy: 120; --fh: 180; opacity: 0.7; animation-duration: 80s; animation-direction: reverse; }
@keyframes hero-mist { to { transform: translateX(var(--tile)); } }

/* The old branch, where the owl sits by night and a songbird by day. It
 * grows from a tree off the left of the screen, so it is held to the
 * screen's edge rather than the frame's, and the bird's stretch of it is
 * always in the shot. */
.hero-perch {
  --fy: 450;
  --fw: 400;
  position: absolute;
  left: 0;
  top: calc(var(--band) + var(--fy) * var(--u));
  width: calc(var(--fw) * var(--u));
  overflow: visible;
}
.hero-bark { fill: var(--bark); }
.hero-bark--leaves { fill: var(--leaves, var(--bark)); }
.hero-rim { fill: none; stroke: var(--rim); stroke-width: 1.2; stroke-linecap: round; opacity: 0.7; }

/* Film grain, so the long gradients do not band. */
.hero-grain {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  opacity: var(--grain, 0.035);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---- The fairy's light, and her sparkle --------------------------------------- */
.sb-flyer::before,
.sb-fairy::before {
  content: "";
  position: absolute;
  inset: -110%;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle, var(--fairy-light, rgb(255 214 130 / 0.2)), transparent 68%);
  transition: opacity 600ms var(--ease-out);
}

/* A scene can give the sparkle an edge (--spark-edge, a filter), where its
 * sky is too light for the bare colour to show. The star is cut from the
 * ::before, so the edge, on the element, goes round the cut shape. */
.hero-spark {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 4;
  width: var(--spark-size, 8px);
  height: var(--spark-size, 8px);
  margin: calc(var(--spark-size, 8px) / -2) 0 0 calc(var(--spark-size, 8px) / -2);
  pointer-events: none;
  filter: var(--spark-edge, none);
  animation: hero-spark 1.1s ease-out forwards;
}
.hero-spark::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--spark, var(--fairy-star));
  clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%);
}
@keyframes hero-spark {
  from { opacity: 1; transform: translate(var(--x), var(--y)) scale(var(--s)) rotate(0); }
  to { opacity: 0; transform: translate(var(--x), calc(var(--y) + 26px)) scale(calc(var(--s) * 0.2)) rotate(90deg); }
}

/* With a mouse, the layers shift with the pointer (hero.js); each gets a
 * compositor layer of its own, so moving one repaints nothing. Touch
 * screens have no parallax, and no layers to pay for. */
@media (pointer: fine) {
  .hero-ridge,
  .hero-mist,
  .hero-perch,
  .hero-canvas--far,
  .nt-stars,
  .nt-glints,
  .nt-moon,
  .nt-moonlight,
  .nt-cloud,
  .dy-sun,
  .dy-cloud,
  .dy-beams,
  .dy-flutter {
    will-change: translate;
  }
}

