/* Login mascot "Gusty" + post-login portal transition. Brand red / white / blue; confetti colours are variables (swap pink for blue here). */
:root {
  --g-blue: #2a5bc4;
  --g-red: #d3122f;
  --confetti-a: #ff6b9d;      /* pink (swap to var(--blue) later if wanted) */
  --confetti-b: #ffffff;      /* white */
  --confetti-c: #d3122f;      /* red */
  --g-h: 390px;               /* stage height on desktop (Gusty himself is about 330px) */
}

/* layout: Gusty on the left (standing on the floor, most of the page height), the unchanged login form on the right */
:root { --g-fig-h: clamp(520px, calc(100vh - 104px), 1040px); }
.login-wrap { display: flex; align-items: flex-end; justify-content: center; gap: 1.5rem; max-width: 1060px; margin: 0 auto; }
.page > .flash ~ .login-wrap { --g-fig-h: clamp(480px, calc(100vh - 164px), 1040px); }
.login-wrap .card.narrow.login { margin: 0; flex: 1 1 380px; max-width: 440px; position: relative; z-index: 1; align-self: center; }
.gusty-stage { position: relative; flex: 0 0 auto; height: var(--g-fig-h); width: calc(var(--g-fig-h) * .6333); z-index: 3; pointer-events: none; }   /* he never blocks the form; only the owner pencil takes clicks */
.gusty-svg { display: block; width: 100%; height: 100%; overflow: visible; }
.g-skip[hidden] { display: none; }
.g-skip { display: block; margin: .7rem 0 0; font-size: .82rem; color: var(--muted, #5b6577); }

/* SVG parts: transforms only (cheap), each around a fixed point in SVG user units (viewBox -40 0 380 600) */
.gusty-svg .g-man, .gusty-svg .g-seg, .gusty-svg .g-arm, .gusty-svg .g-arm-pose, .gusty-svg .g-hair, .gusty-svg .g-tassel { transform-box: view-box; }
.gusty-svg .g-man  { transform-origin: 150px 532px; }       /* the cuff on the blower */
.gusty-svg .g-seg1 { transform-origin: 150px 516px; }
.gusty-svg .g-seg2 { transform-origin: 150px 380px; }
.gusty-svg .g-seg3 { transform-origin: 150px 262px; }
.gusty-svg .g-arm-l, .gusty-svg .g-arm-l-pose { transform-origin: 130px 176px; }
.gusty-svg .g-arm-r, .gusty-svg .g-arm-r-pose { transform-origin: 170px 176px; }
.gusty-svg .g-hair { transform-origin: 150px 42px; }
.gusty-svg .g-shadow { transform-box: fill-box; transform-origin: center; }

/* 1. inflate on load: crumpled on the blower -> blown up straight, arms flick back and flail;
   2. then nonstop: slowly deflates (sags and folds over) and re-inflates (whips back up), with the bend running up the tube */
.gusty-stage .g-man  { animation: g-inflate 1.3s cubic-bezier(.3,.7,.4,1) both, g-breathe 4.4s ease-in-out 1.3s infinite; }
.gusty-stage .g-seg1 { animation: g-crumple1 1.3s ease-out both, g-bend1 4.4s ease-in-out 1.3s infinite; }
.gusty-stage .g-seg2 { animation: g-crumple2 1.3s ease-out both, g-bend2 4.4s ease-in-out 1.3s infinite; }
.gusty-stage .g-seg3 { animation: g-crumple3 1.3s ease-out both, g-bend3 4.4s ease-in-out 1.3s infinite; }
.gusty-stage .g-arm-l { animation: g-flail-l 1.5s ease-out both, g-arm-l 4.4s ease-in-out 1.5s infinite; }
.gusty-stage .g-arm-r { animation: g-flail-r 1.5s ease-out both, g-arm-r 4.4s ease-in-out 1.5s infinite; }
.gusty-stage .g-hair { animation: g-hair .9s ease-in-out infinite alternate; }
.gusty-stage .g-tassel { animation: g-hair .7s ease-in-out infinite alternate; }
.gusty-stage .g-shadow { animation: g-shadow 4.4s ease-in-out 1.3s infinite; }

@keyframes g-inflate {
  0%   { transform: scale(1.25, .06); }
  20%  { transform: scale(1.15, .3); }
  42%  { transform: scale(1.06, .66); }
  62%  { transform: scale(.97, 1.04); }
  80%  { transform: scale(1.01, .98); }
  100% { transform: scale(1, 1); }
}
@keyframes g-crumple1 { 0% { transform: rotate(28deg); } 25% { transform: rotate(-20deg); } 50% { transform: rotate(10deg); } 75% { transform: rotate(-4deg); } 100% { transform: rotate(0); } }
@keyframes g-crumple2 { 0% { transform: rotate(-55deg); } 25% { transform: rotate(38deg); } 50% { transform: rotate(-18deg); } 75% { transform: rotate(7deg); } 100% { transform: rotate(0); } }
@keyframes g-crumple3 { 0% { transform: rotate(70deg); } 25% { transform: rotate(-45deg); } 50% { transform: rotate(22deg); } 75% { transform: rotate(-8deg); } 100% { transform: rotate(0); } }
@keyframes g-breathe {          /* air out (shorter, a touch fatter) and back in */
  0%, 100% { transform: scale(1, 1); }
  45%      { transform: scale(1.03, .95); }
  58%      { transform: scale(1.045, .925); }
  72%      { transform: scale(.99, 1.02); }
}
@keyframes g-bend1 { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(1.5deg); } 50% { transform: rotate(-2.5deg); } 70% { transform: rotate(2deg); } 85% { transform: rotate(-.8deg); } }
@keyframes g-bend2 { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-3deg); } 52% { transform: rotate(5deg); } 72% { transform: rotate(-4deg); } 87% { transform: rotate(1.5deg); } }
@keyframes g-bend3 { 0%, 100% { transform: rotate(0); } 27% { transform: rotate(5deg); } 55% { transform: rotate(-11deg); } 74% { transform: rotate(7deg); } 89% { transform: rotate(-2deg); } }
@keyframes g-flail-l { 0% { transform: rotate(-80deg); } 15% { transform: rotate(50deg); } 32% { transform: rotate(-38deg); } 50% { transform: rotate(26deg); } 68% { transform: rotate(-14deg); } 85% { transform: rotate(6deg); } 100% { transform: rotate(0); } }
@keyframes g-flail-r { 0% { transform: rotate(80deg); } 15% { transform: rotate(-50deg); } 32% { transform: rotate(38deg); } 50% { transform: rotate(-26deg); } 68% { transform: rotate(14deg); } 85% { transform: rotate(-6deg); } 100% { transform: rotate(0); } }
@keyframes g-arm-l { 0%, 100% { transform: rotate(0); } 30% { transform: rotate(7deg); } 56% { transform: rotate(-14deg); } 76% { transform: rotate(9deg); } 90% { transform: rotate(-3deg); } }
@keyframes g-arm-r { 0%, 100% { transform: rotate(0); } 30% { transform: rotate(-7deg); } 56% { transform: rotate(16deg); } 76% { transform: rotate(-9deg); } 90% { transform: rotate(3deg); } }
@keyframes g-hair { from { transform: rotate(-6deg); } to { transform: rotate(6deg); } }
@keyframes g-shadow { 0%, 100% { transform: scaleX(1); } 55% { transform: scaleX(1.1); } }

/* 3. speech bubble off his head, tail pointing at his mouth: pops up at 1.3s, lines typed one by one,
      swells like a balloon from 2.3s and POPS at 4.3s (gusty.js bursts the confetti on that 'animationstart'). */
.g-bubble-pop { position: absolute; left: 59%; top: 1%; width: 16.4rem; pointer-events: none; transform-origin: 18% 85%;
  animation: g-bub-pop .26s ease-out 4.3s both; }
.g-bubble-swell { transform-origin: 18% 85%; animation: g-bub-swell 2s cubic-bezier(.5,0,.9,.7) 2.3s both; }
.g-bubble { position: relative; background: #fff; color: var(--navy, #0a2342); border: 3px solid var(--navy, #0a2342); border-radius: 46% 54% 50% 50% / 58% 52% 48% 42%;
  padding: .9rem 1.1rem 1rem; text-align: center; font-weight: 800; line-height: 1.22; font-size: 1.02rem; box-shadow: 0 6px 0 var(--g-red), 0 10px 24px rgba(10,35,66,.18);
  transform-origin: 18% 85%; animation: g-bub-in .42s cubic-bezier(.3,1.7,.5,1) 1.3s both; }
.g-bubble::before, .g-bubble::after { content: ""; position: absolute; border-radius: 50%; background: #fff; border: 3px solid var(--navy, #0a2342); }
.g-bubble::before { width: 16px; height: 16px; left: 2px; bottom: -20px; }      /* thought-style tail: two dots stepping down to his mouth */
.g-bubble::after { width: 9px; height: 9px; left: -12px; bottom: -34px; }
.g-line { display: block; text-align: center; white-space: nowrap; clip-path: inset(0 100% 0 0); }     /* each line centred in the bubble */
.g-l1 { animation: g-type .4s steps(21, end) 1.55s forwards; }
.g-l2 { animation: g-type .4s steps(14, end) 1.95s forwards; }
.g-l3 { animation: g-type .4s steps(14, end) 2.35s forwards; color: var(--g-red); font-size: 1.12em; }
@keyframes g-type { to { clip-path: inset(0 0 0 0); } }
@keyframes g-bub-in { 0% { transform: scale(0) rotate(-12deg); opacity: 0; } 100% { transform: scale(1) rotate(0); opacity: 1; } }
@keyframes g-bub-swell { 0% { transform: scale(1); } 100% { transform: scale(1.38) rotate(2deg); } }
@keyframes g-bub-pop { 0% { transform: scale(1); opacity: 1; } 45% { transform: scale(1.25); opacity: .9; } 100% { transform: scale(1.6); opacity: 0; visibility: hidden; } }

/* 4. confetti layer: never blocks the form */
.g-confetti { position: fixed; inset: 0; pointer-events: none; overflow: hidden; z-index: 60; }
.g-confetti i { position: absolute; left: 0; top: 0; display: block; will-change: transform, opacity; border-radius: 1px; }
.g-confetti i.w { box-shadow: 0 0 0 1px rgba(10,35,66,.14); }

/* skipped / error re-render / finished: Gusty keeps breathing and bending, the bubble is gone, no confetti */
.gusty-stage.g-final .g-man  { animation: g-breathe 4.4s ease-in-out infinite; }
.gusty-stage.g-final .g-seg1 { animation: g-bend1 4.4s ease-in-out infinite; }
.gusty-stage.g-final .g-seg2 { animation: g-bend2 4.4s ease-in-out infinite; }
.gusty-stage.g-final .g-seg3 { animation: g-bend3 4.4s ease-in-out infinite; }
.gusty-stage.g-final .g-arm-l { animation: g-arm-l 4.4s ease-in-out infinite; }
.gusty-stage.g-final .g-arm-r { animation: g-arm-r 4.4s ease-in-out infinite; }
.gusty-stage.g-final .g-shadow { animation: g-shadow 4.4s ease-in-out infinite; }
.gusty-stage.g-final .g-bubble-pop { display: none; }

/* owner-only pencil + edit box (preview page only) */
.g-edit { position: absolute; left: -.4rem; top: -.4rem; z-index: 70; pointer-events: auto; }
.g-pencil { list-style: none; cursor: pointer; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; background: #fff; color: var(--navy, #0a2342);
  border: 2px solid var(--navy, #0a2342); box-shadow: 0 2px 0 var(--g-red); }
.g-pencil::-webkit-details-marker { display: none; }
.g-pencil:hover { background: var(--blue-soft, #e9f0f9); }
.g-edit-box { position: absolute; left: 0; top: 44px; width: 17rem; background: #fff; border: 1px solid var(--line, #d3dae6); border-top: 4px solid var(--navy, #0a2342);
  border-radius: 8px; padding: .8rem; box-shadow: 0 10px 30px rgba(10,35,66,.2); }

/* phones: still on the left, fully visible: arms raised higher so he fits a narrow column (the SVG is wider than its column) */
@media (max-width: 640px) {
  :root { --g-fig-h: clamp(300px, calc(100svh - 300px), 440px); }
  .login-wrap { gap: .35rem; align-items: flex-start; margin-top: .4rem; }
  .login-wrap .card.narrow.login { flex: 1 1 0; min-width: 0; margin-top: 5.6rem; padding: .8rem; align-self: flex-start; }
  .login-wrap .card.narrow.login h1 { font-size: 1.2rem; }
  .gusty-stage { width: calc(var(--g-fig-h) * .6333 * .64); }
  .gusty-stage .gusty-svg { width: calc(var(--g-fig-h) * .6333); margin-left: calc(var(--g-fig-h) * .6333 * -.09); }
  .gusty-svg .g-arm-l-pose { transform: rotate(30deg); }
  .gusty-svg .g-arm-r-pose { transform: rotate(-26deg); }
  .g-bubble-pop { width: 12rem; left: 58%; top: -3%; }
  .g-bubble { font-size: .78rem; padding: .55rem .7rem .65rem; border-width: 2px; }
}

/* reduced motion: static Gusty, bubble shown still, no confetti */
@media (prefers-reduced-motion: reduce) {
  .gusty-stage *, .gusty-stage .g-man, .gusty-stage .g-arm-l, .gusty-stage .g-arm-r { animation: none !important; }
  .gusty-stage .g-line { clip-path: none; }
  .gusty-stage .g-bubble-pop { display: block; }
}

/* ---------- post-login portal transition (successful sign-in only; hidden unless portal_tx.js plays it) ---------- */
.ptx { position: fixed; inset: 0; z-index: 10000; background: var(--bg, #f5f7fb); overflow: hidden; pointer-events: none; }
.ptx[hidden] { display: none; }
.ptx-stage { position: absolute; left: max(1rem, calc(50% - 530px)); bottom: 1rem; height: var(--g-fig-h); width: calc(var(--g-fig-h) * .6333); }
@media (max-width: 640px) { .ptx-stage { left: .2rem; top: 110px; bottom: auto; } }
.ptx-portal { position: absolute; inset: 0; display: grid; place-items: center; clip-path: ellipse(0 0 at 50% 50%);
  background: radial-gradient(ellipse at 50% 45%, #2f6db5 0%, #163a6b 45%, #0a2342 100%); }
.ptx-text { color: #fff; font-weight: 800; font-size: clamp(2rem, 7vw, 4.6rem); text-align: center; padding: 0 1rem; text-shadow: 0 4px 0 #c8102e, 0 0 30px rgba(255,255,255,.35); opacity: 0; }
.ptx-rim { position: absolute; left: 50%; top: 50%; width: 10px; height: 10px; border-radius: 50%; transform: translate(-50%, -50%) scale(0);
  box-shadow: 0 0 0 5px #fff, 0 0 0 11px #c8102e, 0 0 34px 14px rgba(47,109,181,.75); }
.ptx.ptx-reduced { background: transparent; }
.ptx.ptx-reduced .ptx-stage, .ptx.ptx-reduced .ptx-rim { display: none; }
.ptx.ptx-reduced .ptx-portal { clip-path: none; }
.ptx.ptx-reduced .ptx-text { opacity: 1; }
