/* ═══════════════════════════════════════════════════════════════
   GREY CAFÉ
   Mobile-first.

   Two layers, deliberately opposed:
   · THE SKY   — a fixed, pointer-driven stack of cloud, sun and sky.
   · THE INDEX — a cool archive of hairlines, bracketed micro-labels
                 and offset columns, laid over the weather.
   ═══════════════════════════════════════════════════════════════ */

:root{
  --ink:     #0c0e11;
  --paper:   #f3f2f0;
  --ash:     #d9d6d1;   /* the overcast ground */
  --rule:    rgba(255,255,255,.14);
  --rule-2:  rgba(255,255,255,.07);
  --dim:     rgba(255,255,255,.42);
  --mid:     rgba(255,255,255,.66);

  --sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --serif: "Cormorant Garamond", ui-serif, Georgia, "Times New Roman", serif;

  /* driven by sky.js */
  --dusk: 0;      /* scroll progress: the page falls into night */

  /* half-width of the band the day sky blends into the night one across.
     every mask that divides the two reads this, so they widen together. */
  --seam: 13vw;

  /* the procession. defaults draw the scene at rest — sun on the day side,
     moon on the night side — for anyone without script or with motion off */
  --body: 11vmin; /* sun and moon diameter (matches BODY in sky.js) */
  --sx:   20vw;   /* sun */
  --sy:   29vh;
  --ss:   1;      /* sun scale: nearer is bigger */
  --mx:   80vw;   /* moon */
  --my:   29vh;
  --ms:   .73;   /* the moon is the smaller body — see MBASE in sky.js */
  --vis:  1;      /* the sun fades out below the screen and back in above it */
  --mvis: 1;      /* the moon does the same, on its own account: the orbit's lean
                     can carry one body past the rim while the other is mid-sky */
  --mocc: 0;      /* how far the moon is behind the sun, 1 when wholly covered */
  --occx: -999px; /* the sun's disc in the moon's own box, which is what cuts it */
  --occy: -999px;
  --occr: 0px;
  --side: 0;      /* sun: 0 on the day half · 1 on the night half */
  --mside:1;      /* moon: the same */
  --mlit: .5;     /* lit fraction of the moon's face */
  --mterm:1;      /* the terminator's half-width across the disc, 0 at the quarters
                     (a straight edge) and 1 at full and new (it meets the limb) */
  --mbias:0;      /* how far past the terminator the shadow's edge is carried, in
                     percent — nil except within a sliver of full and of new */
  --mang: 0deg;   /* the bearing of the sun from the moon: the shadow turns to it */
  --ecl:  0;      /* how much of the sun the moon covers */
  --tot:  0;      /* totality */

  --pad: clamp(1.15rem, 5.5vw, 3.25rem);
  --bar: 2.15rem;                     /* status bar height */
}

*,*::before,*::after{ box-sizing:border-box; }

html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }

body{
  margin:0;
  background:var(--ink);
  color:var(--paper);
  font-family:var(--sans);
  font-weight:300;
  font-size:15px;
  line-height:1.62;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

img{ max-width:100%; height:auto; display:block; }
a{ color:inherit; }
::selection{ background:rgba(255,226,178,.3); color:#fff; }
:focus-visible{ outline:1px solid rgba(255,255,255,.8); outline-offset:4px; }

/* ═══════════════════ THE SKY ═══════════════════

   One sky, lit two ways. `field-night-*.jpg` is tone-mapped from the exact
   pixels of `field-day-*.jpg`, so the two share cloud geometry perfectly:
   the seam down the middle is a change of light, not a change of sky, and
   every form runs through it unbroken. The plate itself is about half
   cloud and half open sky.

   The cloud layers never move and never repaint. Everything that moves is
   masked into the window group above them: the opening — a soft ellipse
   that thins the cloud under the pointer — and the procession, a sun and
   a moon winding down the screen on a double helix, each carrying a small
   opening of its own.                                                    */

.sky{
  position:fixed; inset:0; z-index:0;
  overflow:hidden;
  background:#05070b;
  pointer-events:none;
  contain:strict;
}
.sky > *{
  position:absolute; inset:0;
  background-repeat:no-repeat;
  background-position:center;
  background-size:cover;
}

/* ── the cloud field ── */

.field{
  background-image:url("assets/field-day-m.jpg");
}

/* the night copy covers the right half, carried in across a wide, eased band
   so the two halves resolve into one another instead of meeting at a line. */
.field--night{
  background-image:url("assets/field-night-m.jpg");
  -webkit-mask-image:linear-gradient(90deg,
    transparent calc(50% - var(--seam)),
    rgba(0,0,0,.10) calc(50% - var(--seam) * .75),
    rgba(0,0,0,.22) calc(50% - var(--seam) * .5),
    rgba(0,0,0,.36) calc(50% - var(--seam) * .25),
    rgba(0,0,0,.5)  50%,
    rgba(0,0,0,.64) calc(50% + var(--seam) * .25),
    rgba(0,0,0,.78) calc(50% + var(--seam) * .5),
    rgba(0,0,0,.90) calc(50% + var(--seam) * .75),
    #000 calc(50% + var(--seam)));
          mask-image:linear-gradient(90deg,
    transparent calc(50% - var(--seam)),
    rgba(0,0,0,.10) calc(50% - var(--seam) * .75),
    rgba(0,0,0,.22) calc(50% - var(--seam) * .5),
    rgba(0,0,0,.36) calc(50% - var(--seam) * .25),
    rgba(0,0,0,.5)  50%,
    rgba(0,0,0,.64) calc(50% + var(--seam) * .25),
    rgba(0,0,0,.78) calc(50% + var(--seam) * .5),
    rgba(0,0,0,.90) calc(50% + var(--seam) * .75),
    #000 calc(50% + var(--seam)));
}

/* stars in the night half's open sky. the outer element keeps them off the
   day half; the inner one is masked by `field-gaps-*.jpg` — the plate's own
   luminance, inverted — so they sit in the gaps between the clouds and
   never on top of one. */
.sky__stars{
  -webkit-mask-image:linear-gradient(90deg,
    transparent calc(50% - var(--seam)),
    rgba(0,0,0,.10) calc(50% - var(--seam) * .75),
    rgba(0,0,0,.22) calc(50% - var(--seam) * .5),
    rgba(0,0,0,.36) calc(50% - var(--seam) * .25),
    rgba(0,0,0,.5)  50%,
    rgba(0,0,0,.64) calc(50% + var(--seam) * .25),
    rgba(0,0,0,.78) calc(50% + var(--seam) * .5),
    rgba(0,0,0,.90) calc(50% + var(--seam) * .75),
    #000 calc(50% + var(--seam)));
          mask-image:linear-gradient(90deg,
    transparent calc(50% - var(--seam)),
    rgba(0,0,0,.10) calc(50% - var(--seam) * .75),
    rgba(0,0,0,.22) calc(50% - var(--seam) * .5),
    rgba(0,0,0,.36) calc(50% - var(--seam) * .25),
    rgba(0,0,0,.5)  50%,
    rgba(0,0,0,.64) calc(50% + var(--seam) * .25),
    rgba(0,0,0,.78) calc(50% + var(--seam) * .5),
    rgba(0,0,0,.90) calc(50% + var(--seam) * .75),
    #000 calc(50% + var(--seam)));
  opacity:calc(.72 + var(--dusk) * .28);
}
.sky__stars-in{
  position:absolute; inset:0;
  background-image:
    radial-gradient(1.4px 1.4px at 54% 12%, rgba(255,255,255,.9), transparent),
    radial-gradient(1.1px 1.1px at 58% 41%, rgba(255,255,255,.7), transparent),
    radial-gradient(1.6px 1.6px at 61% 74%, rgba(255,255,255,.85), transparent),
    radial-gradient(1.1px 1.1px at 64% 27%, rgba(255,255,255,.65), transparent),
    radial-gradient(1.3px 1.3px at 67% 56%, rgba(255,255,255,.8), transparent),
    radial-gradient(1px 1px     at 69% 90%, rgba(255,255,255,.6), transparent),
    radial-gradient(1.5px 1.5px at 72% 8%,  rgba(255,255,255,.85), transparent),
    radial-gradient(1.1px 1.1px at 74% 38%, rgba(255,255,255,.7), transparent),
    radial-gradient(1.2px 1.2px at 77% 64%, rgba(255,255,255,.75), transparent),
    radial-gradient(1px 1px     at 79% 21%, rgba(255,255,255,.6), transparent),
    radial-gradient(1.6px 1.6px at 82% 48%, rgba(255,255,255,.9), transparent),
    radial-gradient(1.1px 1.1px at 84% 83%, rgba(255,255,255,.65), transparent),
    radial-gradient(1.3px 1.3px at 87% 15%, rgba(255,255,255,.8), transparent),
    radial-gradient(1px 1px     at 89% 59%, rgba(255,255,255,.6), transparent),
    radial-gradient(1.5px 1.5px at 92% 33%, rgba(255,255,255,.85), transparent),
    radial-gradient(1.1px 1.1px at 94% 72%, rgba(255,255,255,.7), transparent),
    radial-gradient(1.2px 1.2px at 97% 5%,  rgba(255,255,255,.75), transparent),
    radial-gradient(1px 1px     at 98% 46%, rgba(255,255,255,.6), transparent),
    radial-gradient(1.4px 1.4px at 56% 62%, rgba(255,255,255,.8), transparent),
    radial-gradient(1px 1px     at 63% 95%, rgba(255,255,255,.55), transparent),
    radial-gradient(1.2px 1.2px at 75% 3%,  rgba(255,255,255,.7), transparent),
    radial-gradient(1.1px 1.1px at 91% 88%, rgba(255,255,255,.65), transparent),
    /* five more, placed where field-gaps-m says the plate is actually open —
       the upper night half is solid cloud, so the gaps worth filling are all
       through the lower middle. All clear of the seam's blend band, or they
       would come out dimmed. */
    radial-gradient(1.3px 1.3px at 64% 68%, rgba(255,255,255,.8), transparent),
    radial-gradient(1px 1px     at 70% 62%, rgba(255,255,255,.6), transparent),
    radial-gradient(1.5px 1.5px at 72% 69%, rgba(255,255,255,.85), transparent),
    radial-gradient(1.1px 1.1px at 76% 51%, rgba(255,255,255,.7), transparent),
    radial-gradient(1.2px 1.2px at 81% 72%, rgba(255,255,255,.75), transparent);
  background-size:100% 100%;
  -webkit-mask-image:url("assets/field-gaps-m.jpg");
          mask-image:url("assets/field-gaps-m.jpg");
  -webkit-mask-size:cover;            mask-size:cover;
  -webkit-mask-position:center;       mask-position:center;
  -webkit-mask-repeat:no-repeat;      mask-repeat:no-repeat;
  -webkit-mask-source-type:luminance; mask-mode:luminance;
}

/* ── the window ──
   Masking the window instead of the clouds means the two heavy cloud
   layers are painted once and left alone; only this group's mask is
   rebuilt as the procession moves. The mask is the union of an opening
   around each body — the sky is only ever open where they are. Nothing
   follows the pointer any more, so the openings carry the whole sky and
   are correspondingly wide.                                            */
.window{
  --so:calc(var(--body) * 4.2 * var(--ss) * var(--vis));   /* sun opening  */
  --mo:calc(var(--body) * 4.0 * var(--ms) * var(--mvis));  /* moon opening */
  /* a long, gradual falloff — the sky should diffuse away into the cloud
     rather than stop at a clean edge */
  -webkit-mask-image:
    radial-gradient(circle var(--so) at var(--sx) var(--sy),
      #000 0%, #000 22%, rgba(0,0,0,.72) 46%, rgba(0,0,0,.3) 72%, transparent 100%),
    radial-gradient(circle var(--mo) at var(--mx) var(--my),
      #000 0%, #000 24%, rgba(0,0,0,.7) 48%, rgba(0,0,0,.26) 74%, transparent 100%);
          mask-image:
    radial-gradient(circle var(--so) at var(--sx) var(--sy),
      #000 0%, #000 22%, rgba(0,0,0,.72) 46%, rgba(0,0,0,.3) 72%, transparent 100%),
    radial-gradient(circle var(--mo) at var(--mx) var(--my),
      #000 0%, #000 24%, rgba(0,0,0,.7) 48%, rgba(0,0,0,.26) 74%, transparent 100%);
  will-change:mask-image;
}
.window > *{
  position:absolute; inset:0;
  background-repeat:no-repeat;
  background-position:center;
  background-size:cover;
}

/* what lies beyond the cloud: the plate's own sky on the living side, void
   on the other. the opening closes over as the page descends into night */
.window__void{
  background:
    linear-gradient(180deg, rgba(214,232,246,.08) 0%, transparent 40%, rgba(180,206,232,.06) 100%),
    linear-gradient(90deg,
      #8b96a4 0%, #808d9d 22%,
      #768495 calc(50% - var(--seam)),
      #6c798b calc(50% - var(--seam) * .75),
      #606c7e calc(50% - var(--seam) * .5),
      #525e70 calc(50% - var(--seam) * .25),
      #445062 50%,
      #364154 calc(50% + var(--seam) * .25),
      #293246 calc(50% + var(--seam) * .5),
      #1d2639 calc(50% + var(--seam) * .75),
      #131b2f calc(50% + var(--seam)),
      #0d1425 80%, #080d1a 100%),
    #05070b;
  opacity:calc(1 - var(--dusk) * .62);
}

.window__stars{
  -webkit-mask-image:linear-gradient(90deg,
    transparent calc(50% - var(--seam)),
    rgba(0,0,0,.10) calc(50% - var(--seam) * .75),
    rgba(0,0,0,.22) calc(50% - var(--seam) * .5),
    rgba(0,0,0,.36) calc(50% - var(--seam) * .25),
    rgba(0,0,0,.5)  50%,
    rgba(0,0,0,.64) calc(50% + var(--seam) * .25),
    rgba(0,0,0,.78) calc(50% + var(--seam) * .5),
    rgba(0,0,0,.90) calc(50% + var(--seam) * .75),
    #000 calc(50% + var(--seam)));
          mask-image:linear-gradient(90deg,
    transparent calc(50% - var(--seam)),
    rgba(0,0,0,.10) calc(50% - var(--seam) * .75),
    rgba(0,0,0,.22) calc(50% - var(--seam) * .5),
    rgba(0,0,0,.36) calc(50% - var(--seam) * .25),
    rgba(0,0,0,.5)  50%,
    rgba(0,0,0,.64) calc(50% + var(--seam) * .25),
    rgba(0,0,0,.78) calc(50% + var(--seam) * .5),
    rgba(0,0,0,.90) calc(50% + var(--seam) * .75),
    #000 calc(50% + var(--seam)));
  opacity:calc(.8 * (1 - var(--dusk) * .62));
  background-image:
    radial-gradient(1.4px 1.4px at 18% 22%, rgba(255,255,255,.9), transparent),
    radial-gradient(1.1px 1.1px at 34% 61%, rgba(255,255,255,.75), transparent),
    radial-gradient(1.6px 1.6px at 52% 14%, rgba(255,255,255,.85), transparent),
    radial-gradient(1.1px 1.1px at 61% 78%, rgba(255,255,255,.7), transparent),
    radial-gradient(1.3px 1.3px at 73% 38%, rgba(255,255,255,.8), transparent),
    radial-gradient(1px 1px     at 83% 66%, rgba(255,255,255,.65), transparent),
    radial-gradient(1.5px 1.5px at 91% 19%, rgba(255,255,255,.85), transparent),
    radial-gradient(1px 1px     at 44% 88%, rgba(255,255,255,.6), transparent),
    radial-gradient(1.2px 1.2px at 67% 8%,  rgba(255,255,255,.7), transparent);
  background-size:100% 100%;
}

/* Thinned copies of the very same field, at the very same scale, so the cloud
   forms inside the opening line up exactly with the ones around it. Cloud
   density falls 100% -> 30% across the mask instead of cutting to bare sky,
   which is what makes the opening read as cloud thinning out. */
.window__wisp{
  background-image:url("assets/field-day-m.jpg");
  opacity:calc(.30 * (1 - var(--dusk) * .62));
}
.window__wisp--night{
  background-image:url("assets/field-night-m.jpg");
  opacity:calc(.46 * (1 - var(--dusk) * .62));
  -webkit-mask-image:linear-gradient(90deg,
    transparent calc(50% - var(--seam)),
    rgba(0,0,0,.10) calc(50% - var(--seam) * .75),
    rgba(0,0,0,.22) calc(50% - var(--seam) * .5),
    rgba(0,0,0,.36) calc(50% - var(--seam) * .25),
    rgba(0,0,0,.5)  50%,
    rgba(0,0,0,.64) calc(50% + var(--seam) * .25),
    rgba(0,0,0,.78) calc(50% + var(--seam) * .5),
    rgba(0,0,0,.90) calc(50% + var(--seam) * .75),
    #000 calc(50% + var(--seam)));
          mask-image:linear-gradient(90deg,
    transparent calc(50% - var(--seam)),
    rgba(0,0,0,.10) calc(50% - var(--seam) * .75),
    rgba(0,0,0,.22) calc(50% - var(--seam) * .5),
    rgba(0,0,0,.36) calc(50% - var(--seam) * .25),
    rgba(0,0,0,.5)  50%,
    rgba(0,0,0,.64) calc(50% + var(--seam) * .25),
    rgba(0,0,0,.78) calc(50% + var(--seam) * .5),
    rgba(0,0,0,.90) calc(50% + var(--seam) * .75),
    #000 calc(50% + var(--seam)));
}

/* ── the procession ──
   Positions, scale, visibility and the eclipse are all custom properties
   written by sky.js. Depth is drawn as scale (--ss, --ms) and as stacking:
   the nearer body is on top, swapped by the `is-sunfront` class.        */

@property --spin{ syntax:'<angle>'; initial-value:0deg; inherits:false; }
@keyframes spin{ to{ --spin:360deg; } }

/* Shafts of light, not wedges. A conic gradient with abrupt stops draws
   spokes with crisp straight sides — which is exactly what gave these away:
   they read as flat geometry laid over the sky. Each one now ramps in and back
   out across a few degrees, so it has no edge at all, and they vary in width
   and strength rather than marching round at even intervals. The mask builds
   and releases over a long span for the same reason: a short one ends every
   shaft at the same radius and the whole thing reads as a wheel. */
.window__rays{
  --s:120vmin;
  inset:auto; top:0; left:0; width:var(--s); height:var(--s);
  background:conic-gradient(from 0deg,
    transparent 0deg,
    transparent 1.6deg,
    rgba(255,245,199,0.15) 5deg,
    transparent 8.4deg,
    transparent 26.1deg,
    rgba(255,242,194,0.065) 28deg,
    transparent 29.9deg,
    transparent 49.9deg,
    rgba(255,244,198,0.13) 53deg,
    transparent 56.1deg,
    transparent 77.3deg,
    rgba(255,242,193,0.05) 79deg,
    transparent 80.7deg,
    transparent 101.4deg,
    rgba(255,244,198,0.14) 105deg,
    transparent 108.6deg,
    transparent 129.0deg,
    rgba(255,242,194,0.07) 131deg,
    transparent 133.0deg,
    transparent 155.0deg,
    rgba(255,244,197,0.12) 158deg,
    transparent 161.0deg,
    transparent 184.2deg,
    rgba(255,242,193,0.055) 186deg,
    transparent 187.8deg,
    transparent 208.5deg,
    rgba(255,245,199,0.15) 212deg,
    transparent 215.5deg,
    transparent 238.1deg,
    rgba(255,242,194,0.065) 240deg,
    transparent 241.9deg,
    transparent 263.8deg,
    rgba(255,244,198,0.13) 267deg,
    transparent 270.2deg,
    transparent 294.3deg,
    rgba(255,242,193,0.05) 296deg,
    transparent 297.7deg,
    transparent 320.6deg,
    rgba(255,244,198,0.14) 324deg,
    transparent 327.4deg,
    transparent 349.0deg,
    rgba(255,242,194,0.07) 351deg,
    transparent 353.0deg,
    transparent 360deg);
  -webkit-mask-image:radial-gradient(circle closest-side,
    transparent 4%, rgba(0,0,0,.3) 12%, rgba(0,0,0,.8) 24%, #000 34%,
    rgba(0,0,0,.7) 50%, rgba(0,0,0,.3) 66%, transparent 84%);
          mask-image:radial-gradient(circle closest-side,
    transparent 4%, rgba(0,0,0,.3) 12%, rgba(0,0,0,.8) 24%, #000 34%,
    rgba(0,0,0,.7) 50%, rgba(0,0,0,.3) 66%, transparent 84%);
  transform:translate3d(calc(var(--sx) - var(--s)/2), calc(var(--sy) - var(--s)/2), 0)
            rotate(var(--spin,0deg)) scale(var(--ss));
  mix-blend-mode:screen;
  opacity:calc((.62 - var(--dusk) * .45) * (1 - var(--side) * .55) * var(--vis) * (1 - var(--ecl) * .85));
  animation:spin 150s linear infinite;
}


.window__sun,
.window__moon{
  --s:var(--body);
  inset:auto; top:0; left:0; width:var(--s); height:var(--s);
  border-radius:50%;
}

/* the sun: a disc with a soft rim, and a glow that spills into its opening */
.window__sun{
  z-index:2;
  background:radial-gradient(circle closest-side,
    #fffdf6 0%, #fffaeb 66%, rgba(255,242,214,.92) 82%, rgba(255,228,176,.4) 92%, transparent 100%);
  transform:translate3d(calc(var(--sx) - var(--s)/2), calc(var(--sy) - var(--s)/2), 0) scale(var(--ss));
  opacity:calc(var(--vis) * (1 - var(--dusk) * .82));
}
/* The sun's near glare. This was .window__sun::before, inside the sun — but
   the sun carries both a transform and an opacity, and either one makes it a
   stacking context, so a blend mode in there could only ever reach the sun's
   own disc. The moon passing behind was never screened by it: it kept a hard
   edge in the brightest part of the glare and read as sliding across the front
   of it. Out here as a sibling it blends with whatever is beneath, so the moon
   washes out in the glare the way something behind it should.

   It takes the sun's z-index, which swaps with the moon's — so on a transit it
   lies over the moon, and during an eclipse it stays under it and leaves the
   silhouette crisp against the corona. */
.window__glare{
  --s:calc(var(--body) * 3.4);
  inset:auto; top:0; left:0; width:var(--s); height:var(--s);
  z-index:2; border-radius:50%;
  background:radial-gradient(circle closest-side,
    rgba(255,252,238,.66) 0%, rgba(255,242,208,.36) 22%, rgba(255,228,176,.15) 44%,
    rgba(255,214,150,.05) 70%, transparent 100%);
  transform:translate3d(calc(var(--sx) - var(--s)/2), calc(var(--sy) - var(--s)/2), 0) scale(var(--ss));
  mix-blend-mode:screen;
  opacity:calc(var(--vis) * (1 - var(--dusk) * .82) * (1 - var(--ecl) * .85));
}
.sky.is-sunfront .window__glare{ z-index:3; }
/* carry it across the line and it cools — as it also does on the way down
   the page */
.window__sun::after{
  content:""; position:absolute; inset:0; border-radius:50%;
  background:radial-gradient(circle closest-side,
    #fff 0%, #f4f8ff 62%, rgba(226,236,252,.7) 84%, transparent 100%);
  opacity:max(var(--side), var(--dusk));
}

/* The moon: an actual photograph of the near side, cropped so the disc exactly
   fills the element — the limb was circle-fitted off the plate (centre
   514.3, 505.6, radius 486.4 in the original) and the crop taken at 98.5% of
   that radius, so the element's own round clip cuts through lunar surface
   rather than through the soft edge of the limb, which would have left a dark
   rim. Everything the gradients were imitating — the maria, the ray systems,
   the cratering, the limb darkening — is in the plate, so none of it is drawn
   here any more. The disc is solid at every phase: by day and when new it
   pales or darkens, but you never see the sky through it. */
.window__moon{
  z-index:3;
  overflow:hidden;
  background-image:url("assets/moon-face.jpg");
  /* A whisper of blur on the limb. Everything else in this sky is photographic
     and soft; a hard vector circle read as cut out and laid on top. Sub-pixel
     at the size the moon draws — enough to take the edge off, not enough to
     cost any surface detail — and in em of --s so it holds at any size. The
     filter runs before the element's own clip, which is what lets it reach
     the limb at all. */
  filter:blur(calc(var(--s) * .008));
  box-shadow:0 0 calc(var(--s) * .3) rgba(190,208,240,calc(.3 * var(--mlit)));
  transform:translate3d(calc(var(--mx) - var(--s)/2), calc(var(--my) - var(--s)/2), 0) scale(var(--ms));
  opacity:var(--mvis);
}
/* by day the disc washes out toward the sky's own tone instead of thinning
   into it. It sits under the unlit face, so a dark limb still reads dark. */
.moon__veil{
  position:absolute; inset:0; border-radius:50%;
  background:radial-gradient(circle closest-side,
    #ccd6e3 0%, #bcc7d8 62%, #aab6c9 100%);
  opacity:calc((1 - var(--mside)) * .52 * (1 - var(--ecl)));
}
/* ── the unlit face ──
   The terminator is the rim of the sphere's own shadow seen side-on, so it
   draws as an ellipse: a straight edge at the quarters, bowing out to meet the
   limb at full and new. --mterm is its half-width. The old version drew a
   circle centred on the limb, which is why the shadow read too small and too
   round through the middle of the cycle.

   Waxing or waning decides how the two pieces combine. Past half lit the
   shadow is a thin crescent — the dark half with the lens cut out of it — and
   short of half lit it is the dark half with the lens added on. Clipping does
   the cutting and a second element does the adding, so neither case needs
   mask compositing. The whole of it is built with the sun off to the right and
   then turned by --mang, which is where the sun actually lies — so the cusps
   sit square across that bearing rather than always at the top and bottom. */
.moon__shade{
  position:absolute; inset:0;
  --grow:1.6;   /* the pieces are drawn this much larger than the disc: see below */
  /* turned so the sun is off to the right of everything drawn inside */
  transform:rotate(var(--mang));
  /* the blur sits on the wrapper so it softens the shadow only once the two
     pieces have combined — on the pieces themselves it would soften nothing,
     since a filter is applied before the element's own clip and mask */
  filter:blur(calc(var(--s) * .052));
  /* Cut after the blur — a filter is applied before an element's own clip, so
     this is what stops the blur bleeding past the disc. Deliberately wider
     than the disc, though: cut at exactly 50% it ran along the same circle as
     the moon's own border-radius, and two separate clips on the same edge
     antialias independently. Wherever the shade's coverage fell a fraction
     short of the photograph's, the lit surface came through as a rim of
     specks. Out at 52% the visible edge is cut once, by the moon, for the
     shade and the photograph together. */
  clip-path:circle(52%);
}
/* Drawn well outside the disc. Sized to the moon's own box they would end
   exactly where it is widest and tallest — the disc is inscribed in that box
   and touches it at four points — and blurring a hard edge sitting on those
   points pulls the shadow back at each of them, which is what squared the
   disc off. Out here the edges are nowhere near it. */
.moon__shade > i{
  position:absolute; display:block;
  inset:calc(50% - 50% * var(--grow));
  /* Opaque. The wrapper used to sit at .95, which let five percent of the lit
     face through everywhere — harmless when the surface was a few soft
     gradients, but the plate has bright ray craters on it and those came
     through as specks. The colour is lifted instead, so the unlit side still
     reads as a body in shadow rather than a hole. */
  background:#10131a;
}
/* the dark half — always the far side from the sun, since the whole shade is
   turned to put the sun at its right */
.moon__shade-half{
  clip-path:inset(0 50% 0 0);
}
/* The lens the terminator encloses. Only within the last sliver of the cycle
   is its edge carried past where the terminator strictly is: --mbias is nil
   until the moon is all but new or all but full, and there the terminator lies
   on the limb itself, where the blur would otherwise straddle it, lose its
   outer half to the disc, and ring the moon with a pale rim. Everywhere else
   the edge is exact and the blur straddles it evenly, as it should. */
.moon__shade-lens{
  -webkit-mask-image:radial-gradient(ellipse calc(var(--mterm) * 50% / var(--grow)) calc(50% / var(--grow)) at 50% 50%,
    #000 0%, #000 calc(100% + var(--mbias) * 1%), transparent calc(100% + var(--mbias) * 1% + 3%));
          mask-image:radial-gradient(ellipse calc(var(--mterm) * 50% / var(--grow)) calc(50% / var(--grow)) at 50% 50%,
    #000 0%, #000 calc(100% + var(--mbias) * 1%), transparent calc(100% + var(--mbias) * 1% + 3%));
}
/* past half lit: the lens is taken out of the dark half instead of added to it */
.sky.is-sunfront .moon__shade-lens{ display:none; }
.sky.is-sunfront .moon__shade-half{
  -webkit-mask-image:radial-gradient(ellipse calc(var(--mterm) * 50% / var(--grow)) calc(50% / var(--grow)) at 50% 50%,
    transparent 0%, transparent calc(100% + var(--mbias) * 1%), #000 calc(100% + var(--mbias) * 1% + 3%));
          mask-image:radial-gradient(ellipse calc(var(--mterm) * 50% / var(--grow)) calc(50% / var(--grow)) at 50% 50%,
    transparent 0%, transparent calc(100% + var(--mbias) * 1%), #000 calc(100% + var(--mbias) * 1% + 3%));
}

/* the nearer body sits on top */
.sky.is-sunfront .window__sun { z-index:3; }
.sky.is-sunfront .window__moon{ z-index:2; }

/* And on a transit the sun does not merely sit on top of the moon, it cuts it:
   the moon is masked by the sun's own disc, so it goes behind a hard edge and
   is bitten away rather than dimmed. The sun's painted rim is soft and the
   whole disc thins as the page darkens, so without this the moon showed
   straight through it. Only while the sun is nearer — during an eclipse it is
   the moon in front and there is nothing to cut. */
.sky.is-sunfront .window__moon{
  /* The cut stops short of the sun's edge on purpose. --occr is the sun's
     geometric radius, but its painted disc is only solid to about 82% of that
     and has faded to nothing by 100% — so cutting the moon at the full radius
     deleted it across a ring the sun was no longer covering, and the dark sky
     showed through as a shadow hugging the sun's rim. Ending the cut at 84–88%
     hands the moon back exactly where the sun starts to give out, and the two
     falloffs cover for each other. */
  -webkit-mask-image:radial-gradient(circle var(--occr) at var(--occx) var(--occy),
    transparent 0%, transparent 84%, #000 88%);
          mask-image:radial-gradient(circle var(--occr) at var(--occx) var(--occy),
    transparent 0%, transparent 84%, #000 88%);
}

/* totality: the corona, a ring of light around the dark moon */
.window__corona{
  --s:calc(var(--body) * 4.2);
  inset:auto; top:0; left:0; width:var(--s); height:var(--s);
  z-index:4;
  /* the moon's limb sits at 23.8% of this box (½ ÷ 2.1); the ring hugs it.
     it is centred on the moon, not the sun: it only shows once the moon has
     covered the disc, and a ring drawn off-centre by the last few pixels of
     approach reads as a mistake rather than an eclipse. */
  background:
    radial-gradient(circle closest-side,
      transparent 0%, transparent 23.5%, #fffdf8 25%, rgba(255,250,238,.9) 27%,
      rgba(255,244,222,.5) 34%, rgba(255,238,210,.22) 48%, rgba(255,236,206,.08) 70%, transparent 100%),
    conic-gradient(from 20deg,
      rgba(255,246,228,.22) 0deg 14deg, transparent 22deg 58deg,
      rgba(255,246,228,.16) 66deg 84deg, transparent 92deg 130deg,
      rgba(255,246,228,.2) 138deg 150deg, transparent 158deg 205deg,
      rgba(255,246,228,.15) 213deg 236deg, transparent 244deg 280deg,
      rgba(255,246,228,.19) 288deg 300deg, transparent 308deg 360deg);
  -webkit-mask-image:radial-gradient(circle closest-side, transparent 23%, #000 26%, rgba(0,0,0,.55) 50%, transparent 100%);
          mask-image:radial-gradient(circle closest-side, transparent 23%, #000 26%, rgba(0,0,0,.55) 50%, transparent 100%);
  transform:translate3d(calc(var(--mx) - var(--s)/2), calc(var(--my) - var(--s)/2), 0) scale(var(--ms));
  mix-blend-mode:screen;
  opacity:calc(var(--tot) * var(--mvis));
}

/* ── the seam ── */
.sky__seam{
  background:linear-gradient(90deg,
    transparent calc(50% - 9vw),
    rgba(255,244,222,.05) calc(50% - 3vw),
    rgba(255,250,236,.16) 50%,
    rgba(186,208,238,.05) calc(50% + 3vw),
    transparent calc(50% + 9vw));
  mix-blend-mode:screen;
  opacity:calc(.9 - var(--dusk) * .55);
}

/* light spilling out of the openings and over the nearby cloud */
.sky__bloom{
  --s:78vmin;
  inset:auto; top:0; left:0; width:var(--s); height:var(--s);
  background:radial-gradient(circle closest-side,
    rgba(255,247,228,.44) 0%, rgba(255,232,190,.23) 24%,
    rgba(255,216,160,.10) 46%, rgba(255,206,146,.035) 64%, transparent 80%);
  transform:translate3d(calc(var(--sx) - var(--s)/2), calc(var(--sy) - var(--s)/2), 0) scale(var(--ss));
  mix-blend-mode:screen;
  opacity:calc(.72 * (1 - var(--dusk) * .6) * (1 - var(--side) * .45) * var(--vis) * (1 - var(--ecl) * .85));
}
.sky__mbloom{
  --s:44vmin;
  inset:auto; top:0; left:0; width:var(--s); height:var(--s);
  background:radial-gradient(circle closest-side,
    rgba(196,212,240,.34) 0%, rgba(180,200,236,.14) 34%, transparent 72%);
  transform:translate3d(calc(var(--mx) - var(--s)/2), calc(var(--my) - var(--s)/2), 0) scale(var(--ms));
  mix-blend-mode:screen;
  opacity:calc((.22 + var(--mside) * .5) * var(--mvis) * var(--mlit) * (1 - var(--mocc)));
}

/* the eclipse: the sky falls dark everywhere but around the corona */
.sky__eclipse{
  background:#070812;
  opacity:calc((var(--ecl) * .22 + var(--tot) * .5) * var(--vis));
  -webkit-mask-image:radial-gradient(circle calc(var(--body) * 4.0 * var(--ms)) at var(--mx) var(--my),
    transparent 0%, rgba(0,0,0,.5) 60%, #000 100%);
          mask-image:radial-gradient(circle calc(var(--body) * 4.0 * var(--ms)) at var(--mx) var(--my),
    transparent 0%, rgba(0,0,0,.5) 60%, #000 100%);
}

.sky__dusk{
  background:linear-gradient(180deg, rgba(5,7,12,.55), rgba(3,4,7,.9));
  opacity:calc(var(--dusk) * .82);
}
.sky__vignette{
  background:radial-gradient(ellipse 120% 90% at 50% 45%, transparent 42%, rgba(0,0,0,.5) 100%);
}
.sky__grain{
  opacity:.15; mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  background-size:140px 140px;
  background-repeat:repeat;
}

/* ═══════════════════ MICRO TYPE ═══════════════════ */

.tag{
  margin:0;
  font-size:.605rem;
  line-height:1.5;
  letter-spacing:.2em;
  text-transform:lowercase;
  color:var(--mid);
  font-weight:400;
}
.tag--dim{ color:var(--dim); }
.tag--ink{ color:rgba(20,22,26,.6); }

/* ═══════════════════ MASTHEAD ═══════════════════ */

.mast{
  position:fixed; top:0; left:0; right:0; z-index:40;
  display:flex; align-items:center; justify-content:space-between; gap:1rem;
  padding:calc(env(safe-area-inset-top) + .8rem) var(--pad) .8rem;
  opacity:0; transform:translateY(-.4rem);
  /* visibility, not just opacity: an opacity:0 header still takes focus, and
     these four links are the first tab stops on the page — a keyboard user
     would otherwise tab into a masthead they cannot see. Delay it so the
     fade-out still plays. */
  visibility:hidden;
  transition:opacity .6s ease, transform .6s ease, visibility 0s linear .6s;
  pointer-events:none;
  background:linear-gradient(180deg, rgba(5,7,11,.94) 0%, rgba(5,7,11,.82) 48%, rgba(5,7,11,0) 100%);
  backdrop-filter:blur(7px) saturate(.85);
  -webkit-backdrop-filter:blur(7px) saturate(.85);
  -webkit-mask-image:linear-gradient(180deg,#000 62%,transparent 100%);
          mask-image:linear-gradient(180deg,#000 62%,transparent 100%);
}
.mast.is-shown{
  opacity:1; transform:none; pointer-events:auto;
  visibility:visible;
  transition:opacity .6s ease, transform .6s ease, visibility 0s;
}

.mast__mark{
  text-decoration:none;
  font-size:.62rem; letter-spacing:.32em; text-transform:uppercase;
  color:rgba(255,255,255,.92);
}
.mast__here{
  font-size:.6rem; letter-spacing:.2em; color:var(--dim);
  transition:opacity .35s ease;
}
.mast__nav{ display:flex; gap:1.1rem; }
.mast__nav a{
  text-decoration:none; font-size:.6rem; letter-spacing:.2em;
  color:var(--dim); transition:color .3s;
}
.mast__nav a:hover{ color:#fff; }

/* Over the pale overcast interlude the fixed chrome flips to ink. */
.mast__mark,.mast__here,.mast__nav a{ transition:color .45s ease; }
.mast.is-ink{
  background:linear-gradient(180deg, rgba(217,214,209,.96) 0%, rgba(217,214,209,.8) 48%, rgba(217,214,209,0) 100%);
}
.mast.is-ink .mast__mark{ color:rgba(16,18,22,.95); }
.mast.is-ink .mast__here,
.mast.is-ink .mast__nav a{ color:rgba(16,18,22,.74); }
.mast.is-ink .mast__nav a:hover{ color:#000; }
/* the default near-white focus ring is invisible on the ash interlude */
.mast.is-ink a:focus-visible{ outline-color:rgba(8,10,14,.9); }

@media (max-width:639px){ .mast__here{ display:none; } }

/* ═══════════════════ LAYOUT ═══════════════════ */

main{ position:relative; z-index:1; }

.chapter{
  position:relative;
  padding-block:clamp(5.5rem, 17vw, 10rem);
}
.chapter::before{                        /* readability scrim */
  content:""; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(180deg, transparent, rgba(6,8,12,.74) 13%,
             rgba(6,8,12,.82) 50%, rgba(6,8,12,.74) 87%, transparent);
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 11%,#000 89%,transparent);
          mask-image:linear-gradient(180deg,transparent,#000 11%,#000 89%,transparent);
}

.grid{
  width:100%; max-width:78rem; margin-inline:auto;
  padding-inline:var(--pad);
  display:grid; gap:2.2rem;
}

.rail{ display:flex; align-items:flex-start; gap:.7rem; }
.dot{
  flex:0 0 auto; width:5px; height:5px; margin-top:.42rem;
  border-radius:50%; background:rgba(255,255,255,.75);
}
.rail .tag{ letter-spacing:.22em; }

.body{ min-width:0; }

/* ═══════════════════ HERO ═══════════════════ */

.hero{
  position:relative;
  min-height:100vh; min-height:100svh;
  display:flex; align-items:flex-end;
  padding:0 var(--pad) calc(env(safe-area-inset-bottom) + var(--bar) + 1.6rem);
}
/* the day half of the field is bright; the wordmark needs ground to stand on */
.hero::before{
  content:""; position:absolute; inset:auto 0 0 0; height:72%;
  z-index:-1; pointer-events:none;
  background:linear-gradient(180deg,
    transparent 0%, rgba(6,8,12,.3) 28%, rgba(6,8,12,.64) 60%, rgba(6,8,12,.82) 100%);
}
/* The day half of the field is pale, and 10px micro-type at 42% white lands
   around 2:1 against it. Hero labels get a brighter ink and a little shadow;
   the deepened scrim above does the rest. */
.hero .tag--dim{ color:rgba(255,255,255,.86); }
.hero .tag,
.hero__sub{ text-shadow:0 1px 10px rgba(4,6,10,.72); }
.hero__floor{
  width:100%; max-width:78rem; margin-inline:auto;
  display:grid; gap:2rem;
}

/* The tail of the italic f hangs below the line box — line-height .84 is
   shorter than this face's own ascent plus descent, so the ink overruns the
   box it is measured in by .174em and was running under the status bar at the
   foot of the page. This is that overrun given back, in em so it holds at
   every size the clamp puts the title at. */
.hero__title{
  margin:.5rem 0 0;
  padding-bottom:.22em;
  font-family:var(--serif); font-weight:300;
  line-height:.84; letter-spacing:-.005em;
  font-size:clamp(4rem, 21vw, 11rem);
  color:#fff;
  text-shadow:0 2px 60px rgba(0,0,0,.5), 0 0 150px rgba(255,232,196,.2);
}
.hero__w{ display:block; }
/* The second line is stepped in far enough to carry the acute on the é clear
   of the y's descender above it. At the old .06em the two overlapped by .15em
   of ink — they were not merely close, they crossed. Widening the step is what
   fixes it without giving up the leading: at this size the tail sweeps down and
   to the left, so the clash only breaks once the é is past the whole letter,
   and .5em is where the clearance stops improving. In em, so it holds at every
   size the clamp puts the title at. */
.hero__w--2{ font-style:italic; padding-left:.5em; color:rgba(255,255,255,.88); }

.hero__sub{
  margin:.55rem 0 1.4rem;
  font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:clamp(1.15rem,5.2vw,1.5rem); line-height:1.25;
  color:var(--mid);
}

/* ═══════════════════ DISPLAY TYPE ═══════════════════ */

.display{
  margin:0 0 1.5rem;
  font-family:var(--serif); font-weight:300;
  font-size:clamp(1.95rem, 7.4vw, 3.9rem);
  line-height:1.09; letter-spacing:.004em;
  color:#fff; max-width:21ch; text-wrap:balance;
}
.lede{
  margin:0 0 3rem;
  font-family:var(--serif); font-style:italic;
  font-size:clamp(1.1rem, 4.2vw, 1.45rem); line-height:1.5;
  color:var(--mid); max-width:32ch;
}
.cols{ display:grid; gap:1.3rem; max-width:58rem; color:var(--mid); }
.cols p{ margin:0; }
.note{
  margin:2.4rem 0 0;
  font-size:.74rem; line-height:1.7; color:var(--dim); max-width:42ch;
}

/* ═══════════════════ FIGURES ═══════════════════ */

.figure{ margin:0 0 2.4rem; }
.figure img{ width:100%; border-radius:1px; filter:saturate(.92) contrast(1.02); }
.figure figcaption{
  display:flex; gap:.7rem; flex-wrap:wrap;
  margin-top:.8rem; padding-top:.7rem;
  border-top:1px solid var(--rule-2);
}
.duo{ display:grid; gap:1.4rem; margin-top:2.4rem; }

/* ═══════════════════ OVERCAST (the clouds close) ═══════════════════ */

.overcast{
  position:relative; z-index:2;
  background:var(--ash);
  color:var(--ink);
  padding:clamp(5rem,16vw,9rem) var(--pad) clamp(5rem,16vw,9rem);
  display:grid; gap:1.6rem; justify-items:start;
  max-width:none;
}
.overcast__line{
  margin:0;
  font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:clamp(1.6rem, 6.6vw, 3.1rem); line-height:1.24;
  color:#15171b; max-width:20ch;
}
.overcast__img{
  width:min(100%, 15rem); margin-top:.6rem;
  border-radius:1px; filter:contrast(1.04);
}

/* ═══════════════════ THE LEDGER ═══════════════════ */

.ledger{ margin-top:.4rem; border-top:1px solid var(--rule); }

.grp{ padding-block:1.5rem; border-bottom:1px solid var(--rule); }
.grp__head{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:1rem; margin-bottom:.4rem;
}
.grp__head h3{
  margin:0;
  font-family:var(--serif); font-weight:300; font-style:italic;
  font-size:1.55rem; line-height:1; color:#fff;
}

.rows{ list-style:none; margin:0; padding:0; }
.rows li{
  display:grid;
  grid-template-columns:2.1rem 1fr auto;
  align-items:baseline;
  gap:.15rem .8rem;
  padding:.85rem 0;
  border-top:1px solid var(--rule-2);
  transition:opacity .4s ease;
}
.rows .n{
  grid-row:1; grid-column:1;
  font-style:normal; font-size:.6rem; letter-spacing:.14em;
  color:var(--dim); font-variant-numeric:tabular-nums;
}
.rows b{
  grid-row:1; grid-column:2;
  font-weight:400; font-size:.98rem; color:rgba(255,255,255,.95);
}
.rows b u{
  text-decoration:none; margin-left:.55rem;
  font-size:.53rem; letter-spacing:.2em; text-transform:uppercase;
  color:rgba(255,224,176,.9); vertical-align:.16em;
}
.rows span{
  grid-row:2; grid-column:2;
  font-size:.775rem; line-height:1.45; color:var(--dim);
}
.rows em{
  grid-row:1 / span 2; grid-column:3;
  align-self:center; font-style:normal; font-size:.83rem;
  font-variant-numeric:tabular-nums; color:var(--mid);
}

/* ═══════════════════ VISIT ═══════════════════ */

.visit{ display:grid; gap:2.8rem; }
.visit .tag{ margin-bottom:1rem; }
.hours{ margin:0; border-top:1px solid var(--rule-2); }
.hours > div{
  display:flex; justify-content:space-between; gap:1rem;
  padding:.75rem 0; border-bottom:1px solid var(--rule-2);
}
.hours dt{ color:var(--mid); font-size:.88rem; }
.hours dd{
  margin:0; color:#fff; font-size:.88rem;
  font-variant-numeric:tabular-nums; white-space:nowrap;
}
address{ font-style:normal; line-height:1.9; color:var(--mid); font-size:.92rem; }
address a{ text-decoration:none; border-bottom:1px solid rgba(255,255,255,.22); transition:border-color .3s; }
address a:hover{ border-color:#fff; }

/* ═══════════════════ END ═══════════════════ */

.end{
  position:relative; z-index:1;
  min-height:92svh;
  display:grid; place-items:center;
  text-align:center;
  padding:6rem var(--pad) calc(var(--bar) + 5rem);
  overflow:hidden;
}
/* The plate at the foot of the page. All of it lives in the photograph's own
   coordinates: the viewBox is the plate's intrinsic size and "slice" is what
   object-fit:cover is, so the disc behind its moon and the vignette that
   feathers the plate into the page are both cropped and scaled exactly as the
   image is, and hold their place at every viewport. In CSS they could not —
   the vignette was measured against the section, so on a wide screen it cut
   across the moon and let the backing through unevenly, and a disc placed
   that way drifted off the moon as cover reframed the shot.

   The plate is half transparent so it settles into the page, which is what
   left the sky moving behind its moon — the one thing here that has to read
   as solid. The disc is what stops that. It is not black: the photograph sits
   over it at half strength, so what you see is half of this, and the moon
   comes out a dark grey rather than a hole cut in the page. */
.end__plate{
  position:absolute; inset:0; width:100%; height:100%;
}
.end__moon{ fill:#171c26; }
.end__inner{ position:relative; display:grid; gap:.5rem; justify-items:center; }
.end__cap{ margin-top:2rem; }
.end__line{
  margin:0;
  font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:clamp(1.45rem, 6.2vw, 2.8rem); line-height:1.3;
  color:rgba(255,255,255,.92);
}
/* the second line steps down from the first but stays well above the caption
   below it, and goes to full white rather than the dimmed grey it was */
.end__line--2{
  color:#fff;
  font-size:clamp(1.1rem, 4.5vw, 2rem);
}

/* ═══════════════════ FOOT ═══════════════════ */

.foot{
  position:relative; z-index:1;
  background:#05060a;
  border-top:1px solid var(--rule-2);
  padding:2.6rem var(--pad) calc(env(safe-area-inset-bottom) + var(--bar) + 2rem);
  display:grid; gap:1.6rem;
}
.foot__row{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:1rem; flex-wrap:wrap;
}
.foot__row--fine{ padding-top:1.4rem; border-top:1px solid var(--rule-2); }
.foot__mark{
  margin:0; font-family:var(--serif); font-size:1.5rem; font-weight:300; color:#fff;
}
.foot__nav{ display:flex; gap:1.2rem; flex-wrap:wrap; }
.foot__nav a{
  text-decoration:none; font-size:.6rem; letter-spacing:.2em;
  color:var(--dim); transition:color .3s;
}
.foot__nav a:hover{ color:#fff; }

/* the social marks sit in the same row and take the same colour and hover as
   the text links beside them — stroke:currentColor is what carries it */
.foot__social{ gap:.9rem; }
.foot__social a{ display:inline-flex; }
.foot__social svg{
  width:16px; height:16px; display:block;
  fill:none; stroke:currentColor; stroke-width:1.5;
  stroke-linecap:round; stroke-linejoin:round;
}
.foot__social .dot{ fill:currentColor; stroke:none; }

/* ═══════════════════ STATUS BAR ═══════════════════ */

.status{
  position:fixed; left:0; right:0; bottom:0; z-index:40;
  height:calc(var(--bar) + env(safe-area-inset-bottom));
  padding:0 var(--pad) env(safe-area-inset-bottom);
  display:flex; align-items:center; justify-content:space-between; gap:.8rem;
  border-top:1px solid var(--rule-2);
  background:rgba(5,6,10,.55);
  backdrop-filter:blur(10px) saturate(.9);
  -webkit-backdrop-filter:blur(10px) saturate(.9);
  pointer-events:none;
}
.status__i{
  font-size:.575rem; letter-spacing:.2em; color:var(--dim);
  font-variant-numeric:tabular-nums; white-space:nowrap;
}
.status__i--c{ color:rgba(255,255,255,.78); }
.status[data-phase="day"]   .status__i--c{ color:#ffe9c4; }
.status[data-phase="grey"]  .status__i--c{ color:#e2e2e2; }
.status[data-phase="night"] .status__i--c{ color:#bcd0ea; }

.status,.status__i{ transition:background .45s ease, color .45s ease, border-color .45s ease; }
.status.is-ink{
  background:rgba(214,211,206,.8);
  border-top-color:rgba(0,0,0,.14);
}
.status.is-ink .status__i{ color:rgba(16,18,22,.74); }
.status.is-ink .status__i--c{ color:rgba(16,18,22,.92); }

/* ═══════════════════ REVEALS ═══════════════════ */

.reveal{
  opacity:0; transform:translateY(1.5rem);
  /* An eased-out curve this steep is ~60% done in its first fifth of a second,
     which lands as a pop however long the duration says it is. This one carries
     its weight through the middle instead. */
  transition:opacity 1.15s cubic-bezier(.38,.06,.3,1),
             transform 1.15s cubic-bezier(.38,.06,.3,1);
}
.reveal.is-in{ opacity:1; transform:none; }

/* The wipe must NOT clip in its resting state: IntersectionObserver
   measures the post-clip box, so a clipped-to-nothing heading has zero
   area, never "intersects", and would never be revealed. Keep the
   pre-state a plain opacity:0 and let a keyframe do the clipping. */
.wipe{ opacity:0; }
.wipe.is-in{
  opacity:1;
  animation:wipeIn 1.15s cubic-bezier(.22,.7,.2,1) both;
}
@keyframes wipeIn{
  from{ clip-path:inset(0 0 102% 0); transform:translateY(.6rem); opacity:0; }
  to  { clip-path:inset(0 0 -6% 0);  transform:none;              opacity:1; }
}

/* ═══════════════════ ≥ 640px ═══════════════════ */

@media (min-width:640px){
  body{ font-size:16px; }
  .hero__floor{
    grid-template-columns:1fr auto;
    align-items:end; gap:2.5rem;
  }
  .hero__r{ text-align:right; padding-bottom:.7rem; }
  .hero__sub{ margin-bottom:1.1rem; }
  .visit{ grid-template-columns:1fr 1fr; gap:3.5rem; }
  .duo{ grid-template-columns:1.45fr 1fr; align-items:end; }
  .rows li{ grid-template-columns:2.4rem minmax(9rem,14rem) 1fr auto; gap:.9rem 1.2rem; }
  .rows b{ grid-row:1; grid-column:2; }
  .rows span{ grid-row:1; grid-column:3; }
  .rows em{ grid-row:1; grid-column:4; }
}

/* ═══════════════════ ≥ 800px ═══════════════════ */

@media (min-width:800px){
  .field,
  .window__wisp       { background-image:url("assets/field-day-d.jpg"); }
  .field--night,
  .window__wisp--night{ background-image:url("assets/field-night-d.jpg"); }
  .sky__stars-in{
    -webkit-mask-image:url("assets/field-gaps-d.jpg");
            mask-image:url("assets/field-gaps-d.jpg");
  }

  .grid{ grid-template-columns:11rem 1fr; gap:3rem; }
  .rail{
    position:sticky; top:5.5rem;
    align-self:start;
  }
  .cols{ grid-template-columns:1fr 1fr; gap:2.4rem; }
  .figure--bleed img{ max-height:76vh; object-fit:cover; }

  .overcast{
    grid-template-columns:1fr auto;
    align-items:end;
    column-gap:3rem;
    padding-inline:clamp(3rem,7vw,7rem);
  }
  .overcast .tag--ink:first-child{ grid-column:1 / -1; }
  .overcast__line{ grid-column:1; }
  .overcast__img{ grid-column:2; grid-row:2 / span 2; width:16rem; margin:0; }
}

@media (min-width:1100px){
  .chapter{ padding-block:10.5rem; }
  .display{ font-size:clamp(2.5rem, 4.1vw, 4.2rem); }
  .grid{ grid-template-columns:13rem 1fr; gap:4rem; }
}

/* ═══════════════════ REDUCED MOTION ═══════════════════ */

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .reveal{ opacity:1; transform:none; }
  .wipe{ opacity:1; clip-path:none; transform:none; }
  .window__rays{ display:none; }
  /* the procession holds still; the window's mask can stop being live */
  .window{ will-change:auto; }
}
