JAYC


document.addEventListener("DOMContentLoaded", function () { const video = document.querySelector("video"); if (!video) return; /* ========================================= VIDEO SETUP ========================================= */ video.pause(); video.autoplay = false; video.removeAttribute("autoplay"); video.muted = true; video.loop = false; /* ========================================= STATE ========================================= */ let progress = 0; let targetTime = 0; let currentTime = 0; let animating = false; let videoComplete = false; let controllingVideo = false; let animationFrame = null; const SPEED = 0.0003; const SMOOTH = 0.1; const TOP_THRESHOLD = 10; const END_SNAP = 0.04; /* ========================================= TOP SCROLLBAR CONTROL ========================================= */ const scrollbarStyle = document.createElement("style"); scrollbarStyle.id = "top-scrollbar-hide"; scrollbarStyle.textContent = ` html.hide-top-scrollbar { scrollbar-width: none !important; -ms-overflow-style: none !important; } html.hide-top-scrollbar::-webkit-scrollbar { display: none !important; } `; document.head.appendChild( scrollbarStyle ); function updateScrollbar() { if (window.scrollY <= TOP_THRESHOLD) { document.documentElement.classList.add( "hide-top-scrollbar" ); } else { document.documentElement.classList.remove( "hide-top-scrollbar" ); } } /* * Check immediately. */ updateScrollbar(); /* * Update whenever the user scrolls. */ window.addEventListener( "scroll", updateScrollbar, { passive: true } ); /* ========================================= SCROLL LOCK ========================================= */ let scrollLocked = false; function lockPageScroll() { if (scrollLocked) return; scrollLocked = true; window.scrollTo(0, 0); document.documentElement.style.overflow = "hidden"; document.body.style.overflow = "hidden"; document.documentElement.style.touchAction = "none"; document.body.style.touchAction = "none"; updateScrollbar(); } function unlockPageScroll() { if (!scrollLocked) return; scrollLocked = false; document.documentElement.style.overflow = ""; document.body.style.overflow = ""; document.documentElement.style.touchAction = ""; document.body.style.touchAction = ""; updateScrollbar(); } /* ========================================= EXTRA SCROLL LOCK PROTECTION ========================================= */ function enforceScrollLock() { if ( scrollLocked && window.scrollY !== 0 ) { window.scrollTo(0, 0); } } window.addEventListener( "scroll", enforceScrollLock, { passive: true } ); /* ========================================= TOP CHECK ========================================= */ function isAtTop() { return window.scrollY <= TOP_THRESHOLD; } /* ========================================= STOP ANIMATION ========================================= */ function stopAnimation() { animating = false; if (animationFrame) { cancelAnimationFrame( animationFrame ); animationFrame = null; } } /* ========================================= FREEZE LAST FRAME ========================================= */ function freezeLastFrame() { if (!video.duration) return; stopAnimation(); progress = 1; videoComplete = true; controllingVideo = false; const finalFrame = Math.max( 0, video.duration - END_SNAP ); currentTime = finalFrame; targetTime = finalFrame; video.pause(); if (video.readyState >= 2) { video.currentTime = finalFrame; } } /* ========================================= VIDEO ANIMATION ========================================= */ function animate() { if (!animating) return; if ( targetTime >= video.duration - END_SNAP ) { freezeLastFrame(); unlockPageScroll(); return; } currentTime += (targetTime - currentTime) * SMOOTH; if (video.readyState >= 2) { video.currentTime = currentTime; } if ( Math.abs( targetTime - currentTime ) < 0.01 ) { currentTime = targetTime; video.currentTime = targetTime; stopAnimation(); if (progress >= 1) { freezeLastFrame(); unlockPageScroll(); } return; } animationFrame = requestAnimationFrame( animate ); } function startAnimation() { if (animating) return; animating = true; animationFrame = requestAnimationFrame( animate ); } /* ========================================= SET VIDEO PROGRESS ========================================= */ function setProgress(value) { progress = Math.max( 0, Math.min(1, value) ); if (video.duration) { targetTime = progress * video.duration; if ( progress >= 1 || targetTime >= video.duration - END_SNAP ) { progress = 1; targetTime = Math.max( 0, video.duration - END_SNAP ); } } startAnimation(); } /* ========================================= START VIDEO CONTROL ========================================= */ function startVideoControl() { controllingVideo = true; videoComplete = false; lockPageScroll(); window.scrollTo(0, 0); updateScrollbar(); } /* ========================================= WHEEL HANDLER ========================================= */ function wheelHandler(e) { /* ===================================== VIDEO FINISHED ===================================== */ if (videoComplete) { if ( e.deltaY < 0 && isAtTop() ) { e.preventDefault(); e.stopPropagation(); startVideoControl(); videoComplete = false; setProgress( progress + e.deltaY * SPEED ); } return; } /* ===================================== VIDEO AT BEGINNING ===================================== */ if ( progress <= 0 && !controllingVideo ) { if ( e.deltaY > 0 && isAtTop() ) { e.preventDefault(); e.stopPropagation(); startVideoControl(); setProgress( progress + e.deltaY * SPEED ); } return; } /* ===================================== VIDEO CURRENTLY BEING SCRUBBED ===================================== */ if (controllingVideo) { e.preventDefault(); e.stopPropagation(); if (window.scrollY !== 0) { window.scrollTo(0, 0); } setProgress( progress + e.deltaY * SPEED ); /* ================================= VIDEO REACHED BEGINNING ================================= */ if (progress <= 0) { progress = 0; targetTime = 0; currentTime = 0; stopAnimation(); video.currentTime = 0; controllingVideo = false; videoComplete = false; window.scrollTo(0, 0); unlockPageScroll(); return; } /* ================================= VIDEO REACHED END ================================= */ if (progress >= 1) { progress = 1; targetTime = Math.max( 0, video.duration - END_SNAP ); startAnimation(); return; } } } /* ========================================= PREVENT AUTOPLAY ========================================= */ video.addEventListener( "play", function () { video.pause(); if (videoComplete) { freezeLastFrame(); } } ); /* ========================================= VIDEO ENDED ========================================= */ video.addEventListener( "ended", function () { progress = 1; freezeLastFrame(); unlockPageScroll(); } ); /* ========================================= SETUP ========================================= */ video.addEventListener( "loadedmetadata", function () { video.pause(); video.currentTime = 0; progress = 0; targetTime = 0; currentTime = 0; updateScrollbar(); window.addEventListener( "wheel", wheelHandler, { passive: false, capture: true } ); } ); /* ========================================= KEYBOARD SCROLL PROTECTION ========================================= */ window.addEventListener( "keydown", function (e) { if (!controllingVideo) return; const scrollKeys = [ "ArrowDown", "ArrowUp", "PageDown", "PageUp", "Home", "End", " ", "Spacebar" ]; if ( scrollKeys.includes(e.key) ) { e.preventDefault(); e.stopPropagation(); } }, { passive: false, capture: true } ); /* ========================================= TOUCH PROTECTION ========================================= */ window.addEventListener( "touchmove", function (e) { if (!controllingVideo) return; e.preventDefault(); }, { passive: false, capture: true } ); }); ```
window.addEventListener("load", function () { const title = document.getElementById("headertext1"); if (!title) return; const TEXT = "jayc"; /* ========================================= SETTINGS ========================================= */ const TRIGGER = 1000; const COLUMN_DURATION = 900; const EXIT_DURATION = 500; /* MATCHES LOGO: MOVE_UP = 80 SHOW_DURATION = 800 */ const RETURN_DISTANCE = 80; const RETURN_DURATION = 800; const SPACING = 45; const COLUMN_SHIFT_X = -80; const COLUMN_MIN_LEFT = 20; const BAR_WIDTH = 110; const BAR_START_OFFSET = 180; const BAR_HORIZONTAL_OFFSET = -20; const EXIT_DISTANCE = 220; /* ========================================= STATE ========================================= */ let progress = 0; let animationFrame = null; let letters = null; let hasTriggered = false; let exiting = false; /* ========================================= FOREGROUND LAYER ========================================= */ const layer = document.createElement("div"); layer.style.cssText = ` position:fixed!important; top:0!important; left:0!important; width:100vw!important; height:100vh!important; pointer-events:none!important; z-index:2147483647!important; overflow:visible!important; `; document.body.appendChild(layer); /* ========================================= BLACK BAR ========================================= */ const blackBar = document.createElement("div"); blackBar.style.cssText = ` position:fixed!important; top:0!important; bottom:0!important; width:${BAR_WIDTH}px!important; background:#000000!important; opacity:0!important; pointer-events:none!important; z-index:0!important; transform:translateX(-50%)!important; will-change:left,opacity!important; `; layer.appendChild(blackBar); /* ========================================= FIND TEXT NODE ========================================= */ function getTextNode() { const walker = document.createTreeWalker( title, NodeFilter.SHOW_TEXT ); let node; while ( node = walker.nextNode() ) { if ( node.textContent.trim() ) { return node; } } return null; } /* ========================================= CREATE LETTERS ========================================= */ function createLetters() { const node = getTextNode(); if (!node) return null; const positions = []; for ( let i = 0; i < TEXT.length; i++ ) { const range = document.createRange(); range.setStart( node, i ); range.setEnd( node, i + 1 ); const rect = range.getBoundingClientRect(); positions.push({ x: rect.left + rect.width / 2, y: rect.top + rect.height / 2, left: rect.left, top: rect.top, width: rect.width, height: rect.height }); } const anchorX = positions[0].x; const anchorY = positions[0].y; const style = window.getComputedStyle( title ); const result = []; for ( let i = 0; i < TEXT.length; i++ ) { const letter = document.createElement( "span" ); letter.textContent = TEXT[i]; letter.style.cssText = ` position:fixed!important; left: ${positions[i].left}px!important; top: ${positions[i].top}px!important; margin:0!important; padding:0!important; font-family: ${style.fontFamily}!important; font-size: ${style.fontSize}!important; font-weight: ${style.fontWeight}!important; font-style: ${style.fontStyle}!important; line-height: ${style.lineHeight}!important; color: ${style.color}!important; white-space: nowrap!important; pointer-events: none!important; visibility: visible!important; opacity: 1!important; display: block!important; will-change: transform, opacity!important; z-index: 1!important; `; layer.appendChild( letter ); const desiredColumnX = anchorX + COLUMN_SHIFT_X; const safeColumnX = Math.max( COLUMN_MIN_LEFT + positions[i].width / 2, desiredColumnX ); result.push({ element: letter, startX: positions[i].x, startY: positions[i].y, columnX: safeColumnX, columnY: anchorY + i * SPACING, columnOffsetX: 0, columnOffsetY: 0 }); } return result; } /* ========================================= RENDER COLUMN ========================================= */ function renderColumn( value ) { if (!letters) return; letters.forEach( function (item) { const x = ( item.columnX - item.startX ) * value; const y = ( item.columnY - item.startY ) * value; item.element.style.transform = `translate3d(${x}px,${y}px,0)`; if ( value === 1 ) { item.columnOffsetX = x; item.columnOffsetY = y; } } ); } /* ========================================= BAR POSITION ========================================= */ function getFinalBarX() { if ( !letters || !letters.length ) { return 0; } const first = letters[0]; return ( first.startX + first.columnOffsetX + BAR_HORIZONTAL_OFFSET ); } /* ========================================= SCROLL DOWN ========================================= */ function animateDown() { if (exiting) return; if (!letters) { letters = createLetters(); } if (!letters) return; blackBar.style.opacity = "0"; renderColumn(0); renderColumn(1); const finalBarX = getFinalBarX(); renderColumn(0); const startBarX = finalBarX - BAR_START_OFFSET; blackBar.style.left = `${startBarX}px`; blackBar.style.opacity = "0"; title.style.transition = "none"; title.style.transform = "translateY(0px)"; title.style.visibility = "hidden"; const start = progress; const startTime = performance.now(); function frame(time) { const raw = Math.min( ( time - startTime ) / COLUMN_DURATION, 1 ); const eased = 1 - Math.pow( 1 - raw, 3 ); progress = start + ( 1 - start ) * eased; renderColumn( progress ); const barX = startBarX + ( finalBarX - startBarX ) * eased; blackBar.style.left = `${barX}px`; blackBar.style.opacity = String( eased ); if ( raw < 1 ) { animationFrame = requestAnimationFrame( frame ); } else { progress = 1; animationFrame = null; renderColumn(1); blackBar.style.left = `${finalBarX}px`; blackBar.style.opacity = "1"; } } animationFrame = requestAnimationFrame( frame ); } /* ========================================= SCROLL BACK UP ========================================= */ function animateUp() { if ( !letters || exiting ) { return; } exiting = true; if ( animationFrame ) { cancelAnimationFrame( animationFrame ); animationFrame = null; } renderColumn(1); const startingBarX = getFinalBarX(); blackBar.style.left = `${startingBarX}px`; blackBar.style.opacity = "1"; /* ========================================= START JAYC RETURN IMMEDIATELY This now starts at the exact same trigger point as jclogo. ========================================= */ title.style.transition = "none"; title.style.transform = `translateY(-${RETURN_DISTANCE}px)`; title.style.visibility = "visible"; title.style.opacity = "1"; /* Force browser to register the upper position. */ void title.offsetHeight; /* MATCH LOGO SLIDE DOWN */ title.style.transition = `transform ${RETURN_DURATION}ms cubic-bezier(.4,0,.2,1)`; title.style.transform = "translateY(0px)"; /* ========================================= COLUMN + BAR EXIT ========================================= */ const startTime = performance.now(); function frame(time) { const raw = Math.min( ( time - startTime ) / EXIT_DURATION, 1 ); const eased = 1 - Math.pow( 1 - raw, 3 ); const moveLeft = EXIT_DISTANCE * eased; letters.forEach( function (item) { const x = item.columnOffsetX - moveLeft; const y = item.columnOffsetY; item.element.style.transform = `translate3d(${x}px,${y}px,0)`; item.element.style.opacity = String( 1 - eased ); } ); blackBar.style.left = `${startingBarX - moveLeft}px`; blackBar.style.opacity = String( 1 - eased ); if ( raw < 1 ) { requestAnimationFrame( frame ); } else { letters.forEach( function (item) { item.element.remove(); } ); letters = null; progress = 0; blackBar.style.opacity = "0"; exiting = false; } } requestAnimationFrame( frame ); } /* ========================================= SCROLL DETECTION ========================================= */ window.addEventListener( "scroll", function () { const scroll = window.scrollY || window.pageYOffset; /* DOWN */ if ( scroll >= TRIGGER && !hasTriggered ) { hasTriggered = true; animateDown(); } /* UP */ else if ( scroll < TRIGGER && hasTriggered ) { hasTriggered = false; animateUp(); } }, { passive:true } ); });
window.addEventListener("load", function () { const topbar = document.getElementById("topbar"); if (!topbar) return; /* ========================================= SETTINGS ========================================= */ const TRIGGER = 1000; const SHOW_DURATION = 400; const HIDE_DURATION = 500; const VISIBLE_TOP = -20; const HIDDEN_TOP = -120; /* ========================================= CREATE BLACK BOX ========================================= */ const oldBox = document.getElementById( "scroll-black-box" ); if (oldBox) { oldBox.remove(); } const blackBox = document.createElement("div"); blackBox.id = "scroll-black-box"; blackBox.style.cssText = ` position:fixed; top:${VISIBLE_TOP}px; left:0; width:100vw; height:100px; background:#000000; pointer-events:none; opacity:1; z-index:9999998; will-change:top; `; topbar.parentNode.insertBefore( blackBox, topbar ); topbar.style.zIndex = "9999999"; let hidden = false; let hiding = false; let showing = false; let animationFrame = null; /* ========================================= GET CURRENT POSITION ========================================= */ function getCurrentTop() { const value = parseFloat( blackBox.style.top ); return Number.isFinite(value) ? value : VISIBLE_TOP; } /* ========================================= SHOW ========================================= */ function showBox() { if ( showing && !hiding ) return; if (animationFrame) { cancelAnimationFrame( animationFrame ); animationFrame = null; } hiding = false; showing = true; blackBox.style.opacity = "1"; const startTop = getCurrentTop(); const startTime = performance.now(); function frame(time) { const progress = Math.min( (time - startTime) / SHOW_DURATION, 1 ); const eased = 1 - Math.pow( 1 - progress, 3 ); const top = startTop + ( VISIBLE_TOP - startTop ) * eased; blackBox.style.top = top + "px"; if (progress < 1) { animationFrame = requestAnimationFrame( frame ); } else { blackBox.style.top = VISIBLE_TOP + "px"; animationFrame = null; hidden = false; hiding = false; showing = false; } } animationFrame = requestAnimationFrame( frame ); } /* ========================================= HIDE ========================================= */ function hideBox() { if ( hiding && !showing ) return; if (animationFrame) { cancelAnimationFrame( animationFrame ); animationFrame = null; } showing = false; hiding = true; const startTop = getCurrentTop(); const startTime = performance.now(); function frame(time) { const progress = Math.min( (time - startTime) / HIDE_DURATION, 1 ); const eased = 1 - Math.pow( 1 - progress, 3 ); const top = startTop + ( HIDDEN_TOP - startTop ) * eased; blackBox.style.top = top + "px"; /* NO FADE */ blackBox.style.opacity = "1"; if (progress < 1) { animationFrame = requestAnimationFrame( frame ); } else { blackBox.style.top = HIDDEN_TOP + "px"; animationFrame = null; hidden = true; hiding = false; showing = false; } } animationFrame = requestAnimationFrame( frame ); } /* ========================================= SCROLL ========================================= */ function update() { const scroll = window.scrollY || window.pageYOffset; /* ABOVE 1000 MOVE UP IMMEDIATELY */ if ( scroll >= TRIGGER ) { hideBox(); } /* BELOW 1000 COME BACK IMMEDIATELY */ else { showBox(); } } window.addEventListener( "scroll", update, { passive:true } ); update(); });
window.addEventListener("load", function () { const logo = document.getElementById("jclogo"); if (!logo) return; const TRIGGER = 1000; const MOVE_UP = 80; const HIDE_DURATION = 300; const SHOW_DURATION = 800; let hideTimer = null; let state = null; /* ========================================= KILL CARRD FADE EFFECTS ========================================= */ function removeFade() { logo.style.setProperty( "opacity", "1", "important" ); logo.style.setProperty( "filter", "none", "important" ); logo.style.setProperty( "-webkit-filter", "none", "important" ); logo.style.setProperty( "animation", "none", "important" ); const children = logo.querySelectorAll("*"); children.forEach(function (el) { el.style.setProperty( "opacity", "1", "important" ); el.style.setProperty( "filter", "none", "important" ); el.style.setProperty( "-webkit-filter", "none", "important" ); el.style.setProperty( "transition", "none", "important" ); el.style.setProperty( "animation", "none", "important" ); }); } /* ========================================= GET CURRENT Y POSITION ========================================= */ function getCurrentY() { const transform = window.getComputedStyle( logo ).transform; if ( !transform || transform === "none" ) { return 0; } try { const matrix = new DOMMatrixReadOnly( transform ); return matrix.m42; } catch (e) { return 0; } } /* ========================================= FREEZE AT CURRENT POSITION ========================================= */ function freezePosition() { const currentY = getCurrentY(); logo.style.setProperty( "transition", "none", "important" ); logo.style.setProperty( "transform", `translateY(${currentY}px)`, "important" ); void logo.offsetHeight; return currentY; } /* ========================================= INITIAL STATE NO ANIMATION ========================================= */ removeFade(); const initialScroll = window.scrollY || window.pageYOffset; logo.style.setProperty( "transition", "none", "important" ); if ( initialScroll >= TRIGGER ) { state = "hidden"; logo.style.setProperty( "transform", `translateY(-${MOVE_UP}px)`, "important" ); logo.style.setProperty( "visibility", "hidden", "important" ); } else { state = "visible"; logo.style.setProperty( "transform", "translateY(0px)", "important" ); logo.style.setProperty( "visibility", "visible", "important" ); } /* ========================================= SLIDE UP ========================================= */ function hideLogo() { if ( state === "hidden" || state === "hiding" ) { return; } clearTimeout( hideTimer ); removeFade(); /* If we're currently sliding down, capture the exact current position instead of jumping. */ const currentY = freezePosition(); state = "hiding"; logo.style.setProperty( "visibility", "visible", "important" ); /* Calculate duration based on how much distance is actually left. */ const distanceLeft = Math.abs( currentY + MOVE_UP ); const duration = Math.max( 50, HIDE_DURATION * ( distanceLeft / MOVE_UP ) ); logo.style.setProperty( "transition", `transform ${duration}ms cubic-bezier(.4,0,.2,1)`, "important" ); requestAnimationFrame( function () { logo.style.setProperty( "transform", `translateY(-${MOVE_UP}px)`, "important" ); } ); hideTimer = setTimeout( function () { const scroll = window.scrollY || window.pageYOffset; if ( scroll >= TRIGGER ) { logo.style.setProperty( "visibility", "hidden", "important" ); state = "hidden"; } }, duration + 20 ); } /* ========================================= SLIDE DOWN ========================================= */ function showLogo() { if ( state === "visible" || state === "showing" ) { return; } clearTimeout( hideTimer ); removeFade(); /* If we're currently sliding upward, capture the exact current position. This is the part that prevents the logo from instantly appearing. */ let currentY = freezePosition(); /* If it was completely hidden, start at the normal upper position. */ if ( state === "hidden" ) { currentY = -MOVE_UP; logo.style.setProperty( "transform", `translateY(-${MOVE_UP}px)`, "important" ); } state = "showing"; logo.style.setProperty( "visibility", "visible", "important" ); void logo.offsetHeight; /* Calculate the return duration based on the remaining distance. */ const distanceLeft = Math.abs( currentY ); const duration = Math.max( 50, SHOW_DURATION * ( distanceLeft / MOVE_UP ) ); logo.style.setProperty( "transition", `transform ${duration}ms cubic-bezier(.4,0,.2,1)`, "important" ); requestAnimationFrame( function () { logo.style.setProperty( "transform", "translateY(0px)", "important" ); } ); /* Don't mark it visible until the animation has actually completed. */ setTimeout( function () { const scroll = window.scrollY || window.pageYOffset; if ( scroll < TRIGGER && state === "showing" ) { state = "visible"; logo.style.setProperty( "transition", "none", "important" ); logo.style.setProperty( "transform", "translateY(0px)", "important" ); } }, duration + 20 ); } /* ========================================= SCROLL ========================================= */ function update() { removeFade(); const scroll = window.scrollY || window.pageYOffset; if ( scroll >= TRIGGER ) { hideLogo(); } else { showLogo(); } } window.addEventListener( "scroll", update, { passive:true } ); });

Consequat leo tellus


Dignissim suscipit leo

Dignissim suscipit leo

Dignissim suscipit leo

Tempor mauris ligula sapien ornare cubilia pretium massa proto. Imperdiet arcu vestibulum ante egestas vel cursus dis sodales. Iaculis lacus euismod montes mattis ullamcorper rhoncus eleifend vis, ligula phasellus, faucibus pretium.

Text

Text