@font-face{font-family:DunbenSerif;src:url("../assets/fonts/LibertinusSans-Regular.ttf") format("truetype");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:DunbenSerif;src:url("../assets/fonts/LibertinusSans-Bold.ttf") format("truetype");font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:DunbenSans;src:url("../assets/fonts/DMSans-VariableFont_opsz,wght.ttf") format("truetype");font-weight:100 1000;font-style:normal;font-display:swap}
@font-face{font-family:DunbenDisplay;src:url("../assets/fonts/Solare-Regular.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:Syncopate;src:url("../assets/vendor/codrops-r3f-mirrors/syncopate.woff") format("woff");font-weight:700;font-style:normal;font-display:swap}

:root{--ink:#121314;--warm:#f6f1e8;--paper:#fbfaf7;--blue:#164cdf;--orange:#ff8f29;--cyan:#cde9f6;--muted:#687078;--line:rgba(24,25,28,.17);--serif:DunbenDisplay,DunbenSerif,"Dunben Serif SC",Georgia,serif;--sans:DunbenSans,"Dunben Sans SC",Helvetica,Arial,sans-serif;--ease:cubic-bezier(.16,1,.3,1)}
*{box-sizing:border-box}
/* scroll-behavior MUST stay `auto`. ScrollTrigger positions a pinned section by
   writing scrollTop directly; with CSS smooth scrolling those writes get
   animated instead of applied, so the pin and the real scroll position drift
   apart — that drift is what exposed the page surface as a white flash on pin
   enter/exit and left a blank band after a reload. In-page anchors keep their
   easing via an explicit scrollTo({behavior:'smooth'}) in script.js. */
/* The root element's background paints the browser canvas — the area outside the
   document box. ScrollTrigger changes the document height whenever it refreshes
   or releases the pin, and for the frame where the height is momentarily below
   the current scroll position the browser fills the exposed strip with that
   canvas colour. With --paper there that strip read as a white flash at the
   bottom of the page.
   Every primary Applied AI surface is now opaque dark, so making the canvas
   --ink means any such frame is dark on dark and invisible. Each section paints
   the document box directly; no shared background state is involved. */
html{scroll-behavior:auto;background:var(--ink)}
body{margin:0;background:var(--ink);color:var(--ink);font-family:var(--sans);font-size:16px;line-height:1.55;overflow-x:hidden}
body.menu-is-open{overflow:hidden}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit}
.skip-link{position:fixed;z-index:100;top:12px;left:12px;padding:8px 12px;background:var(--blue);color:#fff;transform:translateY(-150%);transition:transform .25s ease}
.skip-link:focus{transform:translateY(0)}
.site-header{position:fixed;z-index:50;top:0;left:0;width:100%;padding:25px clamp(22px,3.5vw,52px);display:flex;align-items:flex-start;justify-content:space-between;pointer-events:none;mix-blend-mode:difference;color:#fff;transition:color .3s ease}
.site-header.is-compact{padding-top:18px}
.wordmark{display:flex;flex-direction:column;gap:0;font-family:var(--sans);font-weight:700;letter-spacing:.08em;line-height:.92;pointer-events:auto}
.wordmark__top{font-size:clamp(16px,1.4vw,22px)}.wordmark__bottom{font-size:clamp(10px,.82vw,13px);letter-spacing:.24em;padding-left:1px;margin-top:3px}
.header-status{display:flex;align-items:center;gap:8px;font-size:11px;letter-spacing:.12em;text-transform:uppercase;margin-right:58px;margin-top:3px}.status-dot{display:block;width:7px;height:7px;border-radius:50%;background:var(--orange)}
.menu-toggle{position:absolute;top:22px;right:clamp(22px,3.5vw,52px);width:34px;height:30px;border:0;background:transparent;display:flex;flex-direction:column;justify-content:center;gap:7px;padding:5px;cursor:pointer;pointer-events:auto}.menu-toggle span{display:block;width:100%;height:2px;background:currentColor;transform-origin:center;transition:transform .65s var(--ease)}.menu-is-open .menu-toggle span:first-child{transform:translateY(4.5px) rotate(45deg)}.menu-is-open .menu-toggle span:last-child{transform:translateY(-4.5px) rotate(-45deg)}
.site-menu{position:fixed;z-index:40;inset:0;background:var(--ink);color:var(--warm);clip-path:inset(0 0 100% 0);pointer-events:none;transition:clip-path .8s var(--ease);overflow:hidden}.site-menu.is-open{clip-path:inset(0);pointer-events:auto}.site-menu__inner{position:relative;z-index:2;height:100%;padding:clamp(100px,12vw,160px) clamp(24px,7vw,100px) clamp(30px,5vw,72px);display:flex;flex-direction:column;justify-content:space-between}.eyebrow{margin:0;font-size:11px;line-height:1.2;letter-spacing:.12em;text-transform:uppercase;font-weight:650}.eyebrow--light{color:rgba(246,241,232,.62)}.site-menu__list{list-style:none;margin:clamp(28px,4vw,54px) 0 0;padding:0;display:flex;flex-direction:column;align-items:flex-start;gap:clamp(14px,2.3vw,32px)}.site-menu__list a{font-family:var(--serif);font-size:clamp(56px,8vw,126px);line-height:.82;display:block;transform:translateY(110%);opacity:0;transition:transform .75s var(--ease),opacity .6s ease,color .2s ease}.site-menu.is-open .site-menu__list a{transform:translateY(0);opacity:1}.site-menu.is-open .site-menu__list li:nth-child(1) a{transition-delay:.12s}.site-menu.is-open .site-menu__list li:nth-child(2) a{transition-delay:.2s}.site-menu.is-open .site-menu__list li:nth-child(3) a{transition-delay:.28s}.site-menu.is-open .site-menu__list li:nth-child(4) a{transition-delay:.36s}.site-menu__list a:hover,.site-menu__list a:focus-visible,.site-menu__list a.is-active{color:var(--orange)}.site-menu__meta{display:flex;align-items:flex-end;justify-content:space-between;gap:30px;max-width:840px;color:rgba(246,241,232,.68);font-size:14px;transform:translateY(16px);opacity:0;transition:transform .7s var(--ease),opacity .5s ease}.site-menu.is-open .site-menu__meta{transform:translateY(0);opacity:1;transition-delay:.5s}.text-link{display:inline-flex;align-items:center;gap:14px;border-bottom:1px solid currentColor;padding:0 0 8px;font-size:14px;transition:color .2s ease,gap .3s var(--ease)}.text-link:hover,.text-link:focus-visible{color:var(--blue);gap:22px}.text-link--light:hover,.text-link--light:focus-visible{color:#fff}.menu-orbit{position:absolute;right:7vw;top:15vh;width:min(55vw,760px);height:min(70vh,760px);border:1px solid rgba(246,241,232,.15);border-radius:50%;transform:rotate(-21deg)}.menu-orbit__ring{position:absolute;border:1px solid rgba(246,241,232,.13);border-radius:50%;inset:12%;transform:rotate(42deg)}.menu-orbit__ring--two{inset:27%;transform:rotate(-57deg)}.menu-orbit__core{position:absolute;width:clamp(60px,8vw,120px);height:clamp(60px,8vw,120px);border-radius:50%;background:var(--blue);top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 22px rgba(22,76,223,.12)}
.section-shell{position:relative;padding:clamp(104px,13vw,190px) clamp(22px,7vw,100px);display:grid;grid-template-columns:minmax(230px,.9fr) minmax(300px,1.1fr);column-gap:clamp(40px,9vw,150px);row-gap:clamp(48px,8vw,110px);overflow:hidden}.section-shell--ink{background:var(--ink);color:var(--warm)}
.hero{min-height:100svh;align-items:center;padding-top:clamp(132px,13vw,190px);padding-bottom:clamp(70px,8vw,120px);grid-template-columns:minmax(320px,.92fr) minmax(400px,1.08fr);background:var(--paper)}.hero__copy{position:relative;z-index:2;max-width:650px}.hero__title,.section-heading h2{font-family:var(--serif);font-weight:400;letter-spacing:-.055em;line-height:.9;margin:25px 0 36px}.hero__title{font-size:clamp(65px,8.5vw,150px)}.hero__title em,.section-heading h2 em{font-style:normal;color:var(--blue)}.hero__intro{max-width:390px;font-size:clamp(18px,1.65vw,25px);line-height:1.4;margin:0}.circle-link{position:relative;display:flex;align-items:center;justify-content:center;flex-direction:column;margin-top:clamp(40px,6vw,78px);width:clamp(118px,10vw,160px);height:clamp(118px,10vw,160px);border:1px solid var(--ink);border-radius:50%;font-size:12px;line-height:1.2;letter-spacing:.07em;text-transform:uppercase;transition:background .3s ease,color .3s ease,transform .5s var(--ease)}.circle-link:hover,.circle-link:focus-visible{background:var(--blue);color:#fff;transform:rotate(-8deg)}.circle-link__arrow{font-size:20px;margin-top:12px}.hero__diagram{position:relative;min-height:min(650px,75vh);background:var(--ink);color:var(--warm);overflow:hidden}.diagram-grid{position:absolute;inset:0;background-image:linear-gradient(rgba(246,241,232,.08) 1px,transparent 1px),linear-gradient(90deg,rgba(246,241,232,.08) 1px,transparent 1px);background-size:50px 50px;mask-image:linear-gradient(120deg,transparent 0%,black 28%,black 100%)}.diagram-note{position:absolute;top:28px;right:32px;color:rgba(246,241,232,.56);font-size:11px;text-transform:uppercase;letter-spacing:.12em}.diagram-line{position:absolute;height:1px;background:var(--orange);transform-origin:left center;opacity:.85}.diagram-line--one{width:57%;top:43%;left:20%;transform:rotate(-17deg)}.diagram-line--two{width:47%;top:59%;left:38%;transform:rotate(25deg);background:var(--blue)}.diagram-node{position:absolute;display:flex;flex-direction:column;gap:4px;width:clamp(124px,14vw,200px);height:clamp(124px,14vw,200px);justify-content:center;align-items:center;border-radius:50%;border:1px solid rgba(246,241,232,.35);background:rgba(24,25,28,.82);backdrop-filter:blur(8px);transition:transform .6s var(--ease),border-color .3s ease}.diagram-node:hover{transform:scale(1.07);border-color:var(--orange)}.diagram-node__index{color:var(--orange);font-size:11px;letter-spacing:.1em}.diagram-node strong{font-family:var(--serif);font-weight:400;font-size:clamp(21px,2.4vw,38px);line-height:1}.diagram-node small{color:rgba(246,241,232,.56);font-size:10px;letter-spacing:.08em}.diagram-node--method{left:9%;top:32%}.diagram-node--tool{left:39%;top:48%}.diagram-node--product{right:7%;top:68%}.diagram-spark{position:absolute;border-radius:50%;filter:blur(1px)}.diagram-spark--blue{width:clamp(110px,14vw,210px);height:clamp(110px,14vw,210px);background:var(--blue);opacity:.78;right:-30px;top:-24px}.diagram-spark--orange{width:clamp(58px,7vw,96px);height:clamp(58px,7vw,96px);background:var(--orange);left:47%;top:18%;opacity:.9}.diagram-spark--small{width:12px;height:12px;background:var(--cyan);left:21%;bottom:18%}.diagram-caption{position:absolute;left:28px;bottom:25px;color:rgba(246,241,232,.62);font-size:11px;letter-spacing:.1em;text-transform:uppercase}
.section-heading h2{font-size:clamp(56px,7.7vw,130px);margin:18px 0 0}.section-heading--light h2 em{color:var(--orange)}.overview__copy,.method__copy,.tool__copy,.products__copy,.playground__copy,.closing__copy{max-width:560px}.lede{font-size:clamp(20px,2vw,30px);line-height:1.32;margin:0 0 22px}.overview__copy p:not(.lede),.method__copy p:not(.lede),.tool__copy p:not(.lede),.products__copy p:not(.lede),.playground__copy p:not(.lede),.closing__copy p:not(.lede){max-width:500px;color:var(--muted)}.section-shell--ink .method__copy p:not(.lede),.section-shell--ink .playground__copy p:not(.lede){color:rgba(246,241,232,.65)}.overview__copy .lede{color:var(--ink)}.method__copy .lede,.playground__copy .lede{color:var(--warm)}

.method{grid-template-columns:minmax(230px,.8fr) minmax(300px,1.2fr)}.workflow-list{grid-column:1 / -1;display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.workflow-card{border-top:1px solid rgba(246,241,232,.3);padding:21px 0 0;min-height:260px;transition:transform .4s var(--ease),border-color .3s ease}.workflow-card:hover{transform:translateY(-8px);border-color:var(--orange)}.workflow-card__top{display:flex;justify-content:space-between;gap:20px;font-size:11px;text-transform:uppercase;letter-spacing:.1em;color:rgba(246,241,232,.55)}.workflow-card h3{font-family:var(--serif);font-size:clamp(36px,4vw,66px);font-weight:400;line-height:.9;margin:58px 0 13px;color:var(--warm)}.workflow-card p{font-size:14px;color:rgba(246,241,232,.63);margin:0;max-width:220px}.workflow-card__path{display:flex;align-items:center;gap:10px;margin-top:48px;font-size:10px;color:rgba(246,241,232,.6);text-transform:uppercase;letter-spacing:.08em}.workflow-card__path i{width:17px;height:1px;background:var(--orange);display:block;position:relative}.workflow-card__path i:after{content:"";position:absolute;right:0;top:-2px;width:5px;height:5px;border-top:1px solid var(--orange);border-right:1px solid var(--orange);transform:rotate(45deg)}
.tool{grid-template-columns:minmax(230px,.8fr) minmax(300px,1.2fr)}.tool-stack{grid-column:1 / -1;position:relative;display:grid;grid-template-columns:repeat(5,1fr);gap:12px;padding:28px 0 48px}.tool-stack__rail{position:absolute;left:5%;right:5%;top:78px;height:1px;background:var(--blue);z-index:0}.tool-stack__rail span{position:absolute;width:7px;height:7px;background:var(--blue);border-radius:50%;top:-3px}.tool-stack__rail span:nth-child(1){left:0}.tool-stack__rail span:nth-child(2){left:25%}.tool-stack__rail span:nth-child(3){left:50%}.tool-stack__rail span:nth-child(4){left:75%}.tool-stack__rail span:nth-child(5){right:0}.tool-node{position:relative;z-index:1;min-height:270px;border:1px solid var(--line);padding:20px 18px;display:flex;flex-direction:column;background:var(--paper);color:var(--ink);transition:transform .5s var(--ease),background .3s ease,color .3s ease,border-color .3s ease}.tool-node:hover{transform:translateY(-10px);background:var(--blue);color:#fff;border-color:var(--blue)}.tool-node__index{font-size:11px;color:var(--blue)}.tool-node:hover .tool-node__index{color:rgba(255,255,255,.7)}.tool-node h3{font-family:var(--serif);font-size:clamp(24px,2.7vw,43px);font-weight:400;line-height:.95;margin:56px 0 16px}.tool-node p{font-size:13px;color:var(--muted);line-height:1.45;margin:0}.tool-node:hover p{color:rgba(255,255,255,.75)}.tool-node b{font-size:28px;font-weight:300;margin-top:auto;align-self:flex-end}.tool-stack__caption{position:absolute;bottom:0;left:0;font-size:11px;text-transform:uppercase;letter-spacing:.1em;color:var(--muted)}
.transition-band{background:var(--blue);color:#fff;padding:clamp(72px,9vw,130px) clamp(22px,7vw,100px)}.transition-band__inner{max-width:1500px;margin:auto}.transition-path{display:flex;align-items:center;gap:clamp(12px,2.2vw,36px);flex-wrap:wrap;font-family:var(--serif);font-size:clamp(37px,5vw,88px);line-height:.9;margin:34px 0 48px}.transition-path i{height:1px;width:clamp(26px,4vw,72px);background:rgba(255,255,255,.6);position:relative}.transition-path i:after{content:"";position:absolute;right:0;top:-4px;width:8px;height:8px;border-top:1px solid #fff;border-right:1px solid #fff;transform:rotate(45deg)}.transition-path strong{font-weight:400;color:var(--orange)}.transition-band__copy{max-width:470px;color:rgba(255,255,255,.78);margin:0;font-size:18px}
.products{grid-template-columns:minmax(230px,.8fr) minmax(300px,1.2fr)}.products__statement{font-family:var(--serif);font-size:clamp(24px,2.5vw,38px);line-height:1;margin:28px 0;color:var(--blue)!important}.product-group,.product-group--experiments{grid-column:1 / -1}.product-group__heading{display:flex;justify-content:space-between;gap:20px;padding-bottom:14px;border-bottom:1px solid var(--line);font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:var(--muted)}.featured-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;padding-top:14px}.product-card{display:flex;flex-direction:column;min-width:0;background:var(--paper);border:1px solid var(--line);transition:transform .5s var(--ease),box-shadow .4s ease}.product-card:hover,.product-card:focus-visible{transform:translateY(-8px);box-shadow:0 14px 25px rgba(24,25,28,.08)}.product-card--wide{grid-column:span 1}.product-card__visual{position:relative;overflow:hidden;min-height:240px;background:#ddd}.product-card__body{padding:20px 18px 22px}.product-card__body>span:first-child{font-size:10px;text-transform:uppercase;letter-spacing:.1em;color:var(--muted)}.product-card__body h3{font-family:var(--serif);font-size:clamp(26px,2.5vw,41px);font-weight:400;line-height:.95;margin:27px 0 12px}.product-card__body p{font-size:13px;line-height:1.5;color:var(--muted);margin:0 0 25px}.product-card__link{font-size:12px;color:var(--blue);border-bottom:1px solid currentColor;padding-bottom:5px}.visual-label{position:absolute;z-index:3;left:16px;bottom:16px;color:rgba(255,255,255,.68);font-size:9px;letter-spacing:.1em;text-transform:uppercase}.visual-inspiration{background:linear-gradient(130deg,#163dd0 0 40%,#f3b8d1 40% 68%,#ff8f29 68%)}.visual-inspiration:after{content:"";position:absolute;width:210px;height:210px;border:1px solid rgba(255,255,255,.7);border-radius:50%;left:25%;top:-28%;transform:rotate(30deg)}.visual-window{position:absolute;background:rgba(255,255,255,.88);width:39%;height:42%;box-shadow:12px 12px 0 rgba(24,25,28,.15)}.visual-window--a{left:11%;top:17%;transform:rotate(-8deg)}.visual-window--b{right:11%;top:27%;transform:rotate(8deg);background:#cde9f6}.visual-window--c{left:31%;bottom:10%;transform:rotate(2deg);width:35%;height:31%;background:#ff8f29}.visual-knowledge{background:#0f1013}.knowledge-line{position:absolute;left:14%;right:14%;height:1px;background:rgba(246,241,232,.35);transform-origin:left}.knowledge-line:nth-child(1){top:27%;transform:rotate(18deg)}.knowledge-line:nth-child(2){top:50%;transform:rotate(-8deg)}.knowledge-line:nth-child(3){top:70%;transform:rotate(27deg)}.knowledge-node{position:absolute;width:34px;height:34px;border-radius:50%;border:1px solid var(--orange);background:var(--ink)}.knowledge-node--a{left:18%;top:20%}.knowledge-node--b{right:20%;top:43%;background:var(--blue);border-color:var(--blue)}.knowledge-node--c{left:42%;bottom:15%;border-color:var(--cyan);background:var(--cyan)}.visual-operations{background:linear-gradient(160deg,#f0efe9,#b9e7f1)}.ops-chart{position:absolute;bottom:29%;left:16%;width:57%;height:3px;background:var(--ink);transform:rotate(-23deg);transform-origin:left}.ops-chart:after{content:"";position:absolute;right:-2px;top:-4px;width:10px;height:10px;border-radius:50%;background:var(--blue)}.ops-chart--two{left:32%;bottom:43%;width:44%;transform:rotate(11deg);background:var(--blue)}.ops-chart--three{left:28%;bottom:18%;width:52%;transform:rotate(-4deg);background:var(--orange)}.ops-cursor{position:absolute;right:17%;top:17%;font-size:34px;color:var(--blue)}.visual-payments{background:var(--ink);color:#fff}.payment-orbit{position:absolute;width:190px;height:96px;border:1px solid var(--blue);border-radius:50%;left:18%;top:30%;transform:rotate(28deg)}.payment-orbit--two{width:144px;height:144px;left:31%;top:19%;border-color:var(--orange);transform:rotate(48deg)}.payment-core{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:46px;height:46px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--orange);font-family:var(--serif);font-size:27px;color:var(--ink)}.payment-tag{position:absolute;left:17px;bottom:16px;color:rgba(255,255,255,.55);font-size:9px;letter-spacing:.1em}.experiment-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;padding-top:14px}.experiment-card{border:1px solid var(--line);background:var(--paper);display:grid;grid-template-columns:64px 1fr auto;align-items:center;gap:14px;text-align:left;padding:10px 14px 10px 10px;cursor:pointer;transition:background .3s ease,color .3s ease,transform .4s var(--ease)}.experiment-card:hover,.experiment-card:focus-visible{background:var(--ink);color:var(--warm);transform:translateY(-5px)}.experiment-card__visual{height:64px;width:64px;display:flex;align-items:center;justify-content:center;font-family:var(--serif);font-size:35px}.experiment-card__visual--dream{background:#d6c5ed;color:var(--blue)}.experiment-card__visual--pet{background:#ffb267;color:var(--ink)}.experiment-card__visual--koi{background:#ccede7;color:#137c91}.experiment-card__visual--cards{background:#c9d2ff;color:var(--blue)}.experiment-card b{display:block;font-size:13px;font-weight:500}.experiment-card small{display:block;color:var(--muted);font-size:10px;margin-top:3px}.experiment-card:hover small{color:rgba(246,241,232,.58)}.experiment-card i{font-style:normal;color:var(--blue)}.experiment-card:hover i{color:var(--orange)}
.playground{grid-template-columns:minmax(230px,.8fr) minmax(300px,1.2fr)}.playground-wall{grid-column:1 / -1;display:grid;grid-template-columns:1.15fr .75fr 1fr;grid-template-rows:220px 160px 220px;gap:10px;min-height:610px}.visual-tile{position:relative;border:0;padding:0;overflow:hidden;cursor:pointer;background:#282a2e;transition:transform .6s var(--ease),filter .4s ease}.visual-tile:hover,.visual-tile:focus-visible{transform:scale(.985);filter:brightness(1.15)}.visual-tile--a{grid-row:span 2;background:#112236}.visual-tile--b{background:var(--orange)}.visual-tile--c{grid-row:span 2;background:#152855}.visual-tile--d{background:#d8e4ff}.visual-tile--e{background:#3e8b99}.visual-tile--f{background:#27262b;grid-column:span 2}.tile-art{position:absolute;inset:0}.tile-art--liquid{background:radial-gradient(ellipse at 30% 50%,#84e5e1 0 14%,transparent 15%),radial-gradient(ellipse at 65% 45%,#164cdf 0 21%,transparent 22%),radial-gradient(ellipse at 48% 75%,#ff8f29 0 14%,transparent 15%),linear-gradient(120deg,#0c1728,#17305a 48%,#141b35)}.tile-art--liquid:after{content:"";position:absolute;inset:16% 22%;border:1px solid rgba(255,255,255,.65);border-radius:47% 53% 38% 62%;transform:rotate(28deg);animation:float 8s ease-in-out infinite}.tile-art--type{font-family:var(--serif);font-size:clamp(90px,15vw,210px);line-height:1;color:var(--ink);display:flex;align-items:center;justify-content:center;mix-blend-mode:multiply}.tile-art--type:after{content:"/";position:absolute;right:10%;bottom:-25%;font-family:var(--sans);font-size:180px;color:#fbc1aa}.tile-art--particles{background:radial-gradient(circle at 40% 30%,#ff8f29 0 4px,transparent 5px),radial-gradient(circle at 73% 25%,#cde9f6 0 5px,transparent 6px),radial-gradient(circle at 34% 70%,#164cdf 0 6px,transparent 7px),radial-gradient(circle at 72% 73%,#ff8f29 0 3px,transparent 4px);background-size:80px 70px,100px 90px,120px 100px,100px 80px;animation:drift 12s linear infinite}.tile-art--particles i{position:absolute;width:1px;height:100%;left:35%;background:linear-gradient(transparent,rgba(255,255,255,.4),transparent);transform:rotate(22deg)}.tile-art--particles i:nth-child(2){left:55%;transform:rotate(-18deg)}.tile-art--particles i:nth-child(3){left:72%;transform:rotate(34deg)}.tile-art--portrait{background:radial-gradient(circle at 54% 32%,#f4c9b2 0 13%,transparent 14%),radial-gradient(ellipse at 54% 62%,#222938 0 20%,transparent 21%),linear-gradient(145deg,#e8f5f4,#bfd9da 55%,#f08e67)}.tile-art--portrait:after{content:"";position:absolute;left:38%;top:12%;width:31%;height:30%;border:1px solid rgba(24,25,28,.42);border-radius:50%;transform:rotate(-20deg)}.tile-art--motion{background:linear-gradient(90deg,#cde9f6 0 22%,transparent 22% 28%,#ff8f29 28% 52%,transparent 52% 58%,#164cdf 58% 80%,transparent 80%)}.tile-art--motion i{position:absolute;left:20%;top:25%;width:45%;height:50%;border:2px solid var(--ink);border-radius:50%;transform:rotate(32deg)}.tile-art--motion i:nth-child(2){left:33%;top:14%;transform:rotate(-20deg)}.tile-art--motion i:nth-child(3){left:49%;top:36%;transform:rotate(59deg)}.tile-art--grid{background-image:linear-gradient(rgba(246,241,232,.22) 1px,transparent 1px),linear-gradient(90deg,rgba(246,241,232,.22) 1px,transparent 1px);background-size:35px 35px;transform:perspective(300px) rotateX(42deg) scale(1.25);transform-origin:center bottom}.tile-art--grid:after{content:"INTERACTIVE VISUALS";position:absolute;inset:0;display:flex;justify-content:center;align-items:center;font-size:11px;letter-spacing:.15em;color:var(--orange);transform:rotateX(-42deg)}.tile-meta{position:absolute;z-index:2;left:16px;bottom:14px;color:rgba(255,255,255,.72);font-size:10px;letter-spacing:.1em;text-transform:uppercase}.visual-tile--b .tile-meta,.visual-tile--d .tile-meta{color:rgba(24,25,28,.65)}
.closing{min-height:85svh;align-items:start;grid-template-columns:minmax(300px,1fr) minmax(320px,1fr);column-gap:clamp(40px,9vw,150px)}.closing .section-heading{grid-column:1}.closing .section-heading h2{margin-top:0}.closing__copy{grid-column:2;padding-top:0}.closing__statement{font-family:var(--serif);font-size:clamp(25px,2.7vw,42px);line-height:1.08;color:var(--ink)!important;margin:45px 0 35px!important}.closing__actions{display:flex;flex-direction:column;align-items:flex-start;gap:19px}.site-footer{padding:24px clamp(22px,3.5vw,52px);display:flex;justify-content:space-between;gap:20px;background:var(--ink);color:var(--warm);font-size:11px;letter-spacing:.1em;text-transform:uppercase}.site-footer div{display:flex;gap:32px}.site-footer a{transition:color .2s ease}.site-footer a:hover{color:var(--orange)}
.detail-modal{border:0;padding:0;background:transparent;max-width:min(1080px,92vw);width:100%;color:var(--warm)}.detail-modal::backdrop{background:rgba(24,25,28,.72);backdrop-filter:blur(8px)}.detail-modal__inner{position:relative;display:grid;grid-template-columns:1.1fr .9fr;background:var(--ink);min-height:min(620px,85vh);box-shadow:0 24px 70px rgba(0,0,0,.25)}.detail-modal__close{position:absolute;z-index:2;right:17px;top:12px;width:38px;height:38px;border:1px solid rgba(246,241,232,.4);border-radius:50%;background:transparent;color:var(--warm);font-size:26px;line-height:1;cursor:pointer}.detail-modal__close:hover{background:var(--orange);color:var(--ink);border-color:var(--orange)}.detail-modal__visual{min-height:420px;background:#164cdf;position:relative;overflow:hidden}.detail-modal__visual:before,.detail-modal__visual:after{content:"";position:absolute;border-radius:50%;border:1px solid rgba(255,255,255,.55)}.detail-modal__visual:before{width:65%;height:75%;left:12%;top:12%;transform:rotate(27deg)}.detail-modal__visual:after{width:32%;height:38%;right:13%;bottom:14%;background:var(--orange);border:0;box-shadow:-100px -80px 0 rgba(205,233,246,.58)}.detail-modal__copy{padding:clamp(40px,5vw,78px) clamp(28px,4vw,60px);display:flex;flex-direction:column;justify-content:center}.detail-modal__copy h2{font-family:var(--serif);font-size:clamp(43px,5vw,80px);font-weight:400;line-height:.9;margin:18px 0 26px}.detail-modal__copy>p:not(.eyebrow){color:rgba(246,241,232,.7);font-size:15px}.detail-modal__facts{margin:34px 0 0;border-top:1px solid rgba(246,241,232,.3)}.detail-modal__facts div{display:flex;justify-content:space-between;gap:20px;padding:13px 0;border-bottom:1px solid rgba(246,241,232,.18);font-size:12px}.detail-modal__facts dt{color:rgba(246,241,232,.5)}.detail-modal__facts dd{margin:0;text-align:right;color:var(--warm)}
.reveal{opacity:0;transform:translateY(22px);transition:opacity .8s ease,transform .9s var(--ease)}.reveal.is-visible{opacity:1;transform:none}
@keyframes float{0%,100%{transform:rotate(28deg) translate(0,0)}50%{transform:rotate(18deg) translate(13px,-12px)}}@keyframes drift{from{background-position:0 0,0 0,0 0,0 0}to{background-position:80px 50px,-100px 70px,120px -100px,-100px -80px}}
@media (max-width:1040px){.hero,.section-shell{grid-template-columns:1fr 1fr;column-gap:50px}.featured-grid{grid-template-columns:repeat(2,1fr)}.experiment-grid{grid-template-columns:repeat(2,1fr)}.tool-stack{grid-template-columns:repeat(3,1fr)}.tool-node--delivery{grid-column:2}.tool-stack__rail{display:none}.closing{grid-template-columns:.45fr 1fr 1fr}}
@media (max-width:760px){.site-header{padding:20px 20px}.menu-toggle{top:17px;right:18px}.header-status{display:none}.section-shell,.hero,.method,.tool,.products,.playground{display:block;padding:100px 20px}.hero{padding-top:135px;min-height:auto}.hero__title{font-size:clamp(58px,16vw,100px);margin-top:22px}.hero__intro{max-width:350px;font-size:20px}.hero__diagram{min-height:540px;margin-top:72px}.diagram-node{width:122px;height:122px}.diagram-node--method{left:4%;top:29%}.diagram-node--tool{left:34%;top:47%}.diagram-node--product{right:3%;top:69%}.section-heading,.overview__copy,.method__copy,.tool__copy,.products__copy,.playground__copy{margin-bottom:58px}.section-heading h2{font-size:clamp(56px,16vw,100px);margin-bottom:0}.practice-map,.workflow-list,.featured-grid,.experiment-grid,.tool-stack{margin-top:58px}.workflow-list{display:block}.workflow-card{min-height:225px;margin-bottom:35px}.workflow-card h3{margin-top:45px}.tool-stack{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding-bottom:42px}.tool-node{min-height:230px}.tool-node--delivery{grid-column:auto}.tool-node h3{margin-top:38px}.tool-stack__caption{line-height:1.4}.transition-band{padding:76px 20px}.transition-path{gap:13px;font-size:clamp(34px,9.5vw,58px);line-height:.92}.transition-path i{width:28px}.product-group--experiments{margin-top:58px}.product-group__heading{font-size:10px}.product-card__visual{min-height:200px}.playground-wall{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:180px 180px 180px 180px;min-height:0;margin-top:58px}.visual-tile--a{grid-row:span 2}.visual-tile--b{grid-column:2}.visual-tile--c{grid-row:span 2;grid-column:2}.visual-tile--d{grid-column:1;grid-row:3}.visual-tile--e{grid-column:1;grid-row:4}.visual-tile--f{grid-column:2;grid-row:4}.closing{display:grid;grid-template-columns:1fr;padding:100px 20px;min-height:auto}.closing__mark{margin:0 0 50px;font-size:130px}.closing .section-heading,.closing__copy{grid-column:auto;padding-top:0}.closing__copy{margin-top:40px}.site-footer{display:block;padding:24px 20px;font-size:10px}.site-footer div{justify-content:space-between;margin-bottom:14px}.detail-modal{max-width:92vw}.detail-modal__inner{display:block;max-height:92vh;overflow:auto}.detail-modal__visual{min-height:250px}.detail-modal__copy{padding:32px 24px 40px}.detail-modal__copy h2{font-size:48px}.site-menu__inner{padding:100px 24px 32px}.site-menu__list a{font-size:65px}.site-menu__meta{display:block}.site-menu__meta p{margin-bottom:20px}.menu-orbit{right:-24vw;top:35vh;width:90vw;height:50vh}}
@media (max-width:430px){.hero__diagram{min-height:475px}.diagram-node{width:104px;height:104px}.diagram-node strong{font-size:20px}.diagram-node small{font-size:9px}.diagram-node--method{left:2%;top:29%}.diagram-node--tool{left:32%;top:46%}.diagram-node--product{right:1%;top:68%}.tool-stack{display:block}.tool-node{margin-bottom:10px;min-height:190px}.tool-node h3{margin-top:26px}.experiment-card{grid-template-columns:54px 1fr 16px;gap:10px;padding-right:8px}.experiment-card__visual{width:54px;height:54px}.experiment-card b{font-size:12px}.playground-wall{grid-template-rows:140px 140px 140px 140px}.site-footer div{display:block}.site-footer div span{display:block;margin-bottom:6px}}
@media (prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}.reveal{opacity:1;transform:none}}

/* V2 visual alignment: match the current V7 homepage type, navigation and footer. */
:root{--serif:DunbenSerif,"Libertinus Sans","Dunben Serif SC",Georgia,serif}
.site-header{padding:0;mix-blend-mode:difference;color:#fff}
.wordmark{position:fixed;top:clamp(18px,2.2vw,30px);left:clamp(20px,3.4vw,46px);width:clamp(68px,6vw,92px);display:block;line-height:0}
.wordmark__svg{display:block;width:100%;height:auto;filter:grayscale(1) brightness(0) invert(1)}
.header-status{position:fixed;top:clamp(22px,3vw,42px);right:clamp(70px,8vw,112px);margin:0;font-size:11px;letter-spacing:.12em}
.menu-toggle{top:clamp(22px,3vw,42px);right:clamp(22px,4vw,58px);width:2.3rem;height:2rem;padding:5px;gap:.3rem}
.menu-toggle span{height:.16rem}
.hero__title,.section-heading h2{letter-spacing:-.03em}
.hero__title{font-size:clamp(52px,4.8vw,96px);line-height:.96;max-width:600px;margin:22px 0 28px}
.section-heading h2{font-size:clamp(48px,5vw,94px);line-height:.94}
/* zh section titles 2px smaller (2026-10-14); phones: end of file. */
:where(html[lang="zh-CN"]) .section-heading h2:where(#overview-title,#method-title,#tool-title,#products-title,#playground-title){font-size:calc(clamp(48px,5vw,94px) - 2px)}
.transition-path{font-size:clamp(34px,4vw,72px);letter-spacing:-.025em}
.diagram-node strong,.product-card__body h3,.closing__statement{font-family:var(--sans)!important}
.product-card__body h3{font-size:clamp(22px,1.8vw,30px);line-height:1.12;letter-spacing:-.02em}
.closing__statement{font-size:clamp(21px,1.8vw,31px);line-height:1.35;max-width:420px;margin:34px 0 30px!important;letter-spacing:-.02em}

/* Vibe Coding becomes a second row of large, cover-ready product cards. */
.experiment-grid{grid-template-columns:repeat(4,1fr);gap:14px}
.experiment-card{display:flex;flex-direction:column;align-items:stretch;gap:0;min-height:420px;padding:0;background:var(--paper);text-align:left;border:1px solid var(--line);box-shadow:none}
.experiment-card:hover,.experiment-card:focus-visible{background:var(--paper);color:var(--ink);transform:translateY(-8px);box-shadow:0 14px 25px rgba(24,25,28,.08)}
.experiment-card__visual{position:relative;width:100%;height:240px;flex:0 0 240px;display:flex;align-items:center;justify-content:center;font-family:var(--serif);font-size:35px}
.experiment-card__symbol{font-family:var(--serif);font-size:clamp(82px,8vw,132px);line-height:1;transition:transform .5s var(--ease)}
.experiment-card:hover .experiment-card__symbol,.experiment-card:focus-visible .experiment-card__symbol{transform:scale(1.08) rotate(-7deg)}
.experiment-card__body{display:flex;flex:1;flex-direction:column;align-items:flex-start;padding:20px 18px 22px;min-height:170px}
.experiment-card__body>span:first-child{font-size:10px;text-transform:uppercase;letter-spacing:.1em;color:var(--muted)}
.experiment-card__body b{display:block;margin:26px 0 8px;font-family:var(--sans);font-size:clamp(21px,1.8vw,30px);font-weight:500;line-height:1.12;letter-spacing:-.02em}
.experiment-card__body small{display:block;margin:0;color:var(--muted);font-size:12px}
.experiment-card__link{margin-top:auto!important;padding-top:22px;color:var(--blue);font-size:12px;border-bottom:1px solid currentColor;padding-bottom:5px}
.experiment-card:hover .experiment-card__body small{color:var(--muted)}
.experiment-card:hover .experiment-card__link,.experiment-card:focus-visible .experiment-card__link{color:var(--orange)}

/* Chinese copy stays in the site's sans family; English display copy remains Libertinus Sans. */
.hero__intro,.lede,.section-shell p,.workflow-card p,.tool-node p,.transition-band__copy,.product-card__body h3,.product-card__body p,.experiment-card__body,.closing__statement,.detail-modal__copy>p:not(.eyebrow){font-family:var(--sans)!important}

/* Homepage footer pattern: Contact / Let's shape what's next. / social links. */
.footer--homepage{position:relative;overflow:hidden;background:var(--ink);color:#fff;padding:clamp(92px,10vw,154px) clamp(22px,7vw,100px) clamp(42px,7.5vw,120px)}
.footer__container{max-width:1500px;margin:0 auto}
.footer__columns{display:flex;justify-content:space-between;align-items:flex-start;gap:clamp(46px,10vw,160px)}
.footer__copy{max-width:660px}
.footer .label{display:block;margin-bottom:24px;color:rgba(255,255,255,.62);font-size:11px;line-height:1.2;letter-spacing:.12em;text-transform:uppercase}
.footer__title{font-family:var(--serif);font-size:clamp(52px,6vw,104px);font-weight:400;line-height:.9;letter-spacing:-.03em}
.footer__title strong{font-weight:400;color:var(--blue)}
.footer__body{max-width:500px;margin-top:38px;color:rgba(255,255,255,.66)}
.footer__body p{margin:0;font-size:14px;line-height:1.55}
.footer__social-item{padding-top:clamp(44px,5vw,82px);min-width:min(22vw,260px)}
.footer__socials{display:flex;flex-direction:column;gap:0;margin:0;padding:0;list-style:none}
.footer__socials li{border-bottom:1px solid rgba(255,255,255,.35)}
.footer__socials a{display:flex;justify-content:space-between;gap:30px;padding:14px 0;color:#fff;font-size:14px;transition:color .2s ease,transform .3s var(--ease)}
.footer__socials a:hover,.footer__socials a:focus-visible{transform:translateX(8px);color:var(--orange)}
.footer__meta{display:flex;justify-content:space-between;gap:22px;max-width:1500px;margin:clamp(76px,10vw,140px) auto 0;padding-top:15px;border-top:1px solid rgba(255,255,255,.22);color:rgba(255,255,255,.55);font-size:10px;letter-spacing:.1em;text-transform:uppercase}

@media (max-width:1040px){.experiment-card__visual{height:210px;flex-basis:210px}.experiment-card{min-height:390px}.footer__columns{gap:60px}}
@media (max-width:760px){
  .wordmark{top:18px;left:20px;width:76px}.header-status{top:22px;right:70px}.menu-toggle{top:17px;right:18px}
  .hero__title{font-size:clamp(50px,13vw,78px);max-width:500px}.section-heading h2{font-size:clamp(47px,13vw,78px)}
  .experiment-grid{grid-template-columns:repeat(2,1fr);gap:12px}.experiment-card{min-height:370px}.experiment-card__visual{height:180px;flex-basis:180px}.experiment-card__body{padding:16px 14px 18px;min-height:170px}.experiment-card__body b{font-size:20px;margin-top:20px}.experiment-card__link{padding-top:18px;font-size:11px}
  .footer--homepage{padding:82px 20px 38px}.footer__columns{display:block}.footer__copy{max-width:100%}.footer__title{font-size:clamp(54px,15vw,82px)}.footer__body{margin-top:30px}.footer__social-item{padding-top:56px;min-width:0}.footer__meta{margin-top:80px;display:block}.footer__meta span{display:block;margin-top:7px}
}
@media (max-width:430px){.experiment-grid{grid-template-columns:1fr}.experiment-card{min-height:390px}.experiment-card__visual{height:220px;flex-basis:220px}}

/* Footer typography remains local; navigation is owned exclusively by
   assets/main-navigation.css. */
@font-face{font-family:"Font Awesome 6 Brands";src:url("../assets/fonts/fa-brands-400.woff2") format("woff2");font-style:normal;font-weight:400;font-display:swap}
:root{--font-primary:DunbenSerif,"Libertinus Sans","Dunben Serif SC",Georgia,serif;--font-secondary:DunbenSans,"Dunben Sans SC",Helvetica,Arial,sans-serif}

/* The footer uses the exact shared module shape: centered copy, icon row,
   restrained grey body copy, and the existing ICP line. */
.footer{position:relative;display:block;overflow:hidden;padding:clamp(92px,10vw,154px) 0 clamp(70px,7.5vw,120px);background:#121314;color:#fff}
.footer .container{width:min(90vw,1420px);margin:0 auto}
.footer .columns--top{display:flex;flex-direction:column;align-items:center;gap:0;margin:0}
.footer .columns--top>.item:first-child{text-align:center}
.footer .text-block-center{max-width:760px;margin:0 auto}
.footer .label{display:block;margin-bottom:clamp(22px,2.083vw,40px);color:#fff;font-size:11px;line-height:1.2;letter-spacing:.12em;text-transform:uppercase}
.footer .title{font-family:var(--font-primary);font-size:clamp(52px,6vw,104px);font-weight:400;line-height:.9;letter-spacing:-.03em}
.footer .title strong{font-weight:400;color:var(--blue)}
.footer .wysiwyg{max-width:560px;margin:clamp(28px,3vw,56px) auto 0;color:#858585}
.footer .wysiwyg p{margin:0;font-size:14px;line-height:1.55}
.footer .columns--top>.item:nth-child(2){color:#858585;text-align:center}
.footer .menu-social{display:flex;align-items:center;justify-content:center;gap:clamp(28px,5vw,96px);margin:clamp(28px,2vw,38px) 0 0;padding:0;list-style:none}
.footer .menu-social li{width:clamp(42px,2.5vw,48px);height:clamp(42px,2.5vw,48px);display:flex;align-items:center;justify-content:center;border:1px solid rgba(255,255,255,.4);border-radius:4px;transition:border-color .4s ease-out}
.footer .menu-social li:hover,.footer .menu-social li:focus-within{border-color:#fff}
.footer .menu-social a{color:#858585;font-size:clamp(16px,1vw,20px);text-decoration:none;transition:color .4s ease-out}
.footer .menu-social li:hover a,.footer .menu-social li:focus-within a{color:#fff}
.footer .menu-social i{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400}
.footer .fa-facebook-f::before{content:"\f39e"}.footer .fa-instagram::before{content:"\f16d"}.footer .fa-linkedin-in::before{content:"\f0e1"}
.footer .dv-footer-icp{position:absolute;right:0;bottom:clamp(20px,2.2vw,42px);left:0;margin:0;text-align:center;color:#858585;font-size:10px}
.footer .dv-footer-icp a{color:inherit;text-decoration:none}.footer .dv-footer-icp a:hover,.footer .dv-footer-icp a:focus-visible{color:#fff}

@media (max-width:760px){.footer{padding:82px 20px 64px}.footer .container{width:100%}.footer .title{font-size:clamp(54px,15vw,82px)}.footer .wysiwyg{margin-top:30px}.footer .menu-social{gap:clamp(24px,10vw,40px)}}

/* Applied AI uses the same current contact footer as the rebuilt Home. */
.dv-footer{position:relative;min-height:min(88svh,920px);display:flex;align-items:center;justify-content:center;padding:clamp(96px,12vw,170px) clamp(22px,7vw,100px) clamp(72px,9vw,120px);overflow:hidden;background:#121314;color:#fff;text-align:center}.dv-footer__inner{position:relative;z-index:2;width:min(780px,100%);margin:0 auto}.dv-footer__label{margin:0 0 clamp(28px,4vw,54px);font-size:11px;letter-spacing:.11em;text-transform:uppercase}.dv-footer__title{margin:0;font-family:var(--font-primary);font-size:clamp(58px,8vw,138px);font-weight:400;line-height:.88;letter-spacing:-.045em}.dv-footer__title strong{font-weight:400;color:var(--blue)}.dv-footer__body{max-width:630px;margin:clamp(34px,4vw,60px) auto 0;color:#858585;font-family:var(--font-secondary);font-size:clamp(15px,1.3vw,19px);line-height:1.48}.dv-footer__dot{position:absolute;z-index:1;width:12px;height:12px;top:52%;right:clamp(9%,18vw,28%);border-radius:50%;background:var(--blue);box-shadow:0 0 0 10px rgba(22,76,223,.08);animation:dv-footer-pulse 3s ease-in-out infinite}@keyframes dv-footer-pulse{50%{transform:scale(1.24);box-shadow:0 0 0 16px rgba(22,76,223,.03)}}.dv-footer__icp{position:absolute;z-index:2;right:0;bottom:clamp(22px,3vw,44px);left:0;margin:0;color:#858585;font-family:var(--font-secondary);font-size:11px}.dv-footer__icp a{color:inherit;text-decoration:none}.dv-footer__icp a:hover,.dv-footer__icp a:focus-visible{color:#fff}.dv-footer+.footer{display:none}
@media (max-width:760px){.dv-footer{min-height:76svh;padding:84px 20px 74px}.dv-footer__title{font-size:clamp(56px,15vw,92px)}.dv-footer__body{margin-top:31px;font-size:15px}.dv-footer__dot{right:18%;top:48%;width:10px;height:10px}.dv-footer__icp{font-size:10px}}
@media (prefers-reduced-motion:reduce){.dv-footer__dot{animation:none}}

/* Method — the vertical introduction clears the viewport before a purpose-built
   horizontal workflow gallery begins. The gallery is enhanced by script only
   on fine, desktop-sized layouts; its static overflow version remains a usable
   fallback and keeps all three workflows available without motion. */
.method{--method-content-inset:clamp(22px,7vw,100px);--method-card-gap:150px;--method-stage-bottom-gap:max(30px,env(safe-area-inset-bottom));--method-intro-copy-offset:2.4rem;position:relative;display:block;padding:0;overflow:visible;background:var(--ink);color:var(--warm)}
.method__intro{display:grid;grid-template-columns:minmax(500px,.95fr) minmax(420px,1.05fr);column-gap:clamp(40px,9vw,150px);align-content:start;min-height:0;padding:clamp(142px,15vw,220px) var(--method-content-inset) 0}
.method__intro .section-heading h2{max-width:none;margin:0;padding-bottom:.12em;white-space:nowrap}
.method__intro .method__copy{align-self:start;max-width:560px;margin-bottom:0;padding-top:0}
.method-gallery{position:relative;z-index:1;background:var(--ink)}
.method-gallery__stage{width:100%;overflow-x:auto;overscroll-behavior-x:contain;scroll-snap-type:x mandatory;scrollbar-color:rgba(246,241,232,.38) transparent;scrollbar-width:thin}
/* The enhanced desktop gallery owns horizontal position through JavaScript.
   Disable native snapping before its first measurement: otherwise the browser
   scrolls the transformed first card back to x=0 and erases its page gutter. */
.has-js .method-gallery__stage{scroll-snap-type:none}
.method-gallery__track{--method-track-start:var(--method-content-inset);display:flex;gap:clamp(20px,2.1vw,38px);width:max-content;padding:var(--method-card-gap) var(--method-content-inset) clamp(50px,7vw,104px) 0;transform:translate3d(calc(var(--method-track-start) + var(--method-track-x,0px)),0,0);will-change:transform}
.method-card{position:relative;isolation:isolate;flex:0 0 73vw;width:73vw;height:min(780px,calc(100svh - var(--method-card-gap) - var(--method-stage-bottom-gap)));min-height:min(580px,calc(100svh - var(--method-card-gap) - var(--method-stage-bottom-gap)));overflow:hidden;border:1px solid rgba(246,241,232,.34);border-radius:16px;background-color:#191a1d;background-image:linear-gradient(rgba(246,241,232,.075) 1px,transparent 1px),linear-gradient(90deg,rgba(246,241,232,.075) 1px,transparent 1px);background-size:clamp(46px,3.25vw,68px) clamp(46px,3.25vw,68px);color:var(--warm);scroll-snap-align:start}
.method-card:after{position:absolute;z-index:-1;right:-14%;bottom:-38%;width:60%;height:74%;border:1px solid rgba(246,241,232,.12);border-radius:50%;content:"";transform:rotate(-32deg)}
.method-card__title{position:absolute;z-index:2;top:clamp(38px,6vw,84px);right:clamp(28px,5vw,78px);max-width:58%;margin:0;font-family:var(--serif);font-size:clamp(53px,calc(4.3vw + 10px),92px);font-weight:400;letter-spacing:-.035em;line-height:.9;text-align:right;text-transform:uppercase;color:var(--warm)}
.method-card__workflow{position:absolute;z-index:2;top:clamp(142px,20%,196px);bottom:clamp(30px,6%,54px);left:clamp(24px,3.6vw,62px);width:min(43%,520px);padding:clamp(21px,2.1vw,34px);border:1px solid rgba(246,241,232,.34);border-radius:12px;background:#070809;color:var(--warm)}
.method-card__workflow h4{margin:0 0 clamp(18px,2vw,28px);font-size:clamp(17px,1.5vw,25px);font-weight:650;letter-spacing:-.025em}
.method-card__workflow ol{margin:0;padding:0;list-style:none}
.method-card__workflow li{display:block;padding:clamp(12px,1.45vw,21px) 0;border-top:1px solid rgba(246,241,232,.56);font-size:clamp(12px,1.02vw,16px);line-height:1.38}
.method-card__workflow li:last-child{padding-bottom:0}
.method-card__workflow strong{font-weight:650}.method-card__workflow strong:after{content:": "}html[lang="zh-CN"] .method-card__workflow strong:after{content:"："}.method-card__workflow span{display:inline}
.method-card__note{position:absolute;z-index:3;bottom:clamp(44px,10%,88px);left:clamp(48%,49vw,53%);width:min(31%,420px);margin:0;padding:clamp(20px,2.4vw,34px);border-radius:12px;background:rgba(246,241,232,.15);color:rgba(246,241,232,.9);font-size:clamp(13px,1.25vw,20px);font-weight:300;line-height:1.3;transform:rotate(12deg);transform-origin:center;backdrop-filter:blur(7px)}
.method-card__index{position:absolute;z-index:1;right:clamp(25px,5vw,76px);bottom:clamp(8px,1.5vw,20px);font-family:var(--serif);font-size:clamp(156px,18vw,330px);font-weight:400;letter-spacing:-.09em;line-height:.7;color:rgba(246,241,232,.48)}
.method-card__motif{position:absolute;z-index:4;inset:0;pointer-events:none}
.method-card__motif img{--method-rain-left:50%;--method-rain-delay:0ms;--method-rain-duration:5200ms;--method-rain-drift:0px;--method-rain-turn:0deg;position:absolute;top:-74px;left:var(--method-rain-left);width:clamp(26px,2.1vw,42px);height:clamp(26px,2.1vw,42px);object-fit:contain;filter:grayscale(1) brightness(0) invert(1);mix-blend-mode:difference;opacity:0;transform:translate3d(0,-110px,0) rotate(var(--method-rain-turn));will-change:transform,opacity}
.method-card.is-raining .method-card__motif img{animation:method-icon-rain var(--method-rain-duration) cubic-bezier(.48,0,.86,.34) var(--method-rain-delay) infinite both}
.method-card:hover .method-card__workflow{background:#0b0c0d}.method-card:hover .method-card__note{background:rgba(246,241,232,.19)}
.method-gallery.is-enhanced{height:calc(100svh + var(--method-scroll-distance,180vh))}.method-gallery.is-enhanced .method-gallery__stage{position:sticky;top:0;height:100svh;overflow:hidden;scroll-snap-type:none}.method-gallery.is-enhanced .method-card{scroll-snap-align:none}.method-gallery.is-enhanced .method-gallery__track{padding-top:var(--method-card-gap);padding-bottom:clamp(42px,6vh,82px)}
@keyframes method-icon-rain{0%{opacity:0;transform:translate3d(0,-120px,0) rotate(calc(var(--method-rain-turn) - 10deg))}8%{opacity:.9}82%{opacity:.9}100%{opacity:0;transform:translate3d(var(--method-rain-drift),calc(100svh + 250px),0) rotate(calc(var(--method-rain-turn) + 26deg))}}
@media (max-width:1040px) and (min-width:761px){.method__intro{grid-template-columns:1fr 1fr;column-gap:50px}.method-card__workflow{width:47%;left:28px;padding:21px}.method-card__workflow li{font-size:12px}.method-card__note{left:51%;width:34%;font-size:14px}.method-card__index{font-size:clamp(136px,18vw,220px)}}
/* Align the secondary copy with the primary title, rather than with Method's
   kicker. 2.4rem equals the kicker's 20.4px line box plus its shared 18px
   gap to the heading; the single-column layout keeps its own reading rhythm. */
@media (min-width:761px){.method__intro .method__copy{padding-top:var(--method-intro-copy-offset)}}
@media (max-width:760px){.method{--method-content-inset:20px;--method-card-gap:50px;overflow:hidden}.method__intro{display:block;min-height:auto;padding:118px var(--method-content-inset) var(--method-card-gap)}.method__intro .method__copy{padding-top:40px}.method__intro .section-heading h2{max-width:none;white-space:nowrap}.method-gallery{height:auto!important;padding:0 20px 96px}.method-gallery__stage{height:auto!important;overflow:visible;scroll-snap-type:none}.method-gallery__track{display:grid;width:auto;gap:20px;padding:0;transform:none!important}.method-card{display:block;width:100%;height:auto;min-height:0;padding:0 0 28px;border-radius:16px}.method-card:after{right:-25%;bottom:-20%;width:84%;height:44%}.method-card__title{position:relative;top:auto;right:auto;max-width:12ch;margin:78px auto 38px;font-size:clamp(52px,calc(12vw + 10px),72px);text-align:center}.method-card__workflow{position:relative;top:auto;bottom:auto;left:auto;width:auto;margin:0 20px;padding:24px 20px}.method-card__workflow h4{font-size:26px}.method-card__workflow li{padding:18px 0;font-size:16px;line-height:1.42}.method-card__workflow strong{display:inline}.method-card__note{position:relative;right:auto;bottom:auto;left:auto;width:auto;margin:28px 20px 0;padding:24px 20px;font-size:17px;line-height:1.42;transform:none}.method-card__index{display:none}.method-card__motif img{width:34px;height:34px}}
@media (max-width:430px){.method__intro{padding-top:108px}.method-card__title{margin-top:72px;font-size:54px}.method-card__workflow{margin-right:16px;margin-left:16px}.method-card__workflow li{font-size:15px}.method-card__note{margin-right:16px;margin-left:16px;font-size:16px}.method-card__motif img{width:30px;height:30px}}
/* The stacked cards keep all content while dropping the title and row padding
   that made each workflow taller than the reading required. */
@media (max-width:760px){
  .method{
    --method-phone-title-top:clamp(36px,10vw,44px);
    --method-phone-title-bottom:clamp(20px,6vw,26px);
    --method-phone-panel-pad:clamp(18px,5vw,21px);
    --method-phone-workflow-lead:clamp(20px,5.8vw,24px);
    --method-phone-step-gap:clamp(12px,3.5vw,15px);
  }
  .method-card{padding-bottom:var(--method-phone-panel-pad)}
  .method-card__title{margin-top:var(--method-phone-title-top);margin-bottom:var(--method-phone-title-bottom)}
  .method-card__workflow{padding:var(--method-phone-panel-pad)}
  .method-card__workflow h4{margin-bottom:0}
  .method-card__workflow ol{margin-top:var(--method-phone-workflow-lead)}
  .method-card__workflow li{padding:0;border-top:0}
  .method-card__workflow li + li{margin-top:var(--method-phone-step-gap)}
  .method-card__note{margin-top:var(--method-phone-panel-pad);padding:var(--method-phone-panel-pad)}
}
@media (prefers-reduced-motion:reduce){.method-card__motif img{top:var(--method-rain-top,16%);left:var(--method-rain-left);opacity:.84;transform:rotate(var(--method-rain-turn));animation:none}.method-gallery__track{will-change:auto}}

.dv-footer__label { font-size: 13px; }

/* Applied AI content distillation: preserve the incumbent visual system while
   tightening the hierarchy requested in the annotated review. */
.hero__title{margin:0}
.overview .section-heading h2{margin-top:0}
.overview__copy{align-self:start}
.sec-content{width:100%;max-width:560px;margin:0;font-family:var(--sans)!important;font-size:clamp(16px,calc(2vw - 6px),24px);font-weight:400;line-height:calc(1.4em + 2px);letter-spacing:0}
.overview .section-heading h2 em,.method .section-heading h2 em,.tool .section-heading h2 em,.products .section-heading h2 em,.playground .section-heading h2 em,.closing .section-heading h2 em{color:var(--blue)}
@media (min-width:1041px){.overview,.method,.tool,.products,.playground,.closing{grid-template-columns:minmax(230px,.8fr) minmax(300px,1.2fr)}}
@media (min-width:761px){.overview__copy{padding-top:8px}.method__copy,.tool__copy,.products__copy,.playground__copy{padding-top:52px}}
.tool-stack{padding-bottom:0}
.transition-path{margin-bottom:0}
.transition-band__copy{max-width:760px;color:rgba(255,255,255,.82);font-size:18px;line-height:1.55}
.products__highlight{color:var(--blue)}

/* Applied AI now uses one fixed ink surface from Overview through Closing.
   The section classes own their backgrounds directly; no scroll state changes
   the surface or the foreground palette. Light cards remain self-contained. */
.section-shell--ink .sec-content{color:var(--warm)}
.method .workflow-card p{font-size:16px}

/* Products now shares Playground's dark field while its cards remain paper surfaces. */
.products .product-group__heading{color:rgba(246,241,232,.68);border-color:rgba(246,241,232,.24)}
.products .products__highlight{color:var(--blue)}
.products .product-card,.products .experiment-card{color:var(--ink)}

/* Applied AI section labels: remove sequence numbers and strengthen the hierarchy. */
.method .section-heading>.eyebrow,.tool>.section-heading>.eyebrow,.products>.section-heading>.eyebrow,.playground>.section-heading>.eyebrow{font-size:17px}

@media (min-width:761px) and (max-width:1040px){.closing{grid-template-columns:1fr 1fr}}

/* AIGC spiral: the current dark surface continues into a dedicated pinned stage. */
:root{
  /* Single trim token for the three seams the spiral introduces
     (products → stage → AIGC wall, plus closing → footer). Fluid so it never becomes a
     per-viewport patch: it reaches its full value on the desktop widths where
     the gaps read as too loose, and eases off before it can crush mobile. */
  --spiral-trim:clamp(20px,2.5vw,36px);
  /* 竖屏下正面那张卡几乎占满画宽，文案与卡片之间不需要桌面那样的呼吸。
     这条缝单独给一个 token —— 不要再往 --spiral-trim 上叠减数，那个 token
     同时服务三条缝，改它会连带动 closing 和 footer。
     实测：文案底到第一张卡顶共 440px，其中只有这一项（46px→16px）是 padding
     能管的，其余 394px 是 stage 内部的 3D 空白，由 yBase / cameraZ 决定。 */
  --spiral-seam-mobile:16px;
}

/* The pin spacer GSAP injects around the stage inherits no background, so the
   page surface (--paper, near white) shows through for the frame where the
   stage flips between static and fixed — the white flash on pin enter/exit —
   and for the whole tail region after the pin releases. Painting the band that
   wraps the spacer keeps the dark surface continuous no matter what GSAP does
   to the stage's own position. */
.aigc-spiral-band{position:relative;background:var(--ink)}
.aigc-spiral-band>.pin-spacer{background:var(--ink)}

.aigc-spiral-stage{
  position:relative;
  min-height:100svh;
  height:auto;
  overflow:visible;
  isolation:isolate;
  background:var(--ink);
  color:var(--warm);
}
/* `contain:paint` is deliberately absent: it makes the stage its own paint
   container, which Chrome can drop for a frame exactly when GSAP flips the
   element to position:fixed — the second source of the pin-enter flash.
   `overflow:hidden` already does the clipping we need. */
.aigc-spiral-stage.is-loading,
.aigc-spiral-stage.is-enhanced{
  min-height:640px;
  height:100svh;
  overflow:hidden;
}

/* Reserve the pinned height from the very first paint. If the box only
   collapses once the WebGL module has enhanced it, the document loses ~1000px
   of fallback grid and gains ~4 screens of pin spacer *after* the browser has
   already restored the previous scroll position — which is how a reload used to
   land inside the blank spacer instead of on the stage. */
@media (prefers-reduced-motion:no-preference){
  html.has-js .aigc-spiral-stage:not([data-aigc-state="fallback"]){
    min-height:640px;
    height:100svh;
    overflow:hidden;
  }
}
.aigc-spiral-stage__canvas{
  position:absolute;
  inset:0;
  z-index:1;
  display:block;
  width:100%;
  height:100%;
  opacity:0;
  touch-action:pan-y;
  transition:opacity .45s cubic-bezier(.16,1,.3,1);
}
.aigc-spiral-stage.is-enhanced .aigc-spiral-stage__canvas{opacity:1}
.aigc-spiral-stage__ui{
  position:absolute;
  inset:0;
  z-index:2;
  display:flex;
  align-items:flex-end;
  justify-content:flex-end;
  padding:clamp(24px,3vw,48px);
  pointer-events:none;
  opacity:0;
  transition:opacity .35s ease;
}
.aigc-spiral-stage.is-enhanced .aigc-spiral-stage__ui{opacity:1}
.aigc-spiral-stage__progress{
  position:relative;
  width:clamp(132px,13vw,180px);
  height:1px;
  background:rgba(246,241,232,.2);
  transition:opacity .2s ease;
}
.aigc-spiral-stage__progress i{
  position:absolute;
  inset:0 auto 0 0;
  display:block;
  width:100%;
  background:var(--warm);
  transform:scaleX(0);
  transform-origin:left center;
  will-change:transform;
}
.aigc-spiral-stage__status{
  position:absolute!important;
  width:1px!important;
  height:1px!important;
  padding:0!important;
  margin:-1px!important;
  overflow:hidden!important;
  clip:rect(0,0,0,0)!important;
  white-space:nowrap!important;
  border:0!important;
}
.aigc-spiral-grid{
  position:relative;
  z-index:3;
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:12px;
  width:min(100%,1440px);
  margin:0 auto;
  padding:clamp(80px,9vw,132px) clamp(22px,5vw,76px);
}
.aigc-spiral-card{
  min-width:0;
  padding:0;
  border:1px solid rgba(246,241,232,.2);
  background:#1a1b1d;
  color:var(--warm);
  text-align:left;
  cursor:pointer;
  transition:transform .35s var(--ease),border-color .25s ease,background .25s ease;
}
.aigc-spiral-card:hover{transform:translateY(-6px);border-color:rgba(246,241,232,.54)}
.aigc-spiral-card:focus-visible{outline:2px solid var(--blue);outline-offset:4px;border-color:var(--blue)}
.aigc-spiral-card__visual{
  position:relative;
  display:grid;
  place-items:center;
  width:100%;
  aspect-ratio:1.7 / 1;
  overflow:hidden;
  background:linear-gradient(135deg,var(--aigc-start),var(--aigc-end));
  color:rgba(255,255,255,.94);
}
.aigc-spiral-card__visual:before,.aigc-spiral-card__visual:after{
  content:"";
  position:absolute;
  width:72%;
  aspect-ratio:1;
  border:1px solid rgba(255,255,255,.18);
  border-radius:50%;
}
.aigc-spiral-card__visual:after{width:48%}
.aigc-spiral-card__visual span{position:relative;z-index:1;font-family:var(--serif);font-size:clamp(45px,5vw,86px);line-height:1}
.aigc-spiral-card__copy{display:block;padding:18px 18px 20px}
.aigc-spiral-card__copy small{display:block;color:rgba(246,241,232,.56);font-size:10px;letter-spacing:.1em;text-transform:uppercase}
.aigc-spiral-card__copy strong{display:block;margin-top:16px;font-family:var(--serif);font-size:clamp(22px,2vw,32px);font-weight:400;line-height:1}
.aigc-spiral-card--cover{border-color:rgba(246,241,232,.32)}
.aigc-spiral-card--cover .aigc-spiral-card__visual{display:block;background:#15171d}
.aigc-spiral-card--cover .aigc-spiral-card__visual::before,.aigc-spiral-card--cover .aigc-spiral-card__visual::after{display:none}
.aigc-spiral-card--cover .aigc-spiral-card__visual img{display:block;width:100%;height:100%;object-fit:cover}

@media (prefers-reduced-motion:no-preference){
  /* The list is the accessible mirror of the canvas. It is hidden from the
     moment we know JS is running — not only once `.is-enhanced` lands — so the
     stage's height never changes between first paint and enhancement. */
  html.has-js .aigc-spiral-stage:not([data-aigc-state="fallback"]) .aigc-spiral-grid,
  .aigc-spiral-stage.is-enhanced .aigc-spiral-grid{
    position:absolute;
    left:clamp(20px,3vw,48px);
    bottom:clamp(20px,3vw,48px);
    width:1px;
    height:1px;
    margin:0;
    padding:0;
    overflow:hidden;
    clip-path:inset(50%);
    grid-template-columns:1fr;
    gap:6px;
    white-space:nowrap;
  }
  html.has-js .aigc-spiral-stage:not([data-aigc-state="fallback"]) .aigc-spiral-grid:focus-within,
  .aigc-spiral-stage.is-enhanced .aigc-spiral-grid:focus-within{
    width:min(360px,calc(100vw - 40px));
    height:auto;
    max-height:calc(100svh - 40px);
    padding:10px;
    overflow:auto;
    clip-path:none;
    white-space:normal;
    background:rgba(18,19,20,.96);
    border:1px solid rgba(246,241,232,.26);
    box-shadow:0 18px 50px rgba(0,0,0,.28);
  }
  .aigc-spiral-stage.is-enhanced .aigc-spiral-card{display:grid;grid-template-columns:82px 1fr;align-items:center;min-height:66px}
  .aigc-spiral-stage.is-enhanced .aigc-spiral-card:hover{transform:none;background:#202124}
  .aigc-spiral-stage.is-enhanced .aigc-spiral-card__visual{width:82px;aspect-ratio:1.7 / 1}
  .aigc-spiral-stage.is-enhanced .aigc-spiral-card__visual span{font-size:27px}
  .aigc-spiral-stage.is-enhanced .aigc-spiral-card__copy{padding:10px 12px}
  .aigc-spiral-stage.is-enhanced .aigc-spiral-card__copy strong{margin-top:5px;font-family:var(--sans);font-size:15px}
}

@media (max-width:1040px){
  .aigc-spiral-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}

@media (max-width:767px){
  .aigc-spiral-stage{height:auto;min-height:0;overflow:visible}
  .aigc-spiral-stage.is-loading,.aigc-spiral-stage.is-enhanced{height:100svh;min-height:100svh;overflow:hidden}
  .aigc-spiral-stage__ui{padding:20px}
  .aigc-spiral-stage__progress{width:min(150px,42vw)}
  .aigc-spiral-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;padding:0 20px 100px}
  .aigc-spiral-card__copy{padding:15px 14px 17px}
  .aigc-spiral-card__copy strong{margin-top:11px;font-family:var(--sans);font-size:17px}
  .aigc-spiral-card__visual span{font-size:clamp(44px,15vw,70px)}
}

@media (max-height:640px){
  .aigc-spiral-stage.is-loading,.aigc-spiral-stage.is-enhanced{height:100svh;min-height:100svh}
}

@media (max-width:480px){
  .aigc-spiral-grid{grid-template-columns:1fr}
  .aigc-spiral-card__visual span{font-size:72px}
}

/* 灵感画板是完整的 Product Case。这个浮层沿用 Case Detail 的暗色阅读场、
   无干扰大画面与宽正文尺度；其余 Products 仍走原有的紧凑信息弹窗。 */
.inspiration-case-modal{width:min(1480px,96vw);max-width:none;height:min(94svh,1120px);max-height:none;margin:auto;padding:0;border:0;background:transparent;color:var(--warm)}
.inspiration-case-modal::backdrop{background:rgba(8,9,11,.82);backdrop-filter:blur(12px)}
.inspiration-case-modal__frame{position:relative;width:100%;height:100%;overflow:hidden;background:#121314;box-shadow:0 28px 90px rgba(0,0,0,.56)}
.inspiration-case-modal__close{position:absolute;z-index:3;top:clamp(16px,2vw,28px);right:clamp(16px,2vw,28px);display:grid;place-items:center;width:46px;height:46px;padding:0;border:1px solid rgba(247,245,242,.36);border-radius:50%;background:rgba(18,19,20,.74);color:#f7f5f2;font-size:25px;line-height:1;cursor:pointer;transition:background .2s ease,color .2s ease,border-color .2s ease}
.inspiration-case-modal__close:hover{border-color:#fff;background:#fff;color:var(--ink)}
.inspiration-case-modal__close:focus-visible{outline:2px solid #fff;outline-offset:4px}
.inspiration-case{height:100%;overflow-y:auto;overscroll-behavior:contain;scrollbar-color:rgba(247,245,242,.42) transparent;scrollbar-width:thin}
.inspiration-case__hero{width:min(100% - clamp(44px,8vw,148px),1280px);margin:0 auto;padding:clamp(92px,10vw,150px) 0 clamp(64px,7vw,112px);text-align:center}
.inspiration-case__opening{margin:0 0 34px;color:#f7f5f2;font-family:var(--serif);font-size:clamp(50px,1.4vw,56px);font-weight:400;letter-spacing:-.025em;line-height:1.08}
.inspiration-case h3,.inspiration-case h4{font-family:var(--serif);font-weight:400;letter-spacing:-.035em}
.inspiration-case__lead{max-width:720px;margin:0 auto clamp(58px,6vw,96px);color:#a8a8a8;font-size:clamp(14px,calc(1.6vw - 4px),21px);line-height:1.48;text-align:center}
.inspiration-case__cover{width:min(100% - 32px,1180px);margin:0 auto;overflow:hidden;border-radius:20px;background:#1c1c1c}
.inspiration-case__cover img{display:block;width:100%;height:auto}
.inspiration-case__built{display:grid;grid-template-columns:minmax(240px,.85fr) minmax(0,1.15fr);gap:clamp(32px,6vw,104px);width:min(100% - clamp(44px,8vw,148px),1180px);margin:0 auto;padding:clamp(74px,8vw,128px) 0;border-bottom:1px solid rgba(247,245,242,.18)}
.inspiration-case h3{margin:0;font-size:clamp(38px,4.5vw,68px);line-height:.96}
.inspiration-case__built dl{margin:0;border-top:1px solid rgba(247,245,242,.26)}
.inspiration-case__built dl div{display:grid;grid-template-columns:minmax(110px,.42fr) 1fr;gap:24px;padding:18px 0;border-bottom:1px solid rgba(247,245,242,.16)}
.inspiration-case__built dt{color:#929292;font-size:12px;letter-spacing:.08em;text-transform:uppercase}
.inspiration-case__built dd{margin:0;color:#f7f5f2;font-size:clamp(16px,1.18vw,19px);line-height:1.42}
.inspiration-case__functions{width:min(100% - clamp(44px,8vw,148px),1280px);margin:0 auto;padding:clamp(74px,9vw,148px) 0 clamp(86px,10vw,160px)}
.inspiration-case__functions>h3{max-width:800px;margin-bottom:clamp(52px,6vw,96px);font-size:clamp(44px,5.3vw,84px);line-height:.92}
.inspiration-case__function{display:grid;grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);gap:clamp(32px,5vw,86px);padding:clamp(42px,5.5vw,82px) 0;border-top:1px solid rgba(247,245,242,.2)}
.inspiration-case__functions>.inspiration-case__function:first-of-type{border-top:0}
.inspiration-case__function-copy{padding-top:4px}
.inspiration-case__function h4{margin:0 0 22px;font-size:clamp(28px,3vw,46px);line-height:1.02;text-align:left}

.inspiration-case__function-copy p{margin:0;color:#a8a8a8;font-size:clamp(16px,1.18vw,19px);line-height:1.65}
.inspiration-case__video{position:relative;align-self:start;overflow:hidden;background:#1b1c20;aspect-ratio:var(--inspiration-video-aspect,16 / 9)}
.inspiration-case__video video{display:block;width:100%;height:100%;background:#1b1c20;object-fit:contain}
.inspiration-case__video button{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:13px;border:0;background:rgba(18,19,20,.34);color:#fff;cursor:pointer;transition:background .2s ease}
.inspiration-case__video button:hover,.inspiration-case__video button:focus-visible{background:rgba(18,19,20,.08)}
.inspiration-case__video button:focus-visible{outline:2px solid #fff;outline-offset:-6px}
.inspiration-case__video button span{display:grid;place-items:center;width:48px;height:48px;border:1px solid rgba(255,255,255,.76);border-radius:50%;font-size:16px;line-height:1;text-indent:2px}
.inspiration-case__video button small{font-size:12px;letter-spacing:.08em;display:none}
.inspiration-case__video button[hidden]{display:none}
.inspiration-case__video button.is-playback-fallback{pointer-events:none;background:linear-gradient(0deg,rgba(18,19,20,.7),transparent);font-size:12px;letter-spacing:.04em}
@media (max-width:760px){.inspiration-case-modal{width:100vw;height:100svh}.inspiration-case-modal__close{top:16px;right:16px;width:42px;height:42px}.inspiration-case__hero,.inspiration-case__built,.inspiration-case__functions{width:calc(100% - 40px)}.inspiration-case__hero{padding-top:108px}.inspiration-case__opening{margin-bottom:28px}.inspiration-case__lead{font-size:16px;line-height:1.55}.inspiration-case__cover{width:100%;border-radius:12px}.inspiration-case__built{display:block;padding-top:72px;padding-bottom:0;border-bottom:0}.inspiration-case__built h3{margin-bottom:42px}.inspiration-case__built dl div{display:block}.inspiration-case__built dd{margin-top:8px}.inspiration-case__function{display:block;padding:48px 0}.inspiration-case__function-copy{margin-bottom:30px}.inspiration-case__function h4{font-size:31px}.inspiration-case__function-copy p{font-size:17px}.inspiration-case__video{width:100%}}
@media (prefers-reduced-motion:reduce){.inspiration-case-modal__close,.inspiration-case__video button{transition:none}}

/* Products → Spiral → AIGC handoff: the pin releases with two cards still
   leaving the upper edge, so keep the next section close to its boundary. */
/* Three seams tightened by --spiral-trim:
   ① products → stage   ② stage → AIGC/photo wall   ③ closing → footer */
.products.section-shell{padding-bottom:max(24px,calc(clamp(104px,13vw,190px) - 84px - var(--spiral-trim)))}
.closing.section-shell{
  padding-top:max(20px,calc(clamp(68px,5vw,92px) - var(--spiral-trim)));
  padding-bottom:max(24px,calc(clamp(104px,13vw,190px) - var(--spiral-trim)));
}

/* Seam ② is NOT a padding problem. Once the cards have lifted out, the stage is
   still a full 100svh box of empty dark — roughly 800px of it — and the AIGC
   section's padding is a rounding error next to that. The only lever is to let
   the AIGC photo-wall section ride up into that empty tail.
   --spiral-overlap is that lever: raise it to close the seam further, drop it to
   0 to restore the original spacing. */
/* The stage is a full 100svh box, and at both ends of the scroll most of it is
   empty dark: ~394px of nothing above the first card on a 430x932 phone, and
   roughly a screen of nothing after the last card lifts out. Padding cannot
   reach either — they are inside the WebGL box. The only lever is to let the
   neighbouring sections ride into that emptiness.
   Portrait needs far more of it than landscape, because the empty band scales
   with viewport height while the copy above it does not. */
:root{
  --spiral-overlap:clamp(220px,18vw,360px);  /* 螺旋尾 → AIGC 照片墙 */
  --spiral-overlap-top:0px;                  /* 桌面上方不需要，构图本来就紧 */
}
@media (max-width:760px){
  :root{
    --spiral-overlap:260px;
    --spiral-overlap-top:150px;
  }
}

/* Both overlaps are scoped to the enhanced stage: if WebGL is unavailable or the
   reader prefers reduced motion, the stage is a tall card list with no empty
   band, and pulling a neighbour in would eat a row of cards. GSAP wraps the
   enhanced stage in `.pin-spacer`, so this must be a descendant match rather
   than a direct-child match; otherwise the overlap silently becomes 0 once the
   real pin is active. Browsers without :has() keep the original spacing — a
   safe degradation. */
.aigc-spiral-band:has(.aigc-spiral-stage.is-enhanced){
  margin-top:calc(-1 * var(--spiral-overlap-top));
}
.aigc-spiral-band:has(.aigc-spiral-stage.is-enhanced) + .playground.section-shell{
  margin-top:calc(-1 * var(--spiral-overlap));
}
/* Products copy above and AIGC/photo wall below both paint over the spiral
   stage's overlap strips. The surface colour is shared, so the seams remain
   invisible while headings and copy stay above the WebGL canvas. */
.products.section-shell,.playground.section-shell{z-index:1}
/* ⚠️ 这里原本是 min-height:calc(85svh - 40px)。在 2000×1164 下它把 section 锁死在
   949px，而内容只要 609px —— 多出来的 340px 死空白全落在内容下方。后果是
   section 高度与 padding 完全解耦：改 padding 只是在盒子里挪空白，"of working."
   到 CONTACT 的距离恒为 854px，怎么调都看不出变化。实测把 padding-bottom 再砍
   36px，总距离 854px → 854px，零变化。
   改由内容定高后 padding 才重新成为有效杠杆（854px → 513px）。 */
@media (min-width:761px){.closing.section-shell{min-height:auto}}
@media (max-width:760px){
  .products.section-shell{padding-bottom:var(--spiral-seam-mobile)}
  .closing.section-shell{padding-bottom:max(24px,calc(60px - var(--spiral-trim)))}
}

body.modal-is-open{overflow:hidden}
.detail-modal{max-height:calc(100svh - 32px);overscroll-behavior:contain}
.detail-modal__close:focus-visible{outline:2px solid var(--blue);outline-offset:3px}
.detail-modal__visual--type{background:linear-gradient(145deg,#ff8a3d,#ffcf7a)}
.detail-modal__visual--portrait{background:linear-gradient(145deg,#dfe7ef,#f6c9b2)}
.detail-modal__visual--motion{background:linear-gradient(145deg,#2aa8a0,#ff8a3d)}
.detail-modal__visual--grid{background:linear-gradient(145deg,#0b0b0e,#26304f)}
.detail-modal__visual--texture{background:linear-gradient(145deg,#5a3fa8,#c9a6ff)}
.detail-modal__visual--type-motion{background:linear-gradient(145deg,#111,#7cf3c4)}

@media (max-width:760px){
  .detail-modal{width:calc(100% - 24px);max-width:none;max-height:calc(100svh - 24px)}
  .detail-modal__inner{max-height:calc(100svh - 24px);min-height:0}
  .detail-modal__visual{min-height:clamp(210px,34svh,300px)}
  .detail-modal__copy{padding:30px 22px 36px}
  .detail-modal__copy h2{font-size:clamp(38px,12vw,54px)}
  .detail-modal__facts div{display:block}
  .detail-modal__facts dd{margin-top:5px;text-align:left}
}

@media (prefers-reduced-motion:reduce){
  .aigc-spiral-card:hover{transform:none}
  .aigc-spiral-stage__canvas,.aigc-spiral-stage__ui{display:none!important}
}

/* Mirror hero — canonical Applied AI first viewport. The WebGL scene is the
   source-locked Panna scene; CSS owns only page integration and fallback. */
.mirror-hero{
  position:relative;
  display:block;
  width:100%;
  min-height:100svh;
  padding:0;
  overflow:hidden;
  isolation:isolate;
  background:var(--ink);
  color:#fff;
  touch-action:pan-y;
}
.mirror-hero__canvas{position:absolute;inset:0;display:block;width:100%;height:100%;outline:0}
.mirror-hero__title{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
/* This is the WebGL fallback, not a loading placeholder. It used to be visible
   during `loading`, so every reload showed a flat CSS "APPLIED AI" that then
   swapped to the rendered scene — read as a flash of stale styling.
   It now stays invisible until the module actually reports a failure, and the
   hero simply holds its global ink field until the first frame lands. The element
   stays in the DOM (and in the accessibility tree) either way, so the live
   region still announces state changes. */
.mirror-hero__status{
  position:absolute;z-index:1;top:50%;left:50%;margin:0;
  transform:translate(-50%,-50%);
  color:#fff;font-family:Syncopate,Arial,sans-serif;
  font-size:clamp(32px,8vw,112px);font-weight:700;line-height:.9;white-space:nowrap;
  opacity:0;pointer-events:none;
}
.mirror-hero[data-mirror-state="fallback"] .mirror-hero__status{opacity:1}
@media (max-width:760px){
  .mirror-hero{min-height:100svh}
  .mirror-hero__status{font-size:clamp(28px,10vw,58px)}
}

/* ═══════════════════════════════════════════════════════════════════════════
   Products — 3D 网格视差场
   移植自 codrops/3DGridContentPreview（MIT）。以下都是原实现的机制，不是近似：
   - 卡片以 Figma 画板归一化百分比坐标定位，桌面与移动端各用一套坐标
   - 移动端舞台按 2453 / 766 横向展开，外层保留原生横向滚动
   - perspective:1000px 在网格容器上；卡片带静态基准姿态（rotationX/Y + z）
   - 磁吸作用在内层图片上，不是整张卡
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  /* Desktop card magnification. 1.5 (a prior value) blew each tile 1.5x past
     its --pc box and made the wall overlap/cram; the --pc positions are laid
     out for ~1.1, which matches the intended scattered gallery. */
  --playground-desktop-card-scale:1.1;
  --playground-phone-gutter:20px;
  /* Rightmost Figma card ends at 284.1273vw; retain exactly 14px after it. */
  --playground-phone-content-end:284.1273vw;
  --playground-phone-end-gap:14px;
}
.product-field{
  grid-column:1 / -1;
  position:relative;
  height:auto;
  aspect-ratio:3580 / 1522;
  margin-top:clamp(28px,4vw,56px);
  margin-inline:calc(-1 * clamp(22px,7vw,100px));
}
.product-field__stage{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  perspective:1000px;              /* 原实现值 */
}
.product-tile{
  position:absolute;
  left:var(--pc-x);
  top:var(--pc-y);
  width:var(--pc-w);
  height:var(--pc-h);
  padding:0;border:0;background:transparent;
  display:block;line-height:0;
  color:var(--warm);text-align:left;cursor:pointer;
}
.product-tile__visual{
  position:relative;
  display:block;
  width:100%;
  height:100%;
  scale:var(--playground-desktop-card-scale);
  transform-origin:center;
  border-radius:10px;              /* 原实现值 */
  overflow:hidden;
  background:linear-gradient(135deg,var(--c1),var(--c2));
  box-shadow:0 18px 40px rgba(0,0,0,.38);
}

/* ⚠️ will-change 原本常驻在 .product-tile 和 .product-tile__visual 上（26 个元素）。
   常驻 = 26 个常驻合成层，而它们带 3D transform，会通过 Overlap 把上下相邻的整段
   section（.aigc-spiral-band 4000×9258、section.closing、.method-gallery…）也一起
   提升成独立图层 —— 实测滚到螺旋区时合成层 205 个。
   现在只在这面墙真正进视口时才提升（script.js 的 IntersectionObserver 挂 .is-live），
   离开就摘掉。别把 will-change 改回无条件常驻。 */
.product-field.is-live .product-tile,
.product-field.is-live .product-tile__visual{will-change:transform}
/* hover 期间由 rAF 每帧写 transform，必须关掉过渡；离开时再交回给过渡做
   1s power4 的回弹（等价于原实现的 gsap timeline） */
.product-tile__visual{transition:transform 1s cubic-bezier(.23,1,.32,1)}
.product-tile.is-magnetic .product-tile__visual{transition:none}
.product-tile__visual::after{
  content:"";position:absolute;inset:0;
  background:radial-gradient(120% 90% at 22% 12%, rgba(255,255,255,.2), transparent 58%);
}
/* The Playground wall is intentionally image-only. Names and indices remain
   available through each button's aria-label and the click-open detail modal. */
.product-tile:focus-visible{outline:2px solid var(--blue);outline-offset:6px}.product-tile[data-coming-soon]{cursor:default}

/* 入场：逐张渐隐浮现（原 demo 没有这段，是你要求保留的） */
.product-tile{opacity:0}
.product-field.is-revealed .product-tile{
  opacity:1;
  transition:opacity .62s ease calc(var(--i) * 68ms);
}

/* 窄屏：不降级成普通列表，而是保留同一面 3D 视觉墙，把它做成可以左右拖动
   探索的画布 —— 舞台比视口宽，用原生横向滚动 + 指针拖拽双通道。
   卡片之间的间距按窄屏重新收紧（span 更大 = 卡更大 = 相对更密）。 */
@media (max-width:760px){
  /* 移动端只留卡片本身：小屏上标题+分类会互相压叠、把画面挤脏，
     信息改由点击弹窗承担。 */
  .product-field{
    /* Figma Phone 一屏：766 × 1365 的可见墙面；完整画布横向展开到 2453。 */
    height:auto;
    min-height:0;
    aspect-ratio:766 / 1365;
    margin-top:32px;
    overflow-x:auto;
    overflow-y:hidden;
    overscroll-behavior-x:contain;      /* 拖到头不要把整页横向带走 */
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
    cursor:grab;
    /* 与当前移动端 section 的 20px gutter 对消，让横向画布从屏幕左缘开始。 */
    margin-inline:calc(-1 * var(--playground-phone-gutter));
  }
  .product-field::-webkit-scrollbar{display:none}
  .product-field.is-dragging{cursor:grabbing}
  .product-field__stage{
    position:relative;
    top:0;left:0;
    width:calc(var(--playground-phone-content-end) + var(--playground-phone-end-gap));
    height:100%;
    min-width:0;
  }
  .product-tile{
    left:var(--phone-x);
    top:var(--phone-y);
    width:var(--phone-w);
    height:var(--phone-h);
    /* A desktop fine pointer can still exist at a narrow responsive viewport.
       Never let the 3D projection enlarge this horizontal scroll surface. */
    transform:none!important;
  }
  .product-tile__visual{scale:1;box-shadow:0 12px 28px rgba(0,0,0,.34)}
  /* The source video has a light edge in its outer pixels. Crop those pixels
     inside the existing rounded visual without changing its aspect ratio. */
  .product-tile[data-aigc-case="card-playground"] .product-tile__visual,
  .product-tile[data-aigc-case="card-playground"] .product-tile__video{background:#0d0d0f}
  .product-tile[data-aigc-case="card-playground"] .product-tile__video{transform:scale(1.03);transform-origin:center}
  /* 拖动时禁止选中与图片拖拽，否则手感会被浏览器默认行为打断 */
  .product-field,.product-field *{user-select:none;-webkit-user-drag:none}
}
@media (prefers-reduced-motion:reduce){
  .product-tile,.product-tile__visual{transition:none!important;transform:none!important}
  .product-tile{opacity:1!important}
}

/* --------------------------------------------------------------------------
   Tool cards
   The five cards are ordinary page content and the detail view is an overlay on
   the document, not on a sub-surface. The previous build embedded a WebGL
   runtime in an <iframe>: its detail panel was `position: fixed` inside that
   frame, so it was pinned to the band's rectangle rather than the viewport —
   opening a card mid-scroll drew the "modal" inside the band with the heading
   above it and the next section still scrolling below. That is structural, not
   a spacing bug, so the structure changed. Layout numbers come from the Figma
   `Tool` board and are resolved in build-tool-cards.mjs.
   -------------------------------------------------------------------------- */
.tool{
  padding-bottom:0;
  overflow:visible;
}
.tool-card-band{
  position:relative;
  grid-column:1 / -1;
  display:flex;
  align-items:center;
  justify-content:center;
  /* Full-bleed by cancelling the shell's own gutter rather than 100vw, which
     overflows by the scrollbar width. */
  /* The parent shell contributes its row-gap before this full-width band. The
     lead-in target is 160px (2× the measured 80px desktop gap), so cancel only
     the shared portion here instead of changing the spacing rhythm of every
     other section. */
  margin-top:calc(-1 * (clamp(48px,8vw,110px) - 160px));
  margin-inline:calc(-1 * clamp(22px,7vw,100px));
  /* Trim another 30px from the current stage tail so Products follows the
     cards sooner without changing card size or the immersive stage treatment. */
  height:clamp(760px,calc(100svh - 90px),990px);
  /* Hover lifts the card by 0.11 × its height. Keep that authored motion
     intact, but do not cut its top edge at the stage boundary. */
  overflow:visible;
  background:var(--ink);
}
.tool-deck{
  /* Card width is the one dimension everything else derives from. 15.3vw is the
     share the board gives it (274.4 / 1791); the floor keeps the deck readable
     on narrow desktops by letting it claim more width instead of shrinking, and
     the ceiling stops it ballooning on very wide screens. The floor is 176px
     rather than the board's own ratio because rotation widens each card's
     bounding box by ~0.11 × its width — the fan measures 5.4 card widths edge to
     edge, not 5.18 — and at 1024 a larger floor pushed the outer cards to within
     8px of the viewport. */
  --tool-card-w:clamp(176px,15.3vw,300px);
  --tool-card-step:1.045;
  --tool-card-rot:4.4deg;
  --tool-card-arc:0.0385;
  --tool-card-radius:calc(var(--tool-card-w) * .045);
  position:relative;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:flex-start;
  gap:clamp(24px,5vh,44px);
  width:100%;
  height:100%;
}
.tool-deck__track{
  position:relative;
  width:100%;
  /* Card height plus the arc drop and the hover lift, so nothing clips. */
  height:calc(var(--tool-card-w) * 88 / 63 * 1.34);
  /* The track is deliberately taller than the card so the fan and hover lift
     have room. Pull its box up by the centering offset so the middle card,
     rather than the track's empty safety area, starts at the 40px lead-in. */
  margin-top:calc(-1 * var(--tool-card-w) * 88 / 63 * .17);
  margin-right:0;
  margin-bottom:0;
  margin-left:0;
  padding:0;
  list-style:none;
}
.tool-deck__item{
  position:absolute;
  left:50%;
  top:50%;
  width:var(--tool-card-w);
  /* Centre card in front, outer cards behind — the only stacking rule needed
     now that the spread barely overlaps. */
  z-index:calc(10 - var(--ad,0));
  transform:
    translate(-50%,-50%)
    translateX(calc(var(--d,0) * var(--tool-card-step) * var(--tool-card-w)))
    translateY(calc(var(--drop,0) * var(--tool-card-arc) * var(--tool-card-w)))
    rotate(calc(var(--d,0) * var(--tool-card-rot)));
}
.tool-deck__item:hover,
.tool-deck__item:focus-within{z-index:20}
.tool-deck__card{
  display:block;
  width:100%;
  padding:0;
  border:0;
  background:none;
  cursor:pointer;
  opacity:0;
  /* --tool-card-lift carries both the entrance rise and the hover lift, so the
     two never fight over `transform` (the layout transform lives on the item). */
  transform:translateY(var(--tool-card-lift,22px));
  transition:opacity .7s var(--ease),transform .55s var(--ease);
  transition-delay:calc(var(--i,0) * 80ms);
}
.reveal.is-visible .tool-deck__card{
  opacity:1;
  --tool-card-lift:0px;
}
/* Drawn out of the deck: the flying clone is standing in for it. Kept at
   opacity 0 rather than visibility/display so it stays focusable and holds its
   slot for the return flight to measure. */
.reveal.is-visible .tool-deck__card.is-drawn{opacity:0;transition:none}
.tool-deck__card:focus-visible{outline:1px solid rgba(246,241,232,.75);outline-offset:6px}
.tool-deck__card img{
  display:block;
  width:100%;
  height:auto;
  aspect-ratio:63/88;
  object-fit:cover;
  border-radius:var(--tool-card-radius);
  box-shadow:0 22px 56px rgba(0,0,0,.46);
  transition:box-shadow .45s var(--ease);
}
@media (hover:hover){
  /* 0.11 × card height — the restraint value the reference project settled on
     after its own hover was judged "jumpy". 88/63 converts it to card widths. */
  .reveal.is-visible .tool-deck__card:hover{
    --tool-card-lift:calc(var(--tool-card-w) * -0.11 * 88 / 63);
    transition-delay:0s;
  }
  .tool-deck__card:hover img{box-shadow:0 34px 74px rgba(0,0,0,.56)}
}
.tool-deck__progress{display:none}
.tool-deck__progress.product-field__progress{display:none}
.tool-deck__hint{
  margin:0;
  color:rgba(246,241,232,.5);
  font-size:clamp(11px,.75vw,13px);
  line-height:1.4;
  letter-spacing:.02em;
  text-align:center;
}
.tool-deck__status{
  position:absolute;
  inset:auto auto 24px 50%;
  margin:0;
  color:rgba(246,241,232,.5);
  font-size:11px;
  letter-spacing:.12em;
  text-transform:uppercase;
  transform:translateX(-50%);
  transition:opacity .35s ease;
}
.tool-card-band.is-ready .tool-deck__status{opacity:0}

/* --bp-lg (64rem) — below it the fan cannot hold five readable faces and there
   is no hover to single one out, so the deck becomes a snap carousel. This is a
   structural change of the same component, not a resize. Figma `Tool_Phone`. */
@media (max-width:63.999rem){
  .tool-deck__hint{display:none}
  .tool-card-band{
    height:calc(100svh - 150px);
    min-height:540px;
    /* Keep the same 160px title-to-deck lead-in on tablet widths. */
    margin-top:calc(-1 * (clamp(48px,8vw,110px) - 160px));
  }
  .tool-deck{
    --tool-card-w:min(70%,340px);
    --tool-deck-inset:clamp(18px,10%,72px);
    --tool-card-radius:14px;
  }
  .tool-deck__track{
    display:flex;
    gap:clamp(14px,4%,28px);
    height:auto;
    margin:0;
    padding:0 0 6px;
    overflow-x:auto;
    overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;
    scroll-padding-inline-start:var(--tool-deck-inset);
    scrollbar-width:none;
    -webkit-overflow-scrolling:touch;
  }
  .tool-deck__track::-webkit-scrollbar{display:none}
  .tool-deck__item{
    position:static;
    flex:0 0 var(--tool-card-w);
    width:auto;
    transform:none;
    scroll-snap-align:start;
    z-index:auto;
  }
  .tool-deck__item:first-child{margin-inline-start:var(--tool-deck-inset)}
  .tool-deck__item:last-child{margin-inline-end:var(--tool-deck-inset)}
  .tool-deck__card img{border:1px solid rgba(246,241,232,.16)}
  .tool-deck__progress{
    position:relative;
    display:block;
    align-self:center;
    width:min(46%,240px);
    height:1px;
    background:rgba(246,241,232,.2);
  }
  .tool-deck__progress i{
    position:absolute;
    inset:0 auto 0 0;
    display:block;
    width:calc(100% / var(--tool-deck-count,5));
    background:var(--warm);
    transform:translateX(calc(var(--tool-deck-index,0) * 100%));
    transition:transform .38s var(--ease);
  }
}

@media (max-width:760px){
  .tool-deck__progress.product-field__progress{
    display:block;
    grid-column:1 / -1;
    justify-self:center;
    margin:clamp(20px,5vw,28px) auto 0;
  }
  /* Tap hint host positions. The hint itself is a <span class="tap-hint">
     injected by script.js (see "Tap hints" at the end of the file). */
  .tool-deck__card--agent{position:relative;--tap-hint-x:78%;--tap-hint-y:55%}
  /* Bottom-right corner, clear of the stamp; a touch smaller to fit the tile. */
  .product-tile[data-aigc-case="card-playground"]{--tap-hint-x:84%;--tap-hint-y:79%;--tap-hint-host-size:clamp(2.75rem,2.3rem + 2vw,3.125rem)}
}

/* Tap hint v2 — AssistiveTouch-style layered disc + double ripple (mobile only).
   One anchor point, both layers centred with translate + border-box sizing,
   so every ring is exactly concentric.
   States (script.js): --tap-hint-fade = scroll-linked fade as the card
   leaves the top of the screen; .is-away = fully faded (animation paused); .is-dismissed = the user opened
   any detail in that module — gone until the page is loaded again. */
.tap-hint{display:none}
@media (max-width:760px){
  .tap-hint{
    --tap-hint-size:var(--tap-hint-host-size,clamp(3.25rem,2.6rem + 3vw,3.75rem));
    position:absolute;
    z-index:3;
    top:var(--tap-hint-y,50%);
    left:var(--tap-hint-x,50%);
    display:block;
    box-sizing:border-box;
    width:var(--tap-hint-size);
    aspect-ratio:1;
    translate:-50% -50%;
    pointer-events:none;
    /* --tap-hint-fade is written by script.js as the card scrolls off the
       top of the screen; the short transition smooths the threshold steps. */
    opacity:var(--tap-hint-fade,1);
    transition:opacity .18s linear;
  }
  .tap-hint.is-dismissed{display:none}
  .tap-hint::before,
  .tap-hint::after{
    content:"";
    position:absolute;
    inset:0;
    box-sizing:border-box;
    border-radius:50%;
  }
  /* The disc: dark glass base + 3 concentric layers drawn in ONE element. */
  .tap-hint::before{
    border:1px solid rgba(246,241,232,.28);
    background:
      radial-gradient(circle closest-side,rgba(255,252,246,.96) 0 27%,rgba(255,252,246,0) 29%),
      radial-gradient(circle closest-side,rgba(246,241,232,0) 0 43%,rgba(246,241,232,.42) 44% 47%,rgba(246,241,232,0) 48%),
      radial-gradient(circle closest-side,rgba(246,241,232,.16) 0 68%,rgba(246,241,232,0) 70%),
      rgba(18,18,20,.42);
    box-shadow:0 .5rem 1.5rem rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.12);
    -webkit-backdrop-filter:blur(8px) saturate(1.2);
    backdrop-filter:blur(8px) saturate(1.2);
    animation:tap-hint-disc 3.6s cubic-bezier(.33,0,.2,1) infinite;
  }
  /* The ripple: two quick waves, then a rest. */
  .tap-hint::after{
    border:1px solid rgba(246,241,232,.7);
    opacity:0;
    animation:tap-hint-ripple 3.6s cubic-bezier(.2,.6,.3,1) infinite;
  }
  /* Don't burn frames on a hint nobody can see. */
  .tap-hint.is-away::before,.tap-hint.is-away::after{animation-play-state:paused}
}
@keyframes tap-hint-disc{
  0%,100%{scale:1;opacity:.82}
  5%{scale:.9;opacity:1}
  14%{scale:1;opacity:.92}
  22%{scale:.9;opacity:1}
  32%,96%{scale:1;opacity:.82}
}
@keyframes tap-hint-ripple{
  0%{scale:1;opacity:0;box-shadow:0 0 0 0 rgba(246,241,232,.18)}
  5%{scale:1;opacity:.75;box-shadow:0 0 0 0 rgba(246,241,232,.18)}
  20%{scale:1.85;opacity:0;box-shadow:0 0 0 .5rem rgba(246,241,232,0)}
  21%{scale:1;opacity:0;box-shadow:0 0 0 0 rgba(246,241,232,.18)}
  23%{scale:1;opacity:.75;box-shadow:0 0 0 0 rgba(246,241,232,.18)}
  40%{scale:1.85;opacity:0;box-shadow:0 0 0 .5rem rgba(246,241,232,0)}
  100%{scale:1.85;opacity:0}
}
@media (prefers-reduced-motion:reduce){
  .tap-hint::before{animation:none;opacity:.9}
  .tap-hint::after{animation:none;opacity:0}
}

@media (max-width:760px){
  /* The stacked section collapses the copy's 58px bottom margin. Set a larger
     explicit value so the collapsed gap really becomes 116px (2×58px). */
  .tool-card-band{margin-top:116px}
}

/* --------------------------------------------------------------------------
   Tool detail overlay — a child of <body>, fixed to the real viewport.
   -------------------------------------------------------------------------- */
body.tool-card-detail-open{
  position:fixed;
  top:var(--tool-card-scroll-lock);
  right:0;
  left:0;
  width:100%;
  overflow:hidden;
}
.tool-modal{
  position:fixed;
  /* Above the shared navigation's own layer (main-navigation.css uses 10020 for
     the overlay and 10030 for the toggle). A modal that leaves the site menu
     button floating on top of it is not modal — and the close control would sit
     directly under the hamburger. Raising this one element is the narrow fix;
     lowering the shared nav would change every page. */
  z-index:10040;
  --tool-modal-tilt:-6deg;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:clamp(52px,10svh,110px) clamp(14px,5vw,80px) clamp(28px,7svh,80px);
  background:rgba(12,13,14,.96);
  backdrop-filter:blur(14px);
  opacity:0;
  visibility:hidden;
  transition:opacity .34s var(--ease),visibility .34s var(--ease);
}
.tool-modal.is-open{opacity:1;visibility:visible}
.tool-modal__inner{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:clamp(48px,7vw,140px);
  width:100%;
  max-width:1360px;
  /* Definite, not `max-height`. A percentage max-height on the panel resolves
     against an auto-height parent as `none`, which let the record grow past the
     viewport at 375 × 667 instead of scrolling inside itself. */
  height:100%;
}
.tool-modal__figure{
  /* Height-driven: the card's constrained axis is vertical, so size it off the
     viewport height and let 63:88 derive the width. Both dimensions are stated
     explicitly — leaving the width to `aspect-ratio` inside a row flex made the
     flex layout under-reserve the column, and the card overlapped the record. */
  --tool-modal-card-h:min(62svh,520px);
  flex:0 0 auto;
  width:calc(var(--tool-modal-card-h) * 63 / 88);
  height:var(--tool-modal-card-h);
  max-height:100%;
  margin:0;
  perspective:1500px;
  opacity:0;
  transition:opacity .5s var(--ease) .06s;
}
.tool-modal.is-open .tool-modal__figure{opacity:1}
/* While the clone is in flight the real figure is held at its resting pose but
   invisible — that pose is what flyToolCard measures as the landing rectangle. */
.tool-modal.is-transiting .tool-modal__figure{opacity:0;transition:none}
.tool-modal.is-landed .tool-modal__figure{opacity:1;transition:none}
/* One transform per layer, per the reference project's own rule: drift owns
   translateY, sway owns the two rotations, flip owns tilt + turn. Merging them
   makes one silently overwrite another. The two idle loops run at 5.1s and 7.3s
   so they never re-sync into a mechanical beat. Both keyframe sets start and end
   neutral, so the landing pose of the flying clone matches exactly. */
.tool-modal__float,
.tool-modal__sway{
  width:100%;
  height:100%;
  transform-style:preserve-3d;
}
.tool-modal.is-open:not(.is-transiting) .tool-modal__float{animation:tool-card-drift 5.1s ease-in-out infinite}
.tool-modal.is-open:not(.is-transiting) .tool-modal__sway{animation:tool-card-sway 7.3s ease-in-out infinite}
@keyframes tool-card-drift{
  0%,100%{transform:translateY(0)}
  25%{transform:translateY(calc(var(--tool-modal-card-h) * -.0275))}
  75%{transform:translateY(calc(var(--tool-modal-card-h) * .0275))}
}
@keyframes tool-card-sway{
  0%,100%{transform:rotateZ(0deg) rotateY(0deg)}
  25%{transform:rotateZ(-.7deg) rotateY(-2.25deg)}
  75%{transform:rotateZ(.7deg) rotateY(2.25deg)}
}
.tool-transit{
  position:fixed;
  z-index:10041;
  margin:0;
  pointer-events:none;
  transform-style:preserve-3d;
  will-change:transform;
}
.tool-modal__flip{
  position:relative;
  display:block;
  width:100%;
  height:100%;
  padding:0;
  border:0;
  background:none;
  cursor:pointer;
  transform-style:preserve-3d;
  /* Resting tilt — the card is held, not filed. Read by script.js so the
     flying clone lands on exactly this angle. */
  transform:rotate(var(--tool-modal-tilt));
  transition:transform .82s var(--ease);
}
.tool-modal__flip.is-flipped{transform:rotate(var(--tool-modal-tilt)) rotateY(180deg)}
.tool-modal__flip:focus-visible{outline:1px solid rgba(246,241,232,.75);outline-offset:8px}
.tool-modal__face{
  position:absolute;
  inset:0;
  overflow:hidden;
  border-radius:16px;
  backface-visibility:hidden;
  box-shadow:0 30px 78px rgba(0,0,0,.52);
}
.tool-modal__face img{display:block;width:100%;height:100%;object-fit:cover}
.tool-modal__face--back{transform:rotateY(180deg)}
.tool-modal__record{
  position:relative;
  flex:0 1 min(46vw,640px);
  display:flex;
  max-height:100%;
}
.tool-modal__panel{
  flex:1 1 auto;
  width:100%;
  max-height:100%;
  overflow:hidden auto;
  overscroll-behavior:contain;
  padding:clamp(26px,3vw,46px) clamp(24px,2.8vw,44px) clamp(30px,3.2vw,50px);
  border:1px solid rgba(246,241,232,.22);
  border-radius:20px;
  background:rgba(18,19,20,.86);
  color:var(--warm);
  opacity:0;
  transform:translateY(24px);
  /* Delay is set by script.js: it waits for the card to be most of the way
     home when a flight is running, and is near-immediate when it is not. */
  transition:opacity .48s var(--ease) var(--tool-modal-panel-delay,100ms),transform .48s var(--ease) var(--tool-modal-panel-delay,100ms);
  scrollbar-color:rgba(246,241,232,.42) transparent;
  scrollbar-width:thin;
}
.tool-modal.is-open .tool-modal__panel{opacity:1;transform:none}
/* Anchored to the record, not the page. A close control parked in the browser's
   top-right corner reads as chrome; on the record's corner it reads as belonging
   to the thing it closes — and it matches the phone board. */
.tool-modal__close{
  position:absolute;
  z-index:2;
  top:clamp(12px,2.2%,20px);
  right:clamp(12px,2.2%,20px);
  display:flex;
  align-items:center;
  justify-content:center;
  width:44px;
  height:44px;
  border:1px solid rgba(246,241,232,.28);
  border-radius:50%;
  background:rgba(18,19,20,.72);
  color:var(--warm);
  font-size:20px;
  line-height:1;
  cursor:pointer;
  opacity:0;
  transform:translateY(10px) scale(.86);
  pointer-events:none;
  /* The close control is part of the record's entrance group. It uses the
     panel's exact delay so it cannot arrive as detached browser chrome before
     the detail UI has entered. */
  transition:
    opacity .48s var(--ease) var(--tool-modal-panel-delay,100ms),
    transform .48s var(--ease) var(--tool-modal-panel-delay,100ms),
    border-color .3s ease,
    background .3s ease;
}
.tool-modal.is-open .tool-modal__close{opacity:1;transform:none;pointer-events:auto}
.tool-modal__close:hover{border-color:rgba(246,241,232,.6)}
/* The kicker ("APPLIED AI PRODUCTION STACK | 01") and its rule sat here and
   were removed 2026-08-21 — the modal now opens straight on the title. The
   panel's own padding-top already gives the first child its top spacing, so
   the title's margin is zeroed only when it is that first child; this keeps
   the shared .tool-modal__title rule generic in case a kicker is ever
   reintroduced above it elsewhere. */
.tool-modal__panel > .tool-modal__title:first-child{ margin-top:0; }
.tool-modal__title{
  margin:clamp(20px,2.2vw,30px) 0 0;
  max-width:12ch;
  font-family:var(--serif);
  font-weight:400;
  font-size:clamp(38px,4.1vw,64px);
  line-height:.94;
  letter-spacing:-.035em;
  text-wrap:balance;
}
.tool-modal__sub{
  margin:16px 0 0;
  max-width:38em;
  font-size:clamp(13px,.92vw,15px);
  line-height:1.5;
  color:rgba(246,241,232,.66);
}
.tool-modal__rule{
  margin:clamp(22px,2.4vw,30px) 0;
  border:0;
  border-top:1px solid rgba(246,241,232,.16);
}
.tool-modal__specs{display:grid;gap:clamp(20px,2.4vw,30px);margin:0}
.tool-modal__specs dt{
  margin:0 0 10px;
  font-size:10px;
  line-height:1.3;
  letter-spacing:.14em;
  font-weight:600;
  color:rgba(246,241,232,.5);
}
.tool-modal__specs dd{
  margin:0;
  font-size:clamp(13px,1vw,16px);
  line-height:1.55;
  white-space:pre-line;
  color:rgba(246,241,232,.88);
}
.tool-modal__structure-list{
  display:grid;
  gap:.4em;
  margin:0;
  padding:0;
  list-style:none;
  white-space:normal;
}
.tool-modal__structure-list li{
  position:relative;
  padding-left:1.15em;
}
.tool-modal__structure-list li::before{
  content:"•";
  position:absolute;
  left:.1em;
  color:rgba(246,241,232,.5);
}
.tool-modal__principle dd{
  max-width:16em;
  font-family:var(--serif);
  font-size:clamp(21px,2vw,32px);
  line-height:1.08;
  letter-spacing:-.025em;
  white-space:normal;
  color:var(--warm);
}
/* Below --bp-lg the overlay drops the card column: the phone board shows the
   record alone, and a 63:88 card plus a scrolling record cannot both be
   legible in one portrait viewport. Figma `Tool_Phone_Detail`. */
@media (max-width:63.999rem){
  .tool-modal{padding:clamp(44px,9svh,96px) clamp(14px,6%,44px) clamp(28px,6svh,72px)}
  .tool-modal__figure{display:none}
  .tool-modal__record{flex:1 1 auto}
  .tool-modal__panel{
    border-radius:24px;
    background:#121314;
    padding:clamp(26px,7%,46px) clamp(22px,6%,42px) clamp(30px,8%,50px);
  }
  .tool-modal__kicker{padding-right:52px}
  .tool-modal__title{font-size:clamp(38px,10vw,60px)}
  .tool-modal__sub{font-size:clamp(13px,3.6vw,15px)}
  .tool-modal__specs dd{font-size:clamp(13px,3.6vw,15px)}
  .tool-modal__principle dd{font-size:clamp(21px,6vw,28px)}
}

@media (prefers-reduced-motion:reduce){
  .tool-deck__card,
  .tool-deck__card img,
  .tool-deck__progress i,
  .tool-modal,
  .tool-modal__figure,
  .tool-modal__panel,
  .tool-modal__flip{transition:none}
  .tool-deck__card{--tool-card-lift:0px}
  .tool-modal__float,.tool-modal__sway{animation:none!important}
}

/* ==========================================================================
   Practice map — "One practice, four parts"
   ==========================================================================
   Figma: Dilivery › One practice, four parts_PC (94:241) and _Phone (94:285).

   WHAT THIS MODULE IS NOW
   It is a text panel, not navigation. The four <a href="#..."> cards were
   removed on 2026-08-20; nothing here scrolls the page any more.

   WHERE THE NUMBERS COME FROM (do not re-guess them)
   The two Figma boards are the two responsive anchors:
     · Phone board  = 402px viewport, values read 1:1
     · PC board     = 3572px artboard whose 3065px panel equals the 1240px
                      content column at a 1440px viewport → scale 0.40314
   Every --pm-* token below is the straight line through those two anchors,
   written as clamp(min, intercept + slope*vw, max). The px the comments quote
   are the Figma values, NOT magic numbers — change the anchors, re-derive the
   line, never hand-tune one width. See RESPONSIVE.md §1 and §2.

   The dividers sit on the column boundaries because that is where Figma puts
   them: in the PC board they land at 24.8% / 48.9% / 74.5% of the panel, i.e.
   the quarter marks. Equal columns therefore reproduce the design AND stay
   fluid, so no width needs its own rule.

   LIGHT TREATMENT
   The surface reuses the shared .shiny-cta system from assets/main-footer.css
   (the footer email button): rotating conic edge beam, masked dot field,
   rotating blue bloom, black ground. It is NOT duplicated here — this file only
   neutralises the pill-shaped box that .shiny-cta also carries, and re-points
   its inset edge at the Figma #707070 hairline.
   -------------------------------------------------------------------------- */

:root{
  /* Fluid scale, Phone(402) → PC(1440). Comment = the two Figma anchors. */
  --pm-title:      clamp(1.201rem, 1.002rem + 0.791vw, 1.714rem);  /* 19.21 → 27.42px */
  --pm-sub:        clamp(0.742rem, 0.619rem + 0.488vw, 1.058rem);  /* 11.87 → 16.93px */
  --pm-stack-gap:  clamp(0.247rem, 0.207rem + 0.158vw, 0.353rem);  /*  3.96 →  5.64px */
  --pm-pad-block:  clamp(1.781rem, 1.618rem + 0.650vw, 2.203rem);  /* 28.50 → 35.25px */
  --pm-row-gap:    clamp(3.250rem, 2.713rem + 2.139vw, 4.637rem);  /* 52.00 → 74.20px */
  --pm-rule-h:     clamp(1.656rem, 0.746rem + 3.622vw, 4.006rem);  /* 26.50 → 64.10px */
  --pm-radius:     clamp(0.530rem, 0.442rem + 0.348vw, 0.756rem);  /*  8.48 → 12.09px */
  --pm-col-pad:    clamp(0.500rem, 0.280rem + 1.100vw, 1.500rem);  /* breathing room only */
  --pm-rule:       #707070;   /* Figma stroke — same value as the panel border */
  --pm-sub-ink:    #999999;   /* Figma color/grey/60 */
  --pm-slash-tilt: 17.8deg;   /* atan(8.5 / 26.5) — the Phone board's "/" */
}

/* Panel ------------------------------------------------------------------ */
/* .practice-map.shiny-cta (0,2,0) is required: main-footer.css loads after
   this file, so a single-class selector would lose to .shiny-cta on order. */
.practice-map.shiny-cta{
  --shiny-cta-bg-subtle: var(--pm-rule);   /* the shared inset edge becomes the Figma hairline */
  grid-column: 1 / -1;
  display: block;
  width: 100%;
  max-width: none;
  padding: var(--pm-pad-block) 0;
  border-radius: var(--pm-radius);
  font: inherit;
  cursor: default;
}

/* The panel is not a control: hold the resting light state under the pointer
   instead of firing the button's hover flare across a 1200px-wide block. */
.practice-map.shiny-cta:is(:hover, :focus-visible){
  --gradient-percent: 5%;
  --gradient-angle-offset: 0deg;
  --gradient-shine: white;
}
.practice-map.shiny-cta:is(:hover, :focus-visible),
.practice-map.shiny-cta:is(:hover, :focus-visible)::before,
.practice-map.shiny-cta:is(:hover, :focus-visible)::after{
  animation-play-state: running, paused;
}
.practice-map.shiny-cta:active{ translate: none; }

/* Four parts ------------------------------------------------------------- */
.practice-map__list{
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));  /* minmax(0,·) so a column may shrink */
  margin: 0;
  padding: 0;
  list-style: none;
}

.practice-map__item{
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--pm-stack-gap);
  padding-inline: var(--pm-col-pad);
  text-align: center;
}

/* Hairline on every interior column boundary. */
.practice-map__item + .practice-map__item::before{
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 50%;
  width: 1px;
  height: var(--pm-rule-h);
  translate: -50% -50%;
  background: var(--pm-rule);
}

.practice-map__title{
  font-family: DunbenSerif, "Dunben Serif SC", Georgia, serif;   /* Figma: Libertinus Sans Bold */
  font-weight: 700;
  font-size: var(--pm-title);
  line-height: 1.08;
  letter-spacing: -.02em;
  text-transform: uppercase;
  color: #fff;
}

.practice-map__sub{
  font-family: var(--sans);                    /* Figma: DM Sans Regular */
  font-weight: 400;
  font-size: var(--pm-sub);
  line-height: 1.08;
  letter-spacing: -.02em;
  color: var(--pm-sub-ink);
}

/* Structural change only: one row of four becomes two rows of two, the column
   hairline becomes the Phone board's tilted slash, and a horizontal rule
   appears between the rows. Sizes are already fluid above — nothing is resized
   here. RESPONSIVE.md §3. */
@media (max-width: 47.999rem){
  .practice-map__list{
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: var(--pm-row-gap);
  }

  /* Keep the DOM's Method → Tool → Products → Playground reading order. */

  .practice-map__item + .practice-map__item::before{ content: none; }

  /* The slashes separate the second item in each row. */
  .practice-map__item.practice-map__item--tool::before,
  .practice-map__item.practice-map__item--aigc::before{
    content: "";
    position: absolute;
    inset-inline-start: 0;
    top: 50%;
    width: 1px;
    height: var(--pm-rule-h);
    translate: -50% -50%;
    rotate: var(--pm-slash-tilt);
    background: var(--pm-rule);
  }

  .practice-map__list::after{
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 89.4%;      /* Figma Phone: 311 of the 348 panel */
    height: 1px;
    translate: -50% -50%;
    background: var(--pm-rule);
  }
}

/* Method now carries the same kicker as Tool / Products / AIGC.
   .method__intro zeroes the h2 margin (the intro is deliberately tight), so the
   heading would sit flush against the new kicker. Restore exactly the shared
   .section-heading h2 top margin — the same 18px every other section already
   gets — and only when a kicker actually precedes the heading. */
.method__intro .section-heading > .eyebrow + h2{ margin-top: 18px; }

/* Applied AI's stacked section-intro template. The 52px rhythm is the former
   58px mobile gap less the requested 6px; every title-to-copy pair below uses
   it, while the following content keeps its existing breathing room. */
:root{ --applied-ai-title-copy-gap: 52px; }

@media (max-width:760px){
  /* The stacked shells use 20px gutters, so the full-bleed Tool stage must
     mirror that exact value instead of the desktop fluid gutter. */
  .tool-card-band{ margin-inline:-20px; }
  .section-heading{ margin-bottom:var(--applied-ai-title-copy-gap); }
  .method__intro .method__copy{ padding-top:0; }
  .closing{ row-gap:0; }
  .closing__copy{ margin-top:0; }
}
/* ── AIGC "What I explore" video-cover tile ──────────────────────────────
   Fills the tile with a real demo video instead of the flat gradient. It
   still lives inside the same .product-tile the magnetic-parallax system in
   script.js already drives (transform is read/written on .product-tile__visual
   itself), so the video just rides along as an absolutely-positioned child —
   no changes needed there. The visual now fills each Figma-defined card box;
   object-fit:cover preserves the media ratio without stretching. */
.product-tile--video .product-tile__visual{aspect-ratio:auto}
.product-tile__video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;background:#0e2a6b}

/* ── AIGC case detail modal ───────────────────────────────────────────────
   A shared, data-driven template (script.js `aigcCases` + `openAigcCaseModal`)
   for every future AIGC case tile, not just this one. Composition borrows
   the Tool card modal's opened-state LAYOUT — an independent media block
   beside a separate rounded detail record, both centered over a blurred
   backdrop with a gap between them, not one shared card split into two flush
   panels — but explicitly WITHOUT Tool's tilt, perspective or idle floating
   motion, per direct request: the video sits flat and static at all times,
   no rotation, no 3D depth, no drift/sway, no flip (there is no back face).
   Sizing mirrors Tool's own rule set (--bp-lg switch, 44×44 close target,
   clamp() type) with one deliberate difference: below --bp-lg this modal
   keeps its video (Tool drops its card entirely there) — full-width at the
   top, with the whole dialog scrolling underneath it so the reader can swipe
   straight down through video → title → description → Built With. Native
   <dialog>, so it follows the existing .detail-modal / .inspiration-case-modal
   convention (styled dialog + ::backdrop) rather than Tool's hand-built
   overlay div. */
.aigc-case-modal{--aigc-case-video-aspect:858 / 684;--aigc-case-video-height:min(100%,459px,35.97vw);width:min(1600px,94vw);max-width:none;height:min(88svh,760px);max-height:none;margin:auto;padding:0;border:0;background:transparent;color:var(--warm)}
.aigc-case-modal::backdrop{background:rgba(8,9,11,.82);backdrop-filter:blur(12px)}
.aigc-case-modal__inner{position:relative;display:flex;align-items:center;justify-content:center;gap:clamp(40px,6vw,120px);width:100%;height:100%}
.aigc-case-modal__figure{flex:0 0 auto;width:auto;height:var(--aigc-case-video-height);aspect-ratio:var(--aigc-case-video-aspect);max-width:none;margin:0}
.aigc-case-modal__frame{position:relative;width:100%;height:100%;border-radius:16px;overflow:hidden;background:#0b0c0e;box-shadow:0 20px 54px rgba(0,0,0,.4)}
.aigc-case-modal__video{display:block;width:100%;height:100%;object-fit:contain}
.aigc-case-modal__record{position:relative;flex:1 1 min(46%,640px);min-width:0;max-width:640px;max-height:100%;display:flex}
.aigc-case-modal__close{position:absolute;z-index:3;top:clamp(12px,2.2%,20px);right:clamp(12px,2.2%,20px);display:grid;place-items:center;width:44px;height:44px;padding:0;border:1px solid rgba(247,245,242,.36);border-radius:50%;background:rgba(18,19,20,.74);color:#f7f5f2;font-size:24px;line-height:1;cursor:pointer;transition:background .2s ease,color .2s ease,border-color .2s ease}
.aigc-case-modal__close:hover{border-color:#fff;background:#fff;color:var(--ink)}
.aigc-case-modal__close:focus-visible{outline:2px solid #fff;outline-offset:4px}
.aigc-case-modal__panel{flex:1 1 auto;width:100%;max-height:100%;overflow-y:auto;overscroll-behavior:contain;padding:clamp(28px,3vw,46px) clamp(26px,2.8vw,44px) clamp(30px,3.2vw,50px);border:1px solid rgba(246,241,232,.22);border-radius:20px;background:rgba(18,19,20,.86);color:var(--warm);scrollbar-color:rgba(246,241,232,.42) transparent;scrollbar-width:thin}
.aigc-case-modal__title{margin:0;font-family:var(--serif);font-weight:400;font-size:clamp(34px,3.6vw,54px);line-height:.96;letter-spacing:-.03em}
.aigc-case-modal__description{margin:clamp(14px,1.6vw,20px) 0 0;max-width:46em;font-size:clamp(14px,1.05vw,16px);line-height:1.6;color:rgba(246,241,232,.82)}
.aigc-case-modal__rule{margin:clamp(24px,2.6vw,32px) 0;border:0;border-top:1px solid rgba(246,241,232,.16)}
.aigc-case-modal__built-title{margin:0 0 clamp(16px,1.8vw,22px);font-family:var(--serif);font-weight:400;font-size:clamp(20px,1.6vw,24px);letter-spacing:-.01em;color:var(--warm)}
.aigc-case-modal__specs{display:grid;gap:clamp(16px,1.8vw,22px);margin:0}
.aigc-case-modal__specs dt{margin:0 0 6px;font-size:10px;line-height:1.3;letter-spacing:.14em;font-weight:600;text-transform:uppercase;color:rgba(246,241,232,.5)}
.aigc-case-modal__specs dd{margin:0;font-size:clamp(13px,1vw,15px);line-height:1.55;color:rgba(246,241,232,.88)}
/* Below --bp-lg (64rem / 1024px, same threshold the Tool modal switches at):
   row becomes a full-screen column — dialog fills the viewport (no radius,
   no margin) the way the existing .inspiration-case-modal already does on
   mobile. A dedicated header strip reserves room for the close button above
   the video. `inner` keeps its header padding, while the close button
   is fixed to the viewport's safe top-right edge, outside the content
   scroll movement. Then video full-width on its
   own native ratio, then title → sub → description → Built With, with the
   whole modal as the scroll surface — video kept, not dropped, unlike Tool
   at this size. */
@media (max-width:63.999rem){
  .aigc-case-modal{width:100%;height:100svh;margin:0}
  .aigc-case-modal__inner{flex-direction:column;align-items:stretch;justify-content:flex-start;height:100%;padding-top:clamp(76px,18vw,100px);overflow-y:auto;overscroll-behavior:contain;gap:0}
  .aigc-case-modal__figure{flex:0 0 auto;width:100%;height:auto;max-width:none;aspect-ratio:var(--aigc-case-video-aspect)}
  .aigc-case-modal__frame{border-radius:0;box-shadow:none}
  .aigc-case-modal__record{position:static;flex:1 1 auto;width:100%;max-width:none;max-height:none;display:block}
  .aigc-case-modal__panel{border-radius:0;border:0;border-top:1px solid rgba(246,241,232,.16);background:#121314;max-height:none;overflow:visible;padding:clamp(28px,7%,40px) clamp(22px,6%,36px) clamp(40px,10%,56px)}
  .aigc-case-modal__close{position:fixed;top:max(var(--case-demo-space-m),env(safe-area-inset-top));right:max(var(--case-demo-space-m),env(safe-area-inset-right))}
}
@media (max-width:760px){
  .aigc-case-modal{position:fixed;inset:0;height:100dvh;max-height:100dvh;background:#121314}
  .aigc-case-modal__record{flex:1 0 auto;display:flex}
}
@media (prefers-reduced-motion:reduce){
  .aigc-case-modal__close{transition:none}
}


/* ── Applied AI closing — framed statement card ──────────────────────────
   Reuses the About "next chapter" card's visual world (navy field + blue
   corner glow + 1px blue-tinted hairline), no heading: the statement stands
   alone, centred. One fluid component — no per-width patches (RESPONSIVE.md).
   Higher-specificity `.closing.section-shell` neutralises the old two-column
   grid set by the section-shell media rules; the seam/padding rules above
   still own the gap to the footer. */
.closing.section-shell{
  grid-template-columns:minmax(0,1fr);
  justify-items:center;
  align-items:center;
  row-gap:0;
}
.closing-card{
  position:relative;
  width:min(100%,1010px);
  margin-inline:auto;
  min-height:clamp(360px,48svh,540px);
  display:grid;
  place-items:center;
  padding:clamp(3rem,2rem + 4.5vw,6rem) clamp(1.6rem,0.7rem + 4vw,4.5rem);
  overflow:hidden;
  border:1px solid rgba(92,127,246,.6);
  border-radius:clamp(18px,1.4vw,25px);
  background:
    radial-gradient(circle at var(--closing-pointer-x,85%) var(--closing-pointer-y,42%),rgba(53,71,255,.85),transparent 46%),
    linear-gradient(135deg,#111a29 0%,#131722 45%,#12131a 100%);
  box-shadow:0 24px 75px rgba(0,0,0,.28);
}
.closing-card::after{
  content:"";
  position:absolute;
  inset:0;
  pointer-events:none;
  opacity:.5;
  background:radial-gradient(circle at 94% 12%,rgba(69,50,255,.4),transparent 40%);
}
/* Keep the copy and shared CTA together as one centred, content-sized group. */
:root{
  --closing-content-gap:clamp(1.5rem,1.2rem + 1vw,2rem);
  --closing-copy-measure:46rem;
  --closing-copy-mobile-measure:40rem;
  --closing-copy-line-height:1.6;
}
.closing-card__content{
  position:relative;
  z-index:1;
  width:100%;
  display:grid;
  justify-items:center;
  gap:var(--closing-content-gap);
}
.closing-card__copy{
  position:relative;
  z-index:1;
  margin:0;
  max-width:var(--closing-copy-measure);
  text-align:center;
  text-wrap:balance;
  font-family:var(--sans);
  font-weight:300;
  font-size:clamp(1.375rem,1.23rem + 0.7vw,1.75rem);
  line-height:var(--closing-copy-line-height);
  letter-spacing:0;
  color:rgba(247,245,242,.92);
}
/* Desktop reads as one balanced paragraph; preserve the mobile sentence break. */
.closing-card__copy br{display:none}html[lang="zh-CN"] .closing-card__copy br{display:revert}
@media (max-width:760px){
  .closing-card__copy{
    max-width:var(--closing-copy-mobile-measure);
    font-size:calc(clamp(1.375rem,1.23rem + 0.7vw,1.75rem) - 2px);
  }
  .closing-card__copy br{display:revert}
}
@media (prefers-reduced-motion:reduce){
  .closing-card{transition:none}
}

/* 游观 online demo: align heading and table at the section's top edge. */
:root{--case-demo-space-s:clamp(.5rem,.45rem + .2vw,.625rem);--case-demo-space-m:clamp(1rem,.9rem + .4vw,1.25rem);--case-demo-type:clamp(.875rem,.82rem + .2vw,1rem);--case-demo-target:2.75rem;--case-demo-scale:.8}
.inspiration-case__built--demo{align-items:start}
.inspiration-case__built--demo .inspiration-case__demo-row{display:grid;grid-template-columns:minmax(0,.42fr) 1fr;align-items:center;gap:var(--case-demo-space-m);padding-block:var(--case-demo-space-s)}
.inspiration-case__built--demo .inspiration-case__demo-row dd{margin:0}
.inspiration-case__built--demo .inspiration-case__demo-row dt{text-transform:uppercase;letter-spacing:.08em}
.inspiration-case__demo-link{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:calc(var(--case-demo-space-s) * var(--case-demo-scale));min-height:calc(var(--case-demo-target) * var(--case-demo-scale));padding:calc(var(--case-demo-space-s) * var(--case-demo-scale)) calc(var(--case-demo-space-m) * var(--case-demo-scale));border:calc(1px * var(--case-demo-scale)) solid rgba(247,245,242,.6);border-radius:999px;color:#f7f5f2;background:transparent;font-family:var(--sans);font-size:calc(var(--case-demo-type) * var(--case-demo-scale));line-height:1.2;text-decoration:none;white-space:nowrap;transition:background-color .2s,color .2s,border-color .2s}
.inspiration-case__demo-link:hover{background:#f7f5f2;color:var(--ink);border-color:#f7f5f2}
.inspiration-case__demo-link:focus-visible{outline:2px solid #f7f5f2;outline-offset:4px}
.inspiration-case__demo-link span{font-size:1.1em;line-height:1}

/* Extend the invisible hit area while keeping the capsule at 80% size. */
.inspiration-case__demo-link::after{content:"";position:absolute;inset-inline:0;top:50%;min-height:var(--case-demo-target);height:100%;transform:translateY(-50%)}

/* Mobile-only copy alternative; desktop online link stays unchanged. */
.inspiration-case__demo-note,.inspiration-case__demo-copy{display:none}
.inspiration-case__copy-announcement{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.inspiration-case__copy-status{width:0;height:1.1em;opacity:0;transform:scale(.7);filter:brightness(0) invert(1);transition:opacity 220ms ease,transform 320ms var(--ease)}
.inspiration-case__demo-copy{cursor:pointer}
.inspiration-case__demo-copy.is-copied .inspiration-case__copy-status{width:1.1em;opacity:1;transform:scale(1)}
.inspiration-case__demo-copy:hover .inspiration-case__copy-status{filter:brightness(0)}
@media (max-width:760px){
  .inspiration-case__built--demo .inspiration-case__demo-row{display:block;padding-block:var(--case-demo-space-m)}
  .inspiration-case__built--demo .inspiration-case__demo-row dt{padding:0;margin-bottom:var(--case-demo-space-s)}
  .inspiration-case__built--demo .inspiration-case__demo-row dd{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--case-demo-space-m)}
  .inspiration-case__demo-row dd>.inspiration-case__demo-link:not(.inspiration-case__demo-copy){display:none}
  .inspiration-case__demo-note{display:block;margin:0;font-size:var(--case-demo-type);line-height:1.5;color:#a8a8a8}
  .inspiration-case__demo-copy{display:inline-flex}
}
@media (prefers-reduced-motion:reduce){.inspiration-case__copy-status{transition:none}}

.inspiration-case__demo-copy .inspiration-case__copy-label{font-size:inherit;line-height:inherit;color:inherit}
.inspiration-case__demo-copy:is(:hover,.is-copied){color:#121314;background:#f7f5f2;border-color:#f7f5f2}
.inspiration-case__demo-copy.is-copied .inspiration-case__copy-status{filter:brightness(0)}

/* Playground modal adapter for the shared Demo link row. */
.aigc-case-modal__specs .inspiration-case__demo-row{display:grid;grid-template-columns:minmax(0,.42fr) 1fr;align-items:center;gap:var(--case-demo-space-m);padding-block:0}
.aigc-case-modal__specs .inspiration-case__demo-row dt{margin:0}
@media (max-width:760px){
  .aigc-case-modal__specs .inspiration-case__demo-row{display:block;padding-block:0}
  .aigc-case-modal__specs .inspiration-case__demo-row dt{margin-bottom:var(--case-demo-space-s)}
  .aigc-case-modal__specs .inspiration-case__demo-row dd{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--case-demo-space-m)}
}

/* Butterfly footage has a black canvas; do not expose the blue placeholder at clipped edges. */
.product-tile[data-aigc-case="iridescent-butterfly"] .product-tile__visual,
.product-tile[data-aigc-case="iridescent-butterfly"] .product-tile__video{background:#000}

/* Brief 20261007: lock the document for every Products dialog. The shared
   controller also suspends the JS scroller; native dialog content can scroll. */
/* The inherited phone circle is 42px; extend its invisible target to 44px
   without changing its drawn size. Macallan keeps its larger existing target. */
:root{--products-close-hit-extension:1px}
.inspiration-case-modal__close::after{content:"";position:absolute;inset:calc(-1 * var(--products-close-hit-extension));border-radius:inherit}
html.products-modal-is-open{overflow:hidden;overscroll-behavior:none}
html.products-modal-is-open body{overscroll-behavior:none}
/* Accepted Products rollout: all seven shared dialogs fill the desktop viewport.
   Keep the incumbent 760px boundary and the independent Macallan dialogs. */
@media (min-width:761px){
  .inspiration-case-modal[data-inspiration-modal]{
    position:fixed;inset:0;width:100%;max-width:none;height:100%;max-height:none;margin:0;
  }
  .inspiration-case-modal[data-inspiration-modal] .inspiration-case-modal__frame{box-shadow:none}
}
/* zh closing card: button 4px lower than the shared content gap (2026-10-13). */
html[lang="zh-CN"] .closing-card__content > .button{margin-top:4px}
/* zh Inspiration Board / Product modal (2026-10-13): 技术构成 and 主要功能流程
   share one left edge and one size. Built With used a 1180px measure while
   Main Function Flow used 1280px, so the two centred blocks started at
   different x; the title size is the Built With size −4px for both. */
@media (min-width:761px){html[lang="zh-CN"] .inspiration-case__built{width:min(100% - clamp(44px,8vw,148px),1280px)}}
html[lang="zh-CN"] .inspiration-case__built h3,html[lang="zh-CN"] .inspiration-case__functions>h3{font-size:calc(clamp(38px,4.5vw,68px) - 4px)}

@media (max-width:760px){:where(html[lang="zh-CN"]) .section-heading h2:where(#overview-title,#method-title,#tool-title,#products-title,#playground-title){font-size:calc(clamp(47px,13vw,78px) - 2px)}}
/* zh section intros (2026-10-14): the right-hand copy's first line starts at
   the same ink top as the title's first line, in all five sections.
   Measured in Chrome: CJK ink sits ~0.098em below the title box (思源宋体,
   line-height 1.22) and ~0.24em below the copy box (思源黑体). The title box
   starts 0 (Overview) or 2.4rem (kicker line 20.4px + 18px gap) below the
   copy column's top, so the copy's padding is the difference. Desktop only;
   the stacked phone layout keeps its own rhythm. */
@media (min-width:761px){
  html[lang="zh-CN"] .overview__copy,
  html[lang="zh-CN"] .method__intro .method__copy,
  html[lang="zh-CN"] .tool__copy,
  html[lang="zh-CN"] .products__copy,
  html[lang="zh-CN"] .playground__copy{
    --zh-title-top:2.4rem;
    padding-top:calc(var(--zh-title-top) + .098 * (clamp(48px,5vw,94px) - 2px) - .24 * clamp(16px,calc(2vw - 6px),24px));
  }
  html[lang="zh-CN"] .overview__copy{--zh-title-top:0px}
}
/* zh Products intro: one colour — the blue closing sentence reads in the
   copy's own bright white (2026-10-14). */
html[lang="zh-CN"] .products__copy .products__highlight{color:inherit}
/* zh phones/tablets (2026-10-14 pm): Tool card「使用原则」text 2px smaller. */
@media (max-width:63.999rem){html[lang="zh-CN"] .tool-modal__principle dd{font-size:calc(clamp(21px,6vw,28px) - 2px)}}
/* zh phones: every Product modal title (incl. both Macallan cases) takes the
   Works Case Detail title style — 思源宋体 Bold at the case hero's phone size. */
@media (max-width:760px){html[lang="zh-CN"] .inspiration-case__opening{font-size:clamp(34px,10.2vw,40px);font-weight:700;line-height:1.22}}
/* Practice map light (2026-10-14): the shared .shiny-cta shimmer is a rotating
   square as wide as the panel. On phones the panel is tall relative to its
   width (diagonal ≈ 1.12–1.19 × width at 414–330px), so while the square turns
   its edges sweep inside the frame and the four corners flash empty. 130% of
   the width always covers the diagonal. Desktop panels are ~1.01, unchanged. */
@media (max-width:760px){.practice-map.shiny-cta::after{width:130%}}

/* Tools — continuous browsing (2026-10-14, communication/Applied AI  Tools 卡片优化.md).
   Desktop: two light chevrons at the far left/right of the overlay, clear of
   the card and the record. Compact: smaller, quieter chevrons in the side
   gutters, vertically centred; the record pages by swipe (script.js), so its
   scroller only claims vertical pans. Hidden at the first / last card. */
.tool-modal__nav{
  position:absolute;
  z-index:3;
  top:50%;
  display:flex;
  align-items:center;
  justify-content:center;
  width:56px;
  height:56px;
  margin-top:-28px;
  padding:0;
  border:0;
  border-radius:50%;
  background:none;
  color:rgba(246,241,232,.5);
  cursor:pointer;
  opacity:0;
  pointer-events:none;
  transition:opacity .48s var(--ease) var(--tool-modal-panel-delay,100ms),color .25s ease,transform .25s ease;
}
.tool-modal.is-open .tool-modal__nav{opacity:1;pointer-events:auto}
.tool-modal__nav[hidden]{display:none}
.tool-modal__nav svg{width:26px;height:26px;fill:none;stroke:currentColor;stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
.tool-modal__nav--prev{left:clamp(8px,2.2vw,40px)}
.tool-modal__nav--next{right:clamp(8px,2.2vw,40px)}
.tool-modal__nav:hover,.tool-modal__nav:focus-visible{color:rgba(246,241,232,.95)}
.tool-modal__nav--prev:hover{transform:translateX(-3px)}
.tool-modal__nav--next:hover{transform:translateX(3px)}
.tool-modal__nav:focus-visible{outline:1px solid rgba(246,241,232,.6);outline-offset:2px}
@media (max-width:63.999rem){
  .tool-modal{overflow:hidden}
  .tool-modal,.tool-modal__panel{touch-action:pan-y}
  .tool-modal__nav{width:28px;height:56px;margin-top:-28px;border-radius:0;color:rgba(246,241,232,.42)}
  .tool-modal__nav svg{width:18px;height:18px;stroke-width:1.6}
  .tool-modal__nav--prev{left:max(0px,env(safe-area-inset-left))}
  .tool-modal__nav--next{right:max(0px,env(safe-area-inset-right))}
  .tool-modal__nav--prev:hover,.tool-modal__nav--next:hover{transform:none}
}
@media (prefers-reduced-motion:reduce){.tool-modal__nav{transition:none}}

/* zh: the Tools record title stays on one line (CJK glyphs are ~2ch wide, so the shared 12ch cap broke 自动化任务 in two). */
html[lang="zh-CN"] .tool-modal__title{max-width:none;white-space:nowrap}

/* Compact pager: inert neighbour copies of the record ride the same track (script.js pageToolRecord). */
.tool-modal__record--ghost{position:absolute;pointer-events:none}
.tool-modal__record--ghost .tool-modal__panel{transition:none}
