From 04f27163bc9237348225f3ae935aea7d1c00e087 Mon Sep 17 00:00:00 2001 From: dinithrathnayaka23 Date: Fri, 19 Jun 2026 00:34:15 +0530 Subject: [PATCH] Polish home page UI and setup config --- .gitignore | 4 +- Frontend/chatbot.js | 2 + Frontend/index.html | 110 ++++--- Frontend/style.css | 763 ++++++++++++++++++++++++++++++++++++++++++- requirements-dev.txt | 3 + requirements.txt | 5 + 6 files changed, 837 insertions(+), 50 deletions(-) create mode 100644 requirements-dev.txt create mode 100644 requirements.txt 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.

- + + Live signal feed
@@ -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