update mobile
This commit is contained in:
@@ -3,11 +3,11 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
content="Kediri Technopark - Katalis Karir dan Bisnis Digital"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!-- Font Awesome -->
|
||||
@@ -26,7 +26,7 @@
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
<title>Kediri Technopark</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
||||
@@ -9,10 +9,27 @@ const AnimatedBackground = () => {
|
||||
const ctx = canvas.getContext('2d');
|
||||
let animationFrameId;
|
||||
let particles = [];
|
||||
const particleCount = 70;
|
||||
|
||||
// Determine particle count based on screen size
|
||||
const getParticleCount = () => {
|
||||
const width = window.innerWidth;
|
||||
if (width <= 400) return 30; // Very small screens
|
||||
if (width <= 576) return 40; // Small screens
|
||||
if (width <= 768) return 50; // Medium screens
|
||||
return 70; // Large screens
|
||||
};
|
||||
|
||||
function Particle(x, y, vx, vy) {
|
||||
this.x = x; this.y = y; this.vx = vx; this.vy = vy; this.radius = 1.5;
|
||||
this.x = x; this.y = y; this.vx = vx; this.vy = vy;
|
||||
|
||||
// Adjust particle radius based on screen size
|
||||
if (window.innerWidth <= 400) {
|
||||
this.radius = 1.0; // Smaller radius for very small screens
|
||||
} else if (window.innerWidth <= 576) {
|
||||
this.radius = 1.2; // Medium radius for small screens
|
||||
} else {
|
||||
this.radius = 1.5; // Default radius for larger screens
|
||||
}
|
||||
}
|
||||
|
||||
const setupCanvas = () => {
|
||||
@@ -31,6 +48,9 @@ const AnimatedBackground = () => {
|
||||
|
||||
ctx.scale(dpr, dpr);
|
||||
|
||||
// Get particle count based on current screen size
|
||||
const particleCount = getParticleCount();
|
||||
|
||||
particles = [];
|
||||
for (let i = 0; i < particleCount; i++) {
|
||||
particles.push(new Particle(Math.random() * cssWidth, Math.random() * cssHeight, (Math.random() - 0.5) * 0.5, (Math.random() - 0.5) * 0.5));
|
||||
@@ -40,7 +60,14 @@ const AnimatedBackground = () => {
|
||||
function connectParticles() {
|
||||
const cssWidth = canvas.clientWidth;
|
||||
const cssHeight = canvas.clientHeight;
|
||||
const connectionDistance = 90;
|
||||
|
||||
// Adjust connection distance based on screen size
|
||||
let connectionDistance = 90;
|
||||
if (window.innerWidth <= 400) {
|
||||
connectionDistance = 60; // Smaller connection distance for very small screens
|
||||
} else if (window.innerWidth <= 576) {
|
||||
connectionDistance = 70; // Medium connection distance for small screens
|
||||
}
|
||||
|
||||
for (let i = 0; i < particles.length; i++) {
|
||||
for (let j = i + 1; j < particles.length; j++) {
|
||||
@@ -83,6 +110,14 @@ const AnimatedBackground = () => {
|
||||
const cssHeight = canvas.clientHeight;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Adjust animation speed based on screen size
|
||||
let speedFactor = 1.0;
|
||||
if (window.innerWidth <= 400) {
|
||||
speedFactor = 0.7; // Slower animation for very small screens
|
||||
} else if (window.innerWidth <= 576) {
|
||||
speedFactor = 0.8; // Slightly slower animation for small screens
|
||||
}
|
||||
|
||||
for (const p of particles) {
|
||||
// LOGIKA BARU: Partikel tembus (wrapping) bukan memantul (bounce)
|
||||
if (p.x > cssWidth + p.radius) p.x = -p.radius;
|
||||
@@ -91,8 +126,8 @@ const AnimatedBackground = () => {
|
||||
if (p.y > cssHeight + p.radius) p.y = -p.radius;
|
||||
else if (p.y < -p.radius) p.y = cssHeight + p.radius;
|
||||
|
||||
p.x += p.vx;
|
||||
p.y += p.vy;
|
||||
p.x += p.vx * speedFactor;
|
||||
p.y += p.vy * speedFactor;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
|
||||
@@ -106,11 +141,17 @@ const AnimatedBackground = () => {
|
||||
|
||||
setupCanvas();
|
||||
animate();
|
||||
window.addEventListener('resize', setupCanvas);
|
||||
|
||||
// Handle resize events to adjust particle count
|
||||
const handleResize = () => {
|
||||
setupCanvas();
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame(animationFrameId);
|
||||
window.removeEventListener('resize', setupCanvas);
|
||||
window.removeEventListener('resize', handleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -71,6 +71,15 @@ const CoverflowCarousel = ({ products, onCardClick }) => {
|
||||
goToProduct(index, dir);
|
||||
};
|
||||
|
||||
// Collapse overlay for center card
|
||||
const collapseOverlay = () => {
|
||||
// Reset animation state to force collapse
|
||||
setAnimationState('spread');
|
||||
setTimeout(() => {
|
||||
setAnimationState('ready');
|
||||
}, 50);
|
||||
};
|
||||
|
||||
// Initialize carousel with spread effect when products are available
|
||||
useEffect(() => {
|
||||
if (!products || products.length === 0) return;
|
||||
@@ -159,7 +168,15 @@ const CoverflowCarousel = ({ products, onCardClick }) => {
|
||||
animationState === 'initial' ? styles.initial :
|
||||
animationState === 'spread' ? styles.spread : ''
|
||||
}`}
|
||||
onClick={() => { goToProduct(productIndex, position > 0 ? 'right' : (position < 0 ? 'left' : null)); }}
|
||||
onClick={() => {
|
||||
// Only trigger navigation if this is not the center card
|
||||
// or if it's the center card but not in hover state (overlay not visible)
|
||||
const isCenter = position === 0;
|
||||
const canHover = isCenter && animationState === 'ready' && !shiftDirection && !isDragging;
|
||||
if (position !== 0 || (position === 0 && (!canHover || animationState !== 'ready' || shiftDirection || isDragging))) {
|
||||
goToProduct(productIndex, position > 0 ? 'right' : (position < 0 ? 'left' : null));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className={styles.cardShadow} aria-hidden="true"></div>
|
||||
<div className={styles.cardWrapper}>
|
||||
@@ -168,6 +185,7 @@ const CoverflowCarousel = ({ products, onCardClick }) => {
|
||||
onCardClick={(p) => { onCardClick && onCardClick(p); }}
|
||||
isCenter={position === 0}
|
||||
canHover={position === 0 && animationState === 'ready' && !shiftDirection && !isDragging}
|
||||
onCollapse={position === 0 ? collapseOverlay : undefined}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,27 @@
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Left and right fade out masks */
|
||||
.leftMask,
|
||||
.rightMask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100px;
|
||||
z-index: 20;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.leftMask {
|
||||
left: 0;
|
||||
background: linear-gradient(to right, #0b1220, transparent);
|
||||
}
|
||||
|
||||
.rightMask {
|
||||
right: 0;
|
||||
background: linear-gradient(to left, #0b1220, transparent);
|
||||
}
|
||||
|
||||
.container.dragging {
|
||||
cursor: grabbing;
|
||||
}
|
||||
@@ -415,6 +436,11 @@
|
||||
.dotsContainer {
|
||||
bottom: -35px;
|
||||
}
|
||||
|
||||
.leftMask,
|
||||
.rightMask {
|
||||
width: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
@@ -453,6 +479,11 @@
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.leftMask,
|
||||
.rightMask {
|
||||
width: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@@ -497,21 +528,26 @@
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
}
|
||||
|
||||
.leftMask,
|
||||
.rightMask {
|
||||
width: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.container {
|
||||
height: 350px;
|
||||
height: 320px;
|
||||
margin: 20px 0 40px 0;
|
||||
}
|
||||
|
||||
.cardContainer {
|
||||
width: 220px;
|
||||
height: 270px;
|
||||
width: 200px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.cardWrapper {
|
||||
padding: 0 8px;
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.navButton {
|
||||
@@ -541,17 +577,39 @@
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
/* Adjust positions for smaller screens */
|
||||
.cardContainer.positionNeg2 {
|
||||
transform: translateX(-280px) rotateY(55deg) scale(0.6);
|
||||
}
|
||||
|
||||
.cardContainer.positionNeg1 {
|
||||
transform: translateX(-140px) rotateY(35deg) scale(0.75);
|
||||
}
|
||||
|
||||
.cardContainer.position1 {
|
||||
transform: translateX(140px) rotateY(-35deg) scale(0.75);
|
||||
}
|
||||
|
||||
.cardContainer.position2 {
|
||||
transform: translateX(280px) rotateY(-55deg) scale(0.6);
|
||||
}
|
||||
|
||||
.leftMask,
|
||||
.rightMask {
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.container {
|
||||
height: 320px;
|
||||
height: 280px;
|
||||
margin: 15px 0 35px 0;
|
||||
}
|
||||
|
||||
.cardContainer {
|
||||
width: 200px;
|
||||
height: 250px;
|
||||
width: 180px;
|
||||
height: 230px;
|
||||
}
|
||||
|
||||
.navButton {
|
||||
@@ -572,4 +630,26 @@
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
/* Further adjust positions for very small screens */
|
||||
.cardContainer.positionNeg2 {
|
||||
transform: translateX(-240px) rotateY(55deg) scale(0.5);
|
||||
}
|
||||
|
||||
.cardContainer.positionNeg1 {
|
||||
transform: translateX(-120px) rotateY(35deg) scale(0.7);
|
||||
}
|
||||
|
||||
.cardContainer.position1 {
|
||||
transform: translateX(120px) rotateY(-35deg) scale(0.7);
|
||||
}
|
||||
|
||||
.cardContainer.position2 {
|
||||
transform: translateX(240px) rotateY(-55deg) scale(0.5);
|
||||
}
|
||||
|
||||
.leftMask,
|
||||
.rightMask {
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,18 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// Close mobile menu when window is resized to desktop size
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
if (window.innerWidth > 600) {
|
||||
setMenuOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<header className={`${styles.header} ${isScrolled ? styles.headerScrolled : ''}`}>
|
||||
<img src="./kediri-technopark-logo.png" className={styles.logo} alt="Logo" />
|
||||
@@ -39,7 +51,7 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
className={`${styles.navLink} ${hoveredNav === 2 ? styles.navLinkHover : ''}`}
|
||||
onMouseEnter={() => setHoveredNav(2)}
|
||||
onMouseLeave={() => setHoveredNav(null)}
|
||||
onClick={() => navigate('/')}
|
||||
onClick={() => { navigate('/'); setMenuOpen(false); }}
|
||||
>
|
||||
Home
|
||||
</a>
|
||||
@@ -49,6 +61,7 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
onMouseLeave={() => setHoveredNav(null)}
|
||||
onClick={() => {
|
||||
navigate('/dashboard');
|
||||
setMenuOpen(false);
|
||||
}}>
|
||||
Dashboard
|
||||
</a>
|
||||
@@ -60,7 +73,7 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
className={`${styles.navLink} ${hoveredNav === 21 ? styles.navLinkHover : ''}`}
|
||||
onMouseEnter={() => setHoveredNav(21)}
|
||||
onMouseLeave={() => setHoveredNav(null)}
|
||||
onClick={() => scrollToId('about')}
|
||||
onClick={() => { scrollToId('about'); setMenuOpen(false); }}
|
||||
>
|
||||
About
|
||||
</a>
|
||||
@@ -68,7 +81,7 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
className={`${styles.navLink} ${hoveredNav === 22 ? styles.navLinkHover : ''}`}
|
||||
onMouseEnter={() => setHoveredNav(22)}
|
||||
onMouseLeave={() => setHoveredNav(null)}
|
||||
onClick={() => scrollToId('services')}
|
||||
onClick={() => { scrollToId('services'); setMenuOpen(false); }}
|
||||
>
|
||||
Services
|
||||
</a>
|
||||
@@ -76,7 +89,7 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
className={`${styles.navLink} ${hoveredNav === 3 ? styles.navLinkHover : ''}`}
|
||||
onMouseEnter={() => setHoveredNav(3)}
|
||||
onMouseLeave={() => setHoveredNav(null)}
|
||||
onClick={() => scrollToId('products')}
|
||||
onClick={() => { scrollToId('products'); setMenuOpen(false); }}
|
||||
>
|
||||
Products
|
||||
</a>
|
||||
@@ -84,7 +97,7 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
className={`${styles.navLink} ${hoveredNav === 4 ? styles.navLinkHover : ''}`}
|
||||
onMouseEnter={() => setHoveredNav(4)}
|
||||
onMouseLeave={() => setHoveredNav(null)}
|
||||
onClick={() => scrollToId('academy')}
|
||||
onClick={() => { scrollToId('academy'); setMenuOpen(false); }}
|
||||
>
|
||||
Academy
|
||||
</a>
|
||||
@@ -92,7 +105,7 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
className={`${styles.navLink} ${hoveredNav === 5 ? styles.navLinkHover : ''}`}
|
||||
onMouseEnter={() => setHoveredNav(5)}
|
||||
onMouseLeave={() => setHoveredNav(null)}
|
||||
onClick={() => scrollToId('faq')}
|
||||
onClick={() => { scrollToId('faq'); setMenuOpen(false); }}
|
||||
>
|
||||
FAQ
|
||||
</a>
|
||||
@@ -111,7 +124,7 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
{username ? (
|
||||
<>
|
||||
<div className={styles.username}>{username}</div>
|
||||
{/* <button onClick={() => { setMenuOpen(false); navigate('/'); }}>Home</button> */}
|
||||
<button onClick={() => { setMenuOpen(false); navigate('/'); }}>Home</button>
|
||||
<button onClick={() => { setMenuOpen(false); scrollToId('about'); }}>About</button>
|
||||
<button onClick={() => { setMenuOpen(false); scrollToId('services'); }}>Services</button>
|
||||
<button onClick={() => { setMenuOpen(false); scrollToId('products'); }}>Products</button>
|
||||
@@ -119,6 +132,7 @@ const Header = ({ username, scrollToProduct, scrollToCourse, setShowedModal, han
|
||||
<button onClick={() => { setMenuOpen(false); scrollToId('faq'); }}>FAQ</button>
|
||||
<button className={styles.logoutButton} onClick={() => {
|
||||
navigate('/dashboard');
|
||||
setMenuOpen(false);
|
||||
}}>
|
||||
Dashboard
|
||||
</button>
|
||||
|
||||
@@ -198,18 +198,25 @@
|
||||
}
|
||||
|
||||
@media (max-width: 575.98px) {
|
||||
.hero { padding-top: 1.25rem; }
|
||||
.hero { padding-top: 1rem; }
|
||||
.ctaGroup { display: grid; gap: 8px; }
|
||||
.ctaPrimary, .ctaSecondary { width: 100% !important; text-align: center; }
|
||||
.copyWrap { max-width: 100%; padding: 0 10px; }
|
||||
.title { font-size: clamp(1.3rem, 2.5vw + 1rem, 1.8rem); }
|
||||
.lead { font-size: clamp(0.9rem, 0.5vw + 0.8rem, 1rem); }
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.imageWrap::before,
|
||||
.imageWrap::after { display: none; }
|
||||
.title { font-size: clamp(1.4rem, 1.8vw + 1rem, 2.1rem); line-height: 1.12; }
|
||||
.title { font-size: clamp(1.4rem, 2vw + 1rem, 2.1rem); line-height: 1.12; }
|
||||
.lead { font-size: clamp(0.93rem, 0.4vw + 0.84rem, 1.03rem); }
|
||||
.bulletItem { font-size: 0.92rem; }
|
||||
.mesh, .grid { display: none; }
|
||||
.copyWrap { max-width: 100%; padding: 0 15px; }
|
||||
.imageWrap { max-width: 100%; }
|
||||
.imageFrame { border-radius: calc(var(--radius-2xl) + 2px); }
|
||||
.heroImage { border-radius: calc(var(--radius-2xl) - 6px); }
|
||||
}
|
||||
|
||||
.imageFrame:hover { box-shadow: none; transform: none; }
|
||||
@@ -217,3 +224,15 @@
|
||||
@media (min-width: 1400px) {
|
||||
.imageWrap { max-width: 720px; }
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.hero { padding-top: 0.8rem; }
|
||||
.title { font-size: clamp(1.2rem, 3vw + 0.9rem, 1.7rem); }
|
||||
.lead { font-size: clamp(0.85rem, 0.5vw + 0.75rem, 0.95rem); }
|
||||
.ctaGroup { gap: 6px; }
|
||||
.ctaPrimary, .ctaSecondary {
|
||||
padding: 0.4rem 0.7rem !important;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.copyWrap { padding: 0 5px; }
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import styles from './ProductCard.module.css';
|
||||
|
||||
const ProductCard = ({ product, onCardClick, isCenter, canHover }) => {
|
||||
const ProductCard = ({ product, onCardClick, isCenter, canHover, onCollapse }) => {
|
||||
return (
|
||||
<div
|
||||
className={`${styles.card} ${isCenter ? styles.isCenter : ''} ${canHover ? styles.canHover : ''}`}
|
||||
@@ -16,10 +16,13 @@ const ProductCard = ({ product, onCardClick, isCenter, canHover }) => {
|
||||
<div
|
||||
className={styles.overlay}
|
||||
onClick={(e) => {
|
||||
if (isCenter) {
|
||||
// Clicks on overlay open detail; prevent parent selection
|
||||
e.stopPropagation();
|
||||
onCardClick && onCardClick(product);
|
||||
// Collapse overlay when clicking on the overlay background (not buttons)
|
||||
if (isCenter && canHover && onCollapse) {
|
||||
// Check if the click target is the overlay itself, not a button
|
||||
if (e.target === e.currentTarget) {
|
||||
e.stopPropagation();
|
||||
onCollapse();
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -132,7 +132,40 @@
|
||||
.description { -webkit-line-clamp: 2; }
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
@media (max-width: 768px) {
|
||||
.title { font-size: 0.9rem; }
|
||||
.overlay { --overlay-collapsed: 56px; }
|
||||
.overlay { --overlay-collapsed: 60px; }
|
||||
.description { font-size: 0.8rem; }
|
||||
.buttonGroup { gap: 6px; }
|
||||
.detailButton,
|
||||
.buyButton {
|
||||
padding: 5px 10px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.title { font-size: 0.85rem; }
|
||||
.overlay { --overlay-collapsed: 50px; }
|
||||
.overlayInner { padding: 10px 12px 12px; }
|
||||
.description { font-size: 0.75rem; margin: 6px 0 8px; }
|
||||
.buttonGroup { gap: 5px; }
|
||||
.detailButton,
|
||||
.buyButton {
|
||||
padding: 4px 8px;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.title { font-size: 0.8rem; }
|
||||
.overlay { --overlay-collapsed: 45px; }
|
||||
.overlayInner { padding: 8px 10px 10px; }
|
||||
.description { font-size: 0.7rem; margin: 4px 0 6px; }
|
||||
.buttonGroup { gap: 4px; }
|
||||
.detailButton,
|
||||
.buyButton {
|
||||
padding: 3px 6px;
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +152,11 @@
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.sectionHeader p {
|
||||
max-width: 100%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.filterWrapper {
|
||||
gap: 8px;
|
||||
}
|
||||
@@ -179,6 +184,11 @@
|
||||
|
||||
.sectionHeader {
|
||||
margin-bottom: 25px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: clamp(1.4rem, 4vw, 1.8rem);
|
||||
}
|
||||
|
||||
.sectionHeader p {
|
||||
@@ -187,6 +197,7 @@
|
||||
|
||||
.filterContainer {
|
||||
margin-bottom: 20px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.filterWrapper {
|
||||
@@ -216,14 +227,33 @@
|
||||
|
||||
.sectionHeader {
|
||||
margin-bottom: 20px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: clamp(1.3rem, 5vw, 1.7rem);
|
||||
}
|
||||
|
||||
.sectionHeader p {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.filterContainer {
|
||||
margin-bottom: 15px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.filterWrapper {
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.filterBtn {
|
||||
padding: 4px 8px;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.carouselContainer {
|
||||
padding: 0 35px;
|
||||
padding: 0 30px;
|
||||
min-height: 320px;
|
||||
}
|
||||
|
||||
@@ -234,8 +264,39 @@
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.productSection {
|
||||
padding: 25px 0;
|
||||
}
|
||||
|
||||
.sectionHeader {
|
||||
margin-bottom: 15px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: clamp(1.2rem, 6vw, 1.6rem);
|
||||
}
|
||||
|
||||
.sectionHeader p {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.filterContainer {
|
||||
margin-bottom: 12px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.filterWrapper {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.filterBtn {
|
||||
padding: 3px 6px;
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
|
||||
.carouselContainer {
|
||||
padding: 0 30px;
|
||||
padding: 0 25px;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
|
||||
@@ -661,16 +661,19 @@
|
||||
/* Responsive Styles */
|
||||
@media (max-width: 800px) {
|
||||
.modalBody {
|
||||
width: 80%;
|
||||
width: 85%;
|
||||
max-width: 90%;
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 14px 2rem;
|
||||
padding: 14px 1.5rem;
|
||||
}
|
||||
|
||||
.heroContainer {
|
||||
grid-template-columns: 1fr;
|
||||
text-align: center;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.ctaTitle,
|
||||
@@ -685,7 +688,7 @@
|
||||
|
||||
.ctaCard,
|
||||
.Section {
|
||||
padding: 2rem 0.8rem;
|
||||
padding: 2rem 1rem;
|
||||
background-color: #f8fafc;
|
||||
}
|
||||
|
||||
@@ -695,7 +698,7 @@
|
||||
|
||||
.ctaContainer,
|
||||
.coursesGrid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(173px, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
@@ -729,6 +732,7 @@
|
||||
display: none;
|
||||
font-size: 28px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mobileMenu {
|
||||
@@ -736,7 +740,7 @@
|
||||
}
|
||||
|
||||
/* Tampilkan burger dan menu di mobile */
|
||||
@media (max-width: 600px) {
|
||||
@media (max-width: 768px) {
|
||||
.nav {
|
||||
display: none;
|
||||
}
|
||||
@@ -757,11 +761,12 @@
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
z-index: 10;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.mobileMenu button {
|
||||
@@ -771,6 +776,8 @@
|
||||
color: white;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mobileMenu button:hover {
|
||||
@@ -782,6 +789,108 @@
|
||||
color: #2563eb;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.logoutButton {
|
||||
background-color: transparent;
|
||||
border: 1px solid #2563eb;
|
||||
color: #2563eb;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
font-size: 0.9rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.logoutButton:hover {
|
||||
background-color: #2563eb;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.header {
|
||||
padding: 12px 1rem;
|
||||
}
|
||||
|
||||
.Section {
|
||||
padding: 1.5rem 0.8rem;
|
||||
}
|
||||
|
||||
.coursesGrid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.ctaContainer {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.featuresList {
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.featureItem {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.featureIcon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.featureTitle {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.mobileMenu {
|
||||
right: 15px;
|
||||
top: 55px;
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.mobileMenu button {
|
||||
padding: 6px 12px;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.Section {
|
||||
padding: 1.2rem 0.6rem;
|
||||
}
|
||||
|
||||
.featureItem {
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.featureIcon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.featureTitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.featureDescription {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.mobileMenu {
|
||||
right: 10px;
|
||||
top: 50px;
|
||||
min-width: 130px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.mobileMenu button {
|
||||
padding: 5px 10px;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
.loggedInContainer {
|
||||
|
||||
Reference in New Issue
Block a user