Files
2026-06-10 19:48:00 +07:00

1159 lines
34 KiB
HTML

<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Portal Combine WebGIS Pontianak</title>
<link rel="preconnect" href="https://unpkg.com">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<style>
:root {
--ink: #eef7fb;
--muted: #a8bbc4;
--line: rgba(148, 163, 184, .24);
--paper: #071118;
--panel: rgba(12, 24, 34, .82);
--green: #157f64;
--blue: #2764d8;
--amber: #c47a14;
--red: #c54242;
--violet: #6d4bd2;
--cyan: #0891b2;
--pink: #c026d3;
--lime: #84cc16;
--orange: #f97316;
--coral: #fb7185;
--silver: #eef4f8;
--platinum: #d9e6ee;
--shadow: 0 18px 55px rgba(31, 49, 44, .16);
}
* {
box-sizing: border-box;
}
html,
body {
min-height: 100%;
margin: 0;
font-family: Inter, "Segoe UI", Arial, sans-serif;
color: var(--ink);
background: var(--paper);
}
body {
overflow-x: hidden;
background:
radial-gradient(circle at 12% 10%, rgba(0, 229, 255, .18), transparent 28%),
radial-gradient(circle at 84% 10%, rgba(249, 115, 22, .18), transparent 28%),
radial-gradient(circle at 68% 78%, rgba(132, 204, 22, .14), transparent 30%),
radial-gradient(circle at 20% 88%, rgba(251, 113, 133, .13), transparent 30%),
linear-gradient(135deg, #061016 0%, #09251f 35%, #1d1831 68%, #121009 100%);
}
a {
color: inherit;
text-decoration: none;
}
code {
padding: 2px 5px;
border: 1px solid var(--line);
border-radius: 5px;
background: rgba(226, 245, 255, .08);
color: #dff8ff;
font-family: "SFMono-Regular", Consolas, monospace;
font-size: .92em;
}
.hero {
position: relative;
min-height: 58vh;
display: grid;
align-items: end;
isolation: isolate;
overflow: hidden;
border-bottom: 1px solid rgba(148, 163, 184, .18);
}
#hero-map {
position: absolute;
inset: 0;
z-index: -2;
background: #071118;
}
.hero::after {
content: "";
position: absolute;
inset: 0;
z-index: -1;
background:
repeating-linear-gradient(115deg, rgba(255,255,255,.045) 0 1px, transparent 1px 18px),
radial-gradient(circle at 74% 18%, rgba(249, 115, 22, .2), transparent 24%),
radial-gradient(circle at 18% 30%, rgba(45, 212, 191, .14), transparent 24%),
radial-gradient(circle at 58% 70%, rgba(132, 204, 22, .1), transparent 30%),
linear-gradient(110deg, rgba(5, 13, 20, .98) 0%, rgba(7, 36, 30, .9) 42%, rgba(45, 26, 20, .52) 100%),
linear-gradient(0deg, rgba(7, 17, 24, 1) 0%, rgba(7, 17, 24, .16) 44%);
pointer-events: none;
}
.hero::before {
content: "";
position: absolute;
inset: auto -10% -26% -10%;
height: 48%;
z-index: -1;
background: linear-gradient(90deg, rgba(34, 211, 238, .22), rgba(132, 204, 22, .18), rgba(249, 115, 22, .18), rgba(251, 113, 133, .16));
filter: blur(42px);
transform: rotate(-2deg);
pointer-events: none;
animation: auroraDrift 9s ease-in-out infinite alternate;
}
.future-bg {
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
overflow: hidden;
}
.scan-grid {
position: absolute;
inset: -20%;
background:
linear-gradient(rgba(103, 232, 249, .09) 1px, transparent 1px),
linear-gradient(90deg, rgba(103, 232, 249, .08) 1px, transparent 1px);
background-size: 56px 56px;
transform: perspective(650px) rotateX(62deg) translateY(18%);
transform-origin: 50% 100%;
opacity: .38;
animation: gridFlow 9s linear infinite;
}
.light-beam {
position: absolute;
width: 46vw;
height: 2px;
left: -52vw;
top: 34%;
background: linear-gradient(90deg, transparent, rgba(103, 232, 249, .76), rgba(132, 204, 22, .58), rgba(249, 115, 22, .52), transparent);
box-shadow: 0 0 22px rgba(132, 204, 22, .32);
animation: beamMove 7s ease-in-out infinite;
}
.light-beam:nth-child(3) {
top: 63%;
animation-delay: 2.4s;
animation-duration: 8.5s;
opacity: .72;
}
.data-pulse {
position: absolute;
width: 7px;
height: 7px;
border-radius: 50%;
background: #fbbf24;
box-shadow: 0 0 18px rgba(251, 191, 36, .86);
animation: dataFloat 6s ease-in-out infinite;
}
.data-pulse.p1 { left: 18%; top: 28%; }
.data-pulse.p2 { left: 62%; top: 24%; animation-delay: 1.1s; }
.data-pulse.p3 { left: 78%; top: 58%; animation-delay: 2.1s; }
.data-pulse.p4 { left: 34%; top: 70%; animation-delay: 3.2s; }
.hero-stage {
position: absolute;
right: clamp(18px, 6vw, 92px);
bottom: clamp(30px, 8vh, 92px);
width: clamp(260px, 34vw, 460px);
aspect-ratio: 1.18;
z-index: 1;
pointer-events: none;
opacity: .96;
}
.holo-panel {
position: absolute;
inset: 11% 4% 12% 4%;
border: 1px solid rgba(103, 232, 249, .25);
border-radius: 14px;
background:
linear-gradient(135deg, rgba(8, 47, 73, .32), rgba(46, 16, 101, .24)),
repeating-linear-gradient(0deg, rgba(103, 232, 249, .08) 0 1px, transparent 1px 17px);
box-shadow:
inset 0 0 40px rgba(103, 232, 249, .08),
0 24px 90px rgba(0, 0, 0, .3),
0 0 44px rgba(34, 211, 238, .14);
transform: perspective(760px) rotateY(-14deg) rotateX(7deg);
animation: holoFloat 5.8s ease-in-out infinite;
backdrop-filter: blur(8px);
}
.holo-panel::before {
content: "";
position: absolute;
inset: 13%;
border: 1px solid rgba(251, 191, 36, .22);
border-radius: 50%;
background:
radial-gradient(circle, transparent 0 32%, rgba(103, 232, 249, .16) 33% 34%, transparent 35% 49%, rgba(251, 191, 36, .15) 50% 51%, transparent 52%),
conic-gradient(from 0deg, rgba(103, 232, 249, .08), rgba(132, 204, 22, .2), rgba(249, 115, 22, .18), rgba(45, 212, 191, .1), rgba(103, 232, 249, .08));
animation: spinSlow 16s linear infinite;
box-shadow: 0 0 30px rgba(103, 232, 249, .15);
}
.holo-panel::after {
content: "";
position: absolute;
left: 9%;
right: 9%;
top: 50%;
height: 2px;
background: linear-gradient(90deg, transparent, rgba(103, 232, 249, .85), rgba(251, 191, 36, .7), transparent);
box-shadow: 0 0 18px rgba(251, 191, 36, .45);
animation: scanner 3.2s ease-in-out infinite;
}
.holo-card {
position: absolute;
display: inline-flex;
align-items: center;
gap: 8px;
min-height: 34px;
padding: 0 12px;
border: 1px solid rgba(226, 245, 255, .22);
border-radius: 999px;
color: #eef7fb;
background: linear-gradient(135deg, rgba(15, 23, 42, .78), rgba(8, 47, 73, .64));
box-shadow: 0 12px 34px rgba(0, 0, 0, .24), 0 0 22px rgba(34, 211, 238, .1);
font-size: 12px;
font-weight: 800;
backdrop-filter: blur(10px);
animation: chipFloat 4.6s ease-in-out infinite;
}
.holo-card::before {
content: "";
width: 7px;
height: 7px;
border-radius: 50%;
background: #bef264;
box-shadow: 0 0 14px rgba(190, 242, 100, .85);
}
.holo-card.c1 { left: 2%; top: 12%; }
.holo-card.c2 { right: 0; top: 34%; animation-delay: 1s; }
.holo-card.c3 { left: 15%; bottom: 6%; animation-delay: 2s; }
.orbital {
position: absolute;
right: clamp(24px, 9vw, 130px);
top: clamp(110px, 18vh, 180px);
width: clamp(150px, 21vw, 250px);
aspect-ratio: 1;
z-index: 1;
pointer-events: none;
opacity: .82;
}
.orbital-ring {
position: absolute;
inset: 0;
border-radius: 50%;
border: 1px solid rgba(226, 245, 255, .28);
background:
linear-gradient(135deg, rgba(226, 245, 255, .18), rgba(255, 255, 255, .03)),
conic-gradient(from 120deg, rgba(34, 211, 238, .18), rgba(132, 204, 22, .22), rgba(249, 115, 22, .22), rgba(251, 113, 133, .18), rgba(45, 212, 191, .22), rgba(34, 211, 238, .18));
box-shadow:
inset 0 0 24px rgba(255, 255, 255, .55),
0 24px 70px rgba(8, 145, 178, .16);
animation: spinSlow 18s linear infinite;
backdrop-filter: blur(4px);
}
.orbital-ring:nth-child(2) {
inset: 22%;
animation-direction: reverse;
animation-duration: 12s;
opacity: .8;
}
.orbital-core {
position: absolute;
inset: 41%;
border-radius: 50%;
background: radial-gradient(circle at 30% 25%, #ffffff, #bef264 34%, #fbbf24 58%, #fb7185);
box-shadow: 0 0 34px rgba(251, 191, 36, .48);
animation: pulseCore 2.8s ease-in-out infinite;
}
.topbar {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 5;
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 18px clamp(18px, 5vw, 64px);
}
.brand {
display: flex;
align-items: center;
gap: 11px;
font-weight: 800;
letter-spacing: 0;
}
.brand-mark {
width: 36px;
height: 36px;
display: grid;
place-items: center;
border-radius: 8px;
color: white;
background: linear-gradient(135deg, #ffffff 0%, #8be9ff 20%, var(--cyan) 45%, var(--lime) 72%, var(--orange) 100%);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .85),
0 12px 30px rgba(8, 145, 178, .28);
}
.status {
display: flex;
align-items: center;
gap: 9px;
padding: 8px 12px;
border: 1px solid rgba(226, 245, 255, .16);
border-radius: 999px;
background: linear-gradient(135deg, rgba(15, 23, 42, .78), rgba(8, 47, 73, .62));
color: #e5f8ff;
font-size: 13px;
backdrop-filter: blur(12px);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .9),
0 10px 28px rgba(31, 49, 44, .08);
}
.status-dot {
width: 9px;
height: 9px;
border-radius: 50%;
background: #fbbf24;
box-shadow: 0 0 0 5px rgba(251, 191, 36, .16), 0 0 16px rgba(251, 191, 36, .8);
animation: pulseDot 2s ease-in-out infinite;
}
.hero-inner {
width: min(1180px, calc(100% - 36px));
margin: 0 auto;
padding: 118px 0 42px;
position: relative;
z-index: 2;
}
.kicker {
display: inline-flex;
align-items: center;
gap: 8px;
margin-bottom: 14px;
padding: 8px 12px;
border: 1px solid rgba(226, 245, 255, .16);
border-radius: 999px;
background: linear-gradient(135deg, rgba(15, 23, 42, .78), rgba(8, 47, 73, .64), rgba(46, 16, 101, .48));
color: #a7f3ff;
font-size: 13px;
font-weight: 750;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .95),
0 12px 30px rgba(8, 145, 178, .12);
}
h1 {
max-width: 760px;
margin: 0;
font-size: clamp(34px, 6vw, 68px);
line-height: .98;
letter-spacing: 0;
text-shadow: 0 0 22px rgba(34, 211, 238, .14);
background: linear-gradient(110deg, #ffffff 0%, #67e8f9 24%, #bef264 46%, #fbbf24 64%, #fb7185 82%, #ffffff 100%);
background-size: 180% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: titleGlow 6s ease-in-out infinite;
}
.lead {
max-width: 650px;
margin: 16px 0 0;
color: #c2d4dc;
font-size: clamp(15px, 2vw, 18px);
line-height: 1.65;
}
.quick-actions {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 28px;
}
.hero-stats {
display: grid;
grid-template-columns: repeat(3, minmax(112px, 1fr));
gap: 10px;
width: min(520px, 100%);
margin-top: 24px;
}
.hero-stat {
padding: 12px;
border: 1px solid rgba(226, 245, 255, .18);
border-radius: 8px;
background: linear-gradient(145deg, rgba(15, 23, 42, .74), rgba(8, 47, 73, .52), rgba(46, 16, 101, .36));
box-shadow: 0 14px 34px rgba(0, 0, 0, .22);
backdrop-filter: blur(12px);
position: relative;
overflow: hidden;
}
.hero-stat::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(105deg, transparent 0%, rgba(255, 255, 255, .72) 48%, transparent 100%);
transform: translateX(-120%);
animation: shimmer 4.8s ease-in-out infinite;
}
.hero-stat strong {
display: block;
font-size: 24px;
line-height: 1;
background: linear-gradient(135deg, #06b6d4, #84cc16, #f97316);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.hero-stat span {
display: block;
margin-top: 5px;
color: #b7ccd5;
font-size: 12px;
font-weight: 700;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 9px;
min-height: 44px;
padding: 0 16px;
border-radius: 8px;
border: 1px solid transparent;
font-size: 14px;
font-weight: 780;
transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.btn:hover {
transform: translateY(-2px);
}
.btn-primary {
color: white;
background: linear-gradient(135deg, #0f766e, #06b6d4 36%, #84cc16 62%, #f97316);
box-shadow: 0 16px 34px rgba(249, 115, 22, .22);
position: relative;
overflow: hidden;
isolation: isolate;
}
.btn-secondary {
color: #eef7fb;
background: linear-gradient(135deg, rgba(15, 23, 42, .76), rgba(8, 47, 73, .62), rgba(46, 16, 101, .48));
border-color: rgba(226, 245, 255, .18);
}
.btn-primary::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(100deg, transparent 0%, rgba(255,255,255,.45) 45%, transparent 78%);
transform: translateX(-130%);
animation: shimmer 5.4s ease-in-out infinite;
}
.btn-primary::before {
content: "";
position: absolute;
inset: -2px;
z-index: -1;
background: linear-gradient(90deg, #67e8f9, #bef264, #fbbf24, #fb7185, #67e8f9);
background-size: 220% 100%;
filter: blur(12px);
opacity: .58;
animation: chromeSlide 4.4s linear infinite;
}
.content {
width: min(1180px, calc(100% - 36px));
margin: 0 auto;
padding: 34px 0 54px;
}
.section-head {
display: flex;
align-items: end;
justify-content: space-between;
gap: 18px;
margin-bottom: 18px;
}
.section-head h2 {
margin: 0;
font-size: clamp(23px, 3vw, 34px);
letter-spacing: 0;
}
.section-head p {
max-width: 500px;
margin: 8px 0 0;
color: var(--muted);
line-height: 1.55;
}
.search {
width: min(360px, 100%);
min-height: 42px;
padding: 0 14px;
border: 1px solid var(--line);
border-radius: 8px;
background: rgba(8, 18, 27, .86);
color: var(--ink);
font: inherit;
outline: none;
box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
backdrop-filter: blur(10px);
}
.search:focus {
border-color: rgba(21, 127, 100, .55);
}
.search::placeholder {
color: #8ea5af;
}
.project-grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 14px;
}
.project-card {
grid-column: span 4;
display: grid;
min-height: 210px;
padding: 18px;
position: relative;
overflow: hidden;
border: 1px solid rgba(226, 245, 255, .16);
border-radius: 8px;
background:
linear-gradient(145deg, rgba(15, 23, 42, .88), rgba(8, 47, 73, .72), rgba(28, 19, 58, .76)),
var(--panel);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .95),
0 12px 36px rgba(0, 0, 0, .24);
transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.project-card::before {
content: "";
position: absolute;
inset: 0;
height: 5px;
background: linear-gradient(90deg, #67e8f9, #bef264, #fbbf24, #fb7185, #ffffff);
background-size: 220% 100%;
animation: chromeSlide 5.8s linear infinite;
}
.project-card::after {
content: "";
position: absolute;
right: -54px;
top: -54px;
width: 150px;
height: 150px;
border-radius: 50%;
background: radial-gradient(circle, rgba(34, 211, 238, .2), rgba(168, 85, 247, .16) 38%, transparent 68%);
pointer-events: none;
}
.project-card:hover {
transform: translateY(-5px);
border-color: rgba(8, 145, 178, .42);
box-shadow:
inset 0 1px 0 rgba(255,255,255,.95),
0 22px 60px rgba(0, 0, 0, .34),
0 0 0 1px rgba(34, 211, 238, .12);
}
.project-card.featured {
grid-column: span 8;
background:
radial-gradient(circle at 90% 10%, rgba(249, 115, 22, .18), transparent 28%),
radial-gradient(circle at 14% 88%, rgba(132, 204, 22, .18), transparent 28%),
linear-gradient(135deg, rgba(17, 24, 39, .88), rgba(7, 47, 39, .76), rgba(59, 35, 20, .68)),
var(--panel);
}
.project-card.featured::before {
background: linear-gradient(90deg, #ffffff, #67e8f9, #bef264, #fbbf24, #fb7185, #ffffff);
background-size: 220% 100%;
}
.project-top {
display: flex;
align-items: start;
justify-content: space-between;
gap: 12px;
}
.project-icon {
width: 46px;
height: 46px;
display: grid;
place-items: center;
border-radius: 8px;
color: white;
background: linear-gradient(135deg, #ffffff 0%, #67e8f9 25%, var(--cyan) 64%, #0f766e 100%);
flex: 0 0 auto;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .95),
0 14px 28px rgba(8, 145, 178, .24);
}
.project-card:nth-child(2) .project-icon {
background: linear-gradient(135deg, #ffffff, #93c5fd 26%, var(--blue), var(--cyan));
box-shadow: 0 14px 28px rgba(39, 100, 216, .2);
}
.project-card:nth-child(3) .project-icon {
background: linear-gradient(135deg, #ffffff, #fde68a 25%, var(--amber), #eab308);
box-shadow: 0 14px 28px rgba(196, 122, 20, .22);
}
.project-card:nth-child(4) .project-icon {
background: linear-gradient(135deg, #ffffff, #fecaca 24%, var(--red), #f97316);
box-shadow: 0 14px 28px rgba(197, 66, 66, .2);
}
.project-card:nth-child(5) .project-icon {
background: linear-gradient(135deg, #ffffff, #67e8f9 18%, #bef264 38%, #fbbf24 58%, #fb7185 78%, #f97316);
box-shadow: 0 14px 28px rgba(109, 75, 210, .22);
}
.badge {
display: inline-flex;
align-items: center;
min-height: 28px;
padding: 0 10px;
border-radius: 999px;
background: linear-gradient(135deg, rgba(14, 116, 144, .34), rgba(15, 23, 42, .72));
color: #c8f7ff;
font-size: 12px;
font-weight: 800;
white-space: nowrap;
border: 1px solid rgba(103, 232, 249, .2);
}
.badge.login {
color: #eadcff;
background: linear-gradient(135deg, rgba(109, 75, 210, .38), rgba(15, 23, 42, .72));
border-color: rgba(251, 191, 36, .24);
}
.project-title {
margin: 18px 0 7px;
font-size: 20px;
line-height: 1.25;
letter-spacing: 0;
color: #f7fbff;
}
.project-desc {
margin: 0;
color: #adc2cb;
line-height: 1.55;
font-size: 14px;
}
.meta-row {
display: flex;
flex-wrap: wrap;
gap: 7px;
margin: 16px 0 0;
}
.meta {
display: inline-flex;
align-items: center;
min-height: 28px;
padding: 0 9px;
border: 1px solid rgba(226, 245, 255, .14);
border-radius: 7px;
color: #c5d6df;
font-size: 12px;
background: rgba(226, 245, 255, .07);
}
.card-actions {
display: flex;
gap: 9px;
align-items: end;
margin-top: auto;
padding-top: 18px;
}
.open-link {
flex: 1;
min-height: 42px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
border-radius: 8px;
background: linear-gradient(135deg, #101827, #0e7490 34%, #15803d 58%, #c2410c);
color: white;
font-size: 14px;
font-weight: 800;
box-shadow: 0 12px 25px rgba(18, 95, 85, .2);
transition: transform .18s ease, box-shadow .18s ease;
position: relative;
overflow: hidden;
}
.open-link::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(105deg, transparent, rgba(255,255,255,.34), transparent);
transform: translateX(-130%);
animation: shimmer 6s ease-in-out infinite;
}
.open-link:hover {
transform: translateY(-2px);
box-shadow: 0 16px 34px rgba(18, 95, 85, .28);
}
.open-link.alt {
color: #eef7fb;
background: rgba(226, 245, 255, .08);
}
.folder {
display: inline-flex;
align-items: center;
min-height: 42px;
padding: 0 11px;
border: 1px solid var(--line);
border-radius: 8px;
color: var(--muted);
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 12px;
background: rgba(226, 245, 255, .07);
}
@keyframes shimmer {
0%, 62% { transform: translateX(-130%); }
100% { transform: translateX(130%); }
}
@keyframes chromeSlide {
0% { background-position: 0% 50%; }
100% { background-position: 220% 50%; }
}
@keyframes auroraDrift {
from { transform: translateX(-2%) rotate(-2deg); opacity: .75; }
to { transform: translateX(3%) rotate(1deg); opacity: 1; }
}
@keyframes spinSlow {
to { transform: rotate(360deg); }
}
@keyframes pulseCore {
0%, 100% { transform: scale(.92); opacity: .78; }
50% { transform: scale(1.16); opacity: 1; }
}
@keyframes pulseDot {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.22); }
}
@keyframes gridFlow {
from { background-position: 0 0, 0 0; }
to { background-position: 0 56px, 56px 0; }
}
@keyframes beamMove {
0% { transform: translateX(0) rotate(-8deg); opacity: 0; }
16% { opacity: .85; }
72% { opacity: .65; }
100% { transform: translateX(160vw) rotate(-8deg); opacity: 0; }
}
@keyframes dataFloat {
0%, 100% { transform: translate3d(0, 0, 0) scale(.8); opacity: .35; }
45% { transform: translate3d(22px, -18px, 0) scale(1.35); opacity: 1; }
70% { transform: translate3d(-12px, 12px, 0) scale(1); opacity: .68; }
}
@keyframes holoFloat {
0%, 100% { transform: perspective(760px) rotateY(-14deg) rotateX(7deg) translateY(0); }
50% { transform: perspective(760px) rotateY(-10deg) rotateX(9deg) translateY(-12px); }
}
@keyframes scanner {
0%, 100% { transform: translateY(-82px); opacity: .18; }
48% { opacity: .95; }
50% { transform: translateY(82px); }
}
@keyframes chipFloat {
0%, 100% { transform: translate3d(0, 0, 0); }
50% { transform: translate3d(10px, -12px, 0); }
}
@keyframes titleGlow {
0%, 100% { background-position: 0% 50%; filter: drop-shadow(0 0 8px rgba(103, 232, 249, .1)); }
50% { background-position: 100% 50%; filter: drop-shadow(0 0 18px rgba(103, 232, 249, .25)); }
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: .01ms !important;
animation-iteration-count: 1 !important;
scroll-behavior: auto !important;
}
}
.hidden {
display: none;
}
@media (max-width: 920px) {
.hero-stage {
opacity: .42;
right: -80px;
bottom: 100px;
}
.orbital {
opacity: .38;
right: -44px;
top: 110px;
}
.project-card,
.project-card.featured {
grid-column: span 6;
}
.section-head {
grid-template-columns: 1fr;
}
}
@media (max-width: 640px) {
.hero {
min-height: 70vh;
}
.orbital {
width: 150px;
right: -58px;
top: 136px;
}
.hero-stage {
width: 280px;
right: -130px;
bottom: 130px;
opacity: .28;
}
.topbar {
align-items: flex-start;
flex-direction: column;
}
.hero-inner {
padding-top: 144px;
}
.project-card,
.project-card.featured {
grid-column: 1 / -1;
}
.card-actions {
align-items: stretch;
flex-direction: column;
}
.folder {
justify-content: center;
}
.hero-stats {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<section class="hero">
<div id="hero-map" aria-hidden="true"></div>
<div class="future-bg" aria-hidden="true">
<div class="scan-grid"></div>
<span class="light-beam"></span>
<span class="light-beam"></span>
<span class="data-pulse p1"></span>
<span class="data-pulse p2"></span>
<span class="data-pulse p3"></span>
<span class="data-pulse p4"></span>
</div>
<div class="hero-stage" aria-hidden="true">
<div class="holo-panel"></div>
<span class="holo-card c1">Publik 04</span>
<span class="holo-card c2">Login V3</span>
<span class="holo-card c3">WebGIS Hub</span>
</div>
<div class="orbital" aria-hidden="true">
<span class="orbital-ring"></span>
<span class="orbital-ring"></span>
<span class="orbital-core"></span>
</div>
<nav class="topbar" aria-label="Navigasi portal">
<a class="brand" href="./" aria-label="Portal Combine WebGIS">
<span class="brand-mark">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M9 18 3 21V6l6-3 6 3 6-3v15l-6 3-6-3Z"/><path d="M9 3v15M15 6v15"/></svg>
</span>
<span>Combine WebGIS</span>
</a>
<div class="status"><span class="status-dot"></span>5 project tersedia</div>
</nav>
<div class="hero-inner">
<div class="kicker">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M12 21s7-5.2 7-11a7 7 0 1 0-14 0c0 5.8 7 11 7 11Z"/><circle cx="12" cy="10" r="2.4"/></svg>
WebGIS Portal
</div>
<h1>Pilih WebGIS yang ingin dibuka.</h1>
<p class="lead">Akses cepat ke 5 project WebGIS dalam satu portal.</p>
<div class="quick-actions">
<a class="btn btn-primary" href="#projects">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M4 5h16M4 12h16M4 19h16"/></svg>
Lihat Project
</a>
<a class="btn btn-secondary" href="webgis-v3/">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><path d="M10 17l5-5-5-5M15 12H3"/></svg>
Masuk WebGIS V3
</a>
</div>
<div class="hero-stats" aria-label="Ringkasan portal">
<div class="hero-stat">
<strong>04</strong>
<span>Publik</span>
</div>
<div class="hero-stat">
<strong>01</strong>
<span>Login</span>
</div>
<div class="hero-stat">
<strong>05</strong>
<span>Project</span>
</div>
</div>
</div>
</section>
<main class="content" id="projects">
<div class="section-head">
<div>
<h2>Daftar Project</h2>
<p><code>webgis01</code> - <code>webgis04</code> publik, <code>webgis-v3</code> login.</p>
</div>
<input class="search" id="projectSearch" type="search" placeholder="Cari project..." aria-label="Cari project">
</div>
<section class="project-grid" id="projectGrid" aria-label="Pilihan project WebGIS">
<article class="project-card" data-project="webgis01 spbu crud tanpa login">
<div class="project-top">
<div class="project-icon">
<svg width="23" height="23" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" aria-hidden="true"><path d="M3 22V5a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v17"/><path d="M8 7h2M7 12h4M14 9h2l3 3v7a2 2 0 0 0 2 2"/><path d="M18 14h.01"/></svg>
</div>
<span class="badge">Tanpa login</span>
</div>
<h3 class="project-title">WebGIS 01</h3>
<p class="project-desc">SPBU Interaktif</p>
<div class="meta-row">
<span class="meta">Leaflet</span>
<span class="meta">CRUD SPBU</span>
<span class="meta">PHP</span>
</div>
<div class="card-actions">
<a class="open-link" href="webgis01/">Buka Project</a>
<span class="folder">webgis01</span>
</div>
</article>
<article class="project-card" data-project="webgis02 jalan parsil jalan rusak tanpa login">
<div class="project-top">
<div class="project-icon">
<svg width="23" height="23" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" aria-hidden="true"><path d="m4 19 5-14M15 5l5 14M9 15h6M10.5 11h3M12 5v14"/></svg>
</div>
<span class="badge">Tanpa login</span>
</div>
<h3 class="project-title">WebGIS 02</h3>
<p class="project-desc">Jalan, Parsil, Rusak</p>
<div class="meta-row">
<span class="meta">Leaflet Draw</span>
<span class="meta">Upload Foto</span>
<span class="meta">Multi layer</span>
</div>
<div class="card-actions">
<a class="open-link" href="webgis02/">Buka Project</a>
<span class="folder">webgis02</span>
</div>
</article>
<article class="project-card" data-project="webgis03 kepadatan penduduk pontianak choropleth tanpa login">
<div class="project-top">
<div class="project-icon">
<svg width="23" height="23" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" aria-hidden="true"><path d="M3 21h18"/><path d="M5 21V9l4-3 4 3v12"/><path d="M13 21V7l3-2 3 2v14"/><path d="M8 13h1M8 17h1M16 11h1M16 15h1"/></svg>
</div>
<span class="badge">Tanpa login</span>
</div>
<h3 class="project-title">WebGIS 03</h3>
<p class="project-desc">Kepadatan Penduduk</p>
<div class="meta-row">
<span class="meta">GeoJSON</span>
<span class="meta">Choropleth</span>
<span class="meta">Pontianak</span>
</div>
<div class="card-actions">
<a class="open-link" href="webgis03/">Buka Project</a>
<span class="folder">webgis03</span>
</div>
</article>
<article class="project-card" data-project="webgis04 spbu layer control tanpa login">
<div class="project-top">
<div class="project-icon">
<svg width="23" height="23" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" aria-hidden="true"><path d="m12 2 9 5-9 5-9-5 9-5Z"/><path d="m3 12 9 5 9-5"/><path d="m3 17 9 5 9-5"/></svg>
</div>
<span class="badge">Tanpa login</span>
</div>
<h3 class="project-title">WebGIS 04</h3>
<p class="project-desc">SPBU Layer Control</p>
<div class="meta-row">
<span class="meta">Layer Control</span>
<span class="meta">SPBU</span>
<span class="meta">Filter status</span>
</div>
<div class="card-actions">
<a class="open-link" href="webgis04/">Buka Project</a>
<span class="folder">webgis04</span>
</div>
</article>
<article class="project-card featured" data-project="webgis-v3 kemiskinan pontianak login dashboard bantuan rumah ibadah">
<div class="project-top">
<div class="project-icon">
<svg width="23" height="23" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" aria-hidden="true"><path d="M12 3 4 7v6c0 5 3.4 7.7 8 9 4.6-1.3 8-4 8-9V7l-8-4Z"/><path d="M9 12l2 2 4-5"/></svg>
</div>
<span class="badge login">Menggunakan login</span>
</div>
<h3 class="project-title">WebGIS V3</h3>
<p class="project-desc">Sistem Kemiskinan Pontianak</p>
<div class="meta-row">
<span class="meta">Autentikasi</span>
<span class="meta">Dashboard</span>
<span class="meta">Manajemen data</span>
<span class="meta">Role akses</span>
</div>
<div class="card-actions">
<a class="open-link" href="webgis-v3/">Masuk Project Login</a>
<span class="folder">webgis-v3</span>
</div>
</article>
</section>
</main>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
const heroMap = L.map('hero-map', {
zoomControl: false,
attributionControl: false,
dragging: false,
scrollWheelZoom: false,
doubleClickZoom: false,
boxZoom: false,
keyboard: false,
tap: false
}).setView([-0.0271, 109.3454], 12);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19
}).addTo(heroMap);
const points = [
[-0.0263, 109.3424, 'WebGIS 01'],
[-0.0400, 109.3300, 'WebGIS 02'],
[-0.0170, 109.3520, 'WebGIS 03'],
[-0.0085, 109.3260, 'WebGIS 04'],
[-0.0318, 109.3650, 'WebGIS V3']
];
points.forEach(([lat, lng, title]) => {
L.circleMarker([lat, lng], {
radius: title.includes('V3') ? 9 : 6,
color: '#ffffff',
weight: 2,
fillColor: title.includes('V3') ? '#f97316' : '#84cc16',
fillOpacity: .95
}).bindTooltip(title, { permanent: false }).addTo(heroMap);
});
const search = document.getElementById('projectSearch');
const cards = [...document.querySelectorAll('.project-card')];
search.addEventListener('input', () => {
const keyword = search.value.trim().toLowerCase();
cards.forEach(card => {
card.classList.toggle('hidden', keyword && !card.dataset.project.includes(keyword));
});
});
</script>
</body>
</html>