diff --git a/.gitignore b/.gitignore
index 71dfa08..e860b6f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
.venv/
+venv/
.vscode/
.idea/
__pycache__/
*.pyc
-.env
\ No newline at end of file
+.env
+flask-server*.log
diff --git a/Frontend/chatbot.js b/Frontend/chatbot.js
index 4b94acb..e1c863a 100644
--- a/Frontend/chatbot.js
+++ b/Frontend/chatbot.js
@@ -162,12 +162,14 @@ document.addEventListener('DOMContentLoaded', () => {
const openPanel = () => {
panel.classList.remove('hidden');
+ document.body.classList.add('chatbot-open');
toggleButton.setAttribute('aria-expanded', 'true');
input.focus();
};
const closePanel = () => {
panel.classList.add('hidden');
+ document.body.classList.remove('chatbot-open');
toggleButton.setAttribute('aria-expanded', 'false');
};
diff --git a/Frontend/index.html b/Frontend/index.html
index 01f3eb9..11d5b4f 100644
--- a/Frontend/index.html
+++ b/Frontend/index.html
@@ -20,6 +20,12 @@
rel="stylesheet"
/>
+
+
@@ -47,16 +53,25 @@
>GitHub
+
+
-
Real-time weather risk monitoring
+
+
+
+
+ Real-time weather risk monitoring
+
Predict climate threats before they interrupt your day.
@@ -75,15 +90,15 @@
Predict climate threats before they interrupt your day.
24/7
- live monitoring
+ weather monitoring
- 2
- risk types tracked
+ 5
+ climate risks tracked
Instant
- alert delivery
+ safety prompts
@@ -108,7 +123,8 @@ Predict climate threats before they interrupt your day.
@@ -120,7 +136,8 @@ Predict climate threats before they interrupt your day.
-
+ Dynamic
+ updates by rainfall, wind, and humidity
@@ -134,6 +151,7 @@ Predict climate threats before they interrupt your day.
+ Priority alerts surface when local conditions begin to intensify.
@@ -146,41 +164,29 @@ Build stronger readiness with climate-smart actions.
Step 1
- Open the analysis page
+ Choose a location
+ Start from the analysis page and focus the forecast on one city, state, and country.
Step 2
- Enter city, state, and country
+ Read risk signals
+ Review weather conditions, hazard scores, and risk levels in a single scan.
-
-
-
-
-
-
+
Step 3
- Review weather, risk, and alerts
+ Act with confidence
+ Use the alerts and safety guidance to prepare earlier and communicate clearly.
@@ -196,17 +202,17 @@ Built for quick decisions when weather conditions change.
🌦
Live weather context
- See current temperature, humidity, rainfall, and wind in one
- clean snapshot.
+ Compare temperature, humidity, rainfall, and wind without
+ jumping between separate reports.
⚠
- Risk-first summary
+ Risk-first summaries
- Flood and heat risks are presented as clear signals, not just
- raw numbers.
+ Translate weather values into clear flood, heat, wildfire,
+ cyclone, and drought signals.
@@ -214,8 +220,8 @@ Risk-first summary
🚨
Actionable alerts
- Important warnings are surfaced immediately so users can react
- faster.
+ Surface the most important warning early, with concise guidance
+ for the next practical step.
@@ -233,8 +239,8 @@
📊
Climate Risk Prediction
- Predict potential climate threats using weather patterns and
- risk scoring models.
+ Estimate near-term hazard exposure from live weather inputs and
+ transparent scoring rules.
@@ -242,8 +248,8 @@ Climate Risk Prediction
🌊
Flood & Heatwave Analysis
- Evaluate flood and heatwave risks with easy-to-understand
- climate indicators.
+ Understand rainfall, humidity, temperature, and wind pressure
+ through readable risk levels.
@@ -251,8 +257,8 @@ Flood & Heatwave Analysis
🤖
AI-Powered Climate Assistant
- Get instant answers and climate safety guidance through
- ClimateBot.
+ Ask ClimateBot for simple safety guidance after reviewing a
+ location report.
@@ -260,8 +266,8 @@ AI-Powered Climate Assistant
📍
Location-Based Insights
- Analyze climate conditions for specific cities and regions
- worldwide.
+ Keep each result tied to a specific place so alerts stay local
+ and easy to act on.
@@ -269,8 +275,8 @@ Location-Based Insights
🌎
Environmental Intelligence
- Access real-time environmental information to support informed
- decisions.
+ Bring weather, risk scoring, alerts, and guidance into one
+ compact decision view.
@@ -458,7 +464,15 @@ Environmental Intelligence
- ↑
+
+
+
diff --git a/Frontend/style.css b/Frontend/style.css
index ddf221e..24b1bd1 100644
--- a/Frontend/style.css
+++ b/Frontend/style.css
@@ -1324,4 +1324,765 @@ body.light-mode .navbar {
.scroll-top-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(14, 165, 233, 0.45);
-}
\ No newline at end of file
+}
+
+/* Home hero/header consistency fixes */
+.navbar {
+ top: 8px;
+ left: 50%;
+ display: grid;
+ grid-template-columns: minmax(240px, 1fr) auto minmax(240px, 1fr);
+ align-items: center;
+ width: min(1200px, calc(100% - 32px));
+ transform: translateX(-50%);
+ flex-wrap: nowrap;
+}
+
+.brand-marks {
+ min-width: 0;
+ justify-self: start;
+}
+
+.nav-actions {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ justify-self: end;
+ gap: 14px;
+ min-width: 0;
+}
+
+.nav-actions #theme-button,
+.nav-actions #analysis-button {
+ display: flex;
+ align-items: center;
+}
+
+.theme-toggle {
+ flex: 0 0 auto;
+}
+
+.hero {
+ max-width: none;
+ gap: 32px 42px;
+ padding: 132px 0 44px;
+}
+
+.hero-copy {
+ align-self: center;
+ width: 100%;
+ min-width: 0;
+ max-width: 680px;
+ margin-top: 0;
+ padding: 18px 8px 24px;
+}
+
+.hero-copy h1 {
+ max-width: 13.5ch;
+ font-size: 4.45rem;
+ line-height: 1.02;
+ letter-spacing: 0;
+}
+
+.hero-copy p {
+ width: 100%;
+ max-width: 52ch;
+ margin-top: 20px;
+ overflow-wrap: break-word;
+}
+
+.hero-actions {
+ justify-content: flex-start;
+}
+
+.hero-stats {
+ max-width: 560px;
+}
+
+.eyebrow {
+ gap: 10px;
+ padding: 8px 16px 8px 10px;
+ line-height: 1.35;
+ letter-spacing: 0;
+}
+
+.eyebrow-icon {
+ display: inline-grid;
+ place-items: center;
+ position: relative;
+ width: 28px;
+ height: 28px;
+ flex: 0 0 auto;
+ border-radius: 50%;
+ color: #e0f2fe;
+ background: rgba(56, 189, 248, 0.22);
+ box-shadow: inset 0 0 0 1px rgba(125, 211, 252, 0.24);
+}
+
+.eyebrow-icon i {
+ position: relative;
+ z-index: 2;
+ font-size: 0.86rem;
+}
+
+.eyebrow-icon::before,
+.eyebrow-icon::after {
+ content: "";
+ position: absolute;
+ pointer-events: none;
+}
+
+.eyebrow-icon::before {
+ left: 7px;
+ top: 11px;
+ width: 14px;
+ height: 8px;
+ border-radius: 999px;
+ background: rgba(224, 242, 254, 0.72);
+ box-shadow:
+ -4px 2px 0 -1px rgba(224, 242, 254, 0.64),
+ 5px 1px 0 -2px rgba(224, 242, 254, 0.64);
+}
+
+.eyebrow-icon::after {
+ left: 11px;
+ top: 18px;
+ width: 2px;
+ height: 6px;
+ border-radius: 999px;
+ background: rgba(224, 242, 254, 0.7);
+ transform: rotate(18deg);
+ box-shadow: 6px -1px 0 rgba(224, 242, 254, 0.7);
+}
+
+@media (max-width: 1100px) {
+ .hero-copy h1 {
+ font-size: 3.9rem;
+ }
+}
+
+@media (max-width: 980px) {
+ .navbar {
+ left: 16px;
+ right: 16px;
+ grid-template-columns: minmax(0, 1fr) auto;
+ gap: 14px;
+ width: auto;
+ padding: 14px 16px;
+ transform: none;
+ }
+
+ .nav-links {
+ grid-column: 1 / -1;
+ justify-content: center;
+ width: 100%;
+ flex-wrap: wrap;
+ }
+
+ .nav-actions {
+ justify-self: end;
+ }
+
+ .hero {
+ padding-top: 176px;
+ }
+
+ .hero-copy,
+ .hero-copy h1 {
+ margin-top: 0;
+ }
+
+ .hero-copy h1 {
+ max-width: 14ch;
+ }
+
+ .hero-actions {
+ justify-content: flex-start;
+ }
+}
+
+@media (max-width: 768px) {
+ .hero {
+ padding-top: 210px;
+ }
+
+ .hero-copy h1 {
+ font-size: 2.8rem;
+ }
+
+ .hero-stats {
+ display: grid;
+ grid-template-columns: 1fr;
+ }
+}
+
+@media (max-width: 600px) {
+ .navbar {
+ left: 10px;
+ right: 10px;
+ grid-template-columns: 1fr;
+ width: auto;
+ padding: 14px;
+ }
+
+ .brand-marks,
+ .nav-actions {
+ justify-self: center;
+ }
+
+ .nav-actions {
+ justify-content: center;
+ width: 100%;
+ gap: 12px;
+ }
+
+ .nav-cta {
+ display: inline-flex;
+ justify-content: center;
+ padding: 10px 14px;
+ font-size: 0.9rem;
+ }
+
+ .hero {
+ padding-top: 252px;
+ }
+
+ .hero-copy h1 {
+ max-width: 12.5ch;
+ font-size: 2.35rem;
+ }
+
+ .hero-copy p {
+ max-width: 32ch;
+ font-size: 1rem;
+ }
+
+ .eyebrow {
+ max-width: calc(100vw - 36px);
+ }
+}
+
+@media (max-width: 480px) {
+ .navbar {
+ left: 10px;
+ right: 10px;
+ grid-template-columns: 1fr;
+ width: auto;
+ }
+
+ .nav-actions {
+ justify-self: stretch;
+ justify-content: center;
+ gap: 12px;
+ width: 100%;
+ }
+
+ .nav-cta {
+ display: inline-flex;
+ justify-content: center;
+ padding: 10px 14px;
+ font-size: 0.9rem;
+ }
+
+ .hero {
+ padding-top: 252px;
+ }
+
+ .hero-copy {
+ margin-top: 0;
+ }
+
+ .hero-copy h1 {
+ max-width: 12.5ch;
+ font-size: 2.35rem;
+ }
+
+ .hero-copy p {
+ max-width: 100%;
+ font-size: 1rem;
+ }
+
+ .eyebrow {
+ align-items: flex-start;
+ border-radius: 18px;
+ font-size: 0.78rem;
+ }
+}
+
+/* Navbar interaction polish and consistent hero spacing */
+:root {
+ --hero-navbar-gap: clamp(48px, 6vw, 72px);
+}
+
+.navbar {
+ position: sticky;
+ top: 8px;
+ left: auto;
+ right: auto;
+ overflow: hidden;
+ isolation: isolate;
+ margin: 8px auto 0;
+ transform: none;
+ animation: cs-navbar-enter 0.62s ease-out both;
+ transition:
+ border-color 0.25s ease,
+ box-shadow 0.25s ease,
+ background 0.25s ease;
+}
+
+.navbar::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ z-index: -1;
+ background:
+ linear-gradient(
+ 120deg,
+ transparent 0%,
+ rgba(125, 211, 252, 0.16) 38%,
+ rgba(34, 211, 238, 0.2) 50%,
+ transparent 62%
+ );
+ opacity: 0;
+ transform: translateX(-45%);
+ transition:
+ opacity 0.3s ease,
+ transform 0.65s ease;
+}
+
+.navbar:hover {
+ border-color: rgba(125, 211, 252, 0.28);
+ box-shadow:
+ 0 22px 54px rgba(8, 47, 73, 0.34),
+ 0 0 0 1px rgba(125, 211, 252, 0.06) inset;
+}
+
+.navbar:hover::before {
+ opacity: 1;
+ transform: translateX(45%);
+}
+
+.brand {
+ transition:
+ color 0.2s ease,
+ transform 0.25s ease;
+}
+
+.brand:hover {
+ transform: translateY(-1px);
+}
+
+.brand-mark {
+ transition:
+ border-color 0.25s ease,
+ box-shadow 0.25s ease,
+ transform 0.25s ease;
+}
+
+.brand:hover .brand-mark {
+ border-color: rgba(125, 211, 252, 0.46);
+ box-shadow: 0 0 22px rgba(56, 189, 248, 0.22);
+ transform: rotate(-5deg) scale(1.04);
+}
+
+.nav-links a {
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ min-height: 38px;
+ padding: 8px 10px;
+ border-radius: 999px;
+ overflow: hidden;
+}
+
+.nav-links a::after {
+ content: "";
+ position: absolute;
+ left: 12px;
+ right: 12px;
+ bottom: 6px;
+ height: 2px;
+ border-radius: 999px;
+ background: linear-gradient(90deg, var(--accent), #22d3ee);
+ transform: scaleX(0);
+ transform-origin: center;
+ transition: transform 0.22s ease;
+}
+
+.nav-links a:hover {
+ color: #f8fafc;
+ background: rgba(56, 189, 248, 0.1);
+}
+
+.nav-links a:hover::after {
+ transform: scaleX(1);
+}
+
+.theme-toggle {
+ transition:
+ transform 0.25s ease,
+ box-shadow 0.25s ease,
+ background 0.25s ease;
+}
+
+.theme-toggle:hover {
+ background: rgba(56, 189, 248, 0.14);
+ box-shadow: 0 0 22px rgba(56, 189, 248, 0.18);
+ transform: translateY(-2px) rotate(12deg);
+}
+
+.nav-cta {
+ position: relative;
+ overflow: hidden;
+}
+
+.nav-cta::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.32), transparent);
+ transform: translateX(-120%);
+ transition: transform 0.55s ease;
+}
+
+.nav-cta:hover {
+ box-shadow:
+ 0 18px 34px rgba(14, 165, 233, 0.36),
+ 0 0 24px rgba(56, 189, 248, 0.22);
+}
+
+.nav-cta:hover::before {
+ transform: translateX(120%);
+}
+
+.hero {
+ padding: var(--hero-navbar-gap) 0 44px;
+}
+
+@keyframes cs-navbar-enter {
+ from {
+ opacity: 0;
+ transform: translateY(-12px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@media (max-width: 980px) {
+ :root {
+ --hero-navbar-gap: 56px;
+ }
+
+ .navbar {
+ left: auto;
+ right: auto;
+ width: min(100% - 32px, 1200px);
+ }
+}
+
+@media (max-width: 600px) {
+ :root {
+ --hero-navbar-gap: 48px;
+ }
+
+ .navbar {
+ width: calc(100% - 20px);
+ }
+
+ .nav-links {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 8px;
+ width: 100%;
+ }
+
+ .nav-links a {
+ justify-content: center;
+ min-height: 34px;
+ padding: 6px 8px;
+ font-size: 0.92rem;
+ }
+}
+
+@media (max-width: 480px) {
+ :root {
+ --hero-navbar-gap: 44px;
+ }
+}
+
+/* Organized content sections and floating controls */
+.hero-strip {
+ gap: 20px;
+ padding-top: 28px;
+}
+
+.hero-strip-title,
+.feature-section > .section-heading,
+.capabilities-section > .section-heading {
+ align-items: center;
+ text-align: center;
+ margin-inline: auto;
+ margin-bottom: 26px;
+}
+
+.hero-strip-title h2,
+.feature-section .section-heading h2,
+.capabilities-section .section-heading h2 {
+ max-width: 26ch;
+}
+
+.hero-step-card,
+.feature-card,
+.capability-card {
+ position: relative;
+ overflow: hidden;
+}
+
+.hero-step-card::before,
+.feature-card::before,
+.capability-card::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ background: linear-gradient(140deg, rgba(56, 189, 248, 0.12), transparent 44%);
+ opacity: 0;
+ transition: opacity 0.25s ease;
+}
+
+.hero-step-card:hover::before,
+.feature-card:hover::before,
+.capability-card:hover::before {
+ opacity: 1;
+}
+
+.hero-step-card {
+ grid-template-rows: auto auto auto 1fr;
+ min-height: 240px;
+ padding: 24px;
+}
+
+.hero-step-card h3 {
+ margin: 0;
+ color: var(--text-heading);
+ font-size: 1.1rem;
+ line-height: 1.35;
+}
+
+.hero-step-card p {
+ margin: 0;
+ color: var(--muted);
+ font-size: 0.94rem;
+ line-height: 1.7;
+}
+
+.hero-step-card-visual {
+ width: 64px;
+ height: 64px;
+ padding: 0;
+ border-radius: 18px;
+ background:
+ linear-gradient(135deg, rgba(56, 189, 248, 0.16), rgba(34, 197, 94, 0.08));
+}
+
+.hero-step-card-visual i {
+ color: #7dd3fc;
+ font-size: 1.55rem;
+}
+
+.feature-grid {
+ gap: 18px;
+}
+
+.feature-card,
+.capability-card {
+ display: grid;
+ align-content: start;
+ gap: 10px;
+}
+
+.feature-card h3,
+.capability-card h3 {
+ margin: 0;
+ font-size: 1.08rem;
+ line-height: 1.35;
+}
+
+.feature-card p,
+.capability-card p {
+ margin: 0;
+ max-width: 34ch;
+ font-size: 0.94rem;
+}
+
+.feature-icon {
+ position: relative;
+ font-size: 0;
+ color: #a5f3fc;
+ transition:
+ border-color 0.25s ease,
+ box-shadow 0.25s ease,
+ transform 0.25s ease;
+}
+
+.feature-icon::before {
+ content: "\f743";
+ font-family: "Font Awesome 6 Free";
+ font-size: 1.28rem;
+ font-weight: 900;
+ line-height: 1;
+}
+
+.feature-card:hover .feature-icon,
+.capability-card:hover .feature-icon {
+ border-color: rgba(125, 211, 252, 0.38);
+ box-shadow: 0 0 24px rgba(56, 189, 248, 0.16);
+ transform: translateY(-2px);
+}
+
+.feature-grid .feature-card:nth-child(1) .feature-icon::before {
+ content: "\f743";
+}
+
+.feature-grid .feature-card:nth-child(2) .feature-icon::before {
+ content: "\f071";
+}
+
+.feature-grid .feature-card:nth-child(3) .feature-icon::before {
+ content: "\f0f3";
+}
+
+.capability-grid .capability-card:nth-child(1) .feature-icon::before {
+ content: "\f201";
+}
+
+.capability-grid .capability-card:nth-child(2) .feature-icon::before {
+ content: "\f773";
+}
+
+.capability-grid .capability-card:nth-child(3) .feature-icon::before {
+ content: "\f544";
+}
+
+.capability-grid .capability-card:nth-child(4) .feature-icon::before {
+ content: "\f601";
+}
+
+.capability-grid .capability-card:nth-child(5) .feature-icon::before {
+ content: "\f57e";
+}
+
+.cs-hero-widget-gauge-copy {
+ display: grid;
+ justify-items: center;
+ gap: 4px;
+ text-align: center;
+ font-size: 0.76rem;
+ line-height: 1.45;
+}
+
+.cs-hero-widget-temp-meta {
+ justify-content: center;
+ font-size: 0.86rem;
+}
+
+.cs-hero-widget-card--mid {
+ height: 240px;
+}
+
+.cs-hero-widget-card--bottom {
+ align-content: center;
+}
+
+.cs-hero-widget-card--bottom p {
+ max-width: 18ch;
+ text-align: center;
+ font-size: 0.78rem;
+ line-height: 1.55;
+}
+
+.chatbot-toggle {
+ font-size: 0;
+}
+
+.chatbot-toggle::before {
+ content: "\f544";
+ font-family: "Font Awesome 6 Free";
+ font-size: 1.2rem;
+ font-weight: 900;
+}
+
+#scrollTopBtn,
+.scroll-top-btn {
+ right: 92px;
+ bottom: 25px;
+ width: 48px;
+ height: 48px;
+ border-radius: 16px;
+ font-size: 1rem;
+ z-index: 38;
+ background:
+ linear-gradient(135deg, rgba(56, 189, 248, 0.95), rgba(14, 165, 233, 0.95));
+ box-shadow:
+ 0 14px 28px rgba(14, 165, 233, 0.24),
+ inset 0 0 0 1px rgba(255, 255, 255, 0.18);
+ transition:
+ opacity 0.22s ease,
+ transform 0.22s ease,
+ box-shadow 0.22s ease,
+ visibility 0.22s ease;
+}
+
+#scrollTopBtn:hover,
+.scroll-top-btn:hover {
+ transform: translateY(-3px);
+ box-shadow:
+ 0 18px 34px rgba(14, 165, 233, 0.34),
+ inset 0 0 0 1px rgba(255, 255, 255, 0.22);
+}
+
+body.chatbot-open #scrollTopBtn,
+body.chatbot-open .scroll-top-btn {
+ opacity: 0;
+ pointer-events: none;
+ visibility: hidden;
+ transform: translateY(10px) scale(0.92);
+}
+
+@media (max-width: 900px) {
+ .hero-strip,
+ .feature-grid,
+ .capability-grid {
+ gap: 16px;
+ }
+
+ .feature-card p,
+ .capability-card p {
+ max-width: none;
+ }
+}
+
+@media (max-width: 600px) {
+ .hero-strip-title,
+ .feature-section > .section-heading,
+ .capabilities-section > .section-heading {
+ align-items: flex-start;
+ text-align: left;
+ }
+
+ .hero-step-card {
+ min-height: auto;
+ }
+
+ #scrollTopBtn,
+ .scroll-top-btn {
+ right: 70px;
+ bottom: 12px;
+ width: 46px;
+ height: 46px;
+ border-radius: 14px;
+ }
+}
diff --git a/requirements-dev.txt b/requirements-dev.txt
new file mode 100644
index 0000000..1350a07
--- /dev/null
+++ b/requirements-dev.txt
@@ -0,0 +1,3 @@
+-r requirements.txt
+pytest>=9.0,<10
+playwright>=1.40,<2
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..ecf8467
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+Flask>=3.0,<4
+flask-cors>=4.0,<7
+requests>=2.31,<3
+python-dotenv>=1.0,<2
+gunicorn>=22,<24