Clean commit: remove all heavy binaries and history
This commit is contained in:
643
assets/css/app.css
Executable file
643
assets/css/app.css
Executable file
@@ -0,0 +1,643 @@
|
||||
/* app.css - Design System Premium untuk SpeedTest */
|
||||
|
||||
/* Impor font Roboto asli proyek */
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("../fonts/roboto-v30-latin-regular.eot");
|
||||
src: local(""),
|
||||
url("../fonts/roboto-v30-latin-regular.eot?#iefix") format("embedded-opentype"),
|
||||
url("../fonts/roboto-v30-latin-regular.woff2") format("woff2"),
|
||||
url("../fonts/roboto-v30-latin-regular.woff") format("woff"),
|
||||
url("../fonts/roboto-v30-latin-regular.ttf") format("truetype"),
|
||||
url("../fonts/roboto-v30-latin-regular.svg#Roboto") format("svg");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url("assets/fonts/roboto-v30-latin-500.eot");
|
||||
src: local(""),
|
||||
url("assets/fonts/roboto-v30-latin-500.eot?#iefix") format("embedded-opentype"),
|
||||
url("assets/fonts/roboto-v30-latin-500.woff2") format("woff2"),
|
||||
url("assets/fonts/roboto-v30-latin-500.woff") format("woff"),
|
||||
url("assets/fonts/roboto-v30-latin-500.ttf") format("truetype"),
|
||||
url("assets/fonts/roboto-v30-latin-500.svg#Roboto") format("svg");
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
background: radial-gradient(circle at 50% 50%, #F8FAFC 0%, #E2E8F0 100%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
transition: background 0.4s ease;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
/* Container Utama */
|
||||
.app-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
max-width: 960px;
|
||||
padding: 24px;
|
||||
box-sizing: border-box;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
/* Header Dashboard */
|
||||
.app-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
animation: fadeInDown 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
}
|
||||
|
||||
.header-logo-img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
object-fit: contain;
|
||||
filter: drop-shadow(0 4px 12px rgba(79, 172, 254, 0.3));
|
||||
}
|
||||
|
||||
.header-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.header-text h1 {
|
||||
margin: 0;
|
||||
font-family: 'Outfit', sans-serif;
|
||||
font-size: 24px;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.02em;
|
||||
color: #0F172A;
|
||||
}
|
||||
|
||||
.header-badge {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #2563EB;
|
||||
background: rgba(37, 99, 235, 0.08);
|
||||
padding: 4px 10px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(37, 99, 235, 0.15);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.client-ip-container {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: calc(50% - 150px);
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #64748B;
|
||||
z-index: 20;
|
||||
pointer-events: none;
|
||||
white-space: nowrap;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
@media only screen and (orientation: portrait) {
|
||||
.client-ip-container {
|
||||
left: 50%;
|
||||
top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.client-ip-container span#client-ip-text {
|
||||
color: #0EA5E9;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Card Wrapper Speed Test */
|
||||
.app-card {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
backdrop-filter: blur(24px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(24px) saturate(180%);
|
||||
border: 1px solid rgba(255, 255, 255, 0.4);
|
||||
border-radius: 32px;
|
||||
box-shadow:
|
||||
0 20px 40px -15px rgba(15, 23, 42, 0.05),
|
||||
0 0 80px rgba(15, 23, 42, 0.02),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.6);
|
||||
padding: 40px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
animation: scaleIn 0.8s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
}
|
||||
|
||||
.app-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow:
|
||||
0 30px 60px -20px rgba(15, 23, 42, 0.08),
|
||||
0 0 100px rgba(15, 23, 42, 0.03),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||
border-color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
/* SVG App Sizing */
|
||||
.openSpeedtestApp {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
height: auto;
|
||||
aspect-ratio: 586 / 346;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Spinner Loader */
|
||||
.spinner {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.spinner>div {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: linear-gradient(135deg, #00F2FE 0%, #4FACFE 100%);
|
||||
border-radius: 50%;
|
||||
animation: bounceDelay 1.4s infinite ease-in-out both;
|
||||
}
|
||||
|
||||
.spinner .bounce1 {
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.spinner .bounce2 {
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
/* ==========================================
|
||||
KONTROL TAMPILAN ELEMENT (PENTING!)
|
||||
Menyembunyikan komponen SVG secara default
|
||||
agar tidak bertumpuk.
|
||||
========================================== */
|
||||
#UI-Desk {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#UI-Mob {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#ipMob {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#ipDesk {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#upSymbolDesk {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#downSymbolDesk {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#upSymbolMob {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#downSymbolMob {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ConnectError {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ==========================================
|
||||
TYPOGRAPHY DI DALAM SVG (ASLI ROBOTO)
|
||||
Menggunakan font-family dan ukuran asli
|
||||
agar layout & koordinat SVG tidak berantakan
|
||||
========================================== */
|
||||
.oDoLive-Speed {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
font-size: 20px !important;
|
||||
font-weight: 500 !important;
|
||||
fill: #500516 !important;
|
||||
text-anchor: middle !important;
|
||||
}
|
||||
|
||||
.oDoLive-Status {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
font-size: 10px !important;
|
||||
font-weight: 500 !important;
|
||||
fill: #94A3B8 !important;
|
||||
text-anchor: middle !important;
|
||||
}
|
||||
|
||||
.rtextnum {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
font-size: 23px !important;
|
||||
font-weight: 500 !important;
|
||||
fill: #0F172A !important;
|
||||
text-anchor: middle !important;
|
||||
}
|
||||
|
||||
.rtext {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
font-size: 10px !important;
|
||||
font-weight: 400 !important;
|
||||
fill: #64748B !important;
|
||||
}
|
||||
|
||||
.rtextmbms {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 500 !important;
|
||||
fill: #94A3B8 !important;
|
||||
text-anchor: middle !important;
|
||||
}
|
||||
|
||||
.oDo-Meter {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
font-size: 16.63px !important;
|
||||
font-weight: 500 !important;
|
||||
fill: #94A3B8 !important;
|
||||
}
|
||||
|
||||
.oDoTop-Speed {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
font-size: 16.96px !important;
|
||||
font-weight: 500 !important;
|
||||
fill: #94A3B8 !important;
|
||||
text-anchor: end !important;
|
||||
}
|
||||
|
||||
.jitter-Mob {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
font-size: 9px !important;
|
||||
font-weight: 500 !important;
|
||||
fill: #64748B !important;
|
||||
text-anchor: middle !important;
|
||||
}
|
||||
|
||||
.buttonTxt {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
font-size: 40px !important;
|
||||
font-weight: 500 !important;
|
||||
fill: #ffffff !important;
|
||||
text-anchor: middle !important;
|
||||
}
|
||||
|
||||
/* ==========================================
|
||||
ESTETIKA DAN DESAIN ELEMEN SVG
|
||||
========================================== */
|
||||
.Cards {
|
||||
fill: rgba(248, 250, 252, 0.8) !important;
|
||||
stroke: rgba(226, 232, 240, 0.8) !important;
|
||||
stroke-width: 1.5px !important;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.uiBg {
|
||||
fill: #94A3B8 !important;
|
||||
}
|
||||
|
||||
.Symbol {
|
||||
fill: url(#gradient) !important;
|
||||
}
|
||||
|
||||
.progressbg {
|
||||
stroke: #E2E8F0 !important;
|
||||
stroke-width: 8px !important;
|
||||
stroke-linecap: round !important;
|
||||
stroke-linejoin: round !important;
|
||||
stroke-dasharray: 400 !important;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
|
||||
.intro-Progress {
|
||||
stroke: #4FACFE !important;
|
||||
stroke-width: 8px !important;
|
||||
stroke-linecap: round !important;
|
||||
stroke-linejoin: round !important;
|
||||
stroke-dasharray: 400 !important;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
|
||||
.progressElmstart {
|
||||
stroke: #4FACFE !important;
|
||||
stroke-width: 8px !important;
|
||||
stroke-linecap: round !important;
|
||||
stroke-linejoin: round !important;
|
||||
stroke-dasharray: 400 !important;
|
||||
stroke-dashoffset: 0;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.main-Gaugebg {
|
||||
fill: none !important;
|
||||
stroke: #E2E8F0 !important;
|
||||
stroke-linecap: round !important;
|
||||
stroke-linejoin: round !important;
|
||||
stroke-width: 22px !important;
|
||||
stroke-dasharray: 681 !important;
|
||||
}
|
||||
|
||||
.main-GaugeBlue {
|
||||
fill: none !important;
|
||||
stroke: url(#gradient) !important;
|
||||
stroke-linecap: round !important;
|
||||
stroke-linejoin: round !important;
|
||||
stroke-width: 22px !important;
|
||||
stroke-dasharray: 681 !important;
|
||||
stroke-opacity: 0;
|
||||
}
|
||||
|
||||
.main-GaugeWhite {
|
||||
fill: none !important;
|
||||
stroke: rgb(255, 255, 255) !important;
|
||||
stroke-linecap: round !important;
|
||||
stroke-linejoin: round !important;
|
||||
stroke-width: 15px !important;
|
||||
stroke-dasharray: 0, 681 !important;
|
||||
stroke-dashoffset: 1;
|
||||
stroke-opacity: 0;
|
||||
}
|
||||
|
||||
.deskStart {
|
||||
fill: none !important;
|
||||
stroke: url(#gradient) !important;
|
||||
stroke-linecap: round !important;
|
||||
stroke-linejoin: round !important;
|
||||
stroke-dasharray: 681 !important;
|
||||
}
|
||||
|
||||
/* Button & Interactive elements */
|
||||
.startButton {
|
||||
fill: url(#gradient) !important;
|
||||
cursor: pointer;
|
||||
filter: drop-shadow(0 8px 20px rgba(0, 242, 254, 0.25));
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transform-box: fill-box;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.startButton:hover {
|
||||
filter: drop-shadow(0 12px 28px rgba(0, 242, 254, 0.45));
|
||||
opacity: 0.95;
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.startButton:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.Startsettings {
|
||||
cursor: pointer;
|
||||
opacity: 0.3;
|
||||
transition: all 0.3s ease;
|
||||
transform-box: fill-box;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.Startsettings:hover {
|
||||
opacity: 0.9;
|
||||
transform: rotate(30deg);
|
||||
}
|
||||
|
||||
/* Restyle logo di SVG menggunakan CSS */
|
||||
svg [style*="fill: #3da6ff"] {
|
||||
fill: #2563EB !important;
|
||||
/* Modern Royal Blue */
|
||||
}
|
||||
|
||||
svg [style*="fill: #4d4d4d"] {
|
||||
fill: #0F172A !important;
|
||||
/* Slate 900 */
|
||||
}
|
||||
|
||||
/* Dark mode toggle */
|
||||
.darkmode {
|
||||
fill: #94A3B8 !important;
|
||||
transition: all 0.3s ease;
|
||||
transform-box: fill-box;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.darkmode:hover {
|
||||
fill: #2563EB !important;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
#daymode {
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
/* Footer & Credits */
|
||||
.Credits {
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 13px;
|
||||
color: #64748B;
|
||||
animation: fadeInUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.Credits p {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.Credits a {
|
||||
text-decoration: none;
|
||||
color: #2563EB;
|
||||
font-weight: 600;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.Credits a:hover {
|
||||
color: #1d4ed8;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-size: 11px;
|
||||
color: #94A3B8;
|
||||
}
|
||||
|
||||
/* Media Queries Responsif */
|
||||
.Mobile,
|
||||
.Desktop {
|
||||
visibility: hidden;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
@media only screen and (orientation: landscape) {
|
||||
.Mobile {
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.Desktop {
|
||||
visibility: visible;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (orientation: portrait) {
|
||||
.app-card {
|
||||
padding: 24px;
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.openSpeedtestApp {
|
||||
width: 100%;
|
||||
max-width: 320px;
|
||||
aspect-ratio: 295.9 / 363.3;
|
||||
}
|
||||
|
||||
.Mobile {
|
||||
visibility: visible;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.Desktop {
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 360px) {
|
||||
.Credits {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Animasi */
|
||||
@keyframes bounceDelay {
|
||||
|
||||
0%,
|
||||
80%,
|
||||
100% {
|
||||
transform: scale(0);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: scale(1.0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tombol Refresh / Uji Lagi */
|
||||
.refresh-btn {
|
||||
display: none;
|
||||
/* Disembunyikan secara default */
|
||||
background: linear-gradient(135deg, #00F2FE 0%, #4FACFE 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 28px;
|
||||
font-family: 'Outfit', 'Inter', sans-serif;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
border-radius: 50px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 8px 20px rgba(0, 242, 254, 0.25);
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
z-index: 10;
|
||||
margin-top: 10px;
|
||||
margin-bottom: -6px;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
animation: fadeInUp 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
}
|
||||
|
||||
.refresh-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 12px 28px rgba(0, 242, 254, 0.45);
|
||||
filter: brightness(1.05);
|
||||
}
|
||||
|
||||
.refresh-btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.refresh-btn svg {
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
.refresh-btn:hover svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
Reference in New Issue
Block a user