/* ------------------------------------------------------------------
   schematk. — thesis page

   Loaded alongside /styles.css, which supplies the stage, ambient field,
   footer, tokens and keyframes. This file styles the thesis layout, the
   eclipse mark above it, and the home link on the wordmark, so
   /styles.css and the landing page stay untouched.
   ------------------------------------------------------------------ */

/* Let the page scroll on short or narrow screens. */
html, body { overflow: auto; }

.stage {
  position: relative;
  height: auto;
  min-height: 100vh;
  min-height: 100dvh;
  row-gap: 56px;
}

/* ---------- Field: near-black, one low ember horizon ---------------- */

.is-horizon .neb--blue,
.is-horizon .neb--silver { display: none; }

/* The horizon drifts sideways, rises and settles, and breathes, while
   its centre wanders (sk-neb-c2 from /styles.css) so it changes shape.
   It stays low on the page throughout. */
.is-horizon .neb--ember {
  left: 10%;
  right: auto;
  width: 80%;
  bottom: -38%;
  height: 70%;
  opacity: .55;
  animation:
    th-horizon 38s var(--ease-drift) infinite,
    sk-neb-c2 29s var(--ease-drift) infinite;
}

@keyframes th-horizon {
  0%, 100% { opacity: .5;  transform: translate3d(0, 0, 0) scale(1);        }
  30%      { opacity: .72; transform: translate3d(9%, -4%, 0) scale(1.08);  }
  65%      { opacity: .58; transform: translate3d(-8%, -1.5%, 0) scale(1.03); }
}

.is-horizon .grain { opacity: .22; }

/* ---------- Aurora: a hint of it, rising out of the horizon ----------
   Curtains after the northern lights, sunk mostly below the bottom of
   the page so only their soft upper edges show: the glow reads as the
   top of an aurora just coming into view. Colours are the home page's
   nebula gradients: ember at the foot, silver through the body, slate
   blue at the top. Each curtain carries a few soft vertical rays,
   and slowly sways, leans, rises and breathes at its own pace.
   Everything animates transform and opacity only, so it stays smooth.
   ------------------------------------------------------------------ */

.aurora {
  position: absolute;
  inset: 0;
  overflow: hidden;
  animation: sk-in 6000ms var(--ease-out) 600ms both;
}

.aurora__band {
  position: absolute;
  transform-origin: 50% 100%;
  mix-blend-mode: screen;
  isolation: isolate;
  filter: blur(26px);
  overflow: hidden;
  background: linear-gradient(to top,
    rgba(214, 112, 70, .95)  0%,
    rgba(194, 96, 58, .7)    24%,
    rgba(132, 146, 156, .45) 52%,
    rgba(74, 110, 142, .32)  76%,
    rgba(61, 90, 115, 0)     100%);
  /* Arched: tallest in the middle, falling away at the ends. */
  -webkit-mask-image: radial-gradient(ellipse 50% 100% at 50% 100%, #000 30%, rgba(0, 0, 0, .5) 62%, transparent 100%);
          mask-image: radial-gradient(ellipse 50% 100% at 50% 100%, #000 30%, rgba(0, 0, 0, .5) 62%, transparent 100%);
}

/* With the pointer: the curtains lean a little, the middle one the
   other way, and the flares a little more, as if nearer. */
.aurora__band    { translate: calc(var(--px) * 12px)  calc(var(--py) * 4px); }
.aurora__band--2 { translate: calc(var(--px) * -9px)  calc(var(--py) * 3px); }
.aurora__flare   { translate: calc(var(--px) * 18px)  calc(var(--py) * 6px); }

/* A few soft rays: two wide, faint stripe patterns. */
.aurora__rays {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -20%;
  width: 140%;
  background:
    repeating-linear-gradient(90deg,
      rgba(8, 9, 11, 0)   0px,
      rgba(8, 9, 11, 0)   70px,
      rgba(8, 9, 11, .32) 110px,
      rgba(8, 9, 11, 0)   150px,
      rgba(8, 9, 11, 0)   190px),
    repeating-linear-gradient(90deg,
      rgba(8, 9, 11, 0)   0px,
      rgba(8, 9, 11, .2)  60px,
      rgba(8, 9, 11, 0)   130px,
      rgba(8, 9, 11, 0)   260px);
  animation: au-rays 44s var(--ease-drift) infinite alternate;
}

/* Sunk below the page edge, so only the upper part of each shows. */
.aurora__band--1 {
  left: 4%;
  width: 70%;
  bottom: -20%;
  height: 46%;
  animation: au-fold-1 52s var(--ease-drift) infinite;
}

.aurora__band--2 {
  left: 34%;
  width: 66%;
  bottom: -18%;
  height: 40%;
  animation: au-fold-2 71s var(--ease-drift) infinite;
}
.aurora__band--2 {
  background: linear-gradient(to top,
    rgba(96, 136, 172, .9)   0%,
    rgba(74, 110, 142, .66)  30%,
    rgba(132, 146, 156, .34) 60%,
    rgba(61, 90, 115, 0)     100%);
}
.aurora__band--2 .aurora__rays { animation-duration: 58s; animation-direction: alternate-reverse; }

.aurora__band--3 {
  left: 16%;
  width: 62%;
  bottom: -24%;
  height: 42%;
  animation: au-fold-3 39s var(--ease-drift) infinite;
}
.aurora__band--3 .aurora__rays { animation-duration: 33s; }

@keyframes au-rays {
  from { transform: translate3d(-3%, 0, 0); }
  to   { transform: translate3d(3%, 0, 0); }
}

/* Gentle: a slow sway, a slight lean, a little rise and fall. */
@keyframes au-fold-1 {
  0%, 100% { opacity: .4;  transform: translate3d(-4%, 0, 0) skewX(-6deg) scaleY(.92); }
  35%      { opacity: .75; transform: translate3d(3%, 0, 0)  skewX(3deg)  scaleY(1.12); }
  70%      { opacity: .55; transform: translate3d(5%, 0, 0)  skewX(6deg)  scaleY(1); }
}

@keyframes au-fold-2 {
  0%, 100% { opacity: .3;  transform: translate3d(4%, 0, 0)  skewX(5deg)  scaleY(.95); }
  50%      { opacity: .65; transform: translate3d(-5%, 0, 0) skewX(-5deg) scaleY(1.15); }
}

@keyframes au-fold-3 {
  0%, 100% { opacity: .35; transform: translate3d(0, 0, 0)   skewX(4deg)  scaleY(.95); }
  50%      { opacity: .6;  transform: translate3d(-4%, 0, 0) skewX(-4deg) scaleY(1.1); }
}

/* Flares: narrower swells that brighten, rise and fade on long cycles
   that never line up, so the light moves along the horizon in patches.
   Negative delays start each one partway through its cycle. */
.aurora__flare {
  position: absolute;
  bottom: -14%;
  transform-origin: 50% 100%;
  mix-blend-mode: screen;
  filter: blur(30px);
  opacity: 0;
  background: linear-gradient(to top,
    rgba(222, 120, 76, .95)  0%,
    rgba(194, 96, 58, .6)    34%,
    rgba(132, 146, 156, .26) 64%,
    rgba(132, 146, 156, 0)   100%);
  -webkit-mask-image: radial-gradient(ellipse 50% 100% at 50% 100%, #000 25%, transparent 100%);
          mask-image: radial-gradient(ellipse 50% 100% at 50% 100%, #000 25%, transparent 100%);
  animation: au-flare 46s var(--ease-drift) infinite;
}

.aurora__flare--1 { left: 6%;  width: 22%; height: 34%; animation-duration: 41s; animation-delay: -6s;  }
.aurora__flare--2 { left: 28%; width: 18%; height: 40%; animation-duration: 53s; animation-delay: -31s; }
.aurora__flare--3 { left: 47%; width: 24%; height: 30%; animation-duration: 37s; animation-delay: -19s; }
.aurora__flare--4 { left: 64%; width: 20%; height: 38%; animation-duration: 59s; animation-delay: -44s; }
.aurora__flare--5 { left: 80%; width: 18%; height: 32%; animation-duration: 47s; animation-delay: -12s; }

/* Slate blue swells. */
.aurora__flare--2,
.aurora__flare--4 {
  background: linear-gradient(to top,
    rgba(104, 144, 182, .95) 0%,
    rgba(74, 110, 142, .62)  36%,
    rgba(61, 90, 115, .24)   66%,
    rgba(61, 90, 115, 0)     100%);
}

/* A silver swell. */
.aurora__flare--3 {
  background: linear-gradient(to top,
    rgba(170, 182, 192, .8)  0%,
    rgba(132, 146, 156, .5)  38%,
    rgba(120, 132, 140, .18) 66%,
    rgba(120, 132, 140, 0)   100%);
}

@keyframes au-flare {
  0%, 100% { opacity: 0;   transform: translate3d(0, 0, 0)   skewX(0deg)  scaleY(.7); }
  18%      { opacity: .7;  transform: translate3d(1%, 0, 0)  skewX(-4deg) scaleY(1.15); }
  34%      { opacity: .4;  transform: translate3d(2%, 0, 0)  skewX(3deg)  scaleY(1.05); }
  52%      { opacity: 0;   transform: translate3d(3%, 0, 0)  skewX(5deg)  scaleY(.85); }
}

/* ---------- Thesis text --------------------------------------------- */

.thesis {
  position: relative;
  align-self: center;
  justify-self: center;
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: 440px;
  --ease-text: cubic-bezier(.33, 0, .2, 1);   /* soft start, soft finish */
}

.thesis__lede {
  margin: 0;
  font-size: 19px;
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: -.015em;
  color: var(--paper);
  animation: th-rise 2600ms var(--ease-text) 1200ms both;
}

.thesis p {
  margin: 0;
  font-size: 16px;
  line-height: 1.6;
  letter-spacing: -.01em;
  color: rgba(250, 249, 245, .5);
  animation: th-rise 2600ms var(--ease-text) 2100ms both;
}

.thesis .thesis__sk { animation-delay: 2700ms; }

/* The page arrives slowly: the eclipse fades in first, then the text,
   each line rising slightly and following the last. */
@keyframes th-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes th-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------------
   Total solar eclipse, coloured as it looks to the eye at totality:
     moon        — pure black, a touch darker than the sky
     corona      — pearly white: faintly cream at the limb, cooling to a
                   silvery blue-white further out, in uneven streamers
     prominences — small pink-red points on the limb (hydrogen-alpha)
     diamond ring — a brief, brilliant white bead of sunlight
   The disc is 34px; the corona spills well past it without affecting
   layout. Motion is slow: streamers sway and breathe, prominences
   pulse, and a soft diamond ring glints now and then.
   ------------------------------------------------------------------ */

.ec {
  --ec-d: 34px;
  position: relative;
  display: block;
  width: var(--ec-d);
  height: var(--ec-d);
  margin: 26px 0 34px 26px;   /* room for the corona to breathe */
  animation: th-fade 3200ms var(--ease-text) 200ms both;
}

.ec > span {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}

/* Inner corona: brightest right at the limb and falling away from it,
   so the light reads as wrapping round the moon. This layer is 3.2
   discs wide, so the limb sits at ~31% of its radius. */
.ec__glow {
  inset: -110%;
  mix-blend-mode: screen;
  background: radial-gradient(circle closest-side,
    rgba(255, 252, 245, 1)   0%,
    rgba(255, 252, 245, 1)   30.5%,
    rgba(255, 251, 243, .78) 32%,
    rgba(250, 248, 244, .5)  34.5%,
    rgba(238, 243, 251, .26) 39%,
    rgba(226, 236, 250, .11) 47%,
    rgba(220, 232, 250, .04) 56%,
    rgba(220, 232, 250, 0)   68%);
  animation: ec-breathe 9s var(--ease-drift) infinite;
}

/* Outer corona: uneven streamers, faded out from the limb. */
.ec__rays {
  inset: -200%;
  background: conic-gradient(from 0deg,
    rgba(240, 245, 255, 0)   0deg,
    rgba(240, 245, 255, .9)  13deg,
    rgba(240, 245, 255, 0)   22deg,
    rgba(240, 245, 255, 0)   46deg,
    rgba(240, 245, 255, .45) 53deg,
    rgba(240, 245, 255, 0)   60deg,
    rgba(240, 245, 255, 0)   84deg,
    rgba(240, 245, 255, 1)   97deg,
    rgba(240, 245, 255, 0)   112deg,
    rgba(240, 245, 255, 0)   166deg,
    rgba(240, 245, 255, .6)  177deg,
    rgba(240, 245, 255, 0)   188deg,
    rgba(240, 245, 255, 0)   244deg,
    rgba(240, 245, 255, .95) 262deg,
    rgba(240, 245, 255, 0)   280deg,
    rgba(240, 245, 255, 0)   306deg,
    rgba(240, 245, 255, .7)  318deg,
    rgba(240, 245, 255, 0)   330deg,
    rgba(240, 245, 255, 0)   360deg);
  -webkit-mask-image: radial-gradient(circle closest-side, transparent 18%, #000 20.5%, rgba(0, 0, 0, .5) 30%, rgba(0, 0, 0, .12) 50%, transparent 74%);
          mask-image: radial-gradient(circle closest-side, transparent 18%, #000 20.5%, rgba(0, 0, 0, .5) 30%, rgba(0, 0, 0, .12) 50%, transparent 74%);
  filter: blur(1.2px);
  mix-blend-mode: screen;
  animation: ec-sway 20s var(--ease-drift) infinite;
}

/* The corona shifts a hair against the pointer, the outer streamers
   most, so the eclipse feels set back from the field in front of it. */
.ec__glow   { translate: calc(var(--px) * -1px)   calc(var(--py) * -1px); }
.ec__rays   { translate: calc(var(--px) * -2.5px) calc(var(--py) * -2.5px); }

/* A second, finer set of streamers, swaying against the first. */
.ec__rays--b {
  inset: -160%;
  background: conic-gradient(from 40deg,
    rgba(255, 250, 240, 0)   0deg,
    rgba(255, 250, 240, .5)  10deg,
    rgba(255, 250, 240, 0)   22deg,
    rgba(255, 250, 240, 0)   80deg,
    rgba(255, 250, 240, .45) 92deg,
    rgba(255, 250, 240, 0)   108deg,
    rgba(255, 250, 240, 0)   200deg,
    rgba(255, 250, 240, .55) 214deg,
    rgba(255, 250, 240, 0)   232deg,
    rgba(255, 250, 240, .3)  300deg,
    rgba(255, 250, 240, 0)   316deg,
    rgba(255, 250, 240, 0)   360deg);
  -webkit-mask-image: radial-gradient(circle closest-side, transparent 22%, #000 25%, rgba(0, 0, 0, .3) 40%, transparent 66%);
          mask-image: radial-gradient(circle closest-side, transparent 22%, #000 25%, rgba(0, 0, 0, .3) 40%, transparent 66%);
  filter: blur(.8px);
  mix-blend-mode: screen;
  animation: ec-sway-b 15s var(--ease-drift) infinite;
  translate: calc(var(--px) * -1.5px) calc(var(--py) * -1.5px);
}

/* Prominences: small pink-red points sitting on the limb. */
.ec__prom {
  inset: -20%;
  background:
    radial-gradient(circle at 16.0% 39.0%, rgba(255, 92, 122, 0.95) 0%, rgba(240, 70, 110, 0) 5.0%),
    radial-gradient(circle at 26.1% 76.5%, rgba(255, 92, 122, 0.8) 0%, rgba(240, 70, 110, 0) 3.6%),
    radial-gradient(circle at 83.1% 36.6%, rgba(255, 92, 122, 0.7) 0%, rgba(240, 70, 110, 0) 2.8%);
  filter: blur(.5px);
  animation: ec-prom 7s var(--ease-drift) infinite;
}

/* The moon. No hard ring at the limb: a fine, soft edge of light and
   a wider faint one, scaled to the disc. Grain sits on its face, as
   the design system asks of objects. */
.ec__moon {
  inset: 0;
  background: radial-gradient(circle at 50% 50%, #020203 0%, #040405 92%, #0A0B0E 100%);
  box-shadow:
    0 0 max(calc(var(--ec-d) * .012), .6px) calc(var(--ec-d) * .002) rgba(255, 251, 242, .55),
    0 0 max(calc(var(--ec-d) * .05), 3px) rgba(255, 248, 236, .22);
}

.ec__moon::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  /* The grain image is faint white speckle (~6% opaque on average), so
     it is used at full strength: enough texture, still reads as black. */
  background: url("/assets/grain-light.png") 0 0 / 90px 90px repeat;
}

/* Diamond ring: a brilliant bead at the upper right, flashing briefly. */
.ec__bead {
  inset: -20%;
  background:
    radial-gradient(circle at 73.9% 23.5%, rgba(255, 255, 255, .9) 0%, rgba(255, 252, 244, .6) 3%, rgba(255, 252, 240, .22) 7%, rgba(255, 252, 240, 0) 15%);
  opacity: 0;
  animation: ec-bead 22s var(--ease-drift) infinite;
}

@keyframes ec-breathe {
  0%, 100% { opacity: .8;  transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.07); }
}

@keyframes ec-sway {
  0%, 100% { transform: rotate(0deg);   opacity: .8; }
  50%      { transform: rotate(12deg);  opacity: 1; }
}

@keyframes ec-sway-b {
  0%, 100% { transform: rotate(0deg);    opacity: .95; }
  50%      { transform: rotate(-15deg);  opacity: .55; }
}

@keyframes ec-prom {
  0%, 100% { opacity: .75; }
  50%      { opacity: 1; }
}

@keyframes ec-bead {
  0%, 70%, 100% { opacity: 0; }
  79%           { opacity: .6; }
  90%           { opacity: 0; }
}

/* ---------- Wordmark links home ------------------------------------- */

.wordmark-link {
  display: block;
  border: 0;
  border-radius: 2px;
  outline: none;
}

.wordmark-link:focus-visible {
  outline: 2px solid var(--paper);
  outline-offset: 6px;
}
