/* ===== shared chrome CSS (lifted verbatim from W-CALCULATORS _chrome) ===== */
.cz-light{
  --w-bg:#f5f5f5;--w-bg-deep:#ededed;--w-bg-elev:#fff;
  --w-surface:#fff;--w-surface-hi:#fff;--w-surface-lo:#f0f0f0;
  --w-card:#fff;--w-card-hi:#fff;--w-card-lo:#fafafa;
  --w-text:#1c1a24;--w-text-2:rgba(28,26,36,.66);--w-text-3:rgba(28,26,36,.62);
  --w-line:rgba(28,26,36,.10);--w-line-soft:rgba(28,26,36,.06);--w-line-strong:rgba(28,26,36,.16);
  /* This lifted .cz-light block is a hand-rolled partial of ds7's :root[data-theme="light"]
     set, and it was missing the two AA corrections that live there:
       --w-brand   must be --w-purple-ink (#6f5fe0). --w-purple (#9887f4) measures 2.52:1
                   against this band's card gradient — it fails even the 3:1 large-text bar,
                   and .ipi__stat.violet was rendering in it at 42px.
       --w-text-3  .46 alpha composites to ~3.0:1 on the card; ds7 bumped it to .62.
     ds7.css itself is correct — do not change it; this copy was the stale one. */
  --w-brand:var(--w-purple-ink);
  background:var(--w-bg);color:var(--w-text)
}
.cz-light .w-section-head__title{color:var(--w-text)}
.cz-light .w-section-head__lead{color:var(--w-text-2)}


/* eyebrow — same recipe as the calculators page so the two tools read as one family */
.cx-eyebrow{display:inline-flex;align-items:center;gap:8px;padding:7px 14px;border-radius:100px;font-size:12px;font-weight:var(--w-fw-semi);letter-spacing:.04em;text-transform:uppercase;color:#fff;background:linear-gradient(158deg,rgba(34,29,48,.94),rgba(12,10,20,.97));border:1px solid rgba(255,255,255,.16);box-shadow:inset 0 1px 0 rgba(255,255,255,.14),0 3px 10px rgba(0,0,0,.14)}
.cx-eyebrow .w-icon{width:15px;height:15px;color:#c9bcff}

/* ===== W-PIPELINE-CALCULATOR page-local styles ===== */
.w-section{padding-block:clamp(80px,5.5vw,112px)}

/* ---------- assessment shell ---------- */
.ip-calc{position:relative;overflow:hidden;background:var(--w-bg);padding-block:clamp(96px,12vh + 2rem,150px) clamp(56px,6vw,86px)}
.ip-calc__bg{position:absolute;inset:0;z-index:0;pointer-events:none;background:radial-gradient(ellipse 60% 55% at 50% 0%,rgba(152,135,244,.18),transparent 70%),radial-gradient(rgba(255,255,255,.045) 1px,transparent 1.4px);background-size:auto,26px 26px}
.ip-calc__bg::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 58%,var(--w-bg))}
.ip-calc .w-container{position:relative;z-index:1}

.ip-head{max-width:760px;margin:0 auto clamp(34px,3.6vw,52px);text-align:center}
.ip-head__h{margin-top:16px;font-size:var(--w-fs-display);line-height:var(--w-lh-tight);letter-spacing:var(--w-ls-tight);font-weight:var(--w-fw-black);color:#fff}
.ip-head__h .w-accent{font-family:var(--w-font-serif);font-style:italic;font-weight:400;color:#c9bcff;-webkit-text-fill-color:#c9bcff;background:none}
.ip-head__sub{margin:18px auto 0;max-width:56ch;font-size:var(--w-fs-lead);line-height:1.6;color:rgba(255,255,255,.84)}

.ip-panel{max-width:1120px;margin-inline:auto;display:grid;grid-template-columns:1fr 1fr;gap:clamp(20px,2.2vw,34px);align-items:start}

/* MATERIAL — .ip-calc is a DARK, busy ground (radial brand wash + a 26px dot grid), so real
   glass earns its keep here: backdrop-filter actually has texture to soften, the top rim reads
   as light catching a lifted edge, and the deep shadow separates the pane from the field. */
.ip-card{
  position:relative;isolation:isolate;
  background:linear-gradient(160deg,rgba(38,32,56,.72),rgba(21,18,30,.80));
  -webkit-backdrop-filter:blur(18px) saturate(140%);backdrop-filter:blur(18px) saturate(140%);
  border:1px solid rgba(255,255,255,.10);border-radius:26px;padding:clamp(26px,2.4vw,40px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.28),0 28px 60px -28px rgba(0,0,0,.72),0 2px 10px rgba(0,0,0,.26)
}
.ip-card--dark{
  background:linear-gradient(160deg,rgba(45,38,68,.74),rgba(24,20,34,.82));
  border-color:rgba(201,188,255,.22);color:#fff;overflow:hidden
}

/* ---------- invite pane (right card, pre-first-answer) ---------- */
.ip-invite{text-align:center;transition:opacity .32s var(--w-ease),transform .32s var(--w-ease),filter .32s var(--w-ease)}
.ip-invite.is-out{opacity:0;transform:translateY(-10px) scale(.985);filter:blur(5px);pointer-events:none}
.ip-invite.is-gone{display:none}
.ip-invite__icon{width:60px;height:60px;margin:0 auto;display:grid;place-items:center;border-radius:18px;background:rgba(152,135,244,.14);border:1px solid rgba(201,188,255,.24)}
.ip-invite__icon .w-icon{width:26px;height:26px;color:#c9bcff}
.ip-invite__h{margin-top:20px;font-size:var(--w-fs-h3);font-weight:var(--w-fw-black);letter-spacing:var(--w-ls-tight);color:#fff}
.ip-invite__h .w-accent{font-family:var(--w-font-serif);font-style:italic;font-weight:400;color:#c9bcff;-webkit-text-fill-color:#c9bcff;background:none}
.ip-invite__sub{margin-top:10px;font-size:var(--w-fs-sm);line-height:1.6;color:rgba(255,255,255,.7)}
.ip-invite__list{margin:clamp(22px,2.2vw,30px) 0 0;padding:0;list-style:none;text-align:left}
.ip-invite__list li{display:flex;gap:12px;align-items:flex-start;padding:13px 0;border-top:1px solid rgba(255,255,255,.08);font-size:var(--w-fs-sm);line-height:1.5;color:rgba(255,255,255,.82)}
.ip-invite__list li:first-child{border-top:none}
.ip-tick{flex:0 0 auto;width:22px;height:22px;display:grid;place-items:center;border-radius:7px;background:rgba(152,135,244,.16);border:1px solid rgba(201,188,255,.24)}
.ip-tick .w-icon{width:13px;height:13px;color:#c9bcff}
.ip-invite__cue{margin-top:clamp(22px,2.2vw,30px);display:flex;align-items:center;justify-content:center;gap:9px;padding:12px 16px;border-radius:var(--w-r-pill);background:rgba(152,135,244,.10);border:1px solid rgba(201,188,255,.20);font-size:var(--w-fs-xs);color:rgba(255,255,255,.72)}
.ip-invite__dot{flex:0 0 auto;width:8px;height:8px;border-radius:var(--w-r-full);background:#c9bcff;box-shadow:0 0 0 0 rgba(201,188,255,.6);animation:ip-cue 2.4s var(--w-ease) infinite}
@keyframes ip-cue{0%{box-shadow:0 0 0 0 rgba(201,188,255,.55)}70%,100%{box-shadow:0 0 0 9px rgba(201,188,255,0)}}

/* ---------- steps ---------- */
.quiz-steps-container{display:none}
.quiz-steps-container.is-active{display:block}
.ip-steps__top{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;padding-bottom:18px;border-bottom:1px solid rgba(255,255,255,.1)}
.ip-steps__title{font-size:var(--w-fs-sm);font-weight:var(--w-fw-bold);color:#fff}
.ip-progress{display:flex;gap:6px}
.progress-step{width:26px;height:4px;border-radius:4px;background:rgba(255,255,255,.14);transition:background .3s ease}
.progress-step.active{background:var(--w-grad-brand)}
.progress-step.complete{background:#c9bcff}

.quiz-step{display:none;opacity:0;transform:translateX(18px);transition:opacity .35s ease,transform .35s ease}
.quiz-step.active{display:block;opacity:1;transform:none}
.quiz-step.exit-left{display:none}

.ip-q{margin-top:clamp(22px,2.2vw,30px)}
.ip-q__meta{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ip-q__num{font-size:var(--w-fs-xs);font-weight:var(--w-fw-semi);letter-spacing:.04em;text-transform:uppercase;color:rgba(255,255,255,.5)}
.ip-q__cat{font-size:var(--w-fs-xs);font-weight:var(--w-fw-bold);letter-spacing:.04em;text-transform:uppercase;color:var(--w-brand);background:rgba(152,135,244,.12);padding:3px 9px;border-radius:100px}
.ip-q__label{margin-top:12px;font-size:var(--w-fs-h4);line-height:var(--w-lh-snug);font-weight:var(--w-fw-bold);color:#fff}
.ip-q__hint{margin-top:10px;font-size:var(--w-fs-sm);line-height:1.55;color:rgba(255,255,255,.62)}

.option-grid{margin-top:clamp(18px,1.8vw,24px);display:grid;grid-template-columns:repeat(2,1fr);gap:10px}
.option-grid.is-shake{animation:ip-shake .5s ease}
@keyframes ip-shake{0%,100%{transform:translateX(0)}20%,60%{transform:translateX(-6px)}40%,80%{transform:translateX(6px)}}
/* min-height 44px: these are the page's primary touch targets (interaction doctrine) */
.option-btn{appearance:none;cursor:pointer;text-align:center;min-height:48px;padding:14px 10px;border-radius:14px;border:1px solid rgba(255,255,255,.15);background:rgba(255,255,255,.05);color:rgba(255,255,255,.85);font:var(--w-fw-semi) var(--w-fs-sm)/1.25 var(--w-font);transition:border-color .2s var(--w-ease),background .2s var(--w-ease),color .2s var(--w-ease),transform .2s var(--w-ease),box-shadow .2s var(--w-ease)}
/* hover AND focus-visible get the identical lift — the tease is hover-driven, so a keyboard
   user must see the same "this one is armed" state while the instrument previews their answer */
.option-btn:hover,.option-btn:focus-visible{border-color:rgba(152,135,244,.6);background:rgba(255,255,255,.09);transform:translateY(-2px);box-shadow:0 10px 22px -12px rgba(152,135,244,.75),inset 0 1px 0 rgba(255,255,255,.16)}
.option-btn:focus-visible{outline:2px solid #c9bcff;outline-offset:2px}
.option-btn.selected{background:var(--w-grad-brand);border-color:transparent;color:#fff}
.option-btn.selected.danger-state{background:linear-gradient(150deg,#ef4444,#b91c1c)}
.option-btn.selected.warning-state{background:linear-gradient(150deg,#f59e0b,#b45309)}
.option-btn.selected.success-state{background:linear-gradient(150deg,#22c55e,#15803d)}

.ip-nav{margin-top:clamp(20px,2vw,28px);display:flex;align-items:center;gap:12px}
.ip-nav--final{justify-content:space-between}
.btn-back{appearance:none;cursor:pointer;display:inline-flex;align-items:center;gap:7px;padding:11px 16px;border-radius:100px;border:1px solid rgba(255,255,255,.16);background:transparent;color:rgba(255,255,255,.72);font:var(--w-fw-semi) var(--w-fs-sm)/1 var(--w-font);transition:border-color .2s ease,color .2s ease}
.btn-back:hover:not(:disabled){border-color:rgba(255,255,255,.34);color:#fff}
.btn-back:disabled{opacity:.34;cursor:not-allowed}
.ip-nav__back-i{width:15px;height:15px;transform:rotate(180deg)}
.calculate-btn{opacity:0;visibility:hidden;transition:opacity .3s ease,visibility .3s}
.calculate-btn.is-visible{opacity:1;visibility:visible}

/* ---------- results panel / instrument ---------- */
/* Three states live on #ipInstrument:
     (none)        — not shown yet; the invite pane owns the card
     .is-on        — mounted
     .is-on        + no .is-revealed = TEASE. Bars and ring arc track a live PROJECTION of the
                     score (answered questions use the real value, unanswered assume 2 of 4), so
                     every hover moves them in the direction that answer would actually push the
                     score. Only the NUMERALS are obscured — the motion is honest.
     .is-revealed  — Calculate Score has run; numerals unblur, tier colours apply. */
.ip-inst{position:relative;display:none;opacity:0;transform:translateY(16px) scale(.99);filter:blur(8px);transition:opacity .52s cubic-bezier(.22,.9,.3,1),transform .52s cubic-bezier(.22,.9,.3,1),filter .52s cubic-bezier(.22,.9,.3,1)}
.ip-inst.is-mounted{display:block}
.ip-inst.is-on{opacity:1;transform:none;filter:none}

/* whirring scan — the instrument is working even when nothing is being hovered */
.ip-inst__scan{position:absolute;inset:-40% -10%;z-index:0;pointer-events:none;opacity:0;background:linear-gradient(112deg,transparent 42%,rgba(201,188,255,.10) 50%,transparent 58%);transform:translate3d(-70%,0,0)}
.ip-inst.is-on:not(.is-revealed) .ip-inst__scan{opacity:1;animation:ip-scan 11s ease-in-out infinite}
@keyframes ip-scan{0%{transform:translate3d(-70%,0,0)}100%{transform:translate3d(70%,0,0)}}
.ip-inst>*:not(.ip-inst__scan){position:relative;z-index:1}

/* the obscuring: numerals only */
.ip-inst .ip-score__num,.ip-inst .ip-dim__val{transition:filter .55s cubic-bezier(.22,.9,.3,1),opacity .55s cubic-bezier(.22,.9,.3,1),transform .34s var(--w-ease-spring)}
.ip-inst:not(.is-revealed) .ip-score__num,
.ip-inst:not(.is-revealed) .ip-dim__val{filter:blur(9px);opacity:.72}
.ip-inst:not(.is-revealed) .ip-dim__val{filter:blur(6px)}
.ip-inst.is-settling .ip-score__num{transform:scale(1.045)}

.ip-inst__lock{margin-top:18px;display:flex;align-items:center;justify-content:center;gap:8px;padding-top:15px;border-top:1px solid rgba(255,255,255,.08);font-size:var(--w-fs-xs);line-height:1.5;color:rgba(255,255,255,.5);transition:opacity .4s var(--w-ease)}
.ip-inst__lock .w-icon{width:13px;height:13px;color:#c9bcff;flex:0 0 auto}
.ip-inst.is-revealed .ip-inst__lock{display:none}

/* screen-reader-only progress line */
.ip-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

.ip-res__top{padding-bottom:20px;border-bottom:1px solid rgba(255,255,255,.1)}
.ip-res__title{font-size:var(--w-fs-h4);font-weight:var(--w-fw-bold);color:#fff}
.ip-res__desc{margin-top:5px;font-size:var(--w-fs-xs);color:rgba(255,255,255,.55)}

.ip-score{margin-top:clamp(22px,2.2vw,30px);display:flex;flex-direction:column;align-items:center;gap:14px;padding:clamp(20px,2vw,28px);border-radius:20px;background:rgba(152,135,244,.08);border:1px solid rgba(201,188,255,.16)}
.ip-score__ring{position:relative;width:180px;height:180px}
.ip-score__ring svg{transform:rotate(-90deg)}
.ip-score__ring circle{fill:none;stroke-width:12}
.ip-score__track{stroke:rgba(255,255,255,.1)}
/* Neutral brand stroke while teasing — a tier colour here would give the verdict away before
   the numbers unlock. animateRing() only paints tier strokes once .is-revealed is on. */
.ip-score__prog{stroke:#8b79ef;stroke-linecap:round;transition:stroke-dashoffset .46s cubic-bezier(.22,.9,.3,1),stroke .4s ease}
.ip-inst.is-revealed .ip-score__prog{transition:stroke-dashoffset .1s linear,stroke .4s ease}
.ip-inst.is-on:not(.is-revealed) .ip-score__ring{animation:ip-ring-breathe 9s ease-in-out infinite}
@keyframes ip-ring-breathe{0%,100%{filter:drop-shadow(0 0 5px rgba(152,135,244,.20))}50%{filter:drop-shadow(0 0 17px rgba(152,135,244,.48))}}
.ip-score__readout{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px}
.ip-score__num{font-size:50px;line-height:1;font-weight:var(--w-fw-black);color:#fff;font-variant-numeric:tabular-nums lining-nums}
.ip-score__of{font-size:var(--w-fs-xs);letter-spacing:.05em;text-transform:uppercase;color:rgba(255,255,255,.5)}
.ip-score__rating{font-size:var(--w-fs-sm);font-weight:var(--w-fw-bold);text-align:center;color:rgba(255,255,255,.55)}
.ip-score__rating.is-visible.critical{color:#f87171}
.ip-score__rating.is-visible.warning{color:#fbbf24}
.ip-score__rating.is-visible.good{color:#4ade80}
.ip-score__rating.is-visible.excellent{color:#34d399}

.ip-dims{margin-top:clamp(22px,2.2vw,30px)}
.ip-dims__h{font-size:var(--w-fs-xs);font-weight:var(--w-fw-bold);letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.5)}
.ip-dim{position:relative;display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:14px;padding:15px 0;border-top:1px solid rgba(255,255,255,.08)}
.ip-dim:first-of-type{border-top:none;padding-top:14px}
/* cued = "this is the dimension the answer you're pointing at moves" */
.ip-dim::before{content:"";position:absolute;inset:-1px -12px;z-index:-1;border-radius:14px;background:rgba(152,135,244,.13);box-shadow:inset 0 0 0 1px rgba(201,188,255,.24);opacity:0;pointer-events:none;transition:opacity .24s var(--w-ease)}
.ip-dim.is-cued::before{opacity:1}
.ip-dim__icon{width:34px;height:34px;display:grid;place-items:center;border-radius:11px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);transition:background .24s var(--w-ease),border-color .24s var(--w-ease),transform .24s var(--w-ease)}
.ip-dim.is-cued .ip-dim__icon{background:rgba(152,135,244,.22);border-color:rgba(201,188,255,.42);transform:scale(1.07)}
.ip-dim__icon .w-icon{width:16px;height:16px;color:#c9bcff}
.ip-dim__name{font-size:var(--w-fs-sm);font-weight:var(--w-fw-semi);color:rgba(255,255,255,.88)}
.ip-dim__track{position:relative;margin-top:7px;height:8px;border-radius:var(--w-r-pill);background:rgba(255,255,255,.1);overflow:hidden}
/* --v is 0..1. The bar keeps its full authored width and TRANSLATES, so the rounded head never
   distorts and the growth is a compositor transform (never `width`, which is layout). */
@property --v{syntax:'<number>';inherits:false;initial-value:0}
.ip-dim__bar{position:absolute;left:0;top:0;width:100%;height:100%;border-radius:var(--w-r-pill);background:var(--w-grad-brand);transform:translate3d(calc((var(--v,0) - 1) * 100%),0,0);transition:transform .62s cubic-bezier(.22,.9,.3,1),background .4s ease;will-change:transform}
.ip-dim__bar.critical{background:linear-gradient(90deg,#ef4444,#f87171)}
.ip-dim__bar.warning{background:linear-gradient(90deg,#f59e0b,#fbbf24)}
.ip-dim__bar.good{background:linear-gradient(90deg,#22c55e,#4ade80)}
.ip-dim__bar.excellent{background:linear-gradient(90deg,#10b981,#34d399)}
/* head glow — staggered so some row is always breathing, but each row's own period is 8s */
.ip-dim__glint{position:absolute;top:0;right:0;width:32px;height:100%;border-radius:inherit;background:linear-gradient(90deg,rgba(255,255,255,0),rgba(255,255,255,.62));opacity:0;pointer-events:none}
.ip-inst.is-on:not(.is-revealed) .ip-dim__glint{animation:ip-glint 8s ease-in-out infinite}
.ip-dim:nth-of-type(2) .ip-dim__glint{animation-delay:1.1s}
.ip-dim:nth-of-type(3) .ip-dim__glint{animation-delay:2.2s}
.ip-dim:nth-of-type(4) .ip-dim__glint{animation-delay:3.3s}
@keyframes ip-glint{0%,100%{opacity:0}5%{opacity:.8}17%{opacity:0}}
.ip-dim__val{min-width:30px;text-align:right;font-size:var(--w-fs-sm);font-weight:var(--w-fw-black);color:#fff;font-variant-numeric:tabular-nums lining-nums}

/* ---------- research band ---------- */
.ip-research{position:relative;overflow:hidden;background:var(--w-bg)}
.ipr{max-width:1160px;margin-inline:auto;display:grid;grid-template-columns:1fr .92fr;gap:clamp(30px,3.6vw,60px);align-items:center}
.ipr__h{margin-top:18px;font-size:var(--w-fs-h1);line-height:var(--w-lh-tight);letter-spacing:var(--w-ls-tight);font-weight:var(--w-fw-black);color:#fff}
.ipr__h .w-accent{font-family:var(--w-font-serif);font-style:italic;font-weight:400;color:#c9bcff;-webkit-text-fill-color:#c9bcff;background:none}
.ipr__sub{margin-top:18px;max-width:56ch;font-size:var(--w-fs-lead);line-height:1.6;color:rgba(255,255,255,.8)}
.ipr__stats{margin-top:clamp(26px,2.6vw,38px);display:grid;grid-template-columns:repeat(3,auto);justify-content:start;gap:clamp(22px,3vw,46px)}
.ipr__stat-v{font-size:clamp(28px,3.2vw,40px);line-height:1;font-weight:var(--w-fw-black);background:var(--w-grad-brand);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.ipr__stat-l{margin-top:7px;font-size:var(--w-fs-xs);letter-spacing:.03em;color:rgba(255,255,255,.6)}

.ipr__viz{position:relative;aspect-ratio:1;min-height:380px;display:grid;place-items:center}
.ipr__glow{position:absolute;border-radius:50%;filter:blur(64px);pointer-events:none;will-change:transform}
.ipr__glow--1{width:280px;height:280px;background:rgba(152,135,244,.26);top:4%;left:2%}
.ipr__glow--2{width:230px;height:230px;background:rgba(193,140,255,.2);bottom:6%;right:4%}
.ipr__radar{position:relative;width:270px;height:270px;display:grid;place-items:center}
.ipr__rings{position:absolute;inset:0;display:grid;place-items:center}
.ipr__rings span{position:absolute;border:1px solid rgba(255,255,255,.09);border-radius:50%}
.ipr__rings span:nth-child(1){width:270px;height:270px}
.ipr__rings span:nth-child(2){width:200px;height:200px}
.ipr__rings span:nth-child(3){width:130px;height:130px}
.ipr__rings span:nth-child(4){width:62px;height:62px}
/* centred with explicit offsets rather than grid alignment — the keyframes own `transform`, so
   a translate(-50%,-50%) centring trick would be clobbered by the scale */
.ipr__ping{position:absolute;left:50%;top:50%;margin:-135px 0 0 -135px;width:270px;height:270px;border-radius:50%;border:1px solid rgba(201,188,255,.55);opacity:0;pointer-events:none;will-change:transform,opacity}
.ipr__poly{position:relative;z-index:1}
.ipr__poly polygon{fill:rgba(152,135,244,.18);stroke:#9887f4;stroke-width:2}
.ipr__poly circle{fill:#c18cff;transform-box:fill-box;transform-origin:center}

/* ===== ambient life =====
   Five loops, all 8–15s ease-in-out, all compositor-only (transform / opacity / filter), all
   low-amplitude and on co-prime-ish periods so they never sync into a pulse. Armed by
   IntersectionObserver (.is-live) — an on-load animation has finished before anyone scrolls here.
   The hexagon itself does NOT scale: its six vertex dots are separate elements, so scaling the
   polygon alone would drift them off the corners. It breathes with a drop-shadow instead. */
.ipr__viz.is-live .ipr__rings span{animation:ipr-breathe 11s ease-in-out infinite}
.ipr__viz.is-live .ipr__rings span:nth-child(2){animation-delay:.9s;animation-duration:12.5s}
.ipr__viz.is-live .ipr__rings span:nth-child(3){animation-delay:1.8s;animation-duration:10s}
.ipr__viz.is-live .ipr__rings span:nth-child(4){animation-delay:2.7s;animation-duration:13.5s}
@keyframes ipr-breathe{0%,100%{transform:scale(1);opacity:.72}50%{transform:scale(1.028);opacity:1}}

.ipr__viz.is-live .ipr__ping--1{animation:ipr-ping 9s cubic-bezier(.22,.9,.3,1) infinite}
.ipr__viz.is-live .ipr__ping--2{animation:ipr-ping 9s cubic-bezier(.22,.9,.3,1) 4.5s infinite}
@keyframes ipr-ping{0%{transform:scale(.18);opacity:0}9%{opacity:.5}68%{opacity:0}100%{transform:scale(1.07);opacity:0}}

.ipr__viz.is-live .ipr__poly{animation:ipr-aura 12s ease-in-out infinite}
@keyframes ipr-aura{0%,100%{filter:drop-shadow(0 0 6px rgba(152,135,244,.24))}50%{filter:drop-shadow(0 0 20px rgba(152,135,244,.56))}}

.ipr__viz.is-live .ipr__poly circle{animation:ipr-node 8s ease-in-out infinite}
.ipr__viz.is-live .ipr__poly circle:nth-of-type(2){animation-delay:1.1s}
.ipr__viz.is-live .ipr__poly circle:nth-of-type(3){animation-delay:2.2s}
.ipr__viz.is-live .ipr__poly circle:nth-of-type(4){animation-delay:3.3s}
.ipr__viz.is-live .ipr__poly circle:nth-of-type(5){animation-delay:4.4s}
.ipr__viz.is-live .ipr__poly circle:nth-of-type(6){animation-delay:5.5s}
@keyframes ipr-node{0%,100%{transform:scale(1);opacity:.74}44%{transform:scale(1.36);opacity:1}}

.ipr__viz.is-live .ipr__glow--1{animation:ipr-drift-a 15s ease-in-out infinite}
.ipr__viz.is-live .ipr__glow--2{animation:ipr-drift-b 12s ease-in-out infinite}
@keyframes ipr-drift-a{0%,100%{transform:translate3d(0,0,0) scale(1)}50%{transform:translate3d(15px,-18px,0) scale(1.09)}}
@keyframes ipr-drift-b{0%,100%{transform:translate3d(0,0,0) scale(1)}50%{transform:translate3d(-17px,14px,0) scale(1.11)}}
.ipr__lbl{position:absolute;z-index:2;white-space:nowrap;font-size:11px;font-weight:var(--w-fw-semi);letter-spacing:.03em;color:rgba(255,255,255,.62)}
.ipr__lbl--n{top:-24px;left:50%;transform:translateX(-50%)}
.ipr__lbl--ne{top:24%;left:calc(100% + 12px)}
.ipr__lbl--se{bottom:24%;left:calc(100% + 12px)}
.ipr__lbl--s{bottom:-24px;left:50%;transform:translateX(-50%)}
.ipr__lbl--sw{bottom:24%;right:calc(100% + 12px)}
.ipr__lbl--nw{top:24%;right:calc(100% + 12px)}

/* MATERIAL — these float over the radar and its two blurred glows: a genuinely busy dark
   ground, so real glass reads. Blur is deliberately lighter (13px) than the assessment cards
   so the dial stays legible through them. */
.ipr__float{position:absolute;z-index:3;padding:13px 15px;border-radius:16px;background:linear-gradient(160deg,rgba(40,34,60,.62),rgba(20,17,29,.72));-webkit-backdrop-filter:blur(13px) saturate(150%);backdrop-filter:blur(13px) saturate(150%);border:1px solid rgba(255,255,255,.13);box-shadow:inset 0 1px 0 rgba(255,255,255,.24),0 18px 38px -16px rgba(0,0,0,.66);min-width:132px;will-change:transform}
/* levitation — four different periods and phases so they never bob in unison */
.ipr__viz.is-live .ipr__float{animation:ipr-lev 10s ease-in-out infinite}
.ipr__viz.is-live .ipr__float--2{animation-duration:13s;animation-delay:.9s}
.ipr__viz.is-live .ipr__float--3{animation-duration:11.5s;animation-delay:2.1s}
.ipr__viz.is-live .ipr__float--4{animation-duration:12.4s;animation-delay:3.4s}
@keyframes ipr-lev{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(0,-7px,0)}}
/* Floats live in the viz CORNERS and the radar's diagonal labels sit at 24%/76% of the viz
   height — the two share horizontal space, so they are separated VERTICALLY. Moving a float
   toward the vertical middle will put it straight on top of a label. */
.ipr__float--1{top:0;left:0}
.ipr__float--2{top:0;right:0}
.ipr__float--3{bottom:0;left:0}
.ipr__float--4{bottom:0;right:0}
.ipr__float-i{width:26px;height:26px;display:grid;place-items:center;border-radius:8px;background:rgba(255,255,255,.06)}
.ipr__float-i .w-icon{width:14px;height:14px}
.ipr__float-i.warning .w-icon{color:#fbbf24}
.ipr__float-i.danger .w-icon{color:#f87171}
.ipr__float-i.violet .w-icon{color:#c9bcff}
.ipr__float-i.success .w-icon{color:#4ade80}
.ipr__float-v{margin-top:8px;font-size:20px;line-height:1;font-weight:var(--w-fw-black)}
.ipr__float-v.warning{color:#fbbf24}
.ipr__float-v.danger{color:#f87171}
.ipr__float-v.violet{color:#c9bcff}
.ipr__float-v.success{color:#4ade80}
.ipr__float-l{margin-top:5px;font-size:10.5px;letter-spacing:.03em;color:rgba(255,255,255,.55)}

/* ---------- insights (light band) ---------- */
.ipi{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,1.8vw,24px)}
/* MATERIAL — #insights is a .cz-light band: a flat near-white field. backdrop-filter here
   would blur nothing and cost a paint, so this is NOT glass. It is layered elevation:
   tinted gradient field, bright top rim, brand hairline, brand-TINTED shadow, and a blurred
   aura cast below the card so the elevation has something to read against.
   The aura sits entirely BELOW the card box on purpose: a z-index:-1 child inside an
   isolated stacking context paints ABOVE its parent's own background, so any overlap would
   show as a purple smear across the card rather than a shadow behind it. */
.ipi__card{
  position:relative;isolation:isolate;
  padding:clamp(24px,2.2vw,32px);border-radius:22px;border:0;
  background:linear-gradient(158deg,#fff 0%,#f8f6ff 54%,#efeaff 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 0 0 1px rgba(111,95,224,.20),
    0 18px 40px -18px rgba(111,95,224,.45),
    0 2px 6px rgba(28,26,36,.05);
  transition:transform var(--w-dur) var(--w-ease),box-shadow var(--w-dur) var(--w-ease)
}
.ipi__card::after{content:"";position:absolute;z-index:-1;left:7%;right:7%;bottom:-22px;height:40px;border-radius:50%;background:radial-gradient(ellipse at center,rgba(111,95,224,.34),transparent 72%);filter:blur(16px);opacity:.9;transition:opacity var(--w-dur) var(--w-ease),transform var(--w-dur) var(--w-ease)}
.ipi__card:hover{transform:translateY(-3px);box-shadow:inset 0 1px 0 rgba(255,255,255,.95),inset 0 0 0 1px rgba(111,95,224,.28),0 26px 52px -20px rgba(111,95,224,.55),0 2px 6px rgba(28,26,36,.05)}
.ipi__card:hover::after{opacity:1;transform:translate3d(0,3px,0) scale(1.04)}
.ipi__icon{width:44px;height:44px;display:grid;place-items:center;border-radius:14px}
.ipi__icon .w-icon{width:20px;height:20px}
.ipi__icon.warning{background:rgba(245,158,11,.12)}.ipi__icon.warning .w-icon{color:#b45309}
.ipi__icon.danger{background:rgba(239,68,68,.1)}.ipi__icon.danger .w-icon{color:#dc2626}
.ipi__icon.violet{background:rgba(152,135,244,.12)}.ipi__icon.violet .w-icon{color:var(--w-brand)}
.ipi__stat{margin-top:18px;font-size:clamp(30px,3.4vw,42px);line-height:1;font-weight:var(--w-fw-black);letter-spacing:var(--w-ls-tight);font-variant-numeric:tabular-nums lining-nums}
.ipi__stat.warning{color:#b45309}
.ipi__stat.danger{color:#dc2626}
.ipi__stat.violet{color:var(--w-brand)}
.ipi__x{font-size:.78em;font-weight:var(--w-fw-black)}
.ipi__title{margin-top:10px;font-size:var(--w-fs-h4);font-weight:var(--w-fw-bold);color:var(--w-text)}
.ipi__desc{margin-top:10px;font-size:var(--w-fs-sm);line-height:1.6;color:var(--w-text-2)}
.ipi__src{margin-top:16px;padding-top:14px;border-top:1px solid var(--w-line);font-size:var(--w-fs-xs);color:var(--w-text-3)}

/* ---------- close ---------- */
.ip-close{position:relative;overflow:hidden;background:var(--w-bg)}
.ip-close__bg{position:absolute;inset:0;z-index:0;background:radial-gradient(ellipse 70% 80% at 50% 120%,rgba(152,135,244,.16),transparent 66%)}
.ip-close .w-container{position:relative;z-index:1}
.ip-close__h{font-size:var(--w-fs-h2);line-height:var(--w-lh-snug);letter-spacing:var(--w-ls-tight);font-weight:var(--w-fw-black);color:#fff}
.ip-close__h .w-accent{font-family:var(--w-font-serif);font-style:italic;font-weight:400;color:#c9bcff;-webkit-text-fill-color:#c9bcff;background:none}
.ip-close__p{margin-top:16px;font-size:var(--w-fs-lead);line-height:1.6;color:rgba(255,255,255,.82)}
.ip-close__actions{margin-top:26px;display:flex;gap:14px;flex-wrap:wrap;justify-content:center}

/* ---------- score modal ---------- */
.ip-modal{position:fixed;inset:0;z-index:200;display:none;align-items:center;justify-content:center;padding:clamp(16px,3vw,40px);background:rgba(10,8,16,.78);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
.ip-modal.is-active{display:flex}
/* MATERIAL — the panel floats on an already-blurred dark scrim, so real glass reads here too.
   Literal colours only: a position:fixed overlay sits outside every .cz-light wrapper and would
   otherwise inherit whichever token set the ROOT happens to carry. */
.ip-modal__panel{position:relative;width:min(980px,100%);max-height:calc(100dvh - 2*clamp(16px,3vw,40px));overflow:auto;border-radius:26px;background:linear-gradient(160deg,rgba(44,37,66,.88),rgba(20,17,29,.93));-webkit-backdrop-filter:blur(22px) saturate(150%);backdrop-filter:blur(22px) saturate(150%);border:1px solid rgba(201,188,255,.22);box-shadow:inset 0 1px 0 rgba(255,255,255,.24),0 40px 90px -24px rgba(0,0,0,.68)}
.ip-modal__close{position:absolute;top:16px;right:16px;z-index:2;appearance:none;cursor:pointer;width:36px;height:36px;display:grid;place-items:center;border-radius:50%;border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.06);color:rgba(255,255,255,.8)}
.ip-modal__close:hover{background:rgba(255,255,255,.12);color:#fff}
.ip-modal__close .w-icon{width:16px;height:16px}

.ip-modal__loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;min-height:340px;padding:40px}
.ip-modal__loading.is-hidden{display:none}
.ip-loader{width:44px;height:44px;border-radius:50%;border:3px solid rgba(255,255,255,.14);border-top-color:#c9bcff;animation:ip-spin 1s linear infinite}
@keyframes ip-spin{to{transform:rotate(360deg)}}
.ip-loader__t{font-size:var(--w-fs-h4);font-weight:var(--w-fw-bold);color:#fff}
.ip-loader__s{font-size:var(--w-fs-sm);color:rgba(255,255,255,.6)}

.ip-modal__content{display:none;grid-template-columns:1fr 1fr}
.ip-modal__content.is-visible{display:grid}
.ip-modal__left{padding:clamp(26px,2.6vw,40px);border-right:1px solid rgba(255,255,255,.1)}
.ip-modal__right{padding:clamp(26px,2.6vw,40px);background:rgba(255,255,255,.03)}
.ip-modal__eyebrow{font-size:var(--w-fs-h4);font-weight:var(--w-fw-bold);color:#fff}
.ip-modal__badge{margin-top:7px;display:inline-block;font-size:var(--w-fs-xs);font-weight:var(--w-fw-semi);letter-spacing:.04em;text-transform:uppercase;color:#c9bcff;background:rgba(152,135,244,.14);border:1px solid rgba(201,188,255,.22);padding:4px 10px;border-radius:100px}

.ip-mscore{margin-top:clamp(20px,2vw,28px);display:flex;flex-direction:column;align-items:center;gap:10px}
.ip-mscore__ring{position:relative;width:120px;height:120px}
.ip-mscore__ring svg{transform:rotate(-90deg)}
.ip-mscore__ring circle{fill:none;stroke-width:10}
.ip-mscore__track{stroke:rgba(255,255,255,.1)}
.ip-mscore__prog{stroke:#4b4560;stroke-linecap:round;transition:stroke-dashoffset .1s linear,stroke .4s ease}
.ip-mscore__num{position:absolute;inset:0;display:grid;place-items:center;font-size:36px;font-weight:var(--w-fw-black);color:#fff}
.ip-mscore__rating{font-size:var(--w-fs-sm);font-weight:var(--w-fw-bold);color:rgba(255,255,255,.7)}
.ip-mscore__rating.critical{color:#f87171}.ip-mscore__rating.warning{color:#fbbf24}
.ip-mscore__rating.good{color:#4ade80}.ip-mscore__rating.excellent{color:#34d399}

.ip-zones{position:relative;margin-top:clamp(22px,2.2vw,30px);display:grid;grid-template-columns:27fr 46fr 27fr;border-radius:14px;overflow:hidden;border:1px solid rgba(255,255,255,.12)}
.ip-zone{padding:30px 8px 12px;text-align:center;font-size:var(--w-fs-xs);font-weight:var(--w-fw-semi);color:rgba(255,255,255,.72);line-height:1.4}
.ip-zone span{display:block;margin-top:3px;font-weight:var(--w-fw-black);color:#fff}
.ip-zone--blind{background:rgba(239,68,68,.16)}
.ip-zone--aware{background:rgba(245,158,11,.14)}
.ip-zone--leaders{background:rgba(34,197,94,.16)}
/* rides in the zone bar's own top gutter (.ip-zone padding-top). It must stay INSIDE
   .ip-zones — that box is overflow:hidden to clip the zone fills to the radius, so a
   marker positioned above the box is invisible. */
.ip-zones__you{position:absolute;top:6px;left:50%;transform:translateX(-50%);transition:left 1s cubic-bezier(.2,.7,.3,1)}
.ip-zones__you span{display:block;font-size:9.5px;font-weight:var(--w-fw-black);letter-spacing:.06em;color:#fff;background:var(--w-grad-brand);padding:3px 8px;border-radius:100px;box-shadow:0 3px 10px rgba(0,0,0,.4)}
.ip-modal__impact{margin-top:clamp(20px,2vw,26px);padding:15px 17px;border-radius:14px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);font-size:var(--w-fs-sm);line-height:1.6;color:rgba(255,255,255,.84)}

.ip-modal__lead-icon{width:44px;height:44px;display:grid;place-items:center;border-radius:14px;background:rgba(152,135,244,.14);border:1px solid rgba(201,188,255,.24)}
.ip-modal__lead-icon .w-icon{width:20px;height:20px;color:#c9bcff}
.ip-modal__lead-h{margin-top:16px;font-size:var(--w-fs-h4);font-weight:var(--w-fw-bold);color:#fff}
.ip-modal__benefits{margin-top:16px;display:flex;flex-direction:column;gap:11px}
.ip-modal__benefit{display:flex;gap:10px;align-items:flex-start;font-size:var(--w-fs-sm);line-height:1.5;color:rgba(255,255,255,.78)}

.ip-form{margin-top:clamp(18px,1.8vw,24px);display:flex;flex-direction:column;gap:10px}
.ip-form.is-hidden{display:none}
.ip-form__row{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.ip-input{width:100%;padding:13px 15px;border-radius:14px;border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.06);color:#fff;font:var(--w-fs-body)/1.2 var(--w-font)}
.ip-input::placeholder{color:rgba(255,255,255,.42)}
.ip-input:focus{outline:none;border-color:var(--w-brand);box-shadow:0 0 0 3px rgba(152,135,244,.16)}
.ip-form__submit{margin-top:4px;width:100%;justify-content:center}
.ip-form__success{display:none;margin-top:clamp(18px,1.8vw,24px);flex-direction:column;align-items:center;gap:10px;padding:24px;border-radius:16px;background:rgba(34,197,94,.1);border:1px solid rgba(34,197,94,.26)}
.ip-form__success.is-active{display:flex}
.ip-form__success-i{width:40px;height:40px;display:grid;place-items:center;border-radius:50%;background:rgba(34,197,94,.2)}
.ip-form__success-i .w-icon{width:19px;height:19px;color:#4ade80}
.ip-form__success-t{font-size:var(--w-fs-body);font-weight:var(--w-fw-bold);color:#fff}
.ip-modal__privacy{margin-top:14px;font-size:var(--w-fs-xs);line-height:1.5;color:rgba(255,255,255,.48)}
.ip-modal__privacy a{color:#c9bcff}

/* ---------- responsive ---------- */
/* The radar's side labels sit OUTSIDE the 270px dial, so the viz box needs ~450px of width.
   Below that the dial is scaled down (transform-origin centre) and the label offsets tighten,
   which keeps every label inside the box instead of being clipped by .ip-research's overflow. */
@media(max-width:1180px){
  .ipr__radar{transform:scale(.84)}
  .ipr__lbl--ne,.ipr__lbl--se{left:calc(100% + 6px)}
  .ipr__lbl--nw,.ipr__lbl--sw{right:calc(100% + 6px)}
}
@media(max-width:900px){
  .ip-panel{grid-template-columns:1fr}
  .ipr{grid-template-columns:1fr}
  .ipr__sub{max-width:none}
  .ipr__viz{min-height:340px;margin-top:14px}
  .ipi{grid-template-columns:1fr}
  .ip-modal__content.is-visible{grid-template-columns:1fr}
  .ip-modal__left{border-right:none;border-bottom:1px solid rgba(255,255,255,.1)}
}
@media(max-width:560px){
  .option-grid{grid-template-columns:1fr}
  .ipr__stats{grid-template-columns:1fr 1fr;gap:20px}
  /* the viz box is too small here to hold the dial, its 6 labels AND 4 corner floats without
     collisions — so the floats stop being absolute and flow as a 2x2 grid under the radar */
  .ipr__viz{aspect-ratio:auto;min-height:0;display:grid;grid-template-columns:1fr 1fr;gap:10px}
  .ipr__radar{grid-column:1 / -1;margin:34px auto 30px;transform:scale(.72)}
  .ipr__lbl{font-size:10px}
  .ipr__lbl--ne,.ipr__lbl--se{left:calc(100% + 2px)}
  .ipr__lbl--nw,.ipr__lbl--sw{right:calc(100% + 2px)}
  .ipr__float{position:static;min-width:0;padding:10px 12px}
  .ipr__glow--1{top:0;left:0}.ipr__glow--2{bottom:22%;right:0}
  .ip-form__row{grid-template-columns:1fr}
  .ip-score__ring{width:150px;height:150px}
  .ip-score__num{font-size:42px}
}
/* .ipr__radar's transform scales its absolutely-positioned labels too, so the dial's visual
   width is (270 + 2 x label width) x scale. Below 400px even .72 lets the longest label
   ("Channel Coverage") escape the column, so scale down once more. */
@media(max-width:400px){
  .ipr__radar{transform:scale(.58)}
}
@media(prefers-reduced-motion:reduce){
  .quiz-step,.ip-dim__bar,.ip-zones__you,.calculate-btn{transition:none}
  .ip-loader{animation:none}
  .option-grid.is-shake{animation:none}

  /* Fail into the FINAL state, never a half-built one. The instrument still swaps panes and
     still previews values on hover/focus — that's feedback, not decoration — it just arrives
     instantly instead of travelling. Every ambient loop is off. */
  .ip-invite,.ip-inst,.ip-inst .ip-score__num,.ip-inst .ip-dim__val,
  .ip-dim::before,.ip-dim__icon,.ip-score__prog,.option-btn,
  .ipi__card,.ipi__card::after,.ip-inst__lock{transition:none}
  .ip-inst{opacity:1;transform:none;filter:none}
  .ip-invite__dot,.ip-inst__scan,.ip-dim__glint,.ip-score__ring,
  .ipr__rings span,.ipr__ping,.ipr__poly,.ipr__poly circle,.ipr__glow,.ipr__float,
  .ipr__viz.is-live .ipr__rings span,.ipr__viz.is-live .ipr__ping,
  .ipr__viz.is-live .ipr__poly,.ipr__viz.is-live .ipr__poly circle,
  .ipr__viz.is-live .ipr__glow--1,.ipr__viz.is-live .ipr__glow--2,
  .ipr__viz.is-live .ipr__float,.ip-inst.is-on:not(.is-revealed) .ip-inst__scan,
  .ip-inst.is-on:not(.is-revealed) .ip-dim__glint,
  .ip-inst.is-on:not(.is-revealed) .ip-score__ring{animation:none}
  .ip-inst__scan{opacity:0}
  .ipr__rings span{opacity:1;transform:none}
  .ipr__poly circle{opacity:1;transform:none}
  .option-btn:hover,.option-btn:focus-visible{transform:none}
  .ipi__card:hover{transform:none}
}
