Updated the core site style and removed AI fuzz.
This commit is contained in:
+51
-110
@@ -4,146 +4,87 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Amateur Radio License Exams – BYU-Idaho Amateur Radio Society</title>
|
<title>Amateur Radio License Exams – BYU-Idaho Amateur Radio Society</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<link rel="stylesheet" href="style.css" />
|
||||||
<script>
|
<script src="script.js" defer></script>
|
||||||
tailwind.config = {
|
|
||||||
darkMode: 'class'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js" defer></script>
|
|
||||||
<style>
|
|
||||||
.accent-bg { background-color: #006eb6; }
|
|
||||||
.banner-bg { background-color: #a2daff; }
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-100 min-h-screen flex flex-col" x-data="appData()" x-init="init()">
|
<body>
|
||||||
|
|
||||||
<!-- Banner -->
|
<!-- Announcement Banner -->
|
||||||
<template x-if="banner.title && banner.content">
|
<div id="banner" class="banner-bg hidden">
|
||||||
<div class="w-full banner-bg text-black text-center py-2 px-4">
|
<strong id="banner-title"></strong>: <span id="banner-content"></span>
|
||||||
<strong x-text="banner.title"></strong>: <span x-text="banner.content"></span>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Navbar -->
|
<!-- Navigation Bar -->
|
||||||
<nav class="accent-bg text-white px-4 py-3 shadow-md" x-data="{ open: false }">
|
<nav class="navbar accent-bg">
|
||||||
<div class="flex flex-wrap items-center justify-between">
|
<div class="nav-container">
|
||||||
<a href="/" class="text-xl font-semibold mr-4">BYU-I Amateur Radio Society</a>
|
<a href="/" class="nav-brand">BYU-I Amateur Radio Society</a>
|
||||||
<button @click="open = !open" class="sm:hidden text-white ml-auto focus:outline-none">
|
|
||||||
<svg x-show="!open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<!-- Mobile Hamburger Toggle -->
|
||||||
|
<button id="menu-toggle" class="icon-button mobile-only" aria-label="Toggle Navigation Menu">
|
||||||
|
<svg id="icon-hamburger" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg id="icon-close" class="icon hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="hidden sm:flex flex-grow justify-center space-x-4">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Desktop Links -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="hover:opacity-80 transition">
|
<div id="desktop-links" class="nav-links desktop-only"></div>
|
||||||
<span x-text="page.name"></span>
|
|
||||||
</a>
|
<!-- Desktop Dark Mode Toggle -->
|
||||||
</template>
|
<button class="theme-toggle icon-button desktop-only" aria-label="Toggle Dark Mode">
|
||||||
</div>
|
<svg class="icon icon-sun hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<div class="hidden sm:flex ml-auto">
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
||||||
<button @click="toggleDarkMode" class="ml-4 text-white focus:outline-none" title="Toggle dark mode">
|
</svg>
|
||||||
<svg x-show="!darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg class="icon icon-moon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
</button>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div x-show="open" class="sm:hidden mt-2 space-y-2">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Mobile Dropdown Menu -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="block px-2 py-1 hover:bg-white/10">
|
<div id="mobile-menu" class="mobile-menu mobile-only hidden">
|
||||||
<span x-text="page.name"></span>
|
<div id="mobile-links"></div>
|
||||||
</a>
|
<button class="theme-toggle mobile-theme-btn" aria-label="Toggle Dark Mode">
|
||||||
</template>
|
<span class="theme-text">🌙 Dark Mode</span>
|
||||||
<button @click="toggleDarkMode" class="w-full text-left px-2 py-1 text-white hover:bg-white/10" title="Toggle dark mode">
|
|
||||||
<span x-text="darkMode ? '☀️ Light Mode' : '🌙 Dark Mode'"></span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="flex-grow p-6">
|
<!-- Main Content -->
|
||||||
<h1 class="text-3xl font-bold mb-4">License Exams</h1>
|
<main class="main-content">
|
||||||
|
<h1>License Exams</h1>
|
||||||
|
|
||||||
<p class="mb-4">
|
<p>
|
||||||
Interested in getting your amateur radio license? The BYU-I Amateur Radio Society hosts exam sessions right here in Rexburg!
|
Interested in getting your amateur radio license? The BYU-I Amateur Radio Society hosts exam sessions right here in Rexburg!
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold mt-6 mb-2">Upcoming Exam Sessions</h2>
|
<h2>Upcoming Exam Sessions</h2>
|
||||||
<ul class="list-disc pl-6 space-y-2">
|
<ul id="exams-list" class="styled-list">
|
||||||
<template x-if="exams.length">
|
<!-- Dynamically populated from /assets/exams.json via script.js -->
|
||||||
<template x-for="exam in exams" :key="exam.date">
|
|
||||||
<li>
|
|
||||||
<span x-text="exam.date"></span>,
|
|
||||||
<span x-text="exam.time"></span> –
|
|
||||||
<span x-text="exam.location"></span> –
|
|
||||||
<a :href="exam.register" class="text-blue-400 underline" target="_blank">Register Here</a>
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
<template x-if="!exams.length">
|
|
||||||
<li>
|
|
||||||
We don't have any sessions scheduled right now, but if you're ready to test let us know and we'll set one up!
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold mt-6 mb-2">Before You Test</h2>
|
<h2>Before You Test</h2>
|
||||||
<ul class="list-disc pl-6 space-y-2">
|
<ul class="styled-list">
|
||||||
<li>Study using <a href="https://hamstudy.org/" class="text-blue-400 underline">HamStudy.org</a> or other resources</li>
|
<li>Study using <a href="https://hamstudy.org/" class="link" target="_blank" rel="noopener">HamStudy.org</a> or other resources</li>
|
||||||
<li>Take practice exams and be sure you're consistently scoring at least 80% (not required, but helpful)</li>
|
<li>Take practice exams and be sure you're consistently scoring at least 80% (not required, but helpful)</li>
|
||||||
<li>Get your <a href="https://apps.fcc.gov/cores/userLogin.do" class="text-blue-400 underline">FCC FRN</a></li>
|
<li>Get your <a href="https://apps.fcc.gov/cores/userLogin.do" class="link" target="_blank" rel="noopener">FCC FRN</a></li>
|
||||||
<li>Register for your session, or contact us to set one up</li>
|
<li>Register for your session, or contact us to set one up</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold mt-6 mb-2">When You Test</h2>
|
<h2>When You Test</h2>
|
||||||
<ul class="list-disc pl-6 space-y-2">
|
<ul class="styled-list">
|
||||||
<li>Bring a government-issued photo ID and a current student ID (students test free!) or $14 for the exam fee</li>
|
<li>Bring a government-issued photo ID and a current student ID (students test free!) or $14 for the exam fee</li>
|
||||||
<li>If you have a calculator and are okay clearing its memory, feel free to bring it!</li>
|
<li>If you have a calculator and are okay clearing its memory, feel free to bring it!</li>
|
||||||
<li>Our sessions typically run for at least an hour and often start a little early, so don't stress if you're running early or late. Just relax</li>
|
<li>Our sessions typically run for at least an hour and often start a little early, so don't stress if you're running early or late. Just relax</li>
|
||||||
</ul>
|
</ul>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="accent-bg text-white text-center py-4">
|
<!-- Footer -->
|
||||||
© 2025-<span x-text="new Date().getFullYear()"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
<footer class="footer accent-bg">
|
||||||
|
© 2025–<span id="current-year"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script>
|
|
||||||
function appData() {
|
|
||||||
return {
|
|
||||||
darkMode: document.documentElement.classList.contains('dark'),
|
|
||||||
currentPath: window.location.pathname,
|
|
||||||
banner: { title: '', content: '' },
|
|
||||||
pages: [],
|
|
||||||
async init() {
|
|
||||||
const navResp = await fetch('/assets/pages.json');
|
|
||||||
this.pages = await navResp.json();
|
|
||||||
|
|
||||||
const bannerResp = await fetch('/assets/banner.json?t=${Date.now()}');
|
|
||||||
this.banner = await bannerResp.json();
|
|
||||||
|
|
||||||
const examResp = await fetch('/assets/exams.json?t=${Date.now()}');
|
|
||||||
this.exams = await examResp.json();
|
|
||||||
},
|
|
||||||
toggleDarkMode() {
|
|
||||||
this.darkMode = !this.darkMode;
|
|
||||||
document.documentElement.classList.toggle('dark');
|
|
||||||
localStorage.theme = this.darkMode ? 'dark' : 'light';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
+45
-87
@@ -3,114 +3,72 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>History – BYU-I Amateur Radio Society</title>
|
<title>History – BYU-Idaho Amateur Radio Society</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<link rel="stylesheet" href="style.css" />
|
||||||
<script>
|
<script src="script.js" defer></script>
|
||||||
tailwind.config = {
|
|
||||||
darkMode: 'class'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js" defer></script>
|
|
||||||
<style>
|
|
||||||
.accent-bg { background-color: #006eb6; }
|
|
||||||
.banner-bg { background-color: #a2daff; }
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-100 min-h-screen flex flex-col" x-data="appData()" x-init="init()">
|
<body>
|
||||||
|
|
||||||
<!-- Banner -->
|
<!-- Announcement Banner -->
|
||||||
<template x-if="banner.title && banner.content">
|
<div id="banner" class="banner-bg hidden">
|
||||||
<div class="w-full banner-bg text-black text-center py-2 px-4">
|
<strong id="banner-title"></strong>: <span id="banner-content"></span>
|
||||||
<strong x-text="banner.title"></strong>: <span x-text="banner.content"></span>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Navbar -->
|
<!-- Navigation Bar -->
|
||||||
<nav class="accent-bg text-white px-4 py-3 shadow-md" x-data="{ open: false }">
|
<nav class="navbar accent-bg">
|
||||||
<div class="flex flex-wrap items-center justify-between">
|
<div class="nav-container">
|
||||||
<a href="/" class="text-xl font-semibold mr-4">BYU-I Amateur Radio Society</a>
|
<a href="/" class="nav-brand">BYU-I Amateur Radio Society</a>
|
||||||
<button @click="open = !open" class="sm:hidden text-white ml-auto focus:outline-none">
|
|
||||||
<svg x-show="!open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<!-- Mobile Hamburger Toggle -->
|
||||||
|
<button id="menu-toggle" class="icon-button mobile-only" aria-label="Toggle Navigation Menu">
|
||||||
|
<svg id="icon-hamburger" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg id="icon-close" class="icon hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="hidden sm:flex flex-grow justify-center space-x-4">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Desktop Links -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="hover:opacity-80 transition">
|
<div id="desktop-links" class="nav-links desktop-only"></div>
|
||||||
<span x-text="page.name"></span>
|
|
||||||
</a>
|
<!-- Desktop Dark Mode Toggle -->
|
||||||
</template>
|
<button class="theme-toggle icon-button desktop-only" aria-label="Toggle Dark Mode">
|
||||||
</div>
|
<svg class="icon icon-sun hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<div class="hidden sm:flex ml-auto">
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
||||||
<button @click="toggleDarkMode" class="ml-4 text-white focus:outline-none" title="Toggle dark mode">
|
</svg>
|
||||||
<svg x-show="!darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg class="icon icon-moon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
</button>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div x-show="open" class="sm:hidden mt-2 space-y-2">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Mobile Dropdown Menu -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="block px-2 py-1 hover:bg-white/10">
|
<div id="mobile-menu" class="mobile-menu mobile-only hidden">
|
||||||
<span x-text="page.name"></span>
|
<div id="mobile-links"></div>
|
||||||
</a>
|
<button class="theme-toggle mobile-theme-btn" aria-label="Toggle Dark Mode">
|
||||||
</template>
|
<span class="theme-text">🌙 Dark Mode</span>
|
||||||
<button @click="toggleDarkMode" class="w-full text-left px-2 py-1 text-white hover:bg-white/10" title="Toggle dark mode">
|
|
||||||
<span x-text="darkMode ? '☀️ Light Mode' : '🌙 Dark Mode'"></span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="flex-grow p-6">
|
<!-- Main Content -->
|
||||||
<h1 class="text-3xl font-bold mb-4">Our History</h1>
|
<main class="main-content">
|
||||||
|
<h1>Our History</h1>
|
||||||
|
|
||||||
<p class="mb-4">
|
<p>
|
||||||
The BYU-Idaho Amateur Radio Society has a long-standing tradition of service, education, and community involvement. Our roots go back to Rick's College in the mid-1900s, and we're proud to still be here thriving today.
|
The BYU-Idaho Amateur Radio Society has a long-standing tradition of service, education, and community involvement. Our roots go back to Ricks College in the mid-1900s, and we're proud to still be thriving today.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="mb-4">
|
<p>
|
||||||
This page is a work in progress — check back soon for a more detailed history of our club's leadership, milestones, and notable moments!
|
This page is a work in progress — check back soon for a more detailed history of our club's leadership, milestones, and notable moments!
|
||||||
</p>
|
</p>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="accent-bg text-white text-center py-4">
|
<!-- Footer -->
|
||||||
© <span x-text="new Date().getFullYear()"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
<footer class="footer accent-bg">
|
||||||
|
© 2025–<span id="current-year"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script>
|
|
||||||
function appData() {
|
|
||||||
return {
|
|
||||||
darkMode: document.documentElement.classList.contains('dark'),
|
|
||||||
currentPath: window.location.pathname,
|
|
||||||
banner: { title: '', content: '' },
|
|
||||||
pages: [],
|
|
||||||
async init() {
|
|
||||||
const navResp = await fetch('/assets/pages.json');
|
|
||||||
this.pages = await navResp.json();
|
|
||||||
|
|
||||||
const bannerResp = await fetch('/assets/banner.json?t=${Date.now()}');
|
|
||||||
this.banner = await bannerResp.json();
|
|
||||||
},
|
|
||||||
toggleDarkMode() {
|
|
||||||
this.darkMode = !this.darkMode;
|
|
||||||
document.documentElement.classList.toggle('dark');
|
|
||||||
localStorage.theme = this.darkMode ? 'dark' : 'light';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
+70
-111
@@ -4,136 +4,95 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>BYU-Idaho Amateur Radio Society</title>
|
<title>BYU-Idaho Amateur Radio Society</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<link rel="stylesheet" href="style.css" />
|
||||||
<script>
|
<script src="script.js" defer></script>
|
||||||
tailwind.config = {
|
|
||||||
darkMode: 'class'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js" defer></script>
|
|
||||||
<script>
|
|
||||||
// Dark mode persistence
|
|
||||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.accent-bg { background-color: #006eb6; }
|
|
||||||
.banner-bg { background-color: #a2daff; }
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-100 min-h-screen flex flex-col" x-data="appData()" x-init="init()">
|
<body>
|
||||||
|
|
||||||
<!-- Banner -->
|
<!-- Announcement Banner -->
|
||||||
<template x-if="banner.title && banner.content">
|
<div id="banner" class="banner-bg hidden">
|
||||||
<div class="w-full banner-bg text-black text-center py-2 px-4">
|
<strong id="banner-title"></strong>: <span id="banner-content"></span>
|
||||||
<strong x-text="banner.title"></strong>: <span x-text="banner.content"></span>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Navbar -->
|
<!-- Navigation Bar -->
|
||||||
<nav class="accent-bg text-white px-4 py-3 shadow-md" x-data="{ open: false }">
|
<nav class="navbar accent-bg">
|
||||||
<div class="flex flex-wrap items-center justify-between">
|
<div class="nav-container">
|
||||||
<a href="/" class="text-xl font-semibold mr-4">BYU-I Amateur Radio Society</a>
|
<a href="/" class="nav-brand">BYU-I Amateur Radio Society</a>
|
||||||
<button @click="open = !open" class="sm:hidden text-white ml-auto focus:outline-none">
|
|
||||||
<svg x-show="!open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<!-- Mobile Hamburger Toggle -->
|
||||||
|
<button id="menu-toggle" class="icon-button mobile-only" aria-label="Toggle Navigation Menu">
|
||||||
|
<svg id="icon-hamburger" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg id="icon-close" class="icon hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="hidden sm:flex flex-grow justify-center space-x-4">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Desktop Links -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="hover:opacity-80 transition">
|
<div id="desktop-links" class="nav-links desktop-only"></div>
|
||||||
<span x-text="page.name"></span>
|
|
||||||
</a>
|
<!-- Desktop Dark Mode Toggle -->
|
||||||
</template>
|
<button class="theme-toggle icon-button desktop-only" aria-label="Toggle Dark Mode">
|
||||||
</div>
|
<svg class="icon icon-sun hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<div class="hidden sm:flex ml-auto">
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
||||||
<button @click="toggleDarkMode" class="ml-4 text-white focus:outline-none" title="Toggle dark mode">
|
</svg>
|
||||||
<svg x-show="!darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg class="icon icon-moon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
</button>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div x-show="open" class="sm:hidden mt-2 space-y-2">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Mobile Dropdown Menu -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="block px-2 py-1 hover:bg-white/10">
|
<div id="mobile-menu" class="mobile-menu mobile-only hidden">
|
||||||
<span x-text="page.name"></span>
|
<div id="mobile-links"></div>
|
||||||
</a>
|
<button class="theme-toggle mobile-theme-btn" aria-label="Toggle Dark Mode">
|
||||||
</template>
|
<span class="theme-text">🌙 Dark Mode</span>
|
||||||
<button @click="toggleDarkMode" class="w-full text-left px-2 py-1 text-white hover:bg-white/10" title="Toggle dark mode">
|
|
||||||
<span x-text="darkMode ? '☀️ Light Mode' : '🌙 Dark Mode'"></span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- Main Content -->
|
<!-- Main Content -->
|
||||||
<main class="flex-grow p-6">
|
<main class="main-content home-content">
|
||||||
<h1 class="text-3xl font-bold mb-4">Welcome to the BYU-Idaho Amateur Radio Society!</h1>
|
<section class="hero" aria-labelledby="welcome-heading">
|
||||||
<p>Established in the mid-1900s, the BYU-Idaho Amateur Radio Society is one of the University's longest-operating student groups.</p>
|
<div class="hero-copy">
|
||||||
|
<p class="eyebrow">K7BYI · Rexburg, Idaho</p>
|
||||||
|
<h1 id="welcome-heading">Explore radio. Build community.</h1>
|
||||||
|
<p class="hero-lede">The BYU-Idaho Amateur Radio Society is one of the University's longest-running student groups—open to curious beginners and experienced operators alike.</p>
|
||||||
|
<div class="hero-actions">
|
||||||
|
<a class="button button-primary" href="https://discord.gg/D9fZ6uWugH" target="_blank" rel="noopener">Join our Discord <span aria-hidden="true">→</span></a>
|
||||||
|
<a class="button button-secondary" href="/exams.html">Get licensed</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<figure class="hero-image">
|
||||||
|
<img
|
||||||
|
src="/assets/i/summerfieldday_20250628_130113.jpg"
|
||||||
|
alt="BYUIARS members at Summer Field Day 2025"
|
||||||
|
class="featured-image"
|
||||||
|
/>
|
||||||
|
<figcaption>Summer Field Day 2025</figcaption>
|
||||||
|
</figure>
|
||||||
|
</section>
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold mt-6 mb-2">Get Involved</h2>
|
<section class="intro-section" aria-labelledby="involved-heading">
|
||||||
<p>We meet most Wednesdays during the semester in STC 231, and host weekly <a href="/net/" class="text-blue-400 underline">nets</a> on the 146.510 MHz K7BYI Repeater.
|
<div>
|
||||||
<br>
|
<p class="eyebrow">Start here</p>
|
||||||
For more information on current events and what we're up to, join our <a href="https://discord.gg/D9fZ6uWugH" class="text-blue-400 underline">Discord</a>!
|
<h2 id="involved-heading">Find your signal</h2>
|
||||||
|
</div>
|
||||||
|
<p>We meet most Wednesdays during the semester in STC 243 and host weekly <a href="/net/" class="link">nets</a> on the 146.510 MHz K7BYI repeater. No license or prior experience is required—we'll help you get started.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
<br><br>We have activies for all skill levels, and no license is required to participate with us (though we'd be happy to help you get yours if you like)</p>
|
<section class="card-grid" aria-label="Reasons to join">
|
||||||
<!-- Homepage Banner Image -->
|
<article class="info-card"><span class="card-number" aria-hidden="true">01</span><h2>Learn by doing</h2><p>Use and build radios, antennas, and practical projects with people who can help bring an idea to life.</p></article>
|
||||||
<div class="my-6">
|
<article class="info-card"><span class="card-number" aria-hidden="true">02</span><h2>Be ready</h2><p>Develop communication skills useful for emergencies, wilderness activities, and everyday problem-solving.</p></article>
|
||||||
<img
|
<article class="info-card"><span class="card-number" aria-hidden="true">03</span><h2>Make connections</h2><p>Meet fellow makers, find project collaborators, and explore scholarship and inter-society opportunities.</p></article>
|
||||||
src="/assets/i/summerfieldday_20250628_130113.jpg"
|
</section>
|
||||||
alt="BYUIARS members at Summer Field Day 2025"
|
</main>ß
|
||||||
class="w-full max-w-5xl mx-auto rounded shadow-md"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold mt-6 mb-2">Why Should I Join the Amateur Radio Society?</h2>
|
|
||||||
<ul class="list-disc pl-6 space-y-2">
|
|
||||||
<li>Hands-on opportunities to learn about, use, and build radios and antennas</li>
|
|
||||||
<li>Learn and apply physics</li>
|
|
||||||
<li>Be better prepared for emergencies and wilderness activities</li>
|
|
||||||
<li>Connect and network with some pretty cool folks</li>
|
|
||||||
<li>Obtain your federal Amateur Radio License at no cost to you (A $50 value!)</li>
|
|
||||||
<li>Plentiful scholarship opportunities</li>
|
|
||||||
<li>Inter-Society collaboration opportunities</li>
|
|
||||||
<li>Great project opportunities. Have a cool idea? We probably have people with the knowledge to help you make it happen!</li>
|
|
||||||
</ul>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<footer class="accent-bg text-white text-center py-4">
|
<footer class="footer accent-bg">
|
||||||
© 2025-<span x-text="new Date().getFullYear()"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
© 2025–<span id="current-year"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script>
|
|
||||||
function appData() {
|
|
||||||
return {
|
|
||||||
darkMode: document.documentElement.classList.contains('dark'),
|
|
||||||
currentPath: window.location.pathname,
|
|
||||||
banner: { title: '', content: '' },
|
|
||||||
pages: [],
|
|
||||||
async init() {
|
|
||||||
const navResp = await fetch('/assets/pages.json');
|
|
||||||
this.pages = await navResp.json();
|
|
||||||
|
|
||||||
const bannerResp = await fetch('/assets/banner.json?t=${Date.now()}');
|
|
||||||
this.banner = await bannerResp.json();
|
|
||||||
},
|
|
||||||
toggleDarkMode() {
|
|
||||||
this.darkMode = !this.darkMode;
|
|
||||||
document.documentElement.classList.toggle('dark');
|
|
||||||
localStorage.theme = this.darkMode ? 'dark' : 'light';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+348
-1677
File diff suppressed because it is too large
Load Diff
+58
-97
@@ -3,133 +3,94 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Rexburg Mesh - BYU-I Amateur Radio Society</title>
|
<title>Rexburg Mesh – BYU-Idaho Amateur Radio Society</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<link rel="stylesheet" href="/style.css" />
|
||||||
<script>
|
<script src="/script.js" defer></script>
|
||||||
tailwind.config = {
|
|
||||||
darkMode: 'class'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js" defer></script>
|
|
||||||
<style>
|
|
||||||
.accent-bg { background-color: #006eb6; }
|
|
||||||
.banner-bg { background-color: #a2daff; }
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-100 min-h-screen flex flex-col" x-data="appData()" x-init="init()">
|
<body>
|
||||||
|
|
||||||
<!-- Banner -->
|
<!-- Announcement Banner -->
|
||||||
<template x-if="banner.title && banner.content">
|
<div id="banner" class="banner-bg hidden">
|
||||||
<div class="w-full banner-bg text-black text-center py-2 px-4">
|
<strong id="banner-title"></strong>: <span id="banner-content"></span>
|
||||||
<strong x-text="banner.title"></strong>: <span x-text="banner.content"></span>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Navbar -->
|
<!-- Navigation Bar -->
|
||||||
<nav class="accent-bg text-white px-4 py-3 shadow-md" x-data="{ open: false }">
|
<nav class="navbar accent-bg">
|
||||||
<div class="flex flex-wrap items-center justify-between">
|
<div class="nav-container">
|
||||||
<a href="/" class="text-xl font-semibold mr-4">BYU-I Amateur Radio Society</a>
|
<a href="/" class="nav-brand">BYU-I Amateur Radio Society</a>
|
||||||
<button @click="open = !open" class="sm:hidden text-white ml-auto focus:outline-none">
|
|
||||||
<svg x-show="!open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<!-- Mobile Hamburger Toggle -->
|
||||||
|
<button id="menu-toggle" class="icon-button mobile-only" aria-label="Toggle Navigation Menu">
|
||||||
|
<svg id="icon-hamburger" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg id="icon-close" class="icon hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="hidden sm:flex flex-grow justify-center space-x-4">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Desktop Links -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="hover:opacity-80 transition">
|
<div id="desktop-links" class="nav-links desktop-only"></div>
|
||||||
<span x-text="page.name"></span>
|
|
||||||
</a>
|
<!-- Desktop Dark Mode Toggle -->
|
||||||
</template>
|
<button class="theme-toggle icon-button desktop-only" aria-label="Toggle Dark Mode">
|
||||||
</div>
|
<svg class="icon icon-sun hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<div class="hidden sm:flex ml-auto">
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
||||||
<button @click="toggleDarkMode" class="ml-4 text-white focus:outline-none" title="Toggle dark mode">
|
</svg>
|
||||||
<svg x-show="!darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg class="icon icon-moon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
</button>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div x-show="open" class="sm:hidden mt-2 space-y-2">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Mobile Dropdown Menu -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="block px-2 py-1 hover:bg-white/10">
|
<div id="mobile-menu" class="mobile-menu mobile-only hidden">
|
||||||
<span x-text="page.name"></span>
|
<div id="mobile-links"></div>
|
||||||
</a>
|
<button class="theme-toggle mobile-theme-btn" aria-label="Toggle Dark Mode">
|
||||||
</template>
|
<span class="theme-text">🌙 Dark Mode</span>
|
||||||
<button @click="toggleDarkMode" class="w-full text-left px-2 py-1 text-white hover:bg-white/10" title="Toggle dark mode">
|
|
||||||
<span x-text="darkMode ? '☀️ Light Mode' : '🌙 Dark Mode'"></span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="flex-grow p-6">
|
<!-- Main Content -->
|
||||||
<h1 class="text-3xl font-bold mb-4">Rexburg Meshtastic and MeshCore</h1>
|
<main class="main-content">
|
||||||
|
<h1>Rexburg Meshtastic and MeshCore</h1>
|
||||||
|
|
||||||
<p class="mb-4">
|
<p>
|
||||||
The BYU-I Amateur Radio Society is experimenting with Meshtastic and MeshCore! These are low-power, long-range mesh radio networks using LoRa devices to support off-grid communication. They are open for all to use and most nodes are designed to continue working in emergencies and extended power outages.
|
The BYU-I Amateur Radio Society is experimenting with Meshtastic and MeshCore! These are low-power, long-range mesh radio networks using LoRa devices to support off-grid communication. They are open for all to use and most nodes are designed to continue working in emergencies and extended power outages.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold mt-6 mb-2">How to Get Involved</h2>
|
<h2>How to Get Involved</h2>
|
||||||
<ul class="list-disc pl-6 space-y-2">
|
<ul class="styled-list">
|
||||||
<li>Purchase a supported LoRa radio (many of our members go with the Heltec V3 or RAK 4631), or check one out at one of our weekly meetings</li>
|
<li>Purchase a supported LoRa radio (many of our members go with the Heltec V3 or RAK 4631), or check one out at one of our weekly meetings</li>
|
||||||
<li>Flash the latest <a href="https://flasher.meshtastic.org/" class="text-blue-400 underline">Meshtastic</a> or <a href="https://flasher.meshcore.co.uk/" class="text-blue-400 underline">MeshCore</a> firmware</li>
|
<li>Flash the latest <a href="https://flasher.meshtastic.org/" class="link" target="_blank" rel="noopener">Meshtastic</a> or <a href="https://meshcore.io/flasher" class="link" target="_blank" rel="noopener">MeshCore</a> firmware</li>
|
||||||
<li>For Meshtastic: Change your Modem Preset to MediumFast, save, then change your Frequency Slot to 51. Then, change your Channel 0 name to Freq51 and the key to 1A==</li>
|
<li>For Meshtastic: Change your Modem Preset to MediumFast, save, then change your Frequency Slot to 51. Then, change your Channel 0 name to Freq51 and the key to 1A==</li>
|
||||||
<li>For MeshCore: Set your radio preset to United States and you're good to go!</li>
|
<li>For MeshCore: Set your radio preset to United States and you're good to go!</li>
|
||||||
<li>Join our <a href="https://discord.gg/D9fZ6uWugH" class="text-blue-400 underline">Discord</a> to get help, share your setup, and connect with us</li>
|
<li>Join our <a href="https://discord.gg/D9fZ6uWugH" class="link" target="_blank" rel="noopener">Discord</a> to get help, share your setup, and connect with us</li>
|
||||||
<li>Get your node on the map (if it's stationary) by letting us know about it</li>
|
<li>Get your node on the map (if it's stationary) by letting us know about it</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2 class="text-xl font-semibold mt-6 mb-2">MeshCore Propagation Maps</h2>
|
|
||||||
<p class="mb-4">Thanks to Roger Coudé and his work on RadioMobile, we have propagation maps available.<br><a href="./eimeshcore.htm" class="text-blue-400 underline">Click here to view.</a></p>
|
<h2>MeshCore Propagation Maps</h2>
|
||||||
<h2 class="text-xl font-semibold mt-6 mb-2">Current Meshtastic Node Map</h2>
|
<p>
|
||||||
<div class="aspect-w-16 aspect-h-9 mb-4">
|
Thanks to Roger Coudé and his work on RadioMobile, we have propagation maps available.<br />
|
||||||
|
<a href="./eimeshcore.htm" class="link">Click here to view.</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Current Meshtastic Node Map</h2>
|
||||||
|
<div class="map-container">
|
||||||
<iframe
|
<iframe
|
||||||
src="https://www.google.com/maps/d/u/1/embed?mid=1P5dIeUwP6589f-JT1CaLcsottrrgGRM&ehbc=2E312F"
|
src="https://eastidahomesh.com/live-map.html"
|
||||||
width="100%"
|
title="Current Meshtastic Node Map"
|
||||||
height="560"
|
|
||||||
class="w-full rounded shadow-md"
|
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
allowfullscreen>
|
allowfullscreen>
|
||||||
</iframe>
|
</iframe>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="accent-bg text-white text-center py-4">
|
<!-- Footer -->
|
||||||
© 2025-<span x-text="new Date().getFullYear()"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
<footer class="footer accent-bg">
|
||||||
|
© 2025–<span id="current-year"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script>
|
|
||||||
function appData() {
|
|
||||||
return {
|
|
||||||
darkMode: document.documentElement.classList.contains('dark'),
|
|
||||||
currentPath: window.location.pathname,
|
|
||||||
banner: { title: '', content: '' },
|
|
||||||
pages: [],
|
|
||||||
async init() {
|
|
||||||
const navResp = await fetch('/assets/pages.json');
|
|
||||||
this.pages = await navResp.json();
|
|
||||||
|
|
||||||
const bannerResp = await fetch('/assets/banner.json?t=${Date.now()}');
|
|
||||||
this.banner = await bannerResp.json();
|
|
||||||
},
|
|
||||||
toggleDarkMode() {
|
|
||||||
this.darkMode = !this.darkMode;
|
|
||||||
document.documentElement.classList.toggle('dark');
|
|
||||||
localStorage.theme = this.darkMode ? 'dark' : 'light';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
+59
-123
@@ -3,146 +3,82 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Net Check-Ins – BYU-I Amateur Radio Society</title>
|
<title>Net Check-Ins – BYU-Idaho Amateur Radio Society</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<link rel="stylesheet" href="/style.css" />
|
||||||
<script>
|
<script src="/script.js" defer></script>
|
||||||
tailwind.config = {
|
<script src="/net/netScript.js" defer></script>
|
||||||
darkMode: 'class'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
||||||
document.documentElement.classList.add('dark')
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js" defer></script>
|
|
||||||
<style>
|
|
||||||
.accent-bg { background-color: #006eb6; }
|
|
||||||
.banner-bg { background-color: #a2daff; }
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-100 min-h-screen flex flex-col" x-data="appData()" x-init="init()">
|
<body>
|
||||||
|
|
||||||
<!-- Banner -->
|
<!-- Announcement Banner -->
|
||||||
<template x-if="banner.title && banner.content">
|
<div id="banner" class="banner-bg hidden">
|
||||||
<div class="w-full banner-bg text-black text-center py-2 px-4">
|
<strong id="banner-title"></strong>: <span id="banner-content"></span>
|
||||||
<strong x-text="banner.title"></strong>: <span x-text="banner.content"></span>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Navbar -->
|
<!-- Navigation Bar -->
|
||||||
<nav class="accent-bg text-white px-4 py-3 shadow-md" x-data="{ open: false }">
|
<nav class="navbar accent-bg">
|
||||||
<div class="flex flex-wrap items-center justify-between">
|
<div class="nav-container">
|
||||||
<a href="/" class="text-xl font-semibold mr-4">BYU-I Amateur Radio Society</a>
|
<a href="/" class="nav-brand">BYU-I Amateur Radio Society</a>
|
||||||
<button @click="open = !open" class="sm:hidden text-white ml-auto focus:outline-none">
|
|
||||||
<svg x-show="!open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<!-- Mobile Hamburger Toggle -->
|
||||||
|
<button id="menu-toggle" class="icon-button mobile-only" aria-label="Toggle Navigation Menu">
|
||||||
|
<svg id="icon-hamburger" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="open" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg id="icon-close" class="icon hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="hidden sm:flex flex-grow justify-center space-x-4">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Desktop Links -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="hover:opacity-80 transition">
|
<div id="desktop-links" class="nav-links desktop-only"></div>
|
||||||
<span x-text="page.name"></span>
|
|
||||||
</a>
|
<!-- Desktop Dark Mode Toggle -->
|
||||||
</template>
|
<button class="theme-toggle icon-button desktop-only" aria-label="Toggle Dark Mode">
|
||||||
</div>
|
<svg class="icon icon-sun hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<div class="hidden sm:flex ml-auto">
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
||||||
<button @click="toggleDarkMode" class="ml-4 text-white focus:outline-none" title="Toggle dark mode">
|
</svg>
|
||||||
<svg x-show="!darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg class="icon icon-moon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg x-show="darkMode" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
</button>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div x-show="open" class="sm:hidden mt-2 space-y-2">
|
|
||||||
<template x-for="page in pages" :key="page.path">
|
<!-- Mobile Dropdown Menu -->
|
||||||
<a :href="page.path" :class="{ 'font-bold underline': currentPath === page.path }" class="block px-2 py-1 hover:bg-white/10">
|
<div id="mobile-menu" class="mobile-menu mobile-only hidden">
|
||||||
<span x-text="page.name"></span>
|
<div id="mobile-links"></div>
|
||||||
</a>
|
<button class="theme-toggle mobile-theme-btn" aria-label="Toggle Dark Mode">
|
||||||
</template>
|
<span class="theme-text">🌙 Dark Mode</span>
|
||||||
<button @click="toggleDarkMode" class="w-full text-left px-2 py-1 text-white hover:bg-white/10" title="Toggle dark mode">
|
|
||||||
<span x-text="darkMode ? '☀️ Light Mode' : '🌙 Dark Mode'"></span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="flex-grow p-6">
|
<!-- Main Content -->
|
||||||
<h1 class="text-3xl font-bold mb-4">Weekly Net Check-Ins</h1>
|
<main class="main-content">
|
||||||
<p>Our net meets each Tuesday at 8pm on the 146.510 repeater, which has a -6MHz offset and a bidirectional 100Hz tone. We'd love to hear you!</p>
|
<h1>Weekly Net Check-Ins</h1>
|
||||||
<br><br>
|
<p>
|
||||||
<div x-data="netStats()" x-init="load()">
|
Our net meets each Tuesday at 8pm on the 146.510 repeater, which has a -6MHz offset and a bidirectional 100Hz tone. We'd love to hear you!
|
||||||
|
</p>
|
||||||
|
|
||||||
<template x-if="callsigns.length">
|
<section id="callsigns-section" class="stats-section hidden">
|
||||||
<div>
|
<h2>Callsigns That Have Checked In since January 2025</h2>
|
||||||
<h2 class="text-xl font-semibold mb-2">Callsigns That Have Checked In since January 2025</h2>
|
<ul id="callsigns-list" class="column-list">
|
||||||
<ul class="columns-2 sm:columns-3 md:columns-4">
|
<!-- Dynamically populated from /net/net.json -->
|
||||||
<template x-for="call in callsigns" :key="call">
|
</ul>
|
||||||
<li x-text="call"></li>
|
</section>
|
||||||
</template>
|
|
||||||
</ul>
|
<section id="weekly-section" class="stats-section hidden">
|
||||||
</div>
|
<h2>Check-Ins Per Week</h2>
|
||||||
</template>
|
<ul id="weekly-list" class="styled-list">
|
||||||
<br><br>
|
<!-- Dynamically populated from /net/net.json -->
|
||||||
<template x-if="weekly.length">
|
</ul>
|
||||||
<div class="mb-6">
|
</section>
|
||||||
<h2 class="text-xl font-semibold mb-2">Check-Ins Per Week</h2>
|
|
||||||
<ul class="space-y-1">
|
|
||||||
<template x-for="week in weekly" :key="week.date">
|
|
||||||
<li>
|
|
||||||
<span x-text="week.date"></span>: <strong x-text="week.count"></strong> check-ins
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="accent-bg text-white text-center py-4">
|
<!-- Footer -->
|
||||||
© 2025-<span x-text="new Date().getFullYear()"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
<footer class="footer accent-bg">
|
||||||
|
© 2025–<span id="current-year"></span> BYU-Idaho Amateur Radio Society. All rights reserved.
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script>
|
|
||||||
function appData() {
|
|
||||||
return {
|
|
||||||
darkMode: document.documentElement.classList.contains('dark'),
|
|
||||||
currentPath: window.location.pathname,
|
|
||||||
banner: { title: '', content: '' },
|
|
||||||
pages: [],
|
|
||||||
async init() {
|
|
||||||
const navResp = await fetch('/assets/pages.json');
|
|
||||||
this.pages = await navResp.json();
|
|
||||||
|
|
||||||
const bannerResp = await fetch('/assets/banner.json?t=${Date.now()}');
|
|
||||||
this.banner = await bannerResp.json();
|
|
||||||
},
|
|
||||||
toggleDarkMode() {
|
|
||||||
this.darkMode = !this.darkMode;
|
|
||||||
document.documentElement.classList.toggle('dark');
|
|
||||||
localStorage.theme = this.darkMode ? 'dark' : 'light';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function netStats() {
|
|
||||||
return {
|
|
||||||
weekly: [],
|
|
||||||
callsigns: [],
|
|
||||||
async load() {
|
|
||||||
const data = await fetch('/net/net.json').then(res => res.json());
|
|
||||||
this.weekly = data.weekly || [];
|
|
||||||
this.callsigns = data.callsigns || [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Net Statistics Rendering */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
function renderNetStats(data, callsignsContainer, weeklyContainer) {
|
||||||
|
const callsigns = data.callsigns || [];
|
||||||
|
const weekly = data.weekly || [];
|
||||||
|
|
||||||
|
// Render Callsigns List
|
||||||
|
if (callsignsContainer && callsigns.length > 0) {
|
||||||
|
callsignsContainer.innerHTML = '';
|
||||||
|
callsigns.forEach(call => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.textContent = call;
|
||||||
|
callsignsContainer.appendChild(li);
|
||||||
|
});
|
||||||
|
document.getElementById('callsigns-section')?.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render Weekly Check-Ins List
|
||||||
|
if (weeklyContainer && weekly.length > 0) {
|
||||||
|
weeklyContainer.innerHTML = '';
|
||||||
|
weekly.forEach(week => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.innerHTML = `${week.date}: <strong>${week.count}</strong> check-ins`;
|
||||||
|
weeklyContainer.appendChild(li);
|
||||||
|
});
|
||||||
|
document.getElementById('weekly-section')?.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
initTheme();
|
||||||
|
initFooterYear();
|
||||||
|
initMobileMenu();
|
||||||
|
fetchPageData();
|
||||||
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Theme / Dark Mode Management */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
function initTheme() {
|
||||||
|
const isDarkStored = localStorage.theme === 'dark';
|
||||||
|
const noThemeStored = !('theme' in localStorage);
|
||||||
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
|
||||||
|
if (isDarkStored || (noThemeStored && prefersDark)) {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
}
|
||||||
|
|
||||||
|
updateThemeUI();
|
||||||
|
|
||||||
|
document.querySelectorAll('.theme-toggle').forEach(button => {
|
||||||
|
button.addEventListener('click', toggleDarkMode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleDarkMode() {
|
||||||
|
const isDark = document.documentElement.classList.toggle('dark');
|
||||||
|
localStorage.theme = isDark ? 'dark' : 'light';
|
||||||
|
updateThemeUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateThemeUI() {
|
||||||
|
const isDark = document.documentElement.classList.contains('dark');
|
||||||
|
|
||||||
|
document.querySelectorAll('.icon-sun').forEach(el => el.classList.toggle('hidden', !isDark));
|
||||||
|
document.querySelectorAll('.icon-moon').forEach(el => el.classList.toggle('hidden', isDark));
|
||||||
|
|
||||||
|
document.querySelectorAll('.theme-text').forEach(el => {
|
||||||
|
el.textContent = isDark ? '☀️ Light Mode' : '🌙 Dark Mode';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Footer Year Handler */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
function initFooterYear() {
|
||||||
|
const yearEl = document.getElementById('current-year');
|
||||||
|
if (yearEl) {
|
||||||
|
yearEl.textContent = new Date().getFullYear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Mobile Menu Toggle */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
function initMobileMenu() {
|
||||||
|
const menuToggleBtn = document.getElementById('menu-toggle');
|
||||||
|
const mobileMenu = document.getElementById('mobile-menu');
|
||||||
|
const iconHamburger = document.getElementById('icon-hamburger');
|
||||||
|
const iconClose = document.getElementById('icon-close');
|
||||||
|
|
||||||
|
if (!menuToggleBtn || !mobileMenu) return;
|
||||||
|
|
||||||
|
menuToggleBtn.setAttribute('aria-expanded', 'false');
|
||||||
|
|
||||||
|
menuToggleBtn.addEventListener('click', () => {
|
||||||
|
const isHidden = mobileMenu.classList.toggle('hidden');
|
||||||
|
menuToggleBtn.setAttribute('aria-expanded', String(!isHidden));
|
||||||
|
iconHamburger.classList.toggle('hidden', !isHidden);
|
||||||
|
iconClose.classList.toggle('hidden', isHidden);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Async Data Fetching (Pages, Banner & Exam Schedule) */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
async function fetchPageData() {
|
||||||
|
const currentPath = window.location.pathname;
|
||||||
|
|
||||||
|
// 1. Fetch Banner Data
|
||||||
|
try {
|
||||||
|
const bannerResp = await fetch(`/assets/banner.json?t=${Date.now()}`);
|
||||||
|
if (bannerResp.ok) {
|
||||||
|
const banner = await bannerResp.json();
|
||||||
|
if (banner && banner.title && banner.content) {
|
||||||
|
document.getElementById('banner-title').textContent = banner.title;
|
||||||
|
document.getElementById('banner-content').textContent = banner.content;
|
||||||
|
document.getElementById('banner').classList.remove('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to load banner data:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Fetch Navigation Links
|
||||||
|
try {
|
||||||
|
const navResp = await fetch('/assets/pages.json');
|
||||||
|
if (navResp.ok) {
|
||||||
|
const pages = await navResp.json();
|
||||||
|
renderNavigation(pages, currentPath);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to load navigation data:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Fetch Exam Schedule (only runs if the #exams-list element exists)
|
||||||
|
const examsContainer = document.getElementById('exams-list');
|
||||||
|
if (examsContainer) {
|
||||||
|
try {
|
||||||
|
const examResp = await fetch(`/assets/exams.json?t=${Date.now()}`);
|
||||||
|
if (examResp.ok) {
|
||||||
|
const exams = await examResp.json();
|
||||||
|
renderExams(exams, examsContainer);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to load exam data:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Fetch Net Check-In Data (only runs on pages containing #callsigns-list or #weekly-list)
|
||||||
|
const callsignsContainer = document.getElementById('callsigns-list');
|
||||||
|
const weeklyContainer = document.getElementById('weekly-list');
|
||||||
|
|
||||||
|
if (callsignsContainer || weeklyContainer) {
|
||||||
|
try {
|
||||||
|
const netResp = await fetch('/net/net.json');
|
||||||
|
if (netResp.ok) {
|
||||||
|
const data = await netResp.json();
|
||||||
|
renderNetStats(data, callsignsContainer, weeklyContainer);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to load net statistics data:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderNavigation(pages, currentPath) {
|
||||||
|
const desktopContainer = document.getElementById('desktop-links');
|
||||||
|
const mobileContainer = document.getElementById('mobile-links');
|
||||||
|
|
||||||
|
if (!desktopContainer || !mobileContainer) return;
|
||||||
|
|
||||||
|
desktopContainer.innerHTML = '';
|
||||||
|
mobileContainer.innerHTML = '';
|
||||||
|
|
||||||
|
pages.forEach(page => {
|
||||||
|
const desktopLink = document.createElement('a');
|
||||||
|
desktopLink.href = page.path;
|
||||||
|
desktopLink.textContent = page.name;
|
||||||
|
if (currentPath === page.path) desktopLink.classList.add('active');
|
||||||
|
desktopContainer.appendChild(desktopLink);
|
||||||
|
|
||||||
|
const mobileLink = document.createElement('a');
|
||||||
|
mobileLink.href = page.path;
|
||||||
|
mobileLink.textContent = page.name;
|
||||||
|
if (currentPath === page.path) mobileLink.classList.add('active');
|
||||||
|
mobileContainer.appendChild(mobileLink);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderExams(exams, container) {
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
if (Array.isArray(exams) && exams.length > 0) {
|
||||||
|
exams.forEach(exam => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.append(`${exam.date}, ${exam.time} – ${exam.location} – `);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = exam.register;
|
||||||
|
link.className = 'link';
|
||||||
|
link.target = '_blank';
|
||||||
|
link.rel = 'noopener';
|
||||||
|
link.textContent = 'Register here';
|
||||||
|
li.appendChild(link);
|
||||||
|
container.appendChild(li);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.textContent = "We don't have any sessions scheduled right now, but if you're ready to test let us know and we'll set one up!";
|
||||||
|
container.appendChild(li);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
:root {
|
||||||
|
--bg-color: #f7f9fb;
|
||||||
|
--surface-color: #ffffff;
|
||||||
|
--text-color: #17212b;
|
||||||
|
--muted-color: #536272;
|
||||||
|
--accent-color: #005da8;
|
||||||
|
--accent-strong: #00477f;
|
||||||
|
--banner-bg: #d8efff;
|
||||||
|
--banner-text: #123653;
|
||||||
|
--link-color: #005da8;
|
||||||
|
--border-color: #dce4ea;
|
||||||
|
--nav-hover: rgba(255, 255, 255, 0.16);
|
||||||
|
--shadow: 0 12px 30px rgba(23, 33, 43, 0.08);
|
||||||
|
--border-radius: 12px;
|
||||||
|
--font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark {
|
||||||
|
--bg-color: #111a23;
|
||||||
|
--surface-color: #18242f;
|
||||||
|
--text-color: #edf4f8;
|
||||||
|
--muted-color: #b3c0ca;
|
||||||
|
--banner-bg: #173b58;
|
||||||
|
--banner-text: #e1f3ff;
|
||||||
|
--border-color: #2d3d4a;
|
||||||
|
--link-color: #82c9fa;
|
||||||
|
--shadow: 0 12px 30px rgba(0, 0, 0, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
body { background: var(--bg-color); color: var(--text-color); display: flex; flex-direction: column; font-family: var(--font-family); line-height: 1.65; min-height: 100vh; }
|
||||||
|
.hidden { display: none !important; }
|
||||||
|
.accent-bg { background-color: var(--accent-color); color: #fff; }
|
||||||
|
.banner-bg { background-color: var(--banner-bg); color: var(--banner-text); }
|
||||||
|
.link { color: var(--link-color); font-weight: 600; text-decoration-thickness: 0.1em; text-underline-offset: 0.15em; }
|
||||||
|
a:focus-visible, button:focus-visible { outline: 3px solid #f4b942; outline-offset: 3px; }
|
||||||
|
|
||||||
|
#banner { font-size: 0.925rem; padding: 0.65rem 1rem; text-align: center; }
|
||||||
|
.navbar { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12); padding: 0.9rem 1.25rem; }
|
||||||
|
.nav-container { align-items: center; display: flex; justify-content: space-between; margin: 0 auto; max-width: 1120px; }
|
||||||
|
.nav-brand { color: #fff; font-size: 1.1rem; font-weight: 700; letter-spacing: -0.02em; text-decoration: none; }
|
||||||
|
.nav-links { display: flex; gap: 0.25rem; }
|
||||||
|
.nav-links a { border-radius: 0.4rem; color: #fff; padding: 0.4rem 0.65rem; text-decoration: none; transition: background-color 0.2s ease; }
|
||||||
|
.nav-links a:hover, .nav-links a.active { background-color: var(--nav-hover); }
|
||||||
|
.nav-links a.active { font-weight: 700; }
|
||||||
|
.icon-button { align-items: center; background: none; border: 0; border-radius: 0.4rem; color: #fff; cursor: pointer; display: flex; padding: 0.4rem; }
|
||||||
|
.icon { height: 1.5rem; width: 1.5rem; }
|
||||||
|
.mobile-menu { display: flex; flex-direction: column; gap: 0.25rem; margin-top: 0.5rem; }
|
||||||
|
.mobile-menu a, .mobile-theme-btn { background: none; border: 0; border-radius: var(--border-radius); color: #fff; cursor: pointer; font-size: 1rem; padding: 0.5rem; text-align: left; text-decoration: none; }
|
||||||
|
.mobile-menu a:hover, .mobile-theme-btn:hover { background-color: var(--nav-hover); }
|
||||||
|
|
||||||
|
.main-content { flex-grow: 1; margin: 0 auto; max-width: 960px; padding: clamp(2rem, 5vw, 4.5rem) 1.25rem; width: 100%; }
|
||||||
|
h1 { font-size: clamp(2rem, 5vw, 3.75rem); font-weight: 700; letter-spacing: -0.045em; line-height: 1.05; margin-bottom: 1.25rem; }
|
||||||
|
h2 { font-size: clamp(1.25rem, 2vw, 1.55rem); font-weight: 700; letter-spacing: -0.025em; margin: 2rem 0 0.5rem; }
|
||||||
|
p { margin-bottom: 1rem; max-width: 70ch; }
|
||||||
|
.styled-list { margin-bottom: 1rem; padding-left: 1.5rem; }
|
||||||
|
.styled-list li { margin-bottom: 0.6rem; }
|
||||||
|
.footer { font-size: 0.875rem; margin-top: auto; padding: 1.5rem 1rem; text-align: center; }
|
||||||
|
|
||||||
|
.home-content { max-width: 1120px; }
|
||||||
|
.hero { align-items: center; display: grid; gap: clamp(2rem, 5vw, 4.5rem); grid-template-columns: 1fr 1fr; min-height: 29rem; }
|
||||||
|
.eyebrow { color: var(--accent-color); font-size: 0.78rem; font-weight: 800; letter-spacing: 0.11em; margin-bottom: 0.8rem; text-transform: uppercase; }
|
||||||
|
.hero-lede { color: var(--muted-color); font-size: clamp(1.05rem, 1.8vw, 1.2rem); }
|
||||||
|
.hero-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.5rem; }
|
||||||
|
.button { align-items: center; border-radius: 0.5rem; display: inline-flex; font-weight: 750; justify-content: center; min-height: 2.75rem; padding: 0.55rem 1rem; text-decoration: none; transition: background-color 0.2s ease, transform 0.2s ease; }
|
||||||
|
.button:hover { transform: translateY(-1px); }
|
||||||
|
.button-primary { background: var(--accent-color); color: #fff; }
|
||||||
|
.button-primary:hover { background: var(--accent-strong); }
|
||||||
|
.button-secondary { border: 1px solid var(--border-color); color: var(--text-color); }
|
||||||
|
.button-secondary:hover { background: var(--surface-color); }
|
||||||
|
.hero-image { margin: 0; position: relative; }
|
||||||
|
.hero-image figcaption { color: var(--muted-color); font-size: 0.8rem; margin-top: 0.5rem; }
|
||||||
|
.featured-image { aspect-ratio: 4 / 3; border-radius: var(--border-radius); box-shadow: var(--shadow); display: block; object-fit: cover; width: 100%; }
|
||||||
|
.intro-section { border-block: 1px solid var(--border-color); display: grid; gap: 2rem; grid-template-columns: minmax(11rem, 0.75fr) 1.25fr; margin: clamp(3rem, 8vw, 6rem) 0 2rem; padding: 2rem 0; }
|
||||||
|
.intro-section h2 { margin: 0; }
|
||||||
|
.intro-section p { color: var(--muted-color); font-size: 1.05rem; margin: 0; }
|
||||||
|
.card-grid { display: grid; gap: 1rem; grid-template-columns: repeat(3, 1fr); }
|
||||||
|
.info-card { background: var(--surface-color); border: 1px solid var(--border-color); border-radius: var(--border-radius); box-shadow: 0 2px 5px rgba(23, 33, 43, 0.025); padding: 1.5rem; }
|
||||||
|
.info-card h2 { font-size: 1.15rem; margin: 0.35rem 0 0.65rem; }
|
||||||
|
.info-card p { color: var(--muted-color); font-size: 0.95rem; margin: 0; }
|
||||||
|
.card-number { color: var(--accent-color); font-size: 0.75rem; font-weight: 800; letter-spacing: 0.1em; }
|
||||||
|
|
||||||
|
.stats-section { margin-top: 2rem; }
|
||||||
|
.column-list { column-count: 2; column-gap: 1.5rem; list-style: none; padding: 0; }
|
||||||
|
.column-list li { margin-bottom: 0.25rem; }
|
||||||
|
.map-container { border-radius: var(--border-radius); box-shadow: var(--shadow); margin-bottom: 1.5rem; overflow: hidden; position: relative; width: 100%; }
|
||||||
|
.map-container iframe { border: 0; display: block; height: 560px; width: 100%; }
|
||||||
|
|
||||||
|
@media (min-width: 640px) { .mobile-only { display: none !important; } .column-list { column-count: 3; } }
|
||||||
|
@media (min-width: 768px) { .column-list { column-count: 4; } }
|
||||||
|
@media (max-width: 639px) {
|
||||||
|
.desktop-only { display: none !important; }
|
||||||
|
.navbar { padding-inline: 1rem; }
|
||||||
|
.nav-brand { font-size: 1rem; }
|
||||||
|
.hero, .intro-section { grid-template-columns: 1fr; }
|
||||||
|
.hero { min-height: 0; }
|
||||||
|
.hero-image { grid-row: 1; }
|
||||||
|
.card-grid { grid-template-columns: 1fr; }
|
||||||
|
.map-container iframe { height: 380px; }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user