/*
  mascot.css: the Sanctity robot, alive (public/js/mascot.js builds the rig).
  The rig sits exactly over the artwork's eyes; the whole robot floats, and
  hover, hop and hello move the robot and its eyes together.
*/

.mascot { position: relative; display: block; width: 100%; height: 100%; animation: mascot-float 3.8s ease-in-out infinite; transform-origin: 50% 90%; }
.mascot > img { position: relative; z-index: 1; display: block; width: 100%; height: 100%; object-fit: contain; user-select: none; }
.mascot-rig { position: absolute; inset: 0; z-index: 2; width: 100%; height: 100%; pointer-events: none; overflow: visible; }

/* Eyes: look, blink, squint, widen. Steps keep the pixel-art feel. */
.mascot-eye { transform-box: fill-box; transform-origin: 50% 55%; transition: transform 90ms steps(2); }
.mascot-look { transform: translate(var(--look-x, 0px), var(--look-y, 0px)); transition: transform .28s steps(3); }
.mascot-shine { transform: translate(calc(var(--look-x, 0px) * .4), calc(var(--look-y, 0px) * .4)); transition: transform .28s steps(3); }
.mascot.is-blinking .mascot-eye { transform: scaleY(.09); }
.mascot.is-sleeping .mascot-eye { transform: scaleY(.3); transition-duration: .6s; }
.mascot[data-mood="surprised"] .mascot-eye { transform: scale(1.12); }
.mascot-happy { opacity: 0; }
.mascot[data-mood="happy"] .mascot-eye { opacity: 0; }
.mascot[data-mood="happy"] .mascot-happy { opacity: 1; }

/* Asleep: little z's drift up. */
.mascot-zz { opacity: 0; transition: opacity .4s; }
.mascot.is-sleeping .mascot-zz { opacity: 1; animation: mascot-zz 2.4s ease-in-out infinite; }
.mascot.is-sleeping { animation-duration: 6s; }

/* Hover, hop, hello. The designer's waddle moved only the image; here it moves the whole robot. */
.companion-button:hover img, .site-companion-button:hover img { animation: none !important; }
.companion-button:hover .mascot, .site-companion-button:hover .mascot { animation: mascot-waddle .55s ease-in-out; }
.mascot.is-hopping { animation: mascot-hop .5s cubic-bezier(.2, .8, .2, 1); }
.mascot.is-arriving { animation: mascot-arrive .7s cubic-bezier(.2, .9, .25, 1.25); }

@keyframes mascot-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes mascot-waddle { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-6deg) translateY(-3px); } 75% { transform: rotate(6deg) translateY(-3px); } }
@keyframes mascot-hop { 0% { transform: translateY(0) scale(1, 1); } 20% { transform: translateY(2px) scale(1.06, .94); } 50% { transform: translateY(-18px) scale(.97, 1.04); } 80% { transform: translateY(0) scale(1.04, .96); } 100% { transform: translateY(0) scale(1, 1); } }
@keyframes mascot-arrive { 0% { transform: translateY(40px) scale(.6); opacity: 0; } 70% { transform: translateY(-6px) scale(1.04); opacity: 1; } 100% { transform: none; } }
@keyframes mascot-zz { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }

@media (prefers-reduced-motion: reduce) {
  .mascot, .mascot.is-hopping, .mascot.is-arriving, .mascot.is-sleeping .mascot-zz { animation: none !important; }
}

/* The artwork is pixel art: keep its edges crisp at any size. */
.mascot > img { image-rendering: pixelated; }

/* The pad stays on the ground; it dims and narrows as the robot rises. */
.mascot-pad { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; pointer-events: none; transform-origin: 50% 88.75%; animation: mascot-pad 3.8s ease-in-out infinite; }
@keyframes mascot-pad { 0%, 100% { transform: scaleX(1); opacity: 1; } 50% { transform: scaleX(.88); opacity: .7; } }

/* Lights: a slow breath on the head, a quick blink on the chest while talking. */
.mascot-glow { opacity: 0; }
.mascot-glow-head { animation: mascot-breathe 4.6s ease-in-out infinite; }
.mascot.is-talking .mascot-glow-chest { animation: mascot-talk .5s steps(2) infinite; }
.mascot[data-mood="happy"] .mascot-glow { opacity: .9; animation: none; }
@keyframes mascot-breathe { 0%, 60%, 100% { opacity: 0; } 80% { opacity: .75; } }
@keyframes mascot-talk { 0% { opacity: 0; } 100% { opacity: .9; } }

@media (prefers-reduced-motion: reduce) {
  .mascot-pad, .mascot-glow-head, .mascot.is-talking .mascot-glow-chest { animation: none !important; }
}

/* Phones: smaller everywhere, and tucked to the edge while the page scrolls. */
.sanctity-companion, .site-companion { transition: transform .35s ease, opacity .35s ease; }
@media (max-width: 700px) {
  .site-companion-button { width: 72px; height: 72px; }
  .site-companion { right: 6px; bottom: 12px; }
  .site-companion-message { margin-right: 52px; }
  .sanctity-companion.is-tucked, .site-companion.is-tucked { transform: translateX(64%); opacity: .5; }
  /* At rest over a link or button: moved just clear of it (mascot.js measures how far). */
}

/* At rest over words or a control, at any width: moved just clear of them (mascot.js measures how far). */
.sanctity-companion.is-parked, .site-companion.is-parked { transform: translateX(var(--park-x, 64%)); }
.sanctity-companion.speaking.is-parked, .site-companion.speaking.is-parked { transform: none; }

/* ------------------------------------------------------------ peeking

   Just the eyes over the edge.

   The first version of this backed the robot up until its head cleared the
   line, which on a wide screen still put most of a robot on the page. MC asked
   for the eyes and nothing else, which is also the funnier version: a thing
   that is clearly hiding and clearly watching.

   So at rest it sits below the bottom edge with only the top of its head
   showing, tipped slightly as though leaning on the sill. A lean brings it up
   far enough to look properly and then it drops back. A scoot slides it along
   the edge to somewhere else. All of it stops while it is speaking, because
   the one moment it has something to say is the moment to be still, and all of
   it stops completely for anyone who asked for less motion. */

.sanctity-companion, .site-companion {
  transform: translate(var(--perch-x, 0px), var(--perch-y, 0px));
  transition: transform .4s ease, opacity .35s ease;
}

/* Parked: below the line, eyes over it. */
.sanctity-companion.is-parked, .site-companion.is-parked {
  transform: translate(var(--perch-x, 0px), calc(var(--perch-y, 0px) + 62%)) rotate(-4deg);
  transform-origin: 50% 100%;
}
.sanctity-companion.speaking.is-parked, .site-companion.speaking.is-parked {
  transform: translate(var(--perch-x, 0px), var(--perch-y, 0px));
}

/* A lean: up over the sill for a proper look, then back down. */
.sanctity-companion.is-leaning.is-parked, .site-companion.is-leaning.is-parked {
  transform: translate(calc(var(--perch-x, 0px) - 6px), calc(var(--perch-y, 0px) + 22%)) rotate(-8deg);
  transition: transform .55s cubic-bezier(.2, .9, .25, 1.3);
}
.sanctity-companion.is-leaning:not(.is-parked), .site-companion.is-leaning:not(.is-parked) {
  transform: translate(calc(var(--perch-x, 0px) - 20px), calc(var(--perch-y, 0px) - 8px)) rotate(-8deg);
  transition: transform .55s cubic-bezier(.2, .9, .25, 1.3);
}

/* A scoot: along the edge, still ducked, so it arrives somewhere else the way
   something hiding would move. */
.sanctity-companion.is-flying, .site-companion.is-flying {
  transform: translate(var(--perch-x, 0px), calc(var(--perch-y, 0px) + 74%)) rotate(3deg);
  transition: transform 1.1s cubic-bezier(.45, .05, .3, 1);
}

@media (prefers-reduced-motion: reduce) {
  .sanctity-companion, .site-companion,
  .sanctity-companion.is-parked, .site-companion.is-parked,
  .sanctity-companion.is-leaning, .site-companion.is-leaning,
  .sanctity-companion.is-flying, .site-companion.is-flying { transition: none; }
  .sanctity-companion.is-leaning, .site-companion.is-leaning,
  .sanctity-companion.is-flying, .site-companion.is-flying {
    transform: translate(var(--perch-x, 0px), calc(var(--perch-y, 0px) + 62%));
  }
}

/* ==================================================================
   The guide: what the robot does when clicked
   ==================================================================

   A small panel over the bottom right, where the robot lives, so it opens
   where the reader's eye already is. Four plain choices, each answered from the
   site's own record. It never covers more than it needs to: at most 360px
   wide, and never taller than the screen allows. */

.robo {
  position: fixed; right: 20px; bottom: 150px; z-index: 60;
  width: min(360px, calc(100vw - 32px)); max-height: min(560px, calc(100dvh - 190px));
  display: flex; flex-direction: column;
  border: 1px solid #e3e3df; border-radius: 18px; background: #fff; color: #191919;
  box-shadow: 0 24px 60px #0000002a, 0 2px 6px #00000010;
  font-family: "Urbanist", "Avenir Next", "Helvetica Neue", Arial, sans-serif;
  transform-origin: 92% 100%;
  animation: robo-in .22s cubic-bezier(.2, .8, .2, 1);
}
.robo[hidden] { display: none; }
@keyframes robo-in { from { opacity: 0; transform: translateY(8px) scale(.97); } to { opacity: 1; transform: none; } }

.robo-head { display: flex; align-items: center; gap: 8px; padding: 14px 14px 10px 18px; border-bottom: 1px solid #efefeb; }
.robo-title { flex: 1; margin: 0; font-size: 15px; font-weight: 500; }
.robo-back, .robo-close {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; flex: none; white-space: nowrap; min-width: 34px; height: 34px; padding: 0 12px;
  border: 1px solid #e3e3df; border-radius: 999px; background: #fff; color: #4b4f4a;
  font: inherit; font-size: 13px; cursor: pointer;
}
.robo-close { padding: 0; font-size: 20px; line-height: 1; }
.robo-back::before { content: "\2190"; }
.robo-back:hover, .robo-close:hover { border-color: #191919; color: #191919; }

.robo-body { padding: 14px 18px 18px; overflow-y: auto; overscroll-behavior: contain; }
.robo-choices { display: grid; gap: 8px; }
.robo-choice {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; min-height: 46px; padding: 0 16px;
  border: 1px solid #e3e3df; border-radius: 12px; background: #fafaf8; color: #191919;
  font: inherit; font-size: 15px; text-align: left; cursor: pointer;
  opacity: 0; animation: robo-choice-in .28s ease forwards; animation-delay: calc(var(--i, 0) * 45ms + 60ms);
  transition: border-color .15s ease, background .15s ease, transform .15s ease;
}
.robo-choice::after { content: "\2192"; color: #6a6e67; transition: transform .15s ease; }
.robo-choice:hover, .robo-choice:focus-visible { border-color: #191919; background: #fff; }
.robo-choice:hover::after { transform: translateX(3px); color: #191919; }
.robo-choice:active { transform: scale(.99); }
@keyframes robo-choice-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.robo-foot { margin: 14px 0 0; font-size: 12.5px; line-height: 1.5; color: #6a6e67; }
.robo-wait { margin: 0; font-size: 14px; color: #6a6e67; }
.robo-lead { margin: 0 0 8px; font-size: 18px; line-height: 1.35; font-weight: 500; }
.robo-text { margin: 0; font-size: 15px; line-height: 1.6; color: #333; }
.robo-stack { margin: 14px 0 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.robo-stack li { font-size: 14px; line-height: 1.5; color: #4b4f4a; padding-left: 12px; border-left: 2px solid #e3e3df; }
.robo-stack li.is-here { border-left-color: #191919; }
.robo-stack b { font-weight: 500; color: #191919; }
.robo-fresh { margin: 0; padding: 0; list-style: none; display: grid; gap: 14px; }
.robo-kind { display: block; margin-bottom: 3px; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: #6a6e67; }
.robo-link { color: #191919; font-size: 14.5px; line-height: 1.5; text-decoration: underline; text-decoration-color: #cfcfca; text-underline-offset: 3px; }
.robo-link:hover { text-decoration-color: #191919; }
.robo-go {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 16px; padding: 11px 18px;
  border-radius: 999px; background: #191919; color: #fff; font-size: 14px; text-decoration: none;
}
.robo-go::after { content: "\2192"; }
.robo-go:hover { background: #333; }

/* The robot while its guide is open: awake, and not wandering off. */
.is-guiding { animation-play-state: paused !important; }


@media (max-width: 700px) {
  .robo { right: 12px; left: 12px; width: auto; bottom: 120px; max-height: calc(100dvh - 170px); }
  .robo-back, .robo-close { min-height: 44px; min-width: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  .robo, .robo-choice { animation: none; opacity: 1; }
}

/* ==================================================================
   The tour (MC, 23 September): the robot flies to things and says what
   they are. It flies at 72 percent of its size, from its top-left corner, so
   the arithmetic in guide.js is a translation and nothing else.
   ================================================================== */
.sanctity-companion.is-touring, .site-companion.is-touring {
  z-index: 62;
  transform: translate(var(--tour-x, 0px), var(--tour-y, 0px)) scale(.72) !important;
  transform-origin: 0 0 !important;
  transition: transform .75s cubic-bezier(.3, .1, .2, 1) !important;
}
.is-touring .site-companion-message, .is-touring .companion-message { display: none !important; }

/* The lit thing: a clear window in a light dimming of everything else. */
.robo-ring {
  position: fixed; z-index: 58; pointer-events: none; border-radius: 14px;
  box-shadow: 0 0 0 3px #2368c2, 0 0 0 9999px rgba(20, 22, 24, .28);
  transition: left .45s ease, top .45s ease, width .45s ease, height .45s ease;
}
.robo-ring[hidden] { display: none; }

/* What the robot says at each stop. */
.robo-tip, .robo-hello {
  position: fixed; z-index: 63; width: min(320px, calc(100vw - 32px));
  padding: 16px 18px 14px; border: 1px solid #e3e3df; border-radius: 16px; background: #fff; color: #191919;
  box-shadow: 0 22px 50px #0000002e, 0 2px 6px #00000012;
  font-family: "Urbanist", "Avenir Next", "Helvetica Neue", Arial, sans-serif;
  animation: robo-in .22s cubic-bezier(.2, .8, .2, 1);
  transition: left .45s ease, top .45s ease;
}
.robo-tip[hidden] { display: none; }
.robo-tip-count { margin: 0 0 4px; font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: #6a6e67; }
.robo-tip-title { margin: 0 0 6px; font-size: 17px; font-weight: 600; line-height: 1.3; }
.robo-tip-text, .robo-hello-text { margin: 0; font-size: 15px; line-height: 1.55; color: #33362f; }
.robo-tip-row { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }
.robo-tip-prev, .robo-tip-next {
  min-height: 38px; padding: 0 16px; border-radius: 999px; font: inherit; font-size: 14px; cursor: pointer;
  transition: transform .12s ease, background-color .15s ease, border-color .15s ease;
}
.robo-tip-prev { border: 1px solid #d9d9d4; background: #fff; color: #33362f; }
.robo-tip-prev:disabled { opacity: .4; cursor: default; }
.robo-tip-next { border: 1px solid #191919; background: #191919; color: #fff; }
.robo-tip-prev:hover:not(:disabled) { border-color: #191919; }
.robo-tip-next:hover { background: #333; }
.robo-tip-prev:active, .robo-tip-next:active { transform: scale(.97); }
.robo-tip-stop { display: block; margin: 10px 0 0 auto; padding: 4px 0; border: 0; background: none; font: inherit; font-size: 13px; color: #6a6e67; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.robo-tip-stop:hover { color: #191919; }

/* The hello sits beside the robot at rest, bottom right. */
.robo-hello { right: 170px; bottom: 60px; }
.robo-hello .robo-go { margin-top: 12px; }
.robo-hello > .robo-tip-prev { margin-top: 12px; }

/* Choices: the part on screen first, then the tour. */
.robo-choice.is-here { border-color: #2368c2; background: #f2f6fd; }
.robo-choice.is-tour { background: #191919; border-color: #191919; color: #fff; }
.robo-choice.is-tour::after { color: #fff; }
.robo-choice.is-tour:hover, .robo-choice.is-tour:focus-visible { background: #333; }
.robo-hide { padding: 0; border: 0; background: none; font: inherit; font-size: inherit; color: #2368c2; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }

/* Hidden, with a small way back. */
.robo-return {
  position: fixed; right: 16px; bottom: 16px; z-index: 30; min-height: 36px; padding: 0 14px;
  border: 1px solid #d9d9d4; border-radius: 999px; background: #fff; color: #33362f;
  font: inherit; font-family: "Urbanist", Arial, sans-serif; font-size: 13px; cursor: pointer; box-shadow: 0 6px 18px #0000001a;
}
.robo-return[hidden] { display: none; }
[data-companion][hidden], #sanctity-companion[hidden] { display: none !important; }

@keyframes robo-in { from { opacity: 0; transform: translateY(6px) scale(.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .sanctity-companion.is-touring, .site-companion.is-touring, .robo-ring, .robo-tip, .robo-hello { transition: none !important; animation: none !important; }
}
@media (max-width: 899px) {
  .robo-hello, .robo-tip, .robo-ring { display: none !important; }
}

/* ------------------------------------------------ antics (features/antics.js)

   The bubble it answers in, a puff of something it would rather you had not
   seen, and the letters it breathes out when it dozes off. */
.robo-quip {
  position: fixed; z-index: 64; max-width: 240px; margin: 0; padding: 11px 14px;
  border: 1px solid rgba(255, 255, 255, .14); border-radius: 16px 16px 4px 16px;
  background: rgba(22, 22, 24, .92); color: #fff; box-shadow: 0 14px 30px rgba(0, 0, 0, .3);
  font: 500 14px/1.4 "Urbanist", "Avenir Next", "Helvetica Neue", Arial, sans-serif; pointer-events: none;
}
.robo-quip.is-in { animation: quip-in .28s cubic-bezier(.2, .8, .2, 1); }
@keyframes quip-in { from { opacity: 0; transform: translateY(8px) scale(.94); } to { opacity: 1; transform: none; } }

.robo-puff { position: fixed; z-index: 23; width: 0; height: 0; pointer-events: none; }
.robo-puff i {
  position: absolute; width: 22px; height: 22px; border-radius: 50%;
  background: radial-gradient(circle at 40% 40%, rgba(190, 196, 170, .75), rgba(160, 166, 140, 0) 70%);
  animation: puff 1.6s ease-out forwards;
}
.robo-puff i:nth-child(2) { animation-delay: .08s; --dx: -34px; --dy: -8px; }
.robo-puff i:nth-child(3) { animation-delay: .16s; --dx: -18px; --dy: -30px; }
.robo-puff i:nth-child(4) { animation-delay: .24s; --dx: -44px; --dy: -26px; }
@keyframes puff {
  from { opacity: .9; transform: translate(0, 0) scale(.4); }
  to { opacity: 0; transform: translate(var(--dx, -26px), var(--dy, -14px)) scale(2.2); }
}

.mascot.is-sleeping::after {
  content: "z z z"; position: absolute; right: -8px; top: -10px;
  font: 600 16px/1 "Urbanist", Arial, sans-serif; letter-spacing: 3px; color: #7a8aa8;
  animation: snooze 2.4s ease-in-out infinite;
}
@keyframes snooze { 0% { opacity: 0; transform: translate(0, 6px) scale(.8); } 40% { opacity: 1; } 100% { opacity: 0; transform: translate(10px, -14px) scale(1.1); } }

@media (prefers-reduced-motion: reduce) {
  .robo-quip.is-in, .robo-puff i, .mascot.is-sleeping::after { animation: none; }
}
