diff --git a/website/_site/about/index.html b/website/_site/about/index.html index 79e9aa2..bedce41 100644 --- a/website/_site/about/index.html +++ b/website/_site/about/index.html @@ -17,7 +17,7 @@ - + @@ -136,5 +136,8 @@ + + + \ No newline at end of file diff --git a/website/_site/assets/css/main.css b/website/_site/assets/css/main.css index b1956f6..bf93ea2 100644 --- a/website/_site/assets/css/main.css +++ b/website/_site/assets/css/main.css @@ -7,10 +7,22 @@ --text: #f8fafc; --muted: #aab6ca; --soft: #64748b; - --accent: #38bdf8; - --accent2: #a855f7; - --accent3: #22c55e; + /*--accent: #38bdf8;*/ + /*--accent2: #a855f7;*/ + /*--accent3: #22c55e;*/ --shadow: 0 24px 80px rgba(0, 0, 0, 0.45); + + --accent: #54d63d; + --accent2: #8aef64; + --accent3: #31b54a; + + --fx-plane: #79ff73; + --fx-plane-muted: rgba(121, 255, 115, 0.42); + --fx-beam: #52ff65; + --fx-beam-glow: rgba(82, 255, 101, 0.28); + --fx-reflection: #d2ffc8; + --fx-trail: rgba(121, 255, 115, 0.17); + --fx-grid: rgba(121, 255, 115, 0.055); } * { @@ -25,13 +37,39 @@ html { body { margin: 0; min-height: 100vh; + background: - radial-gradient(circle at 14% 12%, rgba(168, 85, 247, 0.30), transparent 28%), - radial-gradient(circle at 82% 16%, rgba(56, 189, 248, 0.24), transparent 30%), - radial-gradient(circle at 50% 85%, rgba(34, 197, 94, 0.11), transparent 35%), - linear-gradient(180deg, #050816 0%, #07111f 100%); + radial-gradient( + circle at 14% 12%, + rgba(52, 165, 57, 0.20), + transparent 30% + ), + radial-gradient( + circle at 82% 16%, + rgba(95, 218, 82, 0.14), + transparent 32% + ), + radial-gradient( + circle at 50% 85%, + rgba(32, 126, 55, 0.12), + transparent 36% + ), + linear-gradient( + 180deg, + #070b09 0%, + #0b1410 100% + ); + color: var(--text); - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + font-family: + Inter, + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + sans-serif; + line-height: 1.65; overflow-x: hidden; } @@ -561,4 +599,156 @@ a:hover { .footer-grid { grid-template-columns: 1fr; } +} + +/* + * Interactive radio / aircraft-scatter hero layer + */ + +.hero-radio-fx { + position: absolute; + inset: 0; + z-index: 0; + width: 100%; + height: 100%; + pointer-events: none; + opacity: 0.76; +} + +.hero-fx-vignette { + position: absolute; + inset: 0; + z-index: 1; + pointer-events: none; + + background: + linear-gradient( + 90deg, + rgba(7, 11, 9, 0.92) 0%, + rgba(7, 11, 9, 0.68) 34%, + rgba(7, 11, 9, 0.16) 64%, + rgba(7, 11, 9, 0.42) 100% + ), + linear-gradient( + 180deg, + rgba(7, 11, 9, 0.10), + rgba(7, 11, 9, 0.58) + ); +} + +.hero-split > *:not(.hero-radio-fx):not(.hero-fx-vignette) { + position: relative; + z-index: 2; +} + +/* + * Operator-console badge styling + */ + +.badge, +.eyebrow { + color: #caffc0; + background: rgba(52, 165, 57, 0.12); + border-color: rgba(105, 232, 88, 0.32); + box-shadow: 0 0 22px rgba(82, 255, 101, 0.08); +} + +/* + * Light-mode identity: + * white/grey UI with red contest accents + */ + +html[data-theme="light"] { + --bg: #f4f4f2; + --bg2: #ffffff; + --panel: rgba(255, 255, 255, 0.88); + --panel2: rgba(242, 242, 239, 0.92); + --border: rgba(91, 91, 86, 0.20); + --text: #252522; + --muted: #656560; + --soft: #888881; + + --accent: #d33732; + --accent2: #f25a51; + --accent3: #ae2727; + + --fx-plane: #df3732; + --fx-plane-muted: rgba(211, 55, 50, 0.38); + --fx-beam: #ef4039; + --fx-beam-glow: rgba(239, 64, 57, 0.22); + --fx-reflection: #ff8d84; + --fx-trail: rgba(211, 55, 50, 0.15); + --fx-grid: rgba(185, 47, 43, 0.045); +} + +html[data-theme="light"] body { + background: + radial-gradient( + circle at 14% 12%, + rgba(211, 55, 50, 0.12), + transparent 30% + ), + radial-gradient( + circle at 82% 16%, + rgba(242, 90, 81, 0.09), + transparent 32% + ), + linear-gradient( + 180deg, + #ffffff 0%, + #f0f0ed 100% + ); +} + +html[data-theme="light"] .hero-fx-vignette { + background: + linear-gradient( + 90deg, + rgba(255, 255, 255, 0.95) 0%, + rgba(255, 255, 255, 0.76) 34%, + rgba(255, 255, 255, 0.18) 66%, + rgba(255, 255, 255, 0.48) 100% + ), + linear-gradient( + 180deg, + rgba(255, 255, 255, 0.06), + rgba(240, 240, 237, 0.62) + ); +} + +html[data-theme="light"] .badge, +html[data-theme="light"] .eyebrow { + color: #962a27; + background: rgba(211, 55, 50, 0.08); + border-color: rgba(211, 55, 50, 0.24); +} + +@media (max-width: 900px) { + .hero-radio-fx { + opacity: 0.48; + } + + .hero-fx-vignette { + background: + linear-gradient( + 180deg, + rgba(7, 11, 9, 0.82), + rgba(7, 11, 9, 0.34) + ); + } + + html[data-theme="light"] .hero-fx-vignette { + background: + linear-gradient( + 180deg, + rgba(255, 255, 255, 0.90), + rgba(255, 255, 255, 0.42) + ); + } +} + +@media (prefers-reduced-motion: reduce) { + .hero-radio-fx { + opacity: 0.28; + } } \ No newline at end of file diff --git a/website/_site/assets/js/hero-radio-fx.js b/website/_site/assets/js/hero-radio-fx.js new file mode 100644 index 0000000..b83644f --- /dev/null +++ b/website/_site/assets/js/hero-radio-fx.js @@ -0,0 +1,710 @@ +(() => { + "use strict"; + + const canvas = document.querySelector("[data-hero-radio-fx]"); + + if (!(canvas instanceof HTMLCanvasElement)) { + return; + } + + const context = canvas.getContext("2d", { + alpha: true, + desynchronized: true + }); + + if (!context) { + return; + } + + const hero = canvas.closest(".hero"); + + if (!(hero instanceof HTMLElement)) { + return; + } + + const reducedMotion = window.matchMedia( + "(prefers-reduced-motion: reduce)" + ); + + const coarsePointer = window.matchMedia( + "(pointer: coarse)" + ); + + const state = { + width: 0, + height: 0, + dpr: 1, + running: false, + visible: true, + lastFrame: 0, + spawnAccumulator: 0, + beamAccumulator: 0, + animationFrameId: 0, + pointer: { + x: 0, + y: 0, + active: false + }, + planes: [], + beams: [], + reflections: [] + }; + + const clamp = (value, minimum, maximum) => + Math.max(minimum, Math.min(maximum, value)); + + const randomBetween = (minimum, maximum) => + minimum + Math.random() * (maximum - minimum); + + function getCssColor(name, fallback) { + const value = getComputedStyle(document.documentElement) + .getPropertyValue(name) + .trim(); + + return value || fallback; + } + + function getPalette() { + return { + plane: getCssColor("--fx-plane", "#79ff73"), + planeMuted: getCssColor("--fx-plane-muted", "rgba(121,255,115,.42)"), + beam: getCssColor("--fx-beam", "#52ff65"), + beamGlow: getCssColor("--fx-beam-glow", "rgba(82,255,101,.28)"), + reflection: getCssColor("--fx-reflection", "#c8ffbf"), + trail: getCssColor("--fx-trail", "rgba(121,255,115,.16)"), + grid: getCssColor("--fx-grid", "rgba(121,255,115,.055)") + }; + } + + function resizeCanvas() { + const bounds = hero.getBoundingClientRect(); + + state.width = Math.max(1, Math.round(bounds.width)); + state.height = Math.max(1, Math.round(bounds.height)); + state.dpr = Math.min(window.devicePixelRatio || 1, 1.5); + + canvas.width = Math.round(state.width * state.dpr); + canvas.height = Math.round(state.height * state.dpr); + + canvas.style.width = `${state.width}px`; + canvas.style.height = `${state.height}px`; + + context.setTransform( + state.dpr, + 0, + 0, + state.dpr, + 0, + 0 + ); + + if (!state.pointer.active) { + state.pointer.x = state.width * 0.54; + state.pointer.y = state.height * 0.42; + } + } + + function getPlaneLimit() { + if (coarsePointer.matches) { + return 5; + } + + if (state.width < 900) { + return 7; + } + + return 12; + } + + function createPlane() { + const margin = 55; + const edge = Math.floor(Math.random() * 4); + + let x; + let y; + + switch (edge) { + case 0: + x = randomBetween(0, state.width); + y = -margin; + break; + + case 1: + x = state.width + margin; + y = randomBetween(0, state.height); + break; + + case 2: + x = randomBetween(0, state.width); + y = state.height + margin; + break; + + default: + x = -margin; + y = randomBetween(0, state.height); + break; + } + + const targetX = state.pointer.active + ? state.pointer.x + : state.width * randomBetween(0.38, 0.72); + + const targetY = state.pointer.active + ? state.pointer.y + : state.height * randomBetween(0.2, 0.72); + + const angle = Math.atan2(targetY - y, targetX - x); + const speed = randomBetween(18, 34); + + return { + x, + y, + previousX: x, + previousY: y, + velocityX: Math.cos(angle) * speed, + velocityY: Math.sin(angle) * speed, + angle, + size: randomBetween(5.5, 9), + age: 0, + maximumAge: randomBetween(12, 20), + steering: randomBetween(0.65, 1.2), + wobble: randomBetween(0, Math.PI * 2), + wobbleSpeed: randomBetween(0.7, 1.4), + hit: 0 + }; + } + + function updatePlane(plane, deltaSeconds) { + plane.age += deltaSeconds; + plane.wobble += deltaSeconds * plane.wobbleSpeed; + + plane.previousX = plane.x; + plane.previousY = plane.y; + + const targetX = state.pointer.active + ? state.pointer.x + : state.width * 0.56; + + const targetY = state.pointer.active + ? state.pointer.y + : state.height * 0.44; + + const desiredAngle = Math.atan2( + targetY - plane.y, + targetX - plane.x + ); + + let angleDifference = desiredAngle - plane.angle; + + while (angleDifference > Math.PI) { + angleDifference -= Math.PI * 2; + } + + while (angleDifference < -Math.PI) { + angleDifference += Math.PI * 2; + } + + plane.angle += angleDifference * plane.steering * deltaSeconds; + + const speed = Math.hypot( + plane.velocityX, + plane.velocityY + ); + + const wobble = Math.sin(plane.wobble) * 0.14; + + plane.velocityX = + Math.cos(plane.angle + wobble) * speed; + + plane.velocityY = + Math.sin(plane.angle + wobble) * speed; + + plane.x += plane.velocityX * deltaSeconds; + plane.y += plane.velocityY * deltaSeconds; + + plane.hit = Math.max(0, plane.hit - deltaSeconds * 1.8); + } + + function isPlaneExpired(plane) { + const margin = 180; + + return ( + plane.age > plane.maximumAge || + plane.x < -margin || + plane.x > state.width + margin || + plane.y < -margin || + plane.y > state.height + margin + ); + } + + function chooseBeamTarget() { + if (state.planes.length === 0) { + return null; + } + + const targetX = state.pointer.active + ? state.pointer.x + : state.width * 0.56; + + const targetY = state.pointer.active + ? state.pointer.y + : state.height * 0.44; + + const candidates = state.planes + .map((plane) => ({ + plane, + distance: Math.hypot( + plane.x - targetX, + plane.y - targetY + ) + })) + .filter((entry) => entry.distance < 260) + .sort((a, b) => a.distance - b.distance); + + if (candidates.length > 0) { + return candidates[0].plane; + } + + return state.planes[ + Math.floor(Math.random() * state.planes.length) + ]; + } + + function createBeam(target) { + const leftStation = { + x: state.width * 0.12, + y: state.height * 0.82 + }; + + const rightStation = { + x: state.width * 0.88, + y: state.height * 0.78 + }; + + const source = + Math.abs(target.x - leftStation.x) < + Math.abs(target.x - rightStation.x) + ? leftStation + : rightStation; + + state.beams.push({ + startX: source.x, + startY: source.y, + endX: target.x, + endY: target.y, + age: 0, + maximumAge: 0.62 + }); + + target.hit = 1; + + state.reflections.push({ + x: target.x, + y: target.y, + age: 0, + maximumAge: 0.9, + radius: randomBetween(8, 15) + }); + } + + function updateEffects(deltaSeconds) { + for (const beam of state.beams) { + beam.age += deltaSeconds; + } + + state.beams = state.beams.filter( + (beam) => beam.age < beam.maximumAge + ); + + for (const reflection of state.reflections) { + reflection.age += deltaSeconds; + reflection.radius += deltaSeconds * 30; + } + + state.reflections = state.reflections.filter( + (reflection) => + reflection.age < reflection.maximumAge + ); + } + + function drawGrid(palette) { + context.save(); + + context.strokeStyle = palette.grid; + context.lineWidth = 1; + + const spacing = 54; + + for ( + let x = spacing; + x < state.width; + x += spacing + ) { + context.beginPath(); + context.moveTo(x, 0); + context.lineTo(x, state.height); + context.stroke(); + } + + for ( + let y = spacing; + y < state.height; + y += spacing + ) { + context.beginPath(); + context.moveTo(0, y); + context.lineTo(state.width, y); + context.stroke(); + } + + context.restore(); + } + + function drawRadarTarget(palette) { + const x = state.pointer.active + ? state.pointer.x + : state.width * 0.56; + + const y = state.pointer.active + ? state.pointer.y + : state.height * 0.44; + + context.save(); + + context.strokeStyle = palette.planeMuted; + context.lineWidth = 1; + + for (const radius of [24, 48, 82]) { + context.globalAlpha = 0.24 - radius / 500; + + context.beginPath(); + context.arc(x, y, radius, 0, Math.PI * 2); + context.stroke(); + } + + context.globalAlpha = 0.2; + + context.beginPath(); + context.moveTo(x - 100, y); + context.lineTo(x + 100, y); + context.moveTo(x, y - 100); + context.lineTo(x, y + 100); + context.stroke(); + + context.restore(); + } + + function drawPlane(plane, palette) { + context.save(); + + context.translate(plane.x, plane.y); + context.rotate(plane.angle); + + const alpha = clamp( + Math.min( + plane.age * 1.8, + (plane.maximumAge - plane.age) * 1.8 + ), + 0, + 1 + ); + + context.globalAlpha = alpha; + + context.strokeStyle = palette.trail; + context.lineWidth = 1; + + context.beginPath(); + context.moveTo(-plane.size * 4.5, 0); + context.lineTo(-plane.size * 1.4, 0); + context.stroke(); + + context.fillStyle = + plane.hit > 0 + ? palette.reflection + : palette.plane; + + context.shadowColor = + plane.hit > 0 + ? palette.reflection + : palette.beamGlow; + + context.shadowBlur = + plane.hit > 0 + ? 16 + : 5; + + const size = plane.size; + + context.beginPath(); + + context.moveTo(size * 1.65, 0); + context.lineTo(-size * 0.7, size * 0.34); + context.lineTo(-size * 0.15, size * 1.05); + context.lineTo(-size * 0.65, size * 1.08); + context.lineTo(-size * 1.35, size * 0.3); + context.lineTo(-size * 1.7, size * 0.28); + context.lineTo(-size * 1.12, 0); + context.lineTo(-size * 1.7, -size * 0.28); + context.lineTo(-size * 1.35, -size * 0.3); + context.lineTo(-size * 0.65, -size * 1.08); + context.lineTo(-size * 0.15, -size * 1.05); + context.lineTo(-size * 0.7, -size * 0.34); + + context.closePath(); + context.fill(); + + context.restore(); + } + + function drawBeam(beam, palette) { + const progress = beam.age / beam.maximumAge; + const alpha = Math.sin(progress * Math.PI); + + context.save(); + + context.globalAlpha = alpha; + context.strokeStyle = palette.beamGlow; + context.lineWidth = 6; + context.shadowColor = palette.beam; + context.shadowBlur = 15; + + context.beginPath(); + context.moveTo(beam.startX, beam.startY); + context.lineTo(beam.endX, beam.endY); + context.stroke(); + + context.strokeStyle = palette.beam; + context.lineWidth = 1.4; + context.shadowBlur = 5; + + context.beginPath(); + context.moveTo(beam.startX, beam.startY); + context.lineTo(beam.endX, beam.endY); + context.stroke(); + + context.restore(); + } + + function drawReflection(reflection, palette) { + const progress = + reflection.age / reflection.maximumAge; + + context.save(); + + context.globalAlpha = 1 - progress; + context.strokeStyle = palette.reflection; + context.lineWidth = 1.5; + context.shadowColor = palette.beam; + context.shadowBlur = 12; + + context.beginPath(); + context.arc( + reflection.x, + reflection.y, + reflection.radius, + 0, + Math.PI * 2 + ); + context.stroke(); + + context.restore(); + } + + function drawStaticScene() { + const palette = getPalette(); + + context.clearRect( + 0, + 0, + state.width, + state.height + ); + + drawGrid(palette); + drawRadarTarget(palette); + } + + function drawScene() { + const palette = getPalette(); + + context.clearRect( + 0, + 0, + state.width, + state.height + ); + + drawGrid(palette); + drawRadarTarget(palette); + + for (const plane of state.planes) { + drawPlane(plane, palette); + } + + for (const beam of state.beams) { + drawBeam(beam, palette); + } + + for (const reflection of state.reflections) { + drawReflection(reflection, palette); + } + } + + function animate(timestamp) { + if (!state.running) { + return; + } + + const deltaSeconds = clamp( + (timestamp - state.lastFrame) / 1000 || 0, + 0, + 0.05 + ); + + state.lastFrame = timestamp; + + if (!state.visible || document.hidden) { + state.animationFrameId = + requestAnimationFrame(animate); + + return; + } + + state.spawnAccumulator += deltaSeconds; + state.beamAccumulator += deltaSeconds; + + const planeLimit = getPlaneLimit(); + const spawnInterval = + coarsePointer.matches ? 2.2 : 1.15; + + if ( + state.spawnAccumulator >= spawnInterval && + state.planes.length < planeLimit + ) { + state.spawnAccumulator = 0; + state.planes.push(createPlane()); + } + + const beamInterval = + coarsePointer.matches ? 3.3 : 1.8; + + if ( + state.beamAccumulator >= beamInterval && + state.planes.length > 0 + ) { + state.beamAccumulator = 0; + + const target = chooseBeamTarget(); + + if (target) { + createBeam(target); + } + } + + for (const plane of state.planes) { + updatePlane(plane, deltaSeconds); + } + + state.planes = state.planes.filter( + (plane) => !isPlaneExpired(plane) + ); + + updateEffects(deltaSeconds); + drawScene(); + + state.animationFrameId = + requestAnimationFrame(animate); + } + + function start() { + cancelAnimationFrame(state.animationFrameId); + + resizeCanvas(); + + if (reducedMotion.matches) { + state.running = false; + drawStaticScene(); + return; + } + + state.running = true; + state.lastFrame = performance.now(); + + if (state.planes.length === 0) { + const initialPlanes = + coarsePointer.matches ? 2 : 5; + + for (let index = 0; index < initialPlanes; index++) { + const plane = createPlane(); + plane.age = Math.random() * 2; + state.planes.push(plane); + } + } + + state.animationFrameId = + requestAnimationFrame(animate); + } + + function updatePointer(event) { + const bounds = hero.getBoundingClientRect(); + + state.pointer.x = clamp( + event.clientX - bounds.left, + 0, + bounds.width + ); + + state.pointer.y = clamp( + event.clientY - bounds.top, + 0, + bounds.height + ); + + state.pointer.active = true; + } + + hero.addEventListener("pointermove", updatePointer, { + passive: true + }); + + hero.addEventListener("pointerleave", () => { + state.pointer.active = false; + }); + + window.addEventListener("resize", resizeCanvas, { + passive: true + }); + + document.addEventListener("visibilitychange", () => { + state.lastFrame = performance.now(); + }); + + reducedMotion.addEventListener("change", start); + + const resizeObserver = new ResizeObserver(() => { + resizeCanvas(); + + if (reducedMotion.matches) { + drawStaticScene(); + } + }); + + resizeObserver.observe(hero); + + const intersectionObserver = new IntersectionObserver( + (entries) => { + state.visible = + entries[0]?.isIntersecting ?? true; + + state.lastFrame = performance.now(); + }, + { + threshold: 0.05 + } + ); + + intersectionObserver.observe(hero); + + start(); +})(); \ No newline at end of file diff --git a/website/_site/contact/index.html b/website/_site/contact/index.html index 8097b51..c13f44e 100644 --- a/website/_site/contact/index.html +++ b/website/_site/contact/index.html @@ -17,7 +17,7 @@ - + @@ -124,5 +124,8 @@ + + + \ No newline at end of file diff --git a/website/_site/download/index.html b/website/_site/download/index.html index 3d17083..972a8d1 100644 --- a/website/_site/download/index.html +++ b/website/_site/download/index.html @@ -17,7 +17,7 @@ - + @@ -288,5 +288,8 @@ + + + \ No newline at end of file diff --git a/website/_site/faq/index.html b/website/_site/faq/index.html index 39829c9..c57844f 100644 --- a/website/_site/faq/index.html +++ b/website/_site/faq/index.html @@ -17,7 +17,7 @@ - + @@ -167,5 +167,8 @@ + + + \ No newline at end of file diff --git a/website/_site/features/airscout/index.html b/website/_site/features/airscout/index.html index 24e9303..380605b 100644 --- a/website/_site/features/airscout/index.html +++ b/website/_site/features/airscout/index.html @@ -17,7 +17,7 @@ - + @@ -222,5 +222,8 @@ + + + \ No newline at end of file diff --git a/website/_site/features/dual-chat/index.html b/website/_site/features/dual-chat/index.html index f94b78c..f858c9a 100644 --- a/website/_site/features/dual-chat/index.html +++ b/website/_site/features/dual-chat/index.html @@ -17,7 +17,7 @@ - + @@ -198,5 +198,8 @@ + + + \ No newline at end of file diff --git a/website/_site/features/dx-cluster/index.html b/website/_site/features/dx-cluster/index.html index 5d71a48..17fcb4f 100644 --- a/website/_site/features/dx-cluster/index.html +++ b/website/_site/features/dx-cluster/index.html @@ -17,7 +17,7 @@ - + @@ -197,5 +197,8 @@ + + + \ No newline at end of file diff --git a/website/_site/features/index.html b/website/_site/features/index.html index 19c165b..9bab3cb 100644 --- a/website/_site/features/index.html +++ b/website/_site/features/index.html @@ -17,7 +17,7 @@ - + @@ -183,5 +183,8 @@ + + + \ No newline at end of file diff --git a/website/_site/features/log-sync/index.html b/website/_site/features/log-sync/index.html index 736f352..0c76230 100644 --- a/website/_site/features/log-sync/index.html +++ b/website/_site/features/log-sync/index.html @@ -17,7 +17,7 @@ - + @@ -198,5 +198,8 @@ + + + \ No newline at end of file diff --git a/website/_site/features/macros/index.html b/website/_site/features/macros/index.html index 2f8f4de..a104e9f 100644 --- a/website/_site/features/macros/index.html +++ b/website/_site/features/macros/index.html @@ -17,7 +17,7 @@ - + @@ -197,5 +197,8 @@ + + + \ No newline at end of file diff --git a/website/_site/features/priority-score/index.html b/website/_site/features/priority-score/index.html index 136f301..8412805 100644 --- a/website/_site/features/priority-score/index.html +++ b/website/_site/features/priority-score/index.html @@ -17,7 +17,7 @@ - + @@ -226,5 +226,8 @@ + + + \ No newline at end of file diff --git a/website/_site/features/sked-reminder/index.html b/website/_site/features/sked-reminder/index.html index e9d1277..43a8627 100644 --- a/website/_site/features/sked-reminder/index.html +++ b/website/_site/features/sked-reminder/index.html @@ -17,7 +17,7 @@ - + @@ -220,5 +220,8 @@ + + + \ No newline at end of file diff --git a/website/_site/features/timeline/index.html b/website/_site/features/timeline/index.html index 4520ada..c174a14 100644 --- a/website/_site/features/timeline/index.html +++ b/website/_site/features/timeline/index.html @@ -17,7 +17,7 @@ - + @@ -198,5 +198,8 @@ + + + \ No newline at end of file diff --git a/website/_site/index.html b/website/_site/index.html index 2bc9390..79c069e 100644 --- a/website/_site/index.html +++ b/website/_site/index.html @@ -17,7 +17,7 @@ - + @@ -66,6 +66,14 @@
+ + + +

The contest-optimized ON4KST client

KST4Contest

@@ -288,5 +296,10 @@
+ + + + + \ No newline at end of file diff --git a/website/_site/legal-notice/index.html b/website/_site/legal-notice/index.html index 732f4c6..4d6020e 100644 --- a/website/_site/legal-notice/index.html +++ b/website/_site/legal-notice/index.html @@ -17,7 +17,7 @@ - + @@ -134,5 +134,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/de/airscout-integration/index.html b/website/_site/manual/de/airscout-integration/index.html index d23cabc..117c00a 100644 --- a/website/_site/manual/de/airscout-integration/index.html +++ b/website/_site/manual/de/airscout-integration/index.html @@ -17,7 +17,7 @@ - + @@ -208,5 +208,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/de/benutzeroberflaeche/index.html b/website/_site/manual/de/benutzeroberflaeche/index.html index d178b7f..4260efe 100644 --- a/website/_site/manual/de/benutzeroberflaeche/index.html +++ b/website/_site/manual/de/benutzeroberflaeche/index.html @@ -17,7 +17,7 @@ - + @@ -210,5 +210,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/de/changelog/index.html b/website/_site/manual/de/changelog/index.html index df9ac83..546d4d8 100644 --- a/website/_site/manual/de/changelog/index.html +++ b/website/_site/manual/de/changelog/index.html @@ -17,7 +17,7 @@ - + @@ -345,5 +345,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/de/dx-cluster-server/index.html b/website/_site/manual/de/dx-cluster-server/index.html index 88bbcb6..f77d34a 100644 --- a/website/_site/manual/de/dx-cluster-server/index.html +++ b/website/_site/manual/de/dx-cluster-server/index.html @@ -17,7 +17,7 @@ - + @@ -172,5 +172,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/de/funktionen/index.html b/website/_site/manual/de/funktionen/index.html index 74db7f8..a3dc496 100644 --- a/website/_site/manual/de/funktionen/index.html +++ b/website/_site/manual/de/funktionen/index.html @@ -17,7 +17,7 @@ - + @@ -294,5 +294,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/de/home/index.html b/website/_site/manual/de/home/index.html index 4f6330a..ca4a2f5 100644 --- a/website/_site/manual/de/home/index.html +++ b/website/_site/manual/de/home/index.html @@ -17,7 +17,7 @@ - + @@ -201,5 +201,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/de/index.html b/website/_site/manual/de/index.html index 8bb00b7..793c91b 100644 --- a/website/_site/manual/de/index.html +++ b/website/_site/manual/de/index.html @@ -17,7 +17,7 @@ - + @@ -197,5 +197,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/de/installation/index.html b/website/_site/manual/de/installation/index.html index ed7e847..4a10892 100644 --- a/website/_site/manual/de/installation/index.html +++ b/website/_site/manual/de/installation/index.html @@ -17,7 +17,7 @@ - + @@ -316,5 +316,8 @@ flatpak install kst4contest de.x08.KST4Contest//nightly + + + \ No newline at end of file diff --git a/website/_site/manual/de/konfiguration/index.html b/website/_site/manual/de/konfiguration/index.html index a17ef39..6a50685 100644 --- a/website/_site/manual/de/konfiguration/index.html +++ b/website/_site/manual/de/konfiguration/index.html @@ -17,7 +17,7 @@ - + @@ -252,5 +252,8 @@ Zudem wird die primäre Chat-Kategorie (z. B. IARU Region 1 VHF + + + \ No newline at end of file diff --git a/website/_site/manual/de/log-synchronisation/index.html b/website/_site/manual/de/log-synchronisation/index.html index 99d6ca2..3df4f74 100644 --- a/website/_site/manual/de/log-synchronisation/index.html +++ b/website/_site/manual/de/log-synchronisation/index.html @@ -17,7 +17,7 @@ - + @@ -230,5 +230,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/de/makros-und-variablen/index.html b/website/_site/manual/de/makros-und-variablen/index.html index a382811..697e64e 100644 --- a/website/_site/manual/de/makros-und-variablen/index.html +++ b/website/_site/manual/de/makros-und-variablen/index.html @@ -17,7 +17,7 @@ - + @@ -241,5 +241,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/en/airscout-integration/index.html b/website/_site/manual/en/airscout-integration/index.html index 1fb8a1d..5574904 100644 --- a/website/_site/manual/en/airscout-integration/index.html +++ b/website/_site/manual/en/airscout-integration/index.html @@ -17,7 +17,7 @@ - + @@ -208,5 +208,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/en/changelog/index.html b/website/_site/manual/en/changelog/index.html index 6f9310e..0137385 100644 --- a/website/_site/manual/en/changelog/index.html +++ b/website/_site/manual/en/changelog/index.html @@ -17,7 +17,7 @@ - + @@ -345,5 +345,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/en/configuration/index.html b/website/_site/manual/en/configuration/index.html index b8cffb2..4a42603 100644 --- a/website/_site/manual/en/configuration/index.html +++ b/website/_site/manual/en/configuration/index.html @@ -17,7 +17,7 @@ - + @@ -252,5 +252,8 @@ Also, select the primary chat category (e.g., IARU Region 1 VHF + + + \ No newline at end of file diff --git a/website/_site/manual/en/dx-cluster-server/index.html b/website/_site/manual/en/dx-cluster-server/index.html index 851a654..2992dcf 100644 --- a/website/_site/manual/en/dx-cluster-server/index.html +++ b/website/_site/manual/en/dx-cluster-server/index.html @@ -17,7 +17,7 @@ - + @@ -172,5 +172,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/en/features/index.html b/website/_site/manual/en/features/index.html index de5e9de..b8e7fb0 100644 --- a/website/_site/manual/en/features/index.html +++ b/website/_site/manual/en/features/index.html @@ -17,7 +17,7 @@ - + @@ -293,5 +293,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/en/home/index.html b/website/_site/manual/en/home/index.html index 2d42525..d908bb0 100644 --- a/website/_site/manual/en/home/index.html +++ b/website/_site/manual/en/home/index.html @@ -17,7 +17,7 @@ - + @@ -201,5 +201,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/en/index.html b/website/_site/manual/en/index.html index 1ae25fb..960da5e 100644 --- a/website/_site/manual/en/index.html +++ b/website/_site/manual/en/index.html @@ -17,7 +17,7 @@ - + @@ -197,5 +197,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/en/installation/index.html b/website/_site/manual/en/installation/index.html index dcd3710..7e93ee5 100644 --- a/website/_site/manual/en/installation/index.html +++ b/website/_site/manual/en/installation/index.html @@ -17,7 +17,7 @@ - + @@ -316,5 +316,8 @@ flatpak install kst4contest de.x08.KST4Contest//nightly + + + \ No newline at end of file diff --git a/website/_site/manual/en/log-sync/index.html b/website/_site/manual/en/log-sync/index.html index ac2dc52..00d6080 100644 --- a/website/_site/manual/en/log-sync/index.html +++ b/website/_site/manual/en/log-sync/index.html @@ -17,7 +17,7 @@ - + @@ -230,5 +230,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/en/macros-and-variables/index.html b/website/_site/manual/en/macros-and-variables/index.html index e09da2a..f5e2797 100644 --- a/website/_site/manual/en/macros-and-variables/index.html +++ b/website/_site/manual/en/macros-and-variables/index.html @@ -17,7 +17,7 @@ - + @@ -241,5 +241,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/en/user-interface/index.html b/website/_site/manual/en/user-interface/index.html index a7ec1b1..3c98fb9 100644 --- a/website/_site/manual/en/user-interface/index.html +++ b/website/_site/manual/en/user-interface/index.html @@ -17,7 +17,7 @@ - + @@ -210,5 +210,8 @@ + + + \ No newline at end of file diff --git a/website/_site/manual/index.html b/website/_site/manual/index.html index 468c726..a6f88c6 100644 --- a/website/_site/manual/index.html +++ b/website/_site/manual/index.html @@ -17,7 +17,7 @@ - + @@ -109,5 +109,8 @@ + + + \ No newline at end of file diff --git a/website/_site/news/2026-07-08-hotfix-version-1-41-1/index.html b/website/_site/news/2026-07-08-hotfix-version-1-41-1/index.html index de3d3ee..ffec1c6 100644 --- a/website/_site/news/2026-07-08-hotfix-version-1-41-1/index.html +++ b/website/_site/news/2026-07-08-hotfix-version-1-41-1/index.html @@ -17,7 +17,7 @@ - + @@ -110,5 +110,8 @@ + + + \ No newline at end of file diff --git a/website/_site/news/2026-07-website-launch/index.html b/website/_site/news/2026-07-website-launch/index.html index 5a4c639..c5f24d3 100644 --- a/website/_site/news/2026-07-website-launch/index.html +++ b/website/_site/news/2026-07-website-launch/index.html @@ -17,7 +17,7 @@ - + @@ -114,5 +114,8 @@ + + + \ No newline at end of file diff --git a/website/_site/news/index.html b/website/_site/news/index.html index 6eca771..219e45d 100644 --- a/website/_site/news/index.html +++ b/website/_site/news/index.html @@ -17,7 +17,7 @@ - + @@ -124,5 +124,8 @@ + + + \ No newline at end of file diff --git a/website/_site/privacy/index.html b/website/_site/privacy/index.html index 5656dee..58ce4c7 100644 --- a/website/_site/privacy/index.html +++ b/website/_site/privacy/index.html @@ -17,7 +17,7 @@ - + @@ -165,5 +165,8 @@ + + + \ No newline at end of file diff --git a/website/_site/roadmap/index.html b/website/_site/roadmap/index.html index 961d958..58395da 100644 --- a/website/_site/roadmap/index.html +++ b/website/_site/roadmap/index.html @@ -17,7 +17,7 @@ - + @@ -249,5 +249,8 @@ href="/support/"> + + + \ No newline at end of file diff --git a/website/_site/screenshots/index.html b/website/_site/screenshots/index.html index 1a5483c..23229e0 100644 --- a/website/_site/screenshots/index.html +++ b/website/_site/screenshots/index.html @@ -17,7 +17,7 @@ - + @@ -135,5 +135,8 @@ + + + \ No newline at end of file diff --git a/website/_site/sitemap.xml b/website/_site/sitemap.xml index 00bcd7a..c6a9cf9 100644 --- a/website/_site/sitemap.xml +++ b/website/_site/sitemap.xml @@ -10,94 +10,94 @@ https://kst4contest.hamradioonline.de/about/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/contact/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/download/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/faq/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/features/airscout/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/features/dual-chat/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/features/dx-cluster/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/features/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/features/log-sync/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/features/macros/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/features/priority-score/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/features/sked-reminder/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/features/timeline/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/legal-notice/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/manual/de/airscout-integration/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/manual/de/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/manual/en/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/manual/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/privacy/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/roadmap/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/screenshots/ - 2026-07-11 + 2026-07-12 https://kst4contest.hamradioonline.de/support/ - 2026-07-11 + 2026-07-12 \ No newline at end of file diff --git a/website/_site/support/index.html b/website/_site/support/index.html index 68e7af5..4eec99b 100644 --- a/website/_site/support/index.html +++ b/website/_site/support/index.html @@ -17,7 +17,7 @@ - + @@ -267,5 +267,8 @@ rel="noopener"> + + + \ No newline at end of file