/* ============================================================================
   Kopo · Kobot SVG
   Chaque piece du logo est un element SVG nomme (bras, mains, corps, points,
   zone de l'oeil, pupille, paupieres, cable). Les gestes et les etats se
   declenchent en posant une classe sur le <svg> hote :

     .cligne       geste : les paupieres ferment puis rouvrent l'oeil
     .coucou       geste : le bras droit monte et salue (peek au survol)
     .is-grabbed   etat  : kobot attrape · le cable se retracte comme un
                   enrouleur, les points d'ancrage tombent, panique complete
                   (pupille affolee, bras qui battent, tremblement, sueur)
     .is-falling   etat  : kobot relache · le corps chute hors du cadre
     .is-respawn   etat  : redescente du haut avec un nouveau cable et
                   les points retrouves

   Tout le mouvement est en CSS. kobot.js ne fait que poser les classes,
   deplacer la pupille vers le curseur et piloter le drag du pendule.
   Invariants charte : la zone de l'oeil et la pupille ne se deforment
   jamais, le clignement se fait par caches blancs, Sirocco reste reserve
   a la zone de l'oeil.
   ============================================================================ */

.kobot-svg {
  display: block;
  width: 100%;
  overflow: visible;
  user-select: none;
}

/* === PAUPIERES : deux caches blancs clippes par la zone de l'oeil =========
   Le clip (r 122) et les caches debordent la zone rouge (r 112.5) pour ne
   laisser aucun lisere rouge au bord pendant la fermeture ; ouverture a
   130 px pour que les caches sortent entierement du clip au repos. ======== */
.kobot-svg .k-paupiere-haut { transform: translateY(-130px); }
.kobot-svg .k-paupiere-bas  { transform: translateY(130px); }
.kobot-svg.cligne .k-paupiere-haut { animation: k-lid-haut 0.5s ease-in-out; }
.kobot-svg.cligne .k-paupiere-bas  { animation: k-lid-bas 0.5s ease-in-out; }
@keyframes k-lid-haut {
  0%       { transform: translateY(-130px); }
  40%, 60% { transform: translateY(0); }
  100%     { transform: translateY(-130px); }
}
@keyframes k-lid-bas {
  0%       { transform: translateY(130px); }
  40%, 60% { transform: translateY(0); }
  100%     { transform: translateY(130px); }
}

/* === PUPILLE : suivie du curseur en JS, retour souple ===================== */
.k-pupille {
  transition: transform 300ms var(--ease-out);
  will-change: transform;
}

/* === BRAS ET MAINS : pivot au centre du Kobot ============================= */
.k-bras-droit-grp, .k-bras-gauche-grp,
.k-main-droite-grp, .k-main-gauche-grp {
  transform-box: view-box;
  transform-origin: 512px 512px;
}

/* === COUCOU : le bras droit monte et oscille, la main glisse le long ====== */
.kobot-svg.coucou .k-bras-droit-grp  { animation: k-wave 1.6s ease-in-out; }
.kobot-svg.coucou .k-main-droite-grp { animation: k-main-glisse 1.6s ease-in-out; }
@keyframes k-wave {
  0%   { transform: rotate(0deg); }
  20%  { transform: rotate(-42deg); }
  40%  { transform: rotate(-24deg); }
  60%  { transform: rotate(-42deg); }
  80%  { transform: rotate(-24deg); }
  100% { transform: rotate(0deg); }
}
@keyframes k-main-glisse {
  0%   { transform: rotate(0deg); }
  20%  { transform: rotate(-14deg); }
  40%  { transform: rotate(14deg); }
  60%  { transform: rotate(-14deg); }
  80%  { transform: rotate(14deg); }
  100% { transform: rotate(0deg); }
}

/* ============================================================================
   HERO · pendule, grab, chute, redescente
   Architecture a 2 etages :
   - .kobot-swing-anchor (div) : balancement permanent, jamais touche au drag
   - .kobot-hero (svg)         : une fois attrape, suit la souris librement
     dans tout le hero (translate + inclinaison inertielle via variables CSS)
   Les deux transforms se composent sans interferer.
   ============================================================================ */
.kobot-swing-anchor {
  display: block;
  width: 100%;
  animation: k-swing 5.5s ease-in-out infinite;
  transform-origin: 50% -600%;
}
/* Pause du swing pendant le grab (l'animation reprend depuis sa frame) */
.kobot-swing-anchor:has(.is-grabbed) { animation-play-state: paused; }
@keyframes k-swing {
  0%, 100% { transform: rotate(-1deg); }
  50%      { transform: rotate(1deg); }
}

.kobot-hero {
  --drag-x: 0px;      /* deplacement du corps, en unites viewBox */
  --drag-y: 0px;
  --drag-tilt: 0deg;  /* inclinaison inertielle pendant le drag */
  --throw-x: 0px;     /* derive horizontale de la chute (vitesse au lacher) */
  --throw-rot: 0deg;  /* rotation de la chute, proportionnelle au lancer */
  cursor: grab;
  touch-action: none;
}
.kobot-hero:active { cursor: grabbing; }
/* Seul le corps suit la souris : cable et points, places hors de .k-drag,
   se detachent sur place au moment du grab */
.kobot-hero .k-drag {
  transform: translate(var(--drag-x), var(--drag-y)) rotate(var(--drag-tilt));
  transform-box: view-box;
  transform-origin: 512px 512px;
  will-change: transform;
}
body.kobot-dragging,
body.kobot-dragging * { cursor: grabbing !important; user-select: none; }

/* --- Grab : le cable se retracte d'un coup vers le haut, facon enrouleur -- */
.kobot-hero.is-grabbed .k-cable,
.kobot-hero.is-falling .k-cable {
  animation: k-cable-retract 0.5s cubic-bezier(0.55, 0, 1, 0.45) 0.06s forwards;
}
@keyframes k-cable-retract {
  to { transform: translateY(-9300px); }
}

/* --- Grab : les points d'ancrage tombent un a un --------------------------- */
.kobot-hero.is-grabbed .k-point,
.kobot-hero.is-falling .k-point {
  animation: k-point-fall 0.95s cubic-bezier(0.55, 0, 1, 0.45) both;
}
.kobot-hero.is-grabbed .k-point-centre,
.kobot-hero.is-falling .k-point-centre { animation-delay: 0.08s; }
.kobot-hero.is-grabbed .k-point-droit,
.kobot-hero.is-falling .k-point-droit  { animation-delay: 0.16s; }
@keyframes k-point-fall {
  0%   { transform: translateY(0); opacity: 1; }
  70%  { opacity: 1; }
  100% { transform: translateY(2400px); opacity: 0; }
}

/* --- Panique : pupille affolee, bras qui battent, tremblement -------------- */
.kobot-hero.is-grabbed .k-pupille,
.kobot-hero.is-falling .k-pupille {
  animation: k-panic 0.38s steps(2) infinite;
  transition: none;
}
@keyframes k-panic {
  0%, 100% { transform: translate(30px, -26px); }
  25%      { transform: translate(-32px, 18px); }
  50%      { transform: translate(24px, 28px); }
  75%      { transform: translate(-28px, -20px); }
}
.kobot-hero.is-grabbed .k-bras-droit-grp,
.kobot-hero.is-falling .k-bras-droit-grp  { animation: k-flail-droit 0.42s ease-in-out infinite; }
.kobot-hero.is-grabbed .k-bras-gauche-grp,
.kobot-hero.is-falling .k-bras-gauche-grp { animation: k-flail-gauche 0.42s ease-in-out infinite 0.09s; }
@keyframes k-flail-droit  { 0%, 100% { transform: rotate(6deg); }  50% { transform: rotate(-36deg); } }
@keyframes k-flail-gauche { 0%, 100% { transform: rotate(-6deg); } 50% { transform: rotate(36deg); } }
.kobot-hero.is-grabbed .k-main-droite-grp,
.kobot-hero.is-falling .k-main-droite-grp  { animation: k-main-agite 0.42s ease-in-out infinite; }
.kobot-hero.is-grabbed .k-main-gauche-grp,
.kobot-hero.is-falling .k-main-gauche-grp  { animation: k-main-agite 0.42s ease-in-out infinite 0.09s; }
@keyframes k-main-agite { 0%, 100% { transform: rotate(8deg); } 50% { transform: rotate(-14deg); } }

.kobot-hero.is-grabbed .k-tremble { animation: k-tremble 0.14s linear infinite; }
@keyframes k-tremble {
  0%, 100% { transform: translate(0, 0); }
  25%      { transform: translate(-8px, 3px); }
  75%      { transform: translate(8px, -3px); }
}

/* --- Sueur : apparait apres un court delai puis oscille -------------------- */
.k-sweat-grp { opacity: 0; }
.kobot-hero.is-grabbed .k-sweat-grp {
  opacity: 1;
  transition: opacity 0.2s ease-out 0.35s;
  animation: k-sweat-bob 1.2s ease-in-out 0.55s infinite;
}
.k-sweat { transform-box: fill-box; transform-origin: center; }
.kobot-hero.is-grabbed .k-sweat {
  animation: k-sweat-pop 0.32s cubic-bezier(0.34, 1.56, 0.64, 1) 0.35s both;
}
@keyframes k-sweat-pop {
  from { transform: scale(0); }
  to   { transform: scale(1); }
}
@keyframes k-sweat-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(16px); }
}

/* --- Relache : chute balistique depuis la position du lacher ----------------
   Trois groupes imbriques, un par composante, pour une vraie parabole :
   X lineaire (inertie du lancer), Y accelere (gravite), rotation sur place
   en dernier. La rotation ne doit JAMAIS etre parente d'une translation,
   sinon l'axe de la gravite tourne avec elle et le kobot remonte. -------- */
.kobot-hero.is-falling .k-fallwrap {
  animation: k-body-fall-x 0.82s linear forwards;
}
.kobot-hero.is-falling .k-fally {
  animation: k-body-fall-y 0.82s cubic-bezier(0.55, 0, 1, 0.45) forwards;
}
.kobot-hero.is-falling .k-fallrot {
  transform-box: view-box;
  transform-origin: 512px 512px;
  animation: k-body-fall-rot 0.82s linear forwards;
}
@keyframes k-body-fall-x {
  from { transform: translateX(0); }
  to   { transform: translateX(var(--throw-x)); }
}
@keyframes k-body-fall-y {
  from { transform: translateY(0); }
  to   { transform: translateY(3000px); }
}
@keyframes k-body-fall-rot {
  from { transform: rotate(0deg); }
  to   { transform: rotate(var(--throw-rot)); }
}

/* --- Redescente : nouveau cable, points retrouves, atterrissage amorti ------ */
.kobot-hero.is-respawn .k-rig {
  animation: k-rig-down 1.25s cubic-bezier(0.34, 1.3, 0.64, 1) both;
}
@keyframes k-rig-down {
  from { transform: translateY(-2700px); }
  to   { transform: translateY(0); }
}

/* === ACCESSIBILITE : on calme les mouvements continus ====================== */
@media (prefers-reduced-motion: reduce) {
  .kobot-swing-anchor,
  .kobot-hero.is-grabbed .k-tremble,
  .kobot-hero.is-grabbed .k-bras-droit-grp,
  .kobot-hero.is-grabbed .k-bras-gauche-grp,
  .kobot-hero.is-grabbed .k-main-droite-grp,
  .kobot-hero.is-grabbed .k-main-gauche-grp,
  .kobot-hero.is-falling .k-bras-droit-grp,
  .kobot-hero.is-falling .k-bras-gauche-grp,
  .kobot-hero.is-falling .k-main-droite-grp,
  .kobot-hero.is-falling .k-main-gauche-grp { animation: none !important; }
}
