diff --git a/site/_headers b/site/_headers
index 703c511..89b059c 100644
--- a/site/_headers
+++ b/site/_headers
@@ -1,10 +1,12 @@
https://arsonkupik.pages.dev/
Link: ; rel="canonical"
+ Link: ; rel="preload"; as="image"; type="image/webp"
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
https://arsonkupik.pages.dev/id/
Link: ; rel="canonical"
+ Link: ; rel="preload"; as="image"; type="image/webp"
https://arsonkupik.pages.dev/guide/
Link: ; rel="canonical"
diff --git a/site/experience-v4.js b/site/experience-v4.js
index dd74bbb..89469a4 100644
--- a/site/experience-v4.js
+++ b/site/experience-v4.js
@@ -1,9 +1,8 @@
(() => {
'use strict';
- const language = document.documentElement.lang === 'id' ? 'id' : 'en';
- const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
- const finePointer = window.matchMedia('(hover: hover) and (pointer: fine)').matches;
+ const root = document.documentElement;
+ const language = root.lang === 'id' ? 'id' : 'en';
const text = language === 'id'
? {
preview: 'Buka tampilan aplikasi ukuran besar',
@@ -22,89 +21,10 @@
visible: (count) => `${count} presets shown`
};
- const setMeta = (selector, value) => {
- const element = document.querySelector(selector);
- if (element) element.setAttribute('content', value);
- };
-
- const setText = (selector, value) => {
- const element = document.querySelector(selector);
- if (element) element.textContent = value;
- };
-
- const setupCrossPlatformCopy = () => {
- const isId = language === 'id';
- document.title = isId
- ? 'ArSonKuPik — VST3 Audio Enhancer Musikal untuk Windows dan macOS'
- : 'ArSonKuPik — Musical VST3 Audio Enhancer for Windows and macOS';
-
- const description = isId
- ? 'Hasilkan suara lebih berisi, jernih, dan berdimensi tanpa rangkaian plug-in rumit. ArSonKuPik tersedia sebagai VST3 dan Standalone untuk Windows dan macOS.'
- : 'Achieve fuller, clearer and more dimensional sound without a complex plug-in chain. ArSonKuPik is available as VST3 and Standalone for Windows and macOS.';
- setMeta('meta[name="description"]', description);
- setMeta('meta[property="og:description"]', description);
- setMeta('meta[name="twitter:description"]', description);
-
- setText('.landing-hero .hero-copy > .eyebrow', isId
- ? 'VST3 audio enhancer musikal untuk Windows dan macOS'
- : 'Musical VST3 audio enhancer for Windows and macOS');
-
- const trustFormat = document.querySelector('.trust-grid > div:first-child span');
- if (trustFormat) {
- trustFormat.textContent = isId
- ? 'Di dalam DAW kompatibel atau sebagai aplikasi terpisah di Windows maupun macOS.'
- : 'Inside a compatible DAW or as a separate application on Windows or macOS.';
- }
-
- setText('#download .section-heading .eyebrow', isId
- ? 'Unduhan resmi Windows dan macOS'
- : 'Official Windows and macOS downloads');
-
- const downloadLead = document.querySelector('#download .section-heading .section-lead');
- if (downloadLead) {
- downloadLead.textContent = isId
- ? 'Gunakan installer Windows untuk pemasangan paling mudah, atau pilih paket VST3, Standalone, dan DMG resmi sesuai sistem operasi Anda.'
- : 'Use the Windows installer for the simplest setup, or choose the official VST3, Standalone and DMG package for your operating system.';
- }
-
- const standaloneHint = document.querySelector('#technical span:nth-child(2) small');
- if (standaloneHint) {
- standaloneHint.textContent = isId
- ? 'Aplikasi terpisah untuk workflow audio device yang didukung di Windows atau macOS'
- : 'A separate application for supported audio-device workflows on Windows or macOS';
- }
-
- const macCard = document.getElementById('mac-download-option');
- if (macCard) {
- const heading = macCard.querySelector('h3');
- const paragraph = macCard.querySelector('p');
- const dmg = macCard.querySelector('#mac-dmg-link');
- if (heading) heading.textContent = isId ? 'Paket Mac' : 'Mac package';
- if (paragraph) paragraph.textContent = isId
- ? 'Universal untuk Apple Silicon dan Intel. Ad-hoc signed, tanpa Developer ID dan tanpa notarization.'
- : 'Universal for Apple Silicon and Intel. Ad-hoc signed, without Developer ID signing or notarization.';
- if (dmg) dmg.textContent = isId ? 'Unduh DMG Mac' : 'Download Mac DMG';
- }
-
- const faqStandalone = [...document.querySelectorAll('.faq-grid details')]
- .find((item) => /VST3 (or|atau) Standalone\?/i.test(item.querySelector('summary')?.textContent || ''));
- const faqParagraph = faqStandalone?.querySelector('p');
- if (faqParagraph) {
- faqParagraph.textContent = isId
- ? 'VST3 berjalan di dalam DAW kompatibel. Standalone berjalan sebagai aplikasi terpisah di Windows atau macOS untuk workflow audio device yang didukung.'
- : 'VST3 runs inside a compatible DAW. Standalone runs as a separate Windows or macOS application for supported audio-device workflows.';
- }
-
- setText('#mobile-download-bar strong', isId
- ? 'ArSonKuPik untuk Windows dan macOS'
- : 'ArSonKuPik for Windows and macOS');
-
- document.documentElement.setAttribute('data-crossplatform-copy', 'windows-macos-v0520');
- };
-
const setupProductPreview = () => {
const source = document.querySelector('.product-stage img');
if (!source || typeof HTMLDialogElement === 'undefined') return;
+
source.setAttribute('role', 'button');
source.setAttribute('tabindex', '0');
source.setAttribute('aria-label', text.preview);
@@ -113,6 +33,7 @@
const dialog = document.createElement('dialog');
dialog.className = 'product-preview-dialog';
dialog.setAttribute('aria-label', text.preview);
+
const shell = document.createElement('div');
shell.className = 'product-preview-shell';
const preview = document.createElement('img');
@@ -120,6 +41,8 @@
preview.alt = source.alt;
preview.width = source.width || 1080;
preview.height = source.height || 612;
+ preview.decoding = 'async';
+
const footer = document.createElement('div');
footer.className = 'product-preview-footer';
const caption = document.createElement('span');
@@ -129,6 +52,7 @@
closeButton.className = 'product-preview-close';
closeButton.textContent = text.close;
closeButton.addEventListener('click', () => dialog.close());
+
footer.append(caption, closeButton);
shell.append(preview, footer);
dialog.append(shell);
@@ -155,10 +79,11 @@
const universe = document.querySelector('.preset-universe');
const groupsContainer = universe?.querySelector('.preset-groups');
const groups = groupsContainer ? [...groupsContainer.querySelectorAll('.preset-group')] : [];
- if (!universe || !groupsContainer || groups.length === 0 || universe.dataset.explorerReady === 'true') return;
+ if (!universe || !groupsContainer || !groups.length || universe.dataset.explorerReady === 'true') return;
universe.dataset.explorerReady = 'true';
universe.classList.add('preset-explorer-ready');
+
const categories = groups.map((group, index) => {
const heading = group.querySelector('header strong')?.textContent?.trim() || `Group ${index + 1}`;
const key = heading.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
@@ -194,33 +119,10 @@
const result = document.createElement('span');
result.className = 'preset-result-count';
result.setAttribute('aria-live', 'polite');
+
const total = groups.reduce((sum, group) => sum + Number(group.dataset.presetCount || 0), 0);
result.textContent = text.visible(total);
- const showGroup = (group, visible) => {
- group.getAnimations?.().forEach((animation) => animation.cancel());
- group.dataset.filterTarget = visible ? 'visible' : 'hidden';
- if (reducedMotion || typeof group.animate !== 'function') {
- group.hidden = !visible;
- return;
- }
- if (visible) {
- group.hidden = false;
- group.animate(
- [{ opacity: 0, transform: 'translateY(8px) scale(.995)' }, { opacity: 1, transform: 'translateY(0) scale(1)' }],
- { duration: 240, easing: 'cubic-bezier(.22, 1, .36, 1)' }
- );
- } else if (!group.hidden) {
- const animation = group.animate(
- [{ opacity: 1, transform: 'translateY(0) scale(1)' }, { opacity: 0, transform: 'translateY(5px) scale(.995)' }],
- { duration: 140, easing: 'ease-out' }
- );
- animation.addEventListener('finish', () => {
- if (group.dataset.filterTarget === 'hidden') group.hidden = true;
- }, { once: true });
- }
- };
-
[{ key: 'all', heading: text.all }, ...categories].forEach((choice, index) => {
const button = document.createElement('button');
button.type = 'button';
@@ -229,11 +131,13 @@
button.textContent = choice.heading;
button.setAttribute('aria-pressed', String(index === 0));
button.addEventListener('click', () => {
- filters.querySelectorAll('.preset-filter').forEach((item) => item.setAttribute('aria-pressed', String(item === button)));
+ filters.querySelectorAll('.preset-filter').forEach((item) => {
+ item.setAttribute('aria-pressed', String(item === button));
+ });
let visibleCount = 0;
groups.forEach((group) => {
const visible = choice.key === 'all' || group.dataset.presetCategory === choice.key;
- showGroup(group, visible);
+ group.hidden = !visible;
if (visible) visibleCount += Number(group.dataset.presetCount || 0);
});
result.textContent = text.visible(visibleCount);
@@ -246,137 +150,60 @@
browser.append(toolbar, groupsContainer);
};
- const setupSignalAccent = () => {
- const title = document.querySelector('.signature-title');
- const badge = title?.querySelector(':scope > span');
- if (!title || !badge || title.querySelector('.signal-accent')) return;
- const row = document.createElement('div');
- row.className = 'signature-status-row';
- const meter = document.createElement('span');
- meter.className = 'signal-accent';
- meter.setAttribute('aria-hidden', 'true');
- for (let index = 0; index < 7; index += 1) {
- const bar = document.createElement('i');
- bar.style.setProperty('--bar-index', String(index));
- meter.append(bar);
- }
- badge.before(row);
- row.append(badge, meter);
- };
-
- const setupScrollReveals = () => {
- const targets = [
- ...document.querySelectorAll('.trust-grid > div'),
- document.querySelector('.signature-copy'),
- document.querySelector('.signature-panel'),
- ...document.querySelectorAll('.outcome-grid > article'),
- ...document.querySelectorAll('.test-flow > article'),
- ...document.querySelectorAll('.listening-controls > article'),
- document.querySelector('.preset-intro'),
- document.querySelector('.preset-browser'),
- ...document.querySelectorAll('.download-option'),
- document.querySelector('.freedom-copy'),
- document.querySelector('.freedom-facts'),
- ...document.querySelectorAll('.faq-grid > details'),
- document.querySelector('.cta-card')
- ].filter(Boolean);
- if (reducedMotion || !('IntersectionObserver' in window)) {
- targets.forEach((target) => target.classList.add('is-visible'));
- return;
- }
- targets.forEach((target, index) => {
- target.dataset.reveal = '';
- target.style.setProperty('--reveal-delay', `${(index % 4) * 55}ms`);
- });
- document.documentElement.classList.add('motion-ready');
- const observer = new IntersectionObserver((entries) => {
- entries.forEach((entry) => {
- if (!entry.isIntersecting) return;
- entry.target.classList.add('is-visible');
- observer.unobserve(entry.target);
- });
- }, { rootMargin: '0px 0px -9% 0px', threshold: .08 });
- targets.forEach((target) => observer.observe(target));
- };
-
- const setupHeroEntrance = () => {
- if (reducedMotion || typeof Element.prototype.animate !== 'function') return;
- const items = [...document.querySelectorAll('.landing-hero .hero-copy > *'), document.querySelector('.landing-hero .product-stage')].filter(Boolean);
- items.forEach((item, index) => item.animate(
- [{ opacity: 0, transform: 'translateY(12px)' }, { opacity: 1, transform: 'translateY(0)' }],
- { duration: index === items.length - 1 ? 720 : 520, delay: 45 + index * 65, easing: 'cubic-bezier(.22, 1, .36, 1)', fill: 'both' }
- ));
- };
-
const setupNavigationState = () => {
const nav = document.querySelector('.landing-nav');
const links = [...document.querySelectorAll('.landing-nav nav a[href^="#"]')];
- const sections = links.map((link) => ({ link, section: document.querySelector(link.getAttribute('href')) })).filter((item) => item.section);
- if (!nav || sections.length === 0) return;
- let scheduled = false;
- const update = () => {
- scheduled = false;
+ if (!nav) return;
+
+ let frame = 0;
+ const updateScrolledState = () => {
+ frame = 0;
nav.classList.toggle('is-scrolled', window.scrollY > 18);
- const probe = window.scrollY + Math.min(window.innerHeight * .34, 320);
- let active = sections[0];
- sections.forEach((item) => { if (item.section.offsetTop <= probe) active = item; });
- sections.forEach((item) => {
- const selected = item === active;
- item.link.classList.toggle('is-active', selected);
- if (selected) item.link.setAttribute('aria-current', 'location');
- else item.link.removeAttribute('aria-current');
- });
};
- const requestUpdate = () => {
- if (scheduled) return;
- scheduled = true;
- requestAnimationFrame(update);
+ window.addEventListener('scroll', () => {
+ if (frame) return;
+ frame = window.requestAnimationFrame(updateScrolledState);
+ }, { passive: true });
+ updateScrolledState();
+
+ if (!('IntersectionObserver' in window) || !links.length) return;
+ const sections = links
+ .map((link) => ({ link, section: document.querySelector(link.getAttribute('href')) }))
+ .filter((item) => item.section);
+ if (!sections.length) return;
+
+ const byId = new Map(sections.map((item) => [item.section.id, item.link]));
+ const setActive = (id) => {
+ sections.forEach(({ link, section }) => {
+ const selected = section.id === id;
+ link.classList.toggle('is-active', selected);
+ if (selected) link.setAttribute('aria-current', 'location');
+ else link.removeAttribute('aria-current');
+ });
};
- window.addEventListener('scroll', requestUpdate, { passive: true });
- window.addEventListener('resize', requestUpdate, { passive: true });
- update();
+
+ const observer = new IntersectionObserver((entries) => {
+ const visible = entries
+ .filter((entry) => entry.isIntersecting && byId.has(entry.target.id))
+ .sort((a, b) => Math.abs(a.boundingClientRect.top) - Math.abs(b.boundingClientRect.top));
+ if (visible[0]) setActive(visible[0].target.id);
+ }, { rootMargin: '-18% 0px -70% 0px', threshold: 0 });
+
+ sections.forEach(({ section }) => observer.observe(section));
};
- const setupPointerDepth = () => {
- if (!finePointer || reducedMotion) return;
- const stage = document.querySelector('.product-stage');
- const spotlights = [stage, document.querySelector('.signature-panel'), document.querySelector('.download-option.recommended'), document.querySelector('.cta-card')].filter(Boolean);
- spotlights.forEach((element) => {
- let frame = 0;
- element.addEventListener('pointermove', (event) => {
- if (frame) cancelAnimationFrame(frame);
- frame = requestAnimationFrame(() => {
- const rect = element.getBoundingClientRect();
- const x = Math.min(1, Math.max(0, (event.clientX - rect.left) / rect.width));
- const y = Math.min(1, Math.max(0, (event.clientY - rect.top) / rect.height));
- element.style.setProperty('--spot-x', `${x * 100}%`);
- element.style.setProperty('--spot-y', `${y * 100}%`);
- if (element === stage) {
- element.style.setProperty('--tilt-y', `${(x - .5) * 1.5}deg`);
- element.style.setProperty('--tilt-x', `${(.5 - y) * 1.1}deg`);
- element.dataset.depthActive = 'true';
- }
- });
- }, { passive: true });
- element.addEventListener('pointerleave', () => {
- element.style.removeProperty('--spot-x');
- element.style.removeProperty('--spot-y');
- if (element === stage) {
- element.style.setProperty('--tilt-y', '0deg');
- element.style.setProperty('--tilt-x', '0deg');
- delete element.dataset.depthActive;
- }
- }, { passive: true });
- });
+ const initializeEnhancements = () => {
+ setupPresetExplorer();
+ setupProductPreview();
+ setupNavigationState();
+ root.setAttribute('data-experience-layer', 'v7-static-first');
};
- setupCrossPlatformCopy();
- setupPresetExplorer();
- setupProductPreview();
- setupSignalAccent();
- setupScrollReveals();
- setupHeroEntrance();
- setupNavigationState();
- setupPointerDepth();
- document.documentElement.setAttribute('data-experience-layer', 'v6-static-audio-motion');
+ // All critical copy, SEO metadata and the LCP image are already present in
+ // HTML. Keep enhancement work out of the initial rendering path.
+ if ('requestIdleCallback' in window) {
+ window.requestIdleCallback(initializeEnhancements, { timeout: 1600 });
+ } else {
+ window.requestAnimationFrame(() => window.setTimeout(initializeEnhancements, 0));
+ }
})();
diff --git a/site/hardening-v6.css b/site/hardening-v6.css
index 527ed6c..8f1b623 100644
--- a/site/hardening-v6.css
+++ b/site/hardening-v6.css
@@ -298,6 +298,26 @@ html[data-global-shell="v6"] {
box-shadow: none;
}
+/* Skip layout/paint for long below-the-fold sections until they approach the
+ viewport. The intrinsic fallback keeps scroll geometry stable and preserves
+ static HTML/SEO/accessibility while reducing initial rendering work. */
+@supports (content-visibility: auto) {
+ main > .section {
+ content-visibility: auto;
+ contain-intrinsic-size: auto 760px;
+ }
+
+ .support-strip {
+ content-visibility: auto;
+ contain-intrinsic-size: auto 90px;
+ }
+
+ footer {
+ content-visibility: auto;
+ contain-intrinsic-size: auto 360px;
+ }
+}
+
@media (max-width: 860px) {
.landing-nav nav[aria-label] {
display: none;
diff --git a/site/site-v6.js b/site/site-v6.js
index 9b26ec5..ad55bdf 100644
--- a/site/site-v6.js
+++ b/site/site-v6.js
@@ -25,8 +25,23 @@
const source = currentScript?.src
|| new URL(`${root.dataset.siteBase || '.'}/site-v6.js`, location.href).href;
- const core = document.createElement('script');
- core.src = source.replace(/site-v6\.js(?:\?.*)?$/, 'site-v6-core.js');
- core.async = false;
- document.head.appendChild(core);
+
+ let coreRequested = false;
+ const loadCore = () => {
+ if (coreRequested) return;
+ coreRequested = true;
+ const core = document.createElement('script');
+ core.src = source.replace(/site-v6\.js(?:\?.*)?$/, 'site-v6-core.js');
+ core.async = true;
+ document.head.appendChild(core);
+ };
+
+ // Release enrichment is useful but not required for the first paint. The
+ // reviewed static HTML already routes users to the official GitHub Release,
+ // so let LCP/rendering finish before parsing the larger enhancement runtime.
+ if ('requestIdleCallback' in window) {
+ window.requestIdleCallback(loadCore, { timeout: 1400 });
+ } else {
+ window.requestAnimationFrame(() => window.setTimeout(loadCore, 0));
+ }
})();
diff --git a/site/sitemap.xml b/site/sitemap.xml
index 185fe7d..b41930d 100644
--- a/site/sitemap.xml
+++ b/site/sitemap.xml
@@ -2,11 +2,11 @@
https://arsonkupik.pages.dev/
- 2026-08-23
+ 2026-09-12
https://arsonkupik.pages.dev/id/
- 2026-08-23
+ 2026-09-12
https://arsonkupik.pages.dev/guide/