diff --git a/layouts/_partials/home.html b/layouts/_partials/home.html index c8505e0..6a4512f 100644 --- a/layouts/_partials/home.html +++ b/layouts/_partials/home.html @@ -711,7 +711,7 @@ } - + @@ -803,6 +803,6 @@ - + diff --git a/layouts/_partials/homepage-demo.html b/layouts/_partials/homepage-demo.html index 6efdd15..4a0bd5a 100644 --- a/layouts/_partials/homepage-demo.html +++ b/layouts/_partials/homepage-demo.html @@ -1,4 +1,4 @@ -
+

Telar

diff --git a/layouts/_partials/landing-body.html b/layouts/_partials/landing-body.html index 14a77c0..69b0ff4 100644 --- a/layouts/_partials/landing-body.html +++ b/layouts/_partials/landing-body.html @@ -39,16 +39,20 @@

Telar

-
-
-

What is Telar?¿Qué es Telar?

-

Telar (Spanish for "loom") weaves together images, video, audio, narrative text, and layered contextual information into interactive visual narrative exhibitions. It follows minimal computing principles: plain text authoring, static generation, and sustainable hosting.

-

Telar entreteje imágenes, video, audio, texto narrativo e información contextual en exhibiciones narrativas visuales e interactivas. Sigue los principios de computación mínima: autoría en texto plano, generación estática y alojamiento sostenible.

+
+
+
+
+

What is Telar?¿Qué es Telar?

+

Telar (Spanish for "loom") weaves together images, video, audio, narrative text, and layered contextual information into interactive visual narrative exhibitions. It follows minimal computing principles: plain text authoring, static generation, and sustainable hosting.

+

Telar entreteje imágenes, video, audio, texto narrativo e información contextual en exhibiciones narrativas visuales e interactivas. Sigue los principios de computación mínima: autoría en texto plano, generación estática y alojamiento sostenible.

+
+ {{ partial "homepage-demo.html" . }} +
+
-{{ partial "homepage-demo.html" . }} -
diff --git a/static/assets/homepage-demo/README.md b/static/assets/homepage-demo/README.md index 33f796f..0cb3d70 100644 --- a/static/assets/homepage-demo/README.md +++ b/static/assets/homepage-demo/README.md @@ -1,6 +1,9 @@ # Telar homepage video The homepage uses normal document flow and the supplied Spanish/English Vimeo -embeds. The definition and viewport-fitted film occupy separate scroll steps. There is no native scroll-film renderer or local MP4 fetch. +embeds. The definition and viewport-fitted film share a sticky stage: the next scroll +step fades out the definition and reveals the video in place; the previous step +restores the definition. Hidden layers are inert and hidden from assistive +technology, and the video pauses while the definition is showing. There is no native scroll-film renderer or local MP4 fetch. Only the active-language poster is loaded initially. IntersectionObserver creates the iframe and loads Vimeo's SDK as the film enters view. Playback is muted and diff --git a/static/assets/homepage-demo/homepage-demo.css b/static/assets/homepage-demo/homepage-demo.css index 3c6bf0c..5bd7c87 100644 --- a/static/assets/homepage-demo/homepage-demo.css +++ b/static/assets/homepage-demo/homepage-demo.css @@ -20,7 +20,18 @@ a:focus-visible,button:focus-visible,iframe:focus-visible{outline:3px solid var( .hero__utility a{color:var(--cream);font-size:15px;text-decoration:underline;text-underline-offset:4px;opacity:.9} .hero__utility a:hover{opacity:1} .hero__scroll{bottom:20px} -.telar-about-section{background:var(--demo-background);min-height:100svh;padding:60px 24px} +.telar-about-section{display:block;background:var(--demo-background);padding:0} +.telar-intro-copy{padding:60px 24px} +.telar-about-section.is-enhanced{height:200svh;min-height:200svh;padding:0} +.is-enhanced .telar-intro-stage{position:sticky;top:0;height:100svh} +.is-enhanced .telar-intro-copy,.is-enhanced .telar-demo-section{position:absolute;inset:0;transition:opacity 250ms ease;} +.is-enhanced:not(.intro-ready) .telar-intro-copy,.is-enhanced:not(.intro-ready) .telar-demo-section{transition:none} +.is-enhanced .telar-intro-copy{display:flex;align-items:center;z-index:2} +.is-enhanced .telar-demo-section{min-height:0;opacity:0;pointer-events:none;z-index:1} +.is-enhanced.is-video .telar-intro-copy{opacity:0;pointer-events:none;z-index:1} +.is-enhanced.is-video .telar-demo-section{opacity:1;pointer-events:auto;z-index:2} +.telar-intro-demo-stop{position:absolute;width:1px;height:1px;pointer-events:none} +.is-enhanced .telar-intro-demo-stop{top:50%;left:0} .telar-demo-section{background:var(--demo-background);min-height:100svh;padding:24px} /* Fit the complete film inside one viewport, including on short desktop windows. */ .telar-demo-layout{width:100%;max-width:min(1600px,calc((100svh - 48px) * 16 / 9));margin:auto} @@ -55,7 +66,7 @@ a:focus-visible,button:focus-visible,iframe:focus-visible{outline:3px solid var( .landing-footer a:hover{color:var(--gold)} @media(max-width:900px){ .telar-demo-section{min-height:auto} - .telar-about-section{min-height:auto;padding:64px 24px} + .telar-intro-copy{padding:64px 24px} .telar-demo-media{width:100%} } @media(max-width:600px){ @@ -63,11 +74,12 @@ a:focus-visible,button:focus-visible,iframe:focus-visible{outline:3px solid var( .hero__lang-toggle button{min-height:44px} .hero__utility{gap:4px 18px} .telar-demo-section{padding:24px 16px} - .telar-about-section{padding:48px 20px} + .telar-intro-copy{padding:48px 20px} .cta-section{padding:56px 20px} .features__grid{gap:16px} } @media(prefers-reduced-motion:reduce){ .hero__scroll{animation:none} + .is-enhanced .telar-intro-copy,.is-enhanced .telar-demo-section{transition:none} .fade-in{opacity:1;transform:none;transition:none} } diff --git a/static/assets/homepage-demo/homepage-demo.js b/static/assets/homepage-demo/homepage-demo.js index 1cd076e..8fd06d8 100644 --- a/static/assets/homepage-demo/homepage-demo.js +++ b/static/assets/homepage-demo/homepage-demo.js @@ -111,11 +111,15 @@ window.addEventListener('resize',manualInput);window.addEventListener('resize',()=>lenis.resize()); motion.addEventListener('change',preference);small.addEventListener('change',preference); + const intro=document.querySelector('[data-telar-intro]'); + const introStage=intro?.querySelector('.telar-intro-stage'),introCopy=intro?.querySelector('[data-intro-copy]'); + intro?.classList.add('is-enhanced'); const root=document.querySelector('[data-telar-demo]'),frame=root.querySelector('[data-demo-frame]'); const embed=root.querySelector('[data-demo-embed]'),poster=root.querySelector('[data-demo-poster]'); const error=root.querySelector('[data-demo-error]'),errorText=root.querySelector('[data-demo-error-text]'),errorLink=root.querySelector('[data-demo-error-link]'); const transcript=root.querySelector('[data-demo-transcript]'); window.addEventListener('scroll',()=>{ + updateIntro(); // Cross-origin iframe wheel events do not bubble. Observe their native movement // and hand the gesture to the same step controller, keeping Vimeo clickable. if(!embed.querySelector('iframe')?.matches(':hover')){ @@ -133,6 +137,18 @@ },{passive:true}); const languages=JSON.parse(document.getElementById('telar-demo-config').textContent); let sdkPromise=null,player=null,iframe=null,ready=false,playing=false,inView=false,userPaused=false,pauseExpected=false,generation=0,timeout=0,data; + function updateIntro(){ + if(!intro)return; + const showVideo=(scrollY-layoutTop(intro))/Math.max(1,introStage.offsetHeight)>=.15; + const mode=showVideo?'video':'copy';if(intro.dataset.introState===mode)return; + intro.dataset.introState=mode;intro.classList.toggle('is-video',showVideo); + introCopy.inert=showVideo;introCopy.setAttribute('aria-hidden',String(showVideo)); + root.inert=!showVideo;root.setAttribute('aria-hidden',String(!showVideo)); + if(showVideo&&introCopy.contains(document.activeElement))focusTarget(root.querySelector('h2')); + else if(!showVideo&&root.contains(document.activeElement))focusTarget(introCopy.querySelector('h2')); + syncPlayback(); + } + function videoRevealed(){return !intro||intro.dataset.introState==='video'} function sdk(){ if(window.Vimeo?.Player)return Promise.resolve(window.Vimeo); if(sdkPromise)return sdkPromise; @@ -152,7 +168,7 @@ } function syncPlayback(){ if(!ready||!player)return; - if(!inView||document.hidden){suspend();return} + if(!inView||!videoRevealed()||document.hidden){suspend();return} if(!motion.matches&&!userPaused)player.play().catch(()=>{root.dataset.videoState='paused'}); } function loadPlayer(){ @@ -170,7 +186,7 @@ current.on('play',()=>{ if(token!==generation)return; playing=true;userPaused=false;root.dataset.videoState='playing'; - if(!inView||document.hidden)suspend(); + if(!inView||!videoRevealed()||document.hidden)suspend(); }); current.on('pause',()=>{ if(token!==generation)return; @@ -209,7 +225,20 @@ syncPlayback(); },{threshold:[0,.1]}); document.addEventListener('visibilitychange',syncPlayback); - document.addEventListener('telar:languagechange',language);language();visible.observe(frame); + document.addEventListener('telar:languagechange',language);language();updateIntro();visible.observe(frame); + function restoreIntroLink(){ + if(!intro||!['#about','#demo'].includes(location.hash))return; + stops();const position=layoutTop(document.querySelector(location.hash)); + document.documentElement.classList.add('is-stepping'); + lenis.scrollTo(position,{immediate:true});travel.reset(position);pendingTarget=null; + document.documentElement.classList.remove('is-stepping');updateIntro(); + } + let introInput=false; + for(const type of ['wheel','keydown','touchstart','pointerdown'])window.addEventListener(type,()=>{introInput=true},{once:true,passive:true}); + requestAnimationFrame(()=>{intro?.classList.add('intro-ready');restoreIntroLink()}); + window.addEventListener('hashchange',restoreIntroLink); + window.addEventListener('load',()=>{if(!introInput)restoreIntroLink()}); + window.addEventListener('resize',updateIntro); window.addEventListener('pagehide',event=>{ suspend();if(event.persisted)return; clearTimeout(timeout);visible.disconnect();cancelAnimationFrame(raf);