/* The living moonlit room.

   Mist drifts behind the page, the painted candle breathes, a few motes of
   light rise, ivy sways from the top corners and the footer carries an
   apothecary shelf of glowing bottles. It is all slow on purpose: the page
   is the thing to read, the room is only there to feel like somewhere.

   Every moving part stops when sparkles are off. The sparkle control already
   starts "off" for visitors who ask their device for reduced motion. */

.atmo { position: fixed; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }

/* Mist: two soft violet clouds crossing the dark middle of the room. */
.atmo-mist {
  position: absolute;
  width: 70vmax;
  height: 46vmax;
  border-radius: 50%;
  filter: blur(40px);
  opacity: .5;
  will-change: transform;
}
.atmo-mist-a {
  left: -18vmax;
  top: 18vh;
  background: radial-gradient(closest-side, rgb(var(--c-deep) / .55), rgb(var(--c-deep) / 0));
  animation: atmo-drift-a 70s ease-in-out infinite alternate;
}
.atmo-mist-b {
  right: -22vmax;
  bottom: -8vh;
  background: radial-gradient(closest-side, rgb(var(--c-accent) / .32), rgb(var(--c-accent) / 0));
  animation: atmo-drift-b 90s ease-in-out infinite alternate;
}
@keyframes atmo-drift-a { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(34vw, -8vh, 0) scale(1.15); } }
@keyframes atmo-drift-b { from { transform: translate3d(0, 0, 0) scale(1.1); } to { transform: translate3d(-30vw, -14vh, 0) scale(.95); } }

/* Candle glow sitting over the candles painted into the side windows. */
.atmo-candle {
  position: absolute;
  top: 63%;
  width: 11vw;
  height: 11vw;
  max-width: 190px;
  max-height: 190px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(var(--c-candle) / .34), rgb(var(--c-candle) / .1) 45%, rgb(var(--c-candle) / 0));
  transform: translate(-50%, -50%);
  mix-blend-mode: screen;
  animation: atmo-flicker 5.3s ease-in-out infinite;
}
/* The left glow sits on the painted flame (36, 685 in the 1536 x 1024 room).
   The room is cover-sized and anchored centre top, so its scale is
   max(100vw / 1536, 100vh / 1024) and the flame follows from that. */
.atmo-candle-left {
  left: calc(50vw - max(47.66vw, 71.48vh));
  top: max(44.6vw, 66.9vh);
  animation: atmo-candle-flicker 2.6s linear infinite;
}
/* A small bright core right on the flame that dances faster than the halo. */
.atmo-candle-left::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16%;
  height: 24%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(var(--c-candle-core) / .9), rgb(var(--c-candle) / .45) 55%, rgb(var(--c-candle) / 0));
  transform-origin: 50% 100%;
  animation: atmo-flame-dance .75s ease-in-out infinite;
}
.atmo-candle-right { left: 96%; top: 70%; width: 8vw; height: 8vw; opacity: .55; animation-duration: 6.7s; animation-delay: -2s; background: radial-gradient(closest-side, rgb(var(--c-neon) / .35), rgb(var(--c-neon) / 0)); }
@keyframes atmo-flicker {
  0%, 100% { opacity: .85; transform: translate(-50%, -50%) scale(1); }
  18% { opacity: .7; transform: translate(-50%, -50%) scale(.97); }
  34% { opacity: 1; transform: translate(-50%, -50%) scale(1.04); }
  52% { opacity: .78; transform: translate(-50%, -50%) scale(.99); }
  71% { opacity: .95; transform: translate(-50%, -50%) scale(1.02); }
}
/* Uneven dips and catches, like a real wick in a draught: quick gutters,
   bright flares, and short steady spells in between. */
@keyframes atmo-candle-flicker {
  0%, 100% { opacity: .9; transform: translate(-50%, -50%) scale(1); }
  4% { opacity: .5; transform: translate(-50%, -50%) scale(.9); }
  7% { opacity: 1; transform: translate(-50%, -50%) scale(1.1); }
  12% { opacity: .78; transform: translate(-50%, -50%) scale(.97); }
  17% { opacity: .95; transform: translate(-50%, -50%) scale(1.03); }
  23% { opacity: .42; transform: translate(-50%, -50%) scale(.88); }
  26% { opacity: .88; transform: translate(-50%, -50%) scale(1.02); }
  31% { opacity: .6; transform: translate(-50%, -50%) scale(.93); }
  35% { opacity: 1; transform: translate(-50%, -50%) scale(1.12); }
  46% { opacity: .9; transform: translate(-50%, -50%) scale(1.01); }
  52% { opacity: .55; transform: translate(-50%, -50%) scale(.91); }
  55% { opacity: .97; transform: translate(-50%, -50%) scale(1.06); }
  63% { opacity: .72; transform: translate(-50%, -50%) scale(.95); }
  68% { opacity: 1; transform: translate(-50%, -50%) scale(1.09); }
  76% { opacity: .48; transform: translate(-50%, -50%) scale(.9); }
  80% { opacity: .92; transform: translate(-50%, -50%) scale(1.04); }
  89% { opacity: .66; transform: translate(-50%, -50%) scale(.95); }
  94% { opacity: 1; transform: translate(-50%, -50%) scale(1.07); }
}
@keyframes atmo-flame-dance {
  0%, 100% { opacity: .9; transform: translate(-50%, -62%) scale(1, 1) skewX(0); }
  15% { opacity: .55; transform: translate(-46%, -58%) scale(.84, 1.16) skewX(8deg); }
  35% { opacity: 1; transform: translate(-54%, -66%) scale(1.14, .9) skewX(-7deg); }
  55% { opacity: .7; transform: translate(-47%, -60%) scale(.9, 1.12) skewX(5deg); }
  78% { opacity: .95; transform: translate(-52%, -64%) scale(1.06, .95) skewX(-4deg); }
}
  45% { opacity: 1; transform: translate(-52%, -64%) scale(1.08, .94) skewX(-3deg); }
  70% { opacity: .75; transform: translate(-49%, -61%) scale(.95, 1.05) skewX(2deg); }
}

/* Motes of light rising slowly through the room. */
.atmo-motes { position: absolute; inset: 0; }
.atmo-mote {
  position: absolute;
  bottom: -12px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: rgb(var(--c-violet-100));
  box-shadow: 0 0 6px 2px rgb(var(--c-neon) / .55);
  opacity: 0;
  animation: atmo-rise 26s linear infinite;
}
.atmo-mote:nth-child(1) { left: 4%;  animation-delay: -2s; }
.atmo-mote:nth-child(2) { left: 11%; animation-delay: -15s; animation-duration: 31s; }
.atmo-mote:nth-child(3) { left: 19%; animation-delay: -8s; animation-duration: 23s; width: 3px; height: 3px; }
.atmo-mote:nth-child(4) { left: 33%; animation-delay: -21s; animation-duration: 34s; }
.atmo-mote:nth-child(5) { left: 52%; animation-delay: -5s; animation-duration: 29s; width: 3px; height: 3px; }
.atmo-mote:nth-child(6) { left: 68%; animation-delay: -18s; }
.atmo-mote:nth-child(7) { left: 81%; animation-delay: -11s; animation-duration: 33s; width: 3px; height: 3px; }
.atmo-mote:nth-child(8) { left: 90%; animation-delay: -25s; animation-duration: 27s; }
.atmo-mote:nth-child(9) { left: 96%; animation-delay: -4s; animation-duration: 36s; }
@keyframes atmo-rise {
  0% { transform: translate3d(0, 0, 0); opacity: 0; }
  12% { opacity: .75; }
  50% { transform: translate3d(18px, -55vh, 0); opacity: .45; }
  85% { opacity: .6; }
  100% { transform: translate3d(-10px, -108vh, 0); opacity: 0; }
}

/* Ivy hanging from the top corners, over the painted window columns. */
.atmo-ivy {
  position: absolute;
  top: 58px;
  width: clamp(80px, 8vw, 130px);
  height: auto;
  overflow: visible;
  transform-origin: 50% 0;
  animation: atmo-sway 13s ease-in-out infinite;
}
/* the left ivy hangs just outside the painted moon so the moon stays clear */
.atmo-ivy-left { left: calc(-.6vw - 18px); }
.atmo-ivy-right { right: max(0px, calc(1.2vw - 20px)); transform: scaleX(-1); animation-name: atmo-sway-mirror; animation-duration: 15s; animation-delay: -4s; }
.atmo-ivy-back { opacity: .65; }
.atmo-stem { fill: none; stroke: rgb(var(--c-ivy)); stroke-width: 2.4; stroke-linecap: round; }
.atmo-leaf { fill: rgb(var(--c-ivy)); stroke: rgb(var(--c-ivy-deep)); stroke-width: .8; }
.atmo-ivy-back .atmo-leaf { fill: rgb(var(--c-ivy-deep)); }
.atmo-vein { fill: none; stroke: rgb(var(--c-ivy-vein) / .75); stroke-width: .7; stroke-linecap: round; }
.atmo-ivy use:nth-of-type(3n) { filter: brightness(1.18); }
@keyframes atmo-sway { 0%, 100% { transform: rotate(1.4deg); } 50% { transform: rotate(-1.6deg); } }
@keyframes atmo-sway-mirror { 0%, 100% { transform: scaleX(-1) rotate(1.3deg); } 50% { transform: scaleX(-1) rotate(-1.5deg); } }

/* The ivy and candles only have somewhere to sit on wide screens. */
@media (max-width: 1100px) {
  .atmo-ivy, .atmo-candle { display: none; }
  .atmo-mist { opacity: .4; }
}

/* The apothecary shelf along the top of the footer. */
.apothecary-shelf {
  position: relative;
  z-index: 3;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 1rem;
  height: 118px;
  /* the footer keeps a 3rem top margin; the shelf plank lands on its border */
  margin: 2rem auto calc(-3rem - 1px);
  width: min(100%, 1240px);
  padding-inline: 1rem;
  pointer-events: none;
}
.apothecary-shelf::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 10px;
  border-radius: 3px;
  background: linear-gradient(rgb(var(--c-wood)), rgb(var(--c-night)));
  box-shadow: 0 1px 0 rgb(var(--c-glass) / .22) inset, 0 10px 22px rgb(var(--c-black) / .55);
}
.shelf-cluster { height: 100%; width: auto; overflow: visible; }
.shelf-book { fill: rgb(var(--c-deep) / .85); stroke: rgb(var(--c-glass) / .35); stroke-width: 1; }
.shelf-book-alt { fill: rgb(var(--c-bg-2)); }
.shelf-trim { fill: none; stroke: rgb(var(--c-amber-300-3) / .6); stroke-width: 1.2; }
.shelf-wax { fill: rgb(var(--c-wax)); }
.shelf-drip { fill: none; stroke: rgb(var(--c-wax)); stroke-width: 3; stroke-linecap: round; }
.shelf-wick { stroke: rgb(var(--c-night)); stroke-width: 1.6; }
.shelf-flame { fill: rgb(var(--c-candle)); stroke: rgb(var(--c-candle-core)); stroke-width: 1.2; transform-box: fill-box; transform-origin: 50% 100%; animation: shelf-flame 2.6s ease-in-out infinite; }
.shelf-candle-glow { fill: rgb(var(--c-candle) / .16); animation: atmo-glow 2.6s ease-in-out infinite; }
.shelf-glass { fill: rgb(var(--c-glass) / .08); stroke: rgb(var(--c-glass) / .75); stroke-width: 2; }
.shelf-jar-body { stroke-width: 1.8; }
.shelf-rim { fill: rgb(var(--c-glass) / .5); stroke: rgb(var(--c-glass) / .8); stroke-width: 1; }
.shelf-cork { fill: rgb(var(--c-amber-400-2)); stroke: rgb(var(--c-amber-600)); stroke-width: 1; }
.shelf-label { fill: rgb(var(--c-wax) / .85); }
.shelf-label-ink { fill: none; stroke: rgb(var(--c-deep)); stroke-width: 1.4; }
.shelf-rack { fill: none; stroke: rgb(var(--c-glass) / .45); stroke-width: 2; }
.shelf-liquid { fill: rgb(var(--c-neon)); animation: shelf-pulse 6s ease-in-out infinite; }
.shelf-liquid-b { fill: rgb(var(--c-potion-teal)); animation-delay: -2s; }
.shelf-liquid-c { fill: rgb(var(--c-violet-300)); animation-delay: -4s; }
.shelf-liquid-top { fill: none; stroke: rgb(var(--c-violet-100)); stroke-width: 1.5; opacity: .8; }
.shelf-flask-glow { fill: rgb(var(--c-neon) / .2); filter: blur(10px); animation: atmo-glow 6s ease-in-out infinite; }
.shelf-flask .shelf-glass { filter: drop-shadow(0 0 6px rgb(var(--c-neon) / .7)); }
.shelf-bubble { fill: rgb(var(--c-violet-100)); opacity: 0; animation: shelf-bubble 4.2s ease-in infinite; }
.shelf-bubble-b { animation-delay: -1.4s; }
.shelf-bubble-c { animation-delay: -2.8s; }
.shelf-leaf { fill: rgb(var(--c-ivy)); stroke: rgb(var(--c-ivy-vein) / .6); stroke-width: .8; }
.shelf-leaf-alt { fill: rgb(var(--c-ivy-deep)); }
.shelf-vine { fill: none; stroke: rgb(var(--c-ivy)); stroke-width: 1.8; stroke-linecap: round; }
.shelf-pot { fill: rgb(var(--c-amber-600-3)); stroke: rgb(var(--c-amber-400-2) / .7); stroke-width: 1.2; }
.shelf-fern { transform-box: fill-box; transform-origin: 50% 100%; animation: shelf-fern 11s ease-in-out infinite; }
@keyframes shelf-flame { 0%, 100% { transform: scale(1, 1) skewX(0); } 25% { transform: scale(.94, 1.06) skewX(2deg); } 55% { transform: scale(1.04, .95) skewX(-2deg); } 80% { transform: scale(.98, 1.03) skewX(1deg); } }
@keyframes atmo-glow { 0%, 100% { opacity: .75; } 50% { opacity: 1; } }
@keyframes shelf-pulse { 0%, 100% { opacity: .72; } 50% { opacity: 1; } }
@keyframes shelf-bubble { 0% { opacity: 0; transform: translateY(0); } 20% { opacity: .9; } 100% { opacity: 0; transform: translateY(-26px); } }
@keyframes shelf-fern { 0%, 100% { transform: rotate(-1.2deg); } 50% { transform: rotate(1.4deg); } }
@media (max-width: 760px) {
  .apothecary-shelf { height: 84px; gap: .4rem; padding-inline: .5rem; }
  .shelf-cluster { max-width: 48%; }
}

/* Tonight's moon. The window holds a painted full moon; moon-phase.js lays
   the shadow of the real phase over it, placed from the size of the room
   painting, and a soft halo that grows with the light. */
.lunar { display: contents; }
.lunar-svg { position: fixed; left: 0; top: 0; width: 0; height: 0; z-index: 0; overflow: visible; pointer-events: none; opacity: 0; transition: opacity 1.4s ease; }
.lunar.is-ready .lunar-svg { opacity: 1; }
.lunar-shadow { mix-blend-mode: darken; }
.lunar-glow { mix-blend-mode: screen; }
.lunar-shade { fill: rgb(var(--c-moon-shade) / .95); }
.lunar-halo { animation: lunar-breathe 9s ease-in-out infinite; transform-box: fill-box; transform-origin: 50% 50%; }
.lunar-halo-core { stop-color: rgb(var(--c-moonlight)); stop-opacity: .55; }
.lunar-halo-rim { stop-color: rgb(var(--c-moonlight)); stop-opacity: .34; }
.lunar-halo-mid { stop-color: rgb(var(--c-violet-100)); stop-opacity: .14; }
.lunar-halo-edge { stop-color: rgb(var(--c-neon)); stop-opacity: 0; }
@keyframes lunar-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.06); } }

.lunar-note {
  position: fixed;
  z-index: 2;
  display: grid;
  gap: .1rem;
  padding: .5rem .55rem .55rem;
  border-radius: 10px;
  text-align: center;
  color: rgb(var(--c-surface-soft));
  background: linear-gradient(180deg, rgb(var(--c-night) / .82), rgb(var(--c-bg-2) / .78));
  border: 1px solid rgb(var(--c-glass) / .3);
  box-shadow: 0 0 0 1px rgb(var(--c-night) / .6), 0 8px 22px rgb(var(--c-black) / .45), 0 0 18px rgb(var(--c-moonlight) / .08);
  backdrop-filter: blur(3px);
  pointer-events: auto;
  font-family: var(--lh-sans);
  animation: lunar-note-in 1.2s ease both;
}
.lunar-note[hidden] { display: none; }
.lunar-note p { margin: 0; }
.lunar-note-kicker { font: 700 .6rem/1.3 var(--lh-sans); letter-spacing: .16em; text-transform: uppercase; color: rgb(var(--c-glass)); }
.lunar-note-name { font: 600 1.05rem/1.1 var(--lh-serif); color: rgb(var(--c-white)); text-wrap: balance; }
.lunar-note-lit { font-size: .72rem; color: rgb(var(--c-candle-core)); }
.lunar-note-link {
  display: block;
  margin-top: .3rem;
  padding-top: .35rem;
  border-top: 1px solid rgb(var(--c-glass) / .22);
  font: 600 .72rem/1.3 var(--lh-sans);
  color: rgb(var(--c-violet-100));
  text-decoration: underline;
  text-decoration-color: rgb(var(--c-violet-100) / .45);
  text-underline-offset: 2px;
}
.lunar-note-link:hover { color: rgb(var(--c-white)); text-decoration-color: rgb(var(--c-white)); }
.lunar-note-link:focus-visible { outline: 2px solid rgb(var(--c-candle)); outline-offset: 2px; border-radius: 3px; }
@keyframes lunar-note-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

@media (max-width: 1100px) {
  .lunar, .lunar-note { display: none !important; }
}

/* The hanging garden (partials/hanging_garden.html): phones and tablets only.
   It hangs from under the header at the top of the page and scrolls away. */
.hanging-garden { display: none; }
@media (max-width: 1100px) {
  .hanging-garden { display: block; position: relative; z-index: 4; height: 0; pointer-events: none; }
  .hg-ivy, .hg-planter { position: absolute; top: 0; height: auto; overflow: visible; transform-origin: 50% 0; }
  .hg-ivy { left: -8px; width: 46px; animation: hg-sway 7s ease-in-out infinite; }
  .hg-back { opacity: .7; }
  .hg-back .atmo-leaf { fill: rgb(var(--c-ivy-deep)); }
  .hg-planter { right: 6px; width: 56px; animation: hg-swing 6s ease-in-out infinite; animation-delay: -2s; }
  .hg-chain { fill: none; stroke: rgb(var(--c-glass) / .7); stroke-width: 1.2; stroke-dasharray: 2.5 1.5; }
  .hg-ring { fill: none; stroke: rgb(var(--c-glass) / .8); stroke-width: 1.2; }
  .hg-pot-rim { stroke: rgb(var(--c-amber-400-2)); stroke-width: 2.4; stroke-linecap: round; }
  .hg-vine { stroke-width: 1.8; }
}
@media (max-width: 640px) {
  .hg-ivy { width: 38px; left: -9px; }
  .hg-planter { width: 46px; right: 2px; }
}
@keyframes hg-sway { 0%, 100% { transform: rotate(3deg); } 50% { transform: rotate(-2.5deg); } }
@keyframes hg-swing { 0%, 100% { transform: rotate(-4deg); } 50% { transform: rotate(4deg); } }
html.mobile-nav-open .hanging-garden { visibility: hidden; }
html[data-sparkles='off'] .hanging-garden * { animation: none !important; }
@media (prefers-reduced-motion: reduce) { html:not([data-sparkles='on']) .hanging-garden * { animation: none !important; } }
@media print { .hanging-garden { display: none !important; } }

/* Tonight's moon in the header, for screens too narrow for the painted window. */
.header-moon { display: none; }
@media (max-width: 1100px) {
  .header-moon:not([hidden]) { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; flex: none; -webkit-tap-highlight-color: transparent; }
  .header-moon svg { width: 30px; height: 30px; overflow: visible; }
  .hm-glow { fill: rgb(var(--c-moonlight) / .22); filter: blur(2.5px); animation: lunar-breathe 9s ease-in-out infinite; transform-box: fill-box; transform-origin: 50% 50%; }
  .hm-disc { fill: rgb(var(--c-moonlight)); }
  .hm-shade { fill: rgb(var(--c-bg-2)); stroke: rgb(var(--c-moon-shade) / .6); stroke-width: .5; }
  .header-moon:hover .hm-disc, .header-moon:focus-visible .hm-disc { fill: rgb(var(--c-white)); }
  .header-moon:focus-visible { outline: 2px solid rgb(var(--c-candle)); outline-offset: 1px; }
}
@media (max-width: 480px) { .header-moon:not([hidden]) { width: 38px; } .header-moon svg { width: 26px; height: 26px; } }
html[data-sparkles='off'] .hm-glow { animation: none; }
@media (prefers-reduced-motion: reduce) { html:not([data-sparkles='on']) .hm-glow { animation: none; } }

/* Sparkles off, or a visitor who asked for less motion: the room holds still. */
html[data-sparkles='off'] :is(.lunar-note, .lunar-halo) { animation: none; }
@media (prefers-reduced-motion: reduce) { html:not([data-sparkles='on']) :is(.lunar-note, .lunar-halo) { animation: none; } }
html[data-sparkles='off'] .atmo *,
html[data-sparkles='off'] .apothecary-shelf * { animation: none !important; }
html[data-sparkles='off'] .atmo-mote { display: none; }
html[data-sparkles='off'] .atmo-ivy-right { transform: scaleX(-1); }
@media (prefers-reduced-motion: reduce) {
  html:not([data-sparkles='on']) .atmo *,
  html:not([data-sparkles='on']) .apothecary-shelf * { animation: none !important; }
}
@media print { .atmo, .apothecary-shelf, .lunar, .lunar-note { display: none !important; } }
