101 lines
3.7 KiB
JavaScript
101 lines
3.7 KiB
JavaScript
const commissionPage = document.querySelector(".commissions-page");
|
|
|
|
if (commissionPage) {
|
|
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
const finePointer = window.matchMedia("(hover: hover) and (pointer: fine)").matches;
|
|
|
|
if (finePointer && !reduceMotion) {
|
|
const hero = document.querySelector(".commission-hero-new");
|
|
|
|
window.addEventListener("pointermove", (event) => {
|
|
commissionPage.style.setProperty("--mx", `${event.clientX}px`);
|
|
commissionPage.style.setProperty("--my", `${event.clientY}px`);
|
|
|
|
if (hero) {
|
|
const bounds = hero.getBoundingClientRect();
|
|
hero.style.setProperty("--hx", `${event.clientX - bounds.left}px`);
|
|
hero.style.setProperty("--hy", `${event.clientY - bounds.top}px`);
|
|
}
|
|
}, { passive: true });
|
|
}
|
|
|
|
const clock = document.querySelector(".scope-clock");
|
|
if (clock) {
|
|
const startedAt = Date.now();
|
|
const updateClock = () => {
|
|
const seconds = Math.floor((Date.now() - startedAt) / 1000);
|
|
const hours = String(Math.floor(seconds / 3600)).padStart(2, "0");
|
|
const minutes = String(Math.floor((seconds % 3600) / 60)).padStart(2, "0");
|
|
const remainder = String(seconds % 60).padStart(2, "0");
|
|
clock.textContent = `${hours}:${minutes}:${remainder}`;
|
|
};
|
|
updateClock();
|
|
window.setInterval(updateClock, 1000);
|
|
}
|
|
|
|
const rotatingWord = document.querySelector(".commission-word");
|
|
if (rotatingWord && !reduceMotion) {
|
|
const words = (rotatingWord.dataset.words || "weird").split(",");
|
|
let wordIndex = 0;
|
|
window.setInterval(() => {
|
|
rotatingWord.classList.add("is-changing");
|
|
window.setTimeout(() => {
|
|
wordIndex = (wordIndex + 1) % words.length;
|
|
rotatingWord.textContent = words[wordIndex];
|
|
}, 110);
|
|
window.setTimeout(() => rotatingWord.classList.remove("is-changing"), 280);
|
|
}, 2800);
|
|
}
|
|
|
|
const filterButtons = document.querySelectorAll("[data-price-filter]");
|
|
const priceGroups = document.querySelectorAll("[data-price-category]");
|
|
const visibleCount = document.querySelector("#price-visible-count");
|
|
|
|
filterButtons.forEach((button) => {
|
|
button.addEventListener("click", () => {
|
|
const selected = button.dataset.priceFilter;
|
|
let count = 0;
|
|
|
|
filterButtons.forEach((candidate) => {
|
|
const active = candidate === button;
|
|
candidate.classList.toggle("is-active", active);
|
|
candidate.setAttribute("aria-pressed", String(active));
|
|
});
|
|
|
|
priceGroups.forEach((group) => {
|
|
const visible = selected === "all" || group.dataset.priceCategory === selected;
|
|
group.hidden = !visible;
|
|
if (visible) count += group.querySelectorAll(".price-list > div").length;
|
|
});
|
|
|
|
if (visibleCount) visibleCount.textContent = String(count);
|
|
});
|
|
});
|
|
|
|
const copyBrief = document.querySelector("#copy-brief");
|
|
const copyStatus = document.querySelector("#copy-status");
|
|
const brief = [
|
|
"Hi Alex — I have a commission request.",
|
|
"",
|
|
"What I want to build or fix:",
|
|
"Current system / versions:",
|
|
"What happens now:",
|
|
"What I want to happen:",
|
|
"What counts as done:",
|
|
"Budget range:",
|
|
"Deadline, if any:",
|
|
"Useful logs / screenshots:",
|
|
].join("\n");
|
|
|
|
if (copyBrief && copyStatus) {
|
|
copyBrief.addEventListener("click", async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(brief);
|
|
copyStatus.textContent = "Commission brief copied. Paste it into an email, Telegram, or Discord.";
|
|
} catch {
|
|
copyStatus.textContent = "Clipboard access was blocked. Email me the goal, setup, symptoms, and any logs.";
|
|
}
|
|
window.setTimeout(() => { copyStatus.textContent = ""; }, 4000);
|
|
});
|
|
}
|
|
}
|