/* Parix tools-hub — animated card illustrations.
 * DEMO SCOPE: only the tools listed in parix_tools_hub_viz() get one.
 * Revert: delete this file, its enqueue, and the parix_tools_hub_viz() call
 * inside parix_tools_hub_cards() in templates/template-tools-hub.php.
 * Added 2026-09-18. */

/* The illustration replaces the screenshot for the demo tools only. */
.pt .thumb.has-viz img,
.pt .thumb.has-viz .cover{display:none}

.pt .pxv{
  --beige:#FFF7ED; --or:#FF6B35; --or-deep:#E0551F;
  --trk:#FBD9C3; --edge:#F4D2BB; --ink:#1A1A22; --muted:#8A6A55;
  position:absolute; inset:0; overflow:hidden;
  background:var(--beige); color:var(--ink);
  padding:15px 15px 25px; box-sizing:border-box;
  display:flex; flex-direction:column; justify-content:center; gap:9px;
}
.pt .pxv *{box-sizing:border-box}
.pt .pxv__note{position:absolute; left:15px; bottom:8px; font-size:10px; line-height:1; color:var(--muted)}
.pt .pxv__fig{display:block; font-size:23px; font-weight:700; line-height:1; letter-spacing:-.035em}
.pt .pxv__lab{display:block; margin-top:4px; font-size:10.5px; line-height:1.2; color:var(--muted)}
.pt .pxv__row{display:flex; align-items:center; gap:10px}

/* Every animated part rests in its finished state and is pulled back to its
   start only while the card has not been seen yet, so a browser without the
   observer still shows a correct card. */

/* ---------- 1. ring + ticks (age / score) ---------- */
.pxv-ring{position:relative; flex:none; width:64px; height:64px}
.pxv-ring svg{width:100%; height:100%; transform:rotate(-90deg)}
.pxv-ring circle{fill:none; stroke-width:7}
.pxv-ring .trk{stroke:var(--trk)}
.pxv-ring .val{stroke:var(--or); stroke-linecap:round; stroke-dasharray:100; stroke-dashoffset:var(--off,22); transition:stroke-dashoffset 1.1s cubic-bezier(.2,.8,.2,1) .15s}
.pxv-ring__n{position:absolute; inset:0; display:grid; place-items:center; font-size:18px; font-weight:700; letter-spacing:-.03em}
.pxv-ticks{list-style:none; margin:0; padding:0; display:grid; gap:6px; font-size:11px}
.pxv-ticks span{display:flex; align-items:center; gap:6px; transition:opacity .3s ease, transform .3s ease; transition-delay:calc(.4s + var(--n)*.14s)}
.pxv-ticks span::before{content:""; flex:none; width:13px; height:13px; border-radius:50%; background:var(--or) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M2.2 5.2l1.9 1.9 3.8-4.2' fill='none' stroke='white' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/8px no-repeat}
.pt .tool:not(.is-viz-in) .pxv-ring .val{stroke-dashoffset:100}
.pt .tool:not(.is-viz-in) .pxv-ticks span{opacity:0; transform:translateX(-5px)}

/* ---------- 2. checklist ---------- */
.pxv-check{display:grid; gap:7px}
.pxv-check__r{display:grid; grid-template-columns:14px minmax(0,1fr); align-items:center; gap:8px; transition:opacity .35s ease, transform .35s ease; transition-delay:calc(.15s + var(--n)*.16s)}
.pxv-check__b{width:14px; height:14px; border-radius:4px; border:1.5px solid var(--or); background:var(--or) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M2.2 5.2l1.9 1.9 3.8-4.2' fill='none' stroke='white' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/8px no-repeat}
.pxv-check__l{height:7px; width:var(--w); border-radius:99px; background:var(--trk)}
.pt .tool:not(.is-viz-in) .pxv-check__r{opacity:0; transform:translateX(-6px)}

/* ---------- 3. bar chart ---------- */
.pxv-bars{display:flex; align-items:flex-end; gap:3px; height:44px}
.pxv-bars i{flex:1; height:var(--h); border-radius:2px 2px 0 0; background:var(--or); opacity:calc(.32 + var(--n)*.06); transform-origin:bottom; transition:transform .5s cubic-bezier(.2,.8,.2,1); transition-delay:calc(.15s + var(--n)*.05s)}
.pt .tool:not(.is-viz-in) .pxv-bars i{transform:scaleY(0)}

/* ---------- 4. document + download ---------- */
.pxv-doc{position:relative; display:flex; align-items:center; gap:12px}
.pxv-doc__p{position:relative; flex:none; width:58px; height:74px; border:1.5px solid var(--edge); border-radius:7px; background:#fff; padding:9px 8px; display:grid; gap:5px; align-content:start}
.pxv-doc__p i{display:block; height:5px; border-radius:99px; background:var(--trk); width:var(--w); transform-origin:left; transition:transform .45s cubic-bezier(.2,.8,.2,1); transition-delay:calc(.2s + var(--n)*.12s)}
.pxv-doc__p i:first-child{background:var(--or)}
.pxv-doc__a{display:grid; place-items:center; width:26px; height:26px; border-radius:50%; background:var(--or); transition:opacity .3s ease .75s, transform .3s ease .75s}
.pxv-doc__a svg{width:13px; height:13px; fill:none; stroke:#fff; stroke-width:2.1; stroke-linecap:round; stroke-linejoin:round}
.pt .tool:not(.is-viz-in) .pxv-doc__p i{transform:scaleX(0)}
.pt .tool:not(.is-viz-in) .pxv-doc__a{opacity:0; transform:scale(.4)}

/* ---------- 5. idea sparks ---------- */
.pxv-idea{display:grid; gap:7px}
.pxv-idea__r{display:grid; grid-template-columns:16px minmax(0,1fr); align-items:center; gap:8px; transition:opacity .35s ease, transform .35s ease; transition-delay:calc(.15s + var(--n)*.18s)}
.pxv-idea__s{width:16px; height:16px; fill:var(--or)}
.pxv-idea__l{height:7px; width:var(--w); border-radius:99px; background:var(--trk)}
.pt .tool:not(.is-viz-in) .pxv-idea__r{opacity:0; transform:translateY(6px)}

/* ---------- 6. line graph ---------- */
.pxv-line{position:relative}
.pxv-line svg{position:absolute; right:0; bottom:-4px; width:64%; height:auto; overflow:visible}
.pxv-line .area{fill:rgba(255,107,53,.16); transition:opacity .6s ease .9s}
.pxv-line .ln{fill:none; stroke:var(--or); stroke-width:2.5; stroke-linecap:round; stroke-linejoin:round; stroke-dasharray:1; stroke-dashoffset:0; transition:stroke-dashoffset 1.2s cubic-bezier(.3,.7,.2,1) .2s}
.pxv-line .dot{fill:#fff; stroke:var(--or); stroke-width:2.5; transition:opacity .3s ease 1.3s}
.pt .tool:not(.is-viz-in) .pxv-line .ln{stroke-dashoffset:1}
.pt .tool:not(.is-viz-in) .pxv-line .area,
.pt .tool:not(.is-viz-in) .pxv-line .dot{opacity:0}

/* ---------- 7. email compose ---------- */
.pxv-mail{display:flex; align-items:center; gap:12px}
.pxv-mail__e{position:relative; flex:none; width:62px; height:46px; border:1.5px solid var(--or); border-radius:7px; background:#fff; overflow:hidden}
.pxv-mail__e::after{content:""; position:absolute; left:50%; top:-1px; width:44px; height:44px; margin-left:-22px; border-left:1.5px solid var(--or); border-bottom:1.5px solid var(--or); transform:rotate(-45deg); transform-origin:center}
.pxv-mail__t{display:grid; gap:6px; flex:1; min-width:0}
.pxv-mail__t i{display:block; height:6px; border-radius:99px; background:var(--trk); width:var(--w); transform-origin:left; transition:transform .4s cubic-bezier(.2,.8,.2,1); transition-delay:calc(.2s + var(--n)*.14s)}
.pxv-mail__s{justify-self:start; margin-top:2px; padding:4px 9px; border-radius:99px; background:var(--or); color:#fff; font-size:10px; font-weight:600; line-height:1; transition:opacity .3s ease .8s, transform .3s ease .8s}
.pt .tool:not(.is-viz-in) .pxv-mail__t i{transform:scaleX(0)}
.pt .tool:not(.is-viz-in) .pxv-mail__s{opacity:0; transform:translateY(4px)}

/* ---------- 8. gap comparison ---------- */
.pxv-gap{display:grid; gap:8px; align-content:center}
.pxv-gap__r{display:grid; grid-template-columns:54px minmax(0,1fr) 26px; align-items:center; gap:7px; font-size:10.5px}
.pxv-gap__b{height:7px; border-radius:99px; background:var(--trk); overflow:hidden}
.pxv-gap__b b{display:block; height:100%; width:calc(var(--w)*100%); border-radius:inherit; background:var(--ink); transform-origin:left; transition:transform .8s cubic-bezier(.2,.8,.2,1) .25s}
.pxv-gap__r--them .pxv-gap__b b{background:var(--or); transition-delay:.42s}
.pxv-gap__v{font-weight:600; text-align:right}
.pxv-gap__m{justify-self:start; padding:4px 9px; border:1px solid var(--edge); border-radius:99px; background:#fff; font-size:10.5px; transition:opacity .3s ease 1s}
.pt .tool:not(.is-viz-in) .pxv-gap__b b{transform:scaleX(0)}
.pt .tool:not(.is-viz-in) .pxv-gap__m{opacity:0}

/* ---------- 9. chat bubbles ---------- */
.pxv-chat{display:grid; gap:6px; align-content:center}
.pxv-chat__b{max-width:74%; padding:7px 10px; border-radius:11px; font-size:10.5px; line-height:1.25; transition:opacity .35s ease, transform .35s ease; transition-delay:calc(.15s + var(--n)*.22s)}
.pxv-chat__b--in{justify-self:start; border-bottom-left-radius:3px; background:#fff; border:1px solid var(--edge)}
.pxv-chat__b--out{justify-self:end; border-bottom-right-radius:3px; background:var(--or); color:#fff}
.pxv-chat__d{display:inline-flex; gap:3px; vertical-align:middle}
.pxv-chat__d i{width:4px; height:4px; border-radius:50%; background:var(--or); animation:pxv-blink 1.1s infinite}
.pxv-chat__d i:nth-child(2){animation-delay:.18s}
.pxv-chat__d i:nth-child(3){animation-delay:.36s}
@keyframes pxv-blink{0%,60%,100%{opacity:.25} 30%{opacity:1}}
.pt .tool:not(.is-viz-in) .pxv-chat__b{opacity:0; transform:translateY(7px)}

/* ---------- 10. FAQ accordion ---------- */
.pxv-faq{display:grid; gap:6px; align-content:center}
.pxv-faq__r{border:1px solid var(--edge); border-radius:7px; background:#fff; padding:7px 9px; transition:opacity .35s ease, transform .35s ease; transition-delay:calc(.15s + var(--n)*.16s)}
.pxv-faq__q{display:flex; align-items:center; justify-content:space-between; gap:8px}
.pxv-faq__q i{display:block; height:6px; width:var(--w); border-radius:99px; background:var(--trk)}
.pxv-faq__q svg{flex:none; width:10px; height:10px; fill:none; stroke:var(--or); stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round}
.pxv-faq__r--open{border-color:var(--or)}
.pxv-faq__r--open .pxv-faq__q i{background:var(--or)}
.pxv-faq__r--open svg{transform:rotate(180deg)}
.pxv-faq__a{display:grid; gap:4px; margin-top:6px; overflow:hidden; transform-origin:top; transition:opacity .35s ease .7s, max-height .45s cubic-bezier(.2,.8,.2,1) .7s; max-height:30px}
.pxv-faq__a i{display:block; height:5px; width:var(--w); border-radius:99px; background:var(--trk)}
.pt .tool:not(.is-viz-in) .pxv-faq__r{opacity:0; transform:translateY(6px)}
.pt .tool:not(.is-viz-in) .pxv-faq__a{opacity:0; max-height:0; margin-top:0}

/* ---------- narrow cards ---------- */
@media (max-width:560px){
  .pt .pxv{padding:13px 13px 23px}
  .pxv-ring{width:56px; height:56px}
  .pxv-ring__n{font-size:16px}
  .pt .pxv__fig{font-size:20px}
}

@media (prefers-reduced-motion:reduce){
  .pt .pxv *{transition:none !important; animation:none !important}
  .pt .tool:not(.is-viz-in) .pxv-ring .val{stroke-dashoffset:22}
  .pt .tool:not(.is-viz-in) .pxv-ticks span,
  .pt .tool:not(.is-viz-in) .pxv-check__r,
  .pt .tool:not(.is-viz-in) .pxv-idea__r,
  .pt .tool:not(.is-viz-in) .pxv-chat__b,
  .pt .tool:not(.is-viz-in) .pxv-faq__r,
  .pt .tool:not(.is-viz-in) .pxv-doc__a,
  .pt .tool:not(.is-viz-in) .pxv-mail__s,
  .pt .tool:not(.is-viz-in) .pxv-gap__m,
  .pt .tool:not(.is-viz-in) .pxv-line .area,
  .pt .tool:not(.is-viz-in) .pxv-line .dot{opacity:1; transform:none}
  .pt .tool:not(.is-viz-in) .pxv-bars i,
  .pt .tool:not(.is-viz-in) .pxv-doc__p i,
  .pt .tool:not(.is-viz-in) .pxv-mail__t i,
  .pt .tool:not(.is-viz-in) .pxv-gap__b b{transform:none}
  .pt .tool:not(.is-viz-in) .pxv-line .ln{stroke-dashoffset:0}
  .pt .tool:not(.is-viz-in) .pxv-faq__a{opacity:1; max-height:30px; margin-top:6px}
}

/* =========================================================================
 * PART 2 (2026-09-18) - GSAP layer + shared primitives for tools 11-30.
 * When GSAP is on the page tools-hub-viz.js drives every tween and adds
 * .pxv-gsap here, which switches the CSS transitions off so the two never
 * fight over the same property. Without GSAP the CSS rules above and the
 * utilities below still run the whole thing on their own.
 * ===================================================================== */
.pt.pxv-gsap .pxv *{transition:none !important; animation:none !important}

/* ---------- utilities: any element can opt into one ---------- */
.pt .pxv-rise,.pt .pxv-pop,.pt .pxv-growx,.pt .pxv-growy,.pt .pxv-fade{transition:opacity .4s ease, transform .45s cubic-bezier(.2,.8,.2,1); transition-delay:calc(.12s + var(--n,0)*.09s)}
.pt .pxv-growx{transform-origin:left}
.pt .pxv-growy{transform-origin:bottom}
.pt .pxv-draw{stroke-dasharray:1; stroke-dashoffset:0; transition:stroke-dashoffset 1.1s cubic-bezier(.3,.7,.2,1) calc(.15s + var(--n,0)*.09s)}
.pt .tool:not(.is-viz-in) .pxv-rise{opacity:0; transform:translateY(8px)}
.pt .tool:not(.is-viz-in) .pxv-pop{opacity:0; transform:scale(.5)}
.pt .tool:not(.is-viz-in) .pxv-fade{opacity:0}
.pt .tool:not(.is-viz-in) .pxv-growx{transform:scaleX(0)}
.pt .tool:not(.is-viz-in) .pxv-growy{transform:scaleY(0)}
.pt .tool:not(.is-viz-in) .pxv-draw{stroke-dashoffset:1}

/* ---------- primitive: labelled rows ---------- */
.pxv-list{display:grid; gap:7px; align-content:center}
.pxv-list__r{display:grid; grid-template-columns:auto minmax(0,1fr) auto; align-items:center; gap:8px; font-size:10.5px}
.pxv-list__k{flex:none; width:15px; height:15px; border-radius:5px; background:var(--or); opacity:.9}
.pxv-list__k--soft{background:var(--trk)}
.pxv-list__l{height:7px; width:var(--w,100%); border-radius:99px; background:var(--trk)}
.pxv-list__l--on{background:var(--or)}
.pxv-list__v{font-weight:600; font-size:10px}

/* ---------- primitive: two columns compared ---------- */
.pxv-vs{display:grid; grid-template-columns:1fr auto 1fr; align-items:end; gap:8px; align-content:center}
.pxv-vs__c{display:grid; gap:5px; justify-items:center}
.pxv-vs__bar{width:100%; height:var(--h); min-height:8px; border-radius:5px 5px 0 0; background:var(--trk); transform-origin:bottom}
.pxv-vs__c--win .pxv-vs__bar{background:var(--or)}
.pxv-vs__n{font-size:11px; font-weight:700; letter-spacing:-.02em}
.pxv-vs__t{font-size:9.5px; color:var(--muted)}
.pxv-vs__x{align-self:center; font-size:9.5px; font-weight:600; color:var(--muted)}

/* ---------- primitive: white panel of lines ---------- */
.pxv-panel{position:relative; border:1.5px solid var(--edge); border-radius:8px; background:#fff; padding:9px 10px; display:grid; gap:6px; align-content:start}
.pxv-panel__h{display:flex; align-items:center; gap:6px; font-size:10px; font-weight:600; color:var(--or)}
.pxv-panel__h svg{width:11px; height:11px; fill:var(--or)}
.pxv-panel i{display:block; height:6px; width:var(--w,100%); border-radius:99px; background:var(--trk)}
/* ---------- stars + reply ---------- */
.pxv-stars{display:flex; gap:3px; margin-bottom:2px}
.pxv-stars svg{width:15px; height:15px; fill:var(--or)}
.pxv-reply{padding:7px 9px; border-radius:11px; border-bottom-left-radius:3px; background:#fff; border:1px solid var(--edge); font-size:10.5px; line-height:1.25}

/* ---------- headshot ---------- */
.pxv-face{display:flex; align-items:center; gap:12px}
.pxv-face__a{position:relative; flex:none; width:60px; height:60px; border-radius:50%; overflow:hidden; background:var(--trk)}
.pxv-face__a svg{position:absolute; left:50%; top:54%; width:44px; height:44px; margin:-22px 0 0 -22px; fill:var(--or); opacity:.9}
.pxv-face__a--raw{filter:blur(3px); opacity:.55}
.pxv-face__a--hd{box-shadow:0 0 0 2px var(--or), 0 0 0 5px var(--beige)}
.pxv-face__ar{font-size:14px; color:var(--or); font-weight:700}

/* ---------- background cut-out ---------- */
.pxv-cut{position:relative; height:78px; border-radius:8px; overflow:hidden; border:1.5px solid var(--edge); background:#fff}
.pxv-cut__bg{position:absolute; inset:0; background-image:linear-gradient(45deg,var(--trk) 25%,transparent 25%,transparent 75%,var(--trk) 75%),linear-gradient(45deg,var(--trk) 25%,transparent 25%,transparent 75%,var(--trk) 75%); background-size:12px 12px; background-position:0 0,6px 6px; transform-origin:right}
.pxv-cut__s{position:absolute; left:50%; bottom:0; width:40px; height:54px; margin-left:-20px}
.pxv-cut__s svg{width:100%; height:100%; fill:var(--or)}
.pxv-cut__w{position:absolute; top:0; bottom:0; width:2px; background:var(--or); box-shadow:0 0 10px 2px rgba(255,107,53,.5)}

/* ---------- gauge ---------- */
.pxv-gauge{position:relative; display:grid; justify-items:center}
.pxv-gauge svg{width:112px; height:60px; overflow:visible}
.pxv-gauge .trk{fill:none; stroke:var(--trk); stroke-width:9; stroke-linecap:round}
.pxv-gauge .val{fill:none; stroke:var(--or); stroke-width:9; stroke-linecap:round}
.pxv-gauge__n{margin-top:-14px; font-size:18px; font-weight:700; letter-spacing:-.03em}

/* ---------- radar ---------- */
.pxv-radar{position:relative; width:84px; height:84px; margin:0 auto; border-radius:50%; border:1.5px solid var(--edge); background:#fff}
.pxv-radar::before,.pxv-radar::after{content:""; position:absolute; border-radius:50%; border:1px solid var(--edge)}
.pxv-radar::before{inset:14px}
.pxv-radar::after{inset:28px}
.pxv-radar__s{position:absolute; inset:0; border-radius:50%; background:conic-gradient(from 0deg,rgba(255,107,53,.34),transparent 62deg); transform-origin:center}
.pxv-radar__d{position:absolute; width:8px; height:8px; margin:-4px 0 0 -4px; border-radius:50%; background:var(--or); left:var(--x); top:var(--y)}

/* ---------- funnel ---------- */
.pxv-funnel{position:relative; display:grid; gap:4px; justify-items:center}
.pxv-funnel i{display:block; height:12px; border-radius:3px; background:var(--or); opacity:calc(.9 - var(--n)*.16); width:var(--w); transform-origin:center}
.pxv-funnel__leak{position:absolute; right:14px; top:8px; display:grid; gap:4px; justify-items:center}
.pxv-funnel__leak b{display:block; width:6px; height:6px; border-radius:50%; background:var(--or); opacity:.55}

/* ---------- answer block ---------- */
.pxv-ans{display:grid; gap:7px; align-content:center}
.pxv-ans__q{display:flex; align-items:center; gap:6px; font-size:10.5px; font-weight:600}
.pxv-ans__q::before{content:"Q"; display:grid; place-items:center; flex:none; width:15px; height:15px; border-radius:4px; background:var(--trk); font-size:9px; font-weight:700; color:var(--or-deep)}
.pxv-ans__b{border-left:3px solid var(--or); border-radius:0 7px 7px 0; background:#fff; border-top:1px solid var(--edge); border-right:1px solid var(--edge); border-bottom:1px solid var(--edge); padding:8px 9px; display:grid; gap:5px}
.pxv-ans__b i{display:block; height:6px; width:var(--w); border-radius:99px; background:var(--trk)}
.pxv-ans__b i:first-child{background:var(--or)}

/* ---------- prompt blocks ---------- */
.pxv-blocks{display:flex; flex-wrap:wrap; gap:5px; align-content:center}
.pxv-blocks span{padding:5px 8px; border-radius:6px; font-size:9.5px; line-height:1; background:#fff; border:1px solid var(--edge); color:var(--muted)}
.pxv-blocks span.on{background:var(--or); border-color:var(--or); color:#fff; font-weight:600}

/* ---------- stacked pages ---------- */
.pxv-pages{position:relative; height:76px}
.pxv-pages i{position:absolute; left:calc(var(--n)*13px); top:calc(var(--n)*5px); width:52px; height:66px; border-radius:6px; background:#fff; border:1.5px solid var(--edge)}
.pxv-pages i:last-child{border-color:var(--or)}
.pxv-pages i::after{content:""; position:absolute; left:8px; right:8px; top:10px; height:4px; border-radius:99px; background:var(--trk)}

/* ---------- page wireframe ---------- */
.pxv-wire{display:grid; gap:5px; align-content:center}
.pxv-wire i{display:block; border-radius:4px; background:var(--trk); height:var(--h,10px)}
.pxv-wire i.on{background:var(--or)}
.pxv-wire__two{display:grid; grid-template-columns:1fr 1fr; gap:5px}

/* ---------- slogan words ---------- */
.pxv-slogan{display:flex; flex-wrap:wrap; gap:5px; align-content:center}
.pxv-slogan span{padding:5px 9px; border-radius:99px; font-size:10px; line-height:1; background:#fff; border:1px solid var(--edge)}
.pxv-slogan span.on{background:var(--or); border-color:var(--or); color:#fff; font-weight:600}

/* ---------- whatsapp ticks ---------- */
.pxv-chat__b--wa{background:#fff; border:1px solid var(--edge); color:var(--ink)}
.pxv-tick{display:inline-block; margin-left:5px; width:13px; height:9px; vertical-align:middle; fill:none; stroke:var(--or); stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round}
/* =========================================================================
 * PART 3 (2026-09-18) - primitives for tools 31-70. New components tag their
 * own elements with the .pxv-rise / .pxv-pop / .pxv-growx utilities, so the
 * GSAP rule table in tools-hub-viz.js needs no new selectors.
 * ===================================================================== */

/* ---------- before -> after, on one line ---------- */
.pxv-flow{display:flex; align-items:center; justify-content:center; gap:9px}
.pxv-arrow{flex:none; display:grid; place-items:center; font-size:15px; font-weight:700; line-height:1; color:var(--or)}

/* ---------- brand swatches ---------- */
.pxv-swatch{display:flex; gap:5px}
.pxv-swatch i{display:block; width:22px; height:22px; border-radius:6px; background:var(--c); box-shadow:inset 0 0 0 1px rgba(0,0,0,.06)}

/* ---------- price before / after ---------- */
.pxv-price{display:flex; align-items:baseline; gap:9px}
.pxv-price s{font-size:13px; color:var(--muted)}
.pxv-price b{font-size:22px; font-weight:700; letter-spacing:-.03em; color:var(--or)}

/* ---------- gif frames ---------- */
.pxv-gif{display:flex; align-items:center; gap:11px}
.pxv-gif__s{position:relative; flex:none; width:76px; height:58px; border:1.5px solid var(--edge); border-radius:7px; background:#fff; overflow:hidden}
.pxv-gif__s i{position:absolute; left:9px; top:33px; width:15px; height:15px; border-radius:50%; background:var(--or)}
.pxv-gif__f{display:grid; gap:4px}
.pxv-gif__f span{display:block; width:32px; height:16px; border:1.5px solid var(--edge); border-radius:4px; background:#fff}
.pxv-gif__f span.on{border-color:var(--or)}

/* ---------- framed image ---------- */
.pxv-frame{position:relative; display:flex; align-items:center; justify-content:center; gap:10px; height:74px}
.pxv-frame i{display:block; flex:none; width:var(--w); height:var(--h); border:1.5px solid var(--or); border-radius:6px; background:#fff}
.pxv-frame i.soft{border-color:var(--edge); filter:blur(2px); opacity:.75}
.pxv-frame__t{position:absolute; right:0; bottom:-2px; font-size:10px; font-weight:600; color:var(--or)}

/* ---------- logo mark ---------- */
.pxv-logo{display:flex; align-items:center; gap:10px}
.pxv-logo__m{flex:none; display:grid; place-items:center; width:34px; height:34px; border-radius:9px; background:var(--or)}
.pxv-logo__m svg{width:18px; height:18px; fill:#fff}
.pxv-logo__w{display:grid; gap:5px; flex:1; min-width:0}
.pxv-logo__w i{display:block; height:7px; width:var(--w); border-radius:99px; background:var(--trk)}

/* ---------- struck-out word + correction ---------- */
.pxv-fix{display:flex; flex-wrap:wrap; align-items:center; gap:6px; font-size:11px}
.pxv-fix s{color:var(--muted)}
.pxv-fix b{padding:3px 8px; border-radius:99px; background:var(--or); color:#fff; font-size:10px; font-weight:600}
/* =========================================================================
 * PART 4 (2026-09-18) - primitives for tools 71-80.
 * ===================================================================== */

/* ---------- a search result ---------- */
.pxv-serp{display:grid; gap:5px; padding:9px 10px; border:1.5px solid var(--edge); border-radius:8px; background:#fff}
.pxv-serp__u{font-size:9.5px; line-height:1; color:var(--muted)}
.pxv-serp__t{height:8px; width:var(--w,86%); border-radius:99px; background:var(--or)}
.pxv-serp i{display:block; height:6px; width:var(--w); border-radius:99px; background:var(--trk)}

/* ---------- generated password ---------- */
.pxv-pass{display:grid; gap:8px}
.pxv-pass__f{padding:8px 9px; border:1.5px solid var(--edge); border-radius:7px; background:#fff; font:600 12px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; letter-spacing:.1em; color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.pxv-pass__s{display:flex; gap:4px}
.pxv-pass__s i{flex:1; height:5px; border-radius:99px; background:var(--trk)}
.pxv-pass__s i.on{background:var(--or)}

/* ---------- QR code ---------- */
.pxv-qr{display:grid; grid-template-columns:repeat(7,1fr); gap:2px; width:72px; margin:0 auto; padding:6px; background:#fff; border:1.5px solid var(--edge); border-radius:7px}
.pxv-qr i{display:block; aspect-ratio:1; border-radius:1px; background:var(--trk)}
.pxv-qr i.on{background:var(--ink)}