Build SportsClubOS venue website
@@ -0,0 +1,3 @@
|
|||||||
|
tmp/
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="description" content="A new multi-sport destination for badminton, pickleball and tennis at Old Klang Road, Kuala Lumpur. Opening October 2027." />
|
||||||
|
<title>SportsClubOS | Old Klang Road Court Sports</title>
|
||||||
|
<link rel="stylesheet" href="styles.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="top" class="top-sentinel" aria-hidden="true"></div>
|
||||||
|
<div class="scroll-progress" aria-hidden="true"></div>
|
||||||
|
<div class="announcement">Opening October 2027 <span></span> Old Klang Road, Kuala Lumpur</div>
|
||||||
|
<header class="site-header">
|
||||||
|
<a class="brand" href="#top" aria-label="SportsClubOS home">SportsClub<span>OS</span></a>
|
||||||
|
<button class="menu-toggle" type="button" aria-label="Open menu" aria-expanded="false"><i></i><i></i></button>
|
||||||
|
<nav class="nav" aria-label="Main navigation">
|
||||||
|
<a href="#venue">Venue</a>
|
||||||
|
<a href="#courts">Courts</a>
|
||||||
|
<a href="#plans">Spaces</a>
|
||||||
|
<a href="#academy">Academy</a>
|
||||||
|
<a href="#community">Community</a>
|
||||||
|
<a href="#contact">Contact</a>
|
||||||
|
<button class="language language-toggle language-mobile" type="button" aria-label="切换为中文">中文</button>
|
||||||
|
</nav>
|
||||||
|
<div class="header-actions">
|
||||||
|
<button class="language language-toggle" type="button" aria-label="切换为中文">中文</button>
|
||||||
|
<a class="button button-small" href="#contact">Register interest</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-copy">
|
||||||
|
<p class="eyebrow">Kuala Lumpur's new court-sports destination</p>
|
||||||
|
<h1>Your court.<br><em>Your community.</em></h1>
|
||||||
|
<p class="hero-lede">A purpose-built home for badminton, pickleball and tennis - created for players, families, juniors and teams.</p>
|
||||||
|
<div class="hero-actions">
|
||||||
|
<a class="button" href="#contact">Register interest <b>→</b></a>
|
||||||
|
<a class="button button-outline" href="#academy">Explore academy</a>
|
||||||
|
</div>
|
||||||
|
<div class="hero-meta">
|
||||||
|
<span><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 21s7-6 7-12a7 7 0 1 0-14 0c0 6 7 12 7 12Zm0-9a3 3 0 1 1 0-6 3 3 0 0 1 0 6Z"/></svg>Old Klang Road, Kuala Lumpur</span>
|
||||||
|
<span><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 3v3M19 3v3M4 9h16M5 5h14a2 2 0 0 1 2 2v13H3V7a2 2 0 0 1 2-2Z"/></svg>Grand opening <strong>October 2027</strong></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hero-image">
|
||||||
|
<img src="public/assets/venue-hero.png" alt="Proposed multi-sport venue exterior at Old Klang Road" />
|
||||||
|
<div class="hero-stamp">Three sports<br><strong>One home</strong></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="court-counts" aria-label="Court capacity">
|
||||||
|
<div class="court-count"><span class="sport-mark badminton">◒</span><strong>14</strong><p>Indoor<br>badminton courts</p></div>
|
||||||
|
<div class="court-count"><span class="sport-mark pickleball">◇</span><strong>5</strong><p>Indoor<br>pickleball courts</p></div>
|
||||||
|
<div class="court-count"><span class="sport-mark tennis">◯</span><strong>4</strong><p>Indoor<br>tennis courts</p></div>
|
||||||
|
<p class="count-note">Professional spaces.<br>Designed for everyone.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section intro" id="venue">
|
||||||
|
<div class="section-heading reveal">
|
||||||
|
<p class="eyebrow">The venue</p>
|
||||||
|
<h2>Built around how<br>people <em>really play.</em></h2>
|
||||||
|
</div>
|
||||||
|
<div class="intro-copy reveal">
|
||||||
|
<p class="lead">A modern indoor sports centre planned for one of Kuala Lumpur's most established and connected neighbourhoods.</p>
|
||||||
|
<p>From casual evening games to focused academy training, every floor brings courts, support spaces and community amenities together in one accessible destination.</p>
|
||||||
|
</div>
|
||||||
|
<div class="venue-gallery reveal">
|
||||||
|
<button class="gallery-main gallery-item" type="button" data-image="public/assets/venue-entrance.png" aria-label="View venue entrance image">
|
||||||
|
<img src="public/assets/venue-entrance.png" alt="Proposed venue entrance" /><span>Entrance perspective</span>
|
||||||
|
</button>
|
||||||
|
<button class="gallery-item" type="button" data-image="public/assets/venue-front.png" aria-label="View venue front elevation image">
|
||||||
|
<img src="public/assets/venue-front.png" alt="Proposed front elevation" /><span>Front elevation</span>
|
||||||
|
</button>
|
||||||
|
<button class="gallery-item" type="button" data-image="public/assets/venue-street-b.png" aria-label="View street context image">
|
||||||
|
<img src="public/assets/venue-street-b.png" alt="Proposed venue in Old Klang Road street context" /><span>Street context</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="interior-intro reveal" id="inside">
|
||||||
|
<div><p class="eyebrow">Inside the venue</p><h3>Step inside the <em>game.</em></h3></div>
|
||||||
|
<p>Explore the indoor court environments referenced in the proposal - spaces planned for everyday play, coaching and competition.</p>
|
||||||
|
</div>
|
||||||
|
<div class="interior-gallery reveal">
|
||||||
|
<button class="gallery-item interior-item" type="button" data-image="public/assets/badminton-court.png" aria-label="View indoor badminton court image">
|
||||||
|
<img src="public/assets/badminton-court.png" alt="Indoor badminton courts shown in the proposal" /><span>Indoor badminton courts</span>
|
||||||
|
</button>
|
||||||
|
<button class="gallery-item interior-item" type="button" data-image="public/assets/pickleball-blue.png" aria-label="View pickleball court image">
|
||||||
|
<img src="public/assets/pickleball-blue.png" alt="Pickleball court shown in the proposal" /><span>Pickleball courts</span>
|
||||||
|
</button>
|
||||||
|
<button class="gallery-item interior-item" type="button" data-image="public/assets/tennis-indoor.png" aria-label="View indoor tennis court image">
|
||||||
|
<img src="public/assets/tennis-indoor.png" alt="Indoor tennis courts shown in the proposal" /><span>Indoor tennis courts</span>
|
||||||
|
</button>
|
||||||
|
<button class="gallery-item interior-item" type="button" data-image="public/assets/pickleball-court.png" aria-label="View multi-court interior image">
|
||||||
|
<img src="public/assets/pickleball-court.png" alt="Green indoor multi-court space shown in the proposal" /><span>Indoor multi-court space</span>
|
||||||
|
</button>
|
||||||
|
<button class="gallery-item interior-item" type="button" data-image="public/assets/tennis-court.png" aria-label="View outdoor tennis court image">
|
||||||
|
<img src="public/assets/tennis-court.png" alt="Outdoor tennis courts shown in the proposal" /><span>Outdoor tennis courts</span>
|
||||||
|
</button>
|
||||||
|
<button class="gallery-item interior-item" type="button" data-image="public/assets/pro-shop.png" aria-label="View badminton pro shop image">
|
||||||
|
<img src="public/assets/pro-shop.png" alt="Badminton equipment shop shown in the proposal" /><span>Badminton pro shop</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section courts" id="courts">
|
||||||
|
<div class="section-heading centered reveal">
|
||||||
|
<p class="eyebrow">Three ways to move</p>
|
||||||
|
<h2>Choose your <em>court.</em></h2>
|
||||||
|
<p>Dedicated indoor spaces planned for year-round play, training and competition.</p>
|
||||||
|
</div>
|
||||||
|
<div class="sport-grid">
|
||||||
|
<article class="sport-card reveal">
|
||||||
|
<div class="sport-image"><img src="public/assets/badminton-court.png" alt="Indoor badminton courts from the proposal" /><span>14 courts</span></div>
|
||||||
|
<div class="sport-content"><small>01 / Badminton</small><h3>Fast. Focused.<br>Made for Malaysia.</h3><p>Fourteen indoor courts form the heart of the venue, supporting everyday bookings, academy programmes and tournament play.</p><a href="#contact">Register for court updates →</a></div>
|
||||||
|
</article>
|
||||||
|
<article class="sport-card reveal">
|
||||||
|
<div class="sport-image"><img src="public/assets/pickleball-blue.png" alt="Pickleball court from the proposal" /><span>5 courts</span></div>
|
||||||
|
<div class="sport-content"><small>02 / Pickleball</small><h3>Social by nature.<br>Serious when you are.</h3><p>Five indoor pickleball courts - convertible for badminton - give new players and regular groups room to play their way.</p><a href="#contact">Join the community →</a></div>
|
||||||
|
</article>
|
||||||
|
<article class="sport-card reveal">
|
||||||
|
<div class="sport-image"><img src="public/assets/tennis-indoor.png" alt="Indoor tennis courts from the proposal" /><span>4 courts</span></div>
|
||||||
|
<div class="sport-content"><small>03 / Tennis</small><h3>More court time.<br>Whatever the weather.</h3><p>Four indoor tennis courts provide a dependable setting for lessons, friendly matches and performance sessions.</p><a href="#contact">Ask about tennis →</a></div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="amenities">
|
||||||
|
<div class="amenities-image reveal"><img src="public/assets/pro-shop.png" alt="Badminton equipment shop shown in the proposal" /></div>
|
||||||
|
<div class="amenities-content reveal">
|
||||||
|
<p class="eyebrow eyebrow-light">More than a court</p>
|
||||||
|
<h2>Everything your game needs, <em>under one roof.</em></h2>
|
||||||
|
<div class="amenity-list">
|
||||||
|
<span>Reception & waiting area</span><span>Badminton pro shop</span><span>Changing rooms</span><span>Fitness gym</span><span>Meeting room</span><span>Lounge & food bar</span><span>Court separation nets</span><span>Fire-safety access</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section plans" id="plans">
|
||||||
|
<div class="section-heading reveal">
|
||||||
|
<p class="eyebrow">Space planning</p>
|
||||||
|
<h2>A destination built<br><em>across every level.</em></h2>
|
||||||
|
</div>
|
||||||
|
<div class="plan-layout">
|
||||||
|
<div class="plan-tabs" role="tablist" aria-label="Venue levels">
|
||||||
|
<button class="plan-tab active" type="button" data-plan="public/assets/plan-ground.png" data-copy="Arrival, reception, waiting area, pro shop, changing rooms, badminton courts and tennis courts." role="tab" aria-selected="true"><strong>Ground</strong><span>Arrival & first courts</span></button>
|
||||||
|
<button class="plan-tab" type="button" data-plan="public/assets/plan-level-1.png" data-copy="Badminton and pickleball courts supported by changing rooms, meeting room, fitness gym, lounge and food bar." role="tab" aria-selected="false"><strong>Level 1</strong><span>Play, train & recharge</span></button>
|
||||||
|
<button class="plan-tab" type="button" data-plan="public/assets/plan-level-2.png" data-copy="Additional badminton, pickleball and tennis capacity with dedicated circulation and court separation." role="tab" aria-selected="false"><strong>Level 2</strong><span>Expanded court capacity</span></button>
|
||||||
|
<button class="plan-tab" type="button" data-plan="public/assets/plan-roof.png" data-copy="The upper-level court plan completes the building's multi-sport programme and maximises playable space." role="tab" aria-selected="false"><strong>Upper level</strong><span>The full venue programme</span></button>
|
||||||
|
</div>
|
||||||
|
<div class="plan-visual reveal"><img id="plan-image" src="public/assets/plan-ground.png" alt="Ground floor venue plan" /><p id="plan-copy">Arrival, reception, waiting area, pro shop, changing rooms, badminton courts and tennis courts.</p></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="booking-flow" id="booking">
|
||||||
|
<div class="booking-title reveal"><p class="eyebrow eyebrow-light">Simple court booking</p><h2>From “let's play”<br>to <em>court confirmed.</em></h2></div>
|
||||||
|
<ol class="steps reveal">
|
||||||
|
<li><b>01</b><span>Choose your sport</span></li><li><b>02</b><span>Select your area</span></li><li><b>03</b><span>Pick date & time</span></li><li><b>04</b><span>Confirm your court</span></li><li><b>05</b><span>Pay online</span></li>
|
||||||
|
</ol>
|
||||||
|
<p class="booking-note">The digital booking experience is planned to make court access easy, anytime and anywhere.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="academy" id="academy">
|
||||||
|
<div class="academy-copy reveal">
|
||||||
|
<p class="eyebrow">JUN Badminton Academy</p>
|
||||||
|
<h2>Skills for the court.<br><em>Character for life.</em></h2>
|
||||||
|
<p>Tailored programmes for ages 4 to 50, from beginners taking their first steps to advanced players preparing for competition.</p>
|
||||||
|
<div class="programmes"><span>Kids & adult group classes</span><span>Private one-to-one training</span><span>Singles & doubles programmes</span><span>Corporate & school training</span></div>
|
||||||
|
<button class="button contact-modal-trigger" type="button">Enquire about training →</button>
|
||||||
|
</div>
|
||||||
|
<div class="coach-card reveal">
|
||||||
|
<div class="coach-image"><img src="public/assets/coach-tan-hq.png" alt="Tan Wei Jun, Head Coach of JUN Badminton Academy" /></div>
|
||||||
|
<div class="coach-info"><small>Founder & head coach</small><h3>Tan Wei Jun</h3><p>Former Kedah state player<br>BAM Level 1-certified coach</p></div>
|
||||||
|
</div>
|
||||||
|
<div class="academy-philosophy reveal">
|
||||||
|
<span>Innovative drills</span><span>Fitness programmes</span><span>Mental conditioning</span><span>Local competitions</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section community" id="community">
|
||||||
|
<div class="section-heading centered reveal"><p class="eyebrow">A venue with a pulse</p><h2>Play here. <em>Belong here.</em></h2><p>The proposal is built around more than bookings: it imagines an active, connected local sports community.</p></div>
|
||||||
|
<div class="community-grid">
|
||||||
|
<article class="reveal"><b>01</b><h3>Community events</h3><p>Regular activities that bring neighbours, families and players together.</p></article>
|
||||||
|
<article class="reveal"><b>02</b><h3>Seasonal programmes</h3><p>Campaigns, clinics and formats that keep the calendar fresh year-round.</p></article>
|
||||||
|
<article class="reveal"><b>03</b><h3>Leagues & competition</h3><p>Pathways to play casually, test your level and compete with confidence.</p></article>
|
||||||
|
<article class="reveal"><b>04</b><h3>Business partnerships</h3><p>Space for corporate play, school programmes and local collaborations.</p></article>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="location" id="location">
|
||||||
|
<div class="location-image reveal"><img src="public/assets/venue-street-a.png" alt="Proposed venue in the Old Klang Road neighbourhood" /></div>
|
||||||
|
<div class="location-copy reveal">
|
||||||
|
<p class="eyebrow">Old Klang Road / 旧巴生路</p>
|
||||||
|
<h2>Connected to the city.<br><em>Rooted in the neighbourhood.</em></h2>
|
||||||
|
<p>One of Kuala Lumpur's oldest major corridors, Old Klang Road sits between the city and Petaling Jaya, surrounded by mature residential and commercial communities.</p>
|
||||||
|
<div class="nearby"><span>Taman Desa</span><span>OUG</span><span>Kuchai Lama</span><span>Taman Sri Sentosa</span></div>
|
||||||
|
<ul><li>Links to Federal Highway, NPE and LDP</li><li>A multicultural neighbourhood with a strong local food culture</li><li>Accessible to families, students, residents and corporate groups</li></ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section timeline">
|
||||||
|
<div class="section-heading reveal"><p class="eyebrow">Road to opening</p><h2>Building towards<br><em>October 2027.</em></h2></div>
|
||||||
|
<div class="timeline-track reveal">
|
||||||
|
<article><b>01</b><time>Aug 2025 - Jul 2026</time><h3>Planning permission</h3><p>Four-month planning-permission phase within the wider project programme.</p></article>
|
||||||
|
<article><b>02</b><time>Aug - Nov 2026</time><h3>Earthwork & building plans</h3><p>Approval work for earthworks and the building plan.</p></article>
|
||||||
|
<article><b>03</b><time>Dec 2026 - May 2027</time><h3>Construction</h3><p>Six months planned for venue construction.</p></article>
|
||||||
|
<article><b>04</b><time>Jun - Sep 2027</time><h3>Completion & handover</h3><p>CCC approval, completion and handover.</p></article>
|
||||||
|
<article class="timeline-finish"><b>05</b><time>October 2027</time><h3>Grand opening</h3><p>The first serves, rallies and community games begin.</p></article>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="contact" id="contact">
|
||||||
|
<div class="contact-copy reveal"><p class="eyebrow eyebrow-light">Get on court early</p><h2>Be the first to play.<br><em>Be part of the community.</em></h2><p>Register for opening updates, academy news and early booking information.</p></div>
|
||||||
|
<div class="contact-direct reveal">
|
||||||
|
<p>Choose the channel that works best for you. Every contact detail can be copied individually.</p>
|
||||||
|
<div><span>Training programmes</span><span>Court enquiries</span><span>Corporate & school sessions</span></div>
|
||||||
|
<button class="button button-light contact-modal-trigger" type="button">View contact details →</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div><a class="brand brand-footer" href="#top">SportsClub<span>OS</span></a><p>A new home for court sports at Old Klang Road, Kuala Lumpur.</p></div>
|
||||||
|
<div class="footer-contact">
|
||||||
|
<h4>JUN Academy</h4>
|
||||||
|
<a class="contact-row" href="tel:+60175407411">
|
||||||
|
<span class="contact-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6.6 10.8c1.8 3.5 3.2 4.9 6.7 6.7l2.2-2.2c.3-.3.7-.4 1.1-.2 1.2.4 2.5.7 3.9.7.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.8 21 3 13.2 3 3.5c0-.6.4-1 1-1h3.2c.6 0 1 .4 1 1 0 1.4.2 2.7.7 3.9.1.4 0 .8-.2 1.1l-2.1 2.3Z"/></svg></span>
|
||||||
|
<span>017-540 7411</span>
|
||||||
|
</a>
|
||||||
|
<a class="contact-row" href="mailto:admissions.junba@gmail.com">
|
||||||
|
<span class="contact-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 5h18v14H3V5Zm1.5 1.5L12 12l7.5-5.5M4.5 17.5l5.3-5M19.5 17.5l-5.3-5"/></svg></span>
|
||||||
|
<span>admissions.junba@gmail.com</span>
|
||||||
|
</a>
|
||||||
|
<a class="contact-row" href="https://www.instagram.com/jun_badmintonacademy/" target="_blank" rel="noreferrer">
|
||||||
|
<span class="contact-icon instagram-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="1" class="solid"/></svg></span>
|
||||||
|
<span>@jun_badmintonacademy</span>
|
||||||
|
</a>
|
||||||
|
<div class="contact-row">
|
||||||
|
<span class="contact-icon xhs-icon">小红书</span>
|
||||||
|
<span>JUN 羽球教练</span>
|
||||||
|
</div>
|
||||||
|
<div class="contact-row">
|
||||||
|
<span class="contact-icon facebook-icon">f</span>
|
||||||
|
<span>JUN Badminton Academy</span>
|
||||||
|
</div>
|
||||||
|
<div class="contact-row contact-address">
|
||||||
|
<span class="contact-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 21s7-6 7-12a7 7 0 1 0-14 0c0 6 7 12 7 12Z"/><circle cx="12" cy="9" r="2.5"/></svg></span>
|
||||||
|
<span>Ground Floor, Jalan Perdana 1,<br>Taman Segar Perdana, 43200 Cheras, Selangor</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div><h4>Explore</h4><a href="#venue">Venue</a><a href="#courts">Courts</a><a href="#academy">Academy</a><a href="#location">Location</a></div>
|
||||||
|
<p class="footer-note">Proposed venue information based on the current project proposal. Plans and opening schedule are subject to final approvals.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<dialog class="contact-modal" id="contact-modal" aria-label="Contact JUN Academy">
|
||||||
|
<button class="modal-close" type="button" aria-label="Close contact details">×</button>
|
||||||
|
<p class="eyebrow">Contact JUN Academy</p>
|
||||||
|
<p class="modal-intro">Copy any contact detail below, then reach out using the app you prefer.</p>
|
||||||
|
<div class="modal-contact-list">
|
||||||
|
<div class="modal-contact-row"><span class="modal-contact-icon">☎</span><div><small>Phone</small><strong class="contact-value">017-540 7411</strong></div><button class="copy-contact" type="button" data-copy="017-540 7411">Copy</button></div>
|
||||||
|
<div class="modal-contact-row"><span class="modal-contact-icon">@</span><div><small>Email</small><strong class="contact-value">admissions.junba@gmail.com</strong></div><button class="copy-contact" type="button" data-copy="admissions.junba@gmail.com">Copy</button></div>
|
||||||
|
<div class="modal-contact-row"><span class="modal-contact-icon instagram-icon">◎</span><div><small>Instagram</small><strong class="contact-value">@jun_badmintonacademy</strong></div><button class="copy-contact" type="button" data-copy="@jun_badmintonacademy">Copy</button></div>
|
||||||
|
<div class="modal-contact-row"><span class="modal-contact-icon xhs-icon">小红书</span><div><small>Xiaohongshu</small><strong class="contact-value">JUN 羽球教练</strong></div><button class="copy-contact" type="button" data-copy="JUN 羽球教练">Copy</button></div>
|
||||||
|
<div class="modal-contact-row"><span class="modal-contact-icon facebook-icon">f</span><div><small>Facebook</small><strong class="contact-value">JUN Badminton Academy</strong></div><button class="copy-contact" type="button" data-copy="JUN Badminton Academy">Copy</button></div>
|
||||||
|
<div class="modal-contact-row address-row"><span class="modal-contact-icon">⌖</span><div><small>Address</small><strong class="contact-value">Ground Floor, Jalan Perdana 1,<br>Taman Segar Perdana, 43200 Cheras, Selangor</strong></div><button class="copy-contact" type="button" data-copy="Ground Floor, Jalan Perdana 1, Taman Segar Perdana, 43200 Cheras, Selangor">Copy</button></div>
|
||||||
|
</div>
|
||||||
|
<p class="copy-status" role="status"></p>
|
||||||
|
</dialog>
|
||||||
|
<dialog class="lightbox" id="lightbox"><button type="button" aria-label="Close image">×</button><img src="public/assets/venue-entrance.png" alt="Expanded venue view" /></dialog>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 522 KiB |
|
After Width: | Height: | Size: 907 KiB |
|
After Width: | Height: | Size: 943 KiB |
|
After Width: | Height: | Size: 281 KiB |
|
After Width: | Height: | Size: 390 KiB |
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 439 KiB |
|
After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 469 KiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 3.4 MiB |
|
After Width: | Height: | Size: 3.2 MiB |
@@ -0,0 +1,265 @@
|
|||||||
|
const menuButton = document.querySelector('.menu-toggle');
|
||||||
|
const nav = document.querySelector('.nav');
|
||||||
|
const header = document.querySelector('.site-header');
|
||||||
|
const scrollProgress = document.querySelector('.scroll-progress');
|
||||||
|
|
||||||
|
const EN_TO_ZH = {
|
||||||
|
'Opening October 2027': '预计 2027 年 10 月开业',
|
||||||
|
'Old Klang Road, Kuala Lumpur': '吉隆坡旧巴生路',
|
||||||
|
'Venue': '场馆介绍', 'Courts': '球场', 'Spaces': '空间规划', 'Academy': '羽球学院', 'Community': '社区活动', 'Contact': '联系我们',
|
||||||
|
'Register interest': '登记意向', 'Register interest →': '发送邮件咨询 →',
|
||||||
|
"Kuala Lumpur's new court-sports destination": '吉隆坡全新综合球类运动目的地',
|
||||||
|
'Your court.': '你的球场。', 'Your community.': '你的社区。',
|
||||||
|
'A purpose-built home for badminton, pickleball and tennis - created for players, families, juniors and teams.': '为羽毛球、匹克球与网球量身打造,为球员、家庭、青少年和团队提供共同的运动主场。',
|
||||||
|
'Explore academy': '了解学院', 'Three sports': '三种运动', 'One home': '一个主场',
|
||||||
|
'Grand opening': '预计开业', 'October 2027': '2027 年 10 月',
|
||||||
|
'Indoor': '室内', 'badminton courts': '羽毛球场', 'pickleball courts': '匹克球场', 'tennis courts': '网球场',
|
||||||
|
'Professional spaces.': '专业运动空间。', 'Designed for everyone.': '为每一个人打造。',
|
||||||
|
'The venue': '场馆介绍', 'Built around how': '真正围绕', 'people': '人们的', 'really play.': '运动方式打造。',
|
||||||
|
"A modern indoor sports centre planned for one of Kuala Lumpur's most established and connected neighbourhoods.": '一座规划于吉隆坡成熟、交通便利社区中的现代室内体育中心。',
|
||||||
|
'From casual evening games to focused academy training, every floor brings courts, support spaces and community amenities together in one accessible destination.': '从轻松的晚间约球到系统的学院训练,每一层都把球场、辅助空间与社区配套集中在同一个便捷目的地。',
|
||||||
|
'Entrance perspective': '入口效果图', 'Front elevation': '建筑正立面', 'Street context': '街景效果图',
|
||||||
|
'Inside the venue': '走进场馆', 'Step inside the': '走进', 'game.': '运动现场。',
|
||||||
|
'Explore the indoor court environments referenced in the proposal - spaces planned for everyday play, coaching and competition.': '查看提案中的场内环境,为日常约球、专业训练和赛事活动规划的运动空间。',
|
||||||
|
'Indoor badminton courts': '室内羽毛球场', 'Pickleball courts': '匹克球场', 'Indoor tennis courts': '室内网球场', 'Indoor multi-court space': '室内多用途球场', 'Outdoor tennis courts': '室外网球场',
|
||||||
|
'Three ways to move': '三种运动方式', 'Choose your': '选择你的', 'court.': '球场。',
|
||||||
|
'Dedicated indoor spaces planned for year-round play, training and competition.': '为全年运动、训练和比赛规划的专业室内空间。',
|
||||||
|
'14 courts': '14 个球场', '5 courts': '5 个球场', '4 courts': '4 个球场',
|
||||||
|
'01 / Badminton': '01 / 羽毛球', '02 / Pickleball': '02 / 匹克球', '03 / Tennis': '03 / 网球',
|
||||||
|
'Fast. Focused.': '快速。专注。', 'Made for Malaysia.': '为马来西亚而生。',
|
||||||
|
'Fourteen indoor courts form the heart of the venue, supporting everyday bookings, academy programmes and tournament play.': '14 个室内羽毛球场构成场馆核心,满足日常预约、学院课程及赛事活动。',
|
||||||
|
'Register for court updates →': '登记球场资讯 →',
|
||||||
|
'Social by nature.': '天生适合社交。', 'Serious when you are.': '也能认真竞技。',
|
||||||
|
'Five indoor pickleball courts - convertible for badminton - give new players and regular groups room to play their way.': '5 个室内匹克球场可转换为羽毛球场,让新手与固定球友都能自在开打。',
|
||||||
|
'Join the community →': '加入社区 →',
|
||||||
|
'More court time.': '更多上场时间。', 'Whatever the weather.': '无惧天气变化。',
|
||||||
|
'Four indoor tennis courts provide a dependable setting for lessons, friendly matches and performance sessions.': '4 个室内网球场为课程、友谊赛和进阶训练提供稳定环境。',
|
||||||
|
'Ask about tennis →': '咨询网球场 →',
|
||||||
|
'More than a court': '不只是球场', 'Everything your game needs,': '运动所需的一切,', 'under one roof.': '都在同一屋檐下。',
|
||||||
|
'Reception & waiting area': '前台与等候区', 'Badminton pro shop': '羽毛球用品店', 'Changing rooms': '更衣室', 'Fitness gym': '健身房', 'Meeting room': '会议室', 'Lounge & food bar': '休息室与餐饮吧', 'Court separation nets': '球场隔离网', 'Fire-safety access': '消防通道',
|
||||||
|
'Space planning': '空间规划', 'A destination built': '逐层规划的', 'across every level.': '综合运动目的地。',
|
||||||
|
'Ground': '底层', 'Arrival & first courts': '接待与首层球场', 'Level 1': '一楼', 'Play, train & recharge': '运动、训练与休息', 'Level 2': '二楼', 'Expanded court capacity': '扩展球场容量', 'Upper level': '上层', 'The full venue programme': '完整场馆布局',
|
||||||
|
'Arrival, reception, waiting area, pro shop, changing rooms, badminton courts and tennis courts.': '设置场馆入口、前台、等候区、用品店、更衣室、羽毛球场与网球场。',
|
||||||
|
'Badminton and pickleball courts supported by changing rooms, meeting room, fitness gym, lounge and food bar.': '羽毛球与匹克球场配套更衣室、会议室、健身房、休息室与餐饮吧。',
|
||||||
|
'Additional badminton, pickleball and tennis capacity with dedicated circulation and court separation.': '增加羽毛球、匹克球与网球场地,并配置独立动线与球场隔离。',
|
||||||
|
"The upper-level court plan completes the building's multi-sport programme and maximises playable space.": '上层球场完善整栋建筑的综合运动布局,并最大化可运动空间。',
|
||||||
|
'Simple court booking': '轻松预约球场', 'From “let\'s play”': '从“约场球吧”', 'to': '到', 'court confirmed.': '确认球场。',
|
||||||
|
'Choose your sport': '选择运动项目', 'Select your area': '选择地区', 'Pick date & time': '选择日期与时间', 'Confirm your court': '确认时间与场地', 'Pay online': '线上付款',
|
||||||
|
'The digital booking experience is planned to make court access easy, anytime and anywhere.': '数字预约流程让用户随时随地轻松预订球场。',
|
||||||
|
'JUN Badminton Academy': 'JUN 羽毛球学院', 'Skills for the court.': '练就球场技能。', 'Character for life.': '塑造终身品格。',
|
||||||
|
'Tailored programmes for ages 4 to 50, from beginners taking their first steps to advanced players preparing for competition.': '为 4 至 50 岁不同水平的学员提供定制课程,从初学入门到进阶备赛。',
|
||||||
|
'Kids & adult group classes': '儿童与成人团体课程', 'Private one-to-one training': '私人一对一训练', 'Singles & doubles programmes': '单打与双打课程', 'Corporate & school training': '企业与学校训练',
|
||||||
|
'Enquire about training →': '咨询训练课程 →', 'Founder & head coach': '创办人兼主教练', 'Former Kedah state player': '前吉打州代表队球员', 'BAM Level 1-certified coach': '马来西亚羽总一级认证教练',
|
||||||
|
'Innovative drills': '创新训练', 'Fitness programmes': '体能课程', 'Mental conditioning': '心理训练', 'Local competitions': '本地赛事',
|
||||||
|
'A venue with a pulse': '充满活力的场馆', 'Play here.': '在这里运动。', 'Belong here.': '在这里找到归属。',
|
||||||
|
'The proposal is built around more than bookings: it imagines an active, connected local sports community.': '项目不只关注预约,更希望打造一个活跃、紧密连接的本地运动社区。',
|
||||||
|
'Community events': '社区活动', 'Regular activities that bring neighbours, families and players together.': '通过定期活动连接邻里、家庭和球友。',
|
||||||
|
'Seasonal programmes': '季节性活动', 'Campaigns, clinics and formats that keep the calendar fresh year-round.': '以主题推广、训练营和多种赛制丰富全年活动。',
|
||||||
|
'Leagues & competition': '联赛与竞技', 'Pathways to play casually, test your level and compete with confidence.': '从休闲约球、水平测试到正式竞技,提供清晰进阶路径。',
|
||||||
|
'Business partnerships': '商业合作', 'Space for corporate play, school programmes and local collaborations.': '承接企业活动、学校课程及本地合作项目。',
|
||||||
|
'Old Klang Road / 旧巴生路': '旧巴生路 / Old Klang Road', 'Connected to the city.': '连接城市。', 'Rooted in the neighbourhood.': '扎根社区。',
|
||||||
|
"One of Kuala Lumpur's oldest major corridors, Old Klang Road sits between the city and Petaling Jaya, surrounded by mature residential and commercial communities.": '旧巴生路是吉隆坡历史悠久的重要道路之一,连接市区与八打灵再也,周边拥有成熟住宅和商业社区。',
|
||||||
|
'Links to Federal Highway, NPE and LDP': '连接联邦大道、NPE 与 LDP', 'A multicultural neighbourhood with a strong local food culture': '多元族群共融,并拥有丰富本地美食文化', 'Accessible to families, students, residents and corporate groups': '方便家庭、学生、居民与企业团队到访',
|
||||||
|
'Road to opening': '开业进程', 'Building towards': '稳步迈向', 'Planning permission': '规划许可', 'Earthwork & building plans': '土方与建筑计划', 'Construction': '场馆施工', 'Completion & handover': '完工审批与交付', 'Grand opening': '正式开业',
|
||||||
|
'Four-month planning-permission phase within the wider project programme.': '项目规划中的四个月规划许可申请阶段。', 'Approval work for earthworks and the building plan.': '完成土方工程与建筑计划审批。', 'Six months planned for venue construction.': '预计用六个月完成场馆施工。', 'CCC approval, completion and handover.': '完成合规证书审批、完工与交付。', 'The first serves, rallies and community games begin.': '迎来首场发球、对打与社区活动。',
|
||||||
|
'Get on court early': '抢先上场', 'Be the first to play.': '成为首批球友。', 'Be part of the community.': '加入我们的社区。', 'Register for opening updates, academy news and early booking information.': '登记获取开业动态、学院资讯与优先预约信息。',
|
||||||
|
'Choose the channel that works best for you. Every contact detail can be copied individually.': '选择最方便的联系方式,每条信息都可以单独复制。', 'Training programmes': '训练课程', 'Court enquiries': '球场咨询', 'Corporate & school sessions': '企业与学校课程', 'View contact details →': '查看联系方式 →',
|
||||||
|
'Contact JUN Academy': '联系 JUN 学院', 'Choose a channel.': '选择联系方式。', 'Copy and connect.': '复制后自行联系。', 'Copy any contact detail below, then reach out using the app you prefer.': '单独复制下方任意联系信息,再使用你常用的应用与我们联系。',
|
||||||
|
'Phone': '电话', 'Email': '邮箱', 'Xiaohongshu': '小红书', 'Address': '地址', 'Copy': '复制',
|
||||||
|
'Your name': '姓名', 'Email address': '电子邮箱', "I'm interested in": '感兴趣的内容', 'Name': '姓名',
|
||||||
|
'Court bookings': '球场预约', 'JUN Badminton Academy': 'JUN 羽毛球学院', 'Corporate or school programmes': '企业或学校课程', 'Opening updates': '开业动态',
|
||||||
|
'A new home for court sports at Old Klang Road, Kuala Lumpur.': '位于吉隆坡旧巴生路的全新球类运动主场。', 'JUN Academy': 'JUN 学院', 'Explore': '网站导航', 'Location': '场馆位置',
|
||||||
|
'Ground Floor, Jalan Perdana 1,': '底层,Jalan Perdana 1,', 'Taman Segar Perdana, 43200 Cheras, Selangor': 'Taman Segar Perdana,43200 蕉赖,雪兰莪',
|
||||||
|
'Proposed venue information based on the current project proposal. Plans and opening schedule are subject to final approvals.': '场馆资料来自当前项目提案,具体规划与开业时间以最终审批为准。'
|
||||||
|
};
|
||||||
|
|
||||||
|
const ORIGINAL_TEXT = new WeakMap();
|
||||||
|
|
||||||
|
function translateTextNodes(isChinese) {
|
||||||
|
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
||||||
|
const nodes = [];
|
||||||
|
while (walker.nextNode()) nodes.push(walker.currentNode);
|
||||||
|
nodes.forEach((node) => {
|
||||||
|
if (['SCRIPT', 'STYLE'].includes(node.parentElement?.tagName)) return;
|
||||||
|
if (node.parentElement?.closest('.footer-contact') || node.parentElement?.closest('.contact-value')) return;
|
||||||
|
if (!isChinese) {
|
||||||
|
if (ORIGINAL_TEXT.has(node)) node.nodeValue = ORIGINAL_TEXT.get(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ORIGINAL_TEXT.has(node)) ORIGINAL_TEXT.set(node, node.nodeValue);
|
||||||
|
const original = ORIGINAL_TEXT.get(node);
|
||||||
|
const value = original.trim();
|
||||||
|
if (value && EN_TO_ZH[value]) node.nodeValue = original.replace(value, EN_TO_ZH[value]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLanguage(language) {
|
||||||
|
const isChinese = language === 'zh';
|
||||||
|
translateTextNodes(isChinese);
|
||||||
|
document.documentElement.lang = isChinese ? 'zh-CN' : 'en';
|
||||||
|
document.querySelectorAll('.language-toggle').forEach((button) => {
|
||||||
|
button.textContent = isChinese ? 'EN' : '中文';
|
||||||
|
button.setAttribute('aria-label', isChinese ? 'Switch to English' : '切换为中文');
|
||||||
|
});
|
||||||
|
const nameInput = document.querySelector('input[name="name"]');
|
||||||
|
if (nameInput) nameInput.placeholder = isChinese ? '姓名' : 'Name';
|
||||||
|
const activePlanCopy = document.querySelector('.plan-tab.active')?.dataset.copy;
|
||||||
|
const planDescription = document.querySelector('#plan-copy');
|
||||||
|
if (activePlanCopy && planDescription) planDescription.textContent = isChinese ? (EN_TO_ZH[activePlanCopy] || activePlanCopy) : activePlanCopy;
|
||||||
|
const formStatus = document.querySelector('.form-status');
|
||||||
|
if (formStatus) formStatus.textContent = '';
|
||||||
|
localStorage.setItem('site-language', language);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll('.language-toggle').forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
setLanguage(document.documentElement.lang.startsWith('zh') ? 'en' : 'zh');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setLanguage(localStorage.getItem('site-language') === 'zh' ? 'zh' : 'en');
|
||||||
|
|
||||||
|
menuButton?.addEventListener('click', () => {
|
||||||
|
const open = nav.classList.toggle('open');
|
||||||
|
menuButton.setAttribute('aria-expanded', String(open));
|
||||||
|
});
|
||||||
|
|
||||||
|
nav?.querySelectorAll('a').forEach((link) => {
|
||||||
|
link.addEventListener('click', () => {
|
||||||
|
nav.classList.remove('open');
|
||||||
|
menuButton?.setAttribute('aria-expanded', 'false');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let headerAnchor = header?.offsetTop ?? 0;
|
||||||
|
window.addEventListener('scroll', () => {
|
||||||
|
if (!header) return;
|
||||||
|
header.classList.toggle('is-sticky', window.scrollY > headerAnchor + 160);
|
||||||
|
document.body.style.paddingTop = header.classList.contains('is-sticky') ? `${header.offsetHeight}px` : '0';
|
||||||
|
const scrollable = document.documentElement.scrollHeight - window.innerHeight;
|
||||||
|
const progress = scrollable > 0 ? Math.min(1, Math.max(0, window.scrollY / scrollable)) : 0;
|
||||||
|
if (scrollProgress) scrollProgress.style.transform = `scaleX(${progress})`;
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
const planImage = document.querySelector('#plan-image');
|
||||||
|
const planCopy = document.querySelector('#plan-copy');
|
||||||
|
document.querySelectorAll('.plan-tab').forEach((tab) => {
|
||||||
|
tab.addEventListener('click', () => {
|
||||||
|
document.querySelectorAll('.plan-tab').forEach((item) => {
|
||||||
|
item.classList.remove('active');
|
||||||
|
item.setAttribute('aria-selected', 'false');
|
||||||
|
});
|
||||||
|
tab.classList.add('active');
|
||||||
|
tab.setAttribute('aria-selected', 'true');
|
||||||
|
planImage.style.opacity = '0';
|
||||||
|
setTimeout(() => {
|
||||||
|
planImage.src = tab.dataset.plan;
|
||||||
|
planImage.alt = `${tab.querySelector('strong').textContent} venue plan`;
|
||||||
|
const planText = tab.dataset.copy;
|
||||||
|
planCopy.textContent = document.documentElement.lang.startsWith('zh') ? (EN_TO_ZH[planText] || planText) : planText;
|
||||||
|
planImage.style.opacity = '1';
|
||||||
|
}, 160);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const lightbox = document.querySelector('#lightbox');
|
||||||
|
const lightboxImage = lightbox?.querySelector('img');
|
||||||
|
document.querySelectorAll('.gallery-item').forEach((item) => {
|
||||||
|
item.addEventListener('click', () => {
|
||||||
|
lightboxImage.src = item.dataset.image;
|
||||||
|
lightbox.showModal();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
lightbox?.querySelector('button').addEventListener('click', () => lightbox.close());
|
||||||
|
lightbox?.addEventListener('click', (event) => {
|
||||||
|
if (event.target === lightbox) lightbox.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
const revealObserver = new IntersectionObserver((entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
entry.target.classList.add('visible');
|
||||||
|
revealObserver.unobserve(entry.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, { threshold: 0.08, rootMargin: '0px 0px -30px' });
|
||||||
|
document.querySelectorAll('.reveal').forEach((element) => revealObserver.observe(element));
|
||||||
|
|
||||||
|
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||||
|
const countSection = document.querySelector('.court-counts');
|
||||||
|
const countNumbers = [...document.querySelectorAll('.court-count strong')];
|
||||||
|
if (countSection && !reducedMotion) {
|
||||||
|
const countObserver = new IntersectionObserver((entries) => {
|
||||||
|
if (!entries.some((entry) => entry.isIntersecting)) return;
|
||||||
|
countNumbers.forEach((number) => {
|
||||||
|
const target = Number(number.textContent);
|
||||||
|
const start = performance.now();
|
||||||
|
const duration = 850;
|
||||||
|
number.classList.add('counting');
|
||||||
|
const update = (now) => {
|
||||||
|
const elapsed = Math.min(1, (now - start) / duration);
|
||||||
|
const eased = 1 - Math.pow(1 - elapsed, 3);
|
||||||
|
number.textContent = String(Math.round(target * eased));
|
||||||
|
if (elapsed < 1) requestAnimationFrame(update);
|
||||||
|
else number.classList.remove('counting');
|
||||||
|
};
|
||||||
|
requestAnimationFrame(update);
|
||||||
|
});
|
||||||
|
countObserver.disconnect();
|
||||||
|
}, { threshold: .35 });
|
||||||
|
countObserver.observe(countSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contactModal = document.querySelector('#contact-modal');
|
||||||
|
const copyStatus = contactModal?.querySelector('.copy-status');
|
||||||
|
|
||||||
|
document.querySelectorAll('.contact-modal-trigger').forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
if (!contactModal?.open) contactModal.showModal();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
contactModal?.querySelector('.modal-close').addEventListener('click', () => contactModal.close());
|
||||||
|
contactModal?.addEventListener('click', (event) => {
|
||||||
|
if (event.target === contactModal) contactModal.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function copyContactText(text) {
|
||||||
|
if (navigator.clipboard?.writeText) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
return true;
|
||||||
|
} catch (_) {
|
||||||
|
// Fall through to the file:// compatible copy method.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const field = document.createElement('textarea');
|
||||||
|
field.value = text;
|
||||||
|
field.setAttribute('readonly', '');
|
||||||
|
field.style.position = 'fixed';
|
||||||
|
field.style.opacity = '0';
|
||||||
|
document.body.appendChild(field);
|
||||||
|
field.select();
|
||||||
|
const copied = document.execCommand('copy');
|
||||||
|
field.remove();
|
||||||
|
return copied;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll('.copy-contact').forEach((button) => {
|
||||||
|
button.addEventListener('click', async () => {
|
||||||
|
const copied = await copyContactText(button.dataset.copy);
|
||||||
|
const isChinese = document.documentElement.lang.startsWith('zh');
|
||||||
|
if (copyStatus) {
|
||||||
|
copyStatus.textContent = copied
|
||||||
|
? (isChinese ? `已复制:${button.dataset.copy}` : `Copied: ${button.dataset.copy}`)
|
||||||
|
: (isChinese ? '复制失败,请手动选择文字复制。' : 'Copy failed. Please select and copy the text manually.');
|
||||||
|
}
|
||||||
|
if (!copied) return;
|
||||||
|
button.textContent = isChinese ? '已复制' : 'Copied';
|
||||||
|
button.classList.add('copied');
|
||||||
|
setTimeout(() => {
|
||||||
|
button.textContent = isChinese ? '复制' : 'Copy';
|
||||||
|
button.classList.remove('copied');
|
||||||
|
}, 1600);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,363 @@
|
|||||||
|
:root {
|
||||||
|
--blue: #0b43bf;
|
||||||
|
--blue-dark: #072a82;
|
||||||
|
--orange: #f36c21;
|
||||||
|
--green: #3f8f43;
|
||||||
|
--ink: #101419;
|
||||||
|
--muted: #656b73;
|
||||||
|
--line: #dfe2e7;
|
||||||
|
--paper: #f7f8fa;
|
||||||
|
--display: Impact, Haettenschweiler, "Arial Narrow Bold", sans-serif;
|
||||||
|
--body: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
html { scroll-behavior: smooth; }
|
||||||
|
body { margin: 0; color: var(--ink); background: #fff; font-family: var(--body); font-size: 16px; line-height: 1.55; overflow-x: hidden; }
|
||||||
|
.scroll-progress { position: fixed; top: 0; left: 0; width: 100%; height: 3px; z-index: 100; background: var(--orange); transform: scaleX(0); transform-origin: left center; pointer-events: none; will-change: transform; }
|
||||||
|
img { width: 100%; display: block; }
|
||||||
|
a { color: inherit; text-decoration: none; }
|
||||||
|
button, input, select { font: inherit; }
|
||||||
|
button { color: inherit; }
|
||||||
|
|
||||||
|
.announcement { height: 31px; display: flex; align-items: center; justify-content: center; gap: 12px; background: var(--blue); color: #fff; text-transform: uppercase; letter-spacing: .18em; font-size: 10px; font-weight: 800; }
|
||||||
|
.announcement span { width: 3px; height: 3px; border-radius: 50%; background: var(--orange); }
|
||||||
|
.site-header { height: 78px; max-width: 1440px; margin: auto; padding: 0 4.5vw; display: flex; align-items: center; gap: 42px; background: #fff; position: relative; z-index: 20; }
|
||||||
|
.site-header.is-sticky { position: fixed; top: 0; left: 0; right: 0; max-width: none; box-shadow: 0 6px 30px rgb(0 0 0 / 8%); animation: drop .25s ease; }
|
||||||
|
@keyframes drop { from { transform: translateY(-100%); } }
|
||||||
|
.brand { font-size: clamp(20px, 2.1vw, 31px); font-weight: 900; letter-spacing: -.06em; color: var(--blue); white-space: nowrap; }
|
||||||
|
.brand span { color: var(--orange); }
|
||||||
|
.nav { display: flex; align-items: center; justify-content: center; gap: 32px; margin-left: auto; }
|
||||||
|
.nav a { position: relative; font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: .06em; }
|
||||||
|
.nav a::after { content: ""; position: absolute; left: 0; right: 100%; bottom: -8px; height: 2px; background: var(--orange); transition: .25s; }
|
||||||
|
.nav a:hover::after { right: 0; }
|
||||||
|
.header-actions { display: flex; align-items: center; gap: 18px; }
|
||||||
|
.language { padding: 0; border: 0; background: transparent; font-size: 12px; font-weight: 800; cursor: pointer; }
|
||||||
|
.language-mobile { display: none; }
|
||||||
|
.button { min-height: 48px; padding: 0 23px; display: inline-flex; align-items: center; justify-content: center; gap: 22px; border: 2px solid var(--blue); background: var(--blue); color: #fff; text-transform: uppercase; letter-spacing: .04em; font-size: 11px; font-weight: 900; cursor: pointer; transition: transform .2s, background .2s, color .2s; }
|
||||||
|
.button:hover { transform: translateY(-2px); background: var(--blue-dark); }
|
||||||
|
.button b { transition: transform .22s ease; }
|
||||||
|
.button:hover b { transform: translateX(4px); }
|
||||||
|
.button-small { min-height: 41px; padding: 0 18px; }
|
||||||
|
.button-outline { color: var(--blue); background: transparent; }
|
||||||
|
.button-outline:hover { color: #fff; }
|
||||||
|
.menu-toggle { display: none; border: 0; background: transparent; width: 38px; height: 38px; padding: 8px; }
|
||||||
|
.menu-toggle i { display: block; height: 2px; background: var(--ink); margin: 6px 0; }
|
||||||
|
|
||||||
|
.hero { min-height: 680px; display: grid; grid-template-columns: minmax(400px, .86fr) 1.45fr; background: linear-gradient(100deg, #fff 0%, #fff 42%, #edf4ff 42%, #edf4ff 100%); overflow: hidden; }
|
||||||
|
.hero-copy { padding: clamp(70px, 9vw, 132px) 1vw 70px max(5vw, calc((100vw - 1320px)/2)); position: relative; z-index: 2; }
|
||||||
|
.hero-copy > * { animation: hero-copy-in .7s both cubic-bezier(.22,.8,.32,1); }
|
||||||
|
.hero-copy > *:nth-child(2) { animation-delay: .08s; }
|
||||||
|
.hero-copy > *:nth-child(3) { animation-delay: .15s; }
|
||||||
|
.hero-copy > *:nth-child(4) { animation-delay: .22s; }
|
||||||
|
.hero-copy > *:nth-child(5) { animation-delay: .29s; }
|
||||||
|
@keyframes hero-copy-in { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
|
||||||
|
.eyebrow { margin: 0 0 16px; color: var(--blue); font-size: 11px; line-height: 1; text-transform: uppercase; letter-spacing: .16em; font-weight: 900; }
|
||||||
|
h1, h2 { margin: 0; font-family: var(--display); font-weight: 900; text-transform: uppercase; line-height: .96; letter-spacing: .005em; }
|
||||||
|
h1 { font-size: clamp(60px, 6.6vw, 104px); }
|
||||||
|
h1 em, h2 em { color: var(--blue); font-style: normal; }
|
||||||
|
.hero-lede { max-width: 480px; margin: 28px 0 30px; font-size: clamp(17px, 1.55vw, 21px); line-height: 1.5; }
|
||||||
|
.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; }
|
||||||
|
.hero-meta { display: grid; gap: 11px; margin-top: 38px; color: #353a42; font-size: 13px; }
|
||||||
|
.hero-meta span { display: flex; align-items: center; gap: 9px; }
|
||||||
|
.hero-meta svg { width: 18px; height: 18px; fill: none; stroke: var(--blue); stroke-width: 1.8; }
|
||||||
|
.hero-meta strong { color: var(--orange); }
|
||||||
|
.hero-image { position: relative; min-width: 0; }
|
||||||
|
.hero-image { animation: hero-image-in 1s both cubic-bezier(.2,.75,.25,1); transform-origin: right center; }
|
||||||
|
@keyframes hero-image-in { from { opacity: 0; transform: scale(1.035) translateX(24px); } to { opacity: 1; transform: none; } }
|
||||||
|
.hero-image::before { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, #edf4ff 0, transparent 22%); z-index: 1; pointer-events: none; }
|
||||||
|
.hero-image img { height: 100%; object-fit: cover; object-position: center; }
|
||||||
|
.hero-stamp { position: absolute; right: 5vw; bottom: 40px; z-index: 2; width: 122px; height: 122px; border-radius: 50%; display: grid; place-content: center; border: 1px solid #fff; background: rgb(11 67 191 / 88%); color: #fff; text-align: center; text-transform: uppercase; transform: rotate(-8deg); font-size: 10px; letter-spacing: .12em; }
|
||||||
|
.hero-stamp strong { font-family: var(--display); font-size: 22px; letter-spacing: .03em; }
|
||||||
|
|
||||||
|
.court-counts { max-width: 1180px; min-height: 155px; margin: 0 auto; display: grid; grid-template-columns: repeat(3, 1fr) .9fr; align-items: center; border-bottom: 1px solid var(--line); }
|
||||||
|
.court-count { height: 80px; padding: 0 34px; display: grid; grid-template-columns: auto auto 1fr; align-items: center; gap: 15px; border-right: 1px solid var(--line); }
|
||||||
|
.court-count strong { font-family: var(--display); color: var(--blue); font-size: 60px; line-height: 1; }
|
||||||
|
.court-count strong.counting { color: var(--orange); }
|
||||||
|
.court-count p { margin: 0; text-transform: uppercase; font-family: var(--display); font-size: 16px; line-height: 1.1; }
|
||||||
|
.sport-mark { width: 42px; height: 42px; display: grid; place-items: center; font-size: 35px; line-height: 1; }
|
||||||
|
.badminton { color: var(--blue); }.pickleball { color: var(--green); }.tennis { color: var(--orange); }
|
||||||
|
.count-note { padding-left: 34px; font-size: 13px; line-height: 1.5; color: var(--muted); }
|
||||||
|
|
||||||
|
.section { padding: 120px max(5vw, calc((100vw - 1320px)/2)); }
|
||||||
|
.section-heading { display: flex; justify-content: space-between; align-items: flex-end; gap: 30px; margin-bottom: 52px; }
|
||||||
|
.section-heading h2, .amenities h2, .booking-flow h2, .academy h2, .location h2, .contact h2 { font-size: clamp(48px, 5vw, 78px); }
|
||||||
|
.section-heading h2::after { content: ""; display: block; width: 54px; height: 4px; margin-top: 20px; background: var(--orange); transform: scaleX(0); transform-origin: left; transition: transform .7s .18s cubic-bezier(.2,.8,.3,1); }
|
||||||
|
.section-heading.centered h2::after { margin-inline: auto; transform-origin: center; }
|
||||||
|
.section-heading.visible h2::after { transform: scaleX(1); }
|
||||||
|
.section-heading.centered { display: block; max-width: 700px; margin: 0 auto 58px; text-align: center; }
|
||||||
|
.section-heading.centered > p:last-child { max-width: 580px; margin: 22px auto 0; color: var(--muted); }
|
||||||
|
.intro { display: grid; grid-template-columns: 1.1fr .8fr; gap: 20px 7vw; }
|
||||||
|
.intro .section-heading { margin: 0; display: block; }
|
||||||
|
.intro-copy { align-self: end; padding-bottom: 8px; color: var(--muted); }
|
||||||
|
.intro-copy .lead { color: var(--ink); font-size: 19px; font-weight: 650; }
|
||||||
|
.venue-gallery { grid-column: 1 / -1; display: grid; grid-template-columns: 1.55fr .8fr; grid-template-rows: repeat(2, 245px); gap: 12px; margin-top: 35px; }
|
||||||
|
.gallery-item { border: 0; margin: 0; padding: 0; position: relative; overflow: hidden; cursor: zoom-in; background: #eee; }
|
||||||
|
.gallery-main { grid-row: 1 / 3; }
|
||||||
|
.gallery-item img { width: 100%; height: 100%; object-fit: cover; transition: transform .55s ease; }
|
||||||
|
.gallery-item:hover img { transform: scale(1.035); }
|
||||||
|
.gallery-item::after { content: "↗"; position: absolute; right: 14px; top: 14px; width: 30px; height: 30px; display: grid; place-items: center; border-radius: 50%; color: #fff; background: rgb(11 67 191 / 86%); opacity: 0; transform: translateY(6px); transition: .25s; font-size: 12px; }
|
||||||
|
.gallery-item:hover::after { opacity: 1; transform: none; }
|
||||||
|
.gallery-item span { position: absolute; left: 16px; bottom: 14px; padding: 7px 10px; background: #fff; color: var(--ink); text-transform: uppercase; letter-spacing: .08em; font-size: 9px; font-weight: 900; }
|
||||||
|
.interior-intro { grid-column: 1 / -1; margin-top: 58px; display: grid; grid-template-columns: 1fr 1fr; gap: 6vw; align-items: end; }
|
||||||
|
.interior-intro .eyebrow { margin-bottom: 10px; }
|
||||||
|
.interior-intro h3 { margin: 0; font-family: var(--display); font-size: clamp(38px, 4vw, 60px); line-height: 1; text-transform: uppercase; }
|
||||||
|
.interior-intro h3 em { color: var(--blue); font-style: normal; }
|
||||||
|
.interior-intro > p { max-width: 560px; margin: 0; color: var(--muted); }
|
||||||
|
.interior-gallery { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 24px; }
|
||||||
|
.interior-item { height: 270px; }
|
||||||
|
|
||||||
|
.courts { background: var(--paper); }
|
||||||
|
.sport-grid { display: grid; gap: 34px; }
|
||||||
|
.sport-card { display: grid; grid-template-columns: 1.08fr 1fr; min-height: 410px; background: #fff; }
|
||||||
|
.sport-card:nth-child(even) .sport-image { order: 2; }
|
||||||
|
.sport-image { min-height: 390px; position: relative; overflow: hidden; }
|
||||||
|
.sport-image img { height: 100%; object-fit: cover; transition: transform .5s; }
|
||||||
|
.sport-card:hover .sport-image img { transform: scale(1.03); }
|
||||||
|
.sport-image span { position: absolute; top: 0; left: 0; padding: 14px 18px; background: var(--orange); color: #fff; font-size: 11px; font-weight: 900; text-transform: uppercase; }
|
||||||
|
.sport-content { padding: clamp(35px, 5vw, 70px); align-self: center; }
|
||||||
|
.sport-content small { color: var(--blue); font-size: 10px; font-weight: 900; text-transform: uppercase; letter-spacing: .14em; }
|
||||||
|
.sport-content h3 { margin: 12px 0 20px; font-family: var(--display); font-size: clamp(35px, 3.4vw, 54px); line-height: 1; text-transform: uppercase; }
|
||||||
|
.sport-content p { color: var(--muted); max-width: 500px; }
|
||||||
|
.sport-content a { display: inline-block; margin-top: 16px; color: var(--blue); text-transform: uppercase; letter-spacing: .06em; font-size: 11px; font-weight: 900; }
|
||||||
|
|
||||||
|
.amenities { display: grid; grid-template-columns: .85fr 1.15fr; background: var(--ink); color: #fff; }
|
||||||
|
.amenities-image { min-height: 610px; }
|
||||||
|
.amenities-image img { height: 100%; object-fit: cover; }
|
||||||
|
.amenities-content { padding: clamp(70px, 8vw, 130px); align-self: center; }
|
||||||
|
.eyebrow-light { color: #82a9ff; }
|
||||||
|
.amenities h2 em, .booking-flow h2 em, .contact h2 em { color: #fff; -webkit-text-stroke: 1px #fff; }
|
||||||
|
.amenity-list { margin-top: 44px; display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid rgb(255 255 255 / 20%); }
|
||||||
|
.amenity-list span { padding: 16px 0; border-bottom: 1px solid rgb(255 255 255 / 20%); font-size: 13px; }
|
||||||
|
.amenity-list span::before { content: "+"; color: var(--orange); margin-right: 10px; font-weight: 900; }
|
||||||
|
|
||||||
|
.plans { background: #fff; }
|
||||||
|
.plan-layout { display: grid; grid-template-columns: 330px 1fr; gap: 50px; align-items: start; }
|
||||||
|
.plan-tabs { border-top: 1px solid var(--line); }
|
||||||
|
.plan-tab { width: 100%; padding: 24px 10px; display: grid; grid-template-columns: 100px 1fr; text-align: left; border: 0; border-bottom: 1px solid var(--line); background: transparent; cursor: pointer; }
|
||||||
|
.plan-tab strong { font-family: var(--display); font-size: 25px; text-transform: uppercase; }
|
||||||
|
.plan-tab span { color: var(--muted); font-size: 12px; align-self: center; }
|
||||||
|
.plan-tab.active { padding-left: 18px; color: var(--blue); box-shadow: inset 4px 0 var(--orange); background: #f4f7ff; }
|
||||||
|
.plan-visual { min-width: 0; background: var(--paper); padding: 30px; }
|
||||||
|
.plan-visual img { height: min(52vw, 620px); object-fit: contain; mix-blend-mode: multiply; }
|
||||||
|
.plan-visual p { max-width: 680px; margin: 20px auto 0; padding-top: 16px; border-top: 1px solid var(--line); color: var(--muted); text-align: center; font-size: 13px; }
|
||||||
|
|
||||||
|
.booking-flow { padding: 100px max(5vw, calc((100vw - 1320px)/2)); color: #fff; background: var(--blue); position: relative; overflow: hidden; }
|
||||||
|
.booking-flow::after { content: ""; width: 350px; height: 620px; position: absolute; right: -140px; top: -220px; border: 1px solid rgb(255 255 255 / 20%); transform: rotate(36deg); }
|
||||||
|
.booking-title { display: flex; align-items: end; justify-content: space-between; }
|
||||||
|
.booking-title .eyebrow { align-self: start; }
|
||||||
|
.steps { list-style: none; padding: 0; margin: 65px 0 20px; display: grid; grid-template-columns: repeat(5, 1fr); counter-reset: step; }
|
||||||
|
.steps li { min-height: 120px; padding: 0 20px; display: flex; flex-direction: column; justify-content: space-between; border-left: 1px solid rgb(255 255 255 / 35%); }
|
||||||
|
.steps b { color: #7fa6ff; font-size: 11px; }
|
||||||
|
.steps span { font-family: var(--display); font-size: clamp(22px, 2.2vw, 34px); line-height: 1; text-transform: uppercase; }
|
||||||
|
.booking-note { max-width: 580px; margin: 28px 0 0; color: #d7e3ff; font-size: 13px; }
|
||||||
|
|
||||||
|
.academy { padding: 110px max(5vw, calc((100vw - 1320px)/2)) 0; display: grid; grid-template-columns: 1fr .78fr; background: linear-gradient(120deg, #fff 0, #fff 64%, #f0f5ff 64%); overflow: hidden; }
|
||||||
|
.academy-copy { padding: 20px 7vw 100px 0; }
|
||||||
|
.academy-copy > p:not(.eyebrow) { max-width: 600px; color: var(--muted); font-size: 17px; }
|
||||||
|
.programmes { display: grid; grid-template-columns: 1fr 1fr; gap: 0 24px; margin: 30px 0 36px; }
|
||||||
|
.programmes span { padding: 13px 0; border-bottom: 1px solid var(--line); font-size: 12px; font-weight: 750; }
|
||||||
|
.programmes span::before { content: "✓"; color: var(--orange); margin-right: 9px; }
|
||||||
|
.coach-card { align-self: end; position: relative; min-height: 610px; }
|
||||||
|
.coach-image { height: 610px; display: flex; align-items: flex-end; justify-content: center; background: radial-gradient(circle at 50% 45%, #e9f1ff, #cbdcff 68%, transparent 69%); }
|
||||||
|
.coach-image img { width: auto; max-width: 100%; height: 94%; object-fit: contain; object-position: bottom; filter: drop-shadow(0 20px 25px rgb(17 45 94 / 18%)); }
|
||||||
|
.coach-info { position: absolute; right: 0; bottom: 35px; padding: 20px 25px; min-width: 250px; background: var(--blue); color: #fff; }
|
||||||
|
.coach-info small { color: #a9c1ff; text-transform: uppercase; letter-spacing: .12em; font-size: 9px; font-weight: 900; }
|
||||||
|
.coach-info h3 { margin: 7px 0 3px; font-family: var(--display); font-size: 32px; text-transform: uppercase; }
|
||||||
|
.coach-info p { margin: 0; font-size: 11px; }
|
||||||
|
.academy-philosophy { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(4, 1fr); color: #fff; background: var(--ink); }
|
||||||
|
.academy-philosophy span { padding: 28px 25px; border-right: 1px solid #34373c; text-align: center; text-transform: uppercase; font-size: 11px; font-weight: 850; letter-spacing: .06em; }
|
||||||
|
|
||||||
|
.community { background: var(--paper); }
|
||||||
|
.community-grid { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid #cfd3da; border-left: 1px solid #cfd3da; }
|
||||||
|
.community-grid article { min-height: 290px; padding: 34px; border-right: 1px solid #cfd3da; border-bottom: 1px solid #cfd3da; background: #fff; transition: .25s; }
|
||||||
|
.community-grid article:hover { color: #fff; background: var(--blue); transform: translateY(-5px); }
|
||||||
|
.community-grid b { color: var(--orange); font-size: 11px; }
|
||||||
|
.community-grid h3 { margin: 70px 0 15px; font-family: var(--display); font-size: 30px; text-transform: uppercase; line-height: 1; }
|
||||||
|
.community-grid p { margin: 0; color: var(--muted); font-size: 13px; }
|
||||||
|
.community-grid article:hover p { color: #d9e3ff; }
|
||||||
|
|
||||||
|
.location { display: grid; grid-template-columns: 1.05fr .95fr; }
|
||||||
|
.location-image { min-height: 680px; }
|
||||||
|
.location-image img { height: 100%; object-fit: cover; }
|
||||||
|
.location-copy { padding: clamp(65px, 7vw, 115px); align-self: center; }
|
||||||
|
.location-copy > p:not(.eyebrow), .location-copy li { color: var(--muted); }
|
||||||
|
.nearby { margin: 30px 0; display: flex; flex-wrap: wrap; gap: 9px; }
|
||||||
|
.nearby span { padding: 8px 12px; border: 1px solid var(--blue); color: var(--blue); font-size: 10px; font-weight: 900; text-transform: uppercase; }
|
||||||
|
.location-copy ul { padding-left: 17px; }
|
||||||
|
.location-copy li { margin: 10px 0; }
|
||||||
|
|
||||||
|
.timeline { background: #fff; }
|
||||||
|
.timeline-track { display: grid; grid-template-columns: repeat(5, 1fr); position: relative; }
|
||||||
|
.timeline-track::before { content: ""; position: absolute; left: 0; right: 0; top: 22px; height: 2px; background: var(--line); }
|
||||||
|
.timeline-track article { padding: 70px 24px 25px 0; position: relative; }
|
||||||
|
.timeline-track article::before { content: ""; position: absolute; top: 14px; left: 0; width: 18px; height: 18px; border: 5px solid #fff; border-radius: 50%; background: var(--blue); box-shadow: 0 0 0 1px var(--blue); }
|
||||||
|
.timeline-track.visible article::before { animation: timeline-pulse .55s both; }
|
||||||
|
.timeline-track.visible article:nth-child(2)::before { animation-delay: .1s; }
|
||||||
|
.timeline-track.visible article:nth-child(3)::before { animation-delay: .2s; }
|
||||||
|
.timeline-track.visible article:nth-child(4)::before { animation-delay: .3s; }
|
||||||
|
.timeline-track.visible article:nth-child(5)::before { animation-delay: .4s; }
|
||||||
|
@keyframes timeline-pulse { 0% { transform: scale(.25); opacity: 0; } 65% { transform: scale(1.25); } 100% { transform: scale(1); opacity: 1; } }
|
||||||
|
.timeline-track b { color: #a1a6ae; font-size: 10px; }
|
||||||
|
.timeline-track time { display: block; margin: 10px 0 8px; color: var(--blue); font-size: 11px; font-weight: 900; text-transform: uppercase; }
|
||||||
|
.timeline-track h3 { margin: 0 0 12px; font-family: var(--display); font-size: 25px; line-height: 1; text-transform: uppercase; }
|
||||||
|
.timeline-track p { margin: 0; color: var(--muted); font-size: 12px; }
|
||||||
|
.timeline-track .timeline-finish::before { background: var(--orange); box-shadow: 0 0 0 1px var(--orange); }
|
||||||
|
.timeline-finish h3, .timeline-finish time { color: var(--orange); }
|
||||||
|
|
||||||
|
.contact { padding: 100px max(5vw, calc((100vw - 1320px)/2)); display: grid; grid-template-columns: 1.2fr 1fr; gap: 8vw; color: #fff; background: linear-gradient(125deg, var(--blue-dark), var(--blue)); }
|
||||||
|
.contact-copy p:last-child { max-width: 550px; color: #d7e4ff; }
|
||||||
|
.interest-form { display: grid; grid-template-columns: 1fr 1fr; gap: 17px; align-content: center; }
|
||||||
|
.interest-form label:nth-child(3) { grid-column: 1 / -1; }
|
||||||
|
.interest-form label span { display: block; margin-bottom: 6px; color: #b8ceff; font-size: 9px; font-weight: 900; text-transform: uppercase; letter-spacing: .12em; }
|
||||||
|
.interest-form input, .interest-form select { width: 100%; height: 49px; padding: 0 14px; border: 1px solid rgb(255 255 255 / 35%); border-radius: 0; color: #fff; background: rgb(0 0 0 / 15%); outline: none; }
|
||||||
|
.interest-form input:focus, .interest-form select:focus { border-color: #fff; }
|
||||||
|
.interest-form input::placeholder { color: #bdc9e5; }
|
||||||
|
.button-light { border-color: #fff; background: #fff; color: var(--blue); }
|
||||||
|
.button-light:hover { background: var(--orange); border-color: var(--orange); }
|
||||||
|
.form-status { margin: 0; align-self: center; color: #dbe6ff; font-size: 11px; }
|
||||||
|
.contact-direct { align-self: center; padding: 35px; border: 1px solid rgb(255 255 255 / 30%); background: rgb(0 0 0 / 12%); }
|
||||||
|
.contact-direct > p { margin: 0 0 22px; color: #d7e4ff; }
|
||||||
|
.contact-direct > div { display: flex; flex-wrap: wrap; gap: 9px; margin-bottom: 28px; }
|
||||||
|
.contact-direct > div span { padding: 7px 10px; border: 1px solid rgb(255 255 255 / 28%); color: #fff; text-transform: uppercase; font-size: 9px; font-weight: 850; letter-spacing: .05em; }
|
||||||
|
|
||||||
|
footer { padding: 70px max(5vw, calc((100vw - 1320px)/2)) 30px; display: grid; grid-template-columns: 1.6fr 1fr .7fr; gap: 60px; color: #d4d6d9; background: var(--ink); font-size: 12px; }
|
||||||
|
.brand-footer { color: #fff; }
|
||||||
|
footer h4 { margin: 0 0 16px; color: #fff; text-transform: uppercase; letter-spacing: .1em; font-size: 10px; }
|
||||||
|
footer a, footer span { display: block; margin: 8px 0; }
|
||||||
|
.footer-contact { min-width: 0; }
|
||||||
|
.footer-contact .contact-row { display: flex; align-items: center; gap: 11px; margin: 10px 0; color: #d4d6d9; line-height: 1.35; }
|
||||||
|
.footer-contact a.contact-row:hover { color: #fff; }
|
||||||
|
.footer-contact .contact-row > span { margin: 0; }
|
||||||
|
.footer-contact .contact-icon { width: 27px; height: 27px; flex: 0 0 27px; display: grid; place-items: center; border: 1px solid #454b53; border-radius: 50%; color: #fff; }
|
||||||
|
.contact-icon svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
||||||
|
.contact-icon svg .solid { fill: currentColor; stroke: none; }
|
||||||
|
.footer-contact .instagram-icon { color: #fff; background: linear-gradient(140deg, #7258d5, #db3d84 55%, #f39b3d); border-color: transparent; }
|
||||||
|
.footer-contact .xhs-icon { width: 31px; height: 31px; flex-basis: 31px; border: 0; border-radius: 8px; color: #fff; background: #ff2442; font-size: 7px; font-weight: 900; }
|
||||||
|
.footer-contact .facebook-icon { border: 0; border-radius: 5px; color: #fff; background: #4267b2; font-family: Arial, sans-serif; font-size: 22px; font-weight: 900; }
|
||||||
|
.footer-contact .contact-address { align-items: flex-start; margin-top: 14px; color: #9da2aa; font-size: 10px; }
|
||||||
|
.footer-contact .contact-address .contact-icon { margin-top: 1px; }
|
||||||
|
.footer-note { grid-column: 1 / -1; margin: 25px 0 0; padding-top: 24px; border-top: 1px solid #34383e; color: #777d85; font-size: 10px; }
|
||||||
|
|
||||||
|
.contact-modal { width: min(90vw, 540px); max-height: 78vh; padding: 24px 28px 20px; border: 0; border-radius: 16px; color: var(--ink); background: #fff; box-shadow: 0 24px 80px rgb(0 0 0 / 35%); overflow-y: auto; }
|
||||||
|
.contact-modal::backdrop { background: rgb(5 12 25 / 82%); backdrop-filter: blur(5px); }
|
||||||
|
.contact-modal .modal-close { position: absolute; right: 13px; top: 13px; width: 30px; height: 30px; border: 1px solid var(--line); border-radius: 50%; color: var(--ink); background: #fff; cursor: pointer; font-size: 18px; }
|
||||||
|
.contact-modal .eyebrow { margin-bottom: 7px; }
|
||||||
|
.contact-modal h2 { margin: 0; padding-right: 24px; font-size: clamp(32px, 3.2vw, 40px); line-height: .94; }
|
||||||
|
.contact-modal h2 em { color: var(--blue); font-style: normal; }
|
||||||
|
.modal-intro { max-width: 480px; margin: 9px 0 14px; color: var(--muted); font-size: 11px; }
|
||||||
|
.modal-contact-list { border-top: 1px solid var(--line); }
|
||||||
|
.modal-contact-row { min-height: 48px; display: grid; grid-template-columns: 29px minmax(0, 1fr) auto; align-items: center; gap: 9px; border-bottom: 1px solid var(--line); }
|
||||||
|
.modal-contact-row:last-child { border-bottom: 0; }
|
||||||
|
.modal-contact-icon { width: 24px; height: 24px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 50%; color: var(--blue); font-size: 10px; font-weight: 900; }
|
||||||
|
.modal-contact-icon.instagram-icon { color: #fff; border: 0; background: linear-gradient(140deg, #7258d5, #db3d84 55%, #f39b3d); }
|
||||||
|
.modal-contact-icon.xhs-icon { color: #fff; border: 0; border-radius: 7px; background: #ff2442; font-size: 7px; }
|
||||||
|
.modal-contact-icon.facebook-icon { color: #fff; border: 0; border-radius: 5px; background: #4267b2; font-family: Arial, sans-serif; font-size: 18px; }
|
||||||
|
.modal-contact-row small { display: block; color: var(--muted); text-transform: uppercase; letter-spacing: .09em; font-size: 8px; font-weight: 850; }
|
||||||
|
.modal-contact-row strong { display: block; margin-top: 1px; overflow-wrap: anywhere; font-size: 10.5px; }
|
||||||
|
.copy-contact { min-width: 54px; height: 27px; padding: 0 8px; border: 1px solid var(--blue); color: var(--blue); background: #fff; text-transform: uppercase; font-size: 8px; font-weight: 900; cursor: pointer; transition: .2s; }
|
||||||
|
.copy-contact:hover, .copy-contact.copied { color: #fff; background: var(--blue); }
|
||||||
|
.copy-status { min-height: 15px; margin: 10px 0 0; color: var(--blue); font-size: 10px; }
|
||||||
|
.lightbox { width: min(94vw, 1100px); padding: 0; border: 0; background: transparent; overflow: visible; }
|
||||||
|
.lightbox::backdrop { background: rgb(0 0 0 / 90%); }
|
||||||
|
.lightbox img { max-height: 84vh; object-fit: contain; }
|
||||||
|
.lightbox button { position: absolute; right: 0; top: -47px; width: 42px; height: 42px; border: 1px solid #fff; border-radius: 50%; color: #fff; background: transparent; font-size: 26px; cursor: pointer; }
|
||||||
|
.reveal { opacity: 0; transform: translateY(24px); transition: opacity .7s ease, transform .7s ease; }
|
||||||
|
.reveal.visible { opacity: 1; transform: none; }
|
||||||
|
|
||||||
|
@media (max-width: 1050px) {
|
||||||
|
.nav { gap: 17px; }
|
||||||
|
.nav a { font-size: 9px; }
|
||||||
|
.site-header { padding-inline: 3vw; gap: 20px; }
|
||||||
|
.court-counts { grid-template-columns: repeat(3, 1fr); }
|
||||||
|
.count-note { display: none; }
|
||||||
|
.court-count:last-of-type { border-right: 0; }
|
||||||
|
.community-grid { grid-template-columns: 1fr 1fr; }
|
||||||
|
.timeline-track { grid-template-columns: 1fr 1fr; gap: 0 30px; }
|
||||||
|
.timeline-track::before { display: none; }
|
||||||
|
.timeline-track article { padding-top: 45px; border-top: 1px solid var(--line); }
|
||||||
|
.timeline-track article::before { top: -9px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
.announcement { height: 28px; font-size: 8px; }
|
||||||
|
.site-header { height: 67px; padding: 0 20px; }
|
||||||
|
.menu-toggle { display: block; margin-left: auto; }
|
||||||
|
.header-actions { display: none; }
|
||||||
|
.nav { display: none; position: absolute; left: 0; top: 67px; width: 100%; padding: 25px 20px 30px; flex-direction: column; align-items: flex-start; gap: 18px; background: #fff; box-shadow: 0 16px 25px rgb(0 0 0 / 12%); }
|
||||||
|
.nav.open { display: flex; }
|
||||||
|
.nav a { font-size: 13px; }
|
||||||
|
.nav .language-mobile { display: block; color: var(--blue); font-size: 13px; }
|
||||||
|
.hero { min-height: 0; display: flex; flex-direction: column; background: #fff; }
|
||||||
|
.hero-copy { padding: 70px 22px 40px; }
|
||||||
|
.hero-lede { font-size: 16px; }
|
||||||
|
.hero-image { min-height: 420px; }
|
||||||
|
.hero-image::before { background: linear-gradient(180deg, #fff 0, transparent 20%); }
|
||||||
|
.hero-stamp { width: 92px; height: 92px; right: 18px; bottom: 18px; }
|
||||||
|
.court-counts { min-height: 0; grid-template-columns: 1fr; padding: 20px 22px; }
|
||||||
|
.court-count { height: 86px; padding: 0; border-right: 0; border-bottom: 1px solid var(--line); }
|
||||||
|
.section { padding: 80px 22px; }
|
||||||
|
.section-heading { display: block; }
|
||||||
|
.section-heading h2, .amenities h2, .booking-flow h2, .academy h2, .location h2, .contact h2 { font-size: 48px; }
|
||||||
|
.intro { grid-template-columns: 1fr; }
|
||||||
|
.venue-gallery { grid-template-columns: 1fr 1fr; grid-template-rows: 330px 180px; }
|
||||||
|
.gallery-main { grid-column: 1 / -1; grid-row: auto; }
|
||||||
|
.interior-intro { grid-template-columns: 1fr; gap: 18px; margin-top: 45px; }
|
||||||
|
.interior-gallery { grid-template-columns: 1fr; }
|
||||||
|
.interior-item { height: 260px; }
|
||||||
|
.sport-card { grid-template-columns: 1fr; }
|
||||||
|
.sport-card:nth-child(even) .sport-image { order: 0; }
|
||||||
|
.sport-content { padding: 38px 26px; }
|
||||||
|
.amenities, .location, .contact { grid-template-columns: 1fr; }
|
||||||
|
.amenities-image, .location-image { min-height: 420px; }
|
||||||
|
.amenities-content, .location-copy { padding: 70px 22px; }
|
||||||
|
.plan-layout { grid-template-columns: 1fr; gap: 25px; }
|
||||||
|
.plan-tabs { display: grid; grid-template-columns: 1fr 1fr; }
|
||||||
|
.plan-tab { grid-template-columns: 1fr; }
|
||||||
|
.plan-visual { padding: 12px; }
|
||||||
|
.plan-visual img { height: 65vw; }
|
||||||
|
.booking-flow { padding: 80px 22px; }
|
||||||
|
.booking-title { display: block; }
|
||||||
|
.steps { grid-template-columns: 1fr; margin-top: 40px; }
|
||||||
|
.steps li { min-height: 0; padding: 16px 0; flex-direction: row; border-left: 0; border-top: 1px solid rgb(255 255 255 / 30%); }
|
||||||
|
.steps span { font-size: 25px; }
|
||||||
|
.academy { padding: 80px 22px 0; grid-template-columns: 1fr; background: #fff; }
|
||||||
|
.academy-copy { padding: 0 0 65px; }
|
||||||
|
.coach-card { min-height: 520px; }
|
||||||
|
.coach-image { height: 520px; }
|
||||||
|
.academy-philosophy { margin-inline: -22px; grid-template-columns: 1fr 1fr; }
|
||||||
|
.community-grid { grid-template-columns: 1fr; }
|
||||||
|
.community-grid article { min-height: 220px; }
|
||||||
|
.community-grid h3 { margin-top: 35px; }
|
||||||
|
.timeline-track { grid-template-columns: 1fr; }
|
||||||
|
.timeline-track article { padding: 42px 0 35px; }
|
||||||
|
.contact { padding: 80px 22px; gap: 50px; }
|
||||||
|
.contact-direct { padding: 25px 20px; }
|
||||||
|
footer { grid-template-columns: 1fr 1fr; padding: 60px 22px 25px; gap: 40px; }
|
||||||
|
footer > div:first-child, .footer-note { grid-column: 1 / -1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
h1 { font-size: 56px; }
|
||||||
|
.hero-actions .button { width: 100%; }
|
||||||
|
.hero-image { min-height: 330px; }
|
||||||
|
.venue-gallery { display: block; }
|
||||||
|
.gallery-item { height: 240px; margin-bottom: 8px; width: 100%; }
|
||||||
|
.interior-gallery { display: block; }
|
||||||
|
.amenity-list, .programmes, .interest-form { grid-template-columns: 1fr; }
|
||||||
|
.interest-form label:nth-child(3) { grid-column: auto; }
|
||||||
|
.plan-tabs { grid-template-columns: 1fr; }
|
||||||
|
.academy-philosophy { grid-template-columns: 1fr; }
|
||||||
|
.academy-philosophy span { border-bottom: 1px solid #34373c; }
|
||||||
|
.contact-modal { width: min(92vw, 380px); max-height: 86vh; padding: 24px 16px 20px; }
|
||||||
|
.contact-modal h2 { padding-right: 28px; font-size: 34px; }
|
||||||
|
.modal-contact-row { grid-template-columns: 34px minmax(0, 1fr) auto; gap: 9px; }
|
||||||
|
.copy-contact { min-width: 56px; padding-inline: 8px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
html { scroll-behavior: auto; }
|
||||||
|
*, *::before, *::after { animation: none !important; transition: none !important; }
|
||||||
|
.reveal { opacity: 1; transform: none; }
|
||||||
|
.hero-copy > *, .hero-image { opacity: 1; transform: none; }
|
||||||
|
}
|
||||||