/* ============================================================
   UNIQorn — entrance.css (homepage only)

   Composition: the field is already blue, the red point falls into it and
   lands, and one path leaves it for the bottom of the frame.

     line   = the path of self-discovery
     mist   = what is not yet clear
     anchor = the point in the heart

   The line is drawn, not plotted. The paths share the red point as their
   origin and are seated on the three entrance names by entrance.js.

   The anchor is the Rose Anchor var(--rose) — the point in the heart (design guide
   v4, "Human anchors"). Graphic only: one per screen, never body text.

   The token itself lives in foundation.css. It is not re-declared here.
   ============================================================ */

/*
 * The opening environment is painted at viewport level. The closing footer
 * now eases into the same field, while the header remains inside the
 * watercolour rather than sitting on a separate flat band.
 */
body.is-entrance { background: none; color: var(--white); }

body.is-entrance::before {
  content: "";
  position: fixed;
  inset: -8%;
  z-index: -1;
  background:
    /*
     * Scattered pigment, on top of the washes below it. Generated, not drawn
     * with radial-gradients: CSS can only make a circle, and a "denser rim" on
     * a circle is a ring, which reads as bokeh. See assets/img/pigment.png.
     *
     * It carries its own quiet field — a soft multiplier that drops to 0.40
     * across the headline block and the entrance column — because pigment
     * behind the small print lifts the background and eats the text contrast.
     */
    url("img/pigment.png") center / cover no-repeat,
    /* the main field */
    radial-gradient(82% 60% at 17% 27%, rgba(175, 196, 211, .26) 0%, rgba(175, 196, 211, 0) 58%),
    radial-gradient(68% 56% at 85% 75%, rgba(157, 123, 196, .16) 0%, rgba(157, 123, 196, 0) 62%),
    radial-gradient(56% 44% at 63% 5%,  rgba(39, 75, 114, .55) 0%, rgba(39, 75, 114, 0) 72%),
    radial-gradient(130% 88% at 50% 124%, rgba(20, 42, 72, .95) 0%, rgba(20, 42, 72, 0) 62%),
    linear-gradient(164deg, var(--indigo) 0%, #1B2E4C 48%, var(--midnight) 100%);
  animation: field-drift 38s var(--ease-standard) infinite alternate;
  pointer-events: none;
}
@keyframes field-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-1.5%, 1.1%, 0) scale(1.045); }
}

/* paper grain — keeps the field from reading as a UI gradient */
body.is-entrance::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  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='.86' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: .085;
  mix-blend-mode: overlay;
  pointer-events: none;
}

/* ---------- header: sit inside the dark watercolour field ---------- */
.is-entrance .site-header {
  color: var(--white);
  background: linear-gradient(to bottom, rgba(16, 43, 73, .92), rgba(16, 43, 73, .54) 64%, rgba(16, 43, 73, 0));
  border-bottom: 0;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.is-entrance .wordmark {
  color: var(--white);
  background: transparent;
  -webkit-user-select: none;
  user-select: none;
}
.is-entrance .wordmark span { color: rgba(215, 227, 231, .68); }
.is-entrance .support-nav .menu a,
.is-entrance .support-nav a { color: rgba(239, 245, 248, .74); }
.is-entrance .support-nav .menu a:hover,
.is-entrance .support-nav a:hover,
.is-entrance .support-nav a:focus-visible { color: var(--white); }
.is-entrance .skip-link { background: var(--white); color: var(--indigo); }

.entrance {
  position: relative;
  min-height: calc(100vh - 96px);
  min-height: calc(100svh - 96px);
  overflow: hidden;
  isolation: isolate;
}

/* ---------- the photograph: a real room, dissolved into the field ---------- */

/*
 * Without this the cover is all atmosphere and no temperature. It sits as a
 * block in the lower-left and is soft-masked on every side so it emerges from
 * the mist instead of being pasted on it.
 */

/* ---------- the path ---------- */

/*
 * One stroke, from the point down and out of the bottom of the frame.
 *
 * It is the whole of this page's invitation to scroll, so it is not an
 * entrance animation: it is drawn by the scroll itself. At rest it is fully
 * retracted - the cover is the field, the point and the sentence, nothing
 * else - and the moment the page moves the stroke begins to draw, and it is
 * still drawing when it crosses the bottom edge.
 *
 * The dash pattern has to be given in screen pixels, and entrance.js measures
 * that length into `--path-len`. `pathLength="100"` cannot do it: with a
 * non-scaling stroke the browser resolves the dash pattern in the outermost
 * coordinate system and ignores the normalised length, so
 * `stroke-dasharray: 100` means "100px on, 100px off" - which is what once
 * turned this line into a dashed cable.
 *
 * Without JS the custom property is absent, the dash is `none` and the stroke
 * is simply solid and complete. Never dashed, and never missing.
 */

/*
 * The belly: a wider stroke under the hairline, painted first, so the line
 * gains weight where it travels and thins where it dissolves. A constant
 * stroke width is what makes a line read as a printed trace.
 */

/*
 * The marks. Three short strokes laid across the path, so it reads as
 * surveyed rather than as drawn.
 *
 * They are hidden only while the script that brings them up is running.
 * `js-home` is armed synchronously at the top of front-page.php, above the
 * markup, so there is never a frame where they are painted at full strength
 * and then taken away. Reduced motion puts them back, because there is no
 * animation left to hide them for.
 */

/* ---------- the point ---------- */

/*
 * Placed at 43.5% / 51.5% of the entrance box, and the only red mark on the
 * page. The seat is not arbitrary - the whole cover is arranged around it -
 * but nothing decides it any more: the painting whose star used to land here
 * is gone.
 */

/*
 * The fall.
 *
 * `html.js-threshold` is armed in header.php, synchronously, before the body
 * paints. It is the same flag that used to arm the painting; it is reused
 * rather than renamed because header.php is not this page's to change, and
 * because the requirement is identical - the point must not be painted at its
 * seat and then taken away. Armed, it starts above the frame. Not armed, it
 * is simply already there: the finished state, which is the rule the whole
 * site follows, and what a visitor with no script gets.
 *
 * The start is above the cover box rather than above the viewport, because
 * .entrance clips: the point appears from behind the top edge and falls the
 * last half of the frame.
 *
 * The curve is the arrival curve, not gravity. A drop accelerates, and
 * acceleration is the one thing about falling water that reads as urgency.
 *
 * The quarter-second delay is the blue beat. The page has to be *entirely*
 * blue for a moment before anything happens on it - otherwise the fall starts
 * while the eye is still working out what it is looking at, and the opening
 * reads as a page that was already moving. With `both` fill the point simply
 * waits above the frame, invisible, until the delay is up.
 */
/* the same fall, for the dot that has no transform of its own - the phone */
/* ---------- what the landing opens ---------- */

/* ---------- content ---------- */

/* ---------- the way in ---------- */

/*
 * The other end of the same front.
 *
 * It is dim before the front lands and full after, on the `--motion-base`
 * easing the rest of the cover answers with, and its start is the sum of the
 * sweep's own two tokens — it is not a second delay that happens to be near the
 * right number. Write the number instead and the two ends stop describing one
 * movement the first time the opening is retimed.
 *
 * At rest it is at full strength, which is where `from` resolves when the flag
 * is not armed: this is an exit, and an exit that is only a third of itself
 * until JavaScript runs is an exit that is not there. `both` is what makes the
 * dim state the opening state rather than the resting one.
 */
/*
 * Two texts, one seat. The seat is sized by the longer one and the shorter one
 * is laid over it, so the name — not the two characters that sit there at rest
 * — decides the width. That matters for more than looks: the seat is the hit
 * area, and a link whose text outruns its own box cannot be reached with a
 * mouse over the last two characters. The reveal has to feel like the page
 * answering, not like a link redrawing itself, so it is a crossfade between
 * two absolutely stacked spans and nothing reflows while the pointer crosses.
 */

/* The hairline is the same gesture the edge nav uses on hover: a rule that
   grows out of nothing toward the thing it names. */

/* The first entrance sits left of the star; the other two balance it right. */

/* Clickable affordance & hit target padding */

/* Chinese typography with breathing letter-spacing */

/* Spatial hierarchy: Tarot near gateway, workshops mid, crystals anchor */

/* English coordinate label with gallery tracking */
.path-status { font-size: var(--text-sm); color: rgba(203, 216, 223, .72); }

/* hover / focus optical response */

/* Attention migration: non-targets retreat into mist, focused target is optically pulled forward */

/* the strands are gradient-stroked, so they answer by weight, not by colour */

/* ---------- click-to-white transition ---------- */

/* The cover dissolves; it is not wiped. A geometric circle reads as a reveal.
   A wash has to arrive the way ink does — uneven edge, pigment settling at the
   rim, and something to look at in the middle, because when it fills the
   screen what shows is its centre. `ink-bloom.webp` is baked with all of that:
   wet edge, 170 blurred ellipses for the torn rim, paper mottle and dilute
   blue streaks carried through the white. Only transform and opacity animate,
   so the whole thing stays on the compositor. */
.white-transition {
  position: fixed;
  z-index: 90;
  left: var(--origin-x, 50%);
  top: var(--origin-y, 50%);
  width: 190vmax;
  height: 190vmax;
  margin: -95vmax 0 0 -95vmax;
  background: url("img/ink-bloom.webp") center / 100% 100% no-repeat;
  transform: scale(.02);
  opacity: 0;
  pointer-events: none;
  /* no transition at rest, on purpose: when `.is-leaving` comes off the layer
     must snap back invisible rather than animate shrinking away */
  transition: none;
}
body.is-leaving .white-transition {
  opacity: 1;
  transform: scale(1);
  transition:
    transform 1500ms cubic-bezier(.3, 0, .22, 1),
    opacity 420ms var(--ease-flow);
}

/* ---------- responsive ---------- */

/*
 * Stacked layout.
 *
 * The delta is a horizontal figure — one line arriving, three leaving to the
 * right. In a single column there is no "to the right", so the strands ran
 * straight through the entrance list and the anchor landed on the lede. Rather
 * than squeeze the figure, the mobile composition says the same thing
 * vertically: a point of light, and a short line falling out of it into the
 * page. The three entrances below are already a list; they do not need to be
 * pointed at.
 */
@media (max-width: 768px) {
  .entrance { min-height: calc(100vh - 78px); min-height: calc(100svh - 78px); }
  body.is-entrance::before { animation: none; }
  body.is-entrance::after { opacity: .06; }
}

@media (prefers-reduced-motion: reduce) {
  /* the opening is skipped rather than frozen, and the path is complete
     rather than mid-draw - see the two blocks below */
  body.is-entrance::before { animation: none; }
  /* the second selector is the one that matters: `body.is-leaving …` is more
     specific than a bare `.white-transition`, so the short duration has to be
     declared at that specificity or the wash still animates for 1.5s */
  .white-transition,
  body.is-leaving .white-transition { transition-duration: 1ms; }
}

/*
 * Retired 2026-10-02: the unicorn, and the white page it arrived on.
 *
 * The cover used to open on one plate - the unicorn, alone on a white page -
 * which then dissolved into the blue field over four and a half seconds. It is
 * gone: the page opens on the field itself, with the red point falling into
 * it, and the fall and the landing are drawn further up this file.
 *
 * Everything that drew the painting went with it - the plate's seat on the red
 * point, the two canvases, the dye that turned it blue, the star that became
 * the anchor, and the four keyframes. The whole sequence is recoverable:
 * `git show HEAD:wp-content/themes/uniqorn/assets/entrance.css` for the rules,
 * `git show HEAD:wp-content/themes/uniqorn/front-page.php` for the markup, and
 * `git show HEAD:wp-content/themes/uniqorn/assets/entrance.js` for the canvas
 * pass that spread pigment out of the painting's alpha edge.
 */

/*
 * The cover's own furniture arrives once the field has spread.
 *
 * See the reveal block above for the timing: blue, the fall, the landing, the
 * field opening out of the point, and only then everything else.
 */

/*
 * Everything else waits for the field to be most of the way out.
 *
 * The page opens on the field and nothing else, and it stays that way until
 * the water has spread: the room, the sentence, the header, the marks down the
 * right, the wash, the mist, the horizon and the path all arrive together at
 * 1900ms, by which time the field is about three quarters of the way open. The
 * header waits with them - a white bar across the top would be the one thing
 * on screen that was not part of the field.
 */
html.js-threshold .home-progress,
html.js-threshold .site-header {
  animation: entrance-reveal var(--dur-9) var(--ease-out) 1900ms both;
}

/*
 * `from` only, and no `to`, with `both` for the fill.
 *
 * A `to { opacity: 1 }` would ignore what each element's own opacity is: the
 * photograph is at .80, the mist at .20, the ripples at .52, so each would
 * rise to full and then snap back the moment the flag came off. Ending the
 * keyframe implicitly - letting it resolve to whatever the element's own value
 * is - means every one of them lands on the value it was drawn with, and it is
 * one keyframe instead of a dozen.
 *
 * `both` is what makes that safe: the `from` value holds during the delay, so
 * the element is hidden without the rule having to say `opacity: 0`. Saying it
 * there would be the bug this is avoiding - the keyframe would then resolve to
 * zero and nothing would ever appear.
 */
@keyframes entrance-reveal {
  from { opacity: 0; }
}

/*
 * The drip waits its turn.
 *
 * It is the page's standing invitation - a drop every four seconds - and it
 * has no business starting during the opening, where the only water is the
 * point and the field it opens. Delayed rather than hidden, so its cycle is
 * still the same four seconds once it does begin.
 */

/*
 * Reduced motion: the opening is skipped, not frozen.
 *
 * header.php does not arm the flag when motion is not welcome, so none of this
 * should ever fire; it is the belt to that braces. Dropping the animations
 * leaves every element on its own base value, which is the finished cover. The
 * marks are the exception - `js-home` is armed regardless of motion, and
 * without the tween that brings them up they would stay hidden.
 */
@media (prefers-reduced-motion: reduce) {
  html.js-threshold .home-progress,
html.js-threshold .site-header { animation: none; }

  /*
   * The sentence is not an animation here, it is the only thing on the screen
   * that says what the site is. `animation: none` alone would be enough to stop
   * the front, but the mask is what it is masked with, so it has to be taken
   * off in the same breath — a front parked at its start with nothing driving
   * it is an invisible title, and that is the one failure this rule exists to
   * prevent.
   */
  /* and so the exit is at full strength, which is its own base value */
}

/* ---------- the homepage's own motion ladder ----------

   Taken from the reference's stylesheet rather than from a taste call.
   Counted there: cubic-bezier(0, .55, .45, 1) 48 times,
   cubic-bezier(.33, 1, .68, 1) 36 times, cubic-bezier(.61, 1, .88, 1) 17
   times, and a duration ladder of 0.1 / 0.2 / 0.25 / 0.3 / 0.4 / 0.45 /
   0.55 / 0.6 / 0.8 / 1s. Its 1.45s, 1.8s and 2s are ambient loops and are
   not borrowed.

   Declared here, not in foundation.css, so that changing the cover's
   rhythm cannot move the reading pages. --ease-standard and --ease-flow
   stay where they are and keep doing what they were doing. */

:root {
  --ease-in-out: cubic-bezier(0, .55, .45, 1);      /* movement, opening */
  --ease-out: cubic-bezier(.33, 1, .68, 1);         /* arriving, growing */
  --ease-out-strong: cubic-bezier(.61, 1, .88, 1);  /* emphasis */

  --dur-1: 100ms;  --dur-2: 200ms;  --dur-3: 250ms;  --dur-4: 300ms;
  --dur-5: 400ms;  --dur-6: 450ms;  --dur-7: 550ms;  --dur-8: 600ms;
  --dur-9: 800ms;  --dur-10: 1000ms;
}

/* Overscroll. The field is a fixed layer, so a rubber-band at either end
   shows whatever is behind it - and what is behind it is <html>. */
html:has(body.is-entrance) { background: var(--indigo-deep); }

/* ---------- the lock ----------

   The cover is drawn once, against a 1440 x 900 window, and it is meant to
   stay that drawing. Narrowing the window must not re-break it - the lede
   must not re-wrap, the photograph must not slide under the copy, the point
   must not move relative to either. So below 1440 the whole drawing is
   scaled, and nothing inside it re-flows.

   `zoom` is what does it, for the same reason it does it on the about page:
   it scales the layout along with the paint, so the scaled drawing is
   exactly as wide as the window and nothing ever scrolls sideways.

   The floor is 1001px rather than the about page's 1024px, because 1000px
   is where this page's own narrow layout begins (`max-width: 1000px`, the
   block that moves the dot onto the drip). The
   two have to meet, or there is a band of widths where the desktop layout
   is on screen and unlocked - which is exactly the re-flow this prevents.

   One thing `zoom` does not scale: viewport units. They keep resolving
   against the real window, so a rule that divides them by --lock is asking
   for the value the drawing used. Two consequences, and they are different:

     vw  must be divided. The drawing's width in the zoomed coordinate space
         is 100vw / lock - a constant 1440 - while the window itself got
         narrower. Left alone, a vw value is shrunk twice.

     vh  must NOT be divided. The window's height did not change, so 100vh
         is already the constant the drawing was measured against, and the
         scene boxes (100svh - header) stay in step with the point
         coordinates for free.

   --boost makes a clamp's middle term resolve past its own maximum, so the
   clamp always returns the px bound it was drawn with and the value is a
   constant rather than a function of the window. That is why every clamp in
   this file carries `calc(<n>vw * var(--boost, 1) / var(--lock, 1))`.
   Both factors are 1 outside the locked range, so the narrow layout still
   breathes the way it did. */
@media (min-width: 1001px) {
  :root {
    --lock: min(1, calc(100vw / 1440px));
    --boost: 1.25;
    zoom: var(--lock);
  }
}

/* ---------- the page ---------- */

.entrance-overview {
  --stage-top: 96px;
  --point-x: calc(43.5vw / var(--lock, 1));
  --point-y: calc(var(--stage-top) + (100vh - var(--stage-top)) * .515);
  --point-y: calc(var(--stage-top) + (100svh - var(--stage-top)) * .515);
  --scene-wash: .10;
  --thread: 1;

  position: relative;
  isolation: isolate;
}

.entrance-overview[data-scene="tarot"] {
  --point-x: calc(71vw / var(--lock, 1));
  --point-y: 46vh;
  --scene-wash: .16;
}
.entrance-overview[data-scene="workshops"] {
  --point-x: calc(31vw / var(--lock, 1));
  --point-y: 51vh;
  --scene-wash: .13;
}
.entrance-overview[data-scene="crystals"] {
  --point-x: calc(69vw / var(--lock, 1));
  --point-y: 55vh;
  --scene-wash: .15;
}

/* ---------- the stage ---------- */

/*
 * The scene's colour: one very dilute wash that moves when the scene does.
 *
 * Not a second field. It is a tenth to a sixth of full strength and blended
 * into what is under it rather than laid on top, so what changes between
 * scenes is the temperature of the mist, not the colour of the page.
 *
 * soft-light and opacity only: a gradient cannot be transitioned in Chrome
 * (the property is discrete there), so the colour is fixed and the layer is
 * what moves.
 */

/*
 * Two banks of mist, drawn as soft radial fields.
 *
 * A 64vw disc with a 56px blur is a full-screen filter pass on every frame
 * it moves; a gradient is already soft and costs nothing to translate. The
 * blobs are bigger than the ones they replace for the same reason - the
 * softness now comes from the falloff, not from the blur radius.
 */

/*
 * The water.
 *
 * Seven rings, concentric on the point, from the reference's own spatial
 * geometry. They do NOT rotate with the scene: rotating a figure like this
 * reads as machinery, and what this page is doing is water.
 *
 * So they breathe instead - a little over one percent, one at a time, out
 * of phase by a tenth of a second each. At any moment the whole field is
 * moving by less than the width of the stroke, which is the difference
 * between a surface and an animation.
 */

/*
 * And the rings stop when the cover stops.
 *
 * In the version this came from, --cover-p ran 0 to 1 across the cover and then
 * stayed at 1 for the rest of the document, so the field carried a cover-phase
 * transform straight through the three scenes — where the point has already
 * been re-seated. The field was carrying a transform that belonged to a section
 * that was no longer on screen. Past the cover there is no progress to answer,
 * so the answer is nothing.
 *
 * Written as a rescale rather than the deployed `transform: none`: on this
 * file the same `transform` is what positions the figure at the point, so a
 * bare `none` would drop the rings back to left:0/top:0 and send them to the
 * corner of the viewport. This keeps the seat and drops only the drift.
 */

/*
 * The inner ring pushes the furthest, the outer rings barely travel. Six
 * keyframes instead of two, so the motion has a shoulder and an ease rather
 * than a sine wave - a water surface does not move like a metronome.
 */
/*
 * Fluid ripple rings: each ring has its own transform-origin at center
 * so scroll-driven fluid displacement and elastic lag can operate on them.
 */

/*
 * The field is born out of the landing:
 * Point touches down at 1250ms with zero circles.
 * From 1280ms, rings bloom from center outward in organic waves.
 */
/*
 * The ring a drop opens, and the whole of the page's invitation.
 *
 * One ring, one second, once every four. It grows from nothing at the point
 * the drop landed and is still growing when it leaves the bottom of the
 * frame - which is the entire message. Nothing says "scroll"; the water
 * simply goes somewhere below.
 *
 * The easing is the arrival curve, not gravity. A drop accelerates, and
 * acceleration is the one thing about falling water that reads as urgency.
 */
/*
 * The ring a landing opens, which is a scene change.
 *
 * A separate element from the one above because they are different events:
 * the drop is the page asking to be scrolled, a landing is the page
 * answering. Same shape, same curve, a shade stronger, and it only runs when
 * the script says a landing happened.
 */
/*
 * The thread. One hairline from the left edge to the point, fading out of
 * nothing and into the point.
 *
 * Positioned by transform like everything else on the stage: the element is
 * a full viewport wide and pulled back by its own width, so its right end
 * sits exactly on the point at any scene. The growth is on the inner <i>,
 * which is what the scroll animates - a scale, so it stays on the
 * compositor, and one element so there is nothing else to keep in step.
 */

/* ---------- the invitation, on the cover ---------- */

/* ---------- the photographs ---------- */

/* the cover: all three far back in the mist, none of them the subject */

/* ---------- the three scenes ---------- */

/*
 * The copy is at full strength by default and the dimming is opt-in.
 *
 * `html.js-home` is armed by a synchronous script at the top of
 * front-page.php, and only when IntersectionObserver exists - because the
 * observer is the only thing that can ever change the state. Without it,
 * the class is never set and every copy keeps its strength, which is the
 * same page a visitor with no script gets. A finished state as the default
 * is the rule the whole site follows.
 */

/* one left, one right, one left: the scene and its picture trade sides so
   the eye has to travel rather than settle */

.home-kicker {
  margin: 0 0 var(--space-5);
  font: 500 10px/1.4 var(--font-mono);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(215, 227, 231, .62);
}
.home-title {
  max-width: 10em;
  font-family: var(--font-display);
  font-size: clamp(38px, calc(4.6vw * var(--boost, 1) / var(--lock, 1)), 70px);
  line-height: 1.14;
  letter-spacing: .01em;
  color: var(--white);
  text-wrap: balance;
}
.home-description {
  max-width: 29em;
  margin: 26px 0 0;
  color: rgba(239, 245, 248, .75);
  font-size: clamp(14px, calc(1.25vw * var(--boost, 1) / var(--lock, 1)), 17px);
  line-height: 1.78;
}

.home-enter {
  display: inline-flex;
  align-items: center;
  gap: 18px;
  min-height: 48px;
  margin-top: 34px;
  padding: 0 2px var(--space-2);
  border-bottom: 1px solid rgba(215, 227, 231, .42);
  font-size: 13px;
  letter-spacing: .08em;
  color: rgba(255, 255, 255, .92);
  transition:
    color var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out),
    gap var(--dur-5) var(--ease-out);
}
.home-enter:hover,
.home-enter:focus-visible {
  gap: 25px;
  border-color: rgba(255, 255, 255, .86);
  color: var(--white);
}
.home-enter .path-status { color: rgba(215, 227, 231, .72); }

/* ---------- where you are ---------- */

/*
 * Four marks, one a scene, the current one rose.
 *
 * It is navigation rather than decoration - each mark is a real anchor - and
 * it is the second half of the invitation. The drop says the water goes
 * down; this says how far, and it is the only thing on the page that does.
 */
.home-progress {
  position: fixed;
  z-index: 25;
  right: clamp(18px, calc(2.1vw * var(--boost, 1) / var(--lock, 1)), 34px);
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  gap: 15px;
}
.home-progress a {
  position: relative;
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
}
.home-progress a::before {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: rgba(215, 227, 231, .40);
  transition:
    width var(--dur-3) var(--ease-in-out),
    height var(--dur-3) var(--ease-in-out),
    background var(--dur-3) var(--ease-in-out),
    box-shadow var(--dur-3) var(--ease-in-out);
}
.home-progress a.is-current::before {
  width: 8px;
  height: 8px;
  background: var(--anchor-red);
  box-shadow: 0 0 0 4px rgba(197, 139, 142, .11);
}
.home-progress a:focus-visible { outline-offset: 0; }

/* ---------- responsive ---------- */

@media (max-width: 900px) {
  .entrance-overview { --stage-top: 78px; }

  .is-entrance .site-header {
    background: rgba(16, 43, 73, .88);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
  }
  .home-title { max-width: 8.2em; font-size: clamp(34px, 9.6vw, 52px); }
  .home-description { max-width: 28em; margin-top: 20px; font-size: 14px; }

  /*
   * The stage has no room for a picture here, so the scene carries its own -
   * the same file, behind the copy, masked the same way. It is the only copy
   * of the photograph left, so it is the one that keeps the real alt.
   */

  .home-progress { right: 8px; gap: 11px; }
}

@media (max-width: 560px) {
  .home-kicker { margin-bottom: 14px; }
  .home-title { font-size: clamp(30px, 10vw, 44px); }
  .home-description { line-height: 1.68; }
  .home-enter { margin-top: 26px; }
  .home-progress { right: 3px; }
}

/* ---------- no motion ----------

   foundation.css already stops every animation and transition on the page
   when motion is not welcome, which is enough for all of the above: the
   drop and the ring end on an opacity of 0, so what is left is a still
   surface. This only has to make sure the copy is not left dimmed, since
   the dimming is not an animation and would otherwise stay. */
