.element-window-element-meter {
  position: relative;
  width: 13cqh;
  margin: 2% auto;
  height: 3.2cqh;
  border-radius: 0.7cqh;
}

.element-window-element-meter-inner-container {
  padding: 0;
  display: block;
  height: 100%;
  margin: auto;
  width: fit-content;
}

.element-window-element-icon {
  height: 2.2cqh;
  float: left;
  margin-top: 0.5cqh;
  margin-right: 1cqh;
}

.element-window-meter-value {
  color: black;
  margin-top: 0.25cqh;
  font-size: 2.2cqh;
  float: left;
}

.element-window-action-buttons {
  position: relative;
  margin-top: 3cqh;
  border-bottom: 1px solid white;
  height: 17cqh;
}

.element-window-action-button {
  position: relative;
  display: inline-flex;
  width: calc(33.33% - 4.667cqh);
  height: 13cqh;
  color: white;
  border-radius: 2cqh;
  border: none;
  margin-left: 4cqh;
  transition:
    color,
    background-color 0.1s;

  &:first-child {
    margin-left: 2cqh;
  }
  &:hover {
    cursor: pointer;
    filter: brightness(1.2);
  }
  &:disabled {
    cursor: not-allowed;
    filter: none;
    background-color: #999;
    color: #555;
    transform: none !important;
    box-shadow: 0 1cqh 0 0 #555 !important;

    .footer-lock-icon {
      display: inline-block;
    }

    .element-window-cost-icon {
      fill: #555;
      transition: fill 0.1s;
    }
  }
  &:active {
    transform: translateY(1cqh);
    box-shadow: none;
  }
}

#element-window-create-earth-button {
  margin: auto;
}

.element-window-cost-icon {
  height: 3cqh;
  margin: auto;
  top: 0.7cqh;
  right: 0;
  position: absolute;
  left: 0;
  fill: #fff;
}

.element-window-action-text {
  font-size: 2.2cqh;
  text-align: center;
  top: 4cqh;
  display: block;
  width: 100%;
  left: 0;
  position: absolute;
  height: 12cqh;
  font-weight: 600;
}

.element-window-action-cost {
  display: inline-block;
  position: absolute;
  text-align: center;
  left: 0;
  right: 0;
  width: 100%;
  bottom: 0.7cqh;
  font-size: 2.5cqh;
}

.element-window-boost-buttons-container {
  width: calc(16.65% - 4.667cqh);
  display: inline-flex;
  height: 13cqh;
}

.element-window-boost-button {
  width: 6cqh;
  height: 6cqh;
  position: absolute;
  margin: 0 !important;
  font-size: 4cqh;
  text-align: center;
  display: block;
  &:last-child {
    top: 7.5cqh;
  }
}

#element-window-seed-breeze-button {
  margin-left: 15%;
}

.element-window-practice-info {
  text-align: center;
  margin: 3cqh 0;
}

.element-window-practice-heading {
  font-size: 3.6cqh;
  font-weight: 700;
  margin: 0 0 3cqh;
}

.element-window-practice-info p {
  font-size: 3cqh;
  line-height: 1.35;
  margin: 0 0 1.5cqh;
}

.element-window-practice-info p:last-child {
  margin-bottom: 0;
}

/* Timed-round readouts. Removed when practice mode replaced the timed round;
   restored for the simplified free game, which plays the timed round again.
   Only emitted when window.SIMPLE_MODE is set (see menu-templates.js). */
.element-window-daily-max {
  font-size: 3cqh;
  margin-top: 3cqh;
  text-align: center;
}

.element-window-top-score {
  font-size: 2.5cqh;
  margin-bottom: 3.5cqh;
  text-align: center;
}

.element-window-time {
  font-size: 3.5cqh;
  text-align: center;
  margin-top: 2cqh;
  margin-bottom: 0;
}

.crystal-time-active {
  color: #f281f2;
  font-weight: 700;
  animation: crystal-time-pulse 1.5s infinite;
}

@keyframes crystal-time-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

.element-window-blessing-active {
  font-weight: bold;
  animation: elementBlessingPulse 3s linear infinite;
}

@keyframes elementBlessingPulse {
  0% {
    color: #ff4444;
    text-shadow: 0 0 8px #ff444488;
  }
  16% {
    color: #ff8800;
    text-shadow: 0 0 8px #ff880088;
  }
  33% {
    color: #ffdd00;
    text-shadow: 0 0 8px #ffdd0088;
  }
  50% {
    color: #44ff44;
    text-shadow: 0 0 8px #44ff4488;
  }
  66% {
    color: #4488ff;
    text-shadow: 0 0 8px #4488ff88;
  }
  83% {
    color: #cc44ff;
    text-shadow: 0 0 8px #cc44ff88;
  }
  100% {
    color: #ff4444;
    text-shadow: 0 0 8px #ff444488;
  }
}

.element-window-key-progress {
  margin: 3.5cqh 20% 0;
}

.element-window-key-progress-bar {
  position: relative;
  width: 100%;
  height: 2.5cqh;
  background-color: rgba(0, 0, 0, 0.15);
  border-radius: 1.25cqh;
  overflow: visible;
}

.element-window-key-progress-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #4caf50, #8bc34a);
  border-radius: 1.25cqh;
  transition: width 0.3s;
}

.element-window-key-progress-text {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 1.8cqh;
  opacity: 0.8;
  pointer-events: none;
}

.element-window-blessing-icon {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  font-weight: bold;
  font-size: 2cqh;
  opacity: 0.4;
  transition: opacity 0.3s;
  padding: 0 0.5cqh;
}

.element-window-play-button {
  font-size: 4cqh;
  padding: 1.5cqh 6cqh;
  margin: 6cqh auto 2cqh;
}

.element-window-play-button-icon {
  height: 3cqh;
  fill: white;
}

.element-window-crystal-row {
  display: flex;
  justify-content: center;
  gap: 3cqh;
  margin-top: 0;
  margin-bottom: 2cqh;
}

.crystal-use-button {
  position: relative;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.5cqh;
  border-radius: 1cqh;
  transition:
    opacity 0.2s,
    filter 0.2s;
}

.crystal-use-button:disabled,
.crystal-use-button.crystal-empty {
  opacity: 0.3;
  cursor: not-allowed;
  filter: grayscale(1);
}

.crystal-use-button.crystal-active {
  animation: brightness-pulse 1.5s infinite;
}

.crystal-use-button:hover:not(:disabled) {
  filter: brightness(1.2);
}

.crystal-use-icon {
  height: 4cqh;
  width: 4cqh;
  display: block;
}

.crystal-use-count {
  position: absolute;
  bottom: -0.5cqh;
  right: -0.5cqh;
  background-color: #383a5a;
  color: white;
  font-size: 1.8cqh;
  font-weight: 600;
  min-width: 2.5cqh;
  height: 2.5cqh;
  line-height: 2.5cqh;
  text-align: center;
  border-radius: 50%;
  border: 1px solid #6a6a8a;
}

.play-menu-heart {
  display: inline-block;
  height: 4cqh;
}

@keyframes brightness-pulse {
  0% {
    filter: brightness(1);
  }
  50% {
    filter: brightness(1.2);
  }
  100% {
    filter: brightness(1);
  }
}

.meter-pulse {
  animation: brightness-pulse 1s infinite;
}

.play-button {
  margin: 0 auto 0 auto;
}

#cultivate-earth-button {
  bottom: 30cqh;
  width: 60%;
  margin-left: 20%;
}

#call-breeze-button {
  bottom: 40cqh;
  width: 60%;
  margin-left: 20%;
}

#rain-button {
  bottom: 50cqh;
  width: 60%;
  margin-left: 20%;
}

#sun-spark-button {
  bottom: 60cqh;
  width: 60%;
  margin-left: 20%;
}

.logout-button-ll {
  left: 2cqh;
}

.back-arrow-lr {
  right: 2cqh;
}

.menu-button-text {
  position: absolute;
  /* height: 3vb; */
  margin-top: 1cqh;
  font-size: 4cqh;
  vertical-align: middle;
  color: #ccc;
  text-shadow: 1px 1px 2px black;
  background-color: #0009;
  opacity: 0;
  transition: 0.3s;
}

.fade-in {
  opacity: 1 !important;
}

.fade-out {
  opacity: 0;
}

#menu-button-0-text {
  bottom: 17cqh;
  left: 14cqh;
}

#menu-button-1-text {
  bottom: 27cqh;
  left: 14cqh;
}

#menu-button-2-text {
  bottom: 37cqh;
  left: 14cqh;
}

#menu-button-3-text {
  bottom: 47cqh;
  left: 14cqh;
}

#menu-button-4-text {
  bottom: 17cqh;
  right: 14cqh;
}

#menu-button-5-text {
  bottom: 27cqh;
  right: 14cqh;
}

#menu-button-6-text {
  bottom: 37cqh;
  right: 14cqh;
}

#menu-button-7-text {
  bottom: 47cqh;
  right: 14cqh;
}

#menu-button-8-text {
  bottom: 17cqh;
  left: 14cqh;
}

#menu-button-9-text {
  bottom: 27cqh;
  left: 14cqh;
}

#menu-button-10-text {
  bottom: 27cqh;
  left: 14cqh;
}

#canvas-bg {
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: 0;
}

#canvas {
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: 3;
}

#overlay-canvas {
  position: absolute;
  width: 100%;
  height: 100%;
  /* Above .flower-shelf.open (z-index 5) and .flower-left-panel.open
     (z-index 5) so the canvas-drawn fertilizer sack renders in front
     of the moisture meter, thermometer, and other shelf elements —
     matching the document-order layering the legacy DOM sack had
     when it sat inside the shelf alongside those meters. */
  z-index: 10;
  pointer-events: none;
}

/* The .plant-seed-prompt rules and their bounce keyframes stood here. The
   floating seed-breeze button over bare ground is gone — planting is the
   radial menu's wind segment now. */

/* FUE pointer — bouncing arrow that sits above the footer button the player
   needs to press next (see showFuePointer in fue.js). left/top come from the
   target's measured rect, so the keyframes must preserve the -50% centering
   or the arrow jumps half its width on the first frame. */
.fue-pointer-arrow {
  position: absolute;
  width: 7cqh;
  height: 7cqh;
  z-index: 21;
  pointer-events: none;
  animation: fue-pointer-bounce 0.9s ease-in-out infinite;
}

.fue-pointer-arrow svg {
  width: 100%;
  height: 100%;
  fill: white;
  filter: drop-shadow(0 0 0.8cqh rgba(0, 0, 0, 0.55));
}

@keyframes fue-pointer-bounce {
  0%,
  100% {
    transform: translate(-50%, -0.8cqh);
  }
  50% {
    transform: translate(-50%, 0.8cqh);
  }
}

.water-text {
  color: #00f;
}

.fire-text {
  color: #f00;
}

.earth-text {
  color: #7e4100;
}

.wind-text {
  color: #0fff8f;
}

.mountain-background {
  position: absolute;
  bottom: -50%;
  width: 100%;
  z-index: 1;
  transition: bottom 0.8s cubic-bezier(0.22, 1.36, 0.25, 1);
  pointer-events: none;
}

/* Night layer sits stacked on the day layer and fades in via .night-mode. */
.mountain-background-night {
  opacity: 0;
  transition:
    bottom 0.8s cubic-bezier(0.22, 1.36, 0.25, 1),
    opacity 1.5s ease;
}

.night-mode .mountain-background-night {
  opacity: 1;
}

/* Mirror the day layer's reveal animation on the night layer (sibling order
   in flower-container.html keeps the day img first). */
.mountain-background-show ~ .mountain-background-night,
.mountain-background-show-animation ~ .mountain-background-night {
  bottom: 10%;
}

.mountain-background-show-animation {
  bottom: 10%;
}

.mountain-background-show {
  transition: none;
  bottom: 10%;
}

.main-menu-button {
  position: absolute;
  /* display: none; */
  width: 10cqh;
  height: 10cqh;
  border-radius: 50%;
  padding: 0 0 3cqh 0;
  font-size: 6cqh;
  color: white;
  text-align: center;
  z-index: 10;
  margin: 1cqh;
  border: none;
  background: none;

  &:hover {
    cursor: pointer;

    .main-menu-button-background {
      transition: 0.2s;
      transform: rotate(-247deg);
    }
  }

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    background-color: #111;
    margin: 1cqh;
    width: 10cqh;
    height: 10cqh;
    font-size: 8cqh;
  }

  .main-menu-button-foreground {
    position: absolute;
    display: block;
    width: 8cqh;
    height: 8cqh;
    top: 1cqh;
    left: 1cqh;
    background-color: #383a5a;
    border-radius: 50%;
    z-index: 1;
  }

  .main-menu-button-background {
    position: absolute;
    display: block;
    width: 10cqh;
    height: 6cqh;
    top: 2cqh;
    background-color: #e720b8;
    border-radius: 50%;
    transform: rotate(-67deg);
    z-index: -1;
  }
}

#main-menu-button-add {
  bottom: 16cqh;
  left: 10%;
  display: none;
}

#main-menu-button-sub {
  bottom: 28cqh;
  left: 10%;
  display: none;
}

#main-menu-button-mul {
  bottom: 40cqh;
  left: 10%;
  display: none;
}

#main-menu-button-div {
  bottom: 52cqh;
  left: 10%;
  display: none;
}

#main-menu-button-dungeon {
  bottom: 16cqh;
  right: 10%;
  display: none;
}

.main-menu-button-icon {
  top: 2.5cqh;
  height: 5cqh;
  width: 6cqh;
  position: absolute;
  left: 2cqh;
  z-index: 2;
}

.main-menu-button-icon-pulsing {
  animation: pulse-opacity 1s infinite;
}

@keyframes pulse-opacity {
  0% {
    opacity: 0.5;
  }
  50% {
    opacity: 0.8;
  }
  100% {
    opacity: 0.5;
  }
}

/* #main-menu-button-earth {
  bottom: 25vb;
  left: 10%;
}

#main-menu-button-air {
  bottom: 55vb;
  right: 10%;
}

#main-menu-button-water {
  bottom: 25vb;
  right: 10%;
}

#main-menu-button-fire {
  bottom: 55vb;
  left: 10%;
} */

#main-menu-element-buttons {
  position: fixed;
  display: block;
  height: 100%;
  width: 100%;
  max-width: 75vh;
  bottom: 10%;
  transition: 0.3s;
}

#main-menu-profile-buttons {
  position: fixed;
  display: block;
  height: 50%;
  width: 100%;
  max-width: 75vh;
  bottom: -50%;
  transition: 0.5s;
}

#main-menu-flower-buttons {
  position: fixed;
  display: block;
  height: 50%;
  width: 100%;
  max-width: 75vh;
  bottom: -50%;
  transition: 0.5s;
}

#flower-menu {
  display: none;
}

/* The .flower-menu-tab rules stood here. The pull-out shelf handle is gone
   from the markup; the shelf it opened is not. */

/* --- Shelf close arrow --- */

.shelf-close-arrow {
  position: absolute;
  top: 19%;
  right: 0;
  width: 8%;
  z-index: 2;
  border: none;
  background: none;
  cursor: pointer;
  padding: 0;

  img {
    width: 100%;
    display: block;
  }
}

/* === Flower Shelf (right panel) === */

.flower-shelf {
  position: absolute;
  right: -60%;
  top: 0;
  bottom: 0;
  width: 60%;
  z-index: 4;
  transition: right 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}

.flower-shelf.open {
  right: 0;
  z-index: 5;
  /* Let clicks fall through the shelf's empty/decorative areas to the
     canvas underneath (so the player can tap the flower behind the panel).
     Interactive children re-enable pointer-events below. */
  pointer-events: none;
}

/* Re-enable pointer events for interactive shelf children. All clickable
   shelf elements are <button>s; decorative wrappers (trunk, banners,
   branches, images) stay click-through. */
.flower-shelf.open button,
.flower-shelf.open button * {
  pointer-events: auto;
}

/* --- Trunk --- */

/* --- Base oval shadows --- */

/* Base oval shadow lives on the sibling .left-moisture-meter-shadow div
   so it can stay grounded while the meter itself translates up during the
   fertilizer-tutorial drop-in animation. */

/* Sack shadow removed — was a wide blue-tinted radial-gradient drop shadow
   below the sack. Keep the rule empty so any existing references don't break
   if I missed one; remove entirely once verified. */

.shelf-trunk {
  position: absolute;
  right: 0;
  top: 20%;
  bottom: 25%;
  width: 8%;
  background: #94593c;
  border-radius: 1px;
  z-index: 1;
}

/* --- Bee branch + hive --- */

.shelf-bee-section {
  position: absolute;
  top: 30%;
  right: 0;
  width: 60%;
}

.shelf-bee-branch {
  width: 100%;
  display: block;
}

.shelf-bee-panel {
  position: absolute;
  top: 80%;
  right: 45%;
  width: 30%;
  border: none;
  background: none;
  cursor: pointer;
  padding: 0;
  transition: transform 0.15s;

  img {
    width: 100%;
    display: block;
  }

  &:hover {
    transform: scale(1.08);
  }

  &:active {
    transform: scale(0.95);
  }
}

/* --- Info banner --- */

.shelf-info-banner {
  position: absolute;
  top: 13%;
  right: 0;
  width: 70%;
}

.shelf-info-banner-bg {
  width: 100%;
  display: block;
}

.shelf-info-banner-text {
  position: absolute;
  top: 10%;
  left: 12%;
  right: 5%;
  bottom: 15%;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.shelf-flower-name {
  font-family: "KGHappy", "Outfit", sans-serif;
  font-size: 4cqh;
  font-weight: 700;
  color: #f5e6d0;
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.4);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
  margin-bottom: 1cqh;
}

.shelf-flower-timer {
  font-family: "Outfit", sans-serif;
  font-size: 1.6cqh;
  color: #c8b090;
  font-weight: 600;
  line-height: 1.2;
}

.shelf-warning-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4cqh;
  height: 1.4cqh;
  border-radius: 50%;
  border: 0.15cqh solid currentColor;
  font-size: 1cqh;
  font-weight: 700;
  line-height: 1;
  margin-right: 0.8cqh;
  vertical-align: middle;
}

/* --- Watering can --- */

.shelf-watering-can {
  display: none !important;
  position: absolute;
  bottom: 26.5%;
  right: 10%;
  width: 30%;
  border: none;
  background: none;
  cursor: pointer;
  padding: 0;
  z-index: 1;

  img {
    width: 100%;
    display: block;
  }

  &:hover {
    transform: scale(1.08);
  }

  &:active {
    transform: scale(0.95);
  }
}

.shelf-watering-can.watering-active {
  z-index: 50;
}

.shelf-watering-can.shake {
  animation: moisture-shake 0.5s ease-in-out;
}

/* --- Shovel --- */

.shelf-shovel-section {
  position: absolute;
  top: 45%;
  right: 6%;
  width: 15%;
}

.shelf-shovel-bar {
  width: 100%;
  display: block;
}

.shelf-shovel-button {
  position: absolute;
  top: -10%;
  left: 10%;
  transform: translate(-50%, 0);
  width: 80%;
  border: none;
  background: none;
  cursor: pointer;
  padding: 0;
  transition: transform 0.15s;

  img {
    width: 100%;
    display: block;
  }

  &:hover {
    transform: translate(-50%, 0) scale(1.08);
  }

  &:active {
    transform: translate(-50%, 0) scale(0.95);
  }
}

/* === Left Panel === */

.flower-left-panel {
  position: absolute;
  left: -25%;
  top: 0;
  bottom: 0;
  width: 18%;
  z-index: 4;
  transition: left 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}

.flower-left-panel.open {
  left: 14%;
  z-index: 5;
  pointer-events: auto;
}

/* Set on <body> by maybeAutoOpenFlowerShelf around the initial programmatic
   open so the shelf, meter panel, and menu tab snap into place on page load
   instead of sliding in. Removed on the next frame so subsequent user
   open/close still animates normally. */
body.no-shelf-transition .flower-shelf,
body.no-shelf-transition .flower-left-panel {
  transition: none !important;
}

/* --- Daily crow ---
   Sits on top of the moisture meter once the player has claimed their daily
   math session. Anchored to #flower-container (NOT the sliding left panel)
   so when the shelf closes, the panel slides out underneath and the crow
   takes off on its own keyframe immediately. */
.daily-crow {
  position: absolute;
  /* When .flower-left-panel.open: left 14%, width 18%, so meter centerline
     is at 14% + 9% = 23% of the container. Meter bottom: 25% of panel
     (panel is full container height), meter image height ~33cqw. Anchor
     the crow above the meter top cap. */
  bottom: calc(25% + 31cqw);
  left: 26%;
  width: 16.9cqw;
  transform: translateX(-50%);
  pointer-events: auto;
  cursor: pointer;
  z-index: 6;
  opacity: 0;
  display: none;
}

.daily-crow.is-visible,
.daily-crow.is-flying-in,
.daily-crow.is-flying-out {
  display: block;
}

.daily-crow.is-visible {
  opacity: 1;
}

.daily-crow-img {
  display: block;
  width: 100%;
  height: auto;
}

/* Speech bubble — floats above-and-right of the crow. Pointer-events off so
   clicks pass through to the crow itself. No background; this is a hint-text
   surface that will host gameplay hints later. */
.daily-crow-bubble {
  position: absolute;
  bottom: 105%;
  left: 100%;
  pointer-events: none;
  font-family: "Outfit", sans-serif;
  font-weight: 700;
  font-size: 3.12cqw;
  line-height: 1.15;
  color: #2a1a0a;
  text-shadow: 0 0.15cqw 0 #fff, 0 -0.1cqw 0 #fff, 0.15cqw 0 0 #fff,
    -0.15cqw 0 0 #fff;
  width: max-content;
  max-width: 50cqw;
  opacity: 0;
  transition: opacity 0.18s ease-out, transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
  transform: translateY(0.5cqw);
}

.daily-crow.is-talking .daily-crow-bubble {
  opacity: 1;
  transform: translateY(0);
}

/* Bouncing "!" above a bud-mature flower whose bloom alert the player
   dismissed earlier today. JS in flower.js (updateBloomIndicators) sets
   left/top per frame to track the canvas-rendered flower top; CSS owns the
   3-bounces-then-pause animation. Anchor: bottom-center of the "!" sits at
   (left, top), so position math passes the flower's top-center directly. */
.bloom-indicator {
  position: absolute;
  pointer-events: none;
  font-family: "Outfit", sans-serif;
  font-weight: 900;
  font-size: 4.5cqw;
  line-height: 1;
  color: #ffcc33;
  text-shadow: 0 0.2cqw 0 #fff, 0 -0.15cqw 0 #fff, 0.2cqw 0 0 #fff,
    -0.2cqw 0 0 #fff, 0 0.35cqw 0.6cqw rgba(0, 0, 0, 0.35);
  transform: translate(-50%, -100%);
  opacity: 0;
  /* Above the canvas (z-index 3), overlay-canvas (10), and the shelf
     (4–5) so the indicator stays visible regardless of shelf state. */
  z-index: 11;
}

.bloom-indicator.visible {
  opacity: 1;
  animation: bloom-indicator-bounce 2.4s ease-in-out infinite;
}

/* Three decaying bounces (400ms each, peaks at 8.33% / 25% / 41.67%)
   followed by a 1.2s pause at rest (50%–100%). Amplitudes 0.8em → 0.44em
   → 0.2em mirror the JS amplitudes (1.0 / 0.55 / 0.25 of peak). */
@keyframes bloom-indicator-bounce {
  0%, 16.67%, 33.33%, 50%, 100% {
    transform: translate(-50%, -100%);
  }
  8.33% {
    transform: translate(-50%, calc(-100% - 0.8em));
  }
  25% {
    transform: translate(-50%, calc(-100% - 0.44em));
  }
  41.67% {
    transform: translate(-50%, calc(-100% - 0.2em));
  }
}

/* Bouncing "!" above the crow's head — surfaces when chooseHintGroup() returns
   a non-default actionable state (NEEDS_TREASURE / NEEDS_SUN / NEEDS_WATER).
   Suppressed during fly-in/out and the welcome-onboarding flow so it doesn't
   compete with the welcome/heatmap arrows. */
.daily-crow-alert {
  position: absolute;
  bottom: 92%;
  left: 50%;
  pointer-events: none;
  line-height: 1;
  opacity: 0;
  transform: translateX(-50%);
}

.daily-crow-alert-icon {
  display: block;
  height: 7cqw;
  width: auto;
  filter: drop-shadow(0 0.2cqw 0.4cqw rgba(0, 0, 0, 0.35));
}

.daily-crow.has-alert .daily-crow-alert {
  opacity: 1;
  animation: daily-crow-alert-bounce 0.7s ease-in-out infinite;
}

@keyframes daily-crow-alert-bounce {
  0%,
  100% {
    transform: translateX(-50%) translateY(0);
  }
  50% {
    transform: translateX(-50%) translateY(-0.8cqw);
  }
}

/* Two keyframes only — an intermediate keyframe would split the rule's
   easing into two segments and create a visible mid-flight velocity dip
   ("hitch"). Single segment + smooth easing = continuous arc. */
@keyframes daily-crow-fly-in {
  0% {
    transform: translateX(-50%) translate(500%, -380%) rotate(-15deg);
    opacity: 0;
  }
  15% {
    opacity: 1;
  }
  100% {
    transform: translateX(-50%) translate(0, 0) rotate(0);
    opacity: 1;
  }
}

.daily-crow.is-flying-in {
  animation: daily-crow-fly-in 1.2s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes daily-crow-fly-out {
  0% {
    transform: translateX(-50%) translate(0, 0) rotate(0);
    opacity: 1;
  }
  100% {
    transform: translateX(-50%) translate(500%, -380%) rotate(20deg);
    opacity: 0;
  }
}

.daily-crow.is-flying-out {
  animation: daily-crow-fly-out 0.75s cubic-bezier(0.5, 0, 0.75, 0) forwards;
}

/* --- Moisture meter --- */

.left-moisture-meter {
  position: absolute;
  bottom: 25%;
  left: 0;
  width: 100%;
  transform-origin: center center;
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1),
              opacity 0.4s ease-out,
              top 0.35s cubic-bezier(0.22, 1, 0.36, 1),
              left 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Ground shadow under the meter — stationary at the meter's resting base,
   scales 0→1 in sync with the drop-in transform on .left-moisture-meter.
   Replaces the old .left-moisture-meter::before pseudo, keeping the same
   blue tint and footprint so the at-rest look is unchanged. */
.left-moisture-meter-shadow {
  position: absolute;
  bottom: calc(25% - 0.5cqh);
  left: -10%;
  width: 150%;
  height: 2.5cqh;
  background: radial-gradient(ellipse 50% 100%, #445a86 0%, transparent 70%);
  transform: scale(1);
  transform-origin: center center;
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
  z-index: 0;
}

@keyframes meter-needs-pulse {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(0.8); }
}

.left-moisture-meter.needs-sun:not(.zoomed):not(.meter-portaled),
.left-moisture-meter.needs-water:not(.zoomed):not(.meter-portaled) {
  animation: meter-needs-pulse 1.4s ease-in-out infinite;
}

/* DAILY-mode allocation UI: tap meter zone → meter zooms to center for
   interactive sun-level / moisture commits. Tap backdrop to dismiss. */
.meter-zoom-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0);
  z-index: 9998;
  opacity: 0;
  pointer-events: none;
  transition: background 0.3s ease, opacity 0.3s ease;
}

.meter-zoom-backdrop.active {
  background: rgba(0, 0, 0, 0.55);
  opacity: 1;
  pointer-events: auto;
}

/* When portaled into .container, snap the meter to container center via cq
   anchors. position: fixed inside container-type: size resolves against the
   container. translate(-50%, -50%) self-centers on the anchor. The base
   transform with scale 1 holds before .zoomed activates so the position is
   anchored regardless of zoom state. */
/* .meter-portaled holds the stacking promotion only — top/left/transform stay
   on the inline (original) styles so they form the from-state of the lerp. */
.left-moisture-meter.meter-portaled {
  position: absolute !important;
  z-index: 9999;
}

/* .zoomed is the to-state: center on .container via cq anchors, self-center
   with translate(-50%), then scale. !important wins over inline px top/left.
   Removing .zoomed reverts to inline px → browser lerps back. */
.left-moisture-meter.zoomed {
  top: 45cqh !important;
  left: 50cqw !important;
  right: auto !important;
  bottom: auto !important;
  transform: translate(-50%, -50%) scale(2.5);
}

.left-moisture-meter.zoomed .left-moisture-seg {
  cursor: pointer;
  outline: 1px solid rgba(255, 255, 255, 0.15);
}

.left-moisture-meter.zoomed .left-moisture-seg:hover {
  background: rgba(255, 255, 255, 0.1);
}

/* --- Meter zoom adjustment panel ---
   position: absolute relative to .container (matches the meter's positioning
   strategy so both center on the same coordinate space). Sized + positioned
   in cq units so it scales consistently across device / window sizes.
   bottom: 17cqh anchors above the menu-footer (15cqh tall + 2cqh gap);
   left: 50cqw + translateX(-50%) horizontally centers on the meter's center
   (since meter is also centered at 50cqw of .container). */
.meter-zoom-panel {
  position: absolute;
  z-index: 10000;
  left: 55cqw;
  top: 51cqh;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 3cqh;
  padding: 3.5cqh 2.5cqh 2cqh 2.5cqh;
  width: 70cqw;
  max-width: 82cqw;
  background: rgba(30, 22, 18, 0.96);
  border: 0.18cqh solid rgba(255, 220, 180, 0.18);
  border-radius: 1.4cqh;
  color: #f5e6d0;
  font-family: "Outfit", sans-serif;
  box-shadow: 0 0.9cqh 3.2cqh rgba(0, 0, 0, 0.4);
  /* Slide-in from below. The hidden offset uses 50cqh (container-relative)
     instead of a %-of-self translate so the panel is always parked well below
     the container's bottom edge regardless of its own height. */
  transform: translate(-50%, 50cqh);
  pointer-events: none;
  /* Slide-out: 0.35s, matches the meter shrink. */
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.meter-zoom-panel.active {
  transform: translate(-50%, 0);
  pointer-events: auto;
  /* Slide-in: 0.5s, eases in just behind the meter zoom. */
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

.meter-zoom-panel-row {
  display: flex;
  align-items: center;
  gap: 2cqw;
}

.meter-zoom-arrow {
  width: 5cqh;
  height: 5cqh;
  border-radius: 50%;
  border: 0.18cqh solid rgba(255, 220, 180, 0.25);
  background: rgba(255, 255, 255, 0.06);
  color: #f5e6d0;
  font-size: 3cqh;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  padding: 0;
  line-height: 1;
  transition: background 0.15s, transform 0.1s;
}

.meter-zoom-arrow:hover:not(:disabled) {
  background: rgba(255, 220, 180, 0.18);
}

.meter-zoom-arrow:active:not(:disabled) {
  transform: scale(0.92);
}

.meter-zoom-arrow:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.meter-zoom-confirm {
  align-self: center;
  margin-top: 1cqh;
  padding: 1.2cqh 4cqh;
  border-radius: 1cqh;
  border: 0.18cqh solid rgba(255, 220, 180, 0.35);
  background: rgba(255, 220, 180, 0.18);
  color: #f5e6d0;
  font-family: "KGHappy", "Outfit", sans-serif;
  font-size: 2.4cqh;
  font-weight: 700;
  letter-spacing: 0.05em;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s;
}

.meter-zoom-confirm:hover {
  background: rgba(255, 220, 180, 0.3);
}

.meter-zoom-confirm:active {
  transform: scale(0.96);
}

.meter-zoom-readout {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  line-height: 1.15;
}

.meter-zoom-readout-label {
  font-family: "KGHappy", "Outfit", sans-serif;
  font-size: 3.2cqh;
  font-weight: 700;
  color: #f5e6d0;
  margin-bottom: 0.4cqh;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.8cqw;
  cursor: pointer;
}

#meter-zoom-sun-label.at-zero,
#meter-zoom-water-label.at-zero {
  color: #ff6b6b;
}

.meter-zoom-panel.over-saturated #meter-zoom-water-label,
.meter-zoom-panel.over-saturated .meter-zoom-panel-row-water .meter-zoom-readout-value {
  color: #ff6b6b;
}

#left-moisture-percent.over-saturated {
  color: #ff6b6b;
}

.meter-zoom-help-btn {
  width: 2.6cqh;
  height: 2.6cqh;
  border-radius: 50%;
  border: 0.15cqh solid rgba(255, 220, 180, 0.4);
  background: rgba(255, 255, 255, 0.06);
  color: #f5e6d0;
  font-family: "Outfit", sans-serif;
  font-size: 1.6cqh;
  font-weight: 700;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.15s, transform 0.1s;
}

.meter-zoom-help-btn:hover {
  background: rgba(255, 220, 180, 0.2);
}

.meter-zoom-help-btn:active {
  transform: scale(0.92);
}

/* Help popover — full-area backdrop with the inner box positioned to mirror
   the meter-zoom-panel (centered at 55cqw to account for the 10cqw left
   sidebar, same horizontal anchor as the panel below it). */
.meter-zoom-help {
  position: absolute;
  inset: 0;
  z-index: 10001;
  background: rgba(0, 0, 0, 0.6);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

.meter-zoom-help.active {
  opacity: 1;
  pointer-events: auto;
}

.meter-zoom-help-box {
  position: absolute;
  left: 55cqw;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 65cqw;
  max-width: 78cqw;
  padding: 4.5cqh 5cqw;
  background: rgba(30, 22, 18, 0.97);
  border: 0.2cqh solid rgba(255, 220, 180, 0.18);
  border-radius: 1.6cqh;
  box-shadow: 0 1cqh 3.5cqh rgba(0, 0, 0, 0.4);
  color: #e7d4b3;
  font-family: "Outfit", sans-serif;
}

.meter-zoom-help-title {
  margin: 0 0 1.4cqh 0;
  font-family: "KGHappy", "Outfit", sans-serif;
  font-size: 3.4cqh;
  font-weight: 700;
  color: #f5e6d0;
  text-align: center;
}

.meter-zoom-help-body {
  font-size: 2cqh;
  line-height: 1.45;
}

.meter-zoom-help-body p {
  margin: 0 0 1cqh 0;
}

.meter-zoom-help-body p:last-child {
  margin-bottom: 0;
}

.meter-zoom-help-close {
  position: absolute;
  top: 1cqh;
  right: 1cqh;
  width: 3.4cqh;
  height: 3.4cqh;
  border-radius: 50%;
  border: 0.15cqh solid rgba(255, 220, 180, 0.25);
  background: rgba(255, 255, 255, 0.08);
  color: #f5e6d0;
  font-size: 2.4cqh;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.meter-zoom-help-close:hover {
  background: rgba(255, 220, 180, 0.18);
}

.meter-zoom-readout-value {
  font-family: "Outfit", sans-serif;
  font-size: 2.6cqh;
  font-weight: 700;
  color: #e7d4b3;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.7cqw;
}

.meter-zoom-readout-icon {
  width: 3cqh;
  height: 3cqh;
  fill: currentColor;
}

.meter-zoom-readout-cost {
  font-size: 1.6cqh;
  color: #c8b090;
  margin-top: 0.3cqh;
}

.meter-zoom-panel-relation {
  font-size: 1.6cqh;
  color: #c8b090;
  text-align: center;
  padding-top: 1cqh;
  border-top: 0.12cqh solid rgba(255, 220, 180, 0.12);
}

.left-moisture-meter-bg {
  width: 100%;
  display: block;
}

.left-moisture-meter-zones {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
}

.left-meter-zone-thermo {
  width: 35%;
  height: 100%;
  border: none;
  background: none;
  cursor: pointer;
  padding: 0;
  position: relative;
}

.left-thermo-fill {
  position: absolute;
  bottom: 70%;
  left: 50%;
  width: 8%;
  height: 0%;
  max-height: 18%;
  background-color: #f4e1d0;
  border-radius: 1px;
  transition: height 0.3s;
  pointer-events: none;
}

.left-meter-zone-gauge {
  width: 65%;
  height: 100%;
  border: none;
  background: none;
  cursor: pointer;
  padding: 0;
  position: relative;
}

.left-moisture-segments {
  position: absolute;
  top: 8.9%;
  left: 21%;
  right: 23%;
  height: 35.7%;
  display: flex;
  flex-direction: column;
  gap: 3%;
  pointer-events: none;
}

.left-moisture-seg {
  flex: 1;
  border-radius: 1px;
  position: relative;
  overflow: hidden;
}

.left-moisture-percent {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: "Outfit", sans-serif;
  font-size: 1.4cqh;
  font-weight: 700;
  color: #f4e1d0;
  pointer-events: none;
  z-index: 1;
}

.left-moisture-seg-fill {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 0%;
  background-color: var(--water-color);
  transition: height 0.3s;
}

/* --- Fertilizer sack --- */

/* Fertilizer sack — sits on the shelf ledge inside .flower-shelf, so it
   slides in/out naturally when the shelf opens/closes. Positioned at the
   ledge's right area (was the watering can's previous spot). z-index sits
   above the shelf trunk so the sack draws on top of the wooden ledge. */
.left-fertilizer-sack {
  position: absolute;
  bottom: 22%;
  right: 22%;
  width: 30%;
  border: none;
  background: none;
  cursor: pointer;
  padding: 0;
  z-index: 11;
  transition: transform 0.15s;

  /* Ground shadow beneath the sack. */
  &::after {
    content: "";
    position: absolute;
    bottom: -0.5cqh;
    left: -60%;
    width: 220%;
    height: 2.5cqh;
    background: radial-gradient(ellipse 50% 100%, #445a86 0%, transparent 70%);
    pointer-events: none;
    z-index: -1;
  }

  img {
    width: 100%;
    display: block;
  }

  &:hover {
    transform: scale(1.08);
  }

  &:active {
    transform: scale(0.95);
  }
}

/* --- Harvest button --- */

button.flower-action-button {
  display: none;
  bottom: 17cqh;
  left: 10cqh;
  position: absolute;
  font-size: 2cqh;
  z-index: 10;
}

/* Remove this after temp note */
#landing-heading {
  font-size: 6cqh;
  margin: 10% auto;
  text-align: center;
  opacity: 0;
  position: absolute;
  width: 100%;
  z-index: 10;
}

.bouncing-arrow-left,
.bouncing-arrow-up,
.bouncing-arrow-right,
.bouncing-arrow-down {
  position: absolute;
  height: 10cqh;
  z-index: 999;
  pointer-events: none;
  filter: drop-shadow(0 0 1cqh rgba(0, 0, 0, 0.5));
}

.tutorial-watering-finger {
  position: absolute;
  top: 60%;
  left: 50%;
  width: 9cqh;
  height: 9cqh;
  font-size: 8cqh;
  line-height: 9cqh;
  text-align: center;
  z-index: 999;
  pointer-events: none;
  filter: drop-shadow(0 0.3cqh 0.5cqh rgba(0, 0, 0, 0.4));
  animation: tutorial-finger-trace 2.5s ease-in-out infinite;
}

@keyframes tutorial-finger-trace {
  0% {
    transform: translateX(-18cqw);
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  50% {
    transform: translateX(18cqw);
    opacity: 1;
  }
  60% {
    opacity: 0;
  }
  100% {
    transform: translateX(-18cqw);
    opacity: 0;
  }
}
.bouncing-arrow-left {
  animation: bounce-left 2s infinite;
}
.bouncing-arrow-up {
  animation: bounce-up 2s infinite;
}
.bouncing-arrow-right {
  animation: bounce-right 2s infinite;
}
.bouncing-arrow-down {
  animation: bounce-down 2s infinite;
}

@keyframes bounce-right {
  0%,
  20%,
  50%,
  80%,
  100% {
    transform: translateX(0) rotate(-90deg);
  }
  40% {
    transform: translateX(-30px) rotate(-90deg);
  }
  60% {
    transform: translateX(-15px) rotate(-90deg);
  }
}

@keyframes bounce-left {
  0%,
  20%,
  50%,
  80%,
  100% {
    transform: translateX(0) rotate(90deg);
  }
  40% {
    transform: translateX(30px) rotate(90deg);
  }
  60% {
    transform: translateX(15px) rotate(90deg);
  }
}

@keyframes bounce-up {
  0%,
  20%,
  50%,
  80%,
  100% {
    transform: translateY(0) rotate(180deg);
  }
  40% {
    transform: translateY(30px) rotate(180deg);
  }
  60% {
    transform: translateY(15px) rotate(180deg);
  }
}

@keyframes bounce-down {
  0%,
  20%,
  50%,
  80%,
  100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-30px);
  }
  60% {
    transform: translateY(-15px);
  }
}

/* FUE Create Earth Button */
.fue-create-earth-button {
  position: fixed;
  bottom: 25%;
  left: 0;
  right: 0;
  margin: 0 auto;
  width: fit-content;
  z-index: 100;
  font-size: 4cqh;
  display: flex;
  align-items: center;
  gap: 1cqh;
  white-space: nowrap;
  background-color: var(--earth-color);
  box-shadow: 0 0.5cqh 0 0 var(--earth-color-shadow);
}

.fue-create-earth-icon {
  height: 3.5cqh;
  fill: white;
}

.fue-create-earth-arrow {
  position: fixed;
  bottom: calc(25% + 8cqh);
  left: calc(50% - 5cqh);
}

/* Floating tutorial hint text — non-dialog, hovers over canvas.
   Sizing and positioning are in container query units so the hint
   stays consistent across viewport sizes. */
.tutorial-hint-text {
  position: absolute;
  z-index: 100;
  pointer-events: none;
  font-size: 3.2cqh;
  font-weight: 600;
  color: #fff;
  text-shadow:
    0 0.2cqh 0.4cqh rgba(0, 0, 0, 0.4),
    0 0 0.8cqh rgba(0, 0, 0, 0.6);
  white-space: nowrap;
}

/* Variant: positioned above the flower-menu open tab. The tab itself
   sits at top: 18%, right: 0 (see .flower-menu-tab), so this label
   anchors to the container's right edge a few cqh above. */
.tutorial-hint-text--flower-tab {
  top: 13cqh;
  right: 9.5cqw;
  text-align: right;
}

/* Variant: positioned above the canvas-drawn fertilizer sack on the
   ground. The sack rests at canvasWidth * 0.35 / canvasHeight * 0.78
   (drawFertilizerSack), so this anchors to left: 35cqw with top above
   the sack's visible body. */
.tutorial-hint-text--fertilizer-sack {
  top: 55cqh;
  left: 35cqw;
  transform: translateX(-50%);
  text-align: center;
}

/* Fertilizer sack is now canvas-drawn (see drawFertilizerSack in
   flower.js). The legacy HTML/CSS overlay was removed in favor of
   canvas rendering for consistency with the rest of the visual scene. */

/* While the first-day tutorial is gating the fertilizer arc (GROWTH_INTRO
   intro on screen or the sack is in the sky / mid-drop), hide the
   moisture meter and sun thermometer so the player's focus is on the
   sack. The body class is toggled by first-day-tutorial.js.
   The moisture meter uses transform + opacity (not visibility) so that
   when the gating class is removed, it drops in from above with the
   base transition's easing — see .left-moisture-meter rule. */
body.fertilizer-tutorial-gating .left-moisture-meter {
  transform: translateY(-110cqh);
  opacity: 0;
  pointer-events: none;
}
body.fertilizer-tutorial-gating .left-moisture-meter-shadow {
  transform: scale(0);
}
body.fertilizer-tutorial-gating .left-meter-zone-thermo,
body.fertilizer-tutorial-gating .left-meter-zone-gauge {
  visibility: hidden;
}
