/* Optional atmosphere: Babylon painting behind the hero, embers, gentle motion.
   Everything here is switched off for people who ask their device for reduced motion. */

html { overflow-x: hidden; }
body.fx {
  position: relative; overflow-x: clip;
  /* The colour journey: ember-lit at the top, through wine and plum, to pitch black at the bottom */
  background: linear-gradient(180deg,
    var(--bg) 0, var(--bg) max(118vh, 820px), #2c0d12 42%, #220a1c 56%, #160818 70%, #0b0510 84%, #030204 94%, #000 100%);
}
body.fx::before, body.fx::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 118vh; min-height: 820px;
  pointer-events: none; z-index: -2;
}
body.fx::before {
  background: url("../images/art/babylon.webp") 60% 30% / cover no-repeat;
  animation: fx-drift 45s ease-in-out infinite alternate;
  -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 92%);
          mask-image: linear-gradient(180deg, #000 55%, transparent 92%);
  transform-origin: 70% 30%;
}
body.fx::after {
  z-index: -1;

  background:
    linear-gradient(90deg, rgba(18,7,8,.92) 0%, rgba(18,7,8,.78) 40%, rgba(18,7,8,.35) 72%, rgba(18,7,8,.55) 100%),
    linear-gradient(180deg, rgba(18,7,8,.5) 0%, rgba(18,7,8,0) 25%, rgba(18,7,8,.15) 65%, var(--bg) 100%);
}
body.fx > main, body.fx > header, body.fx > footer { position: relative; z-index: 1; }
@keyframes fx-drift { from { transform: scale(1.04); } to { transform: scale(1.12) translate(-1.5%, -1%); } }

.fx-embers { position: absolute; left: 0; top: 0; width: 100%; height: 100vh; pointer-events: none; z-index: 2; }
body.fx footer { background: transparent; }

/* Hero arrives in a gentle sequence on load */
.js body.fx .hero-head > *, .js body.fx .hero-book, .js body.fx .hero-body > * {
  opacity: 0; transform: translateY(14px);
  animation: fx-in 1.1s cubic-bezier(.2,.7,.1,1) forwards;
}
.js body.fx .hero-head .kicker { animation-delay: .1s; }
.js body.fx .hero-head h1 { animation-delay: .25s; }
.js body.fx .hero-book { animation-delay: .45s; }
.js body.fx .hero-body .blurb { animation-delay: .6s; }
.js body.fx .hero-body .preorder { animation-delay: .75s; }
@keyframes fx-in { to { opacity: 1; transform: none; } }

/* The book floats, and leans a little towards the pointer */
body.fx .hero-book { perspective: 1200px; }
body.fx .hero-book .tilt { transition: transform .4s ease-out; transform-style: preserve-3d; }
body.fx .hero-book .tilt { animation: fx-float 7s ease-in-out infinite; }
body.fx .hero-book img { filter: drop-shadow(0 34px 44px rgba(0,0,0,.7)) drop-shadow(0 0 50px rgba(134,9,18,.3)); }
@keyframes fx-float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -10px; } }

/* The star-eye turns slowly when you hover the name */
body.fx .topbar .mark { transition: transform 1.2s cubic-bezier(.2,.7,.1,1); }


/* Role cards lift slightly on hover */
body.fx .role { transition: transform .5s ease; }
body.fx .role:hover { transform: translateY(-4px); }

@media (max-width: 860px) {
  body.fx::after {
    background: linear-gradient(180deg, rgba(18,7,8,.72) 0%, rgba(18,7,8,.5) 35%, rgba(18,7,8,.85) 75%, var(--bg) 100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  body.fx::before, body.fx .hero-book .tilt { animation: none; }
  .js body.fx .hero-head > *, .js body.fx .hero-book, .js body.fx .hero-body > * { animation: none; opacity: 1; transform: none; }
  .fx-embers { display: none; }
}

/* ---------- Small touches ---------- */

/* The header eye blinks now and then */
body.fx .topbar .mark { width: 58px; height: 58px; margin: -12px 0; }
body.fx .topbar .name { align-items: center; }
body.fx .topbar .name { gap: 14px; }
@media (max-width: 480px) { body.fx .topbar .mark { width: 44px; height: 44px; margin: -8px 0; } }
body.fx svg .eye { transform-origin: 32px 32px; animation: fx-blink 6s ease-in-out infinite; }
body.fx .ornament svg .eye { animation: none; transform-box: view-box; transform-origin: 32px 32px; }
@keyframes fx-blink {
  0%, 86%, 100% { transform: scaleY(1); }
  89% { transform: scaleY(.06); }
  92% { transform: scaleY(1); }
  94.5% { transform: scaleY(.06); }
  97% { transform: scaleY(1); }
}

/* Star-eye ornaments between sections, with a fine line either side */
.ornament {
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter);
  display: flex; align-items: center; gap: 18px;
}
.ornament::before, .ornament::after { content: ""; flex: 1; height: 1px; background: var(--cream-20); }
.ornament svg { width: 64px; height: 64px; opacity: .85; flex: none; }
body.fx .roles, body.fx .about { border-top: 0; }

/* Opening the chapter: paragraphs arrive one after another */
body.fx .reader[open] .excerpt-text { animation: none; }
body.fx .reader[open] .excerpt-text p, body.fx .reader[open] .excerpt-end { opacity: 0; animation: fx-in .9s ease forwards; }
body.fx .reader[open] .excerpt-text p:nth-child(2) { animation-delay: .12s; }
body.fx .reader[open] .excerpt-text p:nth-child(3) { animation-delay: .24s; }
body.fx .reader[open] .excerpt-text p:nth-child(4) { animation-delay: .36s; }
body.fx .reader[open] .excerpt-text p:nth-child(5) { animation-delay: .48s; }
body.fx .reader[open] .excerpt-text p:nth-child(6) { animation-delay: .6s; }
body.fx .reader[open] .excerpt-text p:nth-child(7) { animation-delay: .72s; }
body.fx .reader[open] .excerpt-text p:nth-child(8) { animation-delay: .84s; }
body.fx .reader[open] .excerpt-end { animation-delay: 1s; }

/* Thank-you card fades up gently */
body.fx .thanks.open .card { animation: fx-in .7s ease both; }

@media (prefers-reduced-motion: reduce) {
  body.fx svg .eye, body.fx .reader[open] .excerpt-text p, body.fx .reader[open] .excerpt-end, body.fx .thanks.open .card { animation: none; opacity: 1; }
}

@media (max-width: 480px) { .ornament svg { width: 52px; height: 52px; } }

/* The divider eye watches the cursor, and blinks when you touch it */
.ornament svg { cursor: default; overflow: visible; }
.ornament svg .iris { transition: transform .25s ease-out; }
@keyframes fx-blink-once { 0%, 100% { transform: scaleY(1); } 45% { transform: scaleY(.06); } }
@media (prefers-reduced-motion: reduce) { .ornament svg .iris { transition: none; } }

/* The eye on the cover blinks too (a painted lid closes over it); driven by fx.js */
.hero-book .tilt { position: relative; display: block; }
.cover-lid { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

/* ---------- About: the portrait, no frame, its edges dissolving into the dark ---------- */
.portrait .photo { max-width: 500px; margin: 0 auto; }
.portrait .photo img {
  display: block; width: 100%; height: auto; max-width: none; filter: none;
  aspect-ratio: 1 / 1; object-fit: cover; object-position: 50% 52%; border-radius: 50%;
  box-shadow: 0 30px 70px rgba(0, 0, 0, .55);
}
@media (max-width: 860px) { .portrait .photo { max-width: 320px; } }
/* she emerges slowly from the dark when the section comes into view */
.js body.fx .about .portrait .photo { opacity: 0; filter: brightness(.15); transition: opacity 1.6s ease, filter 2.4s ease .2s; }
.js body.fx .about.in .portrait .photo { opacity: 1; filter: none; }

.js body.fx .about h2 { clip-path: inset(0 100% 0 0); transition: clip-path 1.2s cubic-bezier(.65,0,.35,1) .6s; }
.js body.fx .about.in h2 { clip-path: inset(0 -5% 0 0); }
.js body.fx .about .bio p, .js body.fx .about .links > * { opacity: 0; transform: translateY(16px); transition: opacity .9s ease, transform 1s cubic-bezier(.2,.7,.1,1); }
.js body.fx .about.in .bio p, .js body.fx .about.in .links > * { opacity: 1; transform: none; }
.js body.fx .about.in .bio p:nth-child(1) { transition-delay: .9s; }
.js body.fx .about.in .bio p:nth-child(2) { transition-delay: 1.1s; }
.js body.fx .about.in .bio p:nth-child(3) { transition-delay: 1.3s; }
.js body.fx .about.in .links > *:nth-child(1) { transition-delay: 1.55s; }
.js body.fx .about.in .links > *:nth-child(2) { transition-delay: 1.7s; }
.js body.fx .about.in .links > *:nth-child(3) { transition-delay: 1.85s; }

/* the author's names in the bio glint gold once when they appear */
body.fx .about .bio em { background: linear-gradient(100deg, currentColor 40%, #ffcf7a 50%, currentColor 60%) 0 0 / 300% 100% no-repeat; -webkit-background-clip: text; background-clip: text; }
.js body.fx .about.in .bio em { -webkit-text-fill-color: transparent; animation: about-glint 1.6s ease 2s both; }
@keyframes about-glint { from { background-position: 100% 0; } to { background-position: 0 0; } }

@media (prefers-reduced-motion: reduce) {
  .js body.fx .about .portrait .photo, .js body.fx .about h2, .js body.fx .about .bio p, .js body.fx .about .links > * { opacity: 1; transform: none; clip-path: none; transition: none; filter: none; }
  .js body.fx .about.in .bio em { animation: none; -webkit-text-fill-color: currentColor; }
}

/* ===================== Second round of motion ===================== */

/* 1. The title writes itself, letter by letter */
.js body.fx .hero-head h1 { animation: none; opacity: 1; transform: none; }
.hero-head h1 .w { display: inline-block; white-space: nowrap; }
.hero-head h1 .ch { display: inline-block; }
.js body.fx .hero-head h1 .ch {
  opacity: 0; filter: blur(8px); transform: translateY(.18em);
  animation: ink-in .9s cubic-bezier(.2,.7,.1,1) forwards; animation-delay: calc(.3s + var(--i) * 55ms);
}
@keyframes ink-in { to { opacity: 1; filter: blur(0); transform: none; } }

/* 2. The opening line lights up word by word as you reach it */
.reader .teaser .tw { color: rgba(255, 247, 235, .16); transition: color .6s ease, text-shadow .6s ease; }
.reader .teaser .tw.lit { color: var(--cream); text-shadow: 0 0 22px rgba(255, 190, 120, .18); }

/* 7. The divider eye starts closed and opens when it first appears */
body.fx .ornament svg .eye.closed { transform: scaleY(.06); }

@media (prefers-reduced-motion: reduce) {
  .js body.fx .hero-head h1 .ch { animation: none; opacity: 1; filter: none; transform: none; }
  .reader .teaser .tw { color: var(--cream); }
  body.fx .ornament svg .eye.closed { transform: none; }
}

/* ---------- The serpent: a black indigo snake coiled round the portrait, its head slipping inside the frame ---------- */
.portrait .photo { position: relative; }
.portrait .serpent { position: absolute; left: -18.22%; top: -18.22%; width: 136.44%; height: 136.44%; pointer-events: none; filter: drop-shadow(0 6px 8px rgba(0,0,0,.6)); }
.portrait .serpent img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; border-radius: 0; box-shadow: none; aspect-ratio: auto; filter: none; object-fit: fill; }
@media (max-width: 860px) { .portrait .photo { max-width: 280px; } }
/* it coils slowly round the frame (anticlockwise, the way its body runs), then the neck slides inside and the head arrives */
@property --sweep { syntax: '<angle>'; inherits: false; initial-value: -8deg; }
.js body.fx .about .serpent img { --sweep: -8deg; }
.js body.fx .about .serpent .sp-ring { -webkit-mask: conic-gradient(from 15deg, transparent calc(360deg - var(--sweep) - 8deg), #000 calc(360deg - var(--sweep))); mask: conic-gradient(from 15deg, transparent calc(360deg - var(--sweep) - 8deg), #000 calc(360deg - var(--sweep))); transition: --sweep 4.4s cubic-bezier(.4,0,.85,.9) .7s; }
.js body.fx .about .serpent .sp-neck { -webkit-mask: conic-gradient(from 15deg, transparent calc(360deg - var(--sweep) - 8deg), #000 calc(360deg - var(--sweep))); mask: conic-gradient(from 15deg, transparent calc(360deg - var(--sweep) - 8deg), #000 calc(360deg - var(--sweep))); transition: --sweep 1.5s cubic-bezier(.1,.4,.3,1) 5.05s; }
.js body.fx .about.in .serpent .sp-ring { --sweep: 368deg; }
.js body.fx .about.in .serpent .sp-neck { --sweep: 130deg; }
@media (prefers-reduced-motion: reduce) {
  .js body.fx .about .serpent img { -webkit-mask: none; mask: none; transition: none; }
}
@media (max-width: 860px) { .about .portrait { margin-top: 30px; margin-bottom: 14px; } }
/* on wide screens the coiled portrait sits a little further from the text */
@media (min-width: 861px) { .about .portrait { position: relative; left: clamp(-64px, -3.5vw, -28px); } }
