/* =============================================================================
   ShiftHawk — Team Invitations section (vanilla CSS, no dependencies)
   The flagship "build a team, the work distributes itself" pitch.
   Pairs with assets/js/team-invite.js, which plays the scroll-triggered
   animation (IntersectionObserver) and serves a static composed state under
   prefers-reduced-motion. Reuses the design tokens from styles.css.
   ========================================================================== */

/* ---- Section frame ---------------------------------------------------------- */
.team-section { position: relative; overflow: hidden; }
.team-section .container { position: relative; z-index: 1; }

/* a faint cyan wash high-right, echoing the hero glow but lighter */
.team-glow {
  position: absolute; z-index: 0; pointer-events: none;
  width: 560px; height: 560px; right: -160px; top: -120px; border-radius: 50%;
  background: radial-gradient(circle, rgba(8,145,178,.10), transparent 70%);
  filter: blur(30px);
}
html[data-theme="dark"] .team-glow { background: radial-gradient(circle, rgba(34,211,238,.10), transparent 70%); }

/* ---- Two-up: copy (left) + animation stage (right) -------------------------- */
.team-grid {
  display: grid; grid-template-columns: 0.92fr 1.08fr; gap: var(--s-8);
  align-items: center;
}
@media (max-width: 980px) { .team-grid { grid-template-columns: 1fr; gap: var(--s-7); } }
.team-grid > div { min-width: 0; }

/* ---- Left column: the contrast + the numbered story ------------------------- */
.team-lede { font-size: 1.18rem; color: var(--text-2); }

.team-contrast {
  display: grid; grid-template-columns: 1fr; gap: var(--s-3);
  margin: var(--s-5) 0 var(--s-6);
}
@media (min-width: 540px) { .team-contrast { grid-template-columns: 1fr 1fr; } }
.team-contrast .tc-card {
  border-radius: var(--r-3); padding: var(--s-4) var(--s-5);
  display: flex; flex-direction: column; gap: 6px;
}
.tc-solo { border: 1px dashed var(--border-strong); background: transparent; }
.tc-team { border: 1px solid var(--primary-tint); background: var(--primary-soft); box-shadow: var(--shadow-sm); }
.tc-card .tc-head {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-display); font-weight: 700; font-size: 1.02rem; color: var(--text-1);
}
.tc-solo .tc-head i { color: var(--text-3); font-size: 1.35rem; }
.tc-team .tc-head i { color: var(--primary); font-size: 1.35rem; }
.tc-card p { margin: 0; font-size: .94rem; color: var(--text-2); }

/* numbered story — four short beats that name the steps */
.team-steps { list-style: none; padding: 0; margin: var(--s-5) 0 0; display: grid; gap: var(--s-4); }
.team-steps li { display: grid; grid-template-columns: 34px 1fr; gap: var(--s-3); align-items: start; }
.team-steps .ts-num {
  width: 34px; height: 34px; border-radius: var(--r-2); flex: none;
  display: grid; place-items: center; font-family: var(--font-mono); font-weight: 700; font-size: .95rem;
  background: var(--primary-soft); color: var(--primary-deep); border: 1px solid var(--primary-tint);
}
.team-steps li p { margin: 0; font-size: .98rem; color: var(--text-2); }
.team-steps li strong { color: var(--text-1); }

/* sweetener row — two tokens + the price */
.team-perks { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-6); }
.perk-pill {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-display); font-weight: 600; font-size: .9rem;
  padding: 8px 14px; border-radius: var(--r-pill);
  border: 1px solid var(--border); background: var(--surface); color: var(--text-1);
}
.perk-pill i { font-size: 1.2rem; flex: none; }
.perk-token i { color: var(--success); }
.perk-price { border-color: var(--primary-tint); background: var(--primary-soft); color: var(--primary-deep); }
.perk-price i { color: var(--primary); }
.perk-price s { color: var(--text-3); font-weight: 500; margin-right: 2px; }

/* the price-drop perk is now a link to the pricing section (a "second invite"
   pointer). Keep the pill shape, give it a comfortable tap target + hover. */
a.perk-pill { text-decoration: none; min-height: 44px; transition: background .2s ease, border-color .2s ease, color .2s ease; }
a.perk-price:hover { background: var(--primary); border-color: var(--primary); color: #fff; }
a.perk-price:hover i { color: #fff; }

/* the dual-track clarifier under the perk pills */
.team-perks-note {
  margin: var(--s-3) 0 0; font-size: .92rem; line-height: 1.55; color: var(--text-2);
  max-width: 52ch;
}
.team-perks-note strong { color: var(--text-1); }
.team-perks-note s { color: var(--text-3); font-weight: 500; margin-right: 2px; }
.team-perks-note a { color: var(--primary-deep); font-weight: 600; }

/* ---- Right column: the animation stage -------------------------------------- */
.team-stage {
  position: relative;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-4); box-shadow: var(--shadow-md);
  padding: var(--s-6) var(--s-5) var(--s-5);
  min-height: 420px;
  display: grid; grid-template-rows: auto 1fr auto;
  gap: var(--s-4);
  overflow: hidden;
}
.stage-caption {
  font-family: var(--font-mono); font-size: .74rem; font-weight: 600;
  letter-spacing: .05em; text-transform: uppercase; color: var(--text-3);
  display: flex; align-items: center; gap: 8px; min-height: 18px;
}
.stage-caption i { color: var(--primary); font-size: 1.1rem; }

/* the network grid: a ring of teammate avatars + a center "you/share" hub */
.team-net {
  position: relative; width: 100%; aspect-ratio: 1 / 1; max-width: 380px;
  margin: 0 auto; align-self: center;
}
.net-node {
  position: absolute; width: 16%; aspect-ratio: 1 / 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface-2); border: 1.5px solid var(--border);
  color: var(--text-2);
  box-shadow: var(--shadow-sm);
}
.net-node i { font-size: 1.15rem; }
@media (max-width: 460px) { .net-node i { font-size: .95rem; } }

/* the hub at the center — "you" / share link origin */
.net-hub {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 23%; aspect-ratio: 1 / 1; border-radius: 50%;
  display: grid; place-items: center; z-index: 4;
  background: linear-gradient(160deg, var(--primary-bright), var(--primary));
  border: 2px solid #fff; color: #fff;
  box-shadow: var(--shadow-cyan);
}
html[data-theme="dark"] .net-hub { border-color: rgba(255,255,255,.55); }
.net-hub i { font-size: 1.5rem; }

/* the invited node — starts dim, joins, then glows */
.net-node.is-joiner {
  border-color: var(--primary); color: var(--primary-deep);
  background: var(--primary-soft);
}

/* connecting spokes drawn as a single SVG underlay */
.net-links { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; overflow: visible; }
.net-links line {
  stroke: var(--border-strong); stroke-width: 1.5; opacity: .55;
}
html[data-theme="dark"] .net-links line { stroke: var(--ink-border); opacity: .7; }

/* a token badge that pops near a node (+1 free Single Swap) */
.token-badge {
  position: absolute; transform: translate(-50%, -50%) scale(.4);
  z-index: 5; opacity: 0;
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-mono); font-weight: 700; font-size: .66rem;
  padding: 3px 8px; border-radius: var(--r-pill);
  background: var(--success); color: #fff;
  box-shadow: var(--shadow-sm); white-space: nowrap;
}
.token-badge i { font-size: .85rem; }

/* the price tag that pops in for the joiner */
.price-tag {
  position: absolute; left: 50%; bottom: 6%; transform: translate(-50%, 8px) scale(.7);
  z-index: 6; opacity: 0;
  display: inline-flex; align-items: baseline; gap: 6px;
  font-family: var(--font-display); font-weight: 700;
  padding: 7px 14px; border-radius: var(--r-pill);
  background: var(--banana); color: #92400E;
  box-shadow: var(--shadow-md); white-space: nowrap;
}
.price-tag s { color: #B45309; font-weight: 600; font-size: .82em; opacity: .8; }
.price-tag .pt-now { font-size: 1.05rem; }
.price-tag .pt-unit { font-family: var(--font-body); font-weight: 600; font-size: .72rem; color: #92400E; opacity: .85; }

/* the joiner's mini phone that fills with the team's schedules */
.team-phone {
  align-self: center; justify-self: center;
  width: 122px; flex: none;
  border-radius: 22px; padding: 7px;
  background: linear-gradient(160deg, #2b3648, #0c121e);
  box-shadow: var(--shadow-md);
}
.team-phone-screen {
  border-radius: 16px; background: var(--surface); overflow: hidden;
  display: grid; gap: 4px; padding: 8px 7px;
}
html[data-theme="dark"] .team-phone-screen { background: var(--surface-2); }
.tp-head {
  font-family: var(--font-mono); font-size: .54rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-3); padding: 0 1px 2px;
  display: flex; align-items: center; gap: 4px;
}
.tp-head i { color: var(--primary); font-size: .8rem; }
.tp-row {
  display: grid; grid-template-columns: 14px 1fr auto; gap: 5px; align-items: center;
  font-size: .56rem; color: var(--text-2);
  background: var(--surface-2); border-radius: var(--r-1); padding: 4px 5px;
  opacity: 0; transform: translateY(4px);
}
html[data-theme="dark"] .tp-row { background: rgba(255,255,255,.05); }
.tp-row .tp-dot { width: 9px; height: 9px; border-radius: 50%; }
.tp-row .tp-name { font-weight: 600; color: var(--text-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tp-row .tp-code { font-family: var(--font-mono); font-size: .5rem; color: var(--primary-deep); }

.stage-foot {
  font-size: .9rem; color: var(--text-2); text-align: center;
  min-height: 1.4em; line-height: 1.4;
}
.stage-foot strong { color: var(--text-1); }

/* a small "replay" affordance the JS reveals after the animation completes */
.stage-replay {
  position: absolute; right: var(--s-3); top: var(--s-3); z-index: 7;
  display: none; align-items: center; justify-content: center; gap: 6px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text-2);
  border-radius: var(--r-pill); padding: 0 var(--s-4); cursor: pointer;
  font-family: var(--font-mono); font-size: .7rem; font-weight: 600;
  min-height: 44px;
}
.stage-replay:hover { background: var(--surface); color: var(--text-1); border-color: var(--border-strong); }
.stage-replay.show { display: inline-flex; }
.stage-replay i { font-size: .95rem; }

/* =============================================================================
   ANIMATION — every keyframe and transition below is disabled under
   prefers-reduced-motion (see the media query at the bottom). The JS adds the
   .anim-* classes step-by-step; with reduced motion the JS instead drops the
   stage straight into its final composed state and the rules here never apply.
   ========================================================================== */

/* spokes draw in from the hub */
.net-links line { stroke-dasharray: 200; stroke-dashoffset: 200; transition: stroke-dashoffset .5s ease; }
.team-net.anim-spokes .net-links line { stroke-dashoffset: 0; }

/* nodes settle in with a gentle pop, staggered via inline --d on each node */
.net-node { opacity: 0; transition: opacity .35s ease, transform .35s ease; }
.team-net.anim-nodes .net-node { opacity: 1; }
.team-net.anim-nodes .net-node { animation: node-pop .4s ease both; animation-delay: var(--d, 0s); }
@keyframes node-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.4); }
  70% { transform: translate(-50%, -50%) scale(1.08); }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* the joiner arrives along its spoke + glows */
.net-node.is-joiner { transition: opacity .4s ease, box-shadow .4s ease, border-color .3s; }
.team-net.anim-join .net-node.is-joiner {
  box-shadow: 0 0 0 6px rgba(8,145,178,.18), var(--shadow-md);
  animation: joiner-arrive .6s ease both;
}
@keyframes joiner-arrive {
  0% { opacity: .35; transform: translate(-50%, -50%) scale(.5); }
  60% { transform: translate(-50%, -50%) scale(1.14); }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* ---- UPLOAD parcel: the joiner's schedule visibly travels joiner -> hub ----- */
/* a little "schedule" chip that starts at the joiner node and slides into the
   hub, making "their schedule uploads once" literal before anything radiates. */
.net-parcel {
  position: absolute; z-index: 6; opacity: 0; pointer-events: none;
  /* JS sets --jx/--jy (joiner %) and --hx/--hy (hub %, = 50/50) as inline vars */
  left: var(--jx, 70%); top: var(--jy, 70%);
  transform: translate(-50%, -50%) scale(.5);
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-mono); font-weight: 700; font-size: .58rem;
  padding: 4px 7px; border-radius: var(--r-1);
  background: var(--surface); color: var(--primary-deep);
  border: 1.5px solid var(--primary); box-shadow: var(--shadow-md); white-space: nowrap;
}
.net-parcel i { font-size: .8rem; color: var(--primary); }
/* the joiner's spoke lights up FIRST (schedule flowing inward to the hub) */
.team-net.anim-uplink .net-links line.is-uplink {
  stroke: var(--primary); opacity: 1; transition: stroke .35s ease, opacity .35s ease;
}
.team-net.anim-uplink .net-parcel {
  animation: parcel-uplink 1s ease-in-out forwards;
}
@keyframes parcel-uplink {
  0%   { opacity: 0;  left: var(--jx); top: var(--jy); transform: translate(-50%, -50%) scale(.5); }
  18%  { opacity: 1;  transform: translate(-50%, -50%) scale(1); }
  82%  { opacity: 1;  left: var(--hx); top: var(--hy); transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0;  left: var(--hx); top: var(--hy); transform: translate(-50%, -50%) scale(.7); }
}
/* the hub gives a confirming pulse the instant the parcel lands in it */
.team-net.anim-uplink .net-hub { animation: hub-receive 1s ease both; }
@keyframes hub-receive {
  0%, 78% { box-shadow: var(--shadow-cyan); }
  88%     { box-shadow: 0 0 0 9px rgba(8,145,178,.22), var(--shadow-cyan); }
  100%    { box-shadow: var(--shadow-cyan); }
}

/* the ripple: the hub then radiates the schedule OUT to everyone (pulsing ring) */
.net-ripple {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 23%; aspect-ratio: 1 / 1; border-radius: 50%;
  border: 2px solid var(--primary-bright); z-index: 2; opacity: 0; pointer-events: none;
}
.team-net.anim-ripple .net-ripple { animation: ripple-out 1.1s ease-out forwards; }
@keyframes ripple-out {
  0% { opacity: .8; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(4.6); }
}

/* every OTHER spoke lights cyan as the schedule travels outward to the team */
.team-net.anim-ripple .net-links line { stroke: var(--primary-bright); opacity: 1; transition: stroke .5s ease, opacity .5s ease; }

/* each non-joiner node gets a brief "fills in" ring as the schedule reaches it */
.team-net.anim-ripple .net-node:not(.is-joiner) {
  animation: node-receive .6s ease both; animation-delay: var(--rd, 0s);
}
@keyframes node-receive {
  0%   { box-shadow: var(--shadow-sm); }
  55%  { box-shadow: 0 0 0 5px rgba(8,145,178,.20), var(--shadow-sm); border-color: var(--primary); }
  100% { box-shadow: var(--shadow-sm); }
}

/* token badges pop */
.team-net.anim-perks .token-badge { animation: badge-pop .5s ease both; }
.team-net.anim-perks .token-badge.tb-2 { animation-delay: .12s; }
@keyframes badge-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.4); }
  65% { transform: translate(-50%, -50%) scale(1.18); }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* phone rows fill in, staggered via inline --r on each row */
.team-stage.anim-phone .tp-row { animation: row-in .35s ease both; animation-delay: var(--r, 0s); }
@keyframes row-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* price tag pops last */
.team-net.anim-price .price-tag { animation: price-pop .55s ease both; }
@keyframes price-pop {
  0% { opacity: 0; transform: translate(-50%, 8px) scale(.7); }
  60% { transform: translate(-50%, -2px) scale(1.08); }
  100% { opacity: 1; transform: translate(-50%, 0) scale(1); }
}

/* =============================================================================
   STATIC COMPOSED STATE — applied by the JS (class .is-static on the stage)
   whenever prefers-reduced-motion is set OR IntersectionObserver is missing.
   Everything is shown in its final position with no motion.
   ========================================================================== */
.team-stage.is-static .net-node,
.team-net.is-static .net-node { opacity: 1; animation: none; transform: translate(-50%, -50%); }
.team-stage.is-static .net-links line,
.team-net.is-static .net-links line { stroke-dashoffset: 0; }
.team-stage.is-static .net-node.is-joiner,
.team-net.is-static .net-node.is-joiner { box-shadow: 0 0 0 5px rgba(8,145,178,.16), var(--shadow-sm); }
.team-stage.is-static .token-badge { opacity: 1; transform: translate(-50%, -50%) scale(1); animation: none; }
.team-stage.is-static .price-tag { opacity: 1; transform: translate(-50%, 0) scale(1); animation: none; }
.team-stage.is-static .tp-row { opacity: 1; transform: none; animation: none; }
.team-stage.is-static .net-ripple { display: none; }
/* in the static state the upload is told by the lit joiner spoke + a parcel
   parked at the hub (no travel animation) */
.team-net.is-static .net-links line.is-uplink { stroke: var(--primary); opacity: 1; }
.team-stage.is-static .net-parcel,
.team-net.is-static .net-parcel {
  opacity: 1; left: var(--hx, 50%); top: var(--hy, 50%);
  transform: translate(-50%, -50%) scale(.95); animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .net-links line { transition: none; stroke-dashoffset: 0; }
  .net-links line.is-uplink { stroke: var(--primary); opacity: 1; }
  .net-node { opacity: 1; animation: none !important; transform: translate(-50%, -50%); }
  .net-node.is-joiner { animation: none !important; }
  .token-badge { opacity: 1; transform: translate(-50%, -50%) scale(1); animation: none !important; }
  .price-tag { opacity: 1; transform: translate(-50%, 0) scale(1); animation: none !important; }
  .tp-row { opacity: 1; transform: none; animation: none !important; }
  .net-ripple { display: none; }
  .net-parcel {
    opacity: 1; left: var(--hx, 50%); top: var(--hy, 50%);
    transform: translate(-50%, -50%) scale(.95); animation: none !important;
  }
}
