timeline feaky

This commit is contained in:
deploy
2026-06-04 23:35:09 +00:00
parent 6ceb800855
commit de42c30bab
3 changed files with 265 additions and 40 deletions
+1 -1
View File
@@ -334,7 +334,7 @@ async def _refresh_presence():
await bot.change_presence( await bot.change_presence(
activity=discord.Activity( activity=discord.Activity(
type=discord.ActivityType.playing, type=discord.ActivityType.playing,
name=f"Playing SRE in {GUILD_TOTAL} servers!" name=f"Playing SQB in {GUILD_TOTAL} servers!"
) )
) )
+7 -1
View File
@@ -900,8 +900,14 @@ app.get('/docs', (req, res) => {
}); });
app.get('/timeline', (req, res) => { app.get('/timeline', (req, res) => {
let serverCount = 0;
try {
const report = fs.readFileSync(path.join(STORAGE_ROOT, 'SREBOT_GUILDS.txt'), 'utf8').trim();
serverCount = report ? report.split('\n').length : 0;
} catch { /* file may not exist yet */ }
res.render('timeline', { res.render('timeline', {
botName: 'Toothless SQB Bot' botName: 'Toothless SQB Bot',
serverCount
}); });
}); });
+257 -38
View File
@@ -3,8 +3,11 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Timeline - <%= botName %></title> <title>SREBOT History</title>
<meta name="description" content="The history of <%= botName %>, from a Discord side project to a War Thunder Squadron Battles companion used across the community."> <meta name="description" content="The history of SREBOT, starting from an idea to being the standard for SQB in War Thunder.">
<meta property="og:title" content="SREBOT History">
<meta property="og:description" content="The history of SREBOT, starting from an idea to being the standard for SQB in War Thunder.">
<meta property="og:type" content="website">
<meta name="theme-color" content="#90EE90"> <meta name="theme-color" content="#90EE90">
<link rel="icon" type="image/png" href="/images/transparent_toothlessssss.png"> <link rel="icon" type="image/png" href="/images/transparent_toothlessssss.png">
@@ -80,6 +83,22 @@
fill: #F5F5DC; fill: #F5F5DC;
filter: drop-shadow(0 0 8px rgba(144, 238, 144, 0.7)); filter: drop-shadow(0 0 8px rgba(144, 238, 144, 0.7));
} }
.timeline-line .end-marker {
fill: #1b1b1b;
stroke: rgba(144, 238, 144, 0.35);
stroke-width: 1.5;
}
.timeline-card-footer {
margin-top: 1rem;
padding-top: 0.75rem;
border-top: 1px solid rgba(245, 245, 220, 0.07);
display: flex;
align-items: center;
gap: 0.45rem;
color: rgba(144, 238, 144, 0.65);
font-size: 0.75rem;
letter-spacing: 0.06em;
}
/* The grid of milestone nodes. Default = single column (mobile). */ /* The grid of milestone nodes. Default = single column (mobile). */
.timeline-grid { .timeline-grid {
@@ -94,18 +113,22 @@
.timeline-grid { .timeline-grid {
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
gap: 6rem 2.5rem; gap: 6rem 2.5rem;
align-items: start;
} }
/* The line snakes 3 by 3: row 1 left to right, row 2 right to left, /* The line snakes 3 by 3: row 1 left to right, row 2 right to left,
row 3 left to right, so the connector never crosses itself. */ row 3 left to right, so the connector never crosses itself. */
.timeline-node:nth-child(1) { grid-area: 1 / 1; } .timeline-node:nth-child(1) { grid-area: 1 / 1; }
.timeline-node:nth-child(2) { grid-area: 1 / 2; } .timeline-node:nth-child(2) { grid-area: 1 / 2; }
.timeline-node:nth-child(3) { grid-area: 1 / 3; } .timeline-node:nth-child(3) { grid-area: 1 / 3; }
.timeline-node:nth-child(4) { grid-area: 2 / 3; } .timeline-node:nth-child(4) { grid-area: 2 / 3; }
.timeline-node:nth-child(5) { grid-area: 2 / 2; } .timeline-node:nth-child(5) { grid-area: 2 / 2; }
.timeline-node:nth-child(6) { grid-area: 2 / 1; } .timeline-node:nth-child(6) { grid-area: 2 / 1; }
.timeline-node:nth-child(7) { grid-area: 3 / 1; } .timeline-node:nth-child(7) { grid-area: 3 / 1; }
.timeline-node:nth-child(8) { grid-area: 3 / 2; } .timeline-node:nth-child(8) { grid-area: 3 / 2; }
.timeline-node:nth-child(9) { grid-area: 3 / 3; } .timeline-node:nth-child(9) { grid-area: 3 / 3; }
.timeline-node:nth-child(10) { grid-area: 4 / 3; }
.timeline-node:nth-child(11) { grid-area: 4 / 2; }
.timeline-node:nth-child(12) { grid-area: 4 / 1; }
} }
.timeline-card { .timeline-card {
@@ -163,9 +186,49 @@
/* Reveal animation: node is always opaque (solid background blocks the SVG /* Reveal animation: node is always opaque (solid background blocks the SVG
line); only the inner card fades in. This prevents the line from being line); only the inner card fades in. This prevents the line from being
visible through the semi-transparent card during the fade-in. */ visible through the semi-transparent card during the fade-in. */
#scroll-hint {
position: fixed;
bottom: 3.5rem;
left: 50%;
transform: translateX(-50%);
z-index: 50;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.6rem;
color: rgba(245, 245, 220, 0.4);
font-size: 0.68rem;
letter-spacing: 0.22em;
text-transform: uppercase;
pointer-events: none;
transition: opacity 0.5s ease;
white-space: nowrap;
}
.hint-line {
width: 1px;
height: 52px;
background: rgba(245, 245, 220, 0.12);
position: relative;
overflow: hidden;
}
.hint-line::after {
content: '';
position: absolute;
left: 0;
width: 100%;
height: 45%;
background: linear-gradient(to bottom, transparent, #90EE90, transparent);
animation: hintScroll 1.5s ease-in-out infinite;
}
@keyframes hintScroll {
0% { top: -45%; }
100% { top: 100%; }
}
.timeline-node { .timeline-node {
position: relative; position: relative;
z-index: 2; z-index: 2;
border-radius: 1rem;
/* background is set dynamically in JS only when a card starts /* background is set dynamically in JS only when a card starts
revealing, so unrevealed cards never block the SVG track line */ revealing, so unrevealed cards never block the SVG track line */
} }
@@ -192,8 +255,7 @@
<p class="text-muted text-sm font-semibold tracking-[0.25em] uppercase mb-4">Our Story</p> <p class="text-muted text-sm font-semibold tracking-[0.25em] uppercase mb-4">Our Story</p>
<h1 class="text-4xl lg:text-6xl font-extrabold mb-5 gradient-text">The Timeline</h1> <h1 class="text-4xl lg:text-6xl font-extrabold mb-5 gradient-text">The Timeline</h1>
<p class="text-lg text-white/70 max-w-2xl mx-auto"> <p class="text-lg text-white/70 max-w-2xl mx-auto">
Our history, the milestones we passed along the way, and the giants whose The history of SREBOT, starting from an idea to being the standard for SQB in War Thunder.
shoulders helped us climb higher.
</p> </p>
</div> </div>
</section> </section>
@@ -212,6 +274,7 @@
</defs> </defs>
<path class="track" id="timelineTrack" d=""></path> <path class="track" id="timelineTrack" d=""></path>
<path class="progress" id="timelineProgress" d=""></path> <path class="progress" id="timelineProgress" d=""></path>
<circle class="end-marker" id="timelineEndMarker" r="5" cx="0" cy="0"></circle>
<circle class="comet" id="timelineComet" r="6" cx="0" cy="0" style="opacity:0"></circle> <circle class="comet" id="timelineComet" r="6" cx="0" cy="0" style="opacity:0"></circle>
</svg> </svg>
@@ -236,6 +299,9 @@
within a week, with match data still entered by hand. Within weeks, the prototype within a week, with match data still entered by hand. Within weeks, the prototype
is already being shared with other servers. is already being shared with other servers.
</p> </p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>2 Servers</span>
</div>
</div> </div>
</div> </div>
</article> </article>
@@ -253,6 +319,30 @@
The project outgrows its original name. SNLK SQB BOT becomes The project outgrows its original name. SNLK SQB BOT becomes
<strong class="text-accent">SREBOT</strong>, the identity it still carries today. <strong class="text-accent">SREBOT</strong>, the identity it still carries today.
</p> </p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>4 Servers</span>
</div>
</div>
</div>
</article>
<article class="timeline-node">
<div class="timeline-card">
<div class="timeline-marker"><i class="fas fa-users"></i></div>
<div class="pt-3">
<div class="flex items-center justify-between mb-2">
<span class="timeline-index">03 · Alliance</span>
<span class="timeline-date">January 2025</span>
</div>
<h3 class="timeline-title mb-3">Lux_ and Our Contributions to Each Other</h3>
<p class="timeline-desc">
Lux_ was working on his own bot at the time. We traded knowledge on War Thunder's
APIs and community management, back when neither of us knew how to read a winner
from a replay. His bot later became Spectra, and the cooperation never stopped.
</p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>8 Servers</span>
</div>
</div> </div>
</div> </div>
</article> </article>
@@ -262,15 +352,18 @@
<div class="timeline-marker"><i class="fas fa-file-code"></i></div> <div class="timeline-marker"><i class="fas fa-file-code"></i></div>
<div class="pt-3"> <div class="pt-3">
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<span class="timeline-index">03 · Parser</span> <span class="timeline-index">04 · Parser</span>
<span class="timeline-date">January 2025</span> <span class="timeline-date">February 2025</span>
</div> </div>
<h3 class="timeline-title mb-3">Frovy Opens the Door</h3> <h3 class="timeline-title mb-3">Frovy Opens the Door</h3>
<p class="timeline-desc"> <p class="timeline-desc">
Frovy shows us the first parser and gives SREBOT a real path toward automatic Frovy shows us the first parser and gives SREBOT a real path toward automatic
scoreboards. He had also figured out how to request clandata and receive scoreboards. He had also figured out how to request data from the game and receive
immediate point updates, even if he kept the method from us for months. immediate point updates, even if he kept the method from us for months. :)
</p> </p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>15 Servers</span>
</div>
</div> </div>
</div> </div>
</article> </article>
@@ -280,15 +373,18 @@
<div class="timeline-marker"><i class="fas fa-robot"></i></div> <div class="timeline-marker"><i class="fas fa-robot"></i></div>
<div class="pt-3"> <div class="pt-3">
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<span class="timeline-index">04 · Logs</span> <span class="timeline-index">05 · Logs</span>
<span class="timeline-date">March 13, 2025</span> <span class="timeline-date">March 2025</span>
</div> </div>
<h3 class="timeline-title mb-3">Dagor &amp; The First Logs</h3> <h3 class="timeline-title mb-3">LivingTheDagor and the New Parser</h3>
<p class="timeline-desc"> <p class="timeline-desc">
Dagor is introduced and the second parser is integrated, a much more robust one Dagor is introduced and the second parser is integrated, a much more robust one
that SREBOT still uses today. The logging pipeline matures around the parser work, that SREBOT still uses today. The logging pipeline matures around the parser work,
making scoreboards more informative. making scoreboards more informative.
</p> </p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>20 Servers</span>
</div>
</div> </div>
</div> </div>
</article> </article>
@@ -298,14 +394,17 @@
<div class="timeline-marker"><i class="fas fa-fire"></i></div> <div class="timeline-marker"><i class="fas fa-fire"></i></div>
<div class="pt-3"> <div class="pt-3">
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<span class="timeline-index">05 · Momentum</span> <span class="timeline-index">06 · Momentum</span>
<span class="timeline-date">July 2025</span> <span class="timeline-date">July 2025</span>
</div> </div>
<h3 class="timeline-title mb-3">Word Gets Around</h3> <h3 class="timeline-title mb-3">Word Gets Around</h3>
<p class="timeline-desc"> <p class="timeline-desc">
Squadrons start to take notice. The bot picks up real momentum and grows Squadrons start to take notice. The bot picks up momentum and grows
in popularity as more communities bring it into their servers. in popularity as more communities bring it into their servers.
</p> </p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>60 Servers</span>
</div>
</div> </div>
</div> </div>
</article> </article>
@@ -315,15 +414,19 @@
<div class="timeline-marker"><i class="fas fa-laptop-code"></i></div> <div class="timeline-marker"><i class="fas fa-laptop-code"></i></div>
<div class="pt-3"> <div class="pt-3">
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<span class="timeline-index">06 · Website</span> <span class="timeline-index">07 · Website</span>
<span class="timeline-date">August 2025</span> <span class="timeline-date">August 2025</span>
</div> </div>
<h3 class="timeline-title mb-3">The Site Goes Live</h3> <h3 class="timeline-title mb-3">Clippi Builds the Website</h3>
<p class="timeline-desc"> <p class="timeline-desc">
Friendly competition with the Boris bot pushes the developers to raise Clippi (Sophie) joins, mostly fueled by her hatred of Boris Bot, and takes
their game. The SREBOT website goes live, turning stats, scoreboards, and the lead on the website. She also pushes us off of Replit and onto proper
replays into a browser experience players can explore. infrastructure, forcing me to actually learn how this stuff works. The site
goes live and keeps growing from there.
</p> </p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>100 Servers</span>
</div>
</div> </div>
</div> </div>
</article> </article>
@@ -333,7 +436,7 @@
<div class="timeline-marker"><i class="fas fa-handshake"></i></div> <div class="timeline-marker"><i class="fas fa-handshake"></i></div>
<div class="pt-3"> <div class="pt-3">
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<span class="timeline-index">07 · Partnership</span> <span class="timeline-index">08 · Partnership</span>
<span class="timeline-date">January 2026</span> <span class="timeline-date">January 2026</span>
</div> </div>
<h3 class="timeline-title mb-3">Teaming Up with Spectra</h3> <h3 class="timeline-title mb-3">Teaming Up with Spectra</h3>
@@ -342,6 +445,30 @@
consolidates and partners with Spectra to receive games directly, instead of consolidates and partners with Spectra to receive games directly, instead of
downloading and parsing every match on its own. downloading and parsing every match on its own.
</p> </p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>340 Servers</span>
</div>
</div>
</div>
</article>
<article class="timeline-node">
<div class="timeline-card">
<div class="timeline-marker"><i class="fas fa-route"></i></div>
<div class="pt-3">
<div class="flex items-center justify-between mb-2">
<span class="timeline-index">09 · Paths</span>
<span class="timeline-date">March 2026</span>
</div>
<h3 class="timeline-title mb-3">Max and His Paths</h3>
<p class="timeline-desc">
Max was reviving the WT Heatmaps project and gave us an API to request
images with player paths drawn on the map for each game. We do this
ourselves now, but it started here.
</p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>450 Servers</span>
</div>
</div> </div>
</div> </div>
</article> </article>
@@ -351,7 +478,7 @@
<div class="timeline-marker"><i class="fas fa-coins"></i></div> <div class="timeline-marker"><i class="fas fa-coins"></i></div>
<div class="pt-3"> <div class="pt-3">
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<span class="timeline-index">08 · Monetization</span> <span class="timeline-index">10 · Monetization</span>
<span class="timeline-date">April 2026</span> <span class="timeline-date">April 2026</span>
</div> </div>
<h3 class="timeline-title mb-3">Fueling the Future</h3> <h3 class="timeline-title mb-3">Fueling the Future</h3>
@@ -359,6 +486,30 @@
Monetization brings in real income for the first time, funding better Monetization brings in real income for the first time, funding better
servers and helping new features ship faster. servers and helping new features ship faster.
</p> </p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>580 Servers</span>
</div>
</div>
</div>
</article>
<article class="timeline-node">
<div class="timeline-card">
<div class="timeline-marker"><i class="fas fa-plug"></i></div>
<div class="pt-3">
<div class="flex items-center justify-between mb-2">
<span class="timeline-index">11 · Clients</span>
<span class="timeline-date">May 2026</span>
</div>
<h3 class="timeline-title mb-3">Supporting Client Ports</h3>
<p class="timeline-desc">
We start supporting a client port of our project, letting other bots
build on top of what we made. First up is AXBot, which serves the
Chinese portion of the SQB playerbase.
</p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span>600 Servers</span>
</div>
</div> </div>
</div> </div>
</article> </article>
@@ -368,15 +519,18 @@
<div class="timeline-marker"><i class="fas fa-location-dot"></i></div> <div class="timeline-marker"><i class="fas fa-location-dot"></i></div>
<div class="pt-3"> <div class="pt-3">
<div class="flex items-center justify-between mb-2"> <div class="flex items-center justify-between mb-2">
<span class="timeline-index">09 · Today</span> <span class="timeline-index">12 · Today</span>
<span class="timeline-date">Now</span> <span class="timeline-date">Now</span>
</div> </div>
<h3 class="timeline-title mb-3">Where We Are Now</h3> <h3 class="timeline-title mb-3">Where We Are Now</h3>
<p class="timeline-desc"> <p class="timeline-desc">
Automated parsing through Spectra, funded development, and a growing Automated parsing through Spectra, funded development, and a growing
community of squadrons define the project today. The next chapter is already community of squadrons define the project today. We're already working on
underway. our next product, <a href="https://tss.pawjob.us" target="_blank" rel="noopener" class="text-accent font-semibold hover:underline">TSSBOT</a>.
</p> </p>
<div class="timeline-card-footer">
<i class="fab fa-discord"></i><span><%= serverCount %> Servers</span>
</div>
</div> </div>
</div> </div>
</article> </article>
@@ -392,6 +546,12 @@
</div> </div>
</section> </section>
<!-- Scroll hint — fades out on first scroll -->
<div id="scroll-hint">
<span>SCROLL</span>
<div class="hint-line"></div>
</div>
<!-- Footer --> <!-- Footer -->
<%- include('partials/footer') %> <%- include('partials/footer') %>
@@ -426,6 +586,7 @@
if (!timeline || !svg) return; if (!timeline || !svg) return;
var nodes = Array.prototype.slice.call(timeline.querySelectorAll('.timeline-node')); var nodes = Array.prototype.slice.call(timeline.querySelectorAll('.timeline-node'));
var endMarker = document.getElementById('timelineEndMarker');
var reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; var reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var useGsap = !!(window.gsap && window.ScrollTrigger); var useGsap = !!(window.gsap && window.ScrollTrigger);
var drawProgress = 0; // 0 to 1, how much of the line is drawn var drawProgress = 0; // 0 to 1, how much of the line is drawn
@@ -437,6 +598,7 @@
var lineTrigger = null; var lineTrigger = null;
var nodeTriggers = []; var nodeTriggers = [];
var nextRevealIndex = 0; var nextRevealIndex = 0;
var preRevealProgress = 0;
// Build a rounded-corner path that threads through a list of points. // Build a rounded-corner path that threads through a list of points.
function roundedPath(pts, radius) { function roundedPath(pts, radius) {
@@ -496,6 +658,11 @@
return nodePathProgress(node, index, pathLength); return nodePathProgress(node, index, pathLength);
}); });
if (endMarker && pts.length) {
var ep = pts[pts.length - 1];
endMarker.setAttribute('cx', ep.x.toFixed(1));
endMarker.setAttribute('cy', ep.y.toFixed(1));
}
updateComet(pathLength); updateComet(pathLength);
return { pts: pts, len: pathLength }; return { pts: pts, len: pathLength };
} }
@@ -552,6 +719,23 @@
return lengthAtPoint(getMarkerCenter(node), len) / len; return lengthAtPoint(getMarkerCenter(node), len) / len;
} }
function initPreReveal() {
var vh = window.innerHeight;
var sp = 0;
nodes.forEach(function (node, idx) {
if (node.getBoundingClientRect().top < vh * 0.95) {
sp = Math.max(sp, nodeProgresses[idx] || 0);
}
});
if (sp > state.progress) {
preRevealProgress = sp;
drawProgress = sp;
state.progress = sp;
targetDrawProgress = sp;
renderProgress();
}
}
function revealReachedNodes() { function revealReachedNodes() {
// Scan forward only — nodes are in path order so we never need to re-check // Scan forward only — nodes are in path order so we never need to re-check
while (nextRevealIndex < nodes.length) { while (nextRevealIndex < nodes.length) {
@@ -561,8 +745,11 @@
nodeRevealed[nextRevealIndex] = true; nodeRevealed[nextRevealIndex] = true;
node.classList.add('is-visible'); node.classList.add('is-visible');
if (useGsap) { if (useGsap) {
node.style.background = '#1b1b1b'; node.style.background = 'rgba(27,27,27,0)';
gsap.fromTo(node, { y: -16, scale: 0.97 }, { y: 0, scale: 1, duration: 0.55, ease: 'power2.out', overwrite: true }); gsap.fromTo(node,
{ y: -16, scale: 0.97, backgroundColor: 'rgba(27,27,27,0)' },
{ y: 0, scale: 1, backgroundColor: 'rgba(27,27,27,1)', duration: 0.55, ease: 'power2.out', overwrite: true,
onComplete: function () { node.style.background = '#1b1b1b'; } });
var card = node.querySelector('.timeline-card'); var card = node.querySelector('.timeline-card');
if (card) gsap.fromTo(card, { opacity: 0 }, { opacity: 1, duration: 0.55, ease: 'power2.out' }); if (card) gsap.fromTo(card, { opacity: 0 }, { opacity: 1, duration: 0.55, ease: 'power2.out' });
} }
@@ -646,12 +833,12 @@
trigger: timeline, trigger: timeline,
start: 'top 70%', start: 'top 70%',
endTrigger: nodes[nodes.length - 1] || timeline, endTrigger: nodes[nodes.length - 1] || timeline,
end: 'top 40%', end: 'top 60%',
scrub: 0.6, scrub: 0.6,
invalidateOnRefresh: true, invalidateOnRefresh: true,
onUpdate: function (self) { onUpdate: function (self) {
var p = Math.min(1, Math.max(0, self.progress)); var p = Math.min(1, preRevealProgress + self.progress * (1 - preRevealProgress));
if (p <= state.progress + 0.0005) return; if (p <= state.progress) return;
state.progress = p; state.progress = p;
targetDrawProgress = p; targetDrawProgress = p;
drawProgress = p; drawProgress = p;
@@ -673,6 +860,23 @@
createScrollTriggers(); createScrollTriggers();
renderProgress(); renderProgress();
ScrollTrigger.refresh(); ScrollTrigger.refresh();
requestAnimationFrame(function () {
if (lineTrigger && lineTrigger.progress > state.progress) {
var p = lineTrigger.progress;
state.progress = p;
drawProgress = p;
targetDrawProgress = p;
renderProgress();
}
initPreReveal();
});
var hint = document.getElementById('scroll-hint');
function hideScrollHint() {
if (!hint) return;
hint.style.opacity = '0';
hint = null;
}
if (window.Lenis) { if (window.Lenis) {
var lenis = new Lenis({ var lenis = new Lenis({
@@ -680,9 +884,14 @@
easing: function (t) { return 1 - Math.pow(1 - t, 3); }, easing: function (t) { return 1 - Math.pow(1 - t, 3); },
smoothWheel: true smoothWheel: true
}); });
lenis.on('scroll', ScrollTrigger.update); lenis.on('scroll', function () {
hideScrollHint();
ScrollTrigger.update();
});
gsap.ticker.add(function (time) { lenis.raf(time * 1000); }); gsap.ticker.add(function (time) { lenis.raf(time * 1000); });
gsap.ticker.lagSmoothing(0); gsap.ticker.lagSmoothing(0);
} else {
window.addEventListener('scroll', hideScrollHint, { once: true });
} }
} else { } else {
advanceTo(1, 0); advanceTo(1, 0);
@@ -713,6 +922,16 @@
if (!reduceMotion && useGsap) { if (!reduceMotion && useGsap) {
createScrollTriggers(); createScrollTriggers();
ScrollTrigger.refresh(); ScrollTrigger.refresh();
requestAnimationFrame(function () {
if (lineTrigger && lineTrigger.progress > state.progress) {
var p = lineTrigger.progress;
state.progress = p;
drawProgress = p;
targetDrawProgress = p;
renderProgress();
}
initPreReveal();
});
} }
}); });
})(); })();