:root {
  --space-deep: #1b1240;
  --space-mid: #362463;
  --panel: #2a1f52;
  --panel-light: #4a3a82;
  --panel-dark: #170f33;
  --grass-light: #8fd14f;
  --grass-dark: #5a9c2f;
  --accent: #ffd76b;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 24px;
  min-height: 100vh;
  background:
    radial-gradient(1px 1px at 10% 20%, #fff 100%, transparent),
    radial-gradient(1px 1px at 80% 10%, #fff 100%, transparent),
    radial-gradient(1px 1px at 60% 70%, #fff 100%, transparent),
    radial-gradient(1px 1px at 30% 85%, #fff 100%, transparent),
    radial-gradient(1px 1px at 90% 55%, #fff 100%, transparent),
    radial-gradient(1px 1px at 45% 40%, #fff 100%, transparent),
    radial-gradient(1px 1px at 15% 60%, #fff 100%, transparent),
    linear-gradient(180deg, var(--space-deep), var(--space-mid));
  font-family: 'Comic Sans MS', 'Segoe UI', cursive, sans-serif;
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #f0e9ff;
}

.pet-wrap {
  background: var(--panel);
  padding: 20px;
  border: 6px solid;
  border-color: var(--panel-light) var(--panel-dark) var(--panel-dark) var(--panel-light);
  border-radius: 12px;
  max-width: 480px;
  width: 100%;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}

/* "The home page for the expedition phase" card follow-up (2026-07-25):
   "The two nav bars and the event banner should show above every page"
   - .event-banner/.pet-hub-bar and their rules moved to nav.css (shared
   by every page that includes _topnav.html now, not just this one). */

.pet-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 10px;
}

/* Mobile-only fallback for My Path/Train/Send to Teams - hidden for
   free on desktop since it lives inside #pet-mobile-view, which the
   existing min-width:900px breakpoint already hides wholesale (see
   below) once the per-slot desktop boxes - which already have their
   own copies of all three - become visible instead. */
.pet-mobile-quick-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: center;
  margin: 4px 0 10px;
}

.link-btn {
  padding: 6px 12px;
  cursor: pointer;
  border: 2px solid;
  border-color: var(--grass-light) var(--grass-dark) var(--grass-dark) var(--grass-light);
  background: #79c94a;
  color: #23360f;
  font-weight: bold;
  font-family: inherit;
  border-radius: 4px;
  font-size: 13px;
  text-decoration: none;
}

/* Full-width entry points into the parts/closet modals - chunkier and more
   "pressable" than .link-btn since these open a whole feature, not just
   navigate. Gold-gradient bevel with a drop shadow that collapses on
   press, matching the game's retro-arcade button language. */
.menu-open-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 12px 16px;
  margin: 6px 0 14px;
  font-family: inherit;
  font-size: 15px;
  font-weight: bold;
  color: #2b1b00;
  background: linear-gradient(135deg, #fff0c2, var(--accent) 55%, #f0a940);
  border: 3px solid;
  border-color: #fff6dc #a5701a #a5701a #fff6dc;
  border-radius: 10px;
  cursor: pointer;
  box-shadow: 0 4px 0 #8a5c15, 0 6px 12px rgba(0, 0, 0, 0.35);
  transition: transform 0.08s ease, box-shadow 0.08s ease, filter 0.15s ease;
}

.menu-open-btn:hover {
  filter: brightness(1.06);
}

.menu-open-btn:active {
  transform: translateY(4px);
  box-shadow: 0 0 0 #8a5c15, 0 2px 5px rgba(0, 0, 0, 0.35);
}

/* "Assemble your alien and Closet can each be 50/50 on a shared line"
   (2026-07-25) - #parts-section/#closet-section each keep their own
   independent hidden/shown toggle in pet.js (renderPartPicker/
   renderCloset); this wrapper only lays out whichever is visible.
   flex:1 1 0 on both means if only ONE is ever visible (the other still
   `.hidden`), it naturally expands to fill the whole row instead of
   staying pinned to half width. */
.menu-btn-row {
  display: flex;
  gap: 10px;
}

.menu-btn-row .parts-section,
.menu-btn-row .closet-section {
  flex: 1 1 0;
  min-width: 0;
}

.menu-btn-row .menu-open-btn {
  width: 100%;
}

/* "Have Assemble Your Alien flash if a part is available but not
   equipped" (2026-07-25) - toggled in pet.js's renderPartPicker()/
   buildDesktopOccupiedCard() whenever an unlocked part slot has no
   `chosen` shape yet. */
@keyframes menu-btn-flash {
  0%, 100% { box-shadow: 0 4px 0 #8a5c15, 0 6px 12px rgba(0, 0, 0, 0.35); }
  50% { box-shadow: 0 4px 0 #8a5c15, 0 0 18px 6px var(--accent); }
}

.menu-open-btn.flash-attention {
  animation: menu-btn-flash 1.3s ease-in-out infinite;
}

.danger-btn {
  border-color: #ff9a9a #b33a3a #b33a3a #ff9a9a;
  background: #e05656;
  color: #3a0d0d;
}

.debug-btn {
  border-color: #ffe08a #c99a2e #c99a2e #ffe08a;
  background: var(--accent);
  color: #3a2a05;
}

.hidden {
  display: none !important;
}

.unlock-toast-container {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  pointer-events: none;
  width: 100%;
  padding: 0 12px;
}

.unlock-toast {
  background: var(--panel-light);
  border: 3px solid;
  border-color: var(--accent) #c99a2e #c99a2e var(--accent);
  border-radius: 10px;
  padding: 10px 18px;
  text-align: center;
  font-size: 14px;
  line-height: 1.4;
  color: #fff8e6;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
  max-width: 320px;
  opacity: 0;
  transform: translateY(-16px);
  transition: opacity 0.35s ease, transform 0.35s ease;
}

.unlock-toast.show {
  opacity: 1;
  transform: translateY(0);
}

.unlock-toast strong {
  color: var(--accent);
}

.planet-tagline {
  text-align: center;
  margin: 0 0 12px;
  font-size: 11px;
  color: #cbb8ff;
  font-style: italic;
}

.pet-name-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 20px;
  font-weight: bold;
  margin-bottom: 6px;
}

.slot-arrow-btn {
  border: 2px solid var(--panel-light);
  background: var(--panel);
  color: var(--accent);
  border-radius: 8px;
  width: 32px;
  height: 32px;
  font-size: 14px;
  cursor: pointer;
  flex-shrink: 0;
}

.slot-arrow-btn:hover {
  background: var(--panel-light);
}

.slot-indicator {
  text-align: center;
  font-size: 11px;
  color: #cbb8ff;
  margin: -2px 0 8px;
}

.tiny-btn {
  padding: 2px 8px;
  font-size: 11px;
  cursor: pointer;
  background: none;
  border: none;
  text-decoration: underline;
  color: #cbb8ff;
}

.stage-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  margin-bottom: 10px;
}

.stage-name {
  font-weight: bold;
  color: var(--accent);
  font-size: 14px;
}

.xp-bar-track {
  width: 100%;
  height: 10px;
  background: var(--panel-dark);
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid #000a;
}

.xp-bar-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #ffd76b, #ff9f4a);
  transition: width 0.4s ease;
}

.xp-label {
  font-size: 11px;
  color: #cbb8ff;
}

.pet-stage-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: radial-gradient(ellipse at center, #4a3a82 0%, #2a1f52 80%);
  border-radius: 12px;
  padding: 20px 10px;
  margin-bottom: 8px;
  min-height: 140px;
  transition: background 0.4s ease;
}

/* Planet environment theming - see Pet.current_environment in pet.py */
#pet-wrap[data-environment="water"] .pet-stage-area {
  background: radial-gradient(ellipse at center, #2f6f8f 0%, #163a4a 80%);
}

#pet-wrap[data-environment="sky"] .pet-stage-area {
  background: radial-gradient(ellipse at center, #7fb8e0 0%, #3a6a92 80%);
}

.pet-sprite {
  position: relative;
  z-index: 2;
  font-size: 80px;
  line-height: 1;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.5));
  transition: transform 0.15s ease;
  background: none;
  border: none;
  padding: 0;
  cursor: default;
  font-family: inherit;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.pet-sprite.has-image {
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

.pet-sprite.clickable {
  cursor: pointer;
}

.pet-sprite.clickable:active {
  transform: scale(0.9);
}

/* Personality animations - only applied once hatched (see pet.js), so
   there's no conflict with the egg's clickable squish above. */
@keyframes anim-bounce { 0%, 100% { translate: 0 0; } 50% { translate: 0 -6px; } }
@keyframes anim-shake { 0%, 100% { rotate: 0deg; } 25% { rotate: -4deg; } 75% { rotate: 4deg; } }
@keyframes anim-tilt { 0%, 100% { rotate: 0deg; } 50% { rotate: 6deg; } }
@keyframes anim-shrink { 0%, 100% { scale: 1; } 50% { scale: 0.94; } }
@keyframes anim-pulse { 0%, 100% { scale: 1; } 50% { scale: 1.06; } }
@keyframes anim-wobble { 0%, 100% { rotate: 0deg; translate: 0 0; } 25% { rotate: -3deg; translate: -2px 0; } 75% { rotate: 3deg; translate: 2px 0; } }
@keyframes anim-droop { 0%, 100% { translate: 0 0; } 50% { translate: 0 2px; } }
@keyframes anim-nod { 0%, 100% { rotate: 0deg; } 50% { rotate: -8deg; } }

.anim-bounce { animation: anim-bounce 1.6s ease-in-out infinite; }
.anim-shake { animation: anim-shake 2.2s ease-in-out infinite; }
.anim-tilt { animation: anim-tilt 3s ease-in-out infinite; }
.anim-shrink { animation: anim-shrink 2.4s ease-in-out infinite; }
.anim-pulse { animation: anim-pulse 1.8s ease-in-out infinite; }
.anim-wobble { animation: anim-wobble 2s ease-in-out infinite; }
.anim-droop { animation: anim-droop 3.5s ease-in-out infinite; }
.anim-nod { animation: anim-nod 2.6s ease-in-out infinite; }

.pet-sprite-stack {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Accessory art is positioned dynamically (see pet.js renderAccessories),
   using Pet.sprite_anchors percentages computed server-side from the pet's
   actual current body geometry - not a fixed guess - so a hat sticks to the
   head, glasses sit over the eyes, etc. regardless of which of the 3 torso
   lineages this pet has. The back layer sits behind the sprite (aura/back
   slots); the front layer sits above it (everything else) - see
   ACCESSORY_BACK_LAYER_SLOTS in pet.js. */
.accessory-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

#accessory-layer-back {
  z-index: 1;
}

#accessory-layer-front {
  z-index: 3;
}

.accessory-item {
  position: absolute;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.4));
  /* Purely visual - positioning/scaling/rotating an accessory now happens
     in the accessory-modal's own small preview stack (see pet.js), not by
     dragging the live sprite's own (possibly much bigger, e.g. an aura at
     1.5x the sprite itself) rendered image directly. */
  pointer-events: none;
}

/* 2026-07-25 ("Remove the emojis that show up on the monster's
   portrait" card): a badge used to be an emoji glyph; it's now a
   translucent floating color orb instead (see Pet.trait_visual /
   applyTraitOrb in pet.js + sprite_render.js) - width/height/background
   are all set by JS per pet (hue varies per food category, diameter
   scales with stage_scale), this just supplies the shape, positioning,
   and float animation. Hidden via .trait-badge-hidden (a plain class
   toggle) now that there's no text content for `:empty` to key off of. */
.trait-badge {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  filter: blur(0.5px) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.25));
  animation: trait-orb-float 3.6s ease-in-out infinite;
}

.trait-badge-hidden {
  display: none;
}

@keyframes trait-orb-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-22%); }
}

.trait-front {
  top: 6%;
  right: -6%;
  z-index: 4;
  animation-delay: 0s;
}

.trait-back {
  bottom: 8%;
  left: -10%;
  z-index: 0;
  opacity: 0.9;
  animation-delay: 1.2s;
}

.personality-badge {
  font-size: 11px;
  color: var(--accent);
  background: var(--panel-dark);
  border-radius: 10px;
  padding: 2px 8px;
}

.egg-click-hint {
  margin-top: 4px;
  font-size: 11px;
  color: #cbb8ff;
  text-align: center;
}

.mood-label {
  margin-top: 6px;
  font-size: 12px;
  color: #cbb8ff;
}

.hatch-countdown {
  margin-top: 6px;
  font-size: 13px;
  font-weight: bold;
  color: var(--accent);
}

.stats-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}

.stat {
  display: flex;
  align-items: center;
  gap: 8px;
}

.stat-label {
  width: 92px;
  flex-shrink: 0;
  font-size: 12px;
}

.stat-bar-track {
  flex: 1;
  height: 12px;
  background: var(--panel-dark);
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid #000a;
}

.stat-bar-fill {
  height: 100%;
  width: 100%;
  transition: width 0.4s ease, background 0.4s ease;
}

.stat-bar-fill.hunger { background: linear-gradient(90deg, #ff8a4a, #ffb84a); }
.stat-bar-fill.happiness { background: linear-gradient(90deg, #ff6ec7, #b06eff); }
.stat-bar-fill.clean { background: linear-gradient(90deg, #4adeff, #4aff9f); }
.stat-bar-fill.bond { background: linear-gradient(90deg, #ff9ad1, #ffd76b); }

/* "Define the 'Bound' System" card (2026-07-25) - replaces the old
   Energy stat bar (deleted along with the whole old energy system). */
.bond-row {
  margin-bottom: 16px;
}

.bond-label {
  display: block;
  font-size: 12px;
  margin-bottom: 4px;
}

.bond-progress-text {
  display: block;
  font-size: 10px;
  color: #cbb8ff;
  margin-top: 3px;
}

.pet-desktop-bond-row {
  width: 100%;
  margin-bottom: 6px;
}

.pet-desktop-bond-row .bond-label {
  font-size: 10px;
}

.color-stats-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 10px;
  margin: 4px 0 8px;
}

.color-stat-chip {
  font-size: 11px;
  color: #cbb8ff;
  background: var(--panel-dark);
  border: 1px solid var(--panel-light);
  border-radius: 6px;
  padding: 2px 8px;
}

.color-stat-chip.matching {
  border-color: var(--accent);
  color: var(--accent);
}

.archetype-stats-row {
  text-align: center;
  margin: 4px 0 8px;
}

.archetype-name-text {
  margin: 0 0 2px;
  font-size: 13px;
  font-weight: bold;
  color: var(--accent);
}

.archetype-stats-chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 10px;
}

.archetype-stat-chip {
  font-size: 11px;
  color: #a8e678;
  background: var(--panel-dark);
  border: 1px solid var(--grass-dark);
  border-radius: 6px;
  padding: 2px 8px;
}

.archetype-ability-text {
  margin: 4px 0 0;
  font-size: 11px;
  font-style: italic;
  color: #cbb8ff;
}

.color-wheel-canvas {
  display: block;
  margin: 0 auto 10px;
  border-radius: 50%;
  cursor: crosshair;
  touch-action: none;
}

.color-wheel-hint {
  text-align: center;
  font-size: 13px;
  margin-bottom: 14px;
}

.action-row {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.action-btn {
  padding: 10px 16px;
  cursor: pointer;
  border: 3px solid;
  border-color: var(--grass-light) var(--grass-dark) var(--grass-dark) var(--grass-light);
  background: #79c94a;
  color: #23360f;
  font-weight: bold;
  font-family: inherit;
  font-size: 14px;
  border-radius: 8px;
  touch-action: manipulation;
}

/* "give star and clean up can each be 50/50 on a shared line" (2026-07-25)
   - was already side by side but content-width; this stretches both to
   fill the row evenly. Scoped to .action-row specifically since
   .action-btn is reused elsewhere (modal Save buttons, etc.) where a
   forced 50/50 split wouldn't make sense. */
.action-row > .action-btn {
  flex: 1 1 0;
}

.action-btn:active {
  border-color: var(--grass-dark) var(--grass-light) var(--grass-light) var(--grass-dark);
}

.food-row {
  display: flex;
  align-items: center;
  gap: 6px;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

.food-row-label {
  font-size: 12px;
  color: #cbb8ff;
}

.food-btn {
  position: relative;
  width: 36px;
  height: 36px;
  font-size: 18px;
  cursor: pointer;
  border: 3px solid;
  border-color: var(--grass-light) var(--grass-dark) var(--grass-dark) var(--grass-light);
  background: #79c94a;
  border-radius: 8px;
  touch-action: manipulation;
}

.food-btn:active {
  border-color: var(--grass-dark) var(--grass-light) var(--grass-light) var(--grass-dark);
}

.food-btn.empty {
  opacity: 0.45;
  filter: grayscale(0.6);
}

.food-count {
  position: absolute;
  bottom: -6px;
  right: -6px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 8px;
  background: var(--panel-dark);
  color: var(--accent);
  font-size: 10px;
  font-weight: bold;
  line-height: 16px;
  text-align: center;
  border: 1px solid #000a;
}

.action-message {
  text-align: center;
  min-height: 18px;
  font-size: 12px;
  font-weight: bold;
  color: #ffb84a;
  margin: -6px 0 6px;
}

.pet-hint {
  font-size: 11px;
  color: #cbb8ff;
  text-align: center;
  margin: 0 0 14px;
}

.parts-slots {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 4px;
}

.parts-slot-row {
  display: flex;
  align-items: center;
  gap: 8px;
  border-radius: 8px;
  transition: background 0.3s ease;
}

/* Draws the eye to a slot that's unlocked but still awaiting a choice - a
   toast fires once when the slot unlocks (see checkUnlocks in pet.js), but
   this stays visible for as long as the choice is left pending, in case the
   toast was missed or the player comes back later. */
.parts-slot-row.pending {
  background: rgba(255, 215, 107, 0.12);
  animation: parts-pending-glow 1.8s ease-in-out infinite;
}

@keyframes parts-pending-glow {
  0%, 100% { box-shadow: 0 0 0 rgba(255, 215, 107, 0); }
  50% { box-shadow: 0 0 12px rgba(255, 215, 107, 0.45); }
}

.parts-slot-label {
  width: 60px;
  flex-shrink: 0;
  font-size: 11px;
  color: #cbb8ff;
  text-transform: uppercase;
}

.parts-slot-locked {
  font-size: 11px;
  color: #786a9e;
  font-style: italic;
}

.parts-slot-done {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--accent);
}

.parts-slot-done-img {
  width: 30px;
  height: 30px;
  background: var(--panel-dark);
  border-radius: 6px;
  border: 2px solid var(--accent);
}

.parts-slot-options {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 2px;
}

.part-option-btn {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  padding: 3px;
  border-radius: 6px;
  border: 2px solid var(--panel-light);
  background: var(--panel-dark);
  cursor: pointer;
}

.part-option-btn:hover {
  border-color: var(--accent);
}

.part-option-img {
  width: 100%;
  height: 100%;
}

.part-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.closet-slots {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 4px;
}

.closet-slot-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.closet-slot-label {
  width: 40px;
  flex-shrink: 0;
  font-size: 11px;
  color: #cbb8ff;
  text-transform: uppercase;
}

.closet-item-none-btn {
  font-size: 10px;
  color: #cbb8ff;
}

/* Account menu (pill/dropdown) and account modal (login/register/forgot/
   add-email) CSS both moved to nav.css - both now shared across every
   player-facing page, not just this one. */

.part-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 2200;
  background: rgba(10, 5, 25, 0.8);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.part-modal {
  position: relative;
  background: var(--panel);
  border: 6px solid;
  border-color: var(--panel-light) var(--panel-dark) var(--panel-dark) var(--panel-light);
  border-radius: 14px;
  padding: 24px;
  max-width: 560px;
  width: 100%;
  max-height: 92vh;
  overflow-y: auto;
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.6);
}

.part-modal h2 {
  margin: 0 0 4px;
  font-size: 20px;
  text-align: center;
}

.part-modal .modal-sub {
  margin-bottom: 16px;
}

.part-modal-preview-stack {
  position: relative;
  width: 260px;
  height: 260px;
  margin: 0 auto 6px;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.06), transparent 70%);
  border-radius: 16px;
  touch-action: none;
}

.part-modal-preview-body {
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

/* Body editor (kanban follow-up, 2026-07-28: rolled out from the admin-
   only Body Texture Studio prototype) - same drag-point pattern as that
   tool's own Edit Form, ported to this page's modal chrome. */
.part-modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 14px; }

.body-editor-preview-wrap {
  position: relative;
  width: 260px;
  height: 260px;
  margin: 0 auto 14px;
  background: #fff repeating-conic-gradient(#eee 0% 25%, #fff 0% 50%) 50% / 20px 20px;
  border-radius: 16px;
  overflow: hidden;
  touch-action: none;
}
.body-editor-preview-img { width: 100%; height: 100%; display: block; }
.body-editor-points-layer { position: absolute; inset: 0; }
.body-editor-point-handle {
  position: absolute;
  width: 28px;
  height: 28px;
  margin-left: -14px;
  margin-top: -14px;
  cursor: grab;
  touch-action: none;
}
.body-editor-point-handle::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 10px;
  margin-left: -5px;
  margin-top: -5px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #2b0d24;
  pointer-events: none;
}
.body-editor-point-handle:active { cursor: grabbing; }
.body-editor-point-handle:active::after { background: #fff; }

.body-editor-controls { display: flex; flex-direction: column; gap: 6px; font-size: 12px; color: #cbb8ff; margin-bottom: 6px; }
.body-editor-controls input[type="range"] { width: 100%; }

.part-modal-preview-editing {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Purely visual now - the small .part-modal-preview-handle below is the
     actual drag target (see pet.js), so a full (possibly large) part image
     never has to compete with its mirrored twin for pointer capture. */
  pointer-events: none;
  filter: drop-shadow(0 0 6px rgba(255, 215, 107, 0.8));
}

/* Small fixed-size drag target centered on wherever the part's own artwork
   actually sits (pet.js positions this from Pet.sprite_parts' anchor %,
   read straight off the generated SVG's own placement - see
   pet.py's _part_anchor_pct) - independent of how big the part's art
   itself renders, so grabbing it stays precise and two overlapping limbs
   never fight over the same hit area. */
.part-modal-preview-handle {
  position: absolute;
  width: 20px;
  height: 20px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(255, 215, 107, 0.35);
  border: 2px solid rgba(255, 215, 107, 0.9);
  cursor: grab;
  touch-action: none;
}

.part-modal-preview-handle:active {
  cursor: grabbing;
}

.part-modal-drag-hint {
  text-align: center;
  font-size: 11px;
  color: #cbb8ff;
  margin: 0 0 16px;
}

.part-modal-picker-group {
  margin-bottom: 16px;
}

/* ---------- Evolution circle ("where am I") + egg-hatch options ---------- */

.evolution-circle-wrap {
  display: flex;
  justify-content: center;
}

.evolution-circle-svg {
  width: 100%;
  max-width: 460px;
  aspect-ratio: 1 / 1;
}

/* Renamed from .starter-option-* (2026-07-25, "Card system / egg
   mechanic" card) - the old "pick a lineage after reset" starter picker
   is gone; this exact look now styles the hatch-an-egg buttons in
   #empty-slot-panel instead (see pet.js's renderHatchOptions). */
.egg-options {
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.egg-option-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 18px;
  border-radius: 12px;
  border: 3px solid;
  background: var(--panel-dark);
  color: inherit;
  cursor: pointer;
  font-weight: bold;
}

.egg-option-btn:hover {
  filter: brightness(1.2);
}

.egg-option-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.egg-option-emoji {
  font-size: 32px;
}

.empty-slot-panel {
  text-align: center;
  padding: 20px 0;
}

.empty-slot-message {
  font-size: 15px;
  font-weight: bold;
  margin: 0 0 16px;
}

.hatch-no-eggs-hint {
  font-size: 12px;
  color: #cbb8ff;
  line-height: 1.5;
}

.hatch-no-eggs-hint a {
  color: var(--accent);
}

.no-stars-hint {
  font-size: 11px;
  color: #cbb8ff;
  text-align: center;
  margin: -4px 0 8px;
}

/* ---------- Wheel spin (first-time free egg) ---------- */

.wheel-spin-stage {
  position: relative;
  width: 200px;
  margin: 0 auto 16px;
}

.wheel-spin-pointer {
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 22px;
  color: var(--accent);
  z-index: 2;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.6);
}

.wheel-spin-svg {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
}

#wheel-spin-group {
  transform-origin: 100px 100px;
  transition: transform 3s cubic-bezier(0.15, 0.75, 0.25, 1);
}

.wheel-spin-wedge-0 { fill: #e05656; }
.wheel-spin-wedge-1 { fill: #4a8fd6; }
.wheel-spin-wedge-2 { fill: #8a5ad6; }

.wheel-spin-label {
  fill: #fff;
  font-family: inherit;
  font-size: 11px;
  font-weight: bold;
  text-anchor: middle;
  text-transform: capitalize;
}

.wheel-spin-result {
  font-size: 15px;
  font-weight: bold;
  color: var(--accent);
  text-align: center;
}

.part-modal-picker-label {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: #cbb8ff;
  margin-bottom: 6px;
}

.part-modal-transform-group {
  margin-bottom: 16px;
}

.part-modal-transform-sided {
  display: flex;
  gap: 16px;
  margin-bottom: 0;
}

.part-modal-transform-sided .part-modal-transform-group {
  flex: 1;
}

.part-modal-side-label {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--accent);
  margin-bottom: 6px;
}

.part-modal-slider-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.part-modal-slider-row label {
  font-size: 11px;
  color: #cbb8ff;
  width: 40px;
  flex-shrink: 0;
}

.part-modal-slider-row input[type="range"] {
  flex: 1;
  min-width: 0;
}

.part-modal-options {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.part-shape-btn {
  width: 56px;
  height: 56px;
  padding: 4px;
  border-radius: 8px;
  border: 3px solid var(--panel-light);
  background: var(--panel-dark);
  cursor: pointer;
}

.part-shape-btn img {
  width: 100%;
  height: 100%;
}

.part-shape-btn.selected {
  border-color: var(--accent);
  background: var(--panel-light);
}

.accessory-none-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  color: #cbb8ff;
}

.part-customize-btn {
  font-size: 12px;
  padding: 6px 14px;
  border-radius: 6px;
  border: 2px solid var(--accent);
  background: var(--panel-light);
  color: var(--accent);
  cursor: pointer;
  font-weight: bold;
}

/* .account-modal-overlay/.account-modal/.account-modal h2 and every
   .modal-error/.modal-info/.modal-input/.modal-links/.modal-toggle/
   .modal-back rule below (all account-modal-only) moved to nav.css -
   .modal-sub/.modal-close-btn/.action-btn stay here since the OTHER
   modals on this page (part-modal, wheel-spin-modal, etc.) still use
   them. */

.modal-sub {
  margin: 0 0 16px;
  font-size: 12px;
  color: #cbb8ff;
  text-align: center;
  line-height: 1.4;
}

.modal-close-btn {
  position: absolute;
  top: 10px;
  right: 12px;
  background: none;
  border: none;
  color: #cbb8ff;
  font-size: 18px;
  cursor: pointer;
  padding: 4px;
}

.modal-close-btn:hover {
  color: #f0e9ff;
}

@media (max-width: 480px) {
  body { padding: 10px; }
  .pet-wrap { padding: 14px; }
  .pet-sprite { font-size: 64px; }
}

/* ---------- Desktop wide-screen multi-slot view ----------
   "Display changes" card (2026-07-25): "if the screen is a wide screen
   then it should show all your monsters in their own interactive boxes
   instead of just the one." Both #pet-mobile-view and .pet-desktop-view
   markup always exist - this single breakpoint is the only thing
   toggling which one is visible, so there's no JS-side "which view am I
   in" state to keep in sync beyond `isDesktopView()`'s own
   `matchMedia()` check (see pet.js). */

.pet-desktop-view {
  display: none;
}

@media (min-width: 900px) {
  .pet-wrap {
    /* "general UI Tweeks" card, 4th same-day follow-up (2026-07-25):
       "We should be able to fit 4 groups of 4 on the main row" - a full
       page of 4 desktop cards (200px each + 14px gaps, plus the two 32px
       paging arrows) needs ~962px of room; 900px only ever fit 3 before
       the 4th wrapped to its own row (confirmed against the player's own
       "regular view"/"zoomed-out view" screenshots, both showing the
       exact same wrap). Widened past that with headroom rather than
       shrinking the cards, since the screenshots show the cards
       themselves at the size wanted. */
    max-width: 1000px;
  }

  #pet-mobile-view {
    display: none;
  }

  .pet-desktop-view {
    display: block;
    width: 100%;
    max-width: 1000px;
    margin: 0 auto;
  }
}

.pet-desktop-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pet-desktop-grid {
  flex: 1;
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
}

.pet-desktop-card {
  width: 200px;
  flex: none;
  background: var(--panel);
  border: 4px solid;
  border-color: var(--panel-light) var(--panel-dark) var(--panel-dark) var(--panel-light);
  border-radius: 12px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.pet-desktop-card.is-active-slot {
  border-color: var(--accent);
}

.pet-desktop-card-header {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  margin-bottom: 4px;
}

.pet-desktop-card-name {
  font-weight: bold;
  font-size: 14px;
}

.pet-desktop-card-stage {
  font-size: 11px;
  color: #cbb8ff;
  margin-bottom: 4px;
}

.pet-desktop-card-xp-label {
  font-size: 10px;
  color: #cbb8ff;
  margin: 2px 0 8px;
}

.pet-desktop-sprite-stack {
  width: 100px;
  height: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 4px;
}

.pet-desktop-sprite-stack .pet-sprite.has-image {
  max-width: 90px;
  max-height: 90px;
}

.pet-desktop-sprite {
  font-size: 56px;
}

.pet-desktop-card-stats {
  width: 100%;
  margin-bottom: 6px;
}

.pet-desktop-card-stats .stat-label {
  width: 62px;
  font-size: 10px;
}

.pet-desktop-card-archetype {
  font-size: 11px;
  color: var(--accent);
  font-weight: bold;
  min-height: 14px;
  margin-bottom: 6px;
}

.pet-desktop-card-food-row {
  justify-content: center;
  margin-bottom: 8px;
}

.pet-desktop-card-action-row {
  width: 100%;
  margin-bottom: 8px;
}

.pet-desktop-card > .menu-open-btn,
.pet-desktop-card > .link-btn {
  width: 100%;
  margin-bottom: 6px;
  font-size: 12px;
}

/* "Assemble your alien and Closet can each be 50/50 on a shared line"
   (2026-07-25), desktop per-slot card version - these buttons are no
   longer direct children of .pet-desktop-card (they're wrapped in this
   row now), so the width:100% rule above no longer matches them at all;
   fresh rules here instead. */
.pet-desktop-menu-row {
  display: flex;
  gap: 8px;
  width: 100%;
}

.pet-desktop-menu-row .menu-open-btn {
  width: auto;
  flex: 1 1 0;
  margin: 6px 0;
  font-size: 12px;
}

.pet-desktop-card-empty {
  justify-content: center;
  min-height: 260px;
}

.pet-desktop-hatch-options {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
}
