
@keyframes uiIn{to{opacity:1;transform:none}}
@keyframes stepOn{to{opacity:1}}
@keyframes dotOn{to{background:var(--accent);border-color:var(--accent)}}
@keyframes shim{to{background-position:-200% 0}}
@keyframes gone{to{opacity:0}}
@keyframes grow{to{width:100%}}
@keyframes draw{to{stroke-dashoffset:0}}
@keyframes pulse{50%{box-shadow:0 0 0 5px rgba(63,125,102,.16),0 6px 16px -10px rgba(0,0,0,.3)}}
@keyframes strike{to{background-size:100% 1.5px}}
@keyframes pick{to{border-color:var(--accent);box-shadow:0 0 0 4px rgba(63,125,102,.14),0 14px 34px -20px rgba(0,0,0,.35)}}
@keyframes bar{to{width:var(--v)}}

/* designed compositions */
.compo{position:relative}
.compo .float{position:absolute;z-index:3;background:#fff;border-radius:8px;box-shadow:0 22px 50px -18px rgba(10,14,12,.55);padding:12px 14px;font-size:14px;color:#1b1b19;opacity:0;transform:translateY(12px);transition:opacity .7s ease 1.6s,transform .7s ease 1.6s}
.compo.in .float{opacity:1;transform:none}
.compo.in .float:nth-of-type(2){transition-delay:2.2s}
.compo .float small{display:block;font:600 11px var(--sans);letter-spacing:.04em;color:var(--accent);margin-bottom:3px}
@keyframes bob{50%{transform:translateY(-8px)}}
svg.stars{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
svg.stars line{stroke:rgba(250,250,249,.22);stroke-width:1;stroke-dasharray:300;stroke-dashoffset:300;animation:draw 2.4s ease forwards;animation-delay:var(--d)}
svg.stars circle{fill:rgba(250,250,249,.85);animation:tw 3.2s ease-in-out infinite;animation-delay:var(--d)}
@keyframes tw{50%{opacity:.35}}
.tcard{position:relative;border-radius:8px;overflow:hidden;aspect-ratio:16/10;display:flex;flex-direction:column;justify-content:flex-end;padding:1.1rem 1.2rem;color:var(--ivory)}
.tcard .n{font:600 12px var(--sans);letter-spacing:.06em;color:var(--sage-light);position:relative}
.tcard b{font:400 1.25rem/1.2 var(--serif);position:relative;margin-top:.2rem}
@media (prefers-reduced-motion:reduce){.fadein,.grid td span,.ctx li,.graph .nd,.red ins,.red .cm,.intv .pills span,.answer .steps li{opacity:1!important;transform:none!important}.grid td::before{display:none}.meas .track i{width:var(--v)}.red del{background-size:100% 1.5px}.graph line.e{stroke-dashoffset:0}}

/* vignettes: card graphics */
.vig{position:relative;aspect-ratio:4/3;border-radius:8px;overflow:hidden;display:grid;place-items:center;isolation:isolate}
.vig.twill{background:var(--sage) var(--twill) center/512px}
.vig::before{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(160deg,rgba(150,170,160,.18),rgba(14,17,16,.45))}
.vig .frag{position:relative;width:min(78%,300px);transition:transform .6s cubic-bezier(.2,.8,.2,1)}
a:hover .vig .frag,article:hover .vig .frag,.vig:hover .frag{transform:translateY(-4px) scale(1.02)}
.fc{background:#fbfbf9;color:#1b1b19;border-radius:7px;padding:16px 18px;box-shadow:0 26px 50px -22px rgba(8,12,10,.7),0 0 0 1px rgba(250,250,249,.4);font:14.5px/1.45 var(--sans);text-align:left}
.fc small{display:block;font:500 11.5px var(--sans);letter-spacing:0;color:#77756f;margin-bottom:8px}
.vsteps{list-style:none;margin:0;padding:0}.vsteps li{padding:4px 0 4px 18px;position:relative;opacity:.3}
.vsteps li::before{content:"";position:absolute;left:0;top:9px;width:8px;height:8px;border-radius:50%;border:1.4px solid #1b1b19;box-sizing:border-box}
.reveal.in .vsteps li,.vig.live .vsteps li{animation:stepOn .4s ease forwards;animation-delay:var(--d)}
.reveal.in .vsteps li::before,.vig.live .vsteps li::before{animation:dotOn .3s ease forwards;animation-delay:var(--d)}
.vrows{width:100%;border-collapse:collapse;font-size:12px}.vrows td{padding:5px 0;border-bottom:1px solid #eceae5}
.vrows td:last-child{text-align:right;color:var(--accent);font-weight:600}.vrows td span{opacity:0}
.reveal.in .vrows td span,.vig.live .vrows td span{animation:uiIn .4s ease forwards;animation-delay:var(--d)}
.vnodes{position:relative;height:200px}
.vnodes svg{position:absolute;inset:0;width:100%;height:100%;z-index:0}
.vnodes path{stroke:var(--sage-light);stroke-width:1.6;fill:none;stroke-dasharray:240;stroke-dashoffset:240}
.reveal.in .vnodes path,.vig.live .vnodes path{animation:draw 1.4s ease .3s forwards}
.vnodes .n{position:absolute;z-index:1;background:#fbfbf9;border-radius:5px;padding:7px 10px;font-size:12.5px;box-shadow:0 18px 30px -16px rgba(8,12,10,.7)}
.vnodes .n em{display:block;font:500 10.5px var(--sans);letter-spacing:0;color:#77756f;font-style:normal}
.vnodes .a{left:12px;top:30px}.vnodes .b{right:12px;top:92px;outline:2px solid var(--accent)}.vnodes .c{left:52px;top:146px}
.vred p{margin:0;font:13.5px/1.55 var(--serif)}
.vred del{color:#b23a26;text-decoration:none;background:linear-gradient(#b23a26,#b23a26) left 55%/0 1.4px no-repeat}
.reveal.in .vred del,.vig.live .vred del{animation:strike 1.2s ease .4s forwards}
.vred ins{color:#2d5f9a;opacity:0}.reveal.in .vred ins,.vig.live .vred ins{animation:uiIn .6s ease 1.6s forwards}
.vmem{list-style:none;margin:0;padding:0}.vmem li{padding:5px 0;border-bottom:1px solid #eceae5;opacity:0}
.reveal.in .vmem li,.vig.live .vmem li{animation:uiIn .4s ease forwards;animation-delay:var(--d)}
.vmeas .big{font:400 46px/1 var(--serif)}.vmeas .track{height:8px;background:#ecebe6;border-radius:4px;margin:10px 0 8px;overflow:hidden}
.vmeas .track i{display:block;height:100%;width:0;background:var(--accent);border-radius:4px}
.reveal.in .vmeas .track i,.vig.live .vmeas .track i{animation:bar 1.4s cubic-bezier(.2,.8,.2,1) .5s forwards}
.vmeas span{font-size:12px;color:#55554f}
.vpills{display:flex;flex-wrap:wrap;gap:6px}.vpills span{background:#eef2ee;border:1px solid #cfd6cf;border-radius:3px;padding:3px 8px;font-size:12px;opacity:0}
.reveal.in .vpills span,.vig.live .vpills span{animation:uiIn .4s ease forwards;animation-delay:var(--d)}
.vdep{display:flex;align-items:center;gap:10px;color:var(--ivory);font-size:12px}
.vdep .fc{flex:1;font:400 14px/1.3 var(--serif)}.vdep .fc.on{outline:2px solid var(--accent)}

.vig svg.stars{opacity:.55}
.vig .frag{width:min(84%,320px)}
.vig .frag{min-width:min(280px,84%)}
.vrows td{white-space:nowrap}
.vrows tr{opacity:0}.vrows tr td span{opacity:1}
.reveal.in .vrows tr,.vig.live .vrows tr{animation:uiIn .4s ease forwards;animation-delay:var(--d,.3s)}
.vrows.vx td:first-child{color:#8a8a84;font-size:11.5px}
.vrows.vx td:last-child{color:#1b1b19;font-weight:500}
.vok{display:flex;gap:6px;margin-top:10px}.vok span{font-size:12px;border:1px solid #cfcdc6;border-radius:4px;padding:3px 10px}
.vok span:first-child{background:var(--accent);border-color:var(--accent);color:#fff}
.vcite p{margin:0 0 10px;font:15px/1.5 var(--serif)}
.vcite sup{display:inline-grid;place-items:center;width:16px;height:16px;border-radius:50%;background:#1b1b19;color:#fff;font:600 9px var(--sans);margin-left:3px}
.vcite .src{font-size:12px;color:#55554f;border-left:2px solid var(--accent);padding-left:8px;opacity:0}
.reveal.in .vcite .src,.vig.live .vcite .src{animation:uiIn .5s ease .8s forwards}
.vcite .src b{color:var(--accent);margin-right:6px}
.vprec{list-style:none;margin:0;padding:0}.vprec li{display:flex;justify-content:space-between;padding:5px 0;border-bottom:1px solid #eceae5;opacity:0}
.vprec li em{font-style:normal;font-size:11.5px;color:#8a8a84}
.vprec li.new{color:var(--accent);font-weight:600}.vprec li.new em{color:var(--accent)}
.reveal.in .vprec li,.vig.live .vprec li{animation:uiIn .4s ease forwards;animation-delay:var(--d)}
.vrun{list-style:none;margin:0;padding:0}.vrun li{display:flex;justify-content:space-between;gap:12px;padding:6px 0;border-bottom:1px solid #eceae5;opacity:0;white-space:nowrap}
.vrun em{font:500 11.5px var(--sans);font-variant-numeric:tabular-nums;color:#8a8a84;font-style:normal}
.reveal.in .vrun li,.vig.live .vrun li{animation:uiIn .4s ease forwards;animation-delay:var(--d)}
@media (max-width:560px){.vig .frag{width:calc(100% - 32px);min-width:0}.vrows td,.vrun li{white-space:normal}.vrows td:last-child{padding-left:12px}
 .vred p{font-size:14px}}
.vrun li{display:grid;grid-template-columns:1fr;gap:2px;white-space:normal}
.vrun em{font-size:11px}
.vig.run .frag{width:min(88%,340px)}
.fc.wide{min-width:min(340px,92%)}
.vtab{border-collapse:collapse;font-size:12px;width:100%}
.vtab th{font:600 9.5px var(--sans);text-transform:uppercase;letter-spacing:.06em;color:#8a8a84;text-align:left;padding:0 6px 6px 0;border-bottom:1px solid #e4e2dc}
.vtab td{padding:6px 6px 6px 0;border-bottom:1px solid #eceae5;white-space:nowrap}
.vtab tr{opacity:0}.reveal.in .vtab tr,.vig.live .vtab tr{animation:uiIn .4s ease forwards;animation-delay:var(--d,.3s)}
.vtab tr:first-child{opacity:1}
.vtab td.hl{background:#eef2ee;color:var(--sage-deep);font-weight:600}
.vtab td em{display:inline-grid;place-items:center;width:14px;height:14px;border-radius:50%;background:var(--accent);color:#fff;font:600 8.5px var(--sans);font-style:normal;margin-left:4px;vertical-align:1px}
@media (max-width:820px){.plate .m-only .vig,.shot .m-only .vig{background:none;padding:1rem 0 2rem}.plate .m-only .vig::before,.shot .m-only .vig::before{display:none}}

.m-only{display:none}
@media (max-width:820px){.wwin .uifit{display:none}.wwin .m-only{display:block}}
/* round 5: fragments follow the Harvey grammar, flat white with a one-pixel hairline, no shadow, no constellation, no hover lift */
.fc,.vnodes .n{box-shadow:none;border:1px solid #e5e5e1;background:#fff}
.vig svg.stars{display:none}
a:hover .vig .frag,article:hover .vig .frag,.vig:hover .frag{transform:none}
.vrows.vsr td:first-child{white-space:normal;padding-right:10px}.vrows.vsr td:last-child{color:var(--mute);font-weight:500}
.vchat .q{background:#f4f3ef;border:1px solid #e8e6e1;border-radius:6px;padding:8px 10px;font-size:13px;margin:0 0 12px}.vchat p{font-size:13.5px;margin:4px 0 10px}.vchat sup{font-size:9px;background:#1b1b19;color:#fff;border-radius:50%;padding:0 4px;margin-left:2px}.vchat .src{font-size:11.5px;color:var(--mute);border-left:2px solid var(--accent);padding-left:8px;margin-top:5px}
.vig .fc.vchat p{font:400 14px/1.5 var(--sans);margin:4px 0 10px}
.m-only .vig.cite{aspect-ratio:auto;min-height:0;padding-top:1.6rem;padding-bottom:1.6rem}
/* round 7: the phone table fits its card; the node fragment sits on a canvas */
.vtab{table-layout:fixed}.vtab td{overflow:hidden;text-overflow:ellipsis}.vtab th:first-child,.vtab td:first-child{width:38%}
.vig.nodes .vnodes{background:#fff;border:1px solid #e5e5e1;border-radius:7px}
.vig.nodes .vnodes .n{border:1px solid #e5e5e1}
/* round 11: search tags on one line; the selected deployment card carries a full border and a check */
.vrows.vsr td:last-child{white-space:nowrap}
.vdep .fc.on{outline:none;border:1.5px solid var(--accent)!important;position:relative}
.vdep .fc.on::after{content:"";position:absolute;top:8px;right:8px;width:14px;height:14px;border-radius:50%;background:var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M4 7.2l2 2 4-4.4' fill='none' stroke='white' stroke-width='1.6'/%3E%3C/svg%3E") center/14px}

/* round 13: graph labels keep ink on every band; phone fragments sit on the plate with equal insets */
.vnodes .n{color:#1b1b19}
@media (max-width:820px){.plate .m-only .vig,.shot .m-only .vig{padding:0!important}}
