mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-27 12:29:35 +00:00
Enhance forest scene with mid bamboo layer, butterflies, click confetti, and demo scene polish
This commit is contained in:
@@ -18,6 +18,14 @@
|
||||
# # Clean URLs support (resolves /join to join.html, etc.)
|
||||
# try_files {path} {path}.html {path}/
|
||||
# file_server
|
||||
#
|
||||
# # Serve the themed 404 page for unknown URLs (without this block,
|
||||
# # Caddy returns an empty 404 response)
|
||||
# handle_errors {
|
||||
# @notfound expression {err.status_code} == 404
|
||||
# rewrite @notfound /404.html
|
||||
# file_server
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# syncserver.koalastuff.net {
|
||||
@@ -57,6 +65,14 @@ sync.koalastuff.net {
|
||||
try_files {path} {path}.html {path}/
|
||||
file_server
|
||||
|
||||
# Serve the themed 404 page for unknown URLs (without this block,
|
||||
# Caddy returns an empty 404 response)
|
||||
handle_errors {
|
||||
@notfound expression {err.status_code} == 404
|
||||
rewrite @notfound /404.html
|
||||
file_server
|
||||
}
|
||||
|
||||
# Static Caching for high-performance PageSpeed (1 year with validation)
|
||||
@static {
|
||||
file
|
||||
|
||||
+169
-8
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>KoalaSync</title>
|
||||
<script src="theme-init.js"></script>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Twemoji Country Flags';
|
||||
@@ -26,6 +27,7 @@
|
||||
--accent-terracotta: oklch(0.62 0.14 45);
|
||||
--danger: oklch(0.55 0.15 25);
|
||||
--text-on-green: oklch(0.14 0.02 90);
|
||||
--text-on-warm: oklch(0.16 0.025 45);
|
||||
|
||||
--bg: var(--surface-deep);
|
||||
--card: var(--surface);
|
||||
@@ -37,6 +39,25 @@
|
||||
--error: var(--danger);
|
||||
--radius: 12px;
|
||||
--star: oklch(0.68 0.14 45);
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
html.theme-light {
|
||||
--bg-base: oklch(0.965 0.012 105);
|
||||
--surface: oklch(0.995 0.006 100);
|
||||
--surface-deep: oklch(0.935 0.018 110);
|
||||
--surface-alt: oklch(0.91 0.022 115);
|
||||
--border-soft: oklch(0.28 0.035 140 / 0.10);
|
||||
--border-strong: oklch(0.73 0.035 125);
|
||||
--text-primary: oklch(0.21 0.03 140);
|
||||
--text-secondary: oklch(0.43 0.03 135);
|
||||
--accent-green: oklch(0.56 0.13 150);
|
||||
--accent-green-hover: oklch(0.49 0.13 150);
|
||||
--accent-terracotta: oklch(0.64 0.14 45);
|
||||
--danger: oklch(0.57 0.17 25);
|
||||
--text-on-green: oklch(0.16 0.03 140);
|
||||
--text-on-warm: oklch(0.18 0.03 45);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -47,6 +68,16 @@
|
||||
color: var(--text);
|
||||
font-family: 'Twemoji Country Flags', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
background-image:
|
||||
radial-gradient(circle at 12% -8%, oklch(0.68 0.13 150 / 0.12), transparent 42%),
|
||||
radial-gradient(circle at 105% 12%, oklch(0.62 0.14 45 / 0.08), transparent 34%);
|
||||
transition: background-color 0.25s ease, color 0.25s ease;
|
||||
}
|
||||
|
||||
html.theme-light body {
|
||||
background-image:
|
||||
radial-gradient(circle at 8% -5%, oklch(0.72 0.11 145 / 0.24), transparent 40%),
|
||||
radial-gradient(circle at 105% 5%, oklch(0.82 0.12 65 / 0.2), transparent 38%);
|
||||
}
|
||||
|
||||
.header-row {
|
||||
@@ -81,7 +112,7 @@
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
opacity: 0.5;
|
||||
opacity: 0.72;
|
||||
transition: opacity 0.2s, color 0.2s;
|
||||
}
|
||||
.popup-version:hover {
|
||||
@@ -113,7 +144,8 @@
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s;
|
||||
min-height: 36px;
|
||||
transition: background-color 0.2s, color 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.tab-btn.active {
|
||||
@@ -154,7 +186,7 @@
|
||||
box-sizing: border-box;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border-strong);
|
||||
color: white;
|
||||
color: var(--text);
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
outline: none;
|
||||
@@ -189,7 +221,7 @@
|
||||
font-weight: 700;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
transition: background-color 0.2s, box-shadow 0.2s, transform 0.2s;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
@@ -203,13 +235,44 @@
|
||||
padding: 10px;
|
||||
background: var(--border-strong);
|
||||
border: none;
|
||||
color: white;
|
||||
color: var(--text);
|
||||
font-weight: 600;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
button.secondary:hover {
|
||||
background: oklch(0.38 0.035 125);
|
||||
}
|
||||
|
||||
details > summary:focus-visible {
|
||||
outline: 2px solid var(--accent-hover) !important;
|
||||
outline-offset: 3px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
button:focus-visible,
|
||||
a:focus-visible,
|
||||
input:focus-visible,
|
||||
select:focus-visible {
|
||||
outline: 2px solid var(--accent-hover);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.48;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.copy-success {
|
||||
background: var(--success) !important;
|
||||
border-color: var(--success) !important;
|
||||
color: var(--text-on-green) !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* Info Cards */
|
||||
.info-card {
|
||||
background: var(--card);
|
||||
@@ -289,7 +352,7 @@
|
||||
.toast-success { background: var(--success); color: var(--text-on-green); }
|
||||
.toast-error { background: var(--error); color: white; }
|
||||
.toast-info { background: var(--accent); color: var(--text-on-green); }
|
||||
.toast-warning { background: var(--accent-terracotta); color: white; }
|
||||
.toast-warning { background: var(--accent-terracotta); color: var(--text-on-warm); }
|
||||
|
||||
@keyframes toastSlideIn {
|
||||
from { opacity: 0; transform: translateY(-20px); }
|
||||
@@ -300,6 +363,59 @@
|
||||
to { opacity: 0; transform: translateY(-10px); }
|
||||
}
|
||||
|
||||
/* Eucalyptus confetti: tiny leaves bursting from the copy-invite
|
||||
button (spawned by popup.js, mirrors the website's effect). The
|
||||
outer span owns the flight path — fast burst that brakes at its
|
||||
peak, then sinks — while the inner leaf rocks around its stem. */
|
||||
.click-leaf {
|
||||
position: fixed;
|
||||
z-index: 3000;
|
||||
margin: -5px 0 0 -4px;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
animation: leafBurst var(--leaf-dur, 1s) forwards;
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
.click-leaf i {
|
||||
display: block;
|
||||
width: 7px;
|
||||
height: 10px;
|
||||
border-radius: 0 70% 0 70%;
|
||||
background: linear-gradient(135deg, oklch(0.68 0.13 150 / 0.95), oklch(0.5 0.1 145 / 0.85));
|
||||
transform: rotate(var(--leaf-rot, 0deg));
|
||||
animation: leafRock var(--flutter-dur, 0.55s) ease-in-out infinite alternate;
|
||||
}
|
||||
.click-leaf-sage i {
|
||||
background: linear-gradient(135deg, oklch(0.75 0.09 140 / 0.9), oklch(0.58 0.08 145 / 0.8));
|
||||
}
|
||||
.click-leaf-amber i {
|
||||
background: linear-gradient(135deg, oklch(0.68 0.14 55 / 0.95), oklch(0.55 0.13 40 / 0.85));
|
||||
}
|
||||
@keyframes leafBurst {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate(0, 0) scale(var(--leaf-scale, 1));
|
||||
animation-timing-function: cubic-bezier(0.16, 0.84, 0.44, 1);
|
||||
}
|
||||
10% { opacity: 1; }
|
||||
45% {
|
||||
opacity: 1;
|
||||
transform: translate(var(--leaf-x, 0), var(--leaf-y, -14px)) scale(var(--leaf-scale, 1));
|
||||
animation-timing-function: cubic-bezier(0.55, 0.06, 0.68, 0.19);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translate(calc(var(--leaf-x, 0) * 1.4), calc(var(--leaf-y, -14px) + 30px)) scale(calc(var(--leaf-scale, 1) * 0.92));
|
||||
}
|
||||
}
|
||||
@keyframes leafRock {
|
||||
from { transform: rotate(calc(var(--leaf-rot, 0deg) - 24deg)); }
|
||||
to { transform: rotate(calc(var(--leaf-rot, 0deg) + 24deg)); }
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.click-leaf { display: none; }
|
||||
}
|
||||
|
||||
@keyframes fadeSlideIn {
|
||||
from { opacity: 0; transform: translateX(5px); }
|
||||
to { opacity: 1; transform: translateX(0); }
|
||||
@@ -353,7 +469,7 @@
|
||||
padding-top: 10px;
|
||||
color: var(--text-muted);
|
||||
font-size: 10px;
|
||||
opacity: 0.6;
|
||||
opacity: 0.78;
|
||||
}
|
||||
.popup-footer a {
|
||||
color: var(--text-muted);
|
||||
@@ -364,6 +480,42 @@
|
||||
color: var(--accent);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Light theme polish: preserve the same depth hierarchy without
|
||||
carrying dark-only inline colors into form controls and cards. */
|
||||
html.theme-light .tabs,
|
||||
html.theme-light .info-card,
|
||||
html.theme-light details.form-group,
|
||||
html.theme-light .form-group {
|
||||
box-shadow: 0 8px 24px oklch(0.22 0.035 140 / 0.07);
|
||||
}
|
||||
html.theme-light input,
|
||||
html.theme-light select,
|
||||
html.theme-light option {
|
||||
color: var(--text) !important;
|
||||
background-color: var(--surface) !important;
|
||||
}
|
||||
html.theme-light button.secondary {
|
||||
background: var(--surface-alt);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border-strong);
|
||||
}
|
||||
html.theme-light button.secondary:hover {
|
||||
background: oklch(0.86 0.035 125);
|
||||
}
|
||||
html.theme-light .mock-card,
|
||||
html.theme-light .peer-item {
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
html.theme-light .slider:before {
|
||||
background-color: oklch(0.62 0.025 125);
|
||||
}
|
||||
html.theme-light input:checked + .slider:before {
|
||||
background-color: white;
|
||||
}
|
||||
html.theme-light .popup-footer {
|
||||
border-top-color: var(--border-soft);
|
||||
}
|
||||
.feature-hint {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
@@ -466,7 +618,7 @@
|
||||
<label title="Share this link with friends so they can join" data-i18n="LABEL_INVITE_LINK" data-i18n-title="LABEL_INVITE_LINK_TOOLTIP">Invite Link</label>
|
||||
<div class="invite-box">
|
||||
<input type="text" id="inviteLink" readonly>
|
||||
<button id="copyInvite" class="secondary">📋</button>
|
||||
<button id="copyInvite" class="secondary" title="Copy invite link" aria-label="Copy invite link">📋</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -561,6 +713,15 @@
|
||||
|
||||
<!-- Settings Tab -->
|
||||
<div id="tab-settings" class="tab-content">
|
||||
<div class="form-group" style="display: flex; align-items: center; justify-content: space-between; background: var(--card); padding: 10px; border-radius: 8px; margin-bottom: 12px; border: 1px solid var(--border-strong);">
|
||||
<label id="themeLabel" style="margin-bottom: 0;" title="Follow the system theme or choose a fixed appearance">Appearance</label>
|
||||
<select id="themeSelector" aria-label="Appearance" style="width: 165px; background: var(--bg); border: 1px solid var(--border-strong); color: var(--text); padding: 6px 10px; border-radius: 8px; font-size: 13px; cursor: pointer; outline: none; font-family: inherit;">
|
||||
<option id="themeOptionSystem" value="system">💻 System</option>
|
||||
<option id="themeOptionDark" value="dark">🌙 Dark</option>
|
||||
<option id="themeOptionLight" value="light">☀️ Light</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" style="display: flex; align-items: center; justify-content: space-between; background: var(--card); padding: 10px; border-radius: 8px; margin-bottom: 12px; border: 1px solid var(--border-strong);">
|
||||
<label style="margin-bottom: 0;" title="Username helps others identify you." data-i18n="LABEL_USERNAME" data-i18n-title="LABEL_USERNAME_TOOLTIP">Your Username</label>
|
||||
<input type="text" id="username" data-i18n-placeholder="PLACEHOLDER_USERNAME" placeholder="Anonymous Koala" maxlength="20" style="width: 150px;">
|
||||
|
||||
+83
-12
@@ -64,6 +64,7 @@ const elements = {
|
||||
autoCopyInvite: document.getElementById('autoCopyInvite'),
|
||||
cancelLobbyBtn: document.getElementById('cancelLobbyBtn'),
|
||||
langSelector: document.getElementById('langSelector'),
|
||||
themeSelector: document.getElementById('themeSelector'),
|
||||
|
||||
audioSettingsLink: document.getElementById('audioSettingsLink'),
|
||||
settingsSupportLink: document.getElementById('settingsSupportLink'),
|
||||
@@ -132,6 +133,29 @@ function openAudioSettingsPage() {
|
||||
chrome.tabs.create({ url: chrome.runtime.getURL('audio-options.html') });
|
||||
}
|
||||
|
||||
function localizeThemeSelector(locale) {
|
||||
const labels = {
|
||||
de: ['Darstellung', 'System', 'Dunkel', 'Hell'], fr: ['Apparence', 'Système', 'Sombre', 'Clair'],
|
||||
es: ['Apariencia', 'Sistema', 'Oscuro', 'Claro'], it: ['Aspetto', 'Sistema', 'Scuro', 'Chiaro'],
|
||||
nl: ['Weergave', 'Systeem', 'Donker', 'Licht'], pl: ['Wygląd', 'System', 'Ciemny', 'Jasny'],
|
||||
pt: ['Aparência', 'Sistema', 'Escuro', 'Claro'], 'pt-BR': ['Aparência', 'Sistema', 'Escuro', 'Claro'],
|
||||
tr: ['Görünüm', 'Sistem', 'Koyu', 'Açık'], ru: ['Оформление', 'Системная', 'Тёмная', 'Светлая'],
|
||||
ja: ['外観', 'システム', 'ダーク', 'ライト'], ko: ['테마', '시스템', '다크', '라이트'],
|
||||
zh: ['外观', '跟随系统', '深色', '浅色'], uk: ['Вигляд', 'Системна', 'Темна', 'Світла'],
|
||||
en: ['Appearance', 'System', 'Dark', 'Light']
|
||||
};
|
||||
const [label, system, dark, light] = labels[locale] || labels.en;
|
||||
const labelEl = document.getElementById('themeLabel');
|
||||
const systemEl = document.getElementById('themeOptionSystem');
|
||||
const darkEl = document.getElementById('themeOptionDark');
|
||||
const lightEl = document.getElementById('themeOptionLight');
|
||||
if (labelEl) labelEl.textContent = label;
|
||||
if (systemEl) systemEl.textContent = `💻 ${system}`;
|
||||
if (darkEl) darkEl.textContent = `🌙 ${dark}`;
|
||||
if (lightEl) lightEl.textContent = `☀️ ${light}`;
|
||||
if (elements.themeSelector) elements.themeSelector.setAttribute('aria-label', label);
|
||||
}
|
||||
|
||||
async function updateFeatureHints() {
|
||||
const data = await chrome.storage.sync.get(['dismissedHints']);
|
||||
const dismissed = Array.isArray(data.dismissedHints) ? data.dismissedHints : [];
|
||||
@@ -204,7 +228,7 @@ function setRoomRefreshCooldown() {
|
||||
async function init() {
|
||||
// Local-only by design — settings and room credentials never come from
|
||||
// storage.sync (only onboardingComplete + dismissedHints live there).
|
||||
const localData = await chrome.storage.local.get(['serverUrl', 'useCustomServer', 'roomId', 'password', 'username', 'filterNoise', 'autoSyncNextEpisode', 'sendTabTitle', 'mediaTitlePrivacyMode', 'titlePrivacyMode', 'forceSyncMode', 'browserNotifications', 'autoCopyInvite', 'locale', 'audioSettings', 'activeTab']);
|
||||
const localData = await chrome.storage.local.get(['serverUrl', 'useCustomServer', 'roomId', 'password', 'username', 'filterNoise', 'autoSyncNextEpisode', 'sendTabTitle', 'mediaTitlePrivacyMode', 'titlePrivacyMode', 'forceSyncMode', 'browserNotifications', 'autoCopyInvite', 'locale', 'audioSettings', 'activeTab', 'themeMode']);
|
||||
|
||||
let activeLang = localData.locale;
|
||||
if (!activeLang) {
|
||||
@@ -214,8 +238,10 @@ async function init() {
|
||||
|
||||
await loadLocale(activeLang);
|
||||
translateDOM();
|
||||
localizeThemeSelector(activeLang);
|
||||
|
||||
if (elements.langSelector) elements.langSelector.value = activeLang;
|
||||
if (elements.themeSelector) elements.themeSelector.value = ['dark', 'light'].includes(localData.themeMode) ? localData.themeMode : 'system';
|
||||
|
||||
let username = localData.username;
|
||||
if (!username) {
|
||||
@@ -538,7 +564,7 @@ function updateLastActionUI(state, peers) {
|
||||
peerItem.style.cssText = `display:flex; flex-direction:column; align-items:center; opacity: ${isAcked ? 1 : 0.6};`;
|
||||
|
||||
const dot = document.createElement('div');
|
||||
dot.style.cssText = `width:18px; height:18px; border-radius:50%; background:${color}; color:white; display:flex; align-items:center; justify-content:center; font-size:9px; font-weight:bold; margin-bottom:1px;`;
|
||||
dot.style.cssText = `width:18px; height:18px; border-radius:50%; background:${color}; color:${isAcked ? 'var(--text-on-green)' : 'var(--text-primary)'}; display:flex; align-items:center; justify-content:center; font-size:9px; font-weight:bold; margin-bottom:1px;`;
|
||||
dot.textContent = icon;
|
||||
|
||||
const nameSpan = document.createElement('span');
|
||||
@@ -630,7 +656,10 @@ function renderEmpty(container, type) {
|
||||
copyBtn.title = getMessage('BTN_COPY_INVITE_TOOLTIP');
|
||||
copyBtn.addEventListener('click', () => {
|
||||
navigator.clipboard.writeText(elements.inviteLink.value)
|
||||
.then(() => showToast(getMessage('TOAST_INVITE_COPIED'), 'success', 2000))
|
||||
.then(() => {
|
||||
showToast(getMessage('TOAST_INVITE_COPIED'), 'success', 2000);
|
||||
spawnLeafBurst(copyBtn);
|
||||
})
|
||||
.catch(() => showToast(getMessage('TOAST_COPY_FAILED'), 'error'));
|
||||
});
|
||||
wrapper.appendChild(copyBtn);
|
||||
@@ -725,7 +754,7 @@ function updatePeerList(peers) {
|
||||
// Host Control Mode: show "Solo" badge for peers watching on their own.
|
||||
if (typeof p === 'object' && p.desynced) {
|
||||
const solo = document.createElement('span');
|
||||
solo.style.cssText = 'font-size:10px; color:#fff; background:#c96736; padding:2px 6px; border-radius:6px; font-weight:600;';
|
||||
solo.style.cssText = 'font-size:10px; color:var(--text-on-warm); background:var(--accent-terracotta); padding:2px 6px; border-radius:6px; font-weight:700;';
|
||||
const soloText = getMessage('BADGE_DESYNCED') || 'Solo';
|
||||
solo.textContent = soloText;
|
||||
solo.title = getMessage('TOOLTIP_PEER_DESYNCED') || soloText;
|
||||
@@ -742,7 +771,7 @@ function updatePeerList(peers) {
|
||||
const isController = !isOwner && hcmControllers.includes(pId);
|
||||
if (isOwner || isController) {
|
||||
const roleBadge = document.createElement('span');
|
||||
roleBadge.style.cssText = 'font-size:10px; color:#fff; background:var(--accent); padding:2px 6px; border-radius:6px; font-weight:600;';
|
||||
roleBadge.style.cssText = 'font-size:10px; color:var(--text-on-green); background:var(--accent); padding:2px 6px; border-radius:6px; font-weight:700;';
|
||||
roleBadge.textContent = isOwner ? (getMessage('BADGE_HOST') || 'Host') : (getMessage('BADGE_CONTROLLER') || 'Controller');
|
||||
rightGroup.appendChild(roleBadge);
|
||||
}
|
||||
@@ -755,7 +784,7 @@ function updatePeerList(peers) {
|
||||
btn.title = revoke ? (getMessage('BTN_REVOKE_CONTROL') || 'Revoke') : (getMessage('BTN_GIVE_CONTROL') || 'Give control');
|
||||
btn.addEventListener('mouseenter', () => {
|
||||
btn.style.background = revoke ? 'var(--text-muted)' : 'var(--accent)';
|
||||
btn.style.color = '#fff';
|
||||
btn.style.color = 'var(--text-on-green)';
|
||||
});
|
||||
btn.addEventListener('mouseleave', () => {
|
||||
btn.style.background = 'transparent';
|
||||
@@ -1273,6 +1302,14 @@ if (elements.autoCopyInvite) {
|
||||
});
|
||||
}
|
||||
|
||||
if (elements.themeSelector) {
|
||||
elements.themeSelector.addEventListener('change', () => {
|
||||
const themeMode = elements.themeSelector.value;
|
||||
window.koalaTheme?.setMode(themeMode);
|
||||
chrome.storage.local.set({ themeMode });
|
||||
});
|
||||
}
|
||||
|
||||
if (elements.audioSettingsLink) {
|
||||
elements.audioSettingsLink.addEventListener('click', async (event) => {
|
||||
event.preventDefault();
|
||||
@@ -1305,6 +1342,7 @@ if (elements.langSelector) {
|
||||
await chrome.storage.local.set({ locale: selectedLang });
|
||||
await loadLocale(selectedLang);
|
||||
translateDOM();
|
||||
localizeThemeSelector(selectedLang);
|
||||
configureFooterLinks();
|
||||
await updateFeatureHints();
|
||||
|
||||
@@ -1389,6 +1427,39 @@ function showToast(message, type = 'info', duration = 3000) {
|
||||
setTimeout(() => toast.remove(), duration);
|
||||
}
|
||||
|
||||
// Eucalyptus confetti: a few tiny leaves burst from the given element
|
||||
// (matches the website's copy-invite moment). Subtle by design — few,
|
||||
// tiny, short-lived — and skipped entirely under reduced motion.
|
||||
function spawnLeafBurst(sourceEl) {
|
||||
if (!sourceEl || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||
const rect = sourceEl.getBoundingClientRect();
|
||||
if (!rect.width) return;
|
||||
const originY = rect.top + rect.height / 2;
|
||||
const count = 4 + Math.floor(Math.random() * 3);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const leaf = document.createElement('span');
|
||||
// Three tones of the palette: deep green, sage, a dash of amber
|
||||
const tone = Math.random();
|
||||
leaf.className = 'click-leaf' + (tone < 0.25 ? ' click-leaf-amber' : tone < 0.55 ? ' click-leaf-sage' : '');
|
||||
// Fan out upward to a burst peak spread across the button's width;
|
||||
// the keyframes brake there and let each leaf sink while it rocks.
|
||||
const angle = (-90 + (Math.random() - 0.5) * 150) * Math.PI / 180;
|
||||
const dist = 18 + Math.random() * 24;
|
||||
const dur = 0.85 + Math.random() * 0.4;
|
||||
leaf.style.left = (rect.left + 4 + Math.random() * Math.max(1, rect.width - 8)) + 'px';
|
||||
leaf.style.top = (originY - rect.height * 0.2) + 'px';
|
||||
leaf.style.setProperty('--leaf-x', (Math.cos(angle) * dist).toFixed(1) + 'px');
|
||||
leaf.style.setProperty('--leaf-y', (Math.sin(angle) * dist).toFixed(1) + 'px');
|
||||
leaf.style.setProperty('--leaf-rot', ((Math.random() - 0.5) * 160).toFixed(0) + 'deg');
|
||||
leaf.style.setProperty('--leaf-scale', (0.55 + Math.random() * 0.55).toFixed(2));
|
||||
leaf.style.setProperty('--leaf-dur', dur.toFixed(2) + 's');
|
||||
leaf.style.setProperty('--flutter-dur', (0.35 + Math.random() * 0.3).toFixed(2) + 's');
|
||||
leaf.appendChild(document.createElement('i'));
|
||||
document.body.appendChild(leaf);
|
||||
setTimeout(() => leaf.remove(), dur * 1000 + 150);
|
||||
}
|
||||
}
|
||||
|
||||
function showError(msg) {
|
||||
if (!elements.roomError) return;
|
||||
const currentToken = ++errorToken;
|
||||
@@ -1775,13 +1846,12 @@ elements.copyInvite.addEventListener('click', () => {
|
||||
navigator.clipboard.writeText(elements.inviteLink.value).then(() => {
|
||||
const original = elements.copyInvite.textContent;
|
||||
elements.copyInvite.textContent = '✓';
|
||||
elements.copyInvite.style.background = 'var(--success)';
|
||||
elements.copyInvite.style.color = 'white';
|
||||
elements.copyInvite.classList.add('copy-success');
|
||||
showToast(getMessage('TOAST_INVITE_COPIED'), 'success', 2000);
|
||||
spawnLeafBurst(elements.copyInvite);
|
||||
setTimeout(() => {
|
||||
elements.copyInvite.textContent = original;
|
||||
elements.copyInvite.style.background = '';
|
||||
elements.copyInvite.style.color = '';
|
||||
elements.copyInvite.classList.remove('copy-success');
|
||||
}, 2000);
|
||||
}).catch(() => {
|
||||
showToast(getMessage('TOAST_COPY_FAILED'), 'error');
|
||||
@@ -1793,11 +1863,12 @@ if (elements.syncTabCopyInvite) {
|
||||
navigator.clipboard.writeText(elements.inviteLink.value).then(() => {
|
||||
const original = elements.syncTabCopyInvite.textContent;
|
||||
elements.syncTabCopyInvite.textContent = '✓';
|
||||
elements.syncTabCopyInvite.style.color = 'var(--success)';
|
||||
elements.syncTabCopyInvite.classList.add('copy-success');
|
||||
showToast(getMessage('TOAST_INVITE_COPIED'), 'success', 2000);
|
||||
spawnLeafBurst(elements.syncTabCopyInvite);
|
||||
setTimeout(() => {
|
||||
elements.syncTabCopyInvite.textContent = original;
|
||||
elements.syncTabCopyInvite.style.color = '';
|
||||
elements.syncTabCopyInvite.classList.remove('copy-success');
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
(() => {
|
||||
const systemTheme = window.matchMedia('(prefers-color-scheme: light)');
|
||||
let mode = 'system';
|
||||
|
||||
const normalize = value => ['system', 'dark', 'light'].includes(value) ? value : 'system';
|
||||
const apply = value => {
|
||||
mode = normalize(value);
|
||||
const light = mode === 'light' || (mode === 'system' && systemTheme.matches);
|
||||
document.documentElement.classList.toggle('theme-light', light);
|
||||
document.documentElement.dataset.theme = light ? 'light' : 'dark';
|
||||
document.documentElement.style.colorScheme = light ? 'light' : 'dark';
|
||||
};
|
||||
|
||||
apply('system');
|
||||
window.koalaTheme = {
|
||||
getMode: () => mode,
|
||||
setMode: apply
|
||||
};
|
||||
|
||||
systemTheme.addEventListener('change', () => {
|
||||
if (mode === 'system') apply('system');
|
||||
});
|
||||
|
||||
if (!globalThis.chrome?.storage?.local) return;
|
||||
chrome.storage.local.get(['themeMode'], data => apply(data.themeMode));
|
||||
chrome.storage.onChanged.addListener((changes, area) => {
|
||||
if (area === 'local' && changes.themeMode) apply(changes.themeMode.newValue);
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,146 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="lang-en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>404 – Page Not Found | KoalaSync</title>
|
||||
<!-- Absolute asset paths: Caddy rewrites any missing URL (also nested ones
|
||||
like /foo/bar) to this file, so relative paths would break. -->
|
||||
<link rel="preload" href="/style.min.css" as="style">
|
||||
<link rel="stylesheet" href="/style.min.css">
|
||||
<link rel="icon" type="image/webp" href="/assets/NewLogoIcon_64.webp">
|
||||
<meta name="description" content="This page could not be found.">
|
||||
<meta name="robots" content="noindex, follow">
|
||||
|
||||
<!-- Mobile Browser Theme Styling -->
|
||||
<meta name="theme-color" content="#10190e">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
|
||||
<script src="/lang-init.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="bg-nature" aria-hidden="true">
|
||||
<div class="bg-dusk-tint"></div>
|
||||
<div class="bg-depth-day">
|
||||
<div class="bg-godrays">
|
||||
<span class="godray godray-1"></span>
|
||||
<span class="godray godray-2"></span>
|
||||
<span class="godray godray-3"></span>
|
||||
</div>
|
||||
<div class="bg-canopy"></div>
|
||||
<span class="canopy-arc canopy-arc-1"></span>
|
||||
<span class="canopy-arc canopy-arc-2"></span>
|
||||
<span class="canopy-arc canopy-arc-3"></span>
|
||||
<span class="canopy-arc canopy-arc-4"></span>
|
||||
</div>
|
||||
<div id="bamboo-far">
|
||||
<span class="bamboo-stalk far-1"></span>
|
||||
<span class="bamboo-stalk far-2"></span>
|
||||
<span class="bamboo-stalk far-3"></span>
|
||||
<span class="bamboo-stalk far-4"></span>
|
||||
<span class="bamboo-stalk far-5"></span>
|
||||
</div>
|
||||
<div id="bamboo-near">
|
||||
<div class="bamboo-stalk near-1">
|
||||
<i class="bamboo-node node-1"></i>
|
||||
<i class="bamboo-node node-2"></i>
|
||||
<i class="bamboo-node node-3"></i>
|
||||
<i class="bamboo-leaf leaf-1"></i>
|
||||
<i class="bamboo-leaf leaf-2"></i>
|
||||
</div>
|
||||
<div class="bamboo-stalk near-2">
|
||||
<i class="bamboo-node node-1"></i>
|
||||
<i class="bamboo-node node-2"></i>
|
||||
<i class="bamboo-node node-3"></i>
|
||||
<i class="bamboo-leaf leaf-1"></i>
|
||||
</div>
|
||||
<div class="bamboo-stalk near-3">
|
||||
<i class="bamboo-node node-1"></i>
|
||||
<i class="bamboo-node node-2"></i>
|
||||
<i class="bamboo-node node-3"></i>
|
||||
<i class="bamboo-leaf leaf-1"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span class="fall-leaf fall-leaf-1"><i></i></span>
|
||||
<span class="fall-leaf fall-leaf-2"><i></i></span>
|
||||
<span class="fall-leaf fall-leaf-3"><i></i></span>
|
||||
<span class="fall-leaf fall-leaf-4"><i></i></span>
|
||||
<span class="fall-leaf fall-leaf-5"><i></i></span>
|
||||
<span class="fall-leaf fall-leaf-6"><i></i></span>
|
||||
<span class="fall-leaf fall-leaf-7"><i></i></span>
|
||||
<span class="fall-leaf fall-leaf-8"><i></i></span>
|
||||
<span class="bg-grass bg-grass-1"></span>
|
||||
<span class="bg-grass bg-grass-2"></span>
|
||||
<span class="bg-grass bg-grass-3"></span>
|
||||
<span class="bg-grass bg-grass-4"></span>
|
||||
<div class="bg-depth-dusk">
|
||||
<div class="bg-mist bg-mist-1"></div>
|
||||
<div class="bg-mist bg-mist-2"></div>
|
||||
<div class="bg-horizon"></div>
|
||||
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
|
||||
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
|
||||
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
|
||||
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
|
||||
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
|
||||
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
|
||||
</div>
|
||||
<div class="bg-light-sweep"></div>
|
||||
<div class="bg-grain"></div>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<div class="container nav-content">
|
||||
<a href="/" class="logo-area" style="text-decoration: none;">
|
||||
<img src="/assets/NewLogoIcon.webp" alt="KoalaSync Logo" width="40" height="40">
|
||||
<span>KoalaSync</span>
|
||||
</a>
|
||||
<div class="nav-links">
|
||||
<a href="/" style="display: inline-flex; align-items: center; gap: 6px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="width: 16px; height: 16px; display: block;"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
|
||||
<span>Home</span>
|
||||
</a>
|
||||
<a href="https://github.com/Shik3i/KoalaSync" target="_blank" rel="noopener" style="display: inline-flex; align-items: center; gap: 6px;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" aria-hidden="true" style="display: block;"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="legal-content">
|
||||
<div class="legal-card" data-reveal style="padding: 2.5rem 2rem; text-align: center;">
|
||||
<div style="display: flex; justify-content: center;">
|
||||
<img src="/assets/KoalaSearching.webp" alt="A cute koala looking through a telescope, searching for the missing page" class="legal-mascot" width="180" height="180">
|
||||
</div>
|
||||
<h1 style="margin-bottom: 0.5rem;">404</h1>
|
||||
<p style="text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem; border-bottom: 1px solid var(--glass-border); padding-bottom: 1.5rem; margin-bottom: 1.5rem;">
|
||||
Page not found
|
||||
</p>
|
||||
<p style="max-width: 34rem; margin: 0 auto;">
|
||||
This page wandered off into the bamboo forest. Our koala is still looking for it — in the meantime, head back to safety.
|
||||
</p>
|
||||
<div style="display: flex; justify-content: center; gap: 1rem; margin-top: 2rem; flex-wrap: wrap;">
|
||||
<a href="/" class="btn btn-primary">
|
||||
Back to home
|
||||
</a>
|
||||
<a href="https://github.com/Shik3i/KoalaSync/issues" target="_blank" rel="noopener" class="btn btn-secondary">
|
||||
Report a broken link
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p>© 2026 KoalaSync. Open source under the MIT License.</p>
|
||||
<div style="margin-top: 1.5rem; font-size: 0.8rem; display: flex; justify-content: center; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
|
||||
<a href="/imprint" style="color: var(--text-muted); text-decoration: none;">Legal Notice</a>
|
||||
<a href="/privacy" style="color: var(--text-muted); text-decoration: none;">Privacy Policy</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/app.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -75,6 +75,13 @@ sync.koalastuff.net {
|
||||
file_server
|
||||
encode zstd gzip
|
||||
|
||||
# Themed 404 page (Caddy returns an empty 404 without this)
|
||||
handle_errors {
|
||||
@notfound expression {err.status_code} == 404
|
||||
rewrite @notfound /404.html
|
||||
file_server
|
||||
}
|
||||
|
||||
@static {
|
||||
file
|
||||
path *.ico *.css *.js *.png *.svg *.webp *.avif
|
||||
|
||||
+91
-4
@@ -184,6 +184,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
// Scroll Reveal Logic (IntersectionObserver for performance)
|
||||
const revealElements = document.querySelectorAll('[data-reveal]');
|
||||
|
||||
// Hash navigation must never land on an intentionally transparent state.
|
||||
// Reveal the destination before the smooth scroll begins; the observer
|
||||
// continues to animate sections reached through ordinary scrolling.
|
||||
const revealHashTarget = () => {
|
||||
const id = decodeURIComponent(window.location.hash.slice(1));
|
||||
const target = id ? document.getElementById(id) : null;
|
||||
if (!target) return;
|
||||
if (target.matches('[data-reveal]')) target.classList.add('revealed');
|
||||
target.querySelectorAll('[data-reveal]').forEach(el => el.classList.add('revealed'));
|
||||
};
|
||||
revealHashTarget();
|
||||
window.addEventListener('hashchange', revealHashTarget);
|
||||
|
||||
if ('IntersectionObserver' in window) {
|
||||
const revealObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
@@ -193,7 +206,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
});
|
||||
}, {
|
||||
rootMargin: '0px 0px -30px 0px',
|
||||
rootMargin: '0px 0px 12% 0px',
|
||||
threshold: 0.05
|
||||
});
|
||||
|
||||
@@ -231,6 +244,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
// value crossfades the scene from sunlit canopy into misty dusk, and on
|
||||
// pointer devices the layers tilt slightly toward the cursor.
|
||||
const bambooFar = document.getElementById('bamboo-far');
|
||||
const bambooMid = document.getElementById('bamboo-mid');
|
||||
const bambooNear = document.getElementById('bamboo-near');
|
||||
const forestScene = document.querySelector('.bg-nature');
|
||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
@@ -241,6 +255,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const fireflies = Array.from(document.querySelectorAll('.firefly-wrap'), (el) => ({ el, x: 0, y: 0 }));
|
||||
const canHover = window.matchMedia('(hover: hover)').matches;
|
||||
let mouseX = 0;
|
||||
let mouseY = 0;
|
||||
let pointerX = -9999;
|
||||
let pointerY = -9999;
|
||||
let depthStep = '';
|
||||
@@ -251,9 +266,16 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const doc = document.documentElement;
|
||||
const maxScroll = Math.max(1, doc.scrollHeight - window.innerHeight);
|
||||
const depth = Math.min(1, window.scrollY / maxScroll);
|
||||
const shift = window.innerHeight * 0.14;
|
||||
bambooFar.style.transform = `translate(${(-mouseX * 5).toFixed(1)}px, ${(depth * shift).toFixed(1)}px)`;
|
||||
bambooNear.style.transform = `translate(${(mouseX * 11).toFixed(1)}px, ${(-depth * shift).toFixed(1)}px)`;
|
||||
// Couple the forest directly to the scroll distance so it visibly
|
||||
// travels down instead of being overpowered by upward-moving content.
|
||||
const shift = Math.min(window.innerHeight * 0.55, window.scrollY * 0.14);
|
||||
// All bamboo layers travel in the same vertical direction. Depth
|
||||
// comes from their different speeds; reversing one layer makes
|
||||
// the forest look mechanically disconnected while scrolling.
|
||||
bambooFar.style.transform = `translate(${(-mouseX * 5).toFixed(1)}px, ${(shift * 0.42).toFixed(1)}px)`;
|
||||
bambooNear.style.transform = `translate(${(mouseX * 11).toFixed(1)}px, ${shift.toFixed(1)}px)`;
|
||||
if (bambooMid) bambooMid.style.transform = `translate(${(mouseX * 4).toFixed(1)}px, ${(shift * 0.7).toFixed(1)}px)`;
|
||||
if (depthDay) depthDay.style.transform = `translate(${(-mouseX * 2.5).toFixed(1)}px, ${(mouseY * 1.5).toFixed(1)}px)`;
|
||||
if (depthDay) depthDay.style.opacity = (1 - depth * 0.75).toFixed(3);
|
||||
if (depthDusk) depthDusk.style.opacity = (0.35 + depth * 0.65).toFixed(3);
|
||||
if (duskTint) duskTint.style.opacity = (depth * 0.85).toFixed(3);
|
||||
@@ -316,6 +338,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (canHover) {
|
||||
window.addEventListener('pointermove', (e) => {
|
||||
mouseX = (e.clientX / window.innerWidth - 0.5) * 2;
|
||||
mouseY = (e.clientY / window.innerHeight - 0.5) * 2;
|
||||
pointerX = e.clientX;
|
||||
pointerY = e.clientY;
|
||||
requestForestFrame();
|
||||
@@ -345,6 +368,68 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Eucalyptus click confetti: leaves burst from wherever the visitor
|
||||
// presses. Buttons and other controls shed leaves along their whole
|
||||
// width; anywhere else a small fan rises from the pointer itself. The
|
||||
// hero walkthrough's scripted cursor calls burstFromElement directly so
|
||||
// its fake clicks scatter leaves too. Rate-capped, pointer-events:none —
|
||||
// it can never block a click or flood the DOM.
|
||||
let burstFromElement = () => {};
|
||||
if (!prefersReducedMotion) {
|
||||
const spawnLeaf = (x, y) => {
|
||||
const leaf = document.createElement('span');
|
||||
// Three tones of the palette: deep green, sage, a dash of amber
|
||||
const tone = Math.random();
|
||||
leaf.className = 'click-leaf' + (tone < 0.25 ? ' click-leaf-amber' : tone < 0.55 ? ' click-leaf-sage' : '');
|
||||
// Fan out upward to a burst peak; the keyframes brake there and
|
||||
// let the leaf sink past it while the inner element rocks.
|
||||
const angle = (-90 + (Math.random() - 0.5) * 150) * Math.PI / 180;
|
||||
const dist = 26 + Math.random() * 38;
|
||||
const dur = 0.9 + Math.random() * 0.5;
|
||||
leaf.style.left = x + 'px';
|
||||
leaf.style.top = y + 'px';
|
||||
leaf.style.setProperty('--leaf-x', (Math.cos(angle) * dist).toFixed(1) + 'px');
|
||||
leaf.style.setProperty('--leaf-y', (Math.sin(angle) * dist).toFixed(1) + 'px');
|
||||
leaf.style.setProperty('--leaf-rot', ((Math.random() - 0.5) * 160).toFixed(0) + 'deg');
|
||||
leaf.style.setProperty('--leaf-scale', (0.55 + Math.random() * 0.6).toFixed(2));
|
||||
leaf.style.setProperty('--leaf-dur', dur.toFixed(2) + 's');
|
||||
leaf.style.setProperty('--flutter-dur', (0.4 + Math.random() * 0.35).toFixed(2) + 's');
|
||||
leaf.appendChild(document.createElement('i'));
|
||||
document.body.appendChild(leaf);
|
||||
setTimeout(() => leaf.remove(), dur * 1000 + 150);
|
||||
};
|
||||
|
||||
burstFromElement = (el) => {
|
||||
if (!el) return;
|
||||
const r = el.getBoundingClientRect();
|
||||
if (!r.width || r.bottom < 0 || r.top > window.innerHeight) return;
|
||||
// Leaf count scales with the control's width so a wide demo card
|
||||
// sheds a few more than a compact icon button, capped for subtlety.
|
||||
const count = Math.max(4, Math.min(9, Math.round(r.width / 26)));
|
||||
for (let i = 0; i < count; i++) {
|
||||
const x = r.left + 4 + Math.random() * Math.max(1, r.width - 8);
|
||||
// Spawn along the upper edge, like leaves knocked off the top
|
||||
const y = r.top + r.height * (0.1 + Math.random() * 0.4);
|
||||
spawnLeaf(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
let lastBurst = 0;
|
||||
document.addEventListener('pointerdown', (e) => {
|
||||
if (e.button !== 0 || !e.isPrimary) return;
|
||||
const now = Date.now();
|
||||
if (now - lastBurst < 180) return;
|
||||
lastBurst = now;
|
||||
const control = e.target.closest('button, [role="button"], .btn, .mock-tab, select, .demo-progress');
|
||||
if (control) {
|
||||
burstFromElement(control);
|
||||
} else {
|
||||
const count = 4 + Math.floor(Math.random() * 3);
|
||||
for (let i = 0; i < count; i++) spawnLeaf(e.clientX, e.clientY);
|
||||
}
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
// Invite Detection & Bridge
|
||||
const checkInvite = () => {
|
||||
const isJoinPage = window.location.pathname.includes('join');
|
||||
@@ -1136,6 +1221,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
await wait(180);
|
||||
if (userTookOver || demoRunId !== myRunId) return false;
|
||||
if (action) action(); else el.click();
|
||||
// The scripted cursor's clicks scatter leaves like real ones
|
||||
burstFromElement(el);
|
||||
await wait(320 + (pause || 0));
|
||||
return !userTookOver && demoRunId === myRunId;
|
||||
};
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
+7
-4
@@ -371,7 +371,8 @@ async function compile() {
|
||||
{ src: 'impressum-de.html', dest: 'de/impressum.html' },
|
||||
{ src: 'datenschutz-de.html', dest: 'de/datenschutz.html' },
|
||||
{ src: 'impressum.html', dest: 'impressum.html' },
|
||||
{ src: 'datenschutz.html', dest: 'datenschutz.html' }
|
||||
{ src: 'datenschutz.html', dest: 'datenschutz.html' },
|
||||
{ src: '404.html', dest: '404.html' }
|
||||
];
|
||||
for (const mapping of staticMappings) {
|
||||
const src = path.join(websiteDir, mapping.src);
|
||||
@@ -457,13 +458,15 @@ async function compile() {
|
||||
let html = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// 8a. Replace hashed asset refs and inject SRI (Subresource Integrity)
|
||||
html = html.replace(/(<link\b[^>]*?\bhref=")((?:\.\.\/)*)style\.min\.css"/g, (m, before, prefix) => {
|
||||
// The prefix is either any number of "../" segments or a single "/"
|
||||
// (404.html must use absolute paths: it is served for arbitrary URLs).
|
||||
html = html.replace(/(<link\b[^>]*?\bhref=")((?:\.\.\/)*\/?)style\.min\.css"/g, (m, before, prefix) => {
|
||||
return `${before}${prefix}${styleName}" integrity="${styleSRI}" crossorigin="anonymous"`;
|
||||
});
|
||||
html = html.replace(/(<script\b[^>]*?\bsrc=")((?:\.\.\/)*)app\.min\.js"/g, (m, before, prefix) => {
|
||||
html = html.replace(/(<script\b[^>]*?\bsrc=")((?:\.\.\/)*\/?)app\.min\.js"/g, (m, before, prefix) => {
|
||||
return `${before}${prefix}${appName}" integrity="${appSRI}" crossorigin="anonymous"`;
|
||||
});
|
||||
html = html.replace(/(<script\b[^>]*?\bsrc=")((?:\.\.\/)*)lang-init\.min\.js"/g, (m, before, prefix) => {
|
||||
html = html.replace(/(<script\b[^>]*?\bsrc=")((?:\.\.\/)*\/?)lang-init\.min\.js"/g, (m, before, prefix) => {
|
||||
return `${before}${prefix}${langName}" integrity="${langSRI}" crossorigin="anonymous"`;
|
||||
});
|
||||
|
||||
|
||||
+124
-124
@@ -3,31 +3,31 @@
|
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/imprint</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.3</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/privacy</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.3</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/impressum</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.3</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/datenschutz</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.3</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -49,7 +49,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -71,7 +71,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/fr/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -93,7 +93,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/es/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -115,7 +115,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt-BR/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -137,7 +137,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ru/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -159,7 +159,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/it/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -181,7 +181,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pl/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -203,7 +203,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/tr/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -225,7 +225,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/nl/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -247,7 +247,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ja/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -269,7 +269,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ko/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -291,7 +291,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/zh/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -313,7 +313,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/uk/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -335,7 +335,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt/</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
|
||||
@@ -357,7 +357,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -379,7 +379,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -401,7 +401,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/fr/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -423,7 +423,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/es/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -445,7 +445,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt-BR/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -467,7 +467,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ru/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -489,7 +489,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/it/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -511,7 +511,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pl/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -533,7 +533,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/tr/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -555,7 +555,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/nl/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -577,7 +577,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ja/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -599,7 +599,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ko/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -621,7 +621,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/zh/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -643,7 +643,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/uk/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -665,7 +665,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt/alternatives</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
|
||||
@@ -687,7 +687,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -709,7 +709,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -731,7 +731,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/fr/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -753,7 +753,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/es/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -775,7 +775,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt-BR/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -797,7 +797,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ru/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -819,7 +819,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/it/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -841,7 +841,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pl/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -863,7 +863,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/tr/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -885,7 +885,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/nl/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -907,7 +907,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ja/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -929,7 +929,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ko/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -951,7 +951,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/zh/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -973,7 +973,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/uk/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -995,7 +995,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt/alternatives/teleparty</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
|
||||
@@ -1017,7 +1017,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1039,7 +1039,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1061,7 +1061,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/fr/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1083,7 +1083,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/es/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1105,7 +1105,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt-BR/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1127,7 +1127,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ru/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1149,7 +1149,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/it/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1171,7 +1171,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pl/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1193,7 +1193,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/tr/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1215,7 +1215,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/nl/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1237,7 +1237,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ja/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1259,7 +1259,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ko/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1281,7 +1281,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/zh/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1303,7 +1303,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/uk/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1325,7 +1325,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt/alternatives/screen-sharing</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
|
||||
@@ -1347,7 +1347,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1369,7 +1369,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1391,7 +1391,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/fr/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1413,7 +1413,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/es/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1435,7 +1435,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt-BR/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1457,7 +1457,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ru/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1479,7 +1479,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/it/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1501,7 +1501,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pl/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1523,7 +1523,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/tr/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1545,7 +1545,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/nl/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1567,7 +1567,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ja/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1589,7 +1589,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ko/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1611,7 +1611,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/zh/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1633,7 +1633,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/uk/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1655,7 +1655,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt/alternatives/watch2gether</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/watch2gether"/>
|
||||
@@ -1677,7 +1677,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1699,7 +1699,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1721,7 +1721,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/fr/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1743,7 +1743,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/es/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1765,7 +1765,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt-BR/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1787,7 +1787,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ru/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1809,7 +1809,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/it/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1831,7 +1831,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pl/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1853,7 +1853,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/tr/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1875,7 +1875,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/nl/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1897,7 +1897,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ja/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1919,7 +1919,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ko/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1941,7 +1941,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/zh/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1963,7 +1963,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/uk/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -1985,7 +1985,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt/alternatives/scener</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener"/>
|
||||
@@ -2007,7 +2007,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2029,7 +2029,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2051,7 +2051,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/fr/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2073,7 +2073,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/es/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2095,7 +2095,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt-BR/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2117,7 +2117,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ru/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2139,7 +2139,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/it/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2161,7 +2161,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pl/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2183,7 +2183,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/tr/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2205,7 +2205,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/nl/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2227,7 +2227,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ja/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2249,7 +2249,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ko/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2271,7 +2271,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/zh/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2293,7 +2293,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/uk/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2315,7 +2315,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt/alternatives/kosmi</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi"/>
|
||||
@@ -2337,7 +2337,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2359,7 +2359,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/de/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2381,7 +2381,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/fr/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2403,7 +2403,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/es/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2425,7 +2425,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt-BR/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2447,7 +2447,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ru/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2469,7 +2469,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/it/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2491,7 +2491,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pl/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2513,7 +2513,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/tr/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2535,7 +2535,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/nl/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2557,7 +2557,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ja/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2579,7 +2579,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/ko/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2601,7 +2601,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/zh/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2623,7 +2623,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/uk/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
@@ -2645,7 +2645,7 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://sync.koalastuff.net/pt/alternatives/twoseven</loc>
|
||||
<lastmod>2026-07-10</lastmod>
|
||||
<lastmod>2026-07-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven"/>
|
||||
|
||||
+382
-30
@@ -163,8 +163,8 @@ body {
|
||||
|
||||
#bamboo-far .bamboo-stalk {
|
||||
position: absolute;
|
||||
top: -20%;
|
||||
height: 140%;
|
||||
top: -70%;
|
||||
height: 240%;
|
||||
border-radius: 999px;
|
||||
filter: blur(5.5px);
|
||||
transition: filter 1.2s ease;
|
||||
@@ -183,8 +183,8 @@ body {
|
||||
#bamboo-far::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -20%;
|
||||
height: 140%;
|
||||
top: -70%;
|
||||
height: 240%;
|
||||
border-radius: 999px;
|
||||
filter: blur(8px);
|
||||
opacity: 0.28;
|
||||
@@ -199,6 +199,71 @@ body {
|
||||
.bg-nature.depth-mid #bamboo-far .bamboo-stalk { filter: blur(6.5px); }
|
||||
.bg-nature.depth-deep #bamboo-far .bamboo-stalk { filter: blur(8px); }
|
||||
|
||||
/* (a2) Mid bamboo layer: sits between far and near with its own parallax
|
||||
rate (app.js) and half the near layer's sway, so the three layers drift
|
||||
apart subtly instead of moving as one sheet. Landing page only — the
|
||||
static pages keep the lighter two-layer scene. */
|
||||
#bamboo-mid {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
#bamboo-mid .bamboo-stalk {
|
||||
position: absolute;
|
||||
top: -70%;
|
||||
height: 240%;
|
||||
border-radius: 999px;
|
||||
filter: blur(2.5px);
|
||||
transition: filter 1.2s ease;
|
||||
/* Segment rings + a soft left-of-centre sheen give the stalks culm
|
||||
structure without any extra elements; the blur keeps both faint. */
|
||||
background:
|
||||
repeating-linear-gradient(180deg,
|
||||
transparent 0, transparent 84px,
|
||||
oklch(0.46 0.075 145 / 0.28) 84px, oklch(0.46 0.075 145 / 0.28) 87px),
|
||||
linear-gradient(90deg, transparent 14%, oklch(0.58 0.07 145 / 0.14) 38%, transparent 68%),
|
||||
linear-gradient(180deg, oklch(0.36 0.06 145 / 0.45), oklch(0.25 0.045 140 / 0.2));
|
||||
transform-origin: bottom center;
|
||||
animation: bambooSwayHalf 13s ease-in-out infinite;
|
||||
}
|
||||
|
||||
#bamboo-mid .mid-1 { left: 17%; width: 15px; animation-duration: 12s; }
|
||||
#bamboo-mid .mid-2 { left: 31%; width: 9px; animation-delay: -5s; opacity: 0.55; }
|
||||
#bamboo-mid .mid-3 { right: 15.5%; width: 17px; animation-duration: 14.5s; animation-delay: -8s; }
|
||||
#bamboo-mid .mid-4 { right: 30%; width: 8px; animation-duration: 11.5s; animation-delay: -2.5s; opacity: 0.5; }
|
||||
|
||||
/* A few leaves sprout from the mid stalks (pseudo-elements, so they ride
|
||||
the stalk's sway for free). The slim centre stalks stay bare. */
|
||||
#bamboo-mid .bamboo-stalk::before,
|
||||
#bamboo-mid .bamboo-stalk::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
height: 11px;
|
||||
border-radius: 0 100% 0 100%;
|
||||
background: oklch(0.5 0.1 145 / 0.32);
|
||||
}
|
||||
|
||||
#bamboo-mid .mid-1::before { top: 31%; left: 13px; transform: rotate(20deg); }
|
||||
#bamboo-mid .mid-1::after { top: 55%; left: -26px; transform: rotate(-158deg); width: 20px; height: 9px; }
|
||||
#bamboo-mid .mid-3::before { top: 26%; left: -27px; transform: rotate(-156deg); }
|
||||
#bamboo-mid .mid-3::after { top: 49%; left: 15px; transform: rotate(24deg); width: 21px; height: 10px; }
|
||||
#bamboo-mid .mid-2::before,
|
||||
#bamboo-mid .mid-2::after,
|
||||
#bamboo-mid .mid-4::before,
|
||||
#bamboo-mid .mid-4::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bg-nature.depth-mid #bamboo-mid .bamboo-stalk { filter: blur(3.5px); }
|
||||
.bg-nature.depth-deep #bamboo-mid .bamboo-stalk { filter: blur(4.5px); }
|
||||
|
||||
@keyframes bambooSwayHalf {
|
||||
0%, 100% { transform: rotate(0); }
|
||||
50% { transform: rotate(calc(var(--sway, 1.2deg) * 0.5)); }
|
||||
}
|
||||
|
||||
/* (b) Near bamboo layer: sharp stalks with nodes and leaves, gentle sway */
|
||||
#bamboo-near {
|
||||
position: absolute;
|
||||
@@ -208,10 +273,14 @@ body {
|
||||
|
||||
#bamboo-near .bamboo-stalk {
|
||||
position: absolute;
|
||||
top: -20%;
|
||||
height: 140%;
|
||||
top: -70%;
|
||||
height: 240%;
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(180deg, oklch(0.4 0.07 145 / 0.55), oklch(0.26 0.05 140 / 0.25));
|
||||
/* Vertical sheen over the culm gradient: reads as light from the
|
||||
canopy catching the rounded stalk instead of a flat strip. */
|
||||
background:
|
||||
linear-gradient(90deg, transparent 12%, oklch(0.62 0.08 145 / 0.18) 36%, transparent 64%),
|
||||
linear-gradient(180deg, oklch(0.4 0.07 145 / 0.55), oklch(0.26 0.05 140 / 0.25));
|
||||
transform-origin: bottom center;
|
||||
animation: bambooSway 10s ease-in-out infinite;
|
||||
}
|
||||
@@ -375,13 +444,31 @@ body {
|
||||
.canopy-arc-3 { top: -4px; left: 61%; width: 46px; height: 14px; transform: rotate(-3deg); }
|
||||
.canopy-arc-4 { top: -2px; left: 84%; width: 30px; height: 10px; transform: rotate(7deg); background: oklch(0.33 0.06 145 / 0.4); }
|
||||
|
||||
/* (f) Undergrowth: grass blades in the lower corners */
|
||||
/* (f) Undergrowth: grass blades in the lower corners. Each blade carries a
|
||||
shorter companion blade (::before) so the corners read as small tufts. */
|
||||
.bg-grass {
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
transform-origin: bottom;
|
||||
}
|
||||
|
||||
.bg-grass::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 72%;
|
||||
height: 55%;
|
||||
border-radius: inherit;
|
||||
background: inherit;
|
||||
opacity: 0.7;
|
||||
transform-origin: bottom;
|
||||
}
|
||||
|
||||
.bg-grass-1::before { left: -5px; transform: rotate(-13deg); }
|
||||
.bg-grass-2::before { left: 4px; transform: rotate(11deg); }
|
||||
.bg-grass-3::before { right: -5px; transform: rotate(12deg); }
|
||||
.bg-grass-4::before { right: 4px; transform: rotate(-9deg); }
|
||||
|
||||
.bg-grass-1 { left: 1.5%; width: 6px; height: 52px; border-radius: 100% 0 0 0; background: oklch(0.38 0.07 145 / 0.4); transform: rotate(-9deg); }
|
||||
.bg-grass-2 { left: 3.2%; width: 5px; height: 38px; border-radius: 100% 0 0 0; background: oklch(0.35 0.07 145 / 0.3); transform: rotate(-12deg); }
|
||||
.bg-grass-3 { right: 2%; width: 6px; height: 56px; border-radius: 0 100% 0 0; background: oklch(0.4 0.07 145 / 0.4); transform: rotate(8deg); }
|
||||
@@ -508,6 +595,83 @@ body {
|
||||
100% { translate: -14px -18px; }
|
||||
}
|
||||
|
||||
/* Day/night: fireflies belong to the dark theme. By daylight the same six
|
||||
spots are visited by small butterflies instead — the wrapper (and with it
|
||||
the cursor-shy push and the section greeting) is shared, only the inner
|
||||
dot is redressed. Only animation-name is swapped so the per-firefly
|
||||
duration/delay variety above keeps applying to the butterflies. */
|
||||
html.theme-light .firefly {
|
||||
position: relative;
|
||||
width: 2px;
|
||||
height: 9px;
|
||||
border-radius: 1px;
|
||||
background: oklch(0.35 0.05 140 / 0.8);
|
||||
box-shadow: none;
|
||||
opacity: 0.85;
|
||||
animation-name: butterflyBob, fireflyWander;
|
||||
}
|
||||
|
||||
html.theme-light .firefly::before,
|
||||
html.theme-light .firefly::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
width: 7px;
|
||||
height: 10px;
|
||||
background: oklch(0.62 0.14 45 / 0.7);
|
||||
animation: wingFlap 0.5s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
html.theme-light .firefly::before {
|
||||
left: -6px;
|
||||
border-radius: 90% 10% 60% 40%;
|
||||
transform-origin: 100% 55%;
|
||||
}
|
||||
|
||||
html.theme-light .firefly::after {
|
||||
right: -6px;
|
||||
border-radius: 10% 90% 40% 60%;
|
||||
transform-origin: 0% 55%;
|
||||
animation-name: wingFlapR;
|
||||
}
|
||||
|
||||
/* Every other butterfly wears the sage of the canopy and flaps lazier */
|
||||
html.theme-light .fw-2 .firefly::before,
|
||||
html.theme-light .fw-2 .firefly::after,
|
||||
html.theme-light .fw-4 .firefly::before,
|
||||
html.theme-light .fw-4 .firefly::after,
|
||||
html.theme-light .fw-6 .firefly::before,
|
||||
html.theme-light .fw-6 .firefly::after {
|
||||
background: oklch(0.52 0.12 150 / 0.55);
|
||||
animation-duration: 0.62s;
|
||||
}
|
||||
|
||||
@keyframes butterflyBob {
|
||||
0%, 100% { transform: translateY(0) rotate(-4deg); }
|
||||
50% { transform: translateY(-8px) rotate(5deg); }
|
||||
}
|
||||
|
||||
@keyframes wingFlap {
|
||||
from { transform: scaleX(1) rotate(-6deg); }
|
||||
to { transform: scaleX(0.3) rotate(8deg); }
|
||||
}
|
||||
|
||||
@keyframes wingFlapR {
|
||||
from { transform: scaleX(1) rotate(6deg); }
|
||||
to { transform: scaleX(0.3) rotate(-8deg); }
|
||||
}
|
||||
|
||||
/* By day the dusk layer must not dim the butterflies with scroll depth
|
||||
(the JS crossfade keeps writing inline opacity for the dark theme), and
|
||||
the warm horizon glow steps back so it reads as haze, not dusk. */
|
||||
html.theme-light .bg-depth-dusk {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
html.theme-light .bg-horizon {
|
||||
background: radial-gradient(ellipse 60% 100% at 50% 100%, oklch(0.8 0.08 60 / 0.1), transparent 70%);
|
||||
}
|
||||
|
||||
/* (j) Wandering light sweep */
|
||||
.bg-light-sweep {
|
||||
position: absolute;
|
||||
@@ -525,6 +689,20 @@ body {
|
||||
100% { transform: translate(20%, 20%) rotate(8deg); }
|
||||
}
|
||||
|
||||
/* (j2) Corner vignette: pulls the eye toward the content and grounds the
|
||||
scene — the forest darkens gently toward the edges like real depth. */
|
||||
.bg-nature::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background: radial-gradient(ellipse 120% 90% at 50% 38%, transparent 55%, oklch(0.10 0.025 142 / 0.4) 100%);
|
||||
}
|
||||
|
||||
html.theme-light .bg-nature::after {
|
||||
background: radial-gradient(ellipse 120% 90% at 50% 38%, transparent 62%, oklch(0.78 0.03 120 / 0.3) 100%);
|
||||
}
|
||||
|
||||
/* (k) Film grain (SVG feTurbulence, no external assets) */
|
||||
.bg-grain {
|
||||
position: absolute;
|
||||
@@ -543,6 +721,7 @@ body {
|
||||
.fall-leaf-8,
|
||||
.bg-godrays,
|
||||
.bg-light-sweep,
|
||||
#bamboo-mid,
|
||||
#bamboo-far .far-4,
|
||||
#bamboo-far .far-5,
|
||||
#bamboo-near .near-3 {
|
||||
@@ -550,7 +729,67 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
/* (l) Click confetti: a small handful of eucalyptus leaves bursts from
|
||||
wherever the visitor presses (spawned by app.js). Built like the falling
|
||||
leaves above — the outer span owns the flight path (fast burst that
|
||||
brakes at its peak, then sinks), the inner leaf rocks around its stem
|
||||
the whole way down. Deliberately subtle: few, tiny, short-lived. */
|
||||
.click-leaf {
|
||||
position: fixed;
|
||||
z-index: 3000;
|
||||
margin: -6px 0 0 -4px;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
animation: leafBurst var(--leaf-dur, 1.1s) forwards;
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
.click-leaf i {
|
||||
display: block;
|
||||
width: 8px;
|
||||
height: 12px;
|
||||
border-radius: 0 70% 0 70%;
|
||||
background: linear-gradient(135deg, oklch(0.62 0.12 150 / 0.95), oklch(0.45 0.09 145 / 0.85));
|
||||
transform: rotate(var(--leaf-rot, 0deg));
|
||||
animation: leafRock var(--flutter-dur, 0.6s) ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
.click-leaf-sage i {
|
||||
background: linear-gradient(135deg, oklch(0.72 0.09 140 / 0.9), oklch(0.55 0.08 145 / 0.8));
|
||||
}
|
||||
|
||||
.click-leaf-amber i {
|
||||
background: linear-gradient(135deg, oklch(0.68 0.14 55 / 0.95), oklch(0.55 0.13 40 / 0.85));
|
||||
}
|
||||
|
||||
/* Two-phase flight: --leaf-x/--leaf-y is the burst PEAK; from there each
|
||||
leaf loses momentum and sinks past it while fading. Per-segment timing
|
||||
functions give the fast pop and the gentle fall. */
|
||||
@keyframes leafBurst {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate(0, 0) scale(var(--leaf-scale, 1));
|
||||
animation-timing-function: cubic-bezier(0.16, 0.84, 0.44, 1);
|
||||
}
|
||||
10% { opacity: 1; }
|
||||
45% {
|
||||
opacity: 1;
|
||||
transform: translate(var(--leaf-x, 0), var(--leaf-y, -20px)) scale(var(--leaf-scale, 1));
|
||||
animation-timing-function: cubic-bezier(0.55, 0.06, 0.68, 0.19);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translate(calc(var(--leaf-x, 0) * 1.4), calc(var(--leaf-y, -20px) + 44px)) scale(calc(var(--leaf-scale, 1) * 0.92));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes leafRock {
|
||||
from { transform: rotate(calc(var(--leaf-rot, 0deg) - 24deg)); }
|
||||
to { transform: rotate(calc(var(--leaf-rot, 0deg) + 24deg)); }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.click-leaf { display: none; }
|
||||
.bg-nature *,
|
||||
.bg-nature *::before,
|
||||
.bg-nature *::after {
|
||||
@@ -771,6 +1010,7 @@ html.theme-light .bg-nature {
|
||||
html.theme-light .bg-canopy,
|
||||
html.theme-light .canopy-arc,
|
||||
html.theme-light #bamboo-far .bamboo-stalk,
|
||||
html.theme-light #bamboo-mid .bamboo-stalk,
|
||||
html.theme-light #bamboo-near .bamboo-stalk,
|
||||
html.theme-light .bg-grass {
|
||||
opacity: 0.45;
|
||||
@@ -1158,14 +1398,16 @@ html.theme-light .koala-speech-bubble::after {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.btn-primary {
|
||||
background: var(--accent-green);
|
||||
color: var(--text-on-green);
|
||||
box-shadow: 0 10px 15px -3px var(--accent-glow);
|
||||
background: linear-gradient(135deg, oklch(0.48 0.13 150), oklch(0.39 0.10 145));
|
||||
color: #fff;
|
||||
border: 1px solid oklch(0.72 0.11 95 / 0.24);
|
||||
box-shadow: 0 12px 24px -8px oklch(0.38 0.11 148 / 0.65), 0 0 0 1px oklch(0.80 0.08 90 / 0.06) inset;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(135deg, oklch(0.54 0.14 150), oklch(0.44 0.11 145));
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 20px 25px -5px var(--accent-glow);
|
||||
box-shadow: 0 18px 32px -8px oklch(0.38 0.11 148 / 0.75), 0 0 18px oklch(0.68 0.13 150 / 0.18);
|
||||
}
|
||||
|
||||
.btn-firefox {
|
||||
@@ -1615,6 +1857,19 @@ html.theme-light .koala-speech-bubble::after {
|
||||
put white text on a colour get a darker shade (these beat inline styles). */
|
||||
.hero-demo-scene {
|
||||
--accent: oklch(0.80 0.10 150);
|
||||
--demo-sky-top: oklch(0.22 0.055 152);
|
||||
--demo-sky-mid: oklch(0.145 0.035 150);
|
||||
--demo-sky-bottom: oklch(0.075 0.018 145);
|
||||
--demo-glow: oklch(0.76 0.13 150 / 0.34);
|
||||
--demo-stars: oklch(0.94 0.025 95);
|
||||
--demo-moon: oklch(0.97 0.025 92);
|
||||
--demo-mountain: oklch(0.18 0.055 148 / 0.9);
|
||||
--demo-midground: oklch(0.22 0.065 145 / 0.88);
|
||||
--demo-foreground: oklch(0.065 0.025 145);
|
||||
--demo-card: oklch(0.18 0.032 142);
|
||||
--demo-toolbar: oklch(0.12 0.025 142);
|
||||
--demo-control-fade: oklch(0.055 0.015 145 / 0.94);
|
||||
--demo-track: oklch(0.92 0.02 95 / 0.2);
|
||||
}
|
||||
.hero-demo-scene .mock-tab.active,
|
||||
.hero-demo-scene .mock-btn-force,
|
||||
@@ -1636,17 +1891,33 @@ html.theme-light .koala-speech-bubble::after {
|
||||
|
||||
html.theme-light .hero-demo-scene {
|
||||
--accent: oklch(0.60 0.12 150);
|
||||
--demo-sky-top: oklch(0.86 0.085 78);
|
||||
--demo-sky-mid: oklch(0.76 0.095 112);
|
||||
--demo-sky-bottom: oklch(0.54 0.10 150);
|
||||
--demo-glow: oklch(0.92 0.13 72 / 0.44);
|
||||
--demo-stars: oklch(0.98 0.025 90);
|
||||
--demo-moon: oklch(0.99 0.025 88);
|
||||
--demo-mountain: oklch(0.48 0.095 150 / 0.82);
|
||||
--demo-midground: oklch(0.40 0.10 148 / 0.8);
|
||||
--demo-foreground: oklch(0.24 0.075 145);
|
||||
--demo-card: oklch(0.985 0.008 95);
|
||||
--demo-toolbar: oklch(0.955 0.014 100);
|
||||
--demo-control-fade: oklch(0.16 0.035 145 / 0.88);
|
||||
--demo-track: oklch(0.98 0.01 95 / 0.34);
|
||||
}
|
||||
|
||||
|
||||
html.theme-light .hero-demo-scene .demo-tab-card {
|
||||
background: #ffffff;
|
||||
background: var(--demo-card);
|
||||
border-color: oklch(0.20 0.025 140 / 0.1);
|
||||
box-shadow: 0 18px 38px oklch(0.20 0.025 140 / 0.14);
|
||||
box-shadow:
|
||||
0 18px 38px oklch(0.20 0.025 140 / 0.16),
|
||||
0 0 28px oklch(0.82 0.10 85 / 0.14),
|
||||
inset 0 1px rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
html.theme-light .hero-demo-scene .demo-tab-titlebar {
|
||||
background: oklch(0.96 0.01 90);
|
||||
background: var(--demo-toolbar);
|
||||
border-bottom-color: oklch(0.88 0.015 90);
|
||||
color: oklch(0.45 0.02 110);
|
||||
}
|
||||
@@ -2941,6 +3212,61 @@ footer a:hover {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
html.theme-light .hero-demo-scene .demo-user-a,
|
||||
html.theme-light .hero-demo-scene .demo-user-b {
|
||||
color: oklch(0.36 0.105 150);
|
||||
background: oklch(0.60 0.12 150 / 0.13);
|
||||
}
|
||||
|
||||
html.theme-light .hero-demo-scene .extension-mockup {
|
||||
--bg: oklch(0.935 0.018 110) !important;
|
||||
--card: oklch(0.995 0.006 100) !important;
|
||||
--accent: oklch(0.56 0.13 150) !important;
|
||||
--accent-glow: oklch(0.56 0.13 150 / 0.22) !important;
|
||||
--text: oklch(0.21 0.03 140) !important;
|
||||
--text-muted: oklch(0.43 0.03 135) !important;
|
||||
--success: oklch(0.56 0.13 150) !important;
|
||||
--error: oklch(0.57 0.17 25) !important;
|
||||
--glass-border: oklch(0.28 0.035 140 / 0.10) !important;
|
||||
background: oklch(0.935 0.018 110) !important;
|
||||
border-color: oklch(0.28 0.035 140 / 0.12);
|
||||
box-shadow:
|
||||
0 20px 42px oklch(0.20 0.025 140 / 0.16),
|
||||
0 0 26px oklch(0.82 0.10 85 / 0.12);
|
||||
}
|
||||
|
||||
html.theme-light .hero-demo-scene .mock-tabs,
|
||||
html.theme-light .hero-demo-scene .mock-card,
|
||||
html.theme-light .hero-demo-scene .mock-input {
|
||||
background: oklch(0.995 0.006 100);
|
||||
border-color: oklch(0.28 0.035 140 / 0.14);
|
||||
color: oklch(0.21 0.03 140);
|
||||
}
|
||||
|
||||
html.theme-light .hero-demo-scene .mock-peer-item {
|
||||
background: oklch(0.28 0.035 140 / 0.035);
|
||||
border-color: oklch(0.28 0.035 140 / 0.09);
|
||||
}
|
||||
|
||||
html.theme-light .hero-demo-scene .mock-joined-room,
|
||||
html.theme-light .hero-demo-scene .mock-status-pill {
|
||||
background: oklch(0.56 0.13 150 / 0.10);
|
||||
border-color: oklch(0.56 0.13 150 / 0.24);
|
||||
}
|
||||
|
||||
html.theme-light .hero-demo-scene .mock-close-btn:hover {
|
||||
color: oklch(0.21 0.03 140);
|
||||
background: oklch(0.28 0.035 140 / 0.08);
|
||||
}
|
||||
|
||||
/* A direct hash destination is content, not an entrance animation. Keep it
|
||||
readable from the first paint even before app.js has initialized. */
|
||||
section:target [data-reveal],
|
||||
section:target[data-reveal] {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
|
||||
/* --- Legal Pages --- */
|
||||
.legal-content {
|
||||
@@ -3685,9 +4011,9 @@ footer {
|
||||
}
|
||||
|
||||
.cross {
|
||||
color: oklch(0.55 0.15 25);
|
||||
font-weight: 500;
|
||||
opacity: 0.8;
|
||||
color: oklch(0.68 0.17 25);
|
||||
font-weight: 600;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@@ -3838,7 +4164,7 @@ footer {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
vertical-align: super;
|
||||
opacity: 0.6;
|
||||
opacity: 0.82;
|
||||
transition: opacity 0.2s ease, color 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
@@ -4396,10 +4722,10 @@ header[id] {
|
||||
position: absolute;
|
||||
width: 310px;
|
||||
width: 70cqw;
|
||||
background: oklch(0.21 0.025 138);
|
||||
background: var(--demo-card);
|
||||
border: 1px solid rgba(255, 255, 255, 0.09);
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 18px 36px rgba(0, 0, 0, 0.45);
|
||||
box-shadow: 0 18px 36px rgba(0, 0, 0, 0.45), inset 0 1px rgba(255, 255, 255, 0.05);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
@@ -4471,7 +4797,7 @@ header[id] {
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 8px 6px 10px;
|
||||
background: oklch(0.15 0.02 138);
|
||||
background: var(--demo-toolbar);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
||||
font-size: 10.5px;
|
||||
color: var(--text-muted);
|
||||
@@ -4596,18 +4922,35 @@ header[id] {
|
||||
.demo-video {
|
||||
position: relative;
|
||||
aspect-ratio: 16 / 9;
|
||||
background: #020617;
|
||||
background: var(--demo-sky-bottom);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.demo-video::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.05),
|
||||
inset 0 -24px 36px oklch(0.04 0.015 145 / 0.2);
|
||||
}
|
||||
|
||||
html.theme-light .hero-demo-scene .demo-video::after {
|
||||
box-shadow:
|
||||
inset 0 0 0 1px oklch(0.30 0.04 145 / 0.13),
|
||||
inset 0 18px 32px oklch(0.98 0.03 90 / 0.1),
|
||||
inset 0 -22px 34px oklch(0.18 0.05 145 / 0.16);
|
||||
}
|
||||
|
||||
.demo-video-art {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background:
|
||||
radial-gradient(circle at 78% 22%, oklch(0.96 0.01 90 / 0.28) 0 4%, transparent 5.5%),
|
||||
radial-gradient(120% 90% at 70% 115%, oklch(0.26 0.05 140) 0%, transparent 60%),
|
||||
radial-gradient(100% 80% at 12% 112%, oklch(0.20 0.04 145) 0%, transparent 55%),
|
||||
linear-gradient(160deg, oklch(0.27 0.035 130) 0%, oklch(0.15 0.02 138) 55%, #020617 100%);
|
||||
radial-gradient(30% 42% at 76% 29%, var(--demo-glow), transparent 64%),
|
||||
radial-gradient(90% 85% at 18% 5%, var(--demo-glow), transparent 66%),
|
||||
linear-gradient(160deg, var(--demo-sky-top) 0%, var(--demo-sky-mid) 52%, var(--demo-sky-bottom) 100%);
|
||||
transform-origin: 60% 40%;
|
||||
animation:
|
||||
demoKenBurns 9s ease-in-out infinite alternate,
|
||||
@@ -4624,7 +4967,7 @@ header[id] {
|
||||
width: 70%;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, oklch(0.75 0.13 150 / 0.32), transparent 65%);
|
||||
background: radial-gradient(circle, var(--demo-glow), transparent 65%);
|
||||
animation: demoGlowDrift 7s ease-in-out infinite alternate;
|
||||
animation-play-state: paused;
|
||||
}
|
||||
@@ -4718,7 +5061,7 @@ header[id] {
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 14px 10px 8px;
|
||||
background: linear-gradient(transparent, oklch(0.10 0.01 135 / 0.85));
|
||||
background: linear-gradient(transparent, var(--demo-control-fade));
|
||||
font-size: 9.5px;
|
||||
color: oklch(0.88 0.015 90);
|
||||
z-index: 1;
|
||||
@@ -4737,7 +5080,7 @@ header[id] {
|
||||
flex: 1;
|
||||
height: 5px;
|
||||
border-radius: 99px;
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
background: var(--demo-track);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -4925,6 +5268,15 @@ header[id] {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hero-demo-scene .film-stars { fill: var(--demo-stars) !important; }
|
||||
.hero-demo-scene .film-moon {
|
||||
fill: var(--demo-moon) !important;
|
||||
filter: drop-shadow(0 0 6px var(--demo-moon));
|
||||
}
|
||||
.hero-demo-scene .film-mtn-scroll { fill: var(--demo-mountain) !important; }
|
||||
.hero-demo-scene .film-mid-scroll > * { fill: var(--demo-midground) !important; }
|
||||
.hero-demo-scene .film-fore-scroll > * { fill: var(--demo-foreground) !important; }
|
||||
|
||||
/* Stars: staggered twinkle so the sky feels alive */
|
||||
.film-star {
|
||||
transform-box: fill-box;
|
||||
|
||||
@@ -235,6 +235,12 @@
|
||||
<span class="bamboo-stalk far-4"></span>
|
||||
<span class="bamboo-stalk far-5"></span>
|
||||
</div>
|
||||
<div id="bamboo-mid">
|
||||
<span class="bamboo-stalk mid-1"></span>
|
||||
<span class="bamboo-stalk mid-2"></span>
|
||||
<span class="bamboo-stalk mid-3"></span>
|
||||
<span class="bamboo-stalk mid-4"></span>
|
||||
</div>
|
||||
<div id="bamboo-near">
|
||||
<div class="bamboo-stalk near-1">
|
||||
<i class="bamboo-node node-1"></i>
|
||||
|
||||
Reference in New Issue
Block a user