@font-face{font-family:'Geist';font-style:normal;font-weight:300 800;font-display:swap;src:url(/assets/fonts/geist-latin-v1.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@media not (prefers-reduced-motion: reduce){@view-transition{navigation:auto;}}

  .jny{
    --ease:cubic-bezier(.22,.61,.36,1);
    --easeFluid:cubic-bezier(.16,.84,.3,1);
    --easePress:cubic-bezier(.34,1.2,.64,1);
    --led1:#22E0A0; --led2:#10C6E8; --led3:#1296F2;
    --glow:rgba(18,182,236,.7); --glowSoft:rgba(60,214,246,.55);
    --blue:#12B6EC;
    --gink:#F2F6FA; --gink2:#9AA6B3; --ghair:rgba(255,255,255,.10);
    --ink:#0E1318; --ink2:#51606e;
    font-synthesis:none;
  }
  .jny,.jny *{box-sizing:border-box;}
  .jny button,.jny input,.jny select,.jny textarea,.jny optgroup{font-family:inherit;letter-spacing:inherit;}
  /* Full-bleed in installed standalone (Home Screen app): min-height:100dvh guarantees the room
     reaches the physical bottom edge on iOS 26 standalone (percentage chains can fall short). */
  .jny,.jny{margin:0;height:100%;min-height:100dvh;}
  .jny{
    min-height:100%;color:var(--ink);
    font-family:"Geist",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;letter-spacing:.006em;
    -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;
    letter-spacing:.014em;
    background:
      radial-gradient(70% 46% at 50% 0%, rgba(18,60,90,.34), transparent 62%),
      radial-gradient(60% 34% at 50% 104%, rgba(16,198,232,.10), transparent 66%),
      linear-gradient(180deg,#080c11 0%, #06080b 58%, #05070a 100%);
    overflow-x:hidden;
  }
  /* the B architectural light shafts (rung 4: one room across the whole app) */
  .jny .vshafts{position:fixed;inset:0;overflow:hidden;pointer-events:none;z-index:0;}
  .jny .vshaft{position:absolute;top:-8%;width:2px;height:52%;border-radius:99px;
    background:linear-gradient(180deg,rgba(150,220,250,.30),transparent);opacity:.6;}
  .jny .vshaft.a{left:18%;transform:rotate(9deg);}
  .jny .vshaft.b{right:16%;transform:rotate(-7deg);}
  .jny .tnum{font-variant-numeric:tabular-nums lining-nums slashed-zero;font-feature-settings:"tnum" 1,"lnum" 1,"zero" 1;letter-spacing:0;}

  /* ===== shell ===== */
  .jny .wrap{position:relative;z-index:1;max-width:520px;margin:0 auto;
    height:100vh;height:100dvh;display:flex;flex-direction:column;
    padding:0 18px calc(env(safe-area-inset-bottom) + 14px);}
  .jny .topbar{position:absolute;top:0;left:0;right:0;z-index:50;display:flex;align-items:center;justify-content:space-between;
    padding:max(14px,env(safe-area-inset-top)) 22px 14px;}
  .jny .tbleft{display:flex;align-items:center;gap:11px;}
  .jny .flowback{appearance:none;width:34px;height:34px;flex:0 0 auto;border-radius:50%;cursor:pointer;
    border:1px solid rgba(255,255,255,.15);background:rgba(255,255,255,.10);color:#FFFFFF;
    line-height:1;display:flex;align-items:center;justify-content:center;padding:0;
    backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
    transition:transform .14s cubic-bezier(.34,1.4,.64,1);}
  .jny .flowback:active{transform:scale(.92);}
  .jny .wordmark{font-size:26px;font-weight:700;letter-spacing:.005em;line-height:1;color:#FFFFFF;text-shadow:0 0 20px rgba(255,255,255,.18);}
  .jny .wordmark .dot{color:var(--blue);text-shadow:0 0 18px var(--glow);margin-left:-.02em;}
  .jny .tag{font-size:10px;font-weight:500;letter-spacing:.26em;text-transform:uppercase;color:rgba(255,255,255,.42);}
  /* Quick Draw (mode=offrecord): scratch quick-math over the SAME two instruments (vial +
     syringe). No step counters, no forward nudges, no swipe arrows. Saves nothing unless the
     user taps the one Save button. Additive only: the normal flow never carries .offrec. */
  .jny.offrec .step1 .eyebrow,.jny.offrec .step2 .eyebrow{display:none;}
  .jny.offrec #s2next,.jny.offrec .step2 .hint{display:none;}
  .jny.offrec .s4nova{display:none;}
  /* The quiet promise under the Quick Draw title. Static markup, shown only in offrec. */
  .jny .qdsub{display:none;margin:6px 0 0;font-size:12.5px;font-weight:500;letter-spacing:.02em;color:#7E8FA0;}
  .jny.offrec .step1 .qdsub{display:block;}
  /* Save to my vault is deferred. Off the Record is quick dose math only for now, no vault write. */
  .jny .offrecsave,.jny .offrecdone{display:none;}
  .jny .offrecsave{position:absolute;left:18px;right:18px;bottom:max(16px,env(safe-area-inset-bottom));z-index:60;
    align-items:center;justify-content:center;gap:8px;appearance:none;-webkit-appearance:none;cursor:pointer;
    border:0;border-radius:14px;padding:14px 18px;font-family:inherit;font-size:15px;font-weight:700;letter-spacing:.01em;
    color:#06222e;background:linear-gradient(135deg,#22E0A0,#10C6E8 55%,#1296F2);
    box-shadow:0 12px 30px -12px var(--glow);transition:opacity .25s var(--ease),transform .12s var(--easePress);}
  .jny .offrecsave:active{transform:scale(.97);}
  .jny .offrecsave[disabled]{opacity:.4;pointer-events:none;}
  .jny .offrecsave svg{width:18px;height:18px;}
  .jny .offrecdone{position:absolute;left:18px;right:18px;bottom:max(16px,env(safe-area-inset-bottom));z-index:61;display:none;
    flex-direction:column;align-items:center;gap:10px;text-align:center;
    background:rgba(255,255,255,.05);border:1px solid rgba(18,182,236,.34);border-radius:16px;padding:16px 18px;
    backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);}
  .jny.offrec.offrec-saved .offrecdone{display:flex;}
  .jny.offrec.offrec-saved .offrecsave{display:none;}
  .jny .offrecdone .odmsg{color:#EAF7FE;font-size:14px;font-weight:600;letter-spacing:.01em;}
  .jny .offrecdone .odgo{appearance:none;-webkit-appearance:none;cursor:pointer;border:0;border-radius:12px;padding:11px 16px;
    font-family:inherit;font-size:14px;font-weight:700;color:#06222e;background:linear-gradient(135deg,#22E0A0,#1296F2);}
  .jny .offrecdone .odgo:active{transform:scale(.96);}

  /* dots */
  .jny .dots{display:flex;justify-content:center;gap:9px;margin:max(64px,calc(env(safe-area-inset-top) + 50px)) 0 10px;}
  .jny .dots button{appearance:none;cursor:pointer;padding:0;
    width:8px;height:8px;border-radius:50%;background:transparent;border:1.5px solid rgba(255,255,255,.28);
    transition:width .3s var(--ease),background .3s var(--ease),border-color .3s var(--ease);}
  .jny .dots button.on{width:26px;border-radius:6px;border:0;background:linear-gradient(90deg,var(--led1),var(--led2) 55%,var(--led3));box-shadow:0 2px 10px -3px var(--glow);}

  /* ===== the swipe track ===== */
  .jny .stage{position:relative;flex:1;min-height:0;overflow:hidden;}
  .jny .track{display:flex;align-items:stretch;height:100%;will-change:transform;
    transition:transform .42s var(--easeFluid);touch-action:pan-y;}
  .jny .track.drag{transition:none;}
  .jny .slide{flex:0 0 100%;min-width:100%;padding:2px;display:flex;align-items:stretch;}

  /* ===== the charcoal card (copied .panel treatment) ===== */
  .jny .card{position:relative;flex:1 1 auto;display:flex;flex-direction:column;
    overflow:hidden;color:var(--gink);}
  .jny .card::before,.jny .card::after{display:none;}
  .jny .cardin{position:relative;z-index:1;flex:1;min-height:0;display:flex;flex-direction:column;
    padding:18px 20px 16px;overflow-y:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;}
  .jny .cardin::-webkit-scrollbar{display:none;}

  /* hero banner */
  .jny .hero{flex:none;text-align:center;}
  .jny .eyebrow{font-size:10px;font-weight:700;letter-spacing:.26em;text-transform:uppercase;color:var(--gink2);}
  .jny .htitle{margin:7px 0 0;font-size:34px;font-weight:700;letter-spacing:.01em;line-height:1.02;color:var(--gink);}

  /* picker pill: a transparent native <select> overlays the visual pill so a tap
     opens iOS Safari's own native wheel reliably (no fragile showPicker hack). */
  .jny .pickwrap{position:relative;width:100%;margin:16px 0 2px;}
  .jny .pickselect{position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0;border:0;
    opacity:0;cursor:pointer;font-size:16px;font-family:inherit;-webkit-appearance:none;appearance:none;z-index:2;}
  .jny .pick{position:relative;z-index:1;pointer-events:none;
    display:flex;align-items:center;justify-content:space-between;gap:10px;
    background:rgba(255,255,255,.05);border:1px solid var(--ghair);border-radius:14px;padding:13px 16px;color:var(--gink);
    transition:background .2s var(--ease),border-color .2s var(--ease);}
  .jny .pickselect:focus + .pick,.jny .pickwrap:active .pick{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.18);}
  .jny .pick .pl{display:flex;flex-direction:column;gap:2px;text-align:left;min-width:0;}
  .jny .pick .pk{font-size:9.5px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:#C3CED9;}
  .jny .pick .pn{font-size:16px;font-weight:600;letter-spacing:.006em;color:var(--gink);}
  .jny .pick .chev{color:var(--gink2);font-size:15px;flex:none;opacity:.7;}

  /* vial (from prototype) */
  .jny .vialwrap{flex:1;min-height:200px;display:flex;flex-direction:column;align-items:center;justify-content:center;}
  .jny .vialbox{position:relative;flex:1;min-height:0;aspect-ratio:1536/2752;display:flex;margin:0 auto;isolation:isolate;}
  .jny .vialbox::before{
    content:"";position:absolute;z-index:0;
    left:30%;width:44%;top:85.5%;height:5.5%;
    background:radial-gradient(closest-side, rgba(0,0,0,.5), rgba(0,0,0,.28) 55%, rgba(0,0,0,0) 100%);
    border-radius:50%;-webkit-filter:blur(14px);filter:blur(14px);pointer-events:none;}
  .jny .vialbox img,.jny .vialbox svg{position:absolute;inset:0;width:100%;height:100%;z-index:1;}
  .jny .vialbox img{object-fit:contain;}
  /* clear-water composite: NORMAL low-alpha so the real photo's dark glass shadows AND white
     speculars both govern the volume (screen erased the shadows and read as glowing antifreeze).
     The fluid is mostly transparent; realism comes from the photo showing through, not from color.
     Clip stays on the outer <g>; nested blend group + .vialbox isolation keep it from escaping. */
  .jny .vialbox .fluidblend{mix-blend-mode:normal;}
  .jny .puck{transform-box:fill-box;transform-origin:50% 100%;}
  .jny .wisp{transform-box:fill-box;transform-origin:center;opacity:0;}
  @media (prefers-reduced-motion: reduce){.jny .wisp{display:none;}}

  /* ===== STEP 1 stage: vial DEAD CENTER (hero), water LEFT, concentration RIGHT ===== */
  .jny .s1stage{flex:1 1 auto;min-height:0;display:flex;align-items:center;justify-content:center;gap:6px;}
  .jny .s1flank{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    border-radius:16px;padding:9px 4px;}
  .jny .s1flank .rdn{font-size:36px;font-weight:700;letter-spacing:-.025em;line-height:1;color:#F4F8FB;
    font-variant-numeric:tabular-nums lining-nums;text-shadow:0 1px 1px rgba(0,0,0,.35);transition:color .25s var(--ease);}
  .jny .s1flank .rdl{font-size:8.5px;font-weight:600;letter-spacing:.26em;color:var(--gink2);}
  /* the left water tile: transparent, text only */
  .jny .s1water{background:transparent;box-shadow:none;}
  /* the right tile is the REVEAL: a charging well that pulses, then IGNITES to the number */
  .jny .concskel{display:none;width:44px;height:30px;border-radius:9px;
    background:linear-gradient(90deg,rgba(18,182,236,.14),rgba(34,224,160,.2),rgba(18,182,236,.14));}
  .jny .card.step1:not(.s1-ready) .s1conc{background:transparent;}
  .jny .card.step1:not(.s1-ready) .s1conc #conc{display:block;}
  .jny .card.step1:not(.s1-ready) .s1conc .concskel{display:none;}
  .jny .card.step1:not(.s1-ready) .s1conc .rdl{color:#6b7785;}
  @keyframes tileCharge{0%,100%{box-shadow:0 0 0 0 rgba(18,182,236,0);}
    50%{box-shadow:0 0 18px 1px rgba(18,182,236,.18);}}
  .jny .card.step1.s1-ready .s1conc{background:transparent;}
  .jny .card.step1.s1-ready .s1conc .rdn{color:#EAF7FE;}
  @keyframes tileIgnite{0%{transform:scale(.94);}55%{transform:scale(1.05);}100%{transform:scale(1);}}
  @media (prefers-reduced-motion: reduce){.jny .card.step1:not(.s1-ready) .s1conc,.jny .card.step1.s1-ready .s1conc{animation:none;}}

  /* ===== on-vial water drag: drag DOWN the center of the vial to pour water in,
     exactly like pulling the syringe plunger in Step 2. The vial IS the control. ===== */
  .jny .vialwrap{touch-action:none;cursor:grab;}
  .jny .vialwrap:active{cursor:grabbing;}

  /* the magnetic TARGET NOTCH at the suggested water level: a clean tick + amount the handle snaps to */
  .jny .waternotch{position:absolute;left:19%;right:19%;z-index:3;pointer-events:none;display:flex;align-items:center;
    transform:translateY(-50%);opacity:0;transition:opacity .3s var(--ease),top .25s var(--ease);}
  .jny .card.step1.s1-water:not(.s1-ready) .waternotch{opacity:1;}
  .jny .waternotch .wntick{flex:1;height:0;border-top:2px dashed rgba(150,233,255,.8);}
  .jny .waternotch .wnlab{flex:none;margin-left:7px;font-size:11px;font-weight:800;letter-spacing:.02em;color:#06222e;white-space:nowrap;
    background:linear-gradient(180deg,#22E0A0,#10C6E8 60%,#1296F2);padding:3px 9px;border-radius:999px;
    box-shadow:0 3px 12px -3px var(--glow);animation:notchPulse 2s var(--ease) infinite;}
  @keyframes notchPulse{0%,100%{box-shadow:0 3px 12px -4px var(--glow);}50%{box-shadow:0 3px 20px 0 var(--glow);}}

  /* the glowing GRAB HANDLE riding the water surface: lift UP to fill (wordless, unmissable) */
  .jny .waterhandle{position:absolute;left:18.5%;right:18.5%;z-index:4;pointer-events:none;transform:translateY(-50%);
    opacity:0;transition:opacity .3s var(--ease);}
  .jny .card.step1.s1-water:not(.s1-ready) .waterhandle{opacity:1;}
  .jny .waterhandle .whbar{display:flex;align-items:center;justify-content:center;gap:9px;height:24px;border-radius:13px;
    background:linear-gradient(180deg,rgba(45,228,202,.95),rgba(16,198,232,.95) 55%,rgba(18,150,242,.95));
    border:1px solid rgba(255,255,255,.4);box-shadow:0 5px 18px -4px var(--glow),inset 0 1px 0 rgba(255,255,255,.55);
    animation:handleBreath 2s var(--ease) infinite;}
  .jny .waterhandle .whgrip{width:24px;height:3px;border-radius:2px;background:rgba(6,34,46,.5);
    box-shadow:0 -6px 0 -1px rgba(6,34,46,.34),0 6px 0 -1px rgba(6,34,46,.34);}
  .jny .waterhandle .whchev{font-size:14px;font-weight:800;color:#06222e;line-height:1;}
  @keyframes handleBreath{0%,100%{box-shadow:0 5px 18px -5px var(--glow),inset 0 1px 0 rgba(255,255,255,.55);}
    50%{box-shadow:0 5px 26px -1px var(--glow),inset 0 1px 0 rgba(255,255,255,.55);}}
  @media (prefers-reduced-motion: reduce){.jny .waternotch .wnlab,.jny .waterhandle .whbar{animation:none;}}

  /* while dragging, the right tile shows the LIVE concentration so any custom amount reads its mg/mL */
  .jny .card.step1.s1-dragging .s1conc{animation:none;}
  .jny .card.step1.s1-dragging .s1conc #conc{display:block;color:#EAF7FE;}
  .jny .card.step1.s1-dragging .s1conc .concskel{display:none;}
  .jny .card.step1.s1-dragging .s1conc .rdl{color:var(--gink2);}

  /* labelled blocks */
  .jny .blk{margin-top:18px;}
  .jny .blklk{font-size:10px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:#C3CED9;margin:0 2px 9px;}

  /* mg chips */
  .jny .chips{display:flex;flex-wrap:wrap;gap:6px;}
  .jny .chip{appearance:none;cursor:pointer;font-family:inherit;
    font-size:12.5px;font-weight:600;line-height:1;letter-spacing:.01em;
    padding:9px 13px;min-height:36px;border-radius:11px;
    border:1px solid var(--ghair);background:rgba(255,255,255,.05);color:var(--gink2);
    font-variant-numeric:tabular-nums lining-nums;
    transition:background .16s var(--ease),color .16s var(--ease),border-color .16s var(--ease),transform .12s var(--easePress);}
  .jny .chip:hover{background:rgba(255,255,255,.10);color:var(--gink);}
  .jny .chip:active{transform:scale(.94);}
  .jny .chip.sel{color:#EAF6FC;border-color:transparent;
    background:rgba(255,255,255,.14);
    box-shadow:0 0 0 1.5px rgba(16,198,232,.55),0 6px 22px -6px rgba(16,198,232,.45),inset 0 1px 0 rgba(255,255,255,.2);}
  .jny .chip .cu{font-weight:500;opacity:.8;margin-left:2px;}

  /* recommended water field */
  .jny .water{background:rgba(255,255,255,.04);border:1px solid var(--ghair);border-radius:16px;padding:14px 15px;}
  .jny .watersugg{font-size:13px;line-height:1.5;color:var(--gink2);}
  .jny .watersugg b{color:var(--gink);font-weight:700;}
  .jny .waterrow{display:flex;align-items:center;gap:12px;margin-top:13px;}
  .jny .stepper{display:flex;align-items:center;gap:2px;}
  .jny .stepper button{appearance:none;width:34px;height:34px;border-radius:10px;border:1px solid var(--ghair);background:rgba(255,255,255,.06);
    color:var(--gink);font-size:19px;font-weight:500;line-height:1;cursor:pointer;font-family:inherit;
    display:flex;align-items:center;justify-content:center;transition:background .15s var(--ease),transform .12s var(--easePress);}
  .jny .stepper button:hover{background:rgba(255,255,255,.12);}
  .jny .stepper button:active{transform:scale(.9);}
  .jny .stepper .wval{min-width:78px;text-align:center;font-size:17px;font-weight:700;color:#F4F8FB;
    font-variant-numeric:tabular-nums lining-nums;}
  .jny .stepper .wval small{font-size:12px;font-weight:500;color:var(--gink2);margin-left:2px;}

  /* swipe hint */
  .jny .hint{flex:none;text-align:center;margin-top:14px;margin-bottom:8px;font-size:11.5px;font-weight:500;color:#76828f;letter-spacing:.01em;display:flex;align-items:center;justify-content:center;gap:7px;}
  .jny .hint .arr{display:inline-flex;align-items:center;justify-content:center;}
  /* ONE directional glyph everywhere: same path, viewBox, linecap. Back points left, next points right. */
  .jny .navchev{width:18px;height:18px;display:block;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
  /* the bottom Next chevron is the call to action: bigger, bolder, and an elegant breathe */
  .jny .hint .arr .navchev{width:36px;height:36px;stroke-width:2.5;transform-origin:center;filter:drop-shadow(0 0 6px rgba(16,198,232,.65));}
  .jny .card.show-nudge .hint .arr .navchev{animation:breathe 2s ease-in-out infinite;}
  @keyframes breathe{0%,100%{transform:scale(1);opacity:.6;}50%{transform:scale(1.15);opacity:1;}}
  @media (prefers-reduced-motion: reduce){.jny .card.show-nudge .hint .arr .navchev{animation:none;opacity:1;}}

  /* ===== STEP 1 scoped refinements (vial is the hero, tighter density) =====
     The card is a strict no-scroll flex column sized to the small visible viewport.
     Every non-vial element is compact and flex:none. The vial alone flexes to
     absorb all spare height, so the turquoise button + hint always stay in view. */
  .jny .step1 .cardin{padding:7px 16px 10px;overflow:visible;}
  .jny .step1 .hero{flex:none;}
  .jny .step1 .htitle{margin-top:0;line-height:1;}
  .jny .step1 .pickwrap{margin:8px 0 0;flex:none;}
  .jny .step1 .pick{padding:11px 15px;}
  .jny .step1 .pick .pk{font-size:9px;}
  .jny .step1 .pick .pn{font-size:19px;font-weight:700;letter-spacing:0em;}
  /* mg-size chips sit ABOVE the vial (mg first, then water). One clean line. */
  .jny .step1 .sizeblk{margin-top:8px;flex:none;}
  .jny .step1 .blklk{margin-bottom:5px;font-size:9.5px;}
  .jny .step1 .chips{gap:6px;flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding-bottom:1px;}
  .jny .step1 .chips::-webkit-scrollbar{display:none;}
  .jny .step1 .chip{padding:8px 14px;min-height:34px;font-size:12.5px;flex:0 0 auto;}
  /* the vial stays the centered hero: height-driven, flanked, never shrunk by the numbers */
  .jny .step1 .s1stage{margin-top:2px;gap:4px;position:relative;}
  /* scale-up: flanks pushed to the screen edges so the vial can claim the full width */
  .jny .step1 .s1flank{position:absolute;top:50%;transform:translateY(-50%);flex:none;width:76px;overflow:visible;padding:0;z-index:4;pointer-events:none;}
  .jny .step1 .s1water{left:4px;}
  .jny .step1 .s1conc{right:4px;}
  .jny .step1 .s1water .rdl{white-space:nowrap;}   /* keep "mL Water" on one line, centered under the number */
  /* SLIDE TO ADD WATER cue: hidden until mg chip selected */
  .jny .s1dragcue{display:none;flex:none;text-align:center;font-size:13px;font-weight:800;letter-spacing:.14em;
    text-transform:uppercase;color:#F4F8FB;margin:6px 0 4px;}
  .jny .card.step1.s1-water .s1dragcue{display:block;animation:dragCuePulse 1.4s ease infinite;}
  @keyframes dragCuePulse{0%,100%{opacity:.5;}50%{opacity:1;text-shadow:0 0 20px rgba(18,182,236,.65);}}
  @media (prefers-reduced-motion:reduce){.jny .card.step1.s1-water .s1dragcue{animation:none;}}
  /* D6: the step-1 disclaimer slot no longer rotates instruction copy, so the three state spans
     and their show/hide rules are gone. One line, always on, same as every other step. */
  .jny .step1 .vialwrap{flex:none;height:100%;max-width:calc(100% - 10px);aspect-ratio:1536/2752;min-height:0;margin:0 auto;position:relative;display:flex;}
  .jny .step1 .vialbox{flex:1;min-height:0;height:100%;width:auto;max-width:100%;}
  /* progressive reveal: one decision at a time, each invited by a stronger pulse + glow */
  @keyframes segGlow{0%,100%{box-shadow:0 0 0 0 rgba(18,182,236,0);border-color:var(--ghair);}
    50%{box-shadow:0 0 0 5px rgba(18,182,236,.28),0 0 22px 3px rgba(18,182,236,.34);border-color:rgba(18,182,236,.75);}}
  .jny .card.step1.s1-pep .pick{animation:segGlow 1.8s var(--ease) infinite;}
  /* the ON state is the B lit-glass (white glass + LED ring), never a gradient slab */
  .jny .card.step1:not(.s1-pep) .pick{background:rgba(255,255,255,.14);border-color:transparent;color:#EAF6FC;
    box-shadow:0 0 0 1.5px rgba(16,198,232,.55),0 6px 22px -6px rgba(16,198,232,.45),inset 0 1px 0 rgba(255,255,255,.2);}
  .jny .card.step1:not(.s1-pep) .pick .pk{color:#8FA2B2;}
  .jny .card.step1:not(.s1-pep) .pick .pn{color:#F4F8FB;}
  .jny .card.step1:not(.s1-pep) .pick .chev{color:#8FA2B2;opacity:.85;}
  .jny .card.step1.s1-pep .sizeblk{visibility:hidden;}
  .jny .card.step1.s1-mg .chip:not(.sel){animation:segGlow 1.8s var(--ease) infinite;}
  .jny .card.step1.s1-pep .vialwrap,.jny .card.step1.s1-mg .vialwrap{opacity:.4;filter:saturate(.55);}
  .jny .card.step1.s1-pep .s1flank,.jny .card.step1.s1-mg .s1flank{visibility:hidden;}
  /* the suggest line + drag cue only exist in the water state (their own rules handle that) */
  .jny .card.step1.s1-pep .waterhandle,.jny .card.step1.s1-mg .waterhandle,.jny .card.step1.s1-pep .waternotch,.jny .card.step1.s1-mg .waternotch{display:none;}
  /* PREFILLED: the product is already a solution. Every affordance that says "pour water here"
     has to go, or the vial invites a gesture that would be wrong to perform. The glass just
     opens full. Specificity matches the .s1-water rules above so it wins wherever they apply. */
  .jny .card.step1.s1-prefilled .waterhandle,.jny .card.step1.s1-prefilled .waternotch,.jny .card.step1.s1-prefilled .s1dragcue{display:none;}
  .jny .card.step1.s1-prefilled .vialwrap{opacity:1;filter:none;}
  /* the larger-vial note: sentence case, quieter than the kicker, and only ever visible during
     the water step of a compound that can actually be diluted that far. */
  .jny .s1overcue{display:none;flex:none;text-align:center;font-size:12.5px;font-weight:600;
    letter-spacing:.005em;line-height:1.35;color:rgba(214,242,252,.62);margin-top:5px;}
  .jny .card.step1.s1-water:not(.s1-prefilled) .s1overcue:not([hidden]){display:block;}
  @media (prefers-reduced-motion: reduce){.jny .card.step1.s1-pep .pick,.jny .card.step1.s1-mg .chip:not(.sel){animation:none;}}
  /* the swipe-forward nudge stays hidden until the water is added, then it reveals */
  .jny .step1 .hint{margin-top:7px;flex:none;opacity:0;transform:translateY(5px);pointer-events:none;
    transition:opacity .45s var(--ease),transform .45s var(--ease);}
  .jny .card.step1.show-nudge .hint{opacity:1;transform:none;color:#FFFFFF;font-weight:700;font-size:15px;letter-spacing:.008em;white-space:nowrap;pointer-events:auto;cursor:pointer;}
  /* the Next chevron: white, breathing (see the shared .breathe rule above) */
  .jny .card.step1.show-nudge .hint .arr{opacity:1;color:#FFFFFF;}
  .jny .step1 .disc{margin-top:5px;flex:none;font-size:12px;font-weight:700;color:#F4F8FB;white-space:nowrap;}

  /* carried-over data card (steps 2-4) */
  .jny .carry{display:flex;align-items:center;gap:13px;margin:20px 0 0;padding:15px 16px;border-radius:16px;
    background:rgba(255,255,255,.04);border:1px solid var(--ghair);}
  .jny .carry .cv{width:34px;height:34px;border-radius:10px;flex:none;position:relative;
    background:rgba(255,255,255,.10);border:1px solid var(--ghair);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.4);}
  .jny .carry .cv::after{content:"";position:absolute;left:7px;right:7px;bottom:6px;height:42%;border-radius:4px;
    background:linear-gradient(180deg,#22E0A0,#10C6E8 55%,#1296F2);box-shadow:0 0 9px var(--glow);}
  .jny .carry .ct{min-width:0;}
  .jny .carry .ct b{font-size:16px;font-weight:600;letter-spacing:.006em;color:var(--gink);display:block;}
  .jny .carry .ct span{font-size:12.5px;color:var(--gink2);font-variant-numeric:tabular-nums;}

  .jny .note{margin-top:auto;padding-top:20px;}
  .jny .notebody{font-size:14px;line-height:1.55;color:var(--gink2);font-weight:400;letter-spacing:.017em;}
  .jny .notebody b{color:#c3ced9;font-weight:600;}
  .jny .soon{display:inline-flex;align-items:center;gap:6px;margin-top:14px;font-size:10px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--blue);}
  .jny .soon .sd{width:7px;height:7px;border-radius:50%;background:radial-gradient(circle at 38% 34%,#2BE6C6,#10C6E8 46%,#1296F2);box-shadow:0 0 12px 2px var(--glow);}

  .jny .disc{flex:none;text-align:center;margin:14px 4px 0;font-size:11px;line-height:1.5;color:#8893a2;font-weight:400;}

  /* ===================== STEP 2: Fill your syringe ===================== */
  .jny .step2 .cardin{padding:9px 16px 10px;overflow:hidden;}
  .jny .step2 .hero{flex:none;}
  .jny .step2 .htitle{margin-top:1px;line-height:1;}

  /* carried-over vial chip */
  .jny .s2carry{margin:7px 0 0;padding:8px 12px;gap:11px;flex:none;}
  .jny .s2carry .mvial{width:24px;height:40px;flex:none;}
  .jny .s2carry .ct{flex:1;min-width:0;}
  .jny .s2carry .ct b{font-size:15px;}
  .jny .s2carry .ct span{font-size:12px;}
  .jny .s2ready{flex:none;font-size:8.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:#06222e;
    background:linear-gradient(180deg,#22E0A0,#10C6E8 60%,#1296F2);padding:4px 9px;border-radius:999px;
    box-shadow:0 3px 10px -3px var(--glow);}

  /* syringe size: an experiential question + units-first buttons (smallest to largest) */
  .jny .s2sizes{flex:none;margin-top:7px;}
  .jny .syrq{font-size:15px;font-weight:700;letter-spacing:.01em;color:var(--gink);margin:0 2px 8px;}
  .jny .seg3{display:flex;gap:7px;}
  .jny .seg3 .segbtn{flex:1;appearance:none;cursor:pointer;font-family:inherit;display:flex;flex-direction:column;align-items:center;gap:1px;
    padding:9px 0 8px;border-radius:13px;border:1px solid var(--ghair);background:rgba(255,255,255,.04);color:var(--gink2);
    transition:background .16s var(--ease),color .16s var(--ease),border-color .16s var(--ease),transform .12s var(--easePress);}
  .jny .seg3 .segbtn b{font-size:19px;font-weight:700;line-height:1;letter-spacing:0em;font-variant-numeric:tabular-nums;}
  .jny .seg3 .segbtn span{font-size:9px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;opacity:.9;}
  .jny .seg3 .segbtn i{font-size:11px;font-style:normal;font-weight:500;margin-top:2px;opacity:.72;font-variant-numeric:tabular-nums;}
  .jny .seg3 .segbtn:active{transform:scale(.96);}
  .jny .seg3 .segbtn.sel{color:#EAF6FC;border-color:transparent;background:rgba(255,255,255,.14);
    box-shadow:0 0 0 1.5px rgba(16,198,232,.55),0 6px 22px -6px rgba(16,198,232,.45),inset 0 1px 0 rgba(255,255,255,.2);}
  .jny .seg3 .segbtn.sel span,.jny .seg3 .segbtn.sel i{opacity:.9;}

  /* the stage: the syringe DEAD CENTER, mg and units flanking on its centerline */
  .jny .s2stage{flex:1 1 auto;min-height:0;display:flex;align-items:center;justify-content:center;gap:4px;margin-top:5px;}
  .jny .syrwrap{flex:none;height:60dvh;max-height:100%;aspect-ratio:118/432;position:relative;touch-action:none;cursor:grab;display:flex;}
  .jny .syrwrap:active{cursor:grabbing;}
  /* a soft lightbox glow pools behind the instrument so it reads like a product shot */
  .jny .syrwrap::before{content:"";position:absolute;z-index:0;left:50%;top:48%;transform:translate(-50%,-50%);
    width:230%;height:78%;border-radius:50%;pointer-events:none;
    background:radial-gradient(closest-side, rgba(18,182,236,.16), rgba(34,224,160,.07) 46%, rgba(18,182,236,0) 78%);
    opacity:0;transition:opacity .5s var(--ease);}
  .jny .card.step2.st-drawn .syrwrap::before,.jny .card.step2.st-draw .syrwrap::before{opacity:1;}
  .jny .syringe{position:relative;z-index:1;width:100%;height:100%;display:block;overflow:visible;
    filter:drop-shadow(0 18px 26px rgba(4,10,18,.55));}
  /* the two flanking readouts: same size, locked to the syringe's vertical centerline */
  .jny .s2flank{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;}
  .jny .s2flank .rdn{font-size:36px;font-weight:700;letter-spacing:-.025em;line-height:1;color:#F4F8FB;font-variant-numeric:tabular-nums lining-nums;
    text-shadow:0 1px 1px rgba(0,0,0,.35);transition:color .2s var(--ease);}
  .jny .s2flank .rdl{font-size:8.5px;font-weight:600;letter-spacing:.26em;color:var(--gink2);}
  /* the drawn dose is the live truth: tint both numbers to the brand blue once liquid is in */
  .jny .card.step2.st-drawn .s2flank .rdn{color:#EAF7FE;}
  .jny .card.step2.st-pick .s2flank{visibility:hidden;}     /* no numbers until a syringe is chosen */

  /* the on-syringe pull-down cue (shown only while drawing) */
  /* the glowing plunger grab handle: hidden until a size is chosen, pulses to invite the pull, then steady */
  .jny #plungHandle{display:none;filter:drop-shadow(0 2px 7px rgba(18,182,236,.75));}
  .jny .card.step2.st-draw #plungHandle,.jny .card.step2.st-drawn #plungHandle{display:block;}
  .jny .card.step2.st-draw #plungHandle{animation:phBreath 1.5s var(--ease) infinite;}
  @keyframes phBreath{0%,100%{opacity:.72;}50%{opacity:1;}}
  @media (prefers-reduced-motion: reduce){.jny .card.step2.st-draw #plungHandle{animation:none;}}

  /* one centered caption that swaps by state, keeping the flanks symmetric */
  .jny .s2caption{flex:none;margin-top:9px;text-align:center;min-height:17px;}
  .jny .s2msg{display:none;font-size:13.5px;font-weight:600;letter-spacing:.016em;color:var(--gink2);}
  .jny .card.step2.st-pick .s2pickmsg{display:inline;}
  /* D3: the st-draw caption is deliberately empty. The barrel demonstrates the pull on arrival and
     the handle breathes on the plunger, so the sentence has nothing left to say. min-height on
     .s2caption holds the row, so the stage never jumps between states. */

  /* dim the syringe until a size is chosen; pulse the buttons to invite the choice */
  /* before a size is chosen: a cloudy, frosted, clearly-present empty glass (not near-invisible) */
  .jny #syrFrost{transition:opacity .35s var(--ease);}
  .jny #plungRod,.jny #plungRodHi,.jny #syrPlunger{transition:opacity .35s var(--ease);}
  .jny .card.step2.st-pick .syrwrap{opacity:.7;filter:saturate(.62) brightness(1.05);}
  .jny .card.step2.st-pick #syrFrost{opacity:.18;}
  .jny .card.step2.st-pick #plungRod,.jny .card.step2.st-pick #plungRodHi,.jny .card.step2.st-pick #syrPlunger{opacity:0;}
  .jny .card.step2.st-pick .seg3 .segbtn{animation:segBreathe 1.9s var(--ease) infinite;}
  @keyframes segBreathe{0%,100%{box-shadow:0 0 0 0 rgba(18,182,236,0);border-color:var(--ghair);}50%{box-shadow:0 0 0 4px rgba(18,182,236,.18);border-color:rgba(18,182,236,.55);}}
  @keyframes bounceDown{0%,100%{transform:translateY(0);opacity:.55;}50%{transform:translateY(8px);opacity:1;}}
  @media (prefers-reduced-motion: reduce){.jny .drawcue span,.jny .card.step2.st-pick .seg3 .segbtn{animation:none;}}
  .jny #syrFill,.jny #syrGloss,.jny #syrTop{transition:height .16s var(--ease);}
  .jny #syrPlunger,.jny #drawLine,.jny #plungRod,.jny #plungRodHi{transition:y .16s var(--ease),height .16s var(--ease);}
  /* COMMON beacon: a miniature star about to explode. A bright, alive pulse (iOS-safe
     transform/opacity). transform-box:fill-box + center origin so WebKit scales it in place
     (the radar-ping lesson). */
  .jny .cmnBeacon{animation:cmnNova 1.9s ease-in-out infinite; transform-box:fill-box; transform-origin:center; will-change:transform,opacity;}
  @keyframes cmnNova{0%,100%{transform:scale(.9);opacity:.82;}50%{transform:scale(1.22);opacity:1;}}
  /* COMMON label lifted by LIGHT, not a cheap outline: a soft luminous glow behind the text. */
  .jny .cmnLabGlow{filter:blur(2.2px);opacity:.9;}
  /* when the draw lands on COMMON, the mg + units readouts (number AND label) lock into the
     same subtle pulse, super gentle, so the user feels they are aligned with the mark. */
  /* when on the common mark, the mg + units numbers and labels STAY WHITE and a cyan glow
     pulsates on their OUTER EDGE (no cyan inside the white, no flashing). */
  .jny .card.step2 .s2flank.at-common .rdn,.jny .card.step2 .s2flank.at-common .rdl{animation:cmnSync 1.5s ease-in-out infinite;color:#F4F8FB;}
  @keyframes cmnSync{0%,100%{text-shadow:0 0 6px rgba(16,198,232,.4);}50%{text-shadow:0 0 20px rgba(16,198,232,1),0 0 34px rgba(16,198,232,.7);}}
  @media (prefers-reduced-motion:reduce){.jny .cmnBeacon{animation:none;transform:scale(1);opacity:1;}.jny .s2flank.at-common .rdn,.jny .s2flank.at-common .rdl{animation:none;}}

  /* the swipe-forward nudge: hidden until they draw, then revealed white with the ping */
  .jny .step2 .hint{margin-top:3px;margin-bottom:3px;flex:none;opacity:0;transform:translateY(5px);pointer-events:none;
    transition:opacity .45s var(--ease),transform .45s var(--ease);}
  .jny .card.step2.show-nudge .hint{opacity:1;transform:none;color:#FFFFFF;font-weight:700;font-size:14px;letter-spacing:.006em;white-space:nowrap;pointer-events:auto;cursor:pointer;}
  .jny .card.step2.show-nudge .hint .arr{opacity:1;color:#FFFFFF;}
  .jny .step2 .disc{margin-top:6px;flex:none;font-size:10px;}

  /* ===================== STEP 3: Choose your site (body map) ===================== */
  .jny .step3 .cardin{padding:9px 16px 10px;overflow:hidden;}
  .jny .step3 .hero{flex:none;}
  .jny .step3 .htitle{margin-top:1px;line-height:1;}

  /* carried-over vial chip, matched to Step 2's s2carry */
  .jny .s3carry{margin:9px 0 0;padding:9px 12px;gap:11px;flex:none;}
  .jny .s3carry .mvial{width:24px;height:40px;flex:none;}
  .jny .s3carry .ct{flex:1;min-width:0;}
  .jny .s3carry .ct b{font-size:15px;}
  .jny .s3carry .ct span{font-size:12px;}
  .jny .step3 .s3carry{display:none;}
  .jny .step3 .s3changerow{margin-top:6px;}

  /* the two toggles: Male/Female stacked over Front/Back, both seg3-styled */
  /* Front/Back segment (now in the change-body row) */
  .jny .step3 .seg3{gap:7px;}
  .jny .step3 .seg3 .segbtn{flex:1;appearance:none;cursor:pointer;font-family:inherit;
    padding:8px 0;border-radius:12px;border:1px solid var(--ghair);background:rgba(255,255,255,.04);color:var(--gink2);
    font-size:12.5px;font-weight:600;letter-spacing:.01em;
    transition:background .16s var(--ease),color .16s var(--ease),border-color .16s var(--ease),transform .12s var(--easePress);}
  .jny .step3 .seg3 .segbtn:active{transform:scale(.96);}
  .jny .step3 .seg3 .segbtn.sel{color:#EAF6FC;border-color:transparent;background:rgba(255,255,255,.14);
    box-shadow:0 0 0 1.5px rgba(16,198,232,.55),0 6px 22px -6px rgba(16,198,232,.45),inset 0 1px 0 rgba(255,255,255,.2);}

  /* ===== Step 3 two-stage: CHOOSE your body (two cells), then mark ===== */
  .jny .s3chooser{display:none;flex:0 1 auto;min-height:0;gap:12px;margin:auto 0;height:64dvh;max-height:100%;}
  .jny .card.step3.s3-choosing .s3chooser{display:flex;}
  .jny .card.step3.s3-choosing .s3changerow,.jny .card.step3.s3-choosing .s3stage,.jny .card.step3.s3-choosing .s3announce{display:none;}
  .jny .s3choice{flex:1;min-width:0;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;
    background:#05070a;border:1px solid var(--ghair);border-radius:18px;
    overflow:hidden;cursor:pointer;font-family:inherit;padding:0 0 12px;
    animation:segGlow 2s var(--ease) infinite;transition:border-color .16s var(--ease),transform .12s var(--easePress);}
  .jny .s3choice:active{transform:scale(.985);}
  .jny .s3choiceimg{position:absolute;left:0;right:0;top:0;bottom:0;mix-blend-mode:screen;background-repeat:no-repeat;background-size:cover;background-position:center top;pointer-events:none;}
  .jny .s3choiceimg.cm{background-image:url("/assets/body-male-front-v2.webp");}
  .jny .s3choiceimg.cf{background-image:url("/assets/body-female-front-v2.webp");}
  .jny .s3choicelab{position:relative;font-size:14px;font-weight:700;letter-spacing:.02em;color:var(--gink);
    background:transparent;padding:5px 16px;border-radius:999px;}
  @media (prefers-reduced-motion: reduce){.jny .s3choice{animation:none;}}

  .jny .s3changerow{flex:none;margin-top:10px;display:flex;align-items:center;gap:10px;}
  .jny .s3change{appearance:none;cursor:pointer;font-family:inherit;flex:none;font-size:11.5px;font-weight:700;
    color:var(--gink2);background:rgba(255,255,255,.05);border:1px solid var(--ghair);border-radius:10px;padding:7px 10px;
    display:inline-flex;align-items:center;gap:5px;transition:background .16s var(--ease),color .16s var(--ease);}
  .jny .s3change .navchev{width:14px;height:14px;}
  .jny .s3change:active{background:rgba(255,255,255,.1);}
  .jny .s3changerow .seg3{flex:1;}

  /* the figure stage: the body is the centered hero, absorbing all spare height */
  .jny .s3stage{flex:0 1 auto;min-height:0;display:flex;align-items:center;justify-content:center;margin-top:auto;}
  .jny .s3bodywrap{position:relative;height:64dvh;max-height:100%;aspect-ratio:9 / 16;max-width:100%;display:flex;}
  .jny .s3fig{position:relative;flex:1;min-height:0;aspect-ratio:9 / 16;overflow:hidden;border-radius:14px;}
  /* the licensed figure art, dropped on the charcoal via screen blend so the black ground vanishes */
  .jny .s3figimg{position:absolute;inset:0;mix-blend-mode:screen;background-repeat:no-repeat;background-size:cover;background-position:center;}
  .jny.s3-male   .s3figimg.ff{background-image:url("/assets/body-male-front-v2.webp");}
  .jny.s3-male   .s3figimg.fb{background-image:url("/assets/body-male-back-v2.webp");}
  .jny.s3-female .s3figimg.ff{background-image:url("/assets/body-female-front-v2.webp");}
  .jny.s3-female .s3figimg.fb{background-image:url("/assets/body-female-back-v2.webp");}
  .jny .s3zone{position:absolute;inset:0;width:100%;height:100%;}
  /* one figure at a time on this mobile-first step; the toggle swaps front/back */
  .jny .s3figback{display:none;}
  .jny .s3bodywrap.showback .s3figfront{display:none;}
  .jny .s3bodywrap.showback .s3figback{display:block;}

  /* markers, ported 1:1 from app.css */
  .jny .s3site{cursor:pointer;}
  .jny .s3site .hit{fill:transparent;pointer-events:all;}
  .jny .s3site .mcore{filter:drop-shadow(0 0 2px rgba(150,236,255,.9));transition:r .25s var(--ease),fill .25s var(--ease);}
  /* the glass disc: a frosted translucent circle with a soft cyan rim, breathing gently. */
  .jny .s3site .mrim{filter:drop-shadow(0 0 4px rgba(80,215,255,.7));animation:s3glassbreath 2.8s ease-in-out infinite;transition:fill .25s var(--ease),stroke .25s var(--ease);}
  @keyframes s3glassbreath{0%,100%{filter:drop-shadow(0 0 3px rgba(80,215,255,.5));}50%{filter:drop-shadow(0 0 6px rgba(80,215,255,.9));}}
  @media (prefers-reduced-motion:reduce){.jny .s3site .mrim{animation:none;}}
  .jny .s3site .mglow{opacity:.14;transition:opacity .3s var(--ease);}
  /* recency = the ring lights AMBER (recently used, cools over a week). A lit ring, never a solid fill. */
  .jny .s3site .mheat{filter:drop-shadow(0 0 4px rgba(242,178,90,.9));transition:opacity .5s var(--ease);pointer-events:none;}
  /* SELECTED = SAME glass disc, its outer RING lights up bright cyan and PULSES. Never a
     solid fill (that reads as flat vector art); the glass stays glass, the ring lights. */
  .jny .s3site.sel .mrim{stroke:#8CF0FF;stroke-width:1.8;animation:s3sellit 1.4s ease-in-out infinite;}
  @keyframes s3sellit{0%,100%{filter:drop-shadow(0 0 4px rgba(90,219,255,.7));}50%{filter:drop-shadow(0 0 9px rgba(90,219,255,1)) drop-shadow(0 0 16px rgba(18,182,236,.6));}}
  .jny .s3site.sel .mcore{fill:#EAFBFF;filter:drop-shadow(0 0 3px rgba(140,240,255,1));}
  .jny .s3site.sel .mglow{opacity:.28;}
  /* MOST-RESTED suggestion = SAME glass disc, outer ring lit AMBER and pulsing (matches the
     caption dot). Ring lights, glass stays glass, no fill. */
  .jny .s3site.suggest .mrim{stroke:#F2B25A;stroke-width:1.8;animation:s3suggest 1.9s ease-in-out infinite;}
  .jny .s3site.suggest .mcore{fill:#FFD8A0;filter:drop-shadow(0 0 2px rgba(242,178,90,.95));}
  @keyframes s3suggest{0%,100%{filter:drop-shadow(0 0 3px rgba(242,178,90,.5));}50%{filter:drop-shadow(0 0 8px rgba(242,178,90,1));}}
  @media (prefers-reduced-motion:reduce){.jny .s3site.sel .mrim,.jny .s3site.suggest .mrim{animation:none;}}
  /* radar ping: grows by transform:scale (iOS-safe), not the SVG r attribute */
  .jny .s3site .ping{opacity:0;transform-box:fill-box;transform-origin:center;vector-effect:non-scaling-stroke;will-change:transform,opacity;}
  .jny .s3site.sel .ping{filter:drop-shadow(0 0 5px rgba(91,219,255,1)) drop-shadow(0 0 12px rgba(18,182,236,.8));}
  .jny .s3site.sel .ping1{animation:s3radar 1.8s var(--easeFluid) infinite;}
  .jny .s3site.sel .ping2{animation:s3radar 1.8s var(--easeFluid) infinite;animation-delay:.9s;}
  @keyframes s3radar{0%{opacity:.9;transform:scale(1);}70%{opacity:.18;}100%{opacity:0;transform:scale(3.2);}}
  @media (hover:hover){.jny .s3site:hover .mglow{opacity:.4;}}

  /* the confirming/announce line: the Step-3 equivalent of Step 1's WE SUGGEST.
     amber callout with a live glowing dot, present on arrival, personalizes on log. */
  .jny .s3announce{flex:none;margin-top:10px;margin-bottom:72px;display:flex;align-items:center;gap:9px;padding:10px 12px;border-radius:13px;min-height:42px;
    background:linear-gradient(180deg,rgba(242,178,90,.10),rgba(242,178,90,.035));border:1px solid rgba(242,178,90,.22);
    transition:background .3s var(--ease),border-color .3s var(--ease);}
  /* once a site is logged it flips to the LED-blue confirm tone */
  .jny .card.step3.s3-logged .s3announce{background:linear-gradient(180deg,rgba(18,182,236,.12),rgba(18,182,236,.04));border-color:rgba(18,182,236,.32);}
  .jny .s3announce .adot{width:8px;height:8px;border-radius:50%;flex:none;align-self:flex-start;margin-top:3.5px;background:#F2B25A;
    box-shadow:0 0 6px 1px rgba(242,178,90,.9),0 0 14px 3px rgba(242,178,90,.45);animation:s3breath 2.4s ease-in-out infinite;}
  .jny .card.step3.s3-logged .s3announce .adot{background:#5BDBFF;box-shadow:0 0 6px 1px rgba(91,219,255,.9),0 0 14px 3px rgba(18,182,236,.5);}
  .jny .s3announce .satxt{flex:1;font-size:12px;line-height:1.45;font-weight:500;color:#D9E0E8;letter-spacing:.018em;}
  .jny .s3announce .satxt b{color:#fff;font-weight:700;}
  @keyframes s3breath{0%,100%{opacity:1;}50%{opacity:.5;}}
  @media (prefers-reduced-motion: reduce){.jny .s3announce .adot{animation:none;opacity:1;}}

  /* the swipe-forward nudge, hidden until a site is logged, then revealed white with the ping */
  .jny .step3 .hint{position:absolute;left:0;right:0;bottom:30px;margin:0;z-index:4;opacity:0;transform:translateY(5px);pointer-events:none;
    transition:opacity .45s var(--ease),transform .45s var(--ease);}
  .jny .card.step3.show-nudge .hint{opacity:1;transform:none;color:#FFFFFF;font-weight:700;font-size:15px;letter-spacing:.008em;pointer-events:auto;cursor:pointer;}
  .jny .card.step3.show-nudge .hint .arr{opacity:1;color:#FFFFFF;}
  .jny .step3 .disc{position:absolute;left:16px;right:16px;bottom:8px;margin:0;font-size:10px;text-align:center;z-index:4;}

  /* ===== Step 4: the receipt + one-line vial card ===== */
  .jny .step4 .cardin{padding:15px 18px 14px;}
  .jny .s4detect{margin:14px 0 0;font-size:13.5px;font-weight:500;letter-spacing:.016em;color:var(--gink2);}
  .jny .s4detect b{color:#fff;font-weight:700;}
  /* the hero one-line vial card, exactly what will live in My Vials */
  .jny .s4card{margin:13px 0 0;padding:15px 15px 14px;border-radius:18px;position:relative;
    background:linear-gradient(180deg,rgba(255,255,255,.066),rgba(255,255,255,.03));
    border:1px solid rgba(255,255,255,.12);box-shadow:0 12px 34px -20px rgba(0,0,0,.7),inset 0 1px 0 rgba(255,255,255,.06);
    transition:box-shadow .5s var(--ease),border-color .5s var(--ease);}
  .jny .step4.saved .s4card{border-color:rgba(18,182,236,.4);box-shadow:0 14px 40px -18px rgba(18,182,236,.5),inset 0 1px 0 rgba(255,255,255,.08);}
  .jny .s4top{display:flex;align-items:center;gap:13px;}
  .jny .s4cv{width:34px;height:46px;border-radius:8px;flex:none;position:relative;
    background:rgba(255,255,255,.10);border:1px solid var(--ghair);box-shadow:inset 0 1px 0 rgba(255,255,255,.4);}
  .jny .s4cv::before{content:"";position:absolute;left:9px;right:9px;top:-4px;height:6px;border-radius:3px;background:#c3ced9;box-shadow:inset 0 1px 0 rgba(255,255,255,.5);}
  .jny .s4cv::after{content:"";position:absolute;left:6px;right:6px;bottom:5px;height:var(--vfill,42%);border-radius:4px;
    background:linear-gradient(180deg,#22E0A0,#10C6E8 55%,#1296F2);box-shadow:0 0 10px var(--glow);transition:height .9s var(--easeFluid);}
  .jny .s4head{flex:1;min-width:0;}
  .jny .s4l1{display:flex;align-items:center;gap:8px;}
  .jny .s4l1 b{font-size:18px;font-weight:700;letter-spacing:0em;color:var(--gink);}
  .jny .s4fresh{font-size:9.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#9fb0bf;
    background:rgba(255,255,255,.06);border:1px solid var(--ghair);border-radius:6px;padding:2.5px 6px;}
  .jny .s4fresh.warn{color:#F2B25A;border-color:rgba(242,178,90,.38);background:rgba(242,178,90,.08);}
  .jny .s4l2{margin-top:2px;font-size:12.5px;color:var(--gink2);font-variant-numeric:tabular-nums;letter-spacing:.018em;}
  .jny .s4count{flex:none;text-align:right;line-height:1.05;}
  .jny .s4count b{display:block;font-size:23px;font-weight:700;letter-spacing:0em;color:var(--gink);font-variant-numeric:tabular-nums;}
  .jny .s4count span{font-size:10.5px;font-weight:600;letter-spacing:.02em;color:var(--gink2);}
  /* remaining LED bar */
  .jny .s4bar{margin:13px 0 0;height:7px;border-radius:6px;overflow:hidden;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.06);}
  .jny .s4barfill{display:block;height:100%;border-radius:6px;width:var(--barw,90%);
    background:linear-gradient(90deg,#22E0A0,#10C6E8 55%,#1296F2);box-shadow:0 0 10px -1px var(--glow);
    transition:width .9s var(--easeFluid);}
  .jny .s4site{margin:12px 0 0;display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--gink2);letter-spacing:.017em;}
  .jny .s4site svg{flex:none;width:13px;height:13px;}
  .jny .s4site b{color:#d9e0e8;font-weight:600;}
  /* primary CTA */
  .jny .s4btn{margin:16px 0 0;width:100%;appearance:none;cursor:pointer;font-family:inherit;border:none;
    padding:15px 18px;border-radius:15px;font-size:16px;font-weight:700;letter-spacing:.01em;color:#06222e;
    background:linear-gradient(180deg,#22E0A0,#10C6E8 55%,#1296F2);box-shadow:0 12px 30px -12px var(--glow);
    transition:transform .16s var(--easePress),box-shadow .3s var(--ease),opacity .3s var(--ease);}
  .jny .s4btn:active{transform:scale(.975);}
  .jny .step4.saved .s4btn{display:none;}
  /* saved confirmation, replaces the button */
  .jny .s4done{display:none;margin:16px 0 0;align-items:center;gap:11px;padding:14px 15px;border-radius:15px;
    background:linear-gradient(180deg,rgba(18,182,236,.13),rgba(18,182,236,.04));border:1px solid rgba(18,182,236,.34);}
  .jny .step4.saved .s4done{display:flex;animation:s4pop .42s var(--easePress);}
  @keyframes s4pop{0%{transform:scale(.96);opacity:0;}100%{transform:scale(1);opacity:1;}}
  .jny .s4check{width:26px;height:26px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;
    background:linear-gradient(180deg,#22E0A0,#10C6E8 55%,#1296F2);box-shadow:0 0 14px -2px var(--glow);}
  .jny .s4check svg{width:14px;height:14px;}
  .jny .s4donetx{flex:1;min-width:0;font-size:13.5px;font-weight:600;color:#e6edf3;letter-spacing:.016em;}
  .jny .s4donetx b{color:#fff;}
  .jny .s4undo{flex:none;appearance:none;cursor:pointer;font-family:inherit;font-size:12.5px;font-weight:700;color:var(--blue);
    background:rgba(255,255,255,.05);border:1px solid var(--ghair);border-radius:9px;padding:7px 11px;}
  .jny .s4undo:active{background:rgba(255,255,255,.1);}
  .jny .step4 .disc{margin-top:12px;flex:none;font-size:10px;}
  /* phone bonus: unlock second vial slot */
  .jny .s4phone{display:none;margin-top:12px;padding:14px 16px;border-radius:16px;
    background:rgba(255,255,255,.05);border:1px solid rgba(18,182,236,.22);
    flex-direction:column;gap:9px;}
  .jny .s4phone.show{display:flex;animation:s4pop .38s var(--easePress);}
  .jny .s4phonetitle{font-size:14px;font-weight:700;color:#FFFFFF;letter-spacing:.01em;}
  .jny .s4phonesub{font-size:11.5px;color:rgba(255,255,255,.48);letter-spacing:.01em;margin-top:-4px;}
  .jny .s4phoneinput{display:flex;gap:8px;}
  .jny .s4phoneinput input{flex:1;padding:11px 14px;border-radius:11px;border:1.5px solid rgba(255,255,255,.22);
    background:rgba(255,255,255,.07);color:#FFFFFF;font-family:inherit;font-size:15px;
    outline:none;-webkit-appearance:none;transition:border-color .2s;}
  .jny .s4phoneinput input::placeholder{color:rgba(255,255,255,.35);}
  .jny .s4phoneinput input:focus{border-color:rgba(255,255,255,.6);}
  .jny .s4phoneinput button{padding:11px 18px;border-radius:11px;border:0;
    background:linear-gradient(135deg,#22E0A0,#1296F2);color:#06222e;
    font-family:inherit;font-size:14px;font-weight:700;cursor:pointer;
    -webkit-tap-highlight-color:transparent;white-space:nowrap;letter-spacing:.01em;
    transition:transform .12s var(--easePress);}
  .jny .s4phoneinput button:active{transform:scale(.96);}
  .jny .s4phoneok{display:none;margin-top:10px;font-size:13px;font-weight:700;
    color:var(--blue);text-align:center;letter-spacing:.01em;animation:s4pop .38s var(--easePress);}
  .jny .s4phoneok.show{display:block;}

  /* ===== Pro Max SCALE-UP: reclaim chrome real estate so the hero vial + syringe go massive.
     Stages are flex:1 1 auto, so every pixel freed here flows into .s1stage/.s2stage and the
     height-bound heroes expand to fill it. Source-order overrides; nothing below the fold. ===== */
  .jny .dots{margin:max(44px,calc(env(safe-area-inset-top) + 34px)) 0 5px;}   /* was max(64px, safe+50) 0 10px */
  .jny .topbar{padding:max(10px,env(safe-area-inset-top)) 22px 8px;}          /* tighter header band */
  .jny .wrap{padding-bottom:calc(env(safe-area-inset-bottom) + 5px);}         /* push the bottom UI to the edge */
  .jny .disc{margin-top:8px;}
  .jny .step1 .cardin{padding:3px 16px 4px;}
  .jny .step1 .pickwrap{margin-top:4px;}
  .jny .step1 .pick{padding:9px 15px;}
  .jny .step1 .sizeblk{margin-top:4px;}
  .jny .step2 .cardin{padding:8px 16px 0;}
  /* Step 2 spatial model: top chrome breathes; the syringe (flex:1) stretches into the freed
     bottom half, where the caption + Next float absolutely over the background. */
  .jny .step2 .htitle{margin-top:6px;line-height:1.05;}
  .jny .s2carry{margin-top:12px;padding:7px 12px;}
  .jny .s2carry .ct b{font-size:13.5px;}
  .jny .s2sizes{margin-top:12px;}
  .jny .syrq{margin:0 2px 6px;font-size:13.5px;}
  .jny .s2stage{flex:1 1 auto;min-height:0;margin-top:10px;margin-bottom:84px;}
  .jny .s2bottom{position:absolute;left:0;right:0;bottom:18px;text-align:center;pointer-events:none;z-index:5;}
  .jny .s2bottom .s2caption,.jny .s2bottom .disc{margin:0 auto;text-align:center;width:100%;}
  .jny .s2drawnmsg{color:#FFFFFF;font-weight:700;}
  .jny .card.step2.st-drawn .s2drawnmsg{display:inline;}
  .jny .s2next{appearance:none;-webkit-appearance:none;background:none;border:0;padding:0;cursor:pointer;position:absolute;bottom:14px;right:18px;width:36px;height:36px;display:flex;align-items:center;justify-content:center;color:#FFFFFF;opacity:0;pointer-events:none;transition:opacity .4s;z-index:4;}
  .jny .s2next .navchev{width:36px;height:36px;stroke-width:2.5;filter:drop-shadow(0 0 6px rgba(16,198,236,.65));}
  .jny .card.step2.st-drawn .s2next{opacity:1;pointer-events:auto;}
  .jny .card.step2.st-drawn .s2next .navchev{animation:breathe 2s ease-in-out infinite;}

  /* ===== STEP 3: color unification + hero scale-up ===== */
  /* A. Force all four body assets (M/F, front/back) to the exact brand cyan (--led2 #10C6E8),
     like one laser: sepia(1) flattens each source's varying hue to a single base, then
     saturate + hue-rotate lock the identical neon cyan. Black ground stays black -> screen blend
     still drops it. Applied to both the chooser cells and the marking figures. */
  .jny .s3figimg,.jny .s3choiceimg{filter:sepia(1) saturate(4.6) hue-rotate(144deg) brightness(1.06) contrast(1.05);}
  /* B/C. Ruthless subtraction: thin the Step 3 chrome so the flex:1 chooser + body stage grow and
     the bodies become massive heroes. The figures are background-size:cover in aspect-9/16 boxes and
     the dot SVG is inset:0 over them, so scaling is uniform and the dots stay pinned (req D). */
  .jny .step3 .cardin{padding:3px 16px 4px;}
  .jny .s3chooser{margin:auto 0;gap:10px;}
  .jny .step3 .s3changerow{margin-top:4px;}
  .jny .s3stage{margin-top:auto;}
  .jny .s3choiceimg{bottom:0;}
  .jny .s3choice{padding-bottom:9px;}
  .jny .s3announce{margin-top:6px;}

  /* ===== STEP 4: Confirm Dose. Condensed receipt + the press-and-hold T. ring hero ===== */
  .jny .step4 .cardin{padding:8px 18px 10px;}
  .jny .s4detect{margin:7px 0 0;font-size:12.5px;}
  .jny .s4card{margin:9px 0 0;padding:10px 13px;}      /* shrink the receipt: a record, not the focal point */
  .jny .s4cv{width:28px;height:38px;}
  .jny .s4l1 b{font-size:15px;}
  .jny .s4count b{font-size:18px;}
  .jny .s4bar{margin:9px 0 0;height:6px;}
  .jny .s4site{margin:8px 0 0;font-size:11.5px;}
  /* THE HERO RING: a massive central artifact (40-50% of viewport height via dvh).
     --charge-level (0..1) drives the SVG perimeter trace AND a heating glow (cool dim blue ->
     bright saturated cyan, blur + spread grow). The inner face is overflow:hidden + border-radius:50%
     so the square JPG is clipped to a perfect seamless circle; the outer container stays
     overflow-visible so the glow, track, and flash bloom outward. */
  /* Ring + T rendered ENTIRELY in code. No image, no mask, no clip: nothing can render a right
     angle. The glow is a radial-gradient that fades to transparent, so it is a true circle; the
     container is overflow:visible so it blooms natively. --charge-level (0..1) drives everything. */
  /* The ring is sized off the VIEWPORT so it can overflow its card; a flex item wider than
     its container gets margin:auto resolved to 0 and start-aligns, shoving the ring RIGHT of the
     page center, so symmetric computed margins center it on the page deterministically.
     78vw (was 92vw) leaves a real gutter inside the frame instead of kissing both edges, and
     keeps the charge arc reading as a circle that builds rather than one clipped to the wall. */
  .jny .s4ring{position:relative;--s4w:min(46dvh,78vw,380px);width:var(--s4w);aspect-ratio:1;
    margin:auto calc((100% - var(--s4w))/2);flex:none;cursor:pointer;
    touch-action:none;-webkit-tap-highlight-color:transparent;--charge-level:0;overflow:visible;}
  .jny .s4ring.s4disabled{opacity:.4;pointer-events:none;}
  .jny .s4glow{position:absolute;inset:-24%;border-radius:50%;pointer-events:none;
    opacity:calc(.22 + var(--charge-level)*.78);transform:scale(calc(.6 + var(--charge-level)*.5));
    transition:opacity .08s linear,transform .08s linear;
    background:radial-gradient(circle,rgba(40,230,182,.62) 0%,rgba(16,198,232,.42) 36%,rgba(16,198,232,0) 66%);}
  /* ===== the b5 POWER RING: the lock's machined dial seals the vial in ===== */
  .jny .s4well{display:none;}
  .jny .s4dial{position:absolute;inset:0;transition:transform .6s var(--easeFluid);}
  .jny .s4ring.s4charging .s4dial{transform:scale(1.045);}
  .jny .s4ring.s4brink .s4dial{animation:s4tremor .11s linear infinite;}
  @keyframes s4tremor{0%{transform:scale(1.05) translate(0,0)}25%{transform:scale(1.05) translate(1px,-1px)}50%{transform:scale(1.05) translate(-1px,1px)}75%{transform:scale(1.05) translate(1px,1px)}100%{transform:scale(1.05) translate(0,0)}}
  .jny .s4dial .r1{position:absolute;inset:0;border-radius:50%;
    background:conic-gradient(from 210deg,#cfd6dd,#f5f8fa 12%,#aeb7c0 26%,#e9eef2 42%,#9aa4ad 58%,#f2f6f9 74%,#b8c0c8 88%,#cfd6dd);
    box-shadow:inset 0 1px 1px rgba(255,255,255,.9),inset 0 -2px 3px rgba(30,40,50,.35),
      0 30px 60px -20px rgba(0,0,0,.85),0 8px 18px -8px rgba(0,0,0,.6);}
  .jny .s4dial .brush{position:absolute;inset:0;border-radius:50%;opacity:.5;
    background:repeating-conic-gradient(rgba(255,255,255,.05) 0 .4deg, transparent .4deg .9deg);}
  .jny .s4dial .gap1{position:absolute;inset:2.6%;border-radius:50%;background:#828b94;
    box-shadow:inset 0 1px 2px rgba(0,0,0,.45),inset 0 -1px 0 rgba(255,255,255,.7);}
  .jny .s4dial .r2{position:absolute;inset:3.7%;border-radius:50%;
    background:conic-gradient(from 170deg,#c8cfd6,#f2f6f9 14%,#a6afb8 30%,#e6ebef 46%,#949ea7 62%,#eef3f6 78%,#b2bac2 90%,#c8cfd6);
    box-shadow:inset 0 1px 1px rgba(255,255,255,.85),inset 0 -2px 3px rgba(30,40,50,.3);}
  .jny .s4dial .metalticks{position:absolute;inset:0;pointer-events:none;}
  .jny .s4dial .gap2{position:absolute;inset:9.7%;border-radius:50%;background:#69727b;
    box-shadow:inset 0 1px 2px rgba(0,0,0,.45),inset 0 -1px 0 rgba(255,255,255,.5);}
  .jny .s4dial .ledseam{position:absolute;inset:0;pointer-events:none;animation:s4seambreath 1.9s ease-in-out infinite;}
  @keyframes s4seambreath{0%,100%{opacity:.55}50%{opacity:1}}
  .jny .s4ring.s4charging .ledseam,.jny .s4ring.s4peak .ledseam{animation:none;opacity:1;}
  .jny .s4dial .pulsewrap{position:absolute;inset:0;pointer-events:none;}
  .jny .s4dial .pulsewrap circle{transform-box:fill-box;transform-origin:center;}
  .jny .s4dial .pw1{animation:s4ringpulse 1.9s ease-out infinite;}
  .jny .s4dial .pw2{animation:s4ringpulse 1.9s ease-out infinite;animation-delay:.95s;}
  @keyframes s4ringpulse{0%{transform:scale(.97);opacity:.9}75%{transform:scale(1.16);opacity:0}100%{transform:scale(1.16);opacity:0}}
  .jny .s4ring.s4charging .pulsewrap,.jny .s4ring.s4peak .pulsewrap{display:none;}
  .jny .s4svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;}
  .jny .s4fill{fill:none;stroke:url(#s4seam);stroke-width:4.5;stroke-linecap:round;stroke-dasharray:735.13;stroke-dashoffset:735.13;
    filter:drop-shadow(0 0 calc(2px + var(--charge-level)*11px) rgba(60,224,210,calc(.4 + var(--charge-level)*.6)));}
  /* PURE BLACK BEHIND THE VIAL (design call 2026-07-09, the fork's neck law applied to
     Step 4): a see-through vial shows whatever is behind it, so every light source in
     the portal is retired (drift blobs, breathing pglow, the charging corelight). The
     glass and the empty neck now show flat black at every charge level, no clear-to-
     teal flash, no lit hole through the neck. The charge drama lives ON the ring
     (arc, seam, accelerating ticks, dial swell), never behind the glass. Markup inert. */
  .jny .s4dial .portal{position:absolute;inset:12.2%;border-radius:50%;overflow:hidden;isolation:isolate;
    background:#000;
    box-shadow:inset 0 6px 16px rgba(0,0,0,.75);}
  .jny .s4dial .drift{display:none;}
  .jny .s4dial .drift2{display:none;}
  /* D1 THE TICK RINGS MEAN WORK, NOT WAITING. They used to rotate CONTINUOUSLY at idle
     (26s/44s/15s), which is the visual grammar of a loading spinner: the screen read "wait" and
     the real rest beat, the ring pulse, was drowned out. The system already speeds them while
     charging AND hides the pulse then, so rotation was always meant to say "working". Now the
     angle is INTEGRATED by the same rAF that draws the charge arc: still at rest, moving the
     instant you press, and accelerating all the way to the seal. Driving the angle instead of a
     keyframe duration also kills the 100-175deg SNAP that a mid-flight animation-duration change
     produced on release (measured on both engines before this change). */
  .jny .s4dial .ticks{position:absolute;left:50%;top:50%;width:100%;height:100%;transform:translate(-50%,-50%) rotate(var(--s4r1,0deg));}
  .jny .s4dial .ticks.t2{transform:translate(-50%,-50%) rotate(var(--s4r2,0deg));}
  /* t3 is a single 120-long comet arc, not a dashed ring, so a FROZEN one reads as a progress bar
     stuck at some value, and it would rest at a different angle every time depending on how far
     the last press got. It belongs to the working state: absent at rest, it sweeps in under the
     thumb. (t1 and t2 are 4deg and 7deg dash patterns; freezing those is invisible.) */
  .jny .s4dial .ticks.t3{transform:translate(-50%,-50%) rotate(var(--s4r3,0deg));
    opacity:0;transition:opacity .34s var(--ease);}
  .jny .s4ring.s4charging .ticks.t3,.jny .s4ring.s4peak .ticks.t3{opacity:1;}
  .jny .s4dial .corelight{display:none;}
  .jny .s4dial .pglow{display:none;}
  /* Dead center: the PNG's solid vial content sits at 49.80%/50.94% of its own canvas
     (measured alpha bbox x326-1204 y466-2338 of 1536x2752), so the translate compensates
     to land the GLASS center exactly on the ring center. */
  .jny .s4dial .pvial{position:absolute;left:50%;top:50%;width:54%;transform:translate(-49.8%,-50.94%);transition:transform .5s var(--easeFluid);}
  .jny .s4ring.s4charging .pvial{transform:translate(-49.8%,-50.94%) scale(1.05);}
  .jny .s4dial .pvialbox{position:relative;width:100%;aspect-ratio:1536/2752;isolation:isolate;}
  .jny .s4dial .pvialbox img,.jny .s4dial .pvialbox svg{position:absolute;inset:0;width:100%;height:100%;display:block;}
  .jny .s4hold{margin:14px -18px 0;text-align:center;font-size:16px;font-weight:600;letter-spacing:.004em;color:#cfdae4;white-space:nowrap;transition:opacity .3s;}
  .jny .s4ring.s4peak ~ .s4hold{opacity:0;}
  /* SUPERNOVA: a full-viewport blast ABOVE the vault (z 10000) so it can never cut to black */
  .jny .s4nova{position:fixed;inset:0;z-index:10000;pointer-events:none;opacity:0;transform:scale(.2);
    transform-origin:var(--nx,50%) var(--ny,46%);will-change:opacity,transform;
    background:radial-gradient(circle at var(--nx,50%) var(--ny,46%),#ffffff 0%,#eafff8 16%,#22E0A0 40%,#10C6E8 68%,rgba(16,198,232,0) 92%);}
  .jny .s4nova.go{animation:s4nova .72s cubic-bezier(.2,.72,.2,1) forwards;}
  @keyframes s4nova{0%{opacity:0;transform:scale(.2);}16%{opacity:1;transform:scale(.9);}40%{opacity:1;transform:scale(1.3);}54%{opacity:1;transform:scale(1.48);}100%{opacity:0;transform:scale(1.85);}}
  @media (prefers-reduced-motion:reduce){
    .jny .s4nova.go{animation-duration:.32s;}
    .jny .s4dial,.jny .s4dial .drift,.jny .s4dial .drift2,.jny .s4dial .pglow,.jny .s4dial .ticks.t1,.jny .s4dial .ticks.t2,.jny .s4dial .ticks.t3,.jny .s4dial .ledseam,.jny .s4dial .pw1,.jny .s4dial .pw2,.jny .s4ring.s4brink .s4dial{animation:none;transition:none;}
    .jny .s4dial .pulsewrap{display:none;}
  }
  /* ===== the B header anatomy (b1-b5): centered letterspaced wordmark, back floating
     left, no corner tag; the step eyebrow reads in the LED gradient. ===== */
  .jny .topbar .tag{display:none;}
  .jny .tbleft{position:absolute;left:0;right:0;top:max(10px,env(safe-area-inset-top));justify-content:center;pointer-events:none;}
  .jny .flowback{position:absolute;left:18px;top:50%;transform:translateY(-50%);pointer-events:auto;z-index:2;}
  .jny .flowback:active{transform:translateY(-50%) scale(.92);}
  .jny .wordmark{font-size:15px;font-weight:600;letter-spacing:.42em;text-indent:.42em;text-shadow:none;}
  /* b1-b3 chrome: the step dots retire (the mockups carry the title only; swipe +
     chevrons still navigate). The eyebrow used to read two-tier here, a gradient NEW
     VIAL over a quiet STEP N OF 4; Section C retired the top line (see C6 below). */
  .jny .dots{visibility:hidden;}
  .jny .eyebrow{background:none;-webkit-text-fill-color:#5E6E7D;color:#5E6E7D;
    font-size:9.5px;font-weight:500;letter-spacing:.3em;text-indent:.3em;}
  /* C6: the NEW VIAL line above STEP N OF 4 is gone. Two stacked labels over every title said
     the same thing twice, and the bright one was the least important thing on the card. The
     titles carry the what ("Reconstitute", "Fill your syringe"), STEP N OF 4 carries the where,
     and the 24px it freed goes to the hero, which is the one thing that should dominate. */
  /* ===== B glass material (rung 4): every base control surface is the Lock B replay glass.
     Selected/lit states keep their LED gradient fill (the proven choreography); only the
     resting surfaces trade charcoal-tint for true glass. Source-order override at end of
     sheet; .sel/.lit/hover states out-specify these. ===== */
  .jny .pick,.jny .chip,.jny .carry,.jny .water,.jny .seg3 .segbtn,.jny .s3choice,.jny .s3change,.jny .stepper button,.jny .s4card{
    border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.06);
    -webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.14),0 10px 30px -12px rgba(0,0,0,.7);}
  /* body-choice cards are the black holographic field, NOT frosted glass. */
  .jny .s3choice{background:#05070a;-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none;}
  /* ===== THE B FIDELITY BLOCK: the exact b1/b2/b3/b5 anatomy, end-of-sheet overrides ===== */
  /* b1 ORDER: picker pill, then the vial hero, then the mg chips, then the captions. */
  .jny .step1 .hero{order:0;}
  .jny .step1 .pickwrap{order:1;width:280px;max-width:100%;margin:12px auto 0;flex:none;}
  .jny .step1 .s1stage{order:2;}
  .jny .step1 .sizeblk{order:3;margin:10px 0 2px;}
  .jny .step1 .hint{order:4;}
  .jny .step1 .disc{order:5;}
  .jny .step1 .s1dragcue{display:none!important;}
  .jny .step1 .blklk{display:none;font-size:15px;font-weight:600;letter-spacing:.005em;text-transform:none;color:#EAF6FC;margin:0 0 10px;text-align:center;white-space:nowrap;}
  .jny .card.step1.s1-mg .blklk{display:block;}
  /* b1 picker: a centered glass pill with the LED dot; no PEPTIDE label */
  .jny .step1 .pick{justify-content:center;gap:10px;border-radius:99px;min-height:46px;padding:0 16px;}
  .jny .step1 .pick .pk{display:none;}
  .jny .step1 .pick .pl{display:contents;}
  .jny .step1 .pick::before{content:'';width:6px;height:6px;border-radius:50%;flex:none;
    background:linear-gradient(180deg,var(--led1),var(--led2) 55%,var(--led3));
    box-shadow:0 1px 8px rgba(16,198,232,.55);}
  .jny .step1 .pick .pn{font-size:12px;font-weight:600;letter-spacing:.14em;text-indent:.14em;text-transform:uppercase;
    max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#EAF6FC;}
  .jny .card.step1:not(.s1-pep) .pick{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.16);color:#EAF6FC;
    box-shadow:inset 0 1px 0 rgba(255,255,255,.14),0 10px 30px -12px rgba(0,0,0,.7);}
  /* b1 readouts: quiet tracked labels, tabular values (the flanks keep the vial the hero) */
  .jny .step1 .s1flank .rdn{font-size:22px;font-weight:700;letter-spacing:0;transition:font-size .4s var(--ease),color .3s var(--ease);}
  .jny .step1 .s1flank .rdl{font-size:8.5px;font-weight:600;letter-spacing:.26em;text-indent:.26em;color:#5E6E7D;text-align:center;}
  /* RECONSTITUTED = the reward, matching Step 2's on-common flanks. */
  .jny .card.step1.s1-ready .s1flank .rdn{font-size:32px;color:#F4F8FB;animation:cmnSync 1.5s ease-in-out infinite;}
  .jny .card.step1.s1-ready .s1flank .rdl{color:#C3D2DE;animation:cmnSync 1.5s ease-in-out infinite;}
  @media (prefers-reduced-motion:reduce){.jny .card.step1.s1-ready .s1flank .rdn,.jny .card.step1.s1-ready .s1flank .rdl{animation:none;}}
  /* b1 mg chips: compact keys, the number over a small MG. The ::before/::after auto
     margins center the strip when it fits and keep it scrollable when it overflows. */
  .jny .step1 .chips{gap:9px;}
  .jny .step1 .chips::before,.jny .step1 .chips::after{content:'';margin:auto;flex:0 0 0.5px;}
  .jny .step1 .chip{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
    width:58px;min-width:58px;min-height:44px;padding:0;border-radius:15px;font-size:14px;font-weight:700;}
  .jny .step1 .chip .cu{font-size:7.5px;font-weight:500;letter-spacing:.16em;text-transform:uppercase;color:#8FA2B2;}
  /* b2/b3 carry: a centered glass pill with the LED dot; no icon, no READY badge */
  .jny .s2carry,.jny .s3carry{width:auto;max-width:100%;margin:12px auto 0;min-height:38px;padding:0 18px;
    border-radius:99px;justify-content:center;gap:9px;flex:none;align-self:center;}
  .jny .s2carry::before,.jny .s3carry::before{content:'';width:6px;height:6px;border-radius:50%;flex:none;
    background:linear-gradient(180deg,var(--led1),var(--led2) 55%,var(--led3));
    box-shadow:0 1px 8px rgba(16,198,232,.55);}
  .jny .s2carry .mvial,.jny .s3carry .mvial,.jny .s2ready{display:none;}
  .jny .s2carry .ct,.jny .s3carry .ct{flex:none;display:flex;align-items:baseline;min-width:0;}
  .jny .s2carry .ct b,.jny .s3carry .ct b{display:inline;font-size:10.5px;font-weight:600;letter-spacing:.14em;
    text-transform:uppercase;color:#EAF6FC;white-space:nowrap;}
  .jny .s2carry .ct b::after,.jny .s3carry .ct b::after{content:" \00B7";color:#8FA2B2;margin:0 3px 0 7px;}
  .jny .s2carry .ct span,.jny .s3carry .ct span{font-size:10.5px;font-weight:600;letter-spacing:.14em;
    text-transform:uppercase;color:#8FA2B2;white-space:nowrap;}
  /* b2 fear-killer header: point them at their own syringe (matches Step 1). */
  .jny .syrq{display:block;font-size:15px;font-weight:600;letter-spacing:.005em;text-transform:none;color:#EAF6FC;margin:0 0 10px;text-align:center;white-space:nowrap;}
  .jny .s2stage{margin-bottom:20px;}
  .jny .card.step2.st-pick .syrwrap::before{opacity:.6;}
  /* b3: the figure floats on the room. The swipe track's transform isolates the screen
     blend from the body background, so the wrap paints the room's own dark under the
     figure and the edge-feather mask melts the seam into the real room. */
  .jny .s3bodywrap{background:#06080b;
    -webkit-mask-image:linear-gradient(90deg,transparent,#000 26%,#000 74%,transparent),linear-gradient(180deg,transparent,#000 12%,#000 88%,transparent);
    -webkit-mask-composite:source-in;
    mask-image:linear-gradient(90deg,transparent,#000 26%,#000 74%,transparent),linear-gradient(180deg,transparent,#000 12%,#000 88%,transparent);
    mask-composite:intersect;}
  /* b3 announce: a quiet centered line, not a boxed callout */
  .jny .s3announce,.jny .card.step3.s3-logged .s3announce{margin:8px 0 12px;padding:0;min-height:0;justify-content:center;
    background:none;border:0;box-shadow:none;}
  /* b5 STEP 4: title + one quiet meta line + the dial + the tracked hold cue */
  .jny .s4detect{display:none;}
  .jny .s4card,.jny .step4.saved .s4card{margin:12px 0 0;padding:0;border:0;background:none;
    -webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none;}
  .jny .s4cv,.jny .s4fresh,.jny .s4bar,.jny .s4site{display:none;}
  .jny .s4card .s4top{display:flex;align-items:baseline;justify-content:center;gap:8px;flex-wrap:nowrap;max-width:100%;padding:0 12px;overflow:hidden;}
  .jny .s4head{display:flex;align-items:baseline;gap:8px;min-width:0;overflow:hidden;}
  .jny .s4l2{overflow:hidden;text-overflow:ellipsis;}
  .jny .s4l1{display:flex;}
  .jny .s4l1 b{font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;white-space:nowrap;
    background:linear-gradient(90deg,var(--led1),var(--led2) 55%,var(--led3));
    -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent;}
  .jny .s4l2{font-size:11px;font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:#8FA2B2;white-space:nowrap;}
  .jny .s4count{display:flex;align-items:baseline;gap:4px;font-size:11px;font-weight:500;letter-spacing:.14em;
    text-transform:uppercase;color:#8FA2B2;white-space:nowrap;}
  .jny .s4count::before{content:"\00B7";color:#8FA2B2;margin-right:4px;}
  .jny .s4count b{font-size:11px;font-weight:600;color:#EAF6FC;}
  /* the command: bold, near-white, confident (matches Steps 1-2's handoff line). */
  .jny .s4hold{font-size:16px;font-weight:700;letter-spacing:.02em;text-indent:0;text-transform:none;
    color:#F4F8FB;white-space:nowrap;text-shadow:0 0 12px rgba(16,198,232,.4);}

  /* ===== THE COPY BAND (guide words own their own space; heroes fill everything above).
     Root cause of the on-device overlap: the hero wraps were sized in dvh with
     max-height:100% as the guard, but their flex parents are flex-basis:auto, whose
     height is INDEFINITE in WebKit, so the clamp silently fails on short viewports and
     the barrel/figure runs under the absolutely-pinned caption band. Fix: flex-basis 0
     makes the stage height DEFINITE (both engines resolve child percentages against it),
     the hero fills 100% of it (maximized, physically cannot overlap), and every guide
     line below is a STATIC stacked row, never an absolute overlay with magic margins. */
  .jny .s2stage{flex:1 1 0%;min-height:0;margin-bottom:0;}
  .jny .syrwrap{height:100%;}
  .jny .s2bottom{position:static;left:auto;right:auto;bottom:auto;padding:8px 0 2px;}
  .jny .s2bottom .s2caption{margin-top:0;}
  .jny .s2bottom .disc{margin-top:4px;}
  .jny .s3stage{flex:1 1 0%;min-height:0;margin-top:6px;}
  .jny .s3bodywrap{height:100%;}
  .jny .step3 .hint{position:static;left:auto;right:auto;bottom:auto;margin:8px 0 0;}
  .jny .step3 .disc{position:static;left:auto;right:auto;bottom:auto;margin:4px 0 0;}
  .jny .s3announce,.jny .card.step3.s3-logged .s3announce{margin:8px 0 0;}
  /* one message at a time: once the site is logged, the white "save it" nudge IS the
     line; the announce stands down instead of stacking under it. */
  .jny .card.step3.show-nudge .s3announce{display:none;}

  /* ===== SECTION B: six measured defects, end-of-sheet so they win by source order ===== */
  /* B1. The Step 3 headline's line box did not contain its own descenders: 21px glyphs in a
     line-height:1 box, so the "y" and "j" of "Where did you inject?" ran 4px into the
     Front/Back control and its border glow. Contain the descenders, then give the control
     row real ink clearance instead of the measured 4px. */
  .jny .step3 .htitle{line-height:1.16;}
  .jny .step3 .s3changerow{margin-top:10px;}
  /* B6. The card opened 3px below its own top edge while the closing rows sat 92px off the
     floor: cramped above, loose below. Move the air to where the eye needs it. The body hero
     is flex:1 1 0%, so what the top gains the bottom returns and the figure keeps its height. */
  .jny .step3 .cardin{padding-top:8px;}
  .jny .s3announce,.jny .card.step3.s3-logged .s3announce{margin:3px 0 0;}
  .jny .step3 .hint{margin:4px 0 0;}
  .jny .step3 .disc{margin:3px 0 0;}
  /* B3. The handoff chevron sat 5px off the period on both engines, and the line was pinned
     nowrap, which does not wrap, it overflows. Real optical air for the glyph, and the
     sentence breaks in a balanced lockup on a narrow phone instead of running off it. */
  .jny .hint{gap:12px;}
  .jny .card.step1.show-nudge .hint,.jny .card.step2.show-nudge .hint,.jny .card.step3.show-nudge .hint{white-space:normal;}
  .jny .hint>span:not(.arr){text-wrap:balance;}

  /* ===== SECTION D: the lead consistency pass, end-of-sheet so it wins by source order ===== */
  /* D4. The magnet has to be SEEN, because haptics are off app-wide. The cue rides the HANDLE,
     not the notch: at the suggested level the handle sits exactly ON the notch and hides both the
     dashed tick and its label (caught in the eye gate, every assertion was green). So the handle
     itself goes white hot and stops breathing the moment the water locks on, and drops back to
     its LED gradient the moment you pull past. The detent confirms itself, and locks nothing. */
  .jny .card.step1.s1-atnotch .waterhandle .whbar{animation:none;
    background:linear-gradient(180deg,rgba(240,253,255,.98),rgba(155,238,255,.98) 45%,rgba(47,216,245,.98));
    border-color:rgba(255,255,255,.9);
    box-shadow:0 6px 28px 0 var(--glow),inset 0 1px 0 rgba(255,255,255,.95);}
  /* D6. ONE disclaimer: same words, same slot, same treatment on all four steps. Step 1 used to
     render it 12px/700 in white, which is headline weight, because the slot was doing instruction
     duty as well. It is a footnote everywhere now. nowrap is released so the line can wrap
     instead of overflowing, balance keeps the two lines even instead of orphaning a word, and
     step 2 keeps clear of the absolutely positioned Next chevron. */
  .jny .disc,.jny .step1 .disc,.jny .step2 .disc,.jny .step3 .disc,.jny .step4 .disc{
    font-size:10px;font-weight:400;line-height:1.45;color:#8893a2;text-align:center;white-space:normal;}
  /* each sentence is its own unbreakable unit, so the line can only ever break BETWEEN sentences:
     "Research use only. Not medical advice." / "Not for human consumption." A plain wrap orphaned
     the last word and text-wrap:balance split "Not medical / advice." straight down the middle. */
  .jny .disc span{white-space:nowrap;}
  .jny .step2 .disc{max-width:calc(100% - 72px);margin-left:auto;margin-right:auto;}

  /* ===== SECTION C: ONE type scale, defined once, end-of-sheet so it wins by source order =====
     Root cause of "sloppy in places": the base scale was redefined per step across four stacked
     layers, so the SAME element rendered at a different size on a different screen. Measured
     before: eyebrow 9px on steps 1-3 and 9.5px on step 4; title 23/23/21/24; the hero number
     32px beside the vial and 46px beside the syringe; its label 8.5px/600 then 11px/700. Every
     value below is a per-step selector so it out-specifies the older per-step rules. */
  .jny .step1 .eyebrow,.jny .step2 .eyebrow,.jny .step3 .eyebrow,.jny .step4 .eyebrow{
    font-size:9.5px;font-weight:500;letter-spacing:.3em;text-indent:.3em;}
  /* C1. One title size. 23px is the largest that keeps all five titles on ONE line down to a
     320px screen ("Where did you inject?" and "Seal it in your vault" are the long ones). */
  .jny .step1 .htitle,.jny .step2 .htitle,.jny .step3 .htitle,.jny .step4 .htitle{
    font-size:23px;font-weight:700;letter-spacing:.01em;}
  /* C3. One hero number. 36px is the largest single size that survives the WORST case in the
     narrower step-1 flank: that box is a fixed 76px and "144" mg/mL measures 69px at 36px,
     77px at 40px. Step 1's 22px charging size is untouched, so the ignite still reads. */
  .jny .card.step1.s1-ready .s1flank .rdn,.jny .s2flank .rdn{font-size:36px;letter-spacing:-.025em;}
  .jny .s1flank .rdl,.jny .s2flank .rdl{font-size:8.5px;font-weight:600;letter-spacing:.26em;text-indent:.26em;}
  /* C5. A unit symbol is a symbol, not a word: mg, mL, mg/mL, never MG, ML or MG/ML. The app was
     rendering both at once on the same screen (the chips and flanks uppercased, the syringe sizes
     and the notch pill natural). The letterspaced caps register stays, on WORDS, which are now
     written in caps in the markup where they belong. */
  .jny .step1 .chip .cu,.jny .s1flank .rdl,.jny .s2flank .rdl,.jny .s2carry .ct span,.jny .s3carry .ct span,.jny .s4l2{text-transform:none;}
  /* C4. nowrap does not wrap, it OVERFLOWS, and in the step-4 header it silently ATE the user's
     own data: with the longest compound name in the catalogue ("HGH 191AA (Somatropin)") the
     concentration was ellipsized by 4px at 430pt and 59px at 375pt, so "50 IU/mL" disappeared
     from an iPhone SE. Measured identical on the shipped build, so this is old, not new. The row
     is a wrapping lockup now: the dose count drops to its own centred line when the name is long
     and nothing is ever truncated. */
  .jny .s4card .s4top{flex-wrap:wrap;justify-content:center;row-gap:2px;overflow:visible;}
  /* every child sizes to its own content and refuses to shrink, so a row that will not fit WRAPS
     instead of squeezing one item until it clips (or, with overflow released, paints on top of
     its neighbour: that was the first attempt, and only the eye gate caught it). */
  .jny .s4card .s4top>*{flex:0 0 auto;min-width:0;overflow:visible;}
  .jny .s4l2{overflow:visible;text-overflow:clip;margin-top:0;}
  .jny{background:#06080b}.jny #boot{position:fixed;inset:0;z-index:100000;background:#06080b;transition:opacity .35s ease}.jny.app-ready #boot{opacity:0;pointer-events:none}
  /* Cross-document view transition opt-in, paired with index.html: the vault<->flow hop holds
     the old page's pixels through the document swap and cross-fades, killing the ~0.5s black
     gap filmed on the real device. The #boot cover still runs on engines without pagereveal. */
  @view-transition{navigation:auto}
  .jny ::view-transition-old(root){animation-duration:.28s}
  .jny ::view-transition-new(root){animation-duration:.28s}
  /* a view-transition arrival CUTS the boot cover to transparent; letting the 0.35s opacity
     transition run put a half-black card into the cross-fade (measured 0.56 on frame 1). */
  .jny.vt-arrive #boot{transition:none;opacity:0}

  /* ---- 21+ / terms acknowledgement on the seal. Only paints when .step4 carries .needcert,
     which the boot sets only when the acknowledgement has not been given yet. ---- */
  .jny .s4cert{display:none;align-items:flex-start;gap:9px;margin:0 auto 12px;max-width:330px;
    padding:0 6px;cursor:pointer;-webkit-tap-highlight-color:transparent;text-align:left;}
  .jny .step4.needcert .s4cert{display:flex;}
  .jny .s4cert .s4cbox{position:absolute;opacity:0;width:0;height:0;}
  .jny .s4cert .s4check{flex:none;width:19px;height:19px;margin-top:1px;border-radius:6px;position:relative;
    border:1.5px solid rgba(255,255,255,.34);background:rgba(255,255,255,.05);
    transition:background .16s ease,border-color .16s ease;}
  .jny .s4cert .s4cbox:checked + .s4check{border-color:transparent;
    background:linear-gradient(120deg,#22E0A0,#10C6E8 55%,#1296F2);}
  .jny .s4cert .s4cbox:checked + .s4check::after{content:"";position:absolute;left:6px;top:2px;
    width:5px;height:10px;border:solid #04121c;border-width:0 2.2px 2.2px 0;transform:rotate(45deg);}
  .jny .s4cert .s4cbox:focus-visible + .s4check{box-shadow:0 0 0 3px rgba(18,182,236,.35);}
  .jny .s4cert .s4ctext{font-size:11.5px;line-height:1.45;color:#8d99a5;}
  .jny .s4cert .s4ctext a{color:#37c9f0;text-decoration:underline;}
  /* the seal cannot fire until it is ticked. Its OWN class: s4disabled is already owned by the
     dose-total guard, which retoggles it on every render and would clobber a second writer. */
  .jny .s4ring.s4nocert{opacity:.4;pointer-events:none;}

  /* ---------- Step 4: the quiet "email me this card" offer ----------
     Added at the END on purpose: this file stacks override layers and an earlier rule would be
     overwritten by them. Restraint is the whole design here. One low-contrast underlined line,
     no box and no colour until the user asks for it, so it can never compete with the seal ring
     directly above it. flex:none keeps it out of the stage's height negotiation. */
  .jny .s4mail{flex:none;margin:9px auto 0;max-width:330px;width:100%;text-align:center;}
  /* No `font:` shorthand here. `font: 600 12px/1.3 inherit` is INVALID CSS: the family slot
     cannot take `inherit`, so the whole shorthand is dropped and the control silently falls
     back to the UA's own button font. Longhands inherit the family on their own. */
  .jny .s4mailgo{appearance:none;-webkit-appearance:none;background:none;border:0;padding:3px 6px;
    cursor:pointer;font-weight:600;font-size:12px;line-height:1.3;letter-spacing:.01em;
    color:#7e8b9b;text-decoration:underline;text-underline-offset:3px;
    text-decoration-color:rgba(126,139,155,.38);transition:color .2s;}
  .jny .s4mailgo:hover{color:#b9c6d4;}
  .jny .s4mail.open .s4mailgo{display:none;}
  .jny .s4mailform{display:flex;gap:6px;align-items:center;}
  /* MUST follow the display:flex rule. A class setting `display` outranks the UA sheet's
     [hidden]{display:none}, so without this the email field sits open on Step 4 at rest,
     which is the exact opposite of "collapsed until asked for". */
  .jny .s4mailform[hidden]{display:none;}
  /* 16px is not a taste call: anything smaller makes iOS Safari zoom the whole page on focus. */
  .jny .s4mailin{flex:1 1 auto;min-width:0;width:100%;height:36px;padding:0 11px;border-radius:10px;
    border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.05);color:#eaf2f8;
    font-weight:500;font-size:16px;line-height:1;outline:none;-webkit-appearance:none;appearance:none;}
  .jny .s4mailin::placeholder{color:#6d7a89;}
  .jny .s4mailin:focus{border-color:rgba(18,182,236,.55);background:rgba(255,255,255,.08);}
  .jny .s4mailsend{flex:none;width:36px;height:36px;border-radius:10px;border:0;cursor:pointer;
    display:grid;place-items:center;background:#1296F2;color:#fff;transition:opacity .2s;
    -webkit-appearance:none;appearance:none;}
  .jny .s4mailsend:disabled{opacity:.38;cursor:default;}
  .jny .s4mailsend svg{width:17px;height:17px;}
  /* An empty status line still reserves a line box plus its margin, which turned a one line
     offer into a 63px block on a stage that has no spare height. Measured, not guessed. */
  .jny .s4mailsaid:empty{display:none;}
  .jny .s4mailsaid{margin:5px 0 0;font-weight:400;font-size:11.5px;line-height:1.4;color:#8893a2;}
  .jny .s4mailsaid.good{color:#22E0A0;}
  .jny .s4mailsaid.bad{color:#FF9A9A;}

/* ---- host-page harness: the flow was written to own the viewport ---- */
.jny{position:relative;display:block;height:clamp(460px,72vh,660px);width:100%;margin:22px 0 26px;
  border-radius:22px;overflow:hidden;border:1px solid rgba(255,255,255,.09);
  background:radial-gradient(120% 80% at 50% -10%,#0d151d 0%,#06080b 62%);contain:paint}
.jny .wrap{position:absolute;inset:0;height:100%;width:100%;max-width:none;padding:0;margin:0}
.jny .topbar{display:none}
.jny .stage{position:absolute;inset:0;top:34px;overflow:hidden}
.jny .dots{position:absolute;top:13px;left:0;right:0;z-index:40}
.jny .dots .dot:nth-child(n+3){display:none}
.jny .disc{display:none}
.jny .s4nova,.jny #boot,.jny .vshafts{display:none}
.jny .track .slide:nth-child(n+3){visibility:hidden;pointer-events:none}
.jny #s2next,.jny .step2 .hint{display:none}
