
Tightened Slide
- 43 installs
- 145 repo stars
- Updated June 2, 2026
- jyoung105/future-slide-skill
Helps with ai & agent building tasks.
About
tightened-slide is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- tightened-slide
- AI & Agent Building
- AI-coding skill
Tightened Slide by the numbers
- 43 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #7,921 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jyoung105/future-slide-skill --skill tightened-slideAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 43 |
|---|---|
| repo stars | ★ 145 |
| Last updated | June 2, 2026 |
| Repository | jyoung105/future-slide-skill ↗ |
What it does
Helps with ai & agent building tasks.
Files
Tightened Slide
Use this workflow when a user asks for a Tightened Slide deck, horizontal swipe presentation, HTML slide deck, launch deck, analysis deck, framework deck, product deck, or data-driven talk.
Operating Assumptions
- This is a Tightened Slide only system.
- The output is a static HTML deck, normally
index.html, with an adjacentimages/folder. - The template is
assets/template.html. - Body slides must use registered
S01toS22layouts. - The validator is required before delivery.
- Supported language modes are English and Korean.
Step 1: Clarify Only What Matters
If the user provides a complete outline and assets, proceed. If key inputs are missing, ask at most three questions:
1. Audience and presentation setting. 2. Target duration or page count. 3. Source material, language mode, required images/data, and hard constraints.
If the theme is unspecified, default to International Klein Blue from references/themes.md. If the language mode is unspecified, default to English.
Step 2: Prepare The Deck
Create the target folder and image folder:
mkdir -p path/to/deck/images
cp assets/template.html path/to/deck/index.htmlImmediately replace the <title> placeholder in index.html.
Set the language mode on the root element:
<html lang="en" data-language="en">or:
<html lang="ko" data-language="ko">Korean mode uses the template font stack SUIT, Pretendard, Noto Sans KR, and Noto Sans before falling back to Inter and system sans fonts.
If the deck must work offline with local animation fallback, keep assets/motion.min.js reachable from the copied HTML path or accept the CDN fallback built into the template.
Step 3: Preflight
Before writing slide markup:
- Read the template
<style>block. - Read
references/layout-lock.md. - Read the relevant skeletons in
references/layouts.md. - Confirm every class you plan to use exists in the template.
- Do not invent global classes. Use inline styles only for page-specific tuning.
Create a planning table before coding:
page -> data-layout -> reason -> image slotFor 7-8 page decks, use at least six different Sxx layouts. For 10+ page decks, use at least eight.
Step 4: Pick Layouts
Use the registered layout set:
S01Index CoverS02Vertical Timeline + KPIS03Split StatementS04Six CellsS05Three LayersS06KPI TowerS07Horizontal BarS08Duo CompareS09Dot Matrix StatementS10Split ClosingS11Horizontal TimelineS12Manifesto + Ink BannerS13Three ForcesS14Loop FormS15Matrix + Hero StatS16Multi-card BriefS17System DiagramS18Why NowS19Four CardsS20Stacked KPI LedgerS21Tech Spec SheetS22Image Hero
Use S08 + Tightened Map Component for maps, routes, city relationships, location networks, or historical movement pages.
Use S22 for one large image. Use S15 or S16 adaptations for multiple images. Do not create unregistered image split or evidence wall layouts.
Step 5: Apply The Visual System
Hard rules:
- One accent color per deck.
- No gradients, shadows, rounded cards, glass, neon, 3D, or decorative borders.
- Large type uses light weights:
200or300. - Body text uses restrained weights and clear hierarchy.
- Large sizes use
font-size:min(Xvw,Yvh)withY >= X * 1.6. - Headings sit on the left/top content axis unless using registered statement/split layouts.
- Kicker text sits above the title, not beside it.
.canvas-cardalready has horizontal padding; do not add another5vwpadding layer inside it.- Keep all captions, labels, and footnotes above the bottom navigation safe area.
- SVG may draw geometry only; visible labels must be HTML.
Language rules:
- English mode uses concise sentence case titles and direct body copy.
- Korean mode uses short Korean titles, compact body lines, and consistent product terms.
- Diagram labels and generated-image text must match the chosen language mode.
Step 6: Image Flow
If images are needed:
- Ask before generating new images.
- Choose the layout slot before writing the prompt.
- Use
references/image-prompts.md. - Save generated or provided images in
images/. - Name images
{page}-{semantic-name}.{ext}. - Add
data-image-slotto every local image.
Slot defaults:
S22:s22-hero-21x9S15:s15-grid-21x9ors15-grid-16x10S16:s16-brief-21x9ors16-brief-16x10
Step 7: Validate
Run:
node scripts/validate-deck.mjs path/to/index.htmlFix every error. Warnings require visual review.
Then open the deck in a browser and inspect:
- title alignment
- type weight
- spacing between title and body
- image crop and image slot fit
- captions and footnotes above navigation
- ESC index visibility
Bstatic mode
Use references/checklist.md as the delivery checklist.
/**
* Bundled by jsDelivr using Rollup v2.79.2 and Terser v5.39.0.
* Original file: /npm/motion@11.11.17/dist/es/motion/lib/index.mjs
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
function t(t,e){const n=t.indexOf(e);n>-1&&t.splice(n,1)}class e{constructor(){this.subscriptions=[]}add(e){var n,s;return n=this.subscriptions,s=e,-1===n.indexOf(s)&&n.push(s),()=>t(this.subscriptions,e)}notify(t,e,n){const s=this.subscriptions.length;if(s)if(1===s)this.subscriptions[0](t,e,n);else for(let i=0;i<s;i++){const s=this.subscriptions[i];s&&s(t,e,n)}}getSize(){return this.subscriptions.length}clear(){this.subscriptions.length=0}}function n(t,e){return e?t*(1e3/e):0}const s=!1,i=t=>t;const r=["read","resolveKeyframes","update","preRender","render","postRender"];const{schedule:o,cancel:a,state:l,steps:u}=function(t,e){let n=!1,s=!0;const i={delta:0,timestamp:0,isProcessing:!1},o=()=>n=!0,a=r.reduce(((t,e)=>(t[e]=function(t){let e=new Set,n=new Set,s=!1,i=!1;const r=new WeakSet;let o={delta:0,timestamp:0,isProcessing:!1};function a(e){r.has(e)&&(l.schedule(e),t()),e(o)}const l={schedule:(t,i=!1,o=!1)=>{const a=o&&s?e:n;return i&&r.add(t),a.has(t)||a.add(t),t},cancel:t=>{n.delete(t),r.delete(t)},process:t=>{o=t,s?i=!0:(s=!0,[e,n]=[n,e],n.clear(),e.forEach(a),s=!1,i&&(i=!1,l.process(t)))}};return l}(o),t)),{}),{read:l,resolveKeyframes:u,update:c,preRender:h,render:d,postRender:p}=a,f=()=>{const r=performance.now();n=!1,i.delta=s?1e3/60:Math.max(Math.min(r-i.timestamp,40),1),i.timestamp=r,i.isProcessing=!0,l.process(i),u.process(i),c.process(i),h.process(i),d.process(i),p.process(i),i.isProcessing=!1,n&&e&&(s=!1,t(f))};return{schedule:r.reduce(((e,r)=>{const o=a[r];return e[r]=(e,r=!1,a=!1)=>(n||(n=!0,s=!0,i.isProcessing||t(f)),o.schedule(e,r,a)),e}),{}),cancel:t=>{for(let e=0;e<r.length;e++)a[r[e]].cancel(t)},state:i,steps:a}}("undefined"!=typeof requestAnimationFrame?requestAnimationFrame:i,!0);let c;function h(){c=void 0}const d={now:()=>(void 0===c&&d.set(l.isProcessing||s?l.timestamp:performance.now()),c),set:t=>{c=t,queueMicrotask(h)}};class p{constructor(t,e={}){this.version="11.11.17",this.canTrackVelocity=null,this.events={},this.updateAndNotify=(t,e=!0)=>{const n=d.now();this.updatedAt!==n&&this.setPrevFrameValue(),this.prev=this.current,this.setCurrent(t),this.current!==this.prev&&this.events.change&&this.events.change.notify(this.current),e&&this.events.renderRequest&&this.events.renderRequest.notify(this.current)},this.hasAnimated=!1,this.setCurrent(t),this.owner=e.owner}setCurrent(t){var e;this.current=t,this.updatedAt=d.now(),null===this.canTrackVelocity&&void 0!==t&&(this.canTrackVelocity=(e=this.current,!isNaN(parseFloat(e))))}setPrevFrameValue(t=this.current){this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt}onChange(t){return this.on("change",t)}on(t,n){this.events[t]||(this.events[t]=new e);const s=this.events[t].add(n);return"change"===t?()=>{s(),o.read((()=>{this.events.change.getSize()||this.stop()}))}:s}clearListeners(){for(const t in this.events)this.events[t].clear()}attach(t,e){this.passiveEffect=t,this.stopPassiveEffect=e}set(t,e=!0){e&&this.passiveEffect?this.passiveEffect(t,this.updateAndNotify):this.updateAndNotify(t,e)}setWithVelocity(t,e,n){this.set(e),this.prev=void 0,this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt-n}jump(t,e=!0){this.updateAndNotify(t),this.prev=t,this.prevUpdatedAt=this.prevFrameValue=void 0,e&&this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}get(){return this.current}getPrevious(){return this.prev}getVelocity(){const t=d.now();if(!this.canTrackVelocity||void 0===this.prevFrameValue||t-this.updatedAt>30)return 0;const e=Math.min(this.updatedAt-this.prevUpdatedAt,30);return n(parseFloat(this.current)-parseFloat(this.prevFrameValue),e)}start(t){return this.stop(),new Promise((e=>{this.hasAnimated=!0,this.animation=t(e),this.events.animationStart&&this.events.animationStart.notify()})).then((()=>{this.events.animationComplete&&this.events.animationComplete.notify(),this.clearAnimation()}))}stop(){this.animation&&(this.animation.stop(),this.events.animationCancel&&this.events.animationCancel.notify()),this.clearAnimation()}isAnimating(){return!!this.animation}clearAnimation(){delete this.animation}destroy(){this.clearListeners(),this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}}function f(t,e){return new p(t,e)}function m(t){let e;return()=>(void 0===e&&(e=t()),e)}const g=m((()=>void 0!==window.ScrollTimeline));class y{constructor(t){this.stop=()=>this.runAll("stop"),this.animations=t.filter(Boolean)}then(t,e){return Promise.all(this.animations).then(t).catch(e)}getAll(t){return this.animations[0][t]}setAll(t,e){for(let n=0;n<this.animations.length;n++)this.animations[n][t]=e}attachTimeline(t,e){const n=this.animations.map((n=>g()&&n.attachTimeline?n.attachTimeline(t):e(n)));return()=>{n.forEach(((t,e)=>{t&&t(),this.animations[e].stop()}))}}get time(){return this.getAll("time")}set time(t){this.setAll("time",t)}get speed(){return this.getAll("speed")}set speed(t){this.setAll("speed",t)}get startTime(){return this.getAll("startTime")}get duration(){let t=0;for(let e=0;e<this.animations.length;e++)t=Math.max(t,this.animations[e].duration);return t}runAll(t){this.animations.forEach((e=>e[t]()))}flatten(){this.runAll("flatten")}play(){this.runAll("play")}pause(){this.runAll("pause")}cancel(){this.runAll("cancel")}complete(){this.runAll("complete")}}const v=t=>1e3*t,w=t=>t/1e3;function b(t,e,s){const i=Math.max(e-5,0);return n(s-t(i),e-i)}let T=i,x=i;const S=(t,e,n)=>n>e?e:n<t?t:n,V=.001;function A({duration:t=800,bounce:e=.25,velocity:n=0,mass:s=1}){let i,r,o=1-e;o=S(.05,1,o),t=S(.01,10,w(t)),o<1?(i=e=>{const s=e*o,i=s*t,r=s-n,a=P(e,o),l=Math.exp(-i);return V-r/a*l},r=e=>{const s=e*o*t,r=s*n+n,a=Math.pow(o,2)*Math.pow(e,2)*t,l=Math.exp(-s),u=P(Math.pow(e,2),o);return(-i(e)+V>0?-1:1)*((r-a)*l)/u}):(i=e=>Math.exp(-e*t)*((e-n)*t+1)-.001,r=e=>Math.exp(-e*t)*(t*t*(n-e)));const a=function(t,e,n){let s=n;for(let n=1;n<M;n++)s-=t(s)/e(s);return s}(i,r,5/t);if(t=v(t),isNaN(a))return{stiffness:100,damping:10,duration:t};{const e=Math.pow(a,2)*s;return{stiffness:e,damping:2*o*Math.sqrt(s*e),duration:t}}}const M=12;function P(t,e){return t*Math.sqrt(1-e*e)}const k=["duration","bounce"],F=["stiffness","damping","mass"];function C(t,e){return e.some((e=>void 0!==t[e]))}function E({keyframes:t,restDelta:e,restSpeed:n,...s}){const i=t[0],r=t[t.length-1],o={done:!1,value:i},{stiffness:a,damping:l,mass:u,duration:c,velocity:h,isResolvedFromDuration:d}=function(t){let e={velocity:0,stiffness:100,damping:10,mass:1,isResolvedFromDuration:!1,...t};if(!C(t,F)&&C(t,k)){const n=A(t);e={...e,...n,mass:1},e.isResolvedFromDuration=!0}return e}({...s,velocity:-w(s.velocity||0)}),p=h||0,f=l/(2*Math.sqrt(a*u)),m=r-i,g=w(Math.sqrt(a/u)),y=Math.abs(m)<5;let T;if(n||(n=y?.01:2),e||(e=y?.005:.5),f<1){const t=P(g,f);T=e=>{const n=Math.exp(-f*g*e);return r-n*((p+f*g*m)/t*Math.sin(t*e)+m*Math.cos(t*e))}}else if(1===f)T=t=>r-Math.exp(-g*t)*(m+(p+g*m)*t);else{const t=g*Math.sqrt(f*f-1);T=e=>{const n=Math.exp(-f*g*e),s=Math.min(t*e,300);return r-n*((p+f*g*m)*Math.sinh(s)+t*m*Math.cosh(s))/t}}return{calculatedDuration:d&&c||null,next:t=>{const s=T(t);if(d)o.done=t>=c;else{let i=0;f<1&&(i=0===t?v(p):b(T,t,s));const a=Math.abs(i)<=n,l=Math.abs(r-s)<=e;o.done=a&&l}return o.value=o.done?r:s,o}}}const O=2e4;function R(t){let e=0;let n=t.next(e);for(;!n.done&&e<O;)e+=50,n=t.next(e);return e>=O?1/0:e}function B(t,e=100,n){const s=n({...t,keyframes:[0,e]}),i=Math.min(R(s),O);return{type:"keyframes",ease:t=>s.next(i*t).value/e,duration:w(i)}}const I=(t,e,n)=>t+(e-t)*n,L=(t,e,n)=>{const s=e-t;return 0===s?1:(n-t)/s};function W(t,e){const n=t[t.length-1];for(let s=1;s<=e;s++){const i=L(0,e,s);t.push(I(n,1,i))}}function D(t){const e=[0];return W(e,t.length-1),e}const N=t=>Boolean(t&&t.getVelocity);function K(t,e,n){var s;if("string"==typeof t){let i=document;e&&(x(Boolean(e.current)),i=e.current),n?(null!==(s=n[t])&&void 0!==s||(n[t]=i.querySelectorAll(t)),t=n[t]):t=i.querySelectorAll(t)}else t instanceof Element&&(t=[t]);return Array.from(t||[])}function $(t){return"object"==typeof t&&!Array.isArray(t)}function j(t,e,n,s){return"string"==typeof t&&$(e)?K(t,n,s):t instanceof NodeList?Array.from(t):Array.isArray(t)?t:[t]}function z(t){return"function"==typeof t}function H(t,e,n,s){var i;return"number"==typeof e?e:e.startsWith("-")||e.startsWith("+")?Math.max(0,t+parseFloat(e)):"<"===e?n:null!==(i=s.get(e))&&void 0!==i?i:t}const U=(t,e,n)=>{const s=e-t;return((n-t)%s+s)%s+t},Y=t=>Array.isArray(t)&&"number"!=typeof t[0];function q(t,e){return Y(t)?t[U(0,t.length,e)]:t}function X(e,n,s,i,r,o){!function(e,n,s){for(let i=0;i<e.length;i++){const r=e[i];r.at>n&&r.at<s&&(t(e,r),i--)}}(e,r,o);for(let t=0;t<n.length;t++)e.push({value:n[t],at:I(r,o,i[t]),easing:q(s,t)})}function G(t,e){return t.at===e.at?null===t.value?1:null===e.value?-1:0:t.at-e.at}function Z(t,e){return!e.has(t)&&e.set(t,{}),e.get(t)}function _(t,e){return e[t]||(e[t]=[]),e[t]}function J(t){return Array.isArray(t)?t:[t]}function Q(t,e){return t&&t[e]?{...t,...t[e]}:{...t}}const tt=t=>"number"==typeof t,et=t=>t.every(tt),nt=new WeakMap,st=["transformPerspective","x","y","z","translateX","translateY","translateZ","scale","scaleX","scaleY","rotate","rotateX","rotateY","rotateZ","skew","skewX","skewY"],it=new Set(st),rt={type:"spring",stiffness:500,damping:25,restSpeed:10},ot={type:"keyframes",duration:.8},at={type:"keyframes",ease:[.25,.1,.35,1],duration:.3},lt=(t,{keyframes:e})=>e.length>2?ot:it.has(t)?t.startsWith("scale")?{type:"spring",stiffness:550,damping:0===e[1]?2*Math.sqrt(550):30,restSpeed:10}:rt:at;function ut(t,e){return t?t[e]||t.default||t:void 0}const ct=t=>null!==t;function ht(t,{repeat:e,repeatType:n="loop"},s){const i=t.filter(ct),r=e&&"loop"!==n&&e%2==1?0:i.length-1;return r&&void 0!==s?s:i[r]}const dt=(t,e,n)=>(((1-3*n+3*e)*t+(3*n-6*e))*t+3*e)*t;function pt(t,e,n,s){if(t===e&&n===s)return i;const r=e=>function(t,e,n,s,i){let r,o,a=0;do{o=e+(n-e)/2,r=dt(o,s,i)-t,r>0?n=o:e=o}while(Math.abs(r)>1e-7&&++a<12);return o}(e,0,1,t,n);return t=>0===t||1===t?t:dt(r(t),e,s)}const ft=t=>e=>e<=.5?t(2*e)/2:(2-t(2*(1-e)))/2,mt=t=>e=>1-t(1-e),gt=pt(.33,1.53,.69,.99),yt=mt(gt),vt=ft(yt),wt=t=>(t*=2)<1?.5*yt(t):.5*(2-Math.pow(2,-10*(t-1))),bt=t=>1-Math.sin(Math.acos(t)),Tt=mt(bt),xt=ft(bt),St=t=>/^0[^.\s]+$/u.test(t);const Vt=t=>/^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(t),At=t=>e=>"string"==typeof e&&e.startsWith(t),Mt=At("--"),Pt=At("var(--"),kt=t=>!!Pt(t)&&Ft.test(t.split("/*")[0].trim()),Ft=/var\(--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)$/iu,Ct=/^var\(--(?:([\w-]+)|([\w-]+), ?([a-zA-Z\d ()%#.,-]+))\)/u;function Et(t,e,n=1){const[s,i]=function(t){const e=Ct.exec(t);if(!e)return[,];const[,n,s,i]=e;return[`--${null!=n?n:s}`,i]}(t);if(!s)return;const r=window.getComputedStyle(e).getPropertyValue(s);if(r){const t=r.trim();return Vt(t)?parseFloat(t):t}return kt(i)?Et(i,e,n+1):i}const Ot={test:t=>"number"==typeof t,parse:parseFloat,transform:t=>t},Rt={...Ot,transform:t=>S(0,1,t)},Bt={...Ot,default:1},It=t=>({test:e=>"string"==typeof e&&e.endsWith(t)&&1===e.split(" ").length,parse:parseFloat,transform:e=>`${e}${t}`}),Lt=It("deg"),Wt=It("%"),Dt=It("px"),Nt=It("vh"),Kt=It("vw"),$t={...Wt,parse:t=>Wt.parse(t)/100,transform:t=>Wt.transform(100*t)},jt=new Set(["width","height","top","left","right","bottom","x","y","translateX","translateY"]),zt=t=>t===Ot||t===Dt,Ht=(t,e)=>parseFloat(t.split(", ")[e]),Ut=(t,e)=>(n,{transform:s})=>{if("none"===s||!s)return 0;const i=s.match(/^matrix3d\((.+)\)$/u);if(i)return Ht(i[1],e);{const e=s.match(/^matrix\((.+)\)$/u);return e?Ht(e[1],t):0}},Yt=new Set(["x","y","z"]),qt=st.filter((t=>!Yt.has(t)));const Xt={width:({x:t},{paddingLeft:e="0",paddingRight:n="0"})=>t.max-t.min-parseFloat(e)-parseFloat(n),height:({y:t},{paddingTop:e="0",paddingBottom:n="0"})=>t.max-t.min-parseFloat(e)-parseFloat(n),top:(t,{top:e})=>parseFloat(e),left:(t,{left:e})=>parseFloat(e),bottom:({y:t},{top:e})=>parseFloat(e)+(t.max-t.min),right:({x:t},{left:e})=>parseFloat(e)+(t.max-t.min),x:Ut(4,13),y:Ut(5,14)};Xt.translateX=Xt.x,Xt.translateY=Xt.y;const Gt=t=>e=>e.test(t),Zt=[Ot,Dt,Wt,Lt,Kt,Nt,{test:t=>"auto"===t,parse:t=>t}],_t=t=>Zt.find(Gt(t)),Jt=new Set;let Qt=!1,te=!1;function ee(){if(te){const t=Array.from(Jt).filter((t=>t.needsMeasurement)),e=new Set(t.map((t=>t.element))),n=new Map;e.forEach((t=>{const e=function(t){const e=[];return qt.forEach((n=>{const s=t.getValue(n);void 0!==s&&(e.push([n,s.get()]),s.set(n.startsWith("scale")?1:0))})),e}(t);e.length&&(n.set(t,e),t.render())})),t.forEach((t=>t.measureInitialState())),e.forEach((t=>{t.render();const e=n.get(t);e&&e.forEach((([e,n])=>{var s;null===(s=t.getValue(e))||void 0===s||s.set(n)}))})),t.forEach((t=>t.measureEndState())),t.forEach((t=>{void 0!==t.suspendedScrollY&&window.scrollTo(0,t.suspendedScrollY)}))}te=!1,Qt=!1,Jt.forEach((t=>t.complete())),Jt.clear()}function ne(){Jt.forEach((t=>{t.readKeyframes(),t.needsMeasurement&&(te=!0)}))}class se{constructor(t,e,n,s,i,r=!1){this.isComplete=!1,this.isAsync=!1,this.needsMeasurement=!1,this.isScheduled=!1,this.unresolvedKeyframes=[...t],this.onComplete=e,this.name=n,this.motionValue=s,this.element=i,this.isAsync=r}scheduleResolve(){this.isScheduled=!0,this.isAsync?(Jt.add(this),Qt||(Qt=!0,o.read(ne),o.resolveKeyframes(ee))):(this.readKeyframes(),this.complete())}readKeyframes(){const{unresolvedKeyframes:t,name:e,element:n,motionValue:s}=this;for(let i=0;i<t.length;i++)if(null===t[i])if(0===i){const i=null==s?void 0:s.get(),r=t[t.length-1];if(void 0!==i)t[0]=i;else if(n&&e){const s=n.readValue(e,r);null!=s&&(t[0]=s)}void 0===t[0]&&(t[0]=r),s&&void 0===i&&s.set(t[0])}else t[i]=t[i-1]}setFinalKeyframe(){}measureInitialState(){}renderEndStyles(){}measureEndState(){}complete(){this.isComplete=!0,this.onComplete(this.unresolvedKeyframes,this.finalKeyframe),Jt.delete(this)}cancel(){this.isComplete||(this.isScheduled=!1,Jt.delete(this))}resume(){this.isComplete||this.scheduleResolve()}}const ie=t=>Math.round(1e5*t)/1e5,re=/-?(?:\d+(?:\.\d+)?|\.\d+)/gu;const oe=/^(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))$/iu,ae=(t,e)=>n=>Boolean("string"==typeof n&&oe.test(n)&&n.startsWith(t)||e&&!function(t){return null==t}(n)&&Object.prototype.hasOwnProperty.call(n,e)),le=(t,e,n)=>s=>{if("string"!=typeof s)return s;const[i,r,o,a]=s.match(re);return{[t]:parseFloat(i),[e]:parseFloat(r),[n]:parseFloat(o),alpha:void 0!==a?parseFloat(a):1}},ue={...Ot,transform:t=>Math.round((t=>S(0,255,t))(t))},ce={test:ae("rgb","red"),parse:le("red","green","blue"),transform:({red:t,green:e,blue:n,alpha:s=1})=>"rgba("+ue.transform(t)+", "+ue.transform(e)+", "+ue.transform(n)+", "+ie(Rt.transform(s))+")"};const he={test:ae("#"),parse:function(t){let e="",n="",s="",i="";return t.length>5?(e=t.substring(1,3),n=t.substring(3,5),s=t.substring(5,7),i=t.substring(7,9)):(e=t.substring(1,2),n=t.substring(2,3),s=t.substring(3,4),i=t.substring(4,5),e+=e,n+=n,s+=s,i+=i),{red:parseInt(e,16),green:parseInt(n,16),blue:parseInt(s,16),alpha:i?parseInt(i,16)/255:1}},transform:ce.transform},de={test:ae("hsl","hue"),parse:le("hue","saturation","lightness"),transform:({hue:t,saturation:e,lightness:n,alpha:s=1})=>"hsla("+Math.round(t)+", "+Wt.transform(ie(e))+", "+Wt.transform(ie(n))+", "+ie(Rt.transform(s))+")"},pe={test:t=>ce.test(t)||he.test(t)||de.test(t),parse:t=>ce.test(t)?ce.parse(t):de.test(t)?de.parse(t):he.parse(t),transform:t=>"string"==typeof t?t:t.hasOwnProperty("red")?ce.transform(t):de.transform(t)},fe=/(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))/giu;const me="number",ge="color",ye=/var\s*\(\s*--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)|#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\)|-?(?:\d+(?:\.\d+)?|\.\d+)/giu;function ve(t){const e=t.toString(),n=[],s={color:[],number:[],var:[]},i=[];let r=0;const o=e.replace(ye,(t=>(pe.test(t)?(s.color.push(r),i.push(ge),n.push(pe.parse(t))):t.startsWith("var(")?(s.var.push(r),i.push("var"),n.push(t)):(s.number.push(r),i.push(me),n.push(parseFloat(t))),++r,"${}"))).split("${}");return{values:n,split:o,indexes:s,types:i}}function we(t){return ve(t).values}function be(t){const{split:e,types:n}=ve(t),s=e.length;return t=>{let i="";for(let r=0;r<s;r++)if(i+=e[r],void 0!==t[r]){const e=n[r];i+=e===me?ie(t[r]):e===ge?pe.transform(t[r]):t[r]}return i}}const Te=t=>"number"==typeof t?0:t;const xe={test:function(t){var e,n;return isNaN(t)&&"string"==typeof t&&((null===(e=t.match(re))||void 0===e?void 0:e.length)||0)+((null===(n=t.match(fe))||void 0===n?void 0:n.length)||0)>0},parse:we,createTransformer:be,getAnimatableNone:function(t){const e=we(t);return be(t)(e.map(Te))}},Se=new Set(["brightness","contrast","saturate","opacity"]);function Ve(t){const[e,n]=t.slice(0,-1).split("(");if("drop-shadow"===e)return t;const[s]=n.match(re)||[];if(!s)return t;const i=n.replace(s,"");let r=Se.has(e)?1:0;return s!==n&&(r*=100),e+"("+r+i+")"}const Ae=/\b([a-z-]*)\(.*?\)/gu,Me={...xe,getAnimatableNone:t=>{const e=t.match(Ae);return e?e.map(Ve).join(" "):t}},Pe={borderWidth:Dt,borderTopWidth:Dt,borderRightWidth:Dt,borderBottomWidth:Dt,borderLeftWidth:Dt,borderRadius:Dt,radius:Dt,borderTopLeftRadius:Dt,borderTopRightRadius:Dt,borderBottomRightRadius:Dt,borderBottomLeftRadius:Dt,width:Dt,maxWidth:Dt,height:Dt,maxHeight:Dt,top:Dt,right:Dt,bottom:Dt,left:Dt,padding:Dt,paddingTop:Dt,paddingRight:Dt,paddingBottom:Dt,paddingLeft:Dt,margin:Dt,marginTop:Dt,marginRight:Dt,marginBottom:Dt,marginLeft:Dt,backgroundPositionX:Dt,backgroundPositionY:Dt},ke={rotate:Lt,rotateX:Lt,rotateY:Lt,rotateZ:Lt,scale:Bt,scaleX:Bt,scaleY:Bt,scaleZ:Bt,skew:Lt,skewX:Lt,skewY:Lt,distance:Dt,translateX:Dt,translateY:Dt,translateZ:Dt,x:Dt,y:Dt,z:Dt,perspective:Dt,transformPerspective:Dt,opacity:Rt,originX:$t,originY:$t,originZ:Dt},Fe={...Ot,transform:Math.round},Ce={...Pe,...ke,zIndex:Fe,size:Dt,fillOpacity:Rt,strokeOpacity:Rt,numOctaves:Fe},Ee={...Ce,color:pe,backgroundColor:pe,outlineColor:pe,fill:pe,stroke:pe,borderColor:pe,borderTopColor:pe,borderRightColor:pe,borderBottomColor:pe,borderLeftColor:pe,filter:Me,WebkitFilter:Me},Oe=t=>Ee[t];function Re(t,e){let n=Oe(t);return n!==Me&&(n=xe),n.getAnimatableNone?n.getAnimatableNone(e):void 0}const Be=new Set(["auto","none","0"]);class Ie extends se{constructor(t,e,n,s,i){super(t,e,n,s,i,!0)}readKeyframes(){const{unresolvedKeyframes:t,element:e,name:n}=this;if(!e||!e.current)return;super.readKeyframes();for(let n=0;n<t.length;n++){let s=t[n];if("string"==typeof s&&(s=s.trim(),kt(s))){const i=Et(s,e.current);void 0!==i&&(t[n]=i),n===t.length-1&&(this.finalKeyframe=s)}}if(this.resolveNoneKeyframes(),!jt.has(n)||2!==t.length)return;const[s,i]=t,r=_t(s),o=_t(i);if(r!==o)if(zt(r)&&zt(o))for(let e=0;e<t.length;e++){const n=t[e];"string"==typeof n&&(t[e]=parseFloat(n))}else this.needsMeasurement=!0}resolveNoneKeyframes(){const{unresolvedKeyframes:t,name:e}=this,n=[];for(let e=0;e<t.length;e++)("number"==typeof(s=t[e])?0===s:null===s||"none"===s||"0"===s||St(s))&&n.push(e);var s;n.length&&function(t,e,n){let s,i=0;for(;i<t.length&&!s;){const e=t[i];"string"==typeof e&&!Be.has(e)&&ve(e).values.length&&(s=t[i]),i++}if(s&&n)for(const i of e)t[i]=Re(n,s)}(t,n,e)}measureInitialState(){const{element:t,unresolvedKeyframes:e,name:n}=this;if(!t||!t.current)return;"height"===n&&(this.suspendedScrollY=window.pageYOffset),this.measuredOrigin=Xt[n](t.measureViewportBox(),window.getComputedStyle(t.current)),e[0]=this.measuredOrigin;const s=e[e.length-1];void 0!==s&&t.getValue(n,s).jump(s,!1)}measureEndState(){var t;const{element:e,name:n,unresolvedKeyframes:s}=this;if(!e||!e.current)return;const i=e.getValue(n);i&&i.jump(this.measuredOrigin,!1);const r=s.length-1,o=s[r];s[r]=Xt[n](e.measureViewportBox(),window.getComputedStyle(e.current)),null!==o&&void 0===this.finalKeyframe&&(this.finalKeyframe=o),(null===(t=this.removedTransforms)||void 0===t?void 0:t.length)&&this.removedTransforms.forEach((([t,n])=>{e.getValue(t).set(n)})),this.resolveNoneKeyframes()}}const Le=(t,e)=>"zIndex"!==e&&(!("number"!=typeof t&&!Array.isArray(t))||!("string"!=typeof t||!xe.test(t)&&"0"!==t||t.startsWith("url(")));function We(t,e,n,s){const i=t[0];if(null===i)return!1;if("display"===e||"visibility"===e)return!0;const r=t[t.length-1],o=Le(i,e),a=Le(r,e);return!(!o||!a)&&(function(t){const e=t[0];if(1===t.length)return!0;for(let n=0;n<t.length;n++)if(t[n]!==e)return!0}(t)||("spring"===n||z(n))&&s)}class De{constructor({autoplay:t=!0,delay:e=0,type:n="keyframes",repeat:s=0,repeatDelay:i=0,repeatType:r="loop",...o}){this.isStopped=!1,this.hasAttemptedResolve=!1,this.createdAt=d.now(),this.options={autoplay:t,delay:e,type:n,repeat:s,repeatDelay:i,repeatType:r,...o},this.updateFinishedPromise()}calcStartTime(){return this.resolvedAt&&this.resolvedAt-this.createdAt>40?this.resolvedAt:this.createdAt}get resolved(){return this._resolved||this.hasAttemptedResolve||(ne(),ee()),this._resolved}onKeyframesResolved(t,e){this.resolvedAt=d.now(),this.hasAttemptedResolve=!0;const{name:n,type:s,velocity:i,delay:r,onComplete:o,onUpdate:a,isGenerator:l}=this.options;if(!l&&!We(t,n,s,i)){if(!r)return null==a||a(ht(t,this.options,e)),null==o||o(),void this.resolveFinishedPromise();this.options.duration=0}const u=this.initPlayback(t,e);!1!==u&&(this._resolved={keyframes:t,finalKeyframe:e,...u},this.onPostResolved())}onPostResolved(){}then(t,e){return this.currentFinishedPromise.then(t,e)}flatten(){this.options.type="keyframes",this.options.ease="linear"}updateFinishedPromise(){this.currentFinishedPromise=new Promise((t=>{this.resolveFinishedPromise=t}))}}function Ne({keyframes:t,velocity:e=0,power:n=.8,timeConstant:s=325,bounceDamping:i=10,bounceStiffness:r=500,modifyTarget:o,min:a,max:l,restDelta:u=.5,restSpeed:c}){const h=t[0],d={done:!1,value:h},p=t=>void 0===a?l:void 0===l||Math.abs(a-t)<Math.abs(l-t)?a:l;let f=n*e;const m=h+f,g=void 0===o?m:o(m);g!==m&&(f=g-h);const y=t=>-f*Math.exp(-t/s),v=t=>g+y(t),w=t=>{const e=y(t),n=v(t);d.done=Math.abs(e)<=u,d.value=d.done?g:n};let T,x;const S=t=>{var e;(e=d.value,void 0!==a&&e<a||void 0!==l&&e>l)&&(T=t,x=E({keyframes:[d.value,p(d.value)],velocity:b(v,t,d.value),damping:i,stiffness:r,restDelta:u,restSpeed:c}))};return S(0),{calculatedDuration:null,next:t=>{let e=!1;return x||void 0!==T||(e=!0,w(t),S(t)),void 0!==T&&t>=T?x.next(t-T):(!e&&w(t),d)}}}const Ke=pt(.42,0,1,1),$e=pt(0,0,.58,1),je=pt(.42,0,.58,1),ze=t=>Array.isArray(t)&&"number"==typeof t[0],He={linear:i,easeIn:Ke,easeInOut:je,easeOut:$e,circIn:bt,circInOut:xt,circOut:Tt,backIn:yt,backInOut:vt,backOut:gt,anticipate:wt},Ue=t=>{if(ze(t)){x(4===t.length);const[e,n,s,i]=t;return pt(e,n,s,i)}return"string"==typeof t?He[t]:t},Ye=(t,e)=>n=>e(t(n)),qe=(...t)=>t.reduce(Ye);function Xe(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+(e-t)*(2/3-n)*6:t}function Ge(t,e){return n=>n>0?e:t}const Ze=(t,e,n)=>{const s=t*t,i=n*(e*e-s)+s;return i<0?0:Math.sqrt(i)},_e=[he,ce,de];function Je(t){const e=(n=t,_e.find((t=>t.test(n))));var n;if(!Boolean(e))return!1;let s=e.parse(t);return e===de&&(s=function({hue:t,saturation:e,lightness:n,alpha:s}){t/=360,n/=100;let i=0,r=0,o=0;if(e/=100){const s=n<.5?n*(1+e):n+e-n*e,a=2*n-s;i=Xe(a,s,t+1/3),r=Xe(a,s,t),o=Xe(a,s,t-1/3)}else i=r=o=n;return{red:Math.round(255*i),green:Math.round(255*r),blue:Math.round(255*o),alpha:s}}(s)),s}const Qe=(t,e)=>{const n=Je(t),s=Je(e);if(!n||!s)return Ge(t,e);const i={...n};return t=>(i.red=Ze(n.red,s.red,t),i.green=Ze(n.green,s.green,t),i.blue=Ze(n.blue,s.blue,t),i.alpha=I(n.alpha,s.alpha,t),ce.transform(i))},tn=new Set(["none","hidden"]);function en(t,e){return n=>I(t,e,n)}function nn(t){return"number"==typeof t?en:"string"==typeof t?kt(t)?Ge:pe.test(t)?Qe:on:Array.isArray(t)?sn:"object"==typeof t?pe.test(t)?Qe:rn:Ge}function sn(t,e){const n=[...t],s=n.length,i=t.map(((t,n)=>nn(t)(t,e[n])));return t=>{for(let e=0;e<s;e++)n[e]=i[e](t);return n}}function rn(t,e){const n={...t,...e},s={};for(const i in n)void 0!==t[i]&&void 0!==e[i]&&(s[i]=nn(t[i])(t[i],e[i]));return t=>{for(const e in s)n[e]=s[e](t);return n}}const on=(t,e)=>{const n=xe.createTransformer(e),s=ve(t),i=ve(e);return s.indexes.var.length===i.indexes.var.length&&s.indexes.color.length===i.indexes.color.length&&s.indexes.number.length>=i.indexes.number.length?tn.has(t)&&!i.values.length||tn.has(e)&&!s.values.length?function(t,e){return tn.has(t)?n=>n<=0?t:e:n=>n>=1?e:t}(t,e):qe(sn(function(t,e){var n;const s=[],i={color:0,var:0,number:0};for(let r=0;r<e.values.length;r++){const o=e.types[r],a=t.indexes[o][i[o]],l=null!==(n=t.values[a])&&void 0!==n?n:0;s[r]=l,i[o]++}return s}(s,i),i.values),n):Ge(t,e)};function an(t,e,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n)return I(t,e,n);return nn(t)(t,e)}function ln(t,e,{clamp:n=!0,ease:s,mixer:r}={}){const o=t.length;if(x(o===e.length),1===o)return()=>e[0];if(2===o&&t[0]===t[1])return()=>e[1];t[0]>t[o-1]&&(t=[...t].reverse(),e=[...e].reverse());const a=function(t,e,n){const s=[],r=n||an,o=t.length-1;for(let n=0;n<o;n++){let o=r(t[n],t[n+1]);if(e){const t=Array.isArray(e)?e[n]||i:e;o=qe(t,o)}s.push(o)}return s}(e,s,r),l=a.length,u=e=>{let n=0;if(l>1)for(;n<t.length-2&&!(e<t[n+1]);n++);const s=L(t[n],t[n+1],e);return a[n](s)};return n?e=>u(S(t[0],t[o-1],e)):u}function un({duration:t=300,keyframes:e,times:n,ease:s="easeInOut"}){const i=Y(s)?s.map(Ue):Ue(s),r={done:!1,value:e[0]},o=function(t,e){return t.map((t=>t*e))}(n&&n.length===e.length?n:D(e),t),a=ln(o,e,{ease:Array.isArray(i)?i:(l=e,u=i,l.map((()=>u||je)).splice(0,l.length-1))});var l,u;return{calculatedDuration:t,next:e=>(r.value=a(e),r.done=e>=t,r)}}const cn=t=>{const e=({timestamp:e})=>t(e);return{start:()=>o.update(e,!0),stop:()=>a(e),now:()=>l.isProcessing?l.timestamp:d.now()}},hn={decay:Ne,inertia:Ne,tween:un,keyframes:un,spring:E},dn=t=>t/100;class pn extends De{constructor(t){super(t),this.holdTime=null,this.cancelTime=null,this.currentTime=0,this.playbackSpeed=1,this.pendingPlayState="running",this.startTime=null,this.state="idle",this.stop=()=>{if(this.resolver.cancel(),this.isStopped=!0,"idle"===this.state)return;this.teardown();const{onStop:t}=this.options;t&&t()};const{name:e,motionValue:n,element:s,keyframes:i}=this.options,r=(null==s?void 0:s.KeyframeResolver)||se;this.resolver=new r(i,((t,e)=>this.onKeyframesResolved(t,e)),e,n,s),this.resolver.scheduleResolve()}flatten(){super.flatten(),this._resolved&&Object.assign(this._resolved,this.initPlayback(this._resolved.keyframes))}initPlayback(t){const{type:e="keyframes",repeat:n=0,repeatDelay:s=0,repeatType:i,velocity:r=0}=this.options,o=z(e)?e:hn[e]||un;let a,l;o!==un&&"number"!=typeof t[0]&&(a=qe(dn,an(t[0],t[1])),t=[0,100]);const u=o({...this.options,keyframes:t});"mirror"===i&&(l=o({...this.options,keyframes:[...t].reverse(),velocity:-r})),null===u.calculatedDuration&&(u.calculatedDuration=R(u));const{calculatedDuration:c}=u,h=c+s;return{generator:u,mirroredGenerator:l,mapPercentToKeyframes:a,calculatedDuration:c,resolvedDuration:h,totalDuration:h*(n+1)-s}}onPostResolved(){const{autoplay:t=!0}=this.options;this.play(),"paused"!==this.pendingPlayState&&t?this.state=this.pendingPlayState:this.pause()}tick(t,e=!1){const{resolved:n}=this;if(!n){const{keyframes:t}=this.options;return{done:!0,value:t[t.length-1]}}const{finalKeyframe:s,generator:i,mirroredGenerator:r,mapPercentToKeyframes:o,keyframes:a,calculatedDuration:l,totalDuration:u,resolvedDuration:c}=n;if(null===this.startTime)return i.next(0);const{delay:h,repeat:d,repeatType:p,repeatDelay:f,onUpdate:m}=this.options;this.speed>0?this.startTime=Math.min(this.startTime,t):this.speed<0&&(this.startTime=Math.min(t-u/this.speed,this.startTime)),e?this.currentTime=t:null!==this.holdTime?this.currentTime=this.holdTime:this.currentTime=Math.round(t-this.startTime)*this.speed;const g=this.currentTime-h*(this.speed>=0?1:-1),y=this.speed>=0?g<0:g>u;this.currentTime=Math.max(g,0),"finished"===this.state&&null===this.holdTime&&(this.currentTime=u);let v=this.currentTime,w=i;if(d){const t=Math.min(this.currentTime,u)/c;let e=Math.floor(t),n=t%1;!n&&t>=1&&(n=1),1===n&&e--,e=Math.min(e,d+1);Boolean(e%2)&&("reverse"===p?(n=1-n,f&&(n-=f/c)):"mirror"===p&&(w=r)),v=S(0,1,n)*c}const b=y?{done:!1,value:a[0]}:w.next(v);o&&(b.value=o(b.value));let{done:T}=b;y||null===l||(T=this.speed>=0?this.currentTime>=u:this.currentTime<=0);const x=null===this.holdTime&&("finished"===this.state||"running"===this.state&&T);return x&&void 0!==s&&(b.value=ht(a,this.options,s)),m&&m(b.value),x&&this.finish(),b}get duration(){const{resolved:t}=this;return t?w(t.calculatedDuration):0}get time(){return w(this.currentTime)}set time(t){t=v(t),this.currentTime=t,null!==this.holdTime||0===this.speed?this.holdTime=t:this.driver&&(this.startTime=this.driver.now()-t/this.speed)}get speed(){return this.playbackSpeed}set speed(t){const e=this.playbackSpeed!==t;this.playbackSpeed=t,e&&(this.time=w(this.currentTime))}play(){if(this.resolver.isScheduled||this.resolver.resume(),!this._resolved)return void(this.pendingPlayState="running");if(this.isStopped)return;const{driver:t=cn,onPlay:e,startTime:n}=this.options;this.driver||(this.driver=t((t=>this.tick(t)))),e&&e();const s=this.driver.now();null!==this.holdTime?this.startTime=s-this.holdTime:this.startTime?"finished"===this.state&&(this.startTime=s):this.startTime=null!=n?n:this.calcStartTime(),"finished"===this.state&&this.updateFinishedPromise(),this.cancelTime=this.startTime,this.holdTime=null,this.state="running",this.driver.start()}pause(){var t;this._resolved?(this.state="paused",this.holdTime=null!==(t=this.currentTime)&&void 0!==t?t:0):this.pendingPlayState="paused"}complete(){"running"!==this.state&&this.play(),this.pendingPlayState=this.state="finished",this.holdTime=null}finish(){this.teardown(),this.state="finished";const{onComplete:t}=this.options;t&&t()}cancel(){null!==this.cancelTime&&this.tick(this.cancelTime),this.teardown(),this.updateFinishedPromise()}teardown(){this.state="idle",this.stopDriver(),this.resolveFinishedPromise(),this.updateFinishedPromise(),this.startTime=this.cancelTime=null,this.resolver.cancel()}stopDriver(){this.driver&&(this.driver.stop(),this.driver=void 0)}sample(t){return this.startTime=0,this.tick(t,!0)}}const fn=new Set(["opacity","clipPath","filter","transform"]),mn={linearEasing:void 0};function gn(t,e){const n=m(t);return()=>{var t;return null!==(t=mn[e])&&void 0!==t?t:n()}}const yn=gn((()=>{try{document.createElement("div").animate({opacity:0},{easing:"linear(0, 1)"})}catch(t){return!1}return!0}),"linearEasing");function vn(t){return Boolean("function"==typeof t&&yn()||!t||"string"==typeof t&&(t in bn||yn())||ze(t)||Array.isArray(t)&&t.every(vn))}const wn=([t,e,n,s])=>`cubic-bezier(${t}, ${e}, ${n}, ${s})`,bn={linear:"linear",ease:"ease",easeIn:"ease-in",easeOut:"ease-out",easeInOut:"ease-in-out",circIn:wn([0,.65,.55,1]),circOut:wn([.55,0,1,.45]),backIn:wn([.31,.01,.66,-.59]),backOut:wn([.33,1.53,.69,.99])};function Tn(t,e){return t?"function"==typeof t&&yn()?((t,e)=>{let n="";const s=Math.max(Math.round(e/10),2);for(let e=0;e<s;e++)n+=t(L(0,s-1,e))+", ";return`linear(${n.substring(0,n.length-2)})`})(t,e):ze(t)?wn(t):Array.isArray(t)?t.map((t=>Tn(t,e)||bn.easeOut)):bn[t]:void 0}function xn(t,e,n,{delay:s=0,duration:i=300,repeat:r=0,repeatType:o="loop",ease:a="easeInOut",times:l}={}){const u={[e]:n};l&&(u.offset=l);const c=Tn(a,i);return Array.isArray(c)&&(u.easing=c),t.animate(u,{delay:s,duration:i,easing:Array.isArray(c)?"linear":c,fill:"both",iterations:r+1,direction:"reverse"===o?"alternate":"normal"})}function Sn(t,e){t.timeline=e,t.onfinish=null}const Vn=m((()=>Object.hasOwnProperty.call(Element.prototype,"animate")));const An={anticipate:wt,backInOut:vt,circInOut:xt};class Mn extends De{constructor(t){super(t);const{name:e,motionValue:n,element:s,keyframes:i}=this.options;this.resolver=new Ie(i,((t,e)=>this.onKeyframesResolved(t,e)),e,n,s),this.resolver.scheduleResolve()}initPlayback(t,e){var n;let{duration:s=300,times:i,ease:r,type:o,motionValue:a,name:l,startTime:u}=this.options;if(!(null===(n=a.owner)||void 0===n?void 0:n.current))return!1;var c;if("string"==typeof r&&yn()&&r in An&&(r=An[r]),z((c=this.options).type)||"spring"===c.type||!vn(c.ease)){const{onComplete:e,onUpdate:n,motionValue:a,element:l,...u}=this.options,c=function(t,e){const n=new pn({...e,keyframes:t,repeat:0,delay:0,isGenerator:!0});let s={done:!1,value:t[0]};const i=[];let r=0;for(;!s.done&&r<2e4;)s=n.sample(r),i.push(s.value),r+=10;return{times:void 0,keyframes:i,duration:r-10,ease:"linear"}}(t,u);1===(t=c.keyframes).length&&(t[1]=t[0]),s=c.duration,i=c.times,r=c.ease,o="keyframes"}const h=xn(a.owner.current,l,t,{...this.options,duration:s,times:i,ease:r});return h.startTime=null!=u?u:this.calcStartTime(),this.pendingTimeline?(Sn(h,this.pendingTimeline),this.pendingTimeline=void 0):h.onfinish=()=>{const{onComplete:n}=this.options;a.set(ht(t,this.options,e)),n&&n(),this.cancel(),this.resolveFinishedPromise()},{animation:h,duration:s,times:i,type:o,ease:r,keyframes:t}}get duration(){const{resolved:t}=this;if(!t)return 0;const{duration:e}=t;return w(e)}get time(){const{resolved:t}=this;if(!t)return 0;const{animation:e}=t;return w(e.currentTime||0)}set time(t){const{resolved:e}=this;if(!e)return;const{animation:n}=e;n.currentTime=v(t)}get speed(){const{resolved:t}=this;if(!t)return 1;const{animation:e}=t;return e.playbackRate}set speed(t){const{resolved:e}=this;if(!e)return;const{animation:n}=e;n.playbackRate=t}get state(){const{resolved:t}=this;if(!t)return"idle";const{animation:e}=t;return e.playState}get startTime(){const{resolved:t}=this;if(!t)return null;const{animation:e}=t;return e.startTime}attachTimeline(t){if(this._resolved){const{resolved:e}=this;if(!e)return i;const{animation:n}=e;Sn(n,t)}else this.pendingTimeline=t;return i}play(){if(this.isStopped)return;const{resolved:t}=this;if(!t)return;const{animation:e}=t;"finished"===e.playState&&this.updateFinishedPromise(),e.play()}pause(){const{resolved:t}=this;if(!t)return;const{animation:e}=t;e.pause()}stop(){if(this.resolver.cancel(),this.isStopped=!0,"idle"===this.state)return;this.resolveFinishedPromise(),this.updateFinishedPromise();const{resolved:t}=this;if(!t)return;const{animation:e,keyframes:n,duration:s,type:i,ease:r,times:o}=t;if("idle"===e.playState||"finished"===e.playState)return;if(this.time){const{motionValue:t,onUpdate:e,onComplete:a,element:l,...u}=this.options,c=new pn({...u,keyframes:n,duration:s,type:i,ease:r,times:o,isGenerator:!0}),h=v(this.time);t.setWithVelocity(c.sample(h-10).value,c.sample(h).value,10)}const{onStop:a}=this.options;a&&a(),this.cancel()}complete(){const{resolved:t}=this;t&&t.animation.finish()}cancel(){const{resolved:t}=this;t&&t.animation.cancel()}static supports(t){const{motionValue:e,name:n,repeatDelay:s,repeatType:i,damping:r,type:o}=t;return Vn()&&n&&fn.has(n)&&e&&e.owner&&e.owner.current instanceof HTMLElement&&!e.owner.getProps().onUpdate&&!s&&"mirror"!==i&&0!==r&&"inertia"!==o}}const Pn=(t,e,n,s={},i,r)=>a=>{const l=ut(s,t)||{},u=l.delay||s.delay||0;let{elapsed:c=0}=s;c-=v(u);let h={keyframes:Array.isArray(n)?n:[null,n],ease:"easeOut",velocity:e.getVelocity(),...l,delay:-c,onUpdate:t=>{e.set(t),l.onUpdate&&l.onUpdate(t)},onComplete:()=>{a(),l.onComplete&&l.onComplete()},name:t,motionValue:e,element:r?void 0:i};(function({when:t,delay:e,delayChildren:n,staggerChildren:s,staggerDirection:i,repeat:r,repeatType:o,repeatDelay:a,from:l,elapsed:u,...c}){return!!Object.keys(c).length})(l)||(h={...h,...lt(t,h)}),h.duration&&(h.duration=v(h.duration)),h.repeatDelay&&(h.repeatDelay=v(h.repeatDelay)),void 0!==h.from&&(h.keyframes[0]=h.from);let d=!1;if((!1===h.type||0===h.duration&&!h.repeatDelay)&&(h.duration=0,0===h.delay&&(d=!0)),d&&!r&&void 0!==e.get()){const t=ht(h.keyframes,l);if(void 0!==t)return o.update((()=>{h.onUpdate(t),h.onComplete()})),new y([])}return!r&&Mn.supports(h)?new Mn(h):new pn(h)},kn=t=>(t=>Array.isArray(t))(t)?t[t.length-1]||0:t;function Fn(t){const e=[{},{}];return null==t||t.values.forEach(((t,n)=>{e[0][n]=t.get(),e[1][n]=t.getVelocity()})),e}function Cn(t,e,n,s){if("function"==typeof e){const[i,r]=Fn(s);e=e(void 0!==n?n:t.custom,i,r)}if("string"==typeof e&&(e=t.variants&&t.variants[e]),"function"==typeof e){const[i,r]=Fn(s);e=e(void 0!==n?n:t.custom,i,r)}return e}function En(t,e,n){t.hasValue(e)?t.getValue(e).set(n):t.addValue(e,f(n))}function On(t,e){const n=function(t,e,n){const s=t.getProps();return Cn(s,e,void 0!==n?n:s.custom,t)}(t,e);let{transitionEnd:s={},transition:i={},...r}=n||{};r={...r,...s};for(const e in r){En(t,e,kn(r[e]))}}const Rn=t=>t.replace(/([a-z])([A-Z])/gu,"$1-$2").toLowerCase(),Bn="data-"+Rn("framerAppearId");function In(t){return t.props[Bn]}function Ln(t,e){const n=t.getValue("willChange");if(s=n,Boolean(N(s)&&s.add))return n.add(e);var s}function Wn({protectedKeys:t,needsAnimating:e},n){const s=t.hasOwnProperty(n)&&!0!==e[n];return e[n]=!1,s}function Dn(t,e,{delay:n=0,transitionOverride:s,type:i}={}){var r;let{transition:a=t.getDefaultTransition(),transitionEnd:l,...u}=e;s&&(a=s);const c=[],h=i&&t.animationState&&t.animationState.getState()[i];for(const e in u){const s=t.getValue(e,null!==(r=t.latestValues[e])&&void 0!==r?r:null),i=u[e];if(void 0===i||h&&Wn(h,e))continue;const l={delay:n,...ut(a||{},e)};let d=!1;if(window.MotionHandoffAnimation){const n=In(t);if(n){const t=window.MotionHandoffAnimation(n,e,o);null!==t&&(l.startTime=t,d=!0)}}Ln(t,e),s.start(Pn(e,s,i,t.shouldReduceMotion&&it.has(e)?{type:!1}:l,t,d));const p=s.animation;p&&c.push(p)}return l&&Promise.all(c).then((()=>{o.update((()=>{l&&On(t,l)}))})),c}const Nn={};function Kn(t,{layout:e,layoutId:n}){return it.has(t)||t.startsWith("origin")||(e||void 0!==n)&&(!!Nn[t]||"opacity"===t)}function $n(t,e,n){var s;const{style:i}=t,r={};for(const o in i)(N(i[o])||e.style&&N(e.style[o])||Kn(o,t)||void 0!==(null===(s=null==n?void 0:n.getValue(o))||void 0===s?void 0:s.liveStyle))&&(r[o]=i[o]);return r}const jn="undefined"!=typeof window,zn={current:null},Hn={current:!1};const Un=["initial","animate","whileInView","whileFocus","whileHover","whileTap","whileDrag","exit"];function Yn(t){return null!==(e=t.animate)&&"object"==typeof e&&"function"==typeof e.start||Un.some((e=>function(t){return"string"==typeof t||Array.isArray(t)}(t[e])));var e}const qn={animation:["animate","variants","whileHover","whileTap","exit","whileInView","whileFocus","whileDrag"],exit:["exit"],drag:["drag","dragControls"],focus:["whileFocus"],hover:["whileHover","onHoverStart","onHoverEnd"],tap:["whileTap","onTap","onTapStart","onTapCancel"],pan:["onPan","onPanStart","onPanSessionStart","onPanEnd"],inView:["whileInView","onViewportEnter","onViewportLeave"],layout:["layout","layoutId"]},Xn={};for(const t in qn)Xn[t]={isEnabled:e=>qn[t].some((t=>!!e[t]))};const Gn=[...Zt,pe,xe],Zn=()=>({x:{min:0,max:0},y:{min:0,max:0}}),_n=["AnimationStart","AnimationComplete","Update","BeforeLayoutMeasure","LayoutMeasure","LayoutAnimationStart","LayoutAnimationComplete"];class Jn{scrapeMotionValuesFromProps(t,e,n){return{}}constructor({parent:t,props:e,presenceContext:n,reducedMotionConfig:s,blockInitialAnimation:i,visualState:r},a={}){this.current=null,this.children=new Set,this.isVariantNode=!1,this.isControllingVariants=!1,this.shouldReduceMotion=null,this.values=new Map,this.KeyframeResolver=se,this.features={},this.valueSubscriptions=new Map,this.prevMotionValues={},this.events={},this.propEventSubscriptions={},this.notifyUpdate=()=>this.notify("Update",this.latestValues),this.render=()=>{this.current&&(this.triggerBuild(),this.renderInstance(this.current,this.renderState,this.props.style,this.projection))},this.renderScheduledAt=0,this.scheduleRender=()=>{const t=d.now();this.renderScheduledAt<t&&(this.renderScheduledAt=t,o.render(this.render,!1,!0))};const{latestValues:l,renderState:u}=r;this.latestValues=l,this.baseTarget={...l},this.initialValues=e.initial?{...l}:{},this.renderState=u,this.parent=t,this.props=e,this.presenceContext=n,this.depth=t?t.depth+1:0,this.reducedMotionConfig=s,this.options=a,this.blockInitialAnimation=Boolean(i),this.isControllingVariants=Yn(e),this.isVariantNode=function(t){return Boolean(Yn(t)||t.variants)}(e),this.isVariantNode&&(this.variantChildren=new Set),this.manuallyAnimateOnMount=Boolean(t&&t.current);const{willChange:c,...h}=this.scrapeMotionValuesFromProps(e,{},this);for(const t in h){const e=h[t];void 0!==l[t]&&N(e)&&e.set(l[t],!1)}}mount(t){this.current=t,nt.set(t,this),this.projection&&!this.projection.instance&&this.projection.mount(t),this.parent&&this.isVariantNode&&!this.isControllingVariants&&(this.removeFromVariantTree=this.parent.addVariantChild(this)),this.values.forEach(((t,e)=>this.bindToMotionValue(e,t))),Hn.current||function(){if(Hn.current=!0,jn)if(window.matchMedia){const t=window.matchMedia("(prefers-reduced-motion)"),e=()=>zn.current=t.matches;t.addListener(e),e()}else zn.current=!1}(),this.shouldReduceMotion="never"!==this.reducedMotionConfig&&("always"===this.reducedMotionConfig||zn.current),this.parent&&this.parent.children.add(this),this.update(this.props,this.presenceContext)}unmount(){nt.delete(this.current),this.projection&&this.projection.unmount(),a(this.notifyUpdate),a(this.render),this.valueSubscriptions.forEach((t=>t())),this.valueSubscriptions.clear(),this.removeFromVariantTree&&this.removeFromVariantTree(),this.parent&&this.parent.children.delete(this);for(const t in this.events)this.events[t].clear();for(const t in this.features){const e=this.features[t];e&&(e.unmount(),e.isMounted=!1)}this.current=null}bindToMotionValue(t,e){this.valueSubscriptions.has(t)&&this.valueSubscriptions.get(t)();const n=it.has(t),s=e.on("change",(e=>{this.latestValues[t]=e,this.props.onUpdate&&o.preRender(this.notifyUpdate),n&&this.projection&&(this.projection.isTransformDirty=!0)})),i=e.on("renderRequest",this.scheduleRender);let r;window.MotionCheckAppearSync&&(r=window.MotionCheckAppearSync(this,t,e)),this.valueSubscriptions.set(t,(()=>{s(),i(),r&&r(),e.owner&&e.stop()}))}sortNodePosition(t){return this.current&&this.sortInstanceNodePosition&&this.type===t.type?this.sortInstanceNodePosition(this.current,t.current):0}updateFeatures(){let t="animation";for(t in Xn){const e=Xn[t];if(!e)continue;const{isEnabled:n,Feature:s}=e;if(!this.features[t]&&s&&n(this.props)&&(this.features[t]=new s(this)),this.features[t]){const e=this.features[t];e.isMounted?e.update():(e.mount(),e.isMounted=!0)}}}triggerBuild(){this.build(this.renderState,this.latestValues,this.props)}measureViewportBox(){return this.current?this.measureInstanceViewportBox(this.current,this.props):{x:{min:0,max:0},y:{min:0,max:0}}}getStaticValue(t){return this.latestValues[t]}setStaticValue(t,e){this.latestValues[t]=e}update(t,e){(t.transformTemplate||this.props.transformTemplate)&&this.scheduleRender(),this.prevProps=this.props,this.props=t,this.prevPresenceContext=this.presenceContext,this.presenceContext=e;for(let e=0;e<_n.length;e++){const n=_n[e];this.propEventSubscriptions[n]&&(this.propEventSubscriptions[n](),delete this.propEventSubscriptions[n]);const s=t["on"+n];s&&(this.propEventSubscriptions[n]=this.on(n,s))}this.prevMotionValues=function(t,e,n){for(const s in e){const i=e[s],r=n[s];if(N(i))t.addValue(s,i);else if(N(r))t.addValue(s,f(i,{owner:t}));else if(r!==i)if(t.hasValue(s)){const e=t.getValue(s);!0===e.liveStyle?e.jump(i):e.hasAnimated||e.set(i)}else{const e=t.getStaticValue(s);t.addValue(s,f(void 0!==e?e:i,{owner:t}))}}for(const s in n)void 0===e[s]&&t.removeValue(s);return e}(this,this.scrapeMotionValuesFromProps(t,this.prevProps,this),this.prevMotionValues),this.handleChildMotionValue&&this.handleChildMotionValue()}getProps(){return this.props}getVariant(t){return this.props.variants?this.props.variants[t]:void 0}getDefaultTransition(){return this.props.transition}getTransformPagePoint(){return this.props.transformPagePoint}getClosestVariantNode(){return this.isVariantNode?this:this.parent?this.parent.getClosestVariantNode():void 0}addVariantChild(t){const e=this.getClosestVariantNode();if(e)return e.variantChildren&&e.variantChildren.add(t),()=>e.variantChildren.delete(t)}addValue(t,e){const n=this.values.get(t);e!==n&&(n&&this.removeValue(t),this.bindToMotionValue(t,e),this.values.set(t,e),this.latestValues[t]=e.get())}removeValue(t){this.values.delete(t);const e=this.valueSubscriptions.get(t);e&&(e(),this.valueSubscriptions.delete(t)),delete this.latestValues[t],this.removeValueFromRenderState(t,this.renderState)}hasValue(t){return this.values.has(t)}getValue(t,e){if(this.props.values&&this.props.values[t])return this.props.values[t];let n=this.values.get(t);return void 0===n&&void 0!==e&&(n=f(null===e?void 0:e,{owner:this}),this.addValue(t,n)),n}readValue(t,e){var n;let s=void 0===this.latestValues[t]&&this.current?null!==(n=this.getBaseTargetFromProps(this.props,t))&&void 0!==n?n:this.readValueFromInstance(this.current,t,this.options):this.latestValues[t];var i;return null!=s&&("string"==typeof s&&(Vt(s)||St(s))?s=parseFloat(s):(i=s,!Gn.find(Gt(i))&&xe.test(e)&&(s=Re(t,e))),this.setBaseTarget(t,N(s)?s.get():s)),N(s)?s.get():s}setBaseTarget(t,e){this.baseTarget[t]=e}getBaseTarget(t){var e;const{initial:n}=this.props;let s;if("string"==typeof n||"object"==typeof n){const i=Cn(this.props,n,null===(e=this.presenceContext)||void 0===e?void 0:e.custom);i&&(s=i[t])}if(n&&void 0!==s)return s;const i=this.getBaseTargetFromProps(this.props,t);return void 0===i||N(i)?void 0!==this.initialValues[t]&&void 0===s?void 0:this.baseTarget[t]:i}on(t,n){return this.events[t]||(this.events[t]=new e),this.events[t].add(n)}notify(t,...e){this.events[t]&&this.events[t].notify(...e)}}class Qn extends Jn{constructor(){super(...arguments),this.KeyframeResolver=Ie}sortInstanceNodePosition(t,e){return 2&t.compareDocumentPosition(e)?1:-1}getBaseTargetFromProps(t,e){return t.style?t.style[e]:void 0}removeValueFromRenderState(t,{vars:e,style:n}){delete e[t],delete n[t]}}const ts=(t,e)=>e&&"number"==typeof t?e.transform(t):t,es={x:"translateX",y:"translateY",z:"translateZ",transformPerspective:"perspective"},ns=st.length;function ss(t,e,n){const{style:s,vars:i,transformOrigin:r}=t;let o=!1,a=!1;for(const t in e){const n=e[t];if(it.has(t))o=!0;else if(Mt(t))i[t]=n;else{const e=ts(n,Ce[t]);t.startsWith("origin")?(a=!0,r[t]=e):s[t]=e}}if(e.transform||(o||n?s.transform=function(t,e,n){let s="",i=!0;for(let r=0;r<ns;r++){const o=st[r],a=t[o];if(void 0===a)continue;let l=!0;if(l="number"==typeof a?a===(o.startsWith("scale")?1:0):0===parseFloat(a),!l||n){const t=ts(a,Ce[o]);l||(i=!1,s+=`${es[o]||o}(${t}) `),n&&(e[o]=t)}}return s=s.trim(),n?s=n(e,i?"":s):i&&(s="none"),s}(e,t.transform,n):s.transform&&(s.transform="none")),a){const{originX:t="50%",originY:e="50%",originZ:n=0}=r;s.transformOrigin=`${t} ${e} ${n}`}}function is(t,e,n){return"string"==typeof t?t:Dt.transform(e+n*t)}const rs={offset:"stroke-dashoffset",array:"stroke-dasharray"},os={offset:"strokeDashoffset",array:"strokeDasharray"};function as(t,{attrX:e,attrY:n,attrScale:s,originX:i,originY:r,pathLength:o,pathSpacing:a=1,pathOffset:l=0,...u},c,h){if(ss(t,u,h),c)return void(t.style.viewBox&&(t.attrs.viewBox=t.style.viewBox));t.attrs=t.style,t.style={};const{attrs:d,style:p,dimensions:f}=t;d.transform&&(f&&(p.transform=d.transform),delete d.transform),f&&(void 0!==i||void 0!==r||p.transform)&&(p.transformOrigin=function(t,e,n){return`${is(e,t.x,t.width)} ${is(n,t.y,t.height)}`}(f,void 0!==i?i:.5,void 0!==r?r:.5)),void 0!==e&&(d.x=e),void 0!==n&&(d.y=n),void 0!==s&&(d.scale=s),void 0!==o&&function(t,e,n=1,s=0,i=!0){t.pathLength=1;const r=i?rs:os;t[r.offset]=Dt.transform(-s);const o=Dt.transform(e),a=Dt.transform(n);t[r.array]=`${o} ${a}`}(d,o,a,l,!1)}const ls=new Set(["baseFrequency","diffuseConstant","kernelMatrix","kernelUnitLength","keySplines","keyTimes","limitingConeAngle","markerHeight","markerWidth","numOctaves","targetX","targetY","surfaceScale","specularConstant","specularExponent","stdDeviation","tableValues","viewBox","gradientTransform","pathLength","startOffset","textLength","lengthAdjust"]);function us(t,{style:e,vars:n},s,i){Object.assign(t.style,e,i&&i.getProjectionStyles(s));for(const e in n)t.style.setProperty(e,n[e])}class cs extends Qn{constructor(){super(...arguments),this.type="svg",this.isSVGTag=!1,this.measureInstanceViewportBox=Zn}getBaseTargetFromProps(t,e){return t[e]}readValueFromInstance(t,e){if(it.has(e)){const t=Oe(e);return t&&t.default||0}return e=ls.has(e)?e:Rn(e),t.getAttribute(e)}scrapeMotionValuesFromProps(t,e,n){return function(t,e,n){const s=$n(t,e,n);for(const n in t)(N(t[n])||N(e[n]))&&(s[-1!==st.indexOf(n)?"attr"+n.charAt(0).toUpperCase()+n.substring(1):n]=t[n]);return s}(t,e,n)}build(t,e,n){as(t,e,this.isSVGTag,n.transformTemplate)}renderInstance(t,e,n,s){!function(t,e,n,s){us(t,e,void 0,s);for(const n in e.attrs)t.setAttribute(ls.has(n)?n:Rn(n),e.attrs[n])}(t,e,0,s)}mount(t){var e;this.isSVGTag="string"==typeof(e=t.tagName)&&"svg"===e.toLowerCase(),super.mount(t)}}class hs extends Qn{constructor(){super(...arguments),this.type="html",this.renderInstance=us}readValueFromInstance(t,e){if(it.has(e)){const t=Oe(e);return t&&t.default||0}{const s=(n=t,window.getComputedStyle(n)),i=(Mt(e)?s.getPropertyValue(e):s[e])||0;return"string"==typeof i?i.trim():i}var n}measureInstanceViewportBox(t,{transformPagePoint:e}){return function(t,e){return function({top:t,left:e,right:n,bottom:s}){return{x:{min:e,max:n},y:{min:t,max:s}}}(function(t,e){if(!e)return t;const n=e({x:t.left,y:t.top}),s=e({x:t.right,y:t.bottom});return{top:n.y,left:n.x,bottom:s.y,right:s.x}}(t.getBoundingClientRect(),e))}(t,e)}build(t,e,n){ss(t,e,n.transformTemplate)}scrapeMotionValuesFromProps(t,e,n){return $n(t,e,n)}handleChildMotionValue(){this.childSubscription&&(this.childSubscription(),delete this.childSubscription);const{children:t}=this.props;N(t)&&(this.childSubscription=t.on("change",(t=>{this.current&&(this.current.textContent=`${t}`)})))}}class ds extends Jn{constructor(){super(...arguments),this.type="object"}readValueFromInstance(t,e){if(function(t,e){return t in e}(e,t)){const n=t[e];if("string"==typeof n||"number"==typeof n)return n}}getBaseTargetFromProps(){}removeValueFromRenderState(t,e){delete e.output[t]}measureInstanceViewportBox(){return{x:{min:0,max:0},y:{min:0,max:0}}}build(t,e){Object.assign(t.output,e)}renderInstance(t,{output:e}){Object.assign(t,e)}sortInstanceNodePosition(){return 0}}function ps(t){const e={presenceContext:null,props:{},visualState:{renderState:{transform:{},transformOrigin:{},style:{},vars:{},attrs:{}},latestValues:{}}},n=function(t){return t instanceof SVGElement&&"svg"!==t.tagName}(t)?new cs(e):new hs(e);n.mount(t),nt.set(t,n)}function fs(t){const e=new ds({presenceContext:null,props:{},visualState:{renderState:{output:{}},latestValues:{}}});e.mount(t),nt.set(t,e)}function ms(t,e,n,s){const i=[];if(function(t,e){return N(t)||"number"==typeof t||"string"==typeof t&&!$(e)}(t,e))i.push(function(t,e,n){const s=N(t)?t:f(t);return s.start(Pn("",s,e,n)),s.animation}(t,$(e)&&e.default||e,n&&n.default||n));else{const r=j(t,e,s),o=r.length;for(let t=0;t<o;t++){const s=r[t],a=s instanceof Element?ps:fs;nt.has(s)||a(s);const l=nt.get(s),u={...n};"delay"in u&&"function"==typeof u.delay&&(u.delay=u.delay(t,o)),i.push(...Dn(l,{...e,transition:u},{}))}}return i}function gs(t,e,n){const s=[],i=function(t,{defaultTransition:e={},...n}={},s,i){const r=e.duration||.3,o=new Map,a=new Map,l={},u=new Map;let c=0,h=0,d=0;for(let n=0;n<t.length;n++){const o=t[n];if("string"==typeof o){u.set(o,h);continue}if(!Array.isArray(o)){u.set(o.name,H(h,o.at,c,u));continue}let[p,f,m={}]=o;void 0!==m.at&&(h=H(h,m.at,c,u));let g=0;const y=(t,n,s,o=0,a=0)=>{const l=J(t),{delay:u=0,times:c=D(l),type:p="keyframes",...f}=n;let{ease:m=e.ease||"easeOut",duration:y}=n;const w="function"==typeof u?u(o,a):u,b=l.length,T=z(p)?p:null==i?void 0:i[p];if(b<=2&&T){let t=100;if(2===b&&et(l)){const e=l[1]-l[0];t=Math.abs(e)}const e={...f};void 0!==y&&(e.duration=v(y));const n=B(e,t,T);m=n.ease,y=n.duration}null!=y||(y=r);const x=h+w,S=x+y;1===c.length&&0===c[0]&&(c[1]=1);const V=c.length-l.length;V>0&&W(c,V),1===l.length&&l.unshift(null),X(s,l,m,c,x,S),g=Math.max(w+y,g),d=Math.max(S,d)};if(N(p))y(f,m,_("default",Z(p,a)));else{const t=j(p,f,s,l),e=t.length;for(let n=0;n<e;n++){const s=Z(t[n],a);for(const t in f)y(f[t],Q(m,t),_(t,s),n,e)}}c=h,h+=g}return a.forEach(((t,s)=>{for(const i in t){const r=t[i];r.sort(G);const a=[],l=[],u=[];for(let t=0;t<r.length;t++){const{at:e,value:n,easing:s}=r[t];a.push(n),l.push(L(0,d,e)),u.push(s||"easeOut")}0!==l[0]&&(l.unshift(0),a.unshift(a[0]),u.unshift("easeInOut")),1!==l[l.length-1]&&(l.push(1),a.push(null)),o.has(s)||o.set(s,{keyframes:{},transition:{}});const c=o.get(s);c.keyframes[i]=a,c.transition[i]={...e,duration:d,ease:u,times:l,...n}}})),o}(t,e,n,{spring:E});return i.forEach((({keyframes:t,transition:e},n)=>{s.push(...ms(n,t,e))})),s}function ys(t){return function(e,n,s){let i=[];var r;r=e,i=Array.isArray(r)&&Array.isArray(r[0])?gs(e,n,t):ms(e,n,s,t);const o=new y(i);return t&&t.animations.push(o),o}}const vs=ys();function ws(t,e,n){t.style.setProperty(`--${e}`,n)}function bs(t,e,n){t.style[e]=n}const Ts=m((()=>{try{document.createElement("div").animate({opacity:[1]})}catch(t){return!1}return!0})),xs=new WeakMap;const Ss="easeOut";function Vs(t){const e=xs.get(t)||new Map;return xs.set(t,e),xs.get(t)}class As{constructor(t,e,n,s){const i=e.startsWith("--");this.setValue=i?ws:bs,this.options=s,this.updateFinishedPromise(),x("string"!=typeof s.type);const r=Vs(t).get(e);r&&r.stop();if(Array.isArray(n)||(n=[n]),function(t,e,n){for(let s=0;s<e.length;s++)null===e[s]&&(e[s]=0===s?n():e[s-1]),"number"==typeof e[s]&&Pe[t]&&(e[s]=Pe[t].transform(e[s]));!Ts()&&e.length<2&&e.unshift(n())}(e,n,(()=>e.startsWith("--")?t.style.getPropertyValue(e):window.getComputedStyle(t)[e])),z(s.type)){const t=B(s,100,s.type);s.ease=yn()?t.ease:Ss,s.duration=v(t.duration),s.type="keyframes"}else s.ease=s.ease||Ss;this.removeAnimation=()=>{var n;return null===(n=xs.get(t))||void 0===n?void 0:n.delete(e)};const o=()=>{this.setValue(t,e,ht(n,this.options)),this.cancel(),this.resolveFinishedPromise()};Vn()?(this.animation=xn(t,e,n,s),!1===s.autoplay&&this.animation.pause(),this.animation.onfinish=o,this.pendingTimeline&&Sn(this.animation,this.pendingTimeline),Vs(t).set(e,this)):o()}get duration(){return w(this.options.duration||300)}get time(){var t;return this.animation?w((null===(t=this.animation)||void 0===t?void 0:t.currentTime)||0):0}set time(t){this.animation&&(this.animation.currentTime=v(t))}get speed(){return this.animation?this.animation.playbackRate:1}set speed(t){this.animation&&(this.animation.playbackRate=t)}get state(){return this.animation?this.animation.playState:"finished"}get startTime(){return this.animation?this.animation.startTime:null}flatten(){var t;this.animation&&(null===(t=this.animation.effect)||void 0===t||t.updateTiming({easing:"linear"}))}play(){"finished"===this.state&&this.updateFinishedPromise(),this.animation&&this.animation.play()}pause(){this.animation&&this.animation.pause()}stop(){this.animation&&"idle"!==this.state&&"finished"!==this.state&&(this.animation.commitStyles&&this.animation.commitStyles(),this.cancel())}complete(){this.animation&&this.animation.finish()}cancel(){this.removeAnimation();try{this.animation&&this.animation.cancel()}catch(t){}}then(t,e){return this.currentFinishedPromise.then(t,e)}updateFinishedPromise(){this.currentFinishedPromise=new Promise((t=>{this.resolveFinishedPromise=t}))}attachTimeline(t){return this.animation?Sn(this.animation,t):this.pendingTimeline=t,i}}const Ms=t=>function(e,n,s){return new y(function(t,e,n,s){const i=K(t,s),r=i.length,o=[];for(let t=0;t<r;t++){const s=i[t],a={...n};"function"==typeof a.delay&&(a.delay=a.delay(t,r));for(const t in e){const n=e[t],i={...ut(a,t)};i.duration=i.duration?v(i.duration):i.duration,i.delay=v(i.delay||0),o.push(new As(s,t,n,i))}}return o}(e,n,s,t))},Ps=Ms(),ks=new WeakMap;let Fs;function Cs({target:t,contentRect:e,borderBoxSize:n}){var s;null===(s=ks.get(t))||void 0===s||s.forEach((s=>{s({target:t,contentSize:e,get size(){return function(t,e){if(e){const{inlineSize:t,blockSize:n}=e[0];return{width:t,height:n}}return t instanceof SVGElement&&"getBBox"in t?t.getBBox():{width:t.offsetWidth,height:t.offsetHeight}}(t,n)}})}))}function Es(t){t.forEach(Cs)}function Os(t,e){Fs||"undefined"!=typeof ResizeObserver&&(Fs=new ResizeObserver(Es));const n=K(t);return n.forEach((t=>{let n=ks.get(t);n||(n=new Set,ks.set(t,n)),n.add(e),null==Fs||Fs.observe(t)})),()=>{n.forEach((t=>{const n=ks.get(t);null==n||n.delete(e),(null==n?void 0:n.size)||null==Fs||Fs.unobserve(t)}))}}const Rs=new Set;let Bs;function Is(t){return Rs.add(t),Bs||(Bs=()=>{const t={width:window.innerWidth,height:window.innerHeight},e={target:window,size:t,contentSize:t};Rs.forEach((t=>t(e)))},window.addEventListener("resize",Bs)),()=>{Rs.delete(t),!Rs.size&&Bs&&(Bs=void 0)}}const Ls={x:{length:"Width",position:"Left"},y:{length:"Height",position:"Top"}};function Ws(t,e,s,i){const r=s[e],{length:o,position:a}=Ls[e],l=r.current,u=s.time;r.current=t[`scroll${a}`],r.scrollLength=t[`scroll${o}`]-t[`client${o}`],r.offset.length=0,r.offset[0]=0,r.offset[1]=r.scrollLength,r.progress=L(0,r.scrollLength,r.current);const c=i-u;r.velocity=c>50?0:n(r.current-l,c)}const Ds={Enter:[[0,1],[1,1]],Exit:[[0,0],[1,0]],Any:[[1,0],[0,1]],All:[[0,0],[1,1]]},Ns={start:0,center:.5,end:1};function Ks(t,e,n=0){let s=0;if(t in Ns&&(t=Ns[t]),"string"==typeof t){const e=parseFloat(t);t.endsWith("px")?s=e:t.endsWith("%")?t=e/100:t.endsWith("vw")?s=e/100*document.documentElement.clientWidth:t.endsWith("vh")?s=e/100*document.documentElement.clientHeight:t=e}return"number"==typeof t&&(s=e*t),n+s}const $s=[0,0];function js(t,e,n,s){let i=Array.isArray(t)?t:$s,r=0,o=0;return"number"==typeof t?i=[t,t]:"string"==typeof t&&(i=(t=t.trim()).includes(" ")?t.split(" "):[t,Ns[t]?t:"0"]),r=Ks(i[0],n,s),o=Ks(i[1],e),r-o}const zs={x:0,y:0};function Hs(t,e,n){const{offset:s=Ds.All}=n,{target:i=t,axis:r="y"}=n,o="y"===r?"height":"width",a=i!==t?function(t,e){const n={x:0,y:0};let s=t;for(;s&&s!==e;)if(s instanceof HTMLElement)n.x+=s.offsetLeft,n.y+=s.offsetTop,s=s.offsetParent;else if("svg"===s.tagName){const t=s.getBoundingClientRect();s=s.parentElement;const e=s.getBoundingClientRect();n.x+=t.left-e.left,n.y+=t.top-e.top}else{if(!(s instanceof SVGGraphicsElement))break;{const{x:t,y:e}=s.getBBox();n.x+=t,n.y+=e;let i=null,r=s.parentNode;for(;!i;)"svg"===r.tagName&&(i=r),r=s.parentNode;s=i}}return n}(i,t):zs,l=i===t?{width:t.scrollWidth,height:t.scrollHeight}:function(t){return"getBBox"in t&&"svg"!==t.tagName?t.getBBox():{width:t.clientWidth,height:t.clientHeight}}(i),u={width:t.clientWidth,height:t.clientHeight};e[r].offset.length=0;let c=!e[r].interpolate;const h=s.length;for(let t=0;t<h;t++){const n=js(s[t],u[o],l[o],a[r]);c||n===e[r].interpolatorOffsets[t]||(c=!0),e[r].offset[t]=n}c&&(e[r].interpolate=ln(e[r].offset,D(s)),e[r].interpolatorOffsets=[...e[r].offset]),e[r].progress=e[r].interpolate(e[r].current)}function Us(t,e,n,s={}){return{measure:()=>function(t,e=t,n){if(n.x.targetOffset=0,n.y.targetOffset=0,e!==t){let s=e;for(;s&&s!==t;)n.x.targetOffset+=s.offsetLeft,n.y.targetOffset+=s.offsetTop,s=s.offsetParent}n.x.targetLength=e===t?e.scrollWidth:e.clientWidth,n.y.targetLength=e===t?e.scrollHeight:e.clientHeight,n.x.containerLength=t.clientWidth,n.y.containerLength=t.clientHeight}(t,s.target,n),update:e=>{!function(t,e,n){Ws(t,"x",e,n),Ws(t,"y",e,n),e.time=n}(t,n,e),(s.offset||s.target)&&Hs(t,n,s)},notify:()=>e(n)}}const Ys=new WeakMap,qs=new WeakMap,Xs=new WeakMap,Gs=t=>t===document.documentElement?window:t;function Zs(t,{container:e=document.documentElement,...n}={}){let s=Xs.get(e);s||(s=new Set,Xs.set(e,s));const i=Us(e,t,{time:0,x:{current:0,offset:[],progress:0,scrollLength:0,targetOffset:0,targetLength:0,containerLength:0,velocity:0},y:{current:0,offset:[],progress:0,scrollLength:0,targetOffset:0,targetLength:0,containerLength:0,velocity:0}},n);if(s.add(i),!Ys.has(e)){const t=()=>{for(const t of s)t.measure()},n=()=>{for(const t of s)t.update(l.timestamp)},i=()=>{for(const t of s)t.notify()},a=()=>{o.read(t,!1,!0),o.read(n,!1,!0),o.update(i,!1,!0)};Ys.set(e,a);const c=Gs(e);window.addEventListener("resize",a,{passive:!0}),e!==document.documentElement&&qs.set(e,(u=a,"function"==typeof(r=e)?Is(r):Os(r,u))),c.addEventListener("scroll",a,{passive:!0})}var r,u;const c=Ys.get(e);return o.read(c,!1,!0),()=>{var t;a(c);const n=Xs.get(e);if(!n)return;if(n.delete(i),n.size)return;const s=Ys.get(e);Ys.delete(e),s&&(Gs(e).removeEventListener("scroll",s),null===(t=qs.get(e))||void 0===t||t(),window.removeEventListener("resize",s))}}function _s(t,e){let n;const s=()=>{const{currentTime:s}=e,i=(null===s?0:s.value)/100;n!==i&&t(i),n=i};return o.update(s,!0),()=>a(s)}const Js=new Map;function Qs({source:t,container:e=document.documentElement,axis:n="y"}={}){t&&(e=t),Js.has(e)||Js.set(e,{});const s=Js.get(e);return s[n]||(s[n]=g()?new ScrollTimeline({source:e,axis:n}):function({source:t,container:e,axis:n="y"}){t&&(e=t);const s={value:0},i=Zs((t=>{s.value=100*t[n].progress}),{container:e,axis:n});return{currentTime:s,cancel:i}}({source:e,axis:n})),s[n]}function ti(t){return t&&(t.target||t.offset)}function ei(t,{axis:e="y",...n}={}){const s={axis:e,...n};return"function"==typeof t?function(t,e){return function(t){return 2===t.length}(t)||ti(e)?Zs((n=>{t(n[e.axis].progress,n)}),e):_s(t,Qs(e))}(t,s):function(t,e){if(t.flatten(),ti(e))return t.pause(),Zs((n=>{t.time=t.duration*n[e.axis].progress}),e);{const n=Qs(e);return t.attachTimeline?t.attachTimeline(n,(t=>(t.pause(),_s((e=>{t.time=t.duration*e}),n)))):i}}(t,s)}const ni={some:0,all:1};function si(t,e,{root:n,margin:s,amount:i="some"}={}){const r=K(t),o=new WeakMap,a=new IntersectionObserver((t=>{t.forEach((t=>{const n=o.get(t.target);if(t.isIntersecting!==Boolean(n))if(t.isIntersecting){const n=e(t);"function"==typeof n?o.set(t.target,n):a.unobserve(t.target)}else n&&(n(t),o.delete(t.target))}))}),{root:n,rootMargin:s,threshold:"number"==typeof i?i:ni[i]});return r.forEach((t=>a.observe(t))),()=>a.disconnect()}function ii(t,e="end"){return n=>{const s=(n="end"===e?Math.min(n,.999):Math.max(n,.001))*t,i="end"===e?Math.floor(s):Math.ceil(s);return S(0,1,i/t)}}function ri(t=.1,{startDelay:e=0,from:n=0,ease:s}={}){return(i,r)=>{const o="number"==typeof n?n:function(t,e){if("first"===t)return 0;{const n=e-1;return"last"===t?n:n/2}}(n,r),a=Math.abs(o-i);let l=t*a;if(s){const e=r*t;l=Ue(s)(l/e)*e}return e+l}}function oi(...t){const e=!Array.isArray(t[0]),n=e?0:-1,s=t[0+n],i=t[1+n],r=t[2+n],o=t[3+n],a=ln(i,r,{mixer:(l=r[0],(t=>t&&"object"==typeof t&&t.mix)(l)?l.mix:void 0),...o});var l;return e?a(s):a}function ai(t,e){return function(t,e){const n=d.now(),s=({timestamp:i})=>{const r=i-n;r>=e&&(a(s),t(r-e))};return o.read(s,!0),()=>a(s)}(t,v(e))}const li=(t,e)=>Math.abs(t-e);function ui(t,e){const n=li(t.x,e.x),s=li(t.y,e.y);return Math.sqrt(n**2+s**2)}const ci=o,hi=r.reduce(((t,e)=>(t[e]=t=>a(t),t)),{});export{p as MotionValue,vs as animate,Ps as animateMini,wt as anticipate,yt as backIn,vt as backInOut,gt as backOut,a as cancelFrame,hi as cancelSync,bt as circIn,xt as circInOut,Tt as circOut,S as clamp,ys as createScopedAnimate,pt as cubicBezier,ai as delay,li as distance,ui as distance2D,Ke as easeIn,je as easeInOut,$e as easeOut,o as frame,l as frameData,u as frameSteps,si as inView,Ne as inertia,ln as interpolate,x as invariant,un as keyframes,ft as mirrorEasing,an as mix,f as motionValue,qe as pipe,L as progress,mt as reverseEasing,ei as scroll,Zs as scrollInfo,E as spring,ri as stagger,ii as steps,ci as sync,oi as transform,T as warning,U as wrap};export default null;
//# sourceMappingURL=/sm/d5d4bfa5a3f292edc74ce2b856e25f03ebbfa4c4c22aa37e3f75ca1dabe374b0.map<!doctype html>
<html lang="en" data-language="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Required Deck Title</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;500;600;700;800&family=JetBrains+Mono:wght@300;400;500;600&family=Noto+Sans+KR:wght@200;300;400;500;600;700;800&family=Noto+Sans:wght@200;300;400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root{
--paper:#fafaf8;
--paper-rgb:250,250,248;
--ink:#0a0a0a;
--ink-rgb:10,10,10;
--grey-1:#f0f0ee;
--grey-2:#d4d4d2;
--grey-3:#737373;
--accent:#002FA7;
--accent-rgb:0,47,167;
--accent-on:#ffffff;
--accent-bright:#5B7BFF;
--text-primary:#0a0a0a;
--text-secondary:#525252;
--text-helper:#737373;
--text-placeholder:#a3a3a3;
--text-on-color:#ffffff;
--border-subtle:#e0e0e0;
--border-strong:#a3a3a3;
--font-en:"Inter","Helvetica Neue","Helvetica","Arial",system-ui,-apple-system,sans-serif;
--font-ko:"SUIT","Pretendard","Noto Sans KR","Noto Sans","Inter","Helvetica Neue","Arial",system-ui,-apple-system,sans-serif;
--sans:var(--font-en);
--mono:"JetBrains Mono","IBM Plex Mono","SF Mono","Cascadia Code","Consolas","Courier New",ui-monospace,monospace;
--sp-3:8px;
--sp-4:12px;
--sp-5:16px;
--sp-6:24px;
--sp-7:32px;
--sp-8:40px;
--sp-9:48px;
--sp-10:64px;
--sp-11:80px;
--sp-12:96px;
--sp-13:160px;
--ease-prod:cubic-bezier(.2,0,.38,.9);
--ease-entry:cubic-bezier(0,0,.3,1);
--nav-safe-bottom:8vh;
}
html[data-language="ko"]{--sans:var(--font-ko)}
*{box-sizing:border-box;margin:0;padding:0}
html,body{width:100%;height:100%;overflow:hidden;background:var(--paper);color:var(--ink);font-family:var(--sans)}
body{font-weight:300;letter-spacing:0}
button{font:inherit;color:inherit}
img{display:block;max-width:100%}
#deck{position:fixed;inset:0;overflow:hidden;background:var(--paper)}
.slide{position:absolute;inset:0;display:none;background:var(--paper);color:var(--ink)}
.slide.active{display:block}
.slide.dark{background:var(--ink);color:var(--text-on-color)}
.slide.accent{background:var(--accent);color:var(--accent-on)}
.slide.split .canvas-card{padding:0;display:grid;grid-template-columns:1fr 1fr}
.canvas-card{width:100vw;height:100vh;padding:5.6vh 5vw 4.4vh;display:flex;flex-direction:column;position:relative;overflow:hidden;background:inherit;color:inherit}
.chrome-min{display:flex;align-items:center;justify-content:space-between;gap:24px;margin-bottom:var(--sp-9);font:500 11px/1 var(--mono);text-transform:uppercase;letter-spacing:.16em;color:var(--text-helper)}
.dark .chrome-min,.accent .chrome-min{color:rgba(255,255,255,.78)}
.foot{margin-top:auto;font:400 11px/1.5 var(--mono);text-transform:uppercase;letter-spacing:.12em;color:var(--text-helper)}
.t-meta{font:500 11px/1 var(--mono);text-transform:uppercase;letter-spacing:.18em;color:var(--text-helper)}
.t-cat{font:600 13px/1.1 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--accent)}
.lead{font:300 max(17px,1.45vw)/1.45 var(--sans);color:var(--text-secondary);max-width:58ch}
.body{font:300 max(15px,1.08vw)/1.6 var(--sans);color:var(--text-secondary)}
.body-sm{font:300 max(12px,.88vw)/1.55 var(--sans);color:var(--text-secondary)}
.mono{font-family:var(--mono);font-feature-settings:"tnum"}
.accent-text{color:var(--accent)}
.h-hero{font:200 min(11.6vw,19vh)/.92 var(--sans);letter-spacing:-.045em}
.h-statement{font:200 min(9.6vw,16vh)/.92 var(--sans);letter-spacing:-.045em}
.h-xl{font:200 min(7.2vw,12.8vh)/.96 var(--sans);letter-spacing:-.04em}
.h-md{font:300 min(3.8vw,6.8vh)/1.02 var(--sans);letter-spacing:-.025em}
.num-mega{font:200 min(18vw,24vh)/.82 var(--sans);letter-spacing:-.06em}
.grid-12{display:grid;grid-template-columns:repeat(12,1fr);gap:16px}
.grid-16{display:grid;grid-template-columns:repeat(16,1fr);gap:16px}
.span-2{grid-column:span 2}.span-3{grid-column:span 3}.span-4{grid-column:span 4}.span-5{grid-column:span 5}.span-6{grid-column:span 6}.span-7{grid-column:span 7}.span-8{grid-column:span 8}.span-9{grid-column:span 9}.span-10{grid-column:span 10}.span-12{grid-column:span 12}
.hr-hairline{height:1px;background:currentColor;opacity:.22}
.card-fill,.brief-card,.matrix-cell,.force-card{background:var(--grey-1);padding:24px;color:var(--ink)}
.card-ink{background:var(--ink);color:var(--text-on-color);padding:24px}
.card-accent{background:var(--accent);color:var(--accent-on);padding:24px}
.card-outlined{border:1px solid var(--border-subtle);padding:24px;background:transparent}
.dark .card-fill{background:#161616;color:#fff}
.cover-row{display:grid;grid-template-columns:minmax(120px,22vw) 1fr;gap:3vw;align-items:end;border-top:1px solid currentColor;padding:2.4vh 0}
.cover-row .nb{font:200 min(10vw,16vh)/.85 var(--sans);letter-spacing:-.05em}
.half{padding:5.6vh 3.6vw 4.4vh;display:flex;flex-direction:column;position:relative;overflow:hidden}
.b-ink{background:var(--ink);color:#fff}
.b-paper{background:var(--paper);color:var(--ink)}
.b-accent{background:var(--accent);color:var(--accent-on)}
.sub-grid-3-2{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(2,1fr);gap:1px;background:var(--border-subtle)}
.sub-grid-3-2>*{background:var(--paper);padding:24px}
.stack-row{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.kpi-row-4{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.kpi-tower-row{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;align-items:end}
.bar-tower{height:var(--h,34vh);background:var(--accent)}
.timeline-v{display:grid;gap:24px;position:relative}
.tl-node{display:grid;grid-template-columns:24px 1fr;gap:20px;align-items:start}
.tl-axis{position:relative}
.tl-axis:before{content:"";position:absolute;left:11px;top:0;bottom:-24px;border-left:1px dashed var(--border-strong)}
.dot{position:relative;z-index:1;width:8px;height:8px;margin:4px 0 0 8px;background:var(--accent)}
.timeline-h{position:relative;display:grid;grid-template-columns:repeat(var(--count,5),1fr);gap:16px;padding-top:10vh}
.timeline-h:before{content:"";position:absolute;left:0;right:0;top:calc(10vh + 4px);height:1px;background:var(--border-strong)}
.tl-h-node{position:relative;padding-top:28px}
.tl-h-node:before{content:"";position:absolute;top:0;left:0;width:8px;height:8px;background:var(--accent)}
.h-bar-chart{display:grid;gap:14px}
.bar-row{display:grid;grid-template-columns:minmax(140px,22vw) 1fr auto;gap:16px;align-items:center}
.bar-fill{height:8px;background:var(--accent);width:var(--w,50%)}
.duo-compare{display:grid;grid-template-columns:1fr 1px 1fr;gap:4vw;align-items:stretch;flex:1}
.duo-compare:has(.vrule){grid-template-columns:1fr 1px 1fr}
.vrule{width:1px;background:var(--border-subtle)}
.manifesto-top{display:grid;grid-template-columns:7fr 5fr;gap:4vw;align-items:start}
.ink-banner-full{margin:auto -5vw -4.4vh;padding:6vh 5vw;background:var(--ink);color:#fff}
.three-forces{display:grid;grid-template-columns:5fr 11fr;gap:16px;flex:1}
.hero-ink-col{background:var(--ink);color:#fff;padding:32px;display:flex;flex-direction:column;justify-content:space-between}
.force-num{font:200 min(7vw,11vh)/.9 var(--sans);color:var(--accent)}
.loop-diagram{display:grid;grid-template-columns:5fr 7fr;gap:4vw;align-items:center;flex:1}
.loop-steps{display:grid;gap:16px}
.loop-svg,.sys-svg{width:100%;height:100%;min-height:42vh}
.matrix-fill{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.hero-stat-bottom{margin-top:auto;display:flex;align-items:end;justify-content:space-between;gap:24px}
.brief-grid{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(2,1fr);gap:16px}
.brief-card{min-height:20vh;display:flex;flex-direction:column;justify-content:space-between}
.brief-card.is-accent{background:var(--accent);color:var(--accent-on)}
.system-diagram{display:grid;grid-template-columns:5fr 7fr;gap:4vw;align-items:center;flex:1}
.sys-label{border-top:1px solid var(--border-subtle);padding-top:12px}
.why-now-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;align-items:stretch}
.why-col{display:flex;flex-direction:column;min-height:50vh;border-top:1px solid var(--ink);padding-top:18px}
.why-num-bottom{margin-top:auto;font:200 min(8.4vw,14vh)/.9 var(--sans);letter-spacing:-.05em}
.four-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.fc-col{border-top:1px solid var(--ink);padding-top:16px}
.stacked-ledger{display:grid;gap:0}
.ledger-row{display:grid;grid-template-columns:minmax(180px,28vw) 1fr auto;gap:24px;align-items:end;border-bottom:1px solid var(--border-subtle);padding:1.8vh 0}
.ledger-num{font:200 min(10vw,15vh)/.85 var(--sans);letter-spacing:-.055em}
.tech-spec{display:grid;grid-template-columns:5fr 7fr;gap:4vw;flex:1}
.spec-kpi-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.spec-bars{display:flex;align-items:end;gap:8px;min-height:22vh}
.bar-vert{width:16px;height:var(--h,18vh);background:var(--accent)}
.frame-img{position:relative;overflow:hidden;background:var(--paper)}
.frame-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center center}
.fit-contain img{object-fit:contain}
.r-21x9{aspect-ratio:21/9}
.r-16x10{aspect-ratio:16/10}
.r-16x9{aspect-ratio:16/9}
.h-22{height:22vh}
.h-26{height:26vh}
.image-hero-body{display:grid;grid-template-columns:4fr 8fr;gap:4vw;padding:4vh 5vw 0}
.image-hero-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.dot-mat,.ring-mat,.cross-mat{position:absolute;pointer-events:none;opacity:.18}
.dot-mat{background-image:radial-gradient(currentColor 1px, transparent 1px);background-size:14px 14px}
.ring-mat{background-image:radial-gradient(transparent 4px,currentColor 4px,currentColor 5px,transparent 5px);background-size:20px 20px}
.cross-mat{background-image:linear-gradient(45deg,transparent 47%,currentColor 48%,currentColor 52%,transparent 53%),linear-gradient(-45deg,transparent 47%,currentColor 48%,currentColor 52%,transparent 53%);background-size:18px 18px}
.ascii-bg{position:absolute;inset:0;width:100%;height:100%;z-index:0;opacity:.35}
.canvas-card>*:not(.ascii-bg),.half>*:not(.ascii-bg){position:relative;z-index:1}
.nav-safe-bottom{padding-bottom:var(--nav-safe-bottom)}
.nav-safe-bottom-tight{padding-bottom:4vh}
#hint{position:fixed;right:18px;bottom:18px;z-index:50;font:500 11px/1 var(--mono);text-transform:uppercase;letter-spacing:.12em;color:rgba(10,10,10,.55);pointer-events:none}
.slide.dark~#hint,.slide.accent~#hint{color:rgba(255,255,255,.7)}
#nav{position:fixed;left:50%;bottom:2vh;transform:translateX(-50%);z-index:60;display:flex;gap:8px}
#nav button{width:8px;height:8px;border:0;background:rgba(10,10,10,.22);border-radius:0;padding:0;cursor:pointer}
#nav button.active{background:var(--accent)}
.accent~#nav button.active{background:#fff}
.dark~#nav button{background:rgba(255,255,255,.28)}
#index{position:fixed;inset:0;z-index:80;display:none;background:rgba(250,250,248,.96);padding:4vh 4vw;overflow:auto}
#index.open{display:block}
.index-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:18px}
.index-card{border:1px solid var(--border-subtle);background:#fff;padding:14px;cursor:pointer}
.index-card .n{font:600 11px var(--mono);color:var(--accent);margin-bottom:8px}
.index-card .t{font:400 16px/1.3 var(--sans)}
body.low-power *,body.low-power *:before,body.low-power *:after{animation:none!important;transition:none!important}
[data-anim]{opacity:1}
@media (max-width:800px){
.canvas-card{padding:32px 22px}
.slide.split .canvas-card,.duo-compare,.manifesto-top,.three-forces,.loop-diagram,.system-diagram,.tech-spec,.image-hero-body{grid-template-columns:1fr}
.grid-12,.grid-16,.sub-grid-3-2,.stack-row,.kpi-row-4,.kpi-tower-row,.brief-grid,.why-now-grid,.four-cards,.matrix-fill{grid-template-columns:1fr}
.h-hero{font-size:min(18vw,16vh)}
.h-xl{font-size:min(12vw,10vh)}
}
</style>
</head>
<body>
<div id="deck">
<!-- Replace these sample sections with the final deck. -->
<!-- SLIDES_HERE -->
<section class="slide accent active" data-layout="S01" data-animate="hero">
<div class="canvas-card">
<canvas class="ascii-bg" aria-hidden="true"></canvas>
<div class="chrome-min">
<div class="l">Deck Title</div>
<div class="r">01 / 02</div>
</div>
<div style="flex:1;display:grid;align-content:center;gap:3vh">
<div class="t-meta" style="color:rgba(255,255,255,.78)">Field Note</div>
<h1 class="h-hero">Required<br>Deck Title</h1>
<p class="lead" style="color:rgba(255,255,255,.86)">Replace this sample cover with the finished slide content.</p>
</div>
</div>
</section>
<section class="slide split" data-layout="S10" data-animate="split-statement">
<div class="canvas-card">
<div class="half b-accent">
<canvas class="ascii-bg" aria-hidden="true"></canvas>
<div class="chrome-min">
<div class="l">Closing</div>
<div class="r">02 / 02</div>
</div>
<div style="margin-top:auto">
<h2 class="h-statement">One clear<br>takeaway.</h2>
</div>
</div>
<div class="half b-paper">
<div class="chrome-min">
<div class="l">Summary</div>
<div class="r">End</div>
</div>
<div style="display:grid;gap:24px;margin:auto 0">
<div class="card-fill"><div class="t-meta">01</div><h3 class="h-md">Point one</h3><p class="body-sm">Write one concise closing idea.</p></div>
<div class="card-fill"><div class="t-meta">02</div><h3 class="h-md">Point two</h3><p class="body-sm">Keep each card short and parallel.</p></div>
<div class="card-fill"><div class="t-meta">03</div><h3 class="h-md accent-text">Point three</h3><p class="body-sm">Use the accent once for the final emphasis.</p></div>
</div>
</div>
</div>
</section>
</div>
<div id="nav" aria-label="Slide navigation"></div>
<div id="hint">Left/Right: slides | B: static | Esc: index</div>
<div id="index" aria-hidden="true"></div>
<script>
(() => {
const slides = Array.from(document.querySelectorAll('.slide'));
const nav = document.getElementById('nav');
const hint = document.getElementById('hint');
const index = document.getElementById('index');
const key = 'tightened-slide-low-power';
let current = Math.max(0, slides.findIndex(s => s.classList.contains('active')));
let wheelLock = false;
let startX = 0;
function updateHint(){
hint.textContent = `Left/Right: slides | B: ${document.body.classList.contains('low-power') ? 'motion' : 'static'} | Esc: index`;
}
function setLowPower(on){
document.body.classList.toggle('low-power', on);
localStorage.setItem(key, on ? '1' : '0');
updateHint();
}
function renderNav(){
nav.innerHTML = '';
slides.forEach((_, i) => {
const button = document.createElement('button');
button.type = 'button';
button.setAttribute('aria-label', `Go to slide ${i + 1}`);
button.addEventListener('click', () => show(i));
nav.appendChild(button);
});
}
function show(i){
current = Math.max(0, Math.min(i, slides.length - 1));
slides.forEach((slide, idx) => slide.classList.toggle('active', idx === current));
Array.from(nav.children).forEach((button, idx) => button.classList.toggle('active', idx === current));
window.__currentSlideIndex = current;
}
function openIndex(){
const cards = slides.map((slide, i) => {
const title = slide.querySelector('h1,h2,.h-hero,.h-xl,.h-statement')?.textContent?.trim() || `Slide ${i + 1}`;
return `<button class="index-card" type="button" data-go="${i}"><div class="n">${String(i + 1).padStart(2,'0')}</div><div class="t">${title}</div></button>`;
}).join('');
index.innerHTML = `<div class="index-grid">${cards}</div>`;
index.classList.add('open');
index.setAttribute('aria-hidden','false');
}
function closeIndex(){
index.classList.remove('open');
index.setAttribute('aria-hidden','true');
}
document.addEventListener('keydown', event => {
if(event.key === 'ArrowRight' || event.key === 'PageDown') show(current + 1);
if(event.key === 'ArrowLeft' || event.key === 'PageUp') show(current - 1);
if(event.key === 'Escape') index.classList.contains('open') ? closeIndex() : openIndex();
if(event.key.toLowerCase() === 'b') setLowPower(!document.body.classList.contains('low-power'));
});
document.addEventListener('wheel', event => {
if(wheelLock || Math.abs(event.deltaY) < 20) return;
wheelLock = true;
show(current + (event.deltaY > 0 ? 1 : -1));
setTimeout(() => { wheelLock = false; }, 450);
}, {passive:true});
document.addEventListener('pointerdown', event => { startX = event.clientX; }, {passive:true});
document.addEventListener('pointerup', event => {
const dx = event.clientX - startX;
if(Math.abs(dx) > 50) show(current + (dx < 0 ? 1 : -1));
}, {passive:true});
index.addEventListener('click', event => {
const target = event.target.closest('[data-go]');
if(!target) return;
closeIndex();
show(Number(target.dataset.go));
});
function startAscii(){
const canvases = Array.from(document.querySelectorAll('.ascii-bg'));
if(!canvases.length) return;
const chars = '01/|+-';
const contexts = canvases.map(canvas => {
const ctx = canvas.getContext('2d');
return {canvas, ctx};
});
function draw(time){
contexts.forEach(({canvas, ctx}) => {
const rect = canvas.getBoundingClientRect();
const scale = window.devicePixelRatio || 1;
const w = Math.max(1, Math.floor(rect.width * scale));
const h = Math.max(1, Math.floor(rect.height * scale));
if(canvas.width !== w || canvas.height !== h){canvas.width = w; canvas.height = h}
ctx.clearRect(0,0,w,h);
ctx.font = `${14 * scale}px JetBrains Mono, monospace`;
ctx.fillStyle = 'rgba(255,255,255,.18)';
const step = 22 * scale;
for(let y = step; y < h; y += step){
for(let x = step; x < w; x += step){
const n = Math.floor(Math.abs(Math.sin(x * .004 + y * .006 + time * .001)) * chars.length) % chars.length;
ctx.fillText(chars[n], x, y);
}
}
});
if(!document.body.classList.contains('low-power')) requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
}
if(localStorage.getItem(key) === '1') document.body.classList.add('low-power');
renderNav();
show(current);
updateHint();
startAscii();
})();
</script>
</body>
</html>
Tightened Slide Delivery Checklist
Run this before handing off a deck.
Required Checks
- Every slide has a registered
data-layout. - Body pages use only
S01toS22. - Map/location relationship pages use
S08 + Tightened Map Component. - No custom body layout was invented for image split, evidence wall, or decorative geometry.
- Every local image has
data-image-slot. S22usesdata-image-slot="s22-hero-21x9".- No visible
<text>appears inside SVG. - The validator passes:
node scripts/validate-deck.mjs path/to/index.htmlLanguage Checks
- The deck uses either English mode or Korean mode.
- English decks use
<html lang="en" data-language="en">. - Korean decks use
<html lang="ko" data-language="ko">. - Korean decks use the template Korean font stack:
SUIT,Pretendard,Noto Sans KR, andNoto Sans. - Diagram labels and generated-image text match the chosen language.
Visual System
- One accent color only.
- No gradient, shadow, glass effect, rounded card, neon, or decorative border.
- Large titles use light weight, normally
200or300. - Large type uses
font-size:min(Xvw,Yvh)with enoughvhheadroom. - Body slide titles sit on the left/top content axis unless the registered layout is a statement or split page.
- Kicker/meta text sits above the title.
.canvas-cardhorizontal padding is not duplicated by a nestedpadding:... 5vw ....- Content does not touch the bottom navigation safe area.
Image Checks
- Single large visual pages use
S22. - Multiple image pages adapt
S15orS16. - Image groups share one ratio and one visual scale.
- S22 photos use
object-position:center 35%orcenter center, nottop center. - UI and information graphics use
fit-containonly when preserving an uncontrolled original screenshot or dense text. - Regenerated slot images fill their ratio frame, for example
.frame-img.r-21x9. - Generated images contain no slide title, footer, page number, corner mark, logo, signature, or border.
Browser Checks
- Open the deck and inspect every page after animation settles.
- Use arrow navigation, wheel navigation, touch if relevant, ESC index, and
Bstatic mode. - Confirm ESC index thumbnails show animated content.
- Confirm captions, timeline labels, footnotes, and KPI blocks clear the navigation dots.
Tightened Slide Image Prompts
Use these prompts only after the deck layout and image slot are chosen. Generated images are embedded assets, not standalone slides.
Hard Rules
- Match the selected image slot before generating.
- Use one accent color only: International Klein Blue, Lemon Yellow, Lemon Green, or Safety Orange.
- Keep the Tightened Slide baseline: 12/16 column grid, Helvetica/Inter feel, asymmetry, hairline rules, sharp rectangles, large whitespace.
- Do not generate gradients, shadows, rounded corners, glass effects, 3D, neon, cartoons, fake logos, borders, slide chrome, page numbers, footers, signatures, or title bars.
- Infographic and UI text must match the deck language.
- Supported deck languages are English and Korean.
- For 21:9 assets, keep the subject in the central 70% safe area.
- Same-page image groups must share ratio, visual scale, margin density, and line weight.
Slot Ratios
| Slot | Ratio | Use |
|---|---|---|
s22-hero-21x9 | 21:9 | S22 hero strip |
s15-grid-21x9 | 21:9 | S15 image matrix adaptation |
s15-grid-16x10 | 16:10 | S15 denser UI or infographic grid |
s16-brief-21x9 | 21:9 | S16 brief card image row |
s16-brief-16x10 | 16:10 | S16 UI or chart cards |
Documentary Photo
For S22 hero strips or case evidence.
Generate a 21:9 ultra-wide documentary photograph about [page concept]. Style: Tightened Slide editorial, high contrast, restrained saturation, real office/city/product-use setting, large negative space, subject centered in the safe middle area. No AI robot, sci-fi interface, staged commercial stock pose, logo, watermark, text, title, footer, page chrome, signature, or border. Output only the core photo.System Or Relationship Infographic
For architecture, workflow, comparison, or concept diagrams.
Generate a horizontal International Typographic infographic explaining [concept/process/system relationship]. Use Helvetica/Inter-like sans labels, a strict 12/16-column grid, sharp rectangular modules, 1px hairline rules, black/white/gray, and one [IKB blue / lemon yellow / lemon green / safety orange] accent. Text language: [English/Korean]. Keep each label under 8 words. No gradient, shadow, rounded corner, 3D, cartoon, neon, SaaS template look, logo, title, footer, page number, signature, decorative border, or slide frame. Ratio: [21:9/16:10].UI Redesign Asset
For screenshots, dashboards, workspaces, code, or product flows.
Generate a horizontal UI scene that redesigns [screenshot/interface/workspace content] in the Tightened Slide layout language. Use a minimal dashboard/workspace structure, sharp panels, hairline rules, 12-column grid, restrained black/white/gray, and one [IKB blue / lemon yellow / lemon green / safety orange] accent. Text language: [English/Korean], short labels only. No real brand logos, gradients, shadows, rounded corners, 3D, neon, title bar, footer, page number, signature, border, or slide chrome. Ratio: 16:10.Multi-Image Grid Asset
For one image inside an S15 or S16 group.
Generate one horizontal evidence image about [evidence A/B/C]. It belongs to a coordinated International Typographic image group, so keep the same ratio, element scale, margins, line weight, label density, black/white/gray palette, and single [IKB blue / lemon yellow / lemon green / safety orange] accent as the group. Text language: [English/Korean], short labels only. No title, footer, page number, logo, signature, decorative border, or slide frame. Ratio: [21:9/16:10].Minimal Data Poster
For numeric evidence and small chart assets.
Generate a horizontal International Typographic data graphic. Core data: [number/comparison/ranking]. Meaning: [explanation]. Use oversized light-weight sans numerals, 1px hairline rules, sharp color blocks, black/white/gray, and one [IKB blue / lemon yellow / lemon green / safety orange] accent. Text language: [English/Korean], only necessary labels. No gradients, shadows, rounded corners, 3D, decorative border, page chrome, title, footer, page number, or signature. Ratio: [16:9/16:10].Tightened Slide Layout Lock
This file is the structural contract for Tightened Slide decks. It prevents pages from looking visually related while using unregistered structures.
Generation Rules
1. Every body slide must pick one registered layout before markup is written. 2. Every <section class="slide"> must include data-layout="Sxx" or an allowed cover or closing layout id. 3. Do not invent new body structures. 4. Use S22 Image Hero for one large visual. 5. Use S15 or S16 grid adaptations for multiple visuals. 6. Use S08 + Tightened Map Component for maps, routes, and location networks. 7. Keep body titles on the left/top content axis unless the registered statement or split layout says otherwise. 8. SVG is for geometry only. Visible labels belong in HTML. 9. Choose the image slot before generating or placing an image.
Registered Layouts
| ID | Name | Required Skeleton | Image Rule |
|---|---|---|---|
| S01 | Index Cover | Three cover-row rows with large index and title | None |
| S02 | Vertical Timeline + KPI | Top title, .timeline-v, bottom .kpi-row-4 | None |
| S03 | Split Statement | .slide.split with a large left statement and right explanation | None |
| S04 | Six Cells | Top title and .sub-grid-3-2 six-cell grid | Small icons only |
| S05 | Three Layers | Top title and .stack-row three-block structure | None |
| S06 | KPI Tower | Left title, right note, unequal KPI towers | None |
| S07 | Horizontal Bar | Left-aligned title and horizontal bar list | None |
| S08 | Duo Compare | .duo-compare two columns with a center rule | Map component may replace the right slot |
| S09 | Dot Matrix Statement | Large statement plus dot matrix decoration | None |
| S10 | Split Closing | .slide.split with left statement and right takeaway list | None |
| S11 | Horizontal Timeline | Header plus .timeline-h | None |
| S12 | Manifesto + Ink Banner | Large statement and full-width ink banner | None |
| S13 | Three Forces | Left ink hero block and three right cards | None |
| S14 | Loop Form | Left steps and right geometric loop | SVG geometry only |
| S15 | Matrix + Hero Stat | Matrix grid and bottom hero stat | Multi-image grid may be adapted |
| S16 | Multi-card Brief | Three by two brief cards | Multi-image cards may be adapted |
| S17 | System Diagram | Header, geometric system diagram, bottom notes | SVG geometry only |
| S18 | Why Now | Three progressive columns and bottom numbers | None |
| S19 | Four Cards | Top accent rule and four equal cards | None |
| S20 | Stacked KPI Ledger | Vertical ledger rows with large numbers | None |
| S21 | Tech Spec Sheet | Large title, KPI row, vertical bar matrix | None |
| S22 | Image Hero | Full-width top image, title block, lower KPI row | Main image must be 21:9 |
Image Slot Rules
S22 Hero Strip
- Slot:
s22-hero-21x9. - Ratio:
21:9. - Use for real scenes, product scenes, UI scenes, or case evidence.
- The subject must stay in the central safe area.
- Photos should use
object-fit:coverandobject-position:center 35%orcenter center. - Dense UI or infographic images may use
object-fit:containonly when needed.
S15 and S16 Image Grids
- Use one ratio per group:
21:9or16:10. - Use one visual scale per group.
- Use
.frame-img.r-21x9or.frame-img.r-16x10for regenerated slot images. - Use
.fit-containonly for uncontrolled screenshots or dense text images.
Banned Patterns
- Missing
data-layout. - Unregistered body pages.
- Centered body titles outside registered statement or split layouts.
- Visible SVG
<text>. - Images without
data-image-slot. - Rounded image containers, shadows, gradients, or glass effects.
- S22 photos with
object-position:top center.
Tightened Slide Layouts
This file describes the registered Tightened Slide layouts and when to use them. Body slides must use S01 to S22. Do not invent new page structures.
Baseline
- Use Inter, Helvetica, Arial, and system sans fonts in English mode.
- Use SUIT, Pretendard, Noto Sans KR, and Noto Sans in Korean mode.
- Use one accent color per deck.
- Use 16-column grid thinking even when the markup uses local CSS grids.
- Use sharp rectangles, hairline rules, and large whitespace.
- Do not use gradients, shadows, rounded cards, glass effects, neon effects, or decorative borders.
- Large type uses
font-weight:200or300. - Body text usually uses
300; small category labels use600. - Large font sizes must use
min(Xvw,Yvh)with enoughvhheadroom. - Put category or meta text above the title, not beside it.
- The
.canvas-cardalready provides page padding. Do not add another full-width inner padding layer. - Keep captions, footnotes, and low labels above the bottom navigation area.
- SVG is for geometry only. Put all readable labels in HTML.
Language Modes
English mode:
- Use
<html lang="en" data-language="en">. - Write concise sentence case titles.
- Keep labels short and diagram text under eight words where possible.
Korean mode:
- Use
<html lang="ko" data-language="ko">. - Write compact Korean titles and short body lines.
- Keep product names and technical terms consistent across slides.
Layout Planning Table
Before writing slides, draft this table:
page -> data-layout -> reason -> image slotExample:
01 -> S01 -> cover and topic frame -> none
02 -> S03 -> central thesis -> none
03 -> S08 -> before and after comparison -> none
04 -> S14 -> loop model -> none
05 -> S22 -> product evidence -> s22-hero-21x9
06 -> S10 -> closing takeaways -> noneLayout Diversity
- A 7 or 8 page deck should use at least six different
Sxxlayouts. - A deck with 10 or more pages should use at least eight different
Sxxlayouts. - Avoid three consecutive pages with the same body structure.
- Test decks should include a cover, a closing page, one comparison or timeline, one structure diagram, and one image layout.
Registered Layouts
S01 Index Cover
Use for deck openers or section openers. It carries the title, subtitle, and metadata. Keep it bold, sparse, and highly structured.
Recommended classes: .slide.accent, .canvas-card, .chrome-min, .ascii-bg, .h-hero, .lead.
S02 Vertical Timeline + KPI
Use for evolution over time with real numeric signals. Each node needs a date or stage, a metric, and a short explanation. If there is no numeric signal, use S11.
Recommended classes: .timeline-v, .tl-node, .tl-axis, .dot, .kpi-row-4.
S03 Split Statement
Use for a thesis, chapter statement, or strong claim. Keep one large idea on the left and a short explanation on the right.
Recommended classes: .slide.split, .half, .b-ink, .b-paper, .h-statement.
S04 Six Cells
Use for exactly six peer items: concepts, features, principles, or short definitions. Do not force four or five items into this layout.
Recommended classes: .sub-grid-3-2, .card-fill, .t-cat, .body-sm.
S05 Three Layers
Use for three stages, three layers, or three peer ideas with moderate explanation.
Recommended classes: .stack-row, .card-fill, .h-md, .lead.
S06 KPI Tower
Use for four comparable quantitative metrics. Bar height must reflect real data. Do not use this for qualitative feature lists.
Recommended classes: .kpi-tower-row, .bar-tower, .card-outlined.
S07 Horizontal Bar
Use for five to ten ranked or proportional values. Every bar needs a real comparable value.
Recommended classes: .h-bar-chart, .bar-row, .bar-fill.
S08 Duo Compare
Use for before/after, old/new, model A/model B, or two-track explanations. The two sides should be structurally parallel.
Recommended classes: .duo-compare, .vrule, .card-fill.
Use S08 + Tightened Map Component for route or location networks.
S09 Dot Matrix Statement
Use for a second statement page or a visual pause. It should carry a compressed claim, not a data table or long paragraph.
Recommended classes: .dot-mat, .h-statement, .t-meta.
S10 Split Closing
Use once near the end. Use the left side for the final statement and the right side for three short takeaways.
Recommended classes: .slide.split, .half, .b-accent, .closing-list.
S11 Horizontal Timeline
Use for a linear process or timeline with four to seven steps. Use S14 for loops.
Recommended classes: .timeline-h, .tl-h-node, .tl-h-axis.
S12 Manifesto + Ink Banner
Use for a section close or a strong mid-deck conclusion. It carries a claim plus one high-contrast banner.
Recommended classes: .manifesto-top, .ink-banner-full.
S13 Three Forces
Use for exactly three rich peer ideas. Each card should have the same internal structure.
Recommended classes: .three-forces, .hero-ink-col, .force-card, .force-num.
S14 Loop Form
Use for feedback loops, automation loops, learning loops, or repeated cycles. Do not use it for linear sequences.
Recommended classes: .loop-diagram, .loop-steps, .loop-svg.
S15 Matrix + Hero Stat
Use for eight to twelve peer items plus a total or summary metric. It may be adapted into a multi-image grid when all image slots share one ratio.
Recommended classes: .matrix-fill, .matrix-cell, .hero-stat-bottom, .frame-img.r-21x9.
S16 Multi-card Brief
Use for exactly six compact notes, tips, or small feature cards. It may be adapted into a six-image brief grid.
Recommended classes: .brief-grid, .brief-card, .frame-img.r-21x9.
S17 System Diagram
Use for a strict three-layer system, ecosystem, or architecture map. Labels must be HTML, not SVG text.
Recommended classes: .system-diagram, .sys-svg, .sys-label.
S18 Why Now
Use for three reasons, each backed by a number or clear evidence. The last column may carry the accent.
Recommended classes: .why-now-grid, .why-col, .why-num-bottom.
S19 Four Cards
Use for exactly four equal features or modules. Keep the card style consistent.
Recommended classes: .four-cards, .fc-col.
S20 Stacked KPI Ledger
Use for four to six core metrics in ledger form. Each row needs a number, label, and short context.
Recommended classes: .stacked-ledger, .ledger-row, .ledger-num.
S21 Tech Spec Sheet
Use for product specs, benchmarks, model performance, or dense technical evidence. It needs real multi-dimensional data.
Recommended classes: .tech-spec, .spec-title-col, .spec-kpi-grid, .spec-bars, .bar-vert.
S22 Image Hero
Use for a large visual plus three supporting metrics. The top image must be a 21:9 slot with data-image-slot="s22-hero-21x9".
Recommended classes: .image-hero-body, .image-hero-stats, .frame-img, .r-21x9.
Content To Layout Index
| Content Shape | Use | Avoid |
|---|---|---|
| Cover or opener | S01 | Dense data layouts |
| Thesis or chapter statement | S03 or S09 | KPI layouts |
| Before and after | S08 | Six-cell grids |
| Four peer ideas | S19 | S04 |
| Six peer ideas | S04 or S16 | S19 |
| Three peer ideas | S05 or S13 | S04 |
| Linear process | S11 | S14 |
| Loop or feedback cycle | S14 | S11 |
| Ranked quantitative values | S07 | Statement layouts |
| Four quantitative values | S06 | Qualitative card layouts |
| Dense product specs | S21 | Light statement pages |
| One large visual | S22 | Unregistered split image pages |
| Multiple related visuals | S15 or S16 adaptation | Unregistered evidence walls |
| Route or location network | S08 map extension | Generic cards |
| Closing | S10 | Reusing cover structure |
Common Errors
1. Adding border-radius to cards or image frames. 2. Adding shadows or gradients. 3. Using visible SVG text. 4. Centering a normal body title. 5. Using data layouts without real data. 6. Using one generic animation recipe for every page. 7. Placing captions too close to the navigation dots. 8. Duplicating .canvas-card page padding inside the body. 9. Using mixed image ratios in one group. 10. Generating images before deciding the slot.
Tightened Map Component
Use this component for geography, routes, event locations, store networks, campuses, or city relationships. It is not a new layout. It is an S08 Duo Compare right-slot extension.
Contract
- Keep
data-layout="S08"on the slide. - Keep the left side as relationship notes or explanation cards.
- Replace the right side with a map panel.
- Include markers, connection lines, cards, and
+,-,DRAGcontrols. - Disable wheel zoom and drag by default so slide navigation remains stable.
- Provide static fallback content so the slide remains readable if live map assets fail.
Minimal HTML
<section class="slide light" data-layout="S08" data-animate="duo-mirror">
<div class="canvas-card">
<div class="chrome-min">
<div class="l">Field Map</div>
<div class="r">08 / NN</div>
</div>
<div class="duo-compare">
<div>
<div class="t-meta">Route Logic</div>
<h2 class="h-xl">One network, three anchors</h2>
<div class="map-note-list">
<div class="relation-card">
<div class="nb">01</div>
<div>
<div class="ttl">Anchor A to Anchor B</div>
<div class="desc">State the spatial or operational relationship.</div>
</div>
</div>
<div class="relation-card">
<div class="nb">02</div>
<div>
<div class="ttl">Anchor B to Anchor C</div>
<div class="desc">Keep text short enough for slide reading.</div>
</div>
</div>
</div>
</div>
<div class="map-panel">
<div class="map-controls">
<button type="button" data-map-ctrl="zoom-in">+</button>
<button type="button" data-map-ctrl="zoom-out">-</button>
<button type="button" data-map-ctrl="drag">DRAG</button>
</div>
<div class="map-static">
<div class="map-line"></div>
<div class="map-marker" style="left:22%;top:62%">A</div>
<div class="map-marker" style="left:56%;top:38%">B</div>
<div class="map-marker" style="left:78%;top:58%">C</div>
</div>
</div>
</div>
</div>
</section>Optional CSS
.map-panel{position:relative;min-height:58vh;background:var(--grey-1);overflow:hidden}
.map-controls{position:absolute;right:16px;top:16px;z-index:2;display:flex;gap:8px}
.map-controls button{border:1px solid var(--ink);background:var(--paper);padding:8px 10px;font:600 12px var(--mono);border-radius:0}
.map-static{position:absolute;inset:0}
.map-line{position:absolute;left:24%;top:52%;width:54%;height:1px;background:var(--ink);transform:rotate(-6deg);transform-origin:left center}
.map-marker{position:absolute;width:34px;height:34px;display:grid;place-items:center;background:var(--accent);color:var(--accent-on);font:600 12px var(--mono)}
.map-note-list{display:grid;gap:16px;margin-top:32px}
.relation-card{display:grid;grid-template-columns:auto 1fr;gap:14px;border-top:1px solid var(--ink);padding-top:14px}
.relation-card .nb{font:600 12px var(--mono);color:var(--accent)}
.relation-card .ttl{font-weight:500}
.relation-card .desc{margin-top:6px;color:var(--text-secondary);font-weight:300;line-height:1.5}Tightened Slide Theme Presets
Use exactly one accent color per deck. Do not mix accents and do not accept arbitrary custom hex values.
How To Apply A Theme
1. Open assets/template.html. 2. Find the :root block. 3. Replace the theme variables as a group. 4. Leave the spacing, type, and motion tokens unchanged.
International Klein Blue
Best for general use, AI products, commercial launches, design systems, and analytical talks.
--paper:#fafaf8;
--paper-rgb:250,250,248;
--ink:#0a0a0a;
--ink-rgb:10,10,10;
--grey-1:#f0f0ee;
--grey-2:#d4d4d2;
--grey-3:#737373;
--accent:#002FA7;
--accent-rgb:0,47,167;
--accent-on:#ffffff;
--accent-bright:#5B7BFF;Lemon Yellow
Best for youth, sport, retail, consumer energy, and retro themes.
--paper:#fafaf8;
--paper-rgb:250,250,248;
--ink:#0a0a0a;
--ink-rgb:10,10,10;
--grey-1:#f0f0ee;
--grey-2:#d4d4d2;
--grey-3:#737373;
--accent:#FFD500;
--accent-rgb:255,213,0;
--accent-on:#0a0a0a;
--accent-bright:#FFE866;Lemon Green
Best for sustainability, health, new technology, and future-facing brands.
--paper:#fafaf8;
--paper-rgb:250,250,248;
--ink:#0a0a0a;
--ink-rgb:10,10,10;
--grey-1:#f0f0ee;
--grey-2:#d4d4d2;
--grey-3:#737373;
--accent:#C5E803;
--accent-rgb:197,232,3;
--accent-on:#0a0a0a;
--accent-bright:#DBFF2F;Safety Orange
Best for industrial topics, alerts, motorsport, launches, and decision points.
--paper:#fafaf8;
--paper-rgb:250,250,248;
--ink:#0a0a0a;
--ink-rgb:10,10,10;
--grey-1:#f0f0ee;
--grey-2:#d4d4d2;
--grey-3:#737373;
--accent:#FF6B35;
--accent-rgb:255,107,53;
--accent-on:#ffffff;
--accent-bright:#FF8A5F;Selection Guide
| Use Case | Theme |
|---|---|
| Default, AI, technology, design, product launch | International Klein Blue |
| Youth, sport, retail, energetic consumer work | Lemon Yellow |
| Sustainability, health, future technology | Lemon Green |
| Industrial, warning, urgent, decision-focused topics | Safety Orange |
Do Not
- Do not mix two accent colors.
- Do not change the gray scale variables.
- Do not add gradients, shadows, transparency effects, or rounded accent blocks.
#!/usr/bin/env node
import { readFileSync } from 'node:fs';
const file = process.argv[2];
const allowExperimental = process.argv.includes('--allow-experimental');
if (!file) {
console.error('Usage: node scripts/validate-deck.mjs <index.html> [--allow-experimental]');
process.exit(2);
}
const html = readFileSync(file, 'utf8');
const htmlForSlides = html.replace(/<!--[\s\S]*?-->/g, '');
const errors = [];
const warnings = [];
const allowedLayouts = new Set([
'TIGHTENED-COVER-ASCII',
'TIGHTENED-CLOSING-ASCII',
...Array.from({ length: 22 }, (_, i) => `S${String(i + 1).padStart(2, '0')}`),
]);
const slideRe = /<section\b[^>]*class="[^"]*\bslide\b[^"]*"[^>]*>[\s\S]*?<\/section>/g;
const slides = [...htmlForSlides.matchAll(slideRe)].map((m, idx) => ({ idx: idx + 1, html: m[0], tag: m[0].match(/<section\b[^>]*>/)?.[0] ?? '' }));
if (!slides.length) {
errors.push('No <section class="slide"> pages found.');
}
slides.forEach((slide) => {
const layout = slide.tag.match(/\bdata-layout="([^"]+)"/)?.[1];
if (!layout) {
errors.push(`Slide ${slide.idx}: missing data-layout. Locked layout mode requires S01-S22 or TIGHTENED-COVER-ASCII/TIGHTENED-CLOSING-ASCII.`);
} else if (!allowedLayouts.has(layout)) {
errors.push(`Slide ${slide.idx}: data-layout="${layout}" is not registered in references/layout-lock.md.`);
}
if (!allowExperimental && /\bdata-layout="P2[34]\b|Tightened Image Split|Tightened Evidence Grid|tightened-img-split|tightened-img-grid/.test(slide.html)) {
errors.push(`Slide ${slide.idx}: uses an unregistered experimental image structure. Use S22 or S15/S16 image-grid adaptations instead.`);
}
const isStatement = layout === 'S03' || layout === 'S09' || layout === 'S10' || layout === 'TIGHTENED-COVER-ASCII' || layout === 'TIGHTENED-CLOSING-ASCII';
const topChunk = slide.html.slice(0, 1800);
if (!isStatement && /text-align\s*:\s*center/i.test(topChunk)) {
errors.push(`Slide ${slide.idx}: top title area contains text-align:center. Body titles should stay left aligned.`);
}
if (!isStatement && /align-self\s*:\s*center/i.test(topChunk) && /<h[12]\b/i.test(topChunk)) {
errors.push(`Slide ${slide.idx}: top heading appears vertically/centrally aligned. Use the original left-top title skeleton.`);
}
if (!isStatement && /grid-template-columns\s*:\s*[0-9.]+fr\s+[0-9.]+fr/i.test(topChunk) && /<h[12]\b/i.test(topChunk)) {
warnings.push(`Slide ${slide.idx}: heading inside a custom fr/fr grid. Confirm this is copied from the original Sxx skeleton, not a centered title hack.`);
}
if (/<svg\b[\s\S]*?<text\b/i.test(slide.html)) {
errors.push(`Slide ${slide.idx}: SVG contains visible <text>. Put labels in HTML grid/captions, keep SVG for geometry only.`);
}
const localImages = [...slide.html.matchAll(/<img\b[^>]*src="images\//g)];
localImages.forEach((_, imageIndex) => {
const imgTag = slide.html.slice(_.index, slide.html.indexOf('>', _.index) + 1);
if (!/\bdata-image-slot="/.test(imgTag)) {
errors.push(`Slide ${slide.idx}: local image ${imageIndex + 1} missing data-image-slot. Bind every image to a layout slot such as s22-hero-21x9 or s15-grid-21x9.`);
}
});
const frameImageRe = /<div\b(?=[^>]*\bclass="([^"]*\bframe-img\b[^"]*)")[^>]*>\s*<img\b(?=[^>]*\bdata-image-slot="([^"]+)")[^>]*>/g;
const frameImages = [...slide.html.matchAll(frameImageRe)];
frameImages.forEach((match) => {
const className = match[1];
const slot = match[2];
const frameTag = match[0].match(/^<div\b[^>]*>/)?.[0] ?? '';
if (/^s1[56]-(?:grid|brief)-21x9$/.test(slot)) {
if (/\bfit-contain\b/.test(className)) {
errors.push(`Slide ${slide.idx}: ${slot} uses fit-contain. Regenerated S15/S16 21:9 images should fill the slot with .frame-img.r-21x9.`);
}
if (!/\br-21x9\b/.test(className)) {
errors.push(`Slide ${slide.idx}: ${slot} must use .frame-img.r-21x9 so the image slot controls the visible size.`);
}
if (/height\s*:\s*\d+(?:\.\d+)?vh/i.test(frameTag)) {
errors.push(`Slide ${slide.idx}: ${slot} frame has a fixed vh height. Use aspect-ratio .r-21x9 instead of shrinking long images into a short slot.`);
}
}
});
if (layout === 'S22') {
if (!/data-image-slot="s22-hero-21x9"/.test(slide.html)) {
errors.push(`Slide ${slide.idx}: S22 must use data-image-slot="s22-hero-21x9".`);
}
if (/object-position\s*:\s*top center/i.test(slide.html)) {
errors.push(`Slide ${slide.idx}: S22 photo uses object-position:top center, which commonly crops faces. Use center 35% or center center.`);
}
}
});
if (warnings.length) {
console.warn('Warnings:');
for (const warning of warnings) console.warn(`- ${warning}`);
}
if (errors.length) {
console.error('Deck validation failed:');
for (const error of errors) console.error(`- ${error}`);
process.exit(1);
}
console.log(`Deck validation passed: ${slides.length} slide(s).`);