Merge pull request #2 from Fretuks/overhaul-calculator-for-anomaly-front

Refresh Anomaly Front pages, nav and calculator UI; fix input focus
This commit is contained in:
2026-01-14 20:14:48 +01:00
committed by GitHub
5 changed files with 393 additions and 236 deletions
+155 -21
View File
@@ -282,9 +282,9 @@ input[type="text"], input[type="number"], textarea {
} }
input[type="text"]:focus, input[type="number"]:focus, textarea:focus { input[type="text"]:focus, input[type="number"]:focus, textarea:focus {
border-color: black; border-color: #60a5fa;
box-shadow: 0 0 5px darkred; box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.35);
background-color: #fff; background-color: #0f172a;
outline: none; outline: none;
} }
@@ -1073,9 +1073,9 @@ th, td {
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
gap: 24px; gap: 24px;
background: rgba(15, 23, 42, 0.7); background: linear-gradient(135deg, rgba(15, 23, 42, 0.85), rgba(30, 41, 59, 0.6));
border: 1px solid rgba(148, 163, 184, 0.2); border: 1px solid rgba(148, 163, 184, 0.25);
border-radius: 20px; border-radius: 24px;
padding: 20px 28px; padding: 20px 28px;
margin-bottom: 24px; margin-bottom: 24px;
position: relative; position: relative;
@@ -1083,22 +1083,50 @@ th, td {
backdrop-filter: blur(12px); backdrop-filter: blur(12px);
} }
.af-header::before {
content: "";
position: absolute;
inset: 0;
border-radius: 24px;
padding: 1px;
background: linear-gradient(120deg, rgba(56, 189, 248, 0.6), rgba(59, 130, 246, 0.2), rgba(14, 116, 144, 0.5));
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
.af-brand { .af-brand {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16px; gap: 16px;
} }
.af-badge { .af-logo {
font-size: 0.9rem; width: 44px;
font-weight: 600; height: 44px;
letter-spacing: 0.08em; display: grid;
text-transform: uppercase; grid-template-columns: repeat(2, 1fr);
background: rgba(59, 130, 246, 0.2); grid-template-rows: repeat(2, 1fr);
color: #bae6fd; gap: 4px;
padding: 6px 12px; padding: 6px;
border-radius: 999px; border-radius: 14px;
border: 1px solid rgba(59, 130, 246, 0.35); background: rgba(15, 23, 42, 0.8);
border: 1px solid rgba(148, 163, 184, 0.35);
box-shadow: 0 8px 20px rgba(2, 6, 23, 0.45);
}
.af-logo span {
border-radius: 6px;
background: linear-gradient(135deg, rgba(56, 189, 248, 0.9), rgba(59, 130, 246, 0.6));
}
.af-logo span:nth-child(2) {
background: linear-gradient(135deg, rgba(14, 116, 144, 0.9), rgba(2, 132, 199, 0.6));
}
.af-logo span:nth-child(3) {
background: linear-gradient(135deg, rgba(37, 99, 235, 0.9), rgba(15, 23, 42, 0.6));
} }
.af-title { .af-title {
@@ -1114,27 +1142,63 @@ th, td {
font-size: 0.95rem; font-size: 0.95rem;
} }
.af-nav-toggle {
display: none;
align-items: center;
gap: 8px;
padding: 8px 14px;
border-radius: 999px;
background: rgba(15, 23, 42, 0.6);
border: 1px solid rgba(148, 163, 184, 0.35);
color: #e2e8f0;
font-weight: 600;
cursor: pointer;
z-index: 1;
}
.af-nav { .af-nav {
display: flex; display: flex;
gap: 16px; gap: 16px;
flex-wrap: wrap; flex-wrap: wrap;
z-index: 1;
} }
.af-nav a { .af-nav-link {
position: relative;
color: #e2e8f0; color: #e2e8f0;
font-weight: 500; font-weight: 500;
padding: 8px 14px; padding: 8px 16px;
border-radius: 999px; border-radius: 999px;
border: 1px solid rgba(148, 163, 184, 0.2); border: 1px solid rgba(148, 163, 184, 0.3);
background: rgba(15, 23, 42, 0.4); background: rgba(15, 23, 42, 0.4);
transition: transform 0.2s ease, box-shadow 0.2s ease;
} }
.af-nav a:hover { .af-nav-link::after {
content: "";
position: absolute;
left: 16px;
right: 16px;
bottom: 6px;
height: 2px;
border-radius: 999px;
background: linear-gradient(90deg, rgba(56, 189, 248, 0), rgba(56, 189, 248, 0.9), rgba(56, 189, 248, 0));
opacity: 0;
transition: opacity 0.2s ease;
}
.af-nav-link:hover {
color: #fff; color: #fff;
background: rgba(59, 130, 246, 0.3); background: rgba(59, 130, 246, 0.3);
box-shadow: 0 10px 20px rgba(14, 116, 144, 0.2);
transform: translateY(-1px);
text-decoration: none; text-decoration: none;
} }
.af-nav-link:hover::after {
opacity: 1;
}
.af-shell { .af-shell {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -1201,6 +1265,29 @@ th, td {
box-shadow: 0 16px 30px rgba(2, 6, 23, 0.35); box-shadow: 0 16px 30px rgba(2, 6, 23, 0.35);
} }
.af-card-actions {
margin-top: 18px;
}
.af-cta {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 10px 18px;
border-radius: 999px;
background: linear-gradient(120deg, rgba(56, 189, 248, 0.9), rgba(59, 130, 246, 0.85));
color: #f8fafc;
font-weight: 600;
border: 1px solid rgba(56, 189, 248, 0.6);
box-shadow: 0 12px 24px rgba(14, 116, 144, 0.35);
}
.af-cta:hover {
color: #fff;
text-decoration: none;
transform: translateY(-1px);
}
.af-card-header h2 { .af-card-header h2 {
margin-top: 0; margin-top: 0;
color: #f8fafc; color: #f8fafc;
@@ -1229,6 +1316,31 @@ th, td {
color: #f8fafc; color: #f8fafc;
} }
.af-form input:focus,
.af-notes:focus,
.af-input:focus {
border-color: rgba(56, 189, 248, 0.7);
box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.35);
background: rgba(15, 23, 42, 0.92);
color: #f8fafc;
}
.af-field {
display: grid;
gap: 6px;
color: #e2e8f0;
font-weight: 500;
}
.af-input {
width: 100%;
padding: 12px 14px;
border-radius: 12px;
background: rgba(15, 23, 42, 0.8);
border: 1px solid rgba(148, 163, 184, 0.3);
color: #f8fafc;
}
.af-form-actions { .af-form-actions {
display: flex; display: flex;
gap: 12px; gap: 12px;
@@ -1325,6 +1437,17 @@ th, td {
resize: vertical; resize: vertical;
} }
.af-copy-grid {
display: grid;
gap: 18px;
color: #cbd5f5;
}
.af-copy-grid ul {
padding-left: 18px;
margin: 8px 0 0;
}
@media (max-width: 720px) { @media (max-width: 720px) {
.af-body { .af-body {
padding: 20px; padding: 20px;
@@ -1335,8 +1458,19 @@ th, td {
align-items: flex-start; align-items: flex-start;
} }
.af-nav-toggle {
display: inline-flex;
}
.af-nav { .af-nav {
width: 100%; width: 100%;
justify-content: flex-start; flex-direction: column;
align-items: flex-start;
gap: 10px;
display: none;
}
.af-nav.is-open {
display: flex;
} }
} }
+77 -93
View File
@@ -3,114 +3,98 @@
<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>About Us - TRL Stats</title> <title>About | Anomaly Front Toolkit</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"/> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"/>
</head> </head>
<body class="af-body">
<body> <header class="af-header">
<header> <div class="af-brand">
<nav> <div class="af-logo" aria-hidden="true">
<button class="hamburger" aria-label="Toggle menu" aria-expanded="false" aria-controls="nav-menu"> <span></span>
<span class="bar"></span> <span></span>
<span class="bar"></span> <span></span>
<span class="bar"></span>
</button>
<div class="nav-menu" id="nav-menu">
<a href="{{ url_for('calculator') }}">DPS/DPM CALCULATOR</a>
<a href="{{ url_for('index') }}">GUN STATS</a>
<a href="{{ url_for('suggestion') }}">SUGGESTIONS & FEEDBACK</a>
<a href="https://www.roblox.com/games/5766084948/SCP-The-Red-Lake-EVENT">PLAY THE RED LAKE</a>
<a href="https://discord.gg/2jDevH8aTd">OUR DISCORD</a>
</div> </div>
<div>
<p class="af-title">Anomaly Front</p>
<p class="af-subtitle">About the toolkit</p>
</div>
</div>
<button class="af-nav-toggle" type="button" aria-expanded="false" aria-controls="af-nav">
Menu
</button>
<nav class="af-nav" id="af-nav" aria-label="Primary">
<a class="af-nav-link" href="{{ url_for('index') }}">Home</a>
<a class="af-nav-link" href="{{ url_for('calculator') }}">Calculator</a>
<a class="af-nav-link" href="{{ url_for('suggestion') }}">Feedback</a>
</nav> </nav>
</header> </header>
<main class="about_us_main"> <main class="af-shell">
<h1 class="about_us_h1">About Us</h1> <section class="af-card">
<div class="af-card-header">
<h3 class="about_us_h3"><b>Hey there!</b> You found the TRL Stats Page by <b>Fretux</b> and <b>Losernoob124</b></h3> <h1>About the Anomaly Front toolkit</h1>
<p>
<h2 class="about_us_h2">Our Mission</h2> This site is the staging ground for an unreleased experience. We are rebuilding every tool from the
<p class="about_us_text"> ground up to avoid legacy stats, old branding, or outdated data.
We created this platform to help the TRL community quickly and easily calculate gun DPS and DPM. No
spreadsheets, no hassle. Whether you're theorycrafting a Deathwish loadout or comparing your sidearms, our
tool’s built to support your grind.
</p>
<p class="about_us_text">
Got ideas or stat suggestions? Hit us up on Discord or submit feedback via our <a
href="{{ url_for('suggestion') }}">Suggestions Page</a>.
</p>
<h2 class="about_us_h2">Our Story</h2>
<p class="about_us_text">
It started with a spreadsheet... and frustration. Calculating DPS manually was tedious and we knew we could do
better. What began as a side hobby by Losernoob124 was reignited by Fretux and evolved into a full web app
through plenty of bug fixing, community help, and caffeine.
</p>
<h2 class="about_us_h2">The Team</h2>
<div class="team-section">
<div class="team-member">
<b>Fretux</b> – Frontend Developer & Data Specialist. Designs the UI and ensures stat accuracy.
</div>
<div class="team-member">
<b>Losernoob124</b> – Backend Developer. Handles everything under the hood and makes sure the calculators
work.
</div>
</div>
<h2 class="about_us_h2">Frequently Asked Questions</h2>
<div class="faq">
<p><b>How do you calculate DPS and DPM?</b></p>
<p class="about_us_text">
We use data from <a
href="https://docs.google.com/spreadsheets/d/1hGGLMOKB5Tj3FSo38HX7WbIvOmMbgfE5ZApTSOZgnS8/edit?gid=0#gid=0"
target="_blank">Lanz1021's Stat Sheet</a>, convert it into a JSON structure, and use it with formulas
similar to what’s on the sheet.
</p>
<p><b>How often are stats updated?</b></p>
<p class="about_us_text">
We update our database every time TRL releases a gameplay patch or changes weapon stats.
</p> </p>
</div> </div>
<div class="af-copy-grid">
<h2 class="about_us_h2">Special Thanks</h2> <div>
<div class="thanks-section"> <h2>Purpose</h2>
<p><b>gameknight90999 (holdenn)</b>: Helped with various stat and weapon data and ideas</p> <p>
<p><b>Kris HD</b>: Motivation + bug hunting</p> Provide a shared workspace for balancing weapons, capturing loadout notes, and testing combat pacing
<p><b>Lanz1021</b>: Feedback & review</p> long before the official numbers land.
<p><b>YOU</b>: For visiting — thank you!</p> </p>
</div> </div>
<div>
<h2>What is live today</h2>
<ul>
<li>Baseline combat calculator</li>
<li>Notes and modifier placeholders</li>
<li>Feedback capture workflow</li>
</ul>
</div>
<div>
<h2>What comes next</h2>
<ul>
<li>Shared weapon library for early drafts</li>
<li>Attachment tuning stacks</li>
<li>Operative perks and passive effects</li>
</ul>
</div>
</div>
</section>
<h3 class="about_us_text" style="text-align: center; margin-top: 2rem;"> <section class="af-grid">
Thanks for using <b>TRL Stats</b> <div class="af-card">
</h3> <div class="af-card-header">
<h2>Team notes</h2>
<p>
This is a community-driven project. Use the feedback channel to share balancing ideas, feature
requests, and UI improvements.
</p>
</div>
</div>
<div class="af-card">
<div class="af-card-header">
<h2>Release posture</h2>
<p>
Anomaly Front is unreleased. Everything shown here is a placeholder designed to help us think
through combat pacing before the official data arrives.
</p>
</div>
</div>
</section>
</main> </main>
<script> <script>
const hamburger = document.querySelector('.hamburger'); const navToggle = document.querySelector('.af-nav-toggle');
const navMenu = document.querySelector('.nav-menu'); const nav = document.getElementById('af-nav');
function setMenu(open) { navToggle.addEventListener('click', () => {
hamburger.classList.toggle('active', open); const isOpen = nav.classList.toggle('is-open');
navMenu.classList.toggle('active', open); navToggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
document.body.classList.toggle('menu-open', open);
hamburger.setAttribute('aria-expanded', open ? 'true' : 'false');
}
hamburger.addEventListener('click', () => {
const isOpen = hamburger.classList.contains('active');
setMenu(!isOpen);
}); });
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') setMenu(false);
});
navMenu.querySelectorAll('a').forEach(link =>
link.addEventListener('click', () => setMenu(false))
);
</script> </script>
</body> </body>
</html> </html>
+23 -7
View File
@@ -9,16 +9,23 @@
<body class="af-body"> <body class="af-body">
<header class="af-header"> <header class="af-header">
<div class="af-brand"> <div class="af-brand">
<span class="af-badge">Anomaly Front</span> <div class="af-logo" aria-hidden="true">
<span></span>
<span></span>
<span></span>
</div>
<div> <div>
<p class="af-title">Combat Calculator</p> <p class="af-title">Anomaly Front</p>
<p class="af-subtitle">Pre-release layout for internal balancing and community planning.</p> <p class="af-subtitle">Combat Calculator</p>
</div> </div>
</div> </div>
<nav class="af-nav" aria-label="Primary"> <button class="af-nav-toggle" type="button" aria-expanded="false" aria-controls="af-nav">
<a href="{{ url_for('index') }}">Home</a> Menu
<a href="{{ url_for('suggestion') }}">Feedback</a> </button>
<a href="{{ url_for('about_us') }}">About</a> <nav class="af-nav" id="af-nav" aria-label="Primary">
<a class="af-nav-link" href="{{ url_for('index') }}">Home</a>
<a class="af-nav-link" href="{{ url_for('suggestion') }}">Feedback</a>
<a class="af-nav-link" href="{{ url_for('about_us') }}">About</a>
</nav> </nav>
</header> </header>
<main class="af-shell"> <main class="af-shell">
@@ -151,5 +158,14 @@
</section> </section>
</main> </main>
<script src="{{ url_for('static', filename='filterWeapons.js') }}"></script> <script src="{{ url_for('static', filename='filterWeapons.js') }}"></script>
<script>
const navToggle = document.querySelector('.af-nav-toggle');
const nav = document.getElementById('af-nav');
navToggle.addEventListener('click', () => {
const isOpen = nav.classList.toggle('is-open');
navToggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
});
</script>
</body> </body>
</html> </html>
+81 -62
View File
@@ -3,75 +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>Gun Stats</title> <title>Anomaly Front | Operations Hub</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head> </head>
<header> <body class="af-body">
<nav> <header class="af-header">
<button class="hamburger" aria-label="Toggle menu" aria-expanded="false" aria-controls="nav-menu"> <div class="af-brand">
<span class="bar"></span> <div class="af-logo" aria-hidden="true">
<span class="bar"></span> <span></span>
<span class="bar"></span> <span></span>
</button> <span></span>
<div class="nav-menu" id="nav-menu">
<a href="{{ url_for('calculator') }}">DPS/DPM CALCULATOR</a>
<a href="{{ url_for('about_us') }}">ABOUT US</a>
<a href="{{ url_for('suggestion') }}">SUGGESTIONS & FEEDBACK</a>
<a href="https://www.roblox.com/games/5766084948/SCP-The-Red-Lake-EVENT">PLAY THE RED LAKE</a>
<a href="https://discord.gg/2jDevH8aTd">OUR DISCORD</a>
</div> </div>
<div>
<p class="af-title">Anomaly Front</p>
<p class="af-subtitle">Operations hub for the unreleased toolkit.</p>
</div>
</div>
<button class="af-nav-toggle" type="button" aria-expanded="false" aria-controls="af-nav">
Menu
</button>
<nav class="af-nav" id="af-nav" aria-label="Primary">
<a class="af-nav-link" href="{{ url_for('calculator') }}">Calculator</a>
<a class="af-nav-link" href="{{ url_for('suggestion') }}">Feedback</a>
<a class="af-nav-link" href="{{ url_for('about_us') }}">About</a>
</nav> </nav>
</header> </header>
<body class="background-image"> <main class="af-shell">
<main> <section class="af-hero">
<h1>Gun Stats</h1> <div>
<div class="search-container"> <h1>Welcome to the Anomaly Front planning space</h1>
<input type="text" id="search" placeholder="Search by name" onkeyup="filterTable()"> <p>
This hub replaces the legacy stats pages with a clean foundation for a new game. Start with the
calculator, capture balancing ideas, and iterate as official data arrives.
</p>
</div> </div>
<table id="gun-stats" class="background-roster"> <div class="af-status">
<thead> <div>
<tr> <p class="af-status-label">Core modules</p>
<th>Name</th> <p class="af-status-value">Calculator • Notes • Roadmap</p>
<th>Damage</th> </div>
<th>Rounds per minute</th> <div>
<th>Magazine Size</th> <p class="af-status-label">Data state</p>
<th>Reload time</th> <p class="af-status-value">Prototype-only</p>
<th>RPS</th> </div>
<th>DPS</th> <div>
<th>DPM</th> <p class="af-status-label">Next release</p>
<th>Avg DPS</th> <p class="af-status-value">Loadout library</p>
</tr> </div>
</thead> </div>
<tbody> </section>
<!-- Gun stats will be populated here -->
</tbody>
</table>
<script src="{{ url_for('static', filename='populateTable.js') }}"></script>
<script src="{{ url_for('static', filename='filterTable.js') }}"></script>
<script>
const hamburger = document.querySelector('.hamburger');
const navMenu = document.querySelector('.nav-menu');
function setMenu(open) { <section class="af-grid">
hamburger.classList.toggle('active', open); <div class="af-card">
navMenu.classList.toggle('active', open); <div class="af-card-header">
document.body.classList.toggle('menu-open', open); <h2>Start a baseline build</h2>
hamburger.setAttribute('aria-expanded', open ? 'true' : 'false'); <p>Jump into the combat calculator and block out a weapon profile in minutes.</p>
} </div>
<div class="af-card-actions">
hamburger.addEventListener('click', () => { <a class="af-cta" href="{{ url_for('calculator') }}">Open calculator</a>
const isOpen = hamburger.classList.contains('active'); </div>
setMenu(!isOpen); </div>
}); <div class="af-card">
<div class="af-card-header">
document.addEventListener('keydown', (e) => { <h2>Capture early feedback</h2>
if (e.key === 'Escape') setMenu(false); <p>Use the feedback page to log concepts, UI tweaks, and balancing ideas.</p>
}); </div>
<div class="af-card-actions">
navMenu.querySelectorAll('a').forEach(link => <a class="af-cta" href="{{ url_for('suggestion') }}">Leave feedback</a>
link.addEventListener('click', () => setMenu(false)) </div>
); </div>
</script> <div class="af-card">
<div class="af-card-header">
<h2>Align on the vision</h2>
<p>Keep the team on the same page with the updated Anomaly Front background.</p>
</div>
<div class="af-card-actions">
<a class="af-cta" href="{{ url_for('about_us') }}">Read the brief</a>
</div>
</div>
</section>
</main> </main>
<script>
const navToggle = document.querySelector('.af-nav-toggle');
const nav = document.getElementById('af-nav');
navToggle.addEventListener('click', () => {
const isOpen = nav.classList.toggle('is-open');
navToggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
});
</script>
</body> </body>
</html> </html>
+52 -48
View File
@@ -4,68 +4,72 @@
<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">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<title>Suggestion</title> <title>Feedback | Anomaly Front</title>
</head> </head>
<header> <body class="af-body">
<nav> <header class="af-header">
<button class="hamburger" aria-label="Toggle menu" aria-expanded="false" aria-controls="nav-menu"> <div class="af-brand">
<span class="bar"></span> <div class="af-logo" aria-hidden="true">
<span class="bar"></span> <span></span>
<span class="bar"></span> <span></span>
</button> <span></span>
<div class="nav-menu" id="nav-menu">
<a href="{{ url_for('calculator') }}">DPS/DPM CALCULATOR</a>
<a href="{{ url_for('about_us') }}">ABOUT US</a>
<a href="{{ url_for('index') }}">GUN STATS</a>
<a href="https://www.roblox.com/games/5766084948/SCP-The-Red-Lake-EVENT">PLAY THE RED LAKE</a>
<a href="https://discord.gg/2jDevH8aTd">OUR DISCORD</a>
</div> </div>
<div>
<p class="af-title">Anomaly Front</p>
<p class="af-subtitle">Feedback channel</p>
</div>
</div>
<button class="af-nav-toggle" type="button" aria-expanded="false" aria-controls="af-nav">
Menu
</button>
<nav class="af-nav" id="af-nav" aria-label="Primary">
<a class="af-nav-link" href="{{ url_for('index') }}">Home</a>
<a class="af-nav-link" href="{{ url_for('calculator') }}">Calculator</a>
<a class="af-nav-link" href="{{ url_for('about_us') }}">About</a>
</nav> </nav>
</header> </header>
<body> <main class="af-shell">
<main class="background-image"> <section class="af-card">
<h1>Suggestion</h1> <div class="af-card-header">
<h3 class="suggestion-title"><b>Welcome to Suggestions!</b><br> We encourage you to share your ideas, improvments, <h1>Share your feedback</h1>
or even fun comments with us, so we can develop this website further.</h3> <p>
<article> Help us shape the Anomaly Front toolkit. Share feature requests, balance ideas, or UI tweaks and we
<label for="name">Pseudoname:</label> will log them for the next iteration.
<input type="text" id="name" name="name" placeholder="not required"><br><br> </p>
</div>
<article class="af-form">
<label class="af-field" for="name">
Pseudoname
<input class="af-input" type="text" id="name" name="name" placeholder="Optional">
</label>
<label for="rate">Rating:</label> <label class="af-field" for="rate">
<input type="number" id="rate" name="rating" min="1" max="10" required><br><br> Rating
<input class="af-input" type="number" id="rate" name="rating" min="1" max="10" required>
</label>
<label for="text">Text:</label> <label class="af-field" for="text">
<textarea id="text" name="text" rows="4" cols="50" placeholder="Enter your comments here..." minlength="5" Feedback
maxlength="500" required></textarea><br><br> <textarea class="af-input" id="text" name="text" rows="4" cols="50" placeholder="Enter your comments here..." minlength="5"
maxlength="500" required></textarea>
</label>
</article> </article>
<button class="button1" type="button" onclick="sendMessage()">Send</button> <div class="af-form-actions">
<button class="af-cta" type="button" onclick="sendMessage()">Send feedback</button>
</div>
<p id="successMessage" style="display: none;" aria-live="polite" role="status"></p> <p id="successMessage" style="display: none;" aria-live="polite" role="status"></p>
<p id="errorMessage" style="display: none; color: crimson;" aria-live="polite" role="status"></p> <p id="errorMessage" style="display: none; color: crimson;" aria-live="polite" role="status"></p>
</section>
</main> </main>
<script src="{{ url_for('static', filename='suggestion.js') }}"></script> <script src="{{ url_for('static', filename='suggestion.js') }}"></script>
<script> <script>
const hamburger = document.querySelector('.hamburger'); const navToggle = document.querySelector('.af-nav-toggle');
const navMenu = document.querySelector('.nav-menu'); const nav = document.getElementById('af-nav');
function setMenu(open) { navToggle.addEventListener('click', () => {
hamburger.classList.toggle('active', open); const isOpen = nav.classList.toggle('is-open');
navMenu.classList.toggle('active', open); navToggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
document.body.classList.toggle('menu-open', open);
hamburger.setAttribute('aria-expanded', open ? 'true' : 'false');
}
hamburger.addEventListener('click', () => {
const isOpen = hamburger.classList.contains('active');
setMenu(!isOpen);
}); });
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') setMenu(false);
});
navMenu.querySelectorAll('a').forEach(link =>
link.addEventListener('click', () => setMenu(false))
);
</script> </script>
</body> </body>
</html> </html>