/* Home: interactive character hero — header + hero always fit one screen.
 *
 * The hero is laid out on a "canvas" designed at a fixed height (--D: 830 / 770 / 740 px
 * for desktop / tablet / phone). --k = min(1px, available height / --D) scales every
 * vertical measure, so a short window shrinks the whole composition instead of scrolling;
 * a tall window keeps the original size and centres it.
 * Breakpoints: ≥1500, 1001–1499 (default), 701–1000, ≤700, ≤380.
 */
.page-home { height: 100svh; min-height: 540px; overflow: hidden; overflow: clip; } /* clip: can't be scrolled sideways when something inside gets focus */
.hero { position: relative; flex: 1 1 0; min-height: 0; container-type: size; isolation: isolate; }
.hero-canvas {
  --D: 830;
  --k: min(1px, 100cqh / var(--D));
  position: absolute; left: 0; right: 0; top: 50%;
  height: calc(var(--D) * var(--k));
  transform: translateY(-50%);
}

.hero h1 { color: var(--title, inherit); background: var(--title-fill, none); -webkit-background-clip: text; background-clip: text; position: relative; z-index: 0; margin: calc(-4 * var(--k)) 0 0; text-align: center; font-family: var(--serif); font-style: italic; font-weight: 600; font-size: min(max(90px, 13.8vw), 220px, calc(236 * var(--k))); line-height: 1.18; letter-spacing: -.075em; white-space: nowrap; }
.hero h1 em { color: var(--title-em, inherit); background: var(--title-em-fill, none); -webkit-background-clip: text; background-clip: text; position: relative; font-weight: 600; cursor: pointer; border-radius: 12px; }

.orbit { position: absolute; left: 50%; border: 1px solid var(--orbit); border-radius: 50%; pointer-events: none; z-index: -1; }
.orbit-one { width: calc(700 * var(--k)); height: calc(540 * var(--k)); top: calc(120 * var(--k)); transform: translateX(-50%) rotate(-18deg); }
.orbit-two { width: calc(570 * var(--k)); height: calc(660 * var(--k)); top: calc(70 * var(--k)); transform: translateX(-50%) rotate(35deg); }

/* Dog */
.dog-stage { position: absolute; left: 50%; transform: translateX(-50%); z-index: 2; width: calc(620 * var(--k)); height: calc(620 * var(--k)); top: calc(155 * var(--k)); } /* sits over the title, the top of the letters stays visible */
.floor-shadow { position: absolute; width: 55%; height: 6%; bottom: 1%; left: 23%; border-radius: 50%; background: var(--floor); filter: blur(17px); }
.dog { position: absolute; inset: 0; border: 0; padding: 0; background: none; transform-origin: 50% 87%; animation: breathe 5s ease-in-out infinite; cursor: pointer; }
.dog img, .dog .face { position: absolute; inset: 0; width: 100%; height: 100%; user-select: none; pointer-events: none; }
.eye { transform-box: view-box; transform-origin: 0 0; }
.happy-mouth { opacity: 0; transition: opacity .14s ease; pointer-events: none; }
.dog.happy .happy-mouth, .dog.snack .happy-mouth { opacity: 1; }
.dog.sleeping .happy-mouth { opacity: 0; }
/* a drawn "eyes closed" face (features.eyesClosed) replaces the lids while asleep */
.dog .sleep-eyes { opacity: 0; transition: opacity .4s ease; }
.dog.sleeping .sleep-eyes { opacity: 1; }
.dog:has(.sleep-eyes) .eye { transition: opacity .4s ease; }
.dog.sleeping:has(.sleep-eyes) .eye { opacity: 0; }
/* 點鼻子 (features.lickNose): the drawn tongue-on-nose patch is revealed from the mouth upward and
   pulled back down, once — like a real quick lick (the patch's top part is the unchanged nose) */
.dog .lick-nose { opacity: 0; }
.dog .lick-nose image { transform-box: fill-box; transform-origin: 50% 100%; }
.dog.licking .lick-nose { opacity: 1; }
.dog.licking .lick-nose image { animation: lick 1.6s both; }
.dog.licking .happy-mouth { opacity: 0; }
@keyframes lick {   /* 1.6s: tongue out 0.8s · on the nose 0.3s · back 0.5s */
  0% { clip-path: inset(100% 0 0 0); transform: translateY(10px); animation-timing-function: ease-out; }
  50% { clip-path: inset(0 0 0 0); transform: none; }
  68.75% { clip-path: inset(0 0 0 0); transform: none; animation-timing-function: ease-in; }
  100% { clip-path: inset(100% 0 0 0); transform: translateY(10px); }
}
@media (prefers-reduced-motion: reduce) { .dog.licking .lick-nose image { animation: none; } }
.dog.happy { animation: happy .6s ease-in-out 2; }
.dog.snack { animation: snack .35s ease-in-out 4; }
.dog.sleeping { animation: breathe 7s ease-in-out infinite; filter: saturate(.82); }
/* head tilt (叫名字 / looking for you): cross-fade to the head-tilted frame (tools/make_tilt.py —
   the original body with a redrawn head). The tilted frame comes in first and the base leaves a
   moment later, so the dog never turns see-through; the eye/tongue overlay belongs to the upright
   head and hides meanwhile. */
.dog > .tilt-frame { opacity: 0; transition: opacity .22s ease .08s; }
.dog > img.base { transition: opacity .3s ease-in-out; }
.dog .face { transition: opacity .12s ease; }
.dog.tilt-left .tilt-frame { opacity: 1; transition: opacity .22s ease; }
.dog.tilt-left > img.base { opacity: 0; transition: opacity .22s ease; }
.dog.tilt-left .face { opacity: 0; }
/* 摸摸頭 with a drawn happy face (features.petHappy: 飛機耳 + tongue, tools/make_tilt.py <pet> happy):
   same cross-fade as the tilt; the eye / tongue overlay belongs to the plain face and hides meanwhile */
.dog > .happy-frame { opacity: 0; transition: opacity .15s ease .05s; }
.dog.happy .happy-frame { opacity: 1; transition: opacity .15s ease; }
.dog.happy:has(.happy-frame.ready) > img.base { opacity: 0; transition: opacity .15s ease; }
.dog.happy:has(.happy-frame) .face { opacity: 0; }
/* 打哈欠 before falling asleep (features.yawn, tools/make_tilt.py <pet> yawn) */
/* the mouth opens slowly (0.8s), stays wide (0.8s), closes (0.5s); the base stays underneath (the yawn
   frame is the same picture apart from the face) so the cross-fade never turns see-through */
/* frame in / base out at the same time and the same speed: stacking the two semi-transparent fur
   edges at full strength would make a hard white outline around the body */
.dog > .yawn-frame { opacity: 0; transition: opacity .5s ease-in-out; }
.dog.yawning .yawn-frame { opacity: 1; transition: opacity .8s ease-in-out; }
.dog.yawning:has(.yawn-frame.ready) > img.base { opacity: 0; transition: opacity .8s ease-in-out; }
.dog.yawning .face { opacity: 0; transition: opacity .3s ease; }
/* 嗷嗚 (features.howl, tools/make_tilt.py <pet> howl): head lifts slowly, holds, comes back */
.dog > .howl-frame { opacity: 0; transition: opacity .5s ease-in-out; }
.dog.howling .howl-frame { opacity: 1; transition: opacity .6s ease-in-out; }
.dog.howling:has(.howl-frame.ready) > img.base { opacity: 0; transition: opacity .6s ease-in-out; }
.dog.howling .face { opacity: 0; transition: opacity .3s ease; }
/* 搖尾巴 (features.wag, tools/make_wag.py): the left-tail frame fades in, the right-tail frame flips on and
   off over it while the left one flips the other way (the two differ only in the tail zones) */
/* home.js toggles .tail-right every 180 ms; the frames swap instantly (they are identical outside the tail
   zones and the face), and the base is only hidden once the frames are decoded */
.dog > .wag-frame { opacity: 0; }
.dog.wagging:has(.wag-r.ready) > .wag-l { opacity: 1; }
.dog.wagging.tail-right:has(.wag-r.ready) > .wag-l { opacity: 0; }
.dog.wagging.tail-right:has(.wag-r.ready) > .wag-r { opacity: 1; }
.dog.wagging:has(.wag-r.ready) > img.base { opacity: 0; transition: none; }
.dog.wagging:has(.wag-r.ready) .face { opacity: 0; }
.zone-body { border-radius: 45% 45% 30% 30%; }
.ask { position: absolute; left: -4%; top: 17%; z-index: 4; white-space: nowrap; pointer-events: none;
  font: italic 17px Georgia, 'PingFang TC', serif; color: var(--hint-strong); letter-spacing: 1px;
  padding: 7px 16px 8px; background: var(--bubble); border: 1px solid var(--bubble-border); border-radius: 20px; box-shadow: 0 6px 18px rgb(var(--shadow-rgb) / .078);
  transform-origin: 90% 100%; animation: ask-pop 1.9s ease-out forwards; }
/* the bubble's tail, pointing down-right at his head */
.ask::after { content: ""; position: absolute; right: 14px; bottom: -6px; width: 11px; height: 11px; background: inherit;
  border-right: 1px solid var(--bubble-border); border-bottom: 1px solid var(--bubble-border); transform: rotate(45deg); }
@keyframes ask-pop { 0% { opacity: 0; transform: scale(.6) rotate(-4deg); } 14% { opacity: 1; transform: scale(1.05) rotate(-4deg); } 24% { transform: scale(1) rotate(-4deg); } 82% { opacity: 1; } 100% { opacity: 0; transform: translateY(-8px) rotate(-4deg); } }
.heart { position: absolute; font-family: Arial, sans-serif; color: var(--heart); font-size: 26px; animation: float-up 1.6s ease-out forwards; pointer-events: none; }

/* Hot zones over the head and the right front paw (invisible, keyboard-focusable) */
/* the stage box overlaps the title: only the hot zones take clicks, so the letters of the name
   behind the transparent corners stay clickable (叫名字) */
.dog-stage { pointer-events: none; }
.zone { position: absolute; border: 0; padding: 0; background: transparent; cursor: pointer; border-radius: 50%; pointer-events: auto; }
/* .zone-head / .zone-paw position and size: generated per pet from pet.json (character.zoneHead / zonePaw) */
.zone-paw { border-radius: 40% 40% 30% 30%; }
.zone-nose { z-index: 1; }
.zone:focus-visible { outline: 2px dashed var(--focus-soft); outline-offset: -2px; }

/* Handwritten hints around the dog */
.hint { position: absolute; z-index: 3; margin: 0; display: flex; align-items: flex-end; gap: 8px; font: italic 17px Georgia, 'PingFang TC', serif; line-height: 1.55; color: var(--hint); pointer-events: none; }
.hint svg { width: 46px; height: 31px; flex: none; }
.hint-head { left: calc(50% - 560 * var(--k)); top: calc(315 * var(--k)); transform: rotate(-5deg); }
.hint-paw { left: calc(50% + 300 * var(--k)); top: calc(595 * var(--k)); transform: rotate(4deg); }
.hint-paw svg { transform: translateY(-14px); }
.hint-nose { left: calc(50% - 560 * var(--k)); top: calc(440 * var(--k)); transform: rotate(-3deg); }
.hint-nose svg { transform: translateY(-10px); }
/* 稱讚: a button like zzz — tapping it wags the tail (the body can be tapped too) */
.hint-body { left: calc(50% - 540 * var(--k)); top: calc(575 * var(--k)); flex-direction: column; align-items: flex-start; gap: 2px; pointer-events: auto; cursor: pointer; border: 0; background: transparent; padding: 6px 10px; border-radius: 14px; transform: rotate(-4deg); transition: background .2s; }
@media (hover: hover) { .hint-body:hover { background: var(--hover); } }
.hint-body .praise { font: italic 600 26px var(--serif); color: var(--accent); letter-spacing: 1px; }
.hint-body .zzz-label { font: 11px var(--sans); letter-spacing: 1.5px; color: var(--muted); }
.hint-name .short, .hint-nose .short, .hint-body .short { display: none; }
/* the name hint lives inside <em>name.</em>, so it follows the word whatever size the title is */
.hint-name { left: calc(100% + 16px); top: 30%; transform: rotate(-4deg); letter-spacing: normal; text-align: left; }
@media (max-width: 1280px) { .hint-name { font-size: 14px; } }
.hint-zzz { left: calc(50% + 400 * var(--k)); top: calc(295 * var(--k)); flex-direction: column; align-items: flex-start; gap: 2px; pointer-events: auto; cursor: pointer; border: 0; background: transparent; padding: 6px 10px; border-radius: 14px; transform: rotate(6deg); transition: background .2s; }
@media (hover: hover) { .hint-zzz:hover { background: var(--hover); } }
.hint-zzz .zzz { font: italic 600 30px var(--serif); color: var(--accent); letter-spacing: 1px; }
.hint-howl { left: calc(50% + 400 * var(--k)); top: calc(430 * var(--k)); flex-direction: column; align-items: flex-start; gap: 2px; pointer-events: auto; cursor: pointer; border: 0; background: transparent; padding: 6px 10px; border-radius: 14px; transform: rotate(-3deg); transition: background .2s; }
@media (hover: hover) { .hint-howl:hover { background: var(--hover); } }
.hint-howl .howl-word { font: italic 600 26px var(--serif); color: var(--accent); letter-spacing: 1px; }
.hint-howl .zzz-label { font: 11px var(--sans); letter-spacing: 1.5px; color: var(--muted); }
.hint-zzz .zzz-label { font: 11px var(--sans); letter-spacing: 1.5px; color: var(--muted); }
.hint-zzz[aria-pressed="true"] .zzz { font-size: 24px; }
.hint-zzz .sun { width: 26px; height: 26px; display: block; color: var(--sun); }

/* 握手: crossfade to a redrawn "paw up" frame (see tools/make_paw.py); the paw layer bobs on top */
.shake-rig { position: absolute; inset: 0; opacity: 0; transition: opacity .32s ease; pointer-events: none; }
.shake-rig img { position: absolute; inset: 0; width: 100%; height: 100%; user-select: none; }
.shake-paw { transform-origin: var(--paw-origin, 50% 70%); }   /* elbow, per pet: character.pawOrigin */
.dog > img { transition: opacity .32s ease; }
.dog.shaking > img { opacity: 0; }
.dog.shaking .shake-rig { opacity: 1; }
.dog.shaking .shake-paw { animation: paw-bob 2s ease-in-out .35s both; }

@keyframes paw-bob {
  0%, 100% { transform: none; }
  22%, 66% { transform: translate(.3%, -1.4%) rotate(-4deg); }
  44%      { transform: translate(.1%, .3%) rotate(1deg); }
  85%      { transform: translate(.1%, .2%); }
}
@keyframes breathe { 50% { transform: translateY(-5px) scale(1.006); } }
@keyframes happy { 25% { transform: rotate(-3deg) translateY(-8px); } 75% { transform: rotate(3deg) translateY(-8px); } }
@keyframes snack { 50% { transform: translateY(5px) rotate(1deg); } }
@keyframes float-up { 0% { opacity: 0; transform: translateY(0) scale(.5); } 20% { opacity: 1; } 100% { opacity: 0; transform: translateY(-120px) rotate(15deg) scale(1.3); } }

@media (min-width: 1500px) {
  .hero-canvas { max-width: 1500px; margin-inline: auto; }
  .dog-stage { width: calc(670 * var(--k)); height: calc(670 * var(--k)); top: calc(160 * var(--k)); }
}
@media (max-width: 1000px) {
  .hero-canvas { --D: 770; }
  .hint { font-size: 15px; }
  /* narrow tablets: keep the hints inside the viewport */
  .hint-head { left: max(10px, calc(50% - 470 * var(--k))); top: calc(290 * var(--k)); }
  .hint-paw { left: min(calc(100% - 230px), calc(50% + 255 * var(--k))); top: calc(580 * var(--k)); }
  .hint-nose { left: max(10px, calc(50% - 470 * var(--k))); top: calc(420 * var(--k)); }
  .hint-body { left: max(10px, calc(50% - 470 * var(--k))); top: calc(555 * var(--k)); }
  .hint-zzz { left: min(calc(100% - 150px), calc(50% + 330 * var(--k))); top: calc(270 * var(--k)); }
  .hint-howl { left: min(calc(100% - 150px), calc(50% + 330 * var(--k))); top: calc(410 * var(--k)); }
  .hint-name { left: auto; right: 0; top: calc(100% - 2px); text-align: right; transform: rotate(-3deg); } /* under the end of the word */
  .dog-stage { width: calc(575 * var(--k)); height: calc(575 * var(--k)); top: calc(135 * var(--k)); }
  .floor-shadow { bottom: 7%; }
}
@media (max-width: 700px) {
  /* Phones: a top-to-bottom stack instead of hints in the corners (which kept colliding with the
     ears). The canvas fills the hero; the character's size is whatever fits between the title (--T) and
     the hint strip at the bottom (--B), capped at 112vw, and he is centred in that space. */
  .page-home { min-height: 520px; }
  .hero-canvas { --T: 150px; --B: 76px; --S: min(120vw, 100cqh - var(--T) - var(--B)); --top: calc(var(--T) + (100cqh - var(--T) - var(--B) - var(--S)) / 2);
    top: 0; height: 100%; transform: none; }
  .hero h1 { font-size: min(16.5vw, 64px); margin-top: 30px; }
  .dog-stage { width: var(--S); height: var(--S); top: var(--top); }
  .floor-shadow { bottom: 1%; }
  .orbit-one { width: calc(var(--S) * .92); height: calc(var(--S) * .9); top: calc(var(--top) + var(--S) * .06); }
  .orbit-two { width: calc(var(--S) * .78); height: calc(var(--S) * 1.02); top: calc(var(--top) - var(--S) * .02); }

  /* the hint strip */
  .hint { font-size: 13px; gap: 4px; line-height: 1.5; white-space: nowrap; }
  .hint svg { display: none; } /* no arrows on phones */
  /* 摸摸頭: upper right of his head, the other side from the 叫我嗎？ bubble */
  .hint-head { left: auto; right: 18px; top: max(118px, calc(var(--top) - var(--S) * .02 - 22px)); text-align: right; transform: rotate(3deg); }
  /* bottom row under his paws: zzz on the left, 握手 on the right, level with each other */
  .hint-paw { left: auto; right: 18px; top: min(calc(var(--top) + var(--S) * .99 + 22px), calc(100% - 56px)); bottom: auto; flex-direction: column; align-items: flex-end; text-align: right; transform: rotate(3deg); }
  .hint-nose { left: 14px; right: auto; top: calc(var(--top) + var(--S) * .38); text-align: left; transform: rotate(-3deg); }
  .hint-body { left: 10px; right: auto; top: calc(var(--top) + var(--S) * .58); transform: rotate(-3deg); padding: 6px 10px; white-space: nowrap; }
  .hint-body .praise { font-size: 18px; }
  .hint-body .zzz-label { font-size: 10px; }
  .hint-zzz { left: 10px; right: auto; top: min(calc(var(--top) + var(--S) * .99 + 16px), calc(100% - 66px)); bottom: auto; transform: rotate(-3deg); flex-direction: column; align-items: flex-start; gap: 0; padding: 6px 10px; white-space: nowrap; }
  .hint-zzz .zzz { font-size: 20px; }
  .hint-howl { left: 10px; right: auto; top: calc(var(--top) + var(--S) * .2); transform: rotate(-3deg); padding: 6px 10px; white-space: nowrap; }
  .hint-howl .howl-word { font-size: 18px; }
  .hint-howl .zzz-label { font-size: 10px; }
  .hint-zzz .zzz-label { font-size: 10px; }
  .hint-zzz .sun { width: 20px; height: 20px; }

  /* name hint: one small line under "hello," */
  /* under "hello,": the hint is positioned on the h1 (em made static); "hello" starts 2.33 title
     font-sizes left of centre (Playfair italic, measured) */
  .hero h1 em { position: static; }
  .hint.hint-name { font-size: 14px; left: calc(50% - 2.33 * min(16.5vw, 64px) + 6px); right: auto; top: calc(100% + 2px); bottom: auto; transform: rotate(-3deg); }
  /* the name hint gets a short one-line label on phones */
  .hint-name .long { display: none; }
  .hint-name .short { display: inline; }
  .hint-nose .long, .hint-body .long { display: none; }
  .hint-nose .short, .hint-body .short { display: inline; }

  /* 叫我嗎？ bubble: over the empty corner left of his head */
  .ask { left: max(0px, calc((var(--S) - 100vw) / 2 + 14px)); top: 2%; font-size: 14px; padding: 5px 13px 6px; } /* 14px in from the screen edge (the stage is wider than the screen) */
}
@media (prefers-reduced-motion: reduce) { .heart { opacity: 0; } .dog { transition: none; } .ask { animation-duration: .01s; } }
