/* Chatbot launcher - sky blue bubble + white robot character loop */
.chatbot-button {
  position: fixed;
  right: 8px;
  bottom: 24px;
  z-index: 9999;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.chatbot-launcher {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Small because the tail reaches the bottom of the bubble box and the video
     frame carries ~16px of empty headroom above the robot. */
  gap: 4px;
  will-change: transform;
}

/* 6px of lead-in for the rim, then a 68px panel and an 18px tail below it. The
   extra height over the old pill grows upwards, because the launcher is pinned
   at the bottom, so the tip stays where it was against the robot's head. That
   is also why the panel can be made taller without moving the tail: add to this
   height and to the panel's own depth in the path by the same amount, and every
   coordinate below the panel keeps the screen position it already had. */
.chatbot-bubble {
  position: relative;
  /* Fits the longest line of either message ("홈페이지 제작", ~87px at 16px/800)
     with room to spare, and no more: the panel has to hold the widest thing it
     will ever show, so anything past that is dead space on the other message. */
  width: 116px;
  height: 92px;
  flex-shrink: 0;
}

/* The body itself paints nothing: it only carries the chained drop-shadows
   around the single clipped fill in ::before. Drawing the rim this way instead
   of with a border keeps a white line from cutting straight across the tail. */
.chatbot-bubble__body {
  position: absolute;
  z-index: 1;
  inset: 6px 0 0 0;
  filter:
    drop-shadow(0 1.4px 0 rgba(255, 255, 255, 0.95))
    drop-shadow(0 -1.4px 0 rgba(255, 255, 255, 0.95))
    drop-shadow(1.4px 0 0 rgba(255, 255, 255, 0.95))
    drop-shadow(-1.4px 0 0 rgba(255, 255, 255, 0.95))
    drop-shadow(0 9px 16px rgba(37, 99, 235, 0.3));
}

/* One path for the panel and the tail so the fill, gloss and rim never meet at
   a seam. Traced clockwise over the 116x86 box: a 16px-cornered panel down to
   y=68, then the tail hanging off the bottom left. Its right side drops almost
   straight while the left sweeps in, so the point leans back towards the middle
   of the bubble instead of away from it; that asymmetry is what makes it read
   as a spoken tail rather than a wedge, and the short curve at the bottom
   rounds the point off.

   The tail's x values are scaled about the point itself (x=45.1), so narrowing
   it leaves the tip aiming at exactly the same spot on the robot's head. The
   panel keeps the x it had when it was wider: the launcher centres the bubble
   over the robot, so trimming width off the right walks the tail towards the
   middle of the head rather than off the side of it. */
.chatbot-bubble__body::before {
  content: "";
  position: absolute;
  z-index: 1;
  inset: 0;
  clip-path: path(
    "M 16,0 H 100 A 16,16 0 0 1 116,16 V 52 A 16,16 0 0 1 100,68 H 49.3 Q 48.3,75 46.8,82.5 Q 46.1,87.5 43.2,84.5 Q 37.1,78.5 31.3,68 H 16 A 16,16 0 0 1 0,52 V 16 A 16,16 0 0 1 16,0 Z"
  );
  background:
    radial-gradient(78% 62% at 48% 6%, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.5) 44%, rgba(255, 255, 255, 0) 74%),
    linear-gradient(160deg, #ffffff 0%, #f0f9ff 46%, #dbeafe 100%);
  box-shadow: inset 0 -5px 12px rgba(96, 165, 250, 0.28);
  pointer-events: none;
}

/* Spans the bubble rather than centring on its midpoint: anchoring at left 50%
   would cap the text at half the width and wrap the messages past their own
   line breaks. Vertically it centres on the panel (6px inset + 68px tall), not
   on the bubble, which is taller by the length of the tail. */
.chatbot-bubble__text {
  position: absolute;
  z-index: 2;
  top: 40px;
  left: 8px;
  right: 8px;
  transform: translateY(-50%);
  font-family: "Pretendard Variable", Pretendard, "Malgun Gothic", sans-serif;
  font-weight: 800;
  font-size: 16px;
  line-height: 1.35;
  text-align: center;
  background: linear-gradient(90deg, #2563eb 0%, #3b82f6 52%, #0ea5e9 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, 0.9));
  transition: opacity 320ms ease;
}

/* Held while the script swaps in the next message, so the text never changes
   in plain sight. Keep the duration in step with BUBBLE_FADE_MS. */
.chatbot-bubble__text.is-fading {
  opacity: 0;
}

.chatbot-character {
  margin-top: 0;
}

/* Sized against the 352px canvas, not the robot: the frame carries empty side
   margins so the raised waving arm has somewhere to go. The robot itself still
   lands at ~141px, the same as before the canvas widened. */
.chatbot-character__video,
.chatbot-character__still {
  width: 158px;
  height: auto;
  display: block;
  pointer-events: none;
}

.chatbot-character__still,
.chatbot-character.is-image .chatbot-character__video {
  display: none;
}

.chatbot-character.is-image .chatbot-character__still {
  display: block;
}

/* Tucked: the script adds .is-tucked only where hover exists, so touch screens
   and no-JS keep the launcher fully out. The whole button slides, not just the
   character, so its hit area leaves the page along with it.
   bottom: the frame has ~7px of empty space under the feet, so 54px lines
   them up with the bottom of the hero promo card (61px off the bottom). The
   out state keeps this height: dropping back down under the pointer would
   fire mouseleave and tuck it again. */
.chatbot-button.is-tucked {
  bottom: 54px;
  transition:
    opacity 0.4s var(--ease, ease),
    visibility 0.4s,
    translate 0.4s var(--ease, ease),
    transform 0.7s cubic-bezier(0.34, 1.4, 0.64, 1);
}

/* 92px puts the neck (x=79 of the 158px frame) just past the screen edge, so
   the body stays behind it and only the tilted head leans out. */
.chatbot-button.is-tucked:not(.is-out) {
  transform: translateX(92px);
}

.chatbot-launcher {
  position: relative;
}

.chatbot-character {
  position: relative;
}

/* While tucked, the still is drawn twice and cut at the neck (the narrowest
   row, 51.4% down the 352x416 frame) so the head can tilt on its own. The
   head copy keeps a few px of the neck to cover the seam as it turns.
   The layers stay up through the slide out, so the head straightens and the
   body fades in on the way; the script then adds .is-waving to hand over to
   the wave video. */
.chatbot-peek {
  position: absolute;
  inset: 0;
  display: none;
  pointer-events: none;
}

.chatbot-peek img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: auto;
}

/* Starts at the top of the head's fade so the chin stays solid while the
   body fades back in under the straightening head. */
.chatbot-peek__body {
  clip-path: inset(43% 0 0 0);
  transition: opacity 0.35s ease;
}

/* Faded rather than clipped: with the body hidden, a hard cut at the neck
   shows as a straight slice once the head turns. */
.chatbot-peek__head {
  -webkit-mask-image: linear-gradient(to bottom, #000 43%, transparent 51%);
  mask-image: linear-gradient(to bottom, #000 43%, transparent 51%);
  transform-origin: 50% 51.4%;
  transition: transform 0.6s cubic-bezier(0.34, 1.4, 0.64, 1);
}

.chatbot-button.is-tucked:not(.is-waving) .chatbot-peek {
  display: block;
}

.chatbot-button.is-tucked:not(.is-waving) .chatbot-character__video,
.chatbot-button.is-tucked:not(.is-waving) .chatbot-character__still {
  visibility: hidden;
}

.chatbot-button.is-tucked:not(.is-out) .chatbot-peek__body {
  opacity: 0;
}

.chatbot-button.is-tucked:not(.is-out) .chatbot-peek__head {
  transform: rotate(-56deg);
  animation: chatbot-head-idle 3.2s ease-in-out infinite alternate;
}

.chatbot-button.is-tucked.is-peek:not(.is-out) .chatbot-peek__head {
  animation: chatbot-head-peek 1.6s ease-in-out;
}

@keyframes chatbot-head-idle {
  from { transform: rotate(-52deg); }
  to { transform: rotate(-60deg); }
}

/* Leans further out, tilts back as if looking around, leans again and
   settles. Keep the length in step with PEEK_HOLD_MS. */
@keyframes chatbot-head-peek {
  0% { transform: rotate(-56deg); }
  25% { transform: translateX(-8px) rotate(-70deg); }
  45% { transform: translateX(-4px) rotate(-46deg); }
  65% { transform: translateX(-8px) rotate(-66deg); }
  100% { transform: rotate(-56deg); }
}

/* Sits off the left of the head, outside the button's own box, so it shows
   while the rest of the launcher is still pushed off the edge. */
.chatbot-hi {
  position: absolute;
  z-index: 3;
  top: 118px;
  right: calc(100% + 4px);
  padding: 7px 14px;
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 6px 16px rgba(37, 99, 235, 0.22);
  font-family: "Pretendard Variable", Pretendard, "Malgun Gothic", sans-serif;
  font-size: 16px;
  font-weight: 800;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--brand, #1a86da);
  opacity: 0;
  scale: 0.6;
  transform-origin: right center;
  transition: opacity 0.3s ease, scale 0.45s cubic-bezier(0.34, 1.6, 0.64, 1);
  pointer-events: none;
}

.chatbot-hi::after {
  content: "";
  position: absolute;
  right: -6px;
  top: 50%;
  margin-top: -6px;
  border-left: 8px solid #fff;
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
}

.chatbot-button.is-tucked:not(.is-out) .chatbot-hi {
  opacity: 1;
  scale: 1;
}

.chatbot-button.is-tucked.is-peek:not(.is-out) .chatbot-hi {
  scale: 1.12;
}

.chatbot-button.is-tucked .chatbot-bubble {
  transition: opacity 0.3s ease, transform 0.4s cubic-bezier(0.34, 1.4, 0.64, 1);
}

.chatbot-button.is-tucked:not(.is-out) .chatbot-bubble {
  opacity: 0;
  transform: translateY(10px) scale(0.9);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .chatbot-bubble__text {
    transition: none;
  }

  .chatbot-button.is-tucked,
  .chatbot-button.is-tucked .chatbot-bubble,
  .chatbot-hi {
    transition: opacity 0.3s ease;
  }

  .chatbot-peek__head,
  .chatbot-button.is-tucked.is-peek:not(.is-out) .chatbot-peek__head {
    animation: none;
  }
}

/* 모바일: 말풍선 없이, 오른쪽 가장자리에 머리만 내밀고 숨긴다 */
@media (max-width: 768px) {
  .chatbot-bubble,
  .chatbot-hi {
    display: none;
  }

  .chatbot-character__video,
  .chatbot-character__still {
    width: 92px;
  }

  .chatbot-button,
  .chatbot-button.is-tucked {
    right: 0;
    bottom: 16px;
  }

  .chatbot-button.is-tucked:not(.is-out) {
    transform: translateX(54px);
  }
}
