This commit is contained in:
Flatlogic Bot 2025-10-14 01:36:19 +00:00
parent 0dc274f7fa
commit 73d0602dee
10 changed files with 433 additions and 343 deletions

1
.user.ini Normal file
View File

@ -0,0 +1 @@
memory_limit = 512M

View File

@ -1,43 +0,0 @@
<?php
header('Content-Type: application/json');
header('User-Agent: worldsphere.ai, contact@worldsphere.ai');
// URL for the SPC RSS feed
$url = 'http://www.spc.noaa.gov/products/spcrss.xml';
// Fetch the RSS feed content
$rss = @file_get_contents($url);
if ($rss === false) {
echo json_encode(['error' => 'Failed to fetch SPC data.']);
exit;
}
// Parse the XML
$xml = @simplexml_load_string($rss);
if ($xml === false) {
echo json_encode(['error' => 'Failed to parse SPC XML.']);
exit;
}
$alerts = [];
if (isset($xml->channel->item)) {
foreach ($xml->channel->item as $item) {
// The title often contains the most succinct information
$title = (string)$item->title;
// The description can be long, let's create a summary or just use the title
$description = (string)$item->description;
$alerts[] = [
'headline' => $title,
'description' => strip_tags($description), // Basic sanitization
'link' => (string)$item->link
];
}
}
// Return the alerts as JSON
echo json_encode($alerts);
?>

91
api/gfs.php Normal file
View File

@ -0,0 +1,91 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
header('Content-Type: application/json');
// --- Configuration ---
$gfs_url = 'https://nomads.ncep.noaa.gov/pub/data/nccf/com/gfs/prod/gfs.20251013/00/atmos/gfs.t00z.pgrb2.0p25.f000';
$tmp_dir = '/tmp';
$grib_file = $tmp_dir . '/' . basename($gfs_url);
$xyz_file = $tmp_dir . '/gfs.xyz';
// --- Download the GFS file ---
if (!file_exists($grib_file)) {
$fp = fopen($grib_file, 'w');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $gfs_url);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
fclose($fp);
if ($http_code !== 200) {
unlink($grib_file); // Clean up failed download
echo json_encode(['error' => 'Failed to download GFS file', 'http_code' => $http_code]);
exit;
}
}
// --- Convert GRIB to XYZ using gdal_translate ---
// We'll use band 1 for this example. You can use gdalinfo to see available bands.
$gdal_command = 'gdal_translate -b 1 -of XYZ ' . escapeshellarg($grib_file) . ' ' . escapeshellarg($xyz_file);
$gdal_output = shell_exec($gdal_command);
if (!file_exists($xyz_file)) {
echo json_encode(['error' => 'Failed to convert GRIB to XYZ', 'gdal_output' => $gdal_output]);
unlink($grib_file);
exit;
}
// --- Read the XYZ file and create GeoJSON features ---
$features = [];
$handle = fopen($xyz_file, 'r');
$line_count = 0;
$sample_rate = 100; // Process 1 in every 100 lines
if ($handle) {
while (($line = fgets($handle)) !== false) {
$line_count++;
if ($line_count % $sample_rate !== 0) {
continue;
}
$parts = preg_split('/\s+/', trim($line));
if (count($parts) === 3) {
$lon = floatval($parts[0]);
$lat = floatval($parts[1]);
$value = floatval($parts[2]);
// Skip points that are exactly zero, often represent no data
if ($value === 0.0) {
continue;
}
$features[] = [
'type' => 'Feature',
'properties' => ['value' => $value],
'geometry' => [
'type' => 'Point',
'coordinates' => [$lon, $lat]
]
];
}
}
fclose($handle);
}
// --- Clean up temporary files ---
unlink($grib_file);
unlink($xyz_file);
// --- Output the GeoJSON ---
echo json_encode([
'type' => 'FeatureCollection',
'features' => $features
]);
?>

118
api/hurricanes.php Normal file
View File

@ -0,0 +1,118 @@
<?php
header('Content-Type: application/json');
// URL for the NHC active hurricane KML data
$nhc_kmz_url = 'https://www.nhc.noaa.gov/gis/kml/nhc.kmz';
// Temporary file to store the KMZ
$tmp_kmz_file = tempnam(sys_get_temp_dir(), 'nhc_kmz');
// Fetch the KMZ file
$kmz_data = file_get_contents($nhc_kmz_url);
if ($kmz_data === false) {
echo json_encode(['error' => 'Failed to fetch NHC data.']);
exit;
}
// Save the data to the temporary file
file_put_contents($tmp_kmz_file, $kmz_data);
if (!class_exists('ZipArchive')) {
echo json_encode(['error' => 'ZipArchive class does not exist.']);
exit;
}
// Use ZipArchive to open the KMZ file
$zip = new ZipArchive;
if ($zip->open($tmp_kmz_file) === TRUE) {
// NHC KMZ files typically contain a single KML file, often named doc.kml or similar.
// We will look for the first .kml file in the archive.
$kml_content = false;
for ($i = 0; $i < $zip->numFiles; $i++) {
$filename = $zip->getNameIndex($i);
if (strtolower(substr($filename, -4)) === '.kml') {
$kml_content = $zip->getFromIndex($i);
break;
}
}
$zip->close();
if ($kml_content === false) {
echo json_encode(['error' => 'KML file not found in the KMZ archive.']);
exit;
}
// Parse the KML content
$xml = simplexml_load_string($kml_content, "SimpleXMLElement", LIBXML_NOCDATA);
if ($xml === false) {
echo json_encode(['error' => 'Failed to parse KML data.']);
exit;
}
// Register the KML namespace
$xml->registerXPathNamespace('kml', 'http://www.opengis.net/kml/2.2');
$features = [];
// Find all Placemarks in the KML
foreach ($xml->xpath('//kml:Placemark') as $placemark) {
$placemark->registerXPathNamespace('kml', 'http://www.opengis.net/kml/2.2');
$name = (string)$placemark->name;
// Look for Polygon
$polygon = $placemark->xpath('.//kml:Polygon');
if ($polygon && isset($polygon[0]->outerBoundaryIs->LinearRing->coordinates)) {
$coordinates_str = (string)$polygon[0]->outerBoundaryIs->LinearRing->coordinates;
$coordinates = parse_coordinates($coordinates_str);
if (!empty($coordinates)) {
$features[] = [
'name' => $name,
'type' => 'Polygon',
'coordinates' => $coordinates
];
}
}
// Look for LineString
$linestring = $placemark->xpath('.//kml:LineString');
if ($linestring && isset($linestring[0]->coordinates)) {
$coordinates_str = (string)$linestring[0]->coordinates;
$coordinates = parse_coordinates($coordinates_str);
if (!empty($coordinates)) {
$features[] = [
'name' => $name,
'type' => 'LineString',
'coordinates' => $coordinates
];
}
}
}
echo json_encode($features);
} else {
echo json_encode(['error' => 'Failed to open KMZ file.']);
}
// Clean up the temporary file
unlink($tmp_kmz_file);
function parse_coordinates($coordinates_str) {
$coords = [];
$pairs = explode(' ', trim($coordinates_str));
foreach ($pairs as $pair) {
$parts = explode(',', $pair);
if (count($parts) >= 2) {
$lon = floatval($parts[0]);
$lat = floatval($parts[1]);
// Ensure coordinates are valid
if (is_finite($lat) && is_finite($lon)) {
$coords[] = $lon;
$coords[] = $lat;
}
}
}
return $coords;
}
?>

66
api/spc.php Normal file
View File

@ -0,0 +1,66 @@
<?php
header('Content-Type: application/json');
// URL for the SPC Day 1 Outlook KML data
$spc_kml_url = 'https://www.spc.noaa.gov/products/outlook/day1otlk_cat.kml';
// Fetch the KML file
$kml_content = file_get_contents($spc_kml_url);
if ($kml_content === false) {
echo json_encode(['error' => 'Failed to fetch SPC data.']);
exit;
}
// Parse the KML content
$xml = simplexml_load_string($kml_content, "SimpleXMLElement", LIBXML_NOCDATA);
if ($xml === false) {
echo json_encode(['error' => 'Failed to parse KML data.']);
exit;
}
// Register the KML namespace
$xml->registerXPathNamespace('kml', 'http://www.opengis.net/kml/2.2');
$features = [];
// Find all Placemarks in the KML
foreach ($xml->xpath('//kml:Placemark') as $placemark) {
$placemark->registerXPathNamespace('kml', 'http://www.opengis.net/kml/2.2');
$name = (string)$placemark->name;
// Look for Polygon
$polygon = $placemark->xpath('.//kml:Polygon');
if ($polygon && isset($polygon[0]->outerBoundaryIs->LinearRing->coordinates)) {
$coordinates_str = (string)$polygon[0]->outerBoundaryIs->LinearRing->coordinates;
$coordinates = parse_coordinates($coordinates_str);
if (!empty($coordinates)) {
$features[] = [
'name' => $name,
'type' => 'Polygon',
'coordinates' => $coordinates
];
}
}
}
echo json_encode($features);
function parse_coordinates($coordinates_str) {
$coords = [];
$pairs = explode(' ', trim($coordinates_str));
foreach ($pairs as $pair) {
$parts = explode(',', $pair);
if (count($parts) >= 2) {
$lon = floatval($parts[0]);
$lat = floatval($parts[1]);
// Ensure coordinates are valid
if (is_finite($lat) && is_finite($lon)) {
$coords[] = $lon;
$coords[] = $lat;
}
}
}
return $coords;
}
?>

View File

@ -17,25 +17,6 @@ if ($response === false) {
exit;
}
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
echo json_encode(['error' => 'Could not parse wildfire data.']);
exit;
}
$features = $data['features'] ?? [];
$wildfires = [];
foreach ($features as $feature) {
$properties = $feature['properties'];
$wildfires[] = [
'name' => $properties['poly_IncidentName'],
'acres' => $properties['poly_Acres_AutoCalc'],
'started' => $properties['attr_InitialResponseDateTime'],
'percent_contained' => $properties['attr_PercentContained'],
];
}
echo json_encode($wildfires);
// Directly pass through the GeoJSON response
echo $response;
?>

View File

@ -1,44 +1,26 @@
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #F8F9FA;
color: #212529;
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
main {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.navbar {
padding: 1rem 0;
flex-shrink: 0;
}
.hero {
position: relative;
padding: 8rem 0;
background-size: cover;
background-position: center;
color: white;
}
.hero-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 25, 51, 0.7);
z-index: 1;
}
.hero .container {
position: relative;
z-index: 2;
}
.hero h1 {
font-size: 3.5rem;
font-weight: 700;
}
.hero p {
font-size: 1.25rem;
.hero, .hero-overlay {
display: none; /* Hidden to make map primary */
}
.btn-primary {
@ -58,6 +40,14 @@ section {
padding: 4rem 0;
}
#map-widget {
flex-grow: 1;
padding: 0;
display: flex;
flex-direction: column;
min-height: 80vh; /* Ensure section has height */
}
h2 {
font-size: 2.5rem;
font-weight: 700;
@ -80,6 +70,7 @@ h2 {
background-color: #003366;
color: white;
padding: 3rem 0;
flex-shrink: 0;
}
.footer a {
@ -101,3 +92,20 @@ h2 {
#wildfire-data .card {
background-color: #F8F9FA;
}
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
overflow: hidden; /* Prevent scrollbars */
}
#cesiumContainer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: none; /* Remove the debug border */
}

View File

@ -1,104 +1,119 @@
document.addEventListener('DOMContentLoaded', function () {
const contactForm = document.getElementById('contactForm');
if (contactForm) {
contactForm.addEventListener('submit', function (e) {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const status = document.getElementById('form-status');
console.log('DOM fully loaded and parsed');
// Set your Cesium Ion default access token
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJjZTY0ZTQ1Yi0zYmYxLTQ5MjItODdkOS05ZDY0ZGRjYjQwM2QiLCJpZCI6MjA5ODgwLCJpYXQiOjE3MTM4MTY3OTB9.A-3Jt_G0K81s-A-XLpT2bn5aY2H3s-n2p-2jYf-i-g';
// Basic client-side validation
const name = formData.get('name');
const email = formData.get('email');
const message = formData.get('message');
if (!name || !email || !message) {
status.innerHTML = '<div class="alert alert-danger">Please fill out all fields.</div>';
return;
}
fetch('contact.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
status.innerHTML = `<div class="alert alert-success">${data.message}</div>`;
form.reset();
} else {
status.innerHTML = `<div class="alert alert-danger">${data.message}</div>`;
}
})
.catch(error => {
status.innerHTML = '<div class="alert alert-danger">An error occurred. Please try again.</div>';
console.error('Error:', error);
});
try {
console.log('Initializing Cesium Viewer');
// Initialize a Cesium Viewer with a map
const viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: new Cesium.OpenStreetMapImageryProvider({
url : 'https://a.tile.openstreetmap.org/'
}),
animation: false,
baseLayerPicker: false,
fullscreenButton: false,
geocoder: false,
homeButton: false,
infoBox: true,
sceneModePicker: false,
selectionIndicator: false,
timeline: false,
navigationHelpButton: false,
scene3DOnly: true
});
}
viewer.scene.globe.depthTestAgainstTerrain = false;
console.log('Cesium Viewer initialized successfully');
// Fetch and display cyclone data
const cycloneDataContainer = document.getElementById('cyclone-data');
if (cycloneDataContainer) {
fetch('api/cyclone.php')
.then(response => response.json())
.then(data => {
if (data && data.length > 0) {
let html = '';
data.forEach(alert => {
html += `
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-body d-flex flex-column">
<h5 class="card-title">${alert.headline}</h5>
<p class="card-text">${alert.description.substring(0, 150)}...</p>
<a href="${alert.link}" target="_blank" rel="noopener noreferrer" class="btn btn-primary btn-sm mt-auto">Read More</a>
</div>
</div>
</div>
`;
});
cycloneDataContainer.innerHTML = html;
} else {
cycloneDataContainer.innerHTML = '<div class="col-12"><p>No active severe weather alerts from the SPC at the moment.</p></div>';
}
})
.catch(error => {
cycloneDataContainer.innerHTML = '<p>Could not load cyclone data. Please try again later.</p>';
console.error('Error fetching cyclone data:', error);
});
}
// Fetch and display wildfire data
const wildfireDataContainer = document.getElementById('wildfire-data');
if (wildfireDataContainer) {
fetch('api/wildfires.php')
.then(response => response.json())
.then(data => {
if (data && data.length > 0) {
let html = '';
data.forEach(fire => {
html += `
<div class="col-md-4 mb-4">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">${fire.name}</h5>
<p class="card-text">${fire.acres ? Math.round(fire.acres) + ' acres' : 'Size not available'}</p>
<p class="card-text">${fire.percent_contained !== null ? fire.percent_contained + '% contained' : 'Containment not available'}</p>
</div>
</div>
</div>
`;
});
wildfireDataContainer.innerHTML = html;
} else {
wildfireDataContainer.innerHTML = '<div class="col-12"><p>No active wildfires reported at the moment.</p></div>';
// Function to load wildfire data
const loadWildfireData = async () => {
try {
console.log('Fetching wildfire data...');
const response = await fetch('api/wildfires.php');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
})
.catch(error => {
wildfireDataContainer.innerHTML = '<p>Could not load wildfire data. Please try again later.</p>';
console.error('Error fetching wildfire data:', error);
});
const geojsonData = await response.json();
console.log('Wildfire data fetched successfully.');
const wildfireDataSource = new Cesium.GeoJsonDataSource();
await wildfireDataSource.load(geojsonData, {
stroke: Cesium.Color.RED,
fill: Cesium.Color.RED.withAlpha(0.5),
strokeWidth: 2
});
viewer.dataSources.add(wildfireDataSource);
console.log('Wildfire data source added to viewer.');
} catch (error) {
console.error('Error loading wildfire data:', error);
// This catch block prevents the globe from crashing if the API fails.
}
};
// Function to load hurricane data
const loadHurricaneData = async () => {
try {
console.log('Fetching hurricane data...');
// Use KmlDataSource for the KML data from the hurricanes API
const hurricaneDataSource = await Cesium.KmlDataSource.load('api/hurricanes.php', {
camera: viewer.camera,
canvas: viewer.canvas
});
await viewer.dataSources.add(hurricaneDataSource);
console.log('Hurricane data source added to viewer.');
} catch (error) {
console.error('Error loading hurricane data:', error);
}
};
// Function to load GFS data
const loadGfsData = async () => {
try {
console.log('Fetching GFS data...');
const response = await fetch('api/gfs.php');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const geojsonData = await response.json();
console.log('GFS data fetched successfully.');
const gfsDataSource = new Cesium.GeoJsonDataSource();
await gfsDataSource.load(geojsonData, {
stroke: Cesium.Color.BLUE.withAlpha(0.3),
fill: Cesium.Color.BLUE.withAlpha(0.3),
strokeWidth: 1
});
// Simple heatmap-like styling for GFS points
gfsDataSource.entities.values.forEach(entity => {
const value = entity.properties.value.getValue();
const color = Cesium.Color.fromHsl(0.6 - (value - 100000) / 2000 * 0.5, 1.0, 0.5).withAlpha(0.5);
entity.point = new Cesium.PointGraphics({
color: color,
pixelSize: 5
});
});
viewer.dataSources.add(gfsDataSource);
console.log('GFS data source added to viewer.');
} catch (error) {
console.error('Error loading GFS data:', error);
}
};
// Load all data sources
loadWildfireData();
// loadHurricaneData();
// loadGfsData();
} catch (error) {
console.error('A critical error occurred while initializing the Cesium viewer:', error);
const cesiumContainer = document.getElementById('cesiumContainer');
cesiumContainer.innerHTML = '<div class="alert alert-danger">Error: Could not load the 3D scene. Please check the console for details.</div>';
}
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

155
index.php
View File

@ -1,162 +1,15 @@
<?php
// Fetch a hurricane image from our local API endpoint
$image_api_url = "http://" . $_SERVER['HTTP_HOST'] . "/api/pexels.php?query=hurricane&orientation=landscape";
@$image_data_json = file_get_contents($image_api_url);
$image_data = $image_data_json ? json_decode($image_data_json, true) : null;
$hero_image_url = $image_data ? $image_data['local_path'] : 'https://images.pexels.com/photos/15033937/pexels-photo-15033937.jpeg'; // Fallback
$hero_image_alt = $image_data ? $image_data['alt'] : 'Satellite view of a hurricane';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Worldsphere.ai - AI-Powered Weather Prediction</title>
<meta name="description" content="Worldsphere.ai is revolutionizing climate resilience with AI-powered weather prediction.">
<meta name="keywords" content="ai weather prediction, climate resilience, hurricane forecasting, climate tech, big data analytics, weather risk management, diffusion models, satellite imagery analysis, Built with Flatlogic Generator">
<meta property="og:title" content="Worldsphere.ai - AI-Powered Weather Prediction">
<meta property="og:description" content="Revolutionizing Climate Resilience with AI-Powered Weather Prediction.">
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Worldsphere.ai - 3D Weather Map</title>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.117/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
</head>
<body>
<header class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand fw-bold" href="#">Worldsphere.ai</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="#solutions">Solutions</a></li>
<li class="nav-item"><a class="nav-link" href="#mission">About</a></li>
<li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
</ul>
</div>
</div>
</header>
<main>
<section class="hero text-center text-white" style="background-image: url('<?php echo htmlspecialchars($hero_image_url); ?>');">
<div class="hero-overlay">
<div class="container">
<p class="mb-3">First Beta Version now available! Download now</p>
<h1 class="display-3 fw-bold">Revolutionizing Climate Resilience with AI-Powered Weather Prediction</h1>
<p class="lead mt-4">Where Cutting-Edge Technology Meets Climate Action. At Worldsphere.ai, were harnessing the power of artificial intelligence to transform how we predict, prepare for, and respond to extreme weather events.</p>
<a href="#contact" class="btn btn-primary mt-4">Join the Climate Tech Revolution</a>
</div>
</div>
</section>
<section id="cyclone-widget" class="container text-center">
<h2>Active Tropical Cyclones</h2>
<div id="cyclone-data" class="row">
<p>Loading real-time cyclone data...</p>
</div>
</section>
<section id="wildfire-widget" class="container text-center">
<h2>Active Wildfires</h2>
<div id="wildfire-data" class="row">
<p>Loading real-time wildfire data...</p>
</div>
</section>
<section id="solutions" class="container text-center">
<h2>Technology & Innovation</h2>
<p class="lead mb-5">Our innovative platform combines state-of-the-art AI models, big data analytics, and immersive visualization techniques to provide unparalleled insights into weather risks and climate patterns.</p>
<div class="row">
<div class="col-md-4 mb-4">
<div class="card h-100 p-4">
<h5 class="fw-bold">AI-Powered Hurricane Prediction</h5>
<p>Our flagship technology utilizes advanced diffusion models to revolutionize hurricane forecasting.</p>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card h-100 p-4">
<h5 class="fw-bold">Satellite-to-Wind Technology</h5>
<p>Generate realistic 2D wind fields from infrared satellite imagery and automatically remove land masses.</p>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card h-100 p-4">
<h5 class="fw-bold">Model Interpretability</h5>
<p>We bridge traditional meteorological frameworks and AI-generated insights by mapping atmospheric patterns to model activations.</p>
</div>
</div>
</div>
</section>
<section id="mission" class="bg-white">
<div class="container">
<div class="row align-items-center">
<div class="col-md-6">
<h2>Our Mission</h2>
<p class="lead">Empowering Global Resilience in the Face of Climate Change.</p>
<p>We recognize the urgency of the climate crisis. At Worldsphere.ai, were committed to developing solutions that address both current and future climate challenges, from severe droughts to devastating floods. Our ultimate goal is to create a world where every individual, community, and organization has access to accurate, timely, and actionable weather intelligence.</p>
</div>
<div class="col-md-6">
<h5 class="fw-bold">Our Core Objectives</h5>
<ul>
<li>Advance the field of Al-powered weather prediction</li>
<li>Improve early warning systems for extreme weather events</li>
<li>Support businesses and communities in climate risk management</li>
<li>Foster collaboration between technology and climate science</li>
</ul>
</div>
</div>
</div>
</section>
<section id="contact">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="contact-form text-center">
<h2>Contact Us</h2>
<p>Sign up for our beta testing program and experience the future of weather risk management.</p>
<form id="contactForm" novalidate>
<div class="mb-3">
<input type="text" class="form-control" id="name" name="name" placeholder="Your Name" required>
</div>
<div class="mb-3">
<input type="email" class="form-control" id="email" name="email" placeholder="Your Email" required>
</div>
<div class="mb-3">
<textarea class="form-control" id="message" name="message" rows="5" placeholder="Your Message" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Send Message</button>
</form>
<div id="form-status" class="mt-4"></div>
</div>
</div>
</div>
</div>
</section>
</main>
<footer class="footer">
<div class="container text-center">
<ul class="nav justify-content-center mb-3">
<li class="nav-item"><a href="#" class="nav-link px-2 text-white">LinkedIn</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-white">Instagram</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-white">x.com</a></li>
<li class="nav-item"><a href="privacy.php" class="nav-link px-2 text-white">Privacy Policy</a></li>
</ul>
<p>&copy; 2025 Worldsphere.ai. All Rights Reserved.</p>
<p>Reminder: click Save in the editor to sync changes.</p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<div id="cesiumContainer"></div>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.117/Build/Cesium/Cesium.js"></script>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
</body>
</html>