diff --git a/konesaliturku/.gitignore b/konesaliturku/.gitignore deleted file mode 100644 index dd50837..0000000 --- a/konesaliturku/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.DS_Store -*.swp -*.swo -.env diff --git a/konesaliturku/api.php b/konesaliturku/api.php deleted file mode 100644 index 6dba450..0000000 --- a/konesaliturku/api.php +++ /dev/null @@ -1,126 +0,0 @@ - $entries) { - $limits[$key] = array_filter($entries, fn($t) => $now - $t < $windowSeconds); - if (empty($limits[$key])) { - unset($limits[$key]); - } - } - - $count = count($limits[$ip] ?? []); - if ($count >= $maxRequests) { - return false; - } - - $limits[$ip][] = $now; - - $dir = dirname($file); - if (!is_dir($dir)) { - mkdir($dir, 0755, true); - } - file_put_contents($file, json_encode($limits)); - - return true; -} - -$action = $_GET['action'] ?? ''; - -switch ($action) { - case 'contact': - if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - http_response_code(405); - echo json_encode(['error' => 'Method not allowed']); - exit; - } - - // Honeypot - if (!empty($_POST['website'])) { - echo json_encode(['success' => true]); - exit; - } - - // Rate limit - $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; - if (!checkRateLimit($ip)) { - http_response_code(429); - echo json_encode(['error' => 'Liian monta viestiä. Yritä myöhemmin uudelleen.']); - exit; - } - - // Validate - $name = trim($_POST['name'] ?? ''); - $company = trim($_POST['company'] ?? ''); - $email = trim($_POST['email'] ?? ''); - $phone = trim($_POST['phone'] ?? ''); - $message = trim($_POST['message'] ?? ''); - - if (!$name || !$email || !$message) { - echo json_encode(['error' => 'Täytä kaikki pakolliset kentät.']); - exit; - } - - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - echo json_encode(['error' => 'Tarkista sähköpostiosoite.']); - exit; - } - - // Save to file - $contactFile = __DIR__ . '/data/contacts.json'; - $contacts = []; - if (file_exists($contactFile)) { - $contacts = json_decode(file_get_contents($contactFile), true) ?: []; - } - - $contacts[] = [ - 'id' => uniqid(), - 'name' => $name, - 'company' => $company, - 'email' => $email, - 'phone' => $phone, - 'message' => $message, - 'ip' => $ip, - 'created_at' => date('Y-m-d H:i:s') - ]; - - $dir = dirname($contactFile); - if (!is_dir($dir)) { - mkdir($dir, 0755, true); - } - file_put_contents($contactFile, json_encode($contacts, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); - - // Send email - $to = 'info@konesaliturku.fi'; - $subject = 'Yhteydenotto: ' . $name . ($company ? " ($company)" : ''); - $body = "Uusi yhteydenotto konesaliturku.fi:n kautta\n\n"; - $body .= "Nimi: $name\n"; - if ($company) $body .= "Yritys: $company\n"; - $body .= "Sähköposti: $email\n"; - if ($phone) $body .= "Puhelin: $phone\n"; - $body .= "\nViesti:\n$message\n"; - - $headers = "From: noreply@konesaliturku.fi\r\n"; - $headers .= "Reply-To: $email\r\n"; - $headers .= "Content-Type: text/plain; charset=UTF-8\r\n"; - - @mail($to, $subject, $body, $headers); - - echo json_encode(['success' => true]); - break; - - default: - http_response_code(404); - echo json_encode(['error' => 'Unknown action']); - break; -} diff --git a/konesaliturku/index.html b/konesaliturku/index.html deleted file mode 100644 index 44ece50..0000000 --- a/konesaliturku/index.html +++ /dev/null @@ -1,450 +0,0 @@ - - - - - - Konesali Turku — Colocation & konesalipalvelut Turussa - - - - - - - - -
-
-
-

Luotettavat konesalipalvelut Turussa

-

Colocation-laitepaikkoja ammattimaisessa laitetilassa. Redundantti sähkönsyöttö, nopeat tietoliikenneyhteydet ja henkilökohtainen palvelu.

- -
-
- 99,9% - Käytettävyys SLA -
-
- 24/7 - Valvonta -
-
- 10 Gbit/s - Yhteysnopeus -
-
-
-
-
- - -
-
-

Palvelut

-

Tarjoamme colocation-laitepaikkoja kaikenkokoisille tarpeille

-
-
-
- - - - - -
-

1U Laitepaikka

-

Yksittäinen palvelinpaikka 42U kaapissa. Sopii pienille palvelimille ja verkkolaitteille.

-
    -
  • 1 rack unit (1U)
  • -
  • Jaettu 1 Gbit/s yhteys
  • -
  • 1x 230V sähkösyöttö
  • -
  • Rajoittamaton liikenne
  • -
-
- -
-
- - - - - - - - -
-

Kokokaappi (42U)

-

Kokonainen 42U kaappi omassa lukitussa tilassa. Täysi hallinta ja maksimikapasiteetti.

-
    -
  • 42 rack unitia (42U)
  • -
  • Oma 10 Gbit/s yhteys
  • -
  • 2x 230V / 32A A/B-syöttö
  • -
  • Rajoittamaton liikenne
  • -
-
-
-
-
- - -
-
-

Miksi Konesali Turku?

-

Pienen konesalin edut isoihin ketjuihin verrattuna

-
-
-
- - - - -
-

Paikallinen palvelu

-

Laitteesi ovat lähellä. Voit käydä konesalilla milloin vain ja tapaat aina tutun henkilökunnan.

-
-
-
- - - -
-

Redundantti infrastruktuuri

-

Kahdennettu sähkönsyöttö, UPS-järjestelmä ja varavoimageneraattori takaavat katkeamattoman toiminnan.

-
-
-
- - - -
-

Nopeat yhteydet

-

Moniliittymäinen tietoliikenne usealta operaattorilta. 1–10 Gbit/s porttinopeudet.

-
-
-
- - - -
-

24/7 tuki

-

Remote hands -palvelu ja tekninen tuki ympäri vuorokauden. Ongelmatilanteissa reagoimme nopeasti.

-
-
-
- - - -
-

Turvallisuus

-

Kulunvalvonta, kameravalvonta ja lukitut kaapit. Laitteesi ovat turvassa ympäri vuorokauden.

-
-
-
- - - -
-

Selkeä hinnoittelu

-

Ei piilokustannuksia. Kuukausihintaan sisältyy laitepaikka, yhteys ja peruspalvelut.

-
-
-
-
- - -
-
-

Hinnat

-

Kaikki hinnat alv 0%. Sähkö laskutetaan erikseen kulutuksen mukaan.

-
-
-
-

1U Laitepaikka

-
- €49 - /kk -
-
-
    -
  • - - 1 rack unit (1U) -
  • -
  • - - Jaettu 1 Gbit/s -
  • -
  • - - 1x 230V sähkösyöttö -
  • -
  • - - Rajoittamaton liikenne -
  • -
  • - - 1x IPv4-osoite -
  • -
  • - - 99,9% SLA -
  • -
- Pyydä tarjous -
- -
-
-

Kokokaappi

-
- €490 - /kk -
-
-
    -
  • - - 42 rack unitia (42U) -
  • -
  • - - Oma 10 Gbit/s -
  • -
  • - - 2x 230V / 32A A/B-syöttö -
  • -
  • - - Rajoittamaton liikenne -
  • -
  • - - 8x IPv4-osoitetta -
  • -
  • - - IPv6 /48 -verkko -
  • -
  • - - Remote hands sisältyy -
  • -
  • - - 99,9% SLA -
  • -
- Pyydä tarjous -
-
-

Sähkönkulutus laskutetaan erikseen toteutuneen kulutuksen mukaan hintaan 0,25 €/kWh (alv 0%). Kaikki hinnat ovat kuukausihintoja, alv 0%. Sopimuksen minimikesto 1 kuukausi.

-
-
- - -
-
-

Ota yhteyttä

-

Kerro tarpeistasi, niin teemme sinulle tarjouksen

-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- - - -
-
-
-
- - - - -
- Osoite -

Esimerkkikatu 1
20100 Turku

-
-
-
- - - -
- Sähköposti -

info@konesaliturku.fi

-
-
-
- - - -
- Puhelin -

+358 2 123 4567

-
-
-
- - - -
- Aukioloajat -

Ma-Pe 8:00-17:00
Konesali 24/7

-
-
-
-
-
-
- - - - - - - diff --git a/konesaliturku/konesali.html b/konesaliturku/konesali.html deleted file mode 100644 index fd0f8a2..0000000 --- a/konesaliturku/konesali.html +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - Konesali — Tekniset tiedot | Konesali Turku - - - - - - - - -
-
-

Konesalin tekniset tiedot

-

Ammattimaisesti suunniteltu ja ylläpidetty laitetila Turussa

-
-
- - -
-
-
-
-
99,9%
-
Käytettävyys (SLA)
-
-
-
N+1
-
Redundanssi
-
-
-
24/7
-
Valvonta
-
-
-
10 Gbit/s
-
Yhteysnopeus
-
-
-
-
- - -
-
-
-
-
- - - -
-
-

Sähköjärjestelmät

-

Kahdennettu sähkönsyöttö varmistaa katkeamattoman toiminnan

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SähkönsyöttöKahdennettu A/B-syöttö kahdelta eri muuntajalta
UPS-järjestelmäOnline double-conversion UPS, N+1 redundantti
Akuston kapasiteettiVähintään 15 minuuttia täydellä kuormalla
VaravoimageneraattoriDieselgeneraattori, automaattinen käynnistys sähkökatkossa
Teho per kaappi2–8 kW (räätälöitävissä tarpeen mukaan)
Liitännät230V / 16A tai 32A, C13/C19 -pistokkeet
PDUMonitoroidut PDU:t (virrankulutuksen seuranta)
-
-
-
-
- - -
-
-
-
-
- - - -
-
-

Jäähdytys

-

Tehokas ja energiaoptimoitu jäähdytysjärjestelmä

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
JäähdytystyyppiPrecision air cooling, Cold Aisle Containment
RedundanssiN+1 jäähdytyskapasiteetti
LämpötilaTavoite 20–24 °C (ASHRAE A1 -suositus)
Ilmankosteus40–60% suhteellinen kosteus
ValvontaJatkuva lämpötila- ja kosteusseuranta, hälytykset
Free coolingUlkoilman hyödyntäminen Suomen ilmaston ansiosta
-
-
-
-
- - -
-
-
-
-
- - - -
-
-

Tietoliikenne

-

Moniliittymäinen verkko usealta operaattorilta

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Porttinopeudet1 Gbit/s – 10 Gbit/s (päivitettävissä 100 Gbit/s)
OperaattoritMoniliittymäinen (useampi operaattori redundanssia varten)
LiikenneRajoittamaton sisäänpäin/ulospäin
IPv41–8 osoitetta paketista riippuen (lisäosoitteet saatavilla)
IPv6/64 – /48 -verkot saatavilla
ReititysBGP-reititys, oma AS-numero saatavilla
Cross-connectSuorat yhteydet muihin operaattoreihin ja asiakkaisiin
SLA99,9% verkon käytettävyys
-
-
-
-
- - -
-
-
-
-
- - - -
-
-

Turvallisuus

-

Monikerroksiset turvallisuusjärjestelmät suojaavat laitteita

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
KulunvalvontaSähköinen kulunvalvonta, avainkortti + PIN-koodi
Kameravalvonta24/7 kameravalvonta sisä- ja ulkotiloissa, tallentava
PalontorjuntaAutomaattinen palonilmaisinjärjestelmä, inerttikaasu-sammutusjärjestelmä
Kaappien lukitusLukittavat 42U-kaapit, asiakaskohtaiset avaimet
HälytysjärjestelmäReaaliaikaiset hälytykset: lämpötila, kosteus, sähkö, murto
PääsylokiKaikki käynnit kirjataan ja aikaleimotaan
-
-
-
-
- - -
-
-
-
-
- - - -
-
-

Tilat ja kaapit

-

Ammattitason laitetila suunniteltu vaativaan käyttöön

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
SijaintiTurku, Suomi
KaapitStandardi 42U / 600mm x 1000mm serverikaapit
IlmavirtausHot Aisle / Cold Aisle -erottelu
Korotettu lattiaKorotettu lattia kaapelointia ja ilmavirtausta varten
KantavuusRiittävä raskaimmillekin palvelinratkaisuille
Pääsy24/7 pääsy konesalille etukäteisilmoituksella
-
-
-
-
- - -
-
-

Kiinnostuitko?

-

Kerro tarpeistasi ja teemme sinulle räätälöidyn tarjouksen

-
- Pyydä tarjous - Katso hinnat -
-
-
- - - - - - - diff --git a/konesaliturku/script.js b/konesaliturku/script.js deleted file mode 100644 index 2480463..0000000 --- a/konesaliturku/script.js +++ /dev/null @@ -1,126 +0,0 @@ -document.addEventListener('DOMContentLoaded', () => { - - // === Mobile nav toggle === - const navToggle = document.getElementById('nav-toggle'); - const nav = document.getElementById('nav'); - - if (navToggle && nav) { - navToggle.addEventListener('click', () => { - nav.classList.toggle('open'); - navToggle.classList.toggle('open'); - }); - - // Close nav on link click - nav.querySelectorAll('a').forEach(link => { - link.addEventListener('click', () => { - nav.classList.remove('open'); - navToggle.classList.remove('open'); - }); - }); - } - - // === Sticky header === - const header = document.getElementById('header'); - if (header) { - window.addEventListener('scroll', () => { - header.classList.toggle('scrolled', window.scrollY > 50); - }, { passive: true }); - } - - // === Scroll animations === - const observerOptions = { - threshold: 0.1, - rootMargin: '0px 0px -50px 0px' - }; - - const observer = new IntersectionObserver((entries) => { - entries.forEach(entry => { - if (entry.isIntersecting) { - entry.target.classList.add('visible'); - observer.unobserve(entry.target); - } - }); - }, observerOptions); - - // Add fade-in to sections - document.querySelectorAll('.service-card, .feature, .pricing-card, .contact-form, .contact-info').forEach(el => { - el.classList.add('fade-in'); - observer.observe(el); - }); - - // === Contact form === - const form = document.getElementById('contact-form'); - const formStatus = document.getElementById('form-status'); - - if (form) { - form.addEventListener('submit', async (e) => { - e.preventDefault(); - - const submitBtn = form.querySelector('.btn-submit'); - const originalText = submitBtn.textContent; - submitBtn.textContent = 'Lähetetään...'; - submitBtn.disabled = true; - - // Honeypot check - const honeypot = form.querySelector('input[name="website"]'); - if (honeypot && honeypot.value) { - formStatus.textContent = 'Kiitos viestistäsi!'; - formStatus.className = 'form-status success'; - form.reset(); - submitBtn.textContent = originalText; - submitBtn.disabled = false; - return; - } - - const formData = new FormData(form); - - try { - const response = await fetch('api.php?action=contact', { - method: 'POST', - body: formData - }); - - const data = await response.json(); - - if (data.success) { - formStatus.textContent = 'Kiitos viestistäsi! Otamme yhteyttä pian.'; - formStatus.className = 'form-status success'; - form.reset(); - } else { - formStatus.textContent = data.error || 'Viestin lähetys epäonnistui. Yritä uudelleen.'; - formStatus.className = 'form-status error'; - } - } catch { - formStatus.textContent = 'Viestin lähetys epäonnistui. Yritä uudelleen.'; - formStatus.className = 'form-status error'; - } - - submitBtn.textContent = originalText; - submitBtn.disabled = false; - }); - } - - // === Active nav link on scroll === - const sections = document.querySelectorAll('section[id]'); - const navLinks = document.querySelectorAll('.nav a[href^="#"]'); - - if (sections.length && navLinks.length) { - window.addEventListener('scroll', () => { - let current = ''; - sections.forEach(section => { - const top = section.offsetTop - 100; - if (window.scrollY >= top) { - current = section.getAttribute('id'); - } - }); - - navLinks.forEach(link => { - link.classList.remove('active'); - if (link.getAttribute('href') === '#' + current) { - link.classList.add('active'); - } - }); - }, { passive: true }); - } - -}); diff --git a/konesaliturku/server.py b/konesaliturku/server.py deleted file mode 100644 index 3f7f1a0..0000000 --- a/konesaliturku/server.py +++ /dev/null @@ -1,15 +0,0 @@ -import subprocess -import sys - -def main(): - try: - subprocess.run( - ["php", "-S", "localhost:3001"], - check=True - ) - except KeyboardInterrupt: - print("\nServer stopped.") - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/konesaliturku/style.css b/konesaliturku/style.css deleted file mode 100644 index 7f04cfb..0000000 --- a/konesaliturku/style.css +++ /dev/null @@ -1,970 +0,0 @@ -/* === Reset & Base === */ -*, *::before, *::after { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -:root { - --color-bg: #0a1628; - --color-bg-light: #0f1f3d; - --color-bg-card: #132244; - --color-primary: #1a73e8; - --color-primary-light: #4a9af5; - --color-primary-dark: #1557b0; - --color-accent: #00d4aa; - --color-text: #e2e8f0; - --color-text-muted: #94a3b8; - --color-text-heading: #f1f5f9; - --color-border: #1e3a5f; - --color-surface: #162a4a; - --color-white: #ffffff; - --font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif; - --max-width: 1200px; - --header-height: 72px; - --radius: 12px; - --radius-sm: 8px; - --shadow: 0 4px 24px rgba(0, 0, 0, 0.3); - --shadow-lg: 0 8px 48px rgba(0, 0, 0, 0.4); - --transition: 0.3s ease; -} - -html { - scroll-behavior: smooth; - scroll-padding-top: var(--header-height); -} - -body { - font-family: var(--font-family); - background: var(--color-bg); - color: var(--color-text); - line-height: 1.6; - -webkit-font-smoothing: antialiased; -} - -a { - color: var(--color-primary-light); - text-decoration: none; - transition: color var(--transition); -} - -a:hover { - color: var(--color-accent); -} - -.container { - max-width: var(--max-width); - margin: 0 auto; - padding: 0 24px; -} - -/* === Header === */ -.header { - position: fixed; - top: 0; - left: 0; - right: 0; - height: var(--header-height); - background: rgba(10, 22, 40, 0.9); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-bottom: 1px solid var(--color-border); - z-index: 1000; - transition: background var(--transition); -} - -.header.scrolled { - background: rgba(10, 22, 40, 0.98); - box-shadow: 0 2px 20px rgba(0, 0, 0, 0.3); -} - -.header-inner { - display: flex; - align-items: center; - justify-content: space-between; - height: 100%; -} - -.logo { - display: flex; - align-items: center; - gap: 10px; - color: var(--color-white); - font-size: 1.25rem; - font-weight: 400; - letter-spacing: -0.01em; -} - -.logo:hover { - color: var(--color-white); -} - -.logo strong { - font-weight: 700; -} - -.logo-icon { - color: var(--color-primary-light); -} - -.nav { - display: flex; - gap: 32px; -} - -.nav a { - color: var(--color-text-muted); - font-size: 0.95rem; - font-weight: 500; - transition: color var(--transition); - position: relative; -} - -.nav a:hover, -.nav a.active { - color: var(--color-white); -} - -.nav a::after { - content: ''; - position: absolute; - bottom: -4px; - left: 0; - width: 0; - height: 2px; - background: var(--color-primary); - transition: width var(--transition); -} - -.nav a:hover::after { - width: 100%; -} - -.nav-toggle { - display: none; - flex-direction: column; - gap: 5px; - background: none; - border: none; - cursor: pointer; - padding: 8px; -} - -.nav-toggle span { - display: block; - width: 24px; - height: 2px; - background: var(--color-white); - transition: all var(--transition); -} - -/* === Hero === */ -.hero { - padding: 160px 0 100px; - background: linear-gradient(135deg, var(--color-bg) 0%, var(--color-bg-light) 50%, var(--color-bg) 100%); - position: relative; - overflow: hidden; -} - -.hero::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: - radial-gradient(ellipse 800px 600px at 20% 50%, rgba(26, 115, 232, 0.08) 0%, transparent 70%), - radial-gradient(ellipse 600px 400px at 80% 30%, rgba(0, 212, 170, 0.05) 0%, transparent 70%); - pointer-events: none; -} - -.hero-content { - position: relative; - max-width: 720px; -} - -.hero h1 { - font-size: clamp(2.2rem, 5vw, 3.5rem); - font-weight: 800; - line-height: 1.15; - color: var(--color-white); - margin-bottom: 20px; - letter-spacing: -0.02em; -} - -.highlight { - color: var(--color-primary-light); -} - -.hero-subtitle { - font-size: 1.2rem; - color: var(--color-text-muted); - line-height: 1.7; - margin-bottom: 36px; - max-width: 560px; -} - -.hero-actions { - display: flex; - gap: 16px; - margin-bottom: 56px; -} - -.hero-stats { - display: flex; - gap: 48px; -} - -.stat { - display: flex; - flex-direction: column; -} - -.stat-value { - font-size: 1.5rem; - font-weight: 800; - color: var(--color-white); -} - -.stat-label { - font-size: 0.85rem; - color: var(--color-text-muted); - margin-top: 4px; -} - -/* === Buttons === */ -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 14px 28px; - border-radius: var(--radius-sm); - font-size: 1rem; - font-weight: 600; - border: none; - cursor: pointer; - transition: all var(--transition); - text-decoration: none; -} - -.btn-primary { - background: var(--color-primary); - color: var(--color-white); -} - -.btn-primary:hover { - background: var(--color-primary-dark); - color: var(--color-white); - transform: translateY(-2px); - box-shadow: 0 4px 20px rgba(26, 115, 232, 0.4); -} - -.btn-secondary { - background: var(--color-surface); - color: var(--color-text); - border: 1px solid var(--color-border); -} - -.btn-secondary:hover { - background: var(--color-bg-card); - color: var(--color-white); - border-color: var(--color-primary); -} - -.btn-outline { - background: transparent; - color: var(--color-primary-light); - border: 2px solid var(--color-primary); -} - -.btn-outline:hover { - background: var(--color-primary); - color: var(--color-white); - transform: translateY(-2px); -} - -/* === Sections === */ -.section { - padding: 100px 0; -} - -.section-dark { - background: var(--color-bg-light); -} - -.section-title { - font-size: 2.2rem; - font-weight: 800; - color: var(--color-text-heading); - text-align: center; - margin-bottom: 12px; - letter-spacing: -0.02em; -} - -.section-subtitle { - font-size: 1.1rem; - color: var(--color-text-muted); - text-align: center; - margin-bottom: 56px; - max-width: 600px; - margin-left: auto; - margin-right: auto; -} - -/* === Services === */ -.services-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 24px; -} - -.service-card { - background: var(--color-bg-card); - border: 1px solid var(--color-border); - border-radius: var(--radius); - padding: 36px 28px; - transition: all var(--transition); - position: relative; -} - -.service-card:hover { - transform: translateY(-4px); - box-shadow: var(--shadow-lg); - border-color: var(--color-primary); -} - -.service-card.featured { - border-color: var(--color-primary); - background: linear-gradient(180deg, rgba(26, 115, 232, 0.08) 0%, var(--color-bg-card) 100%); -} - -.service-badge { - position: absolute; - top: -12px; - right: 20px; - background: var(--color-primary); - color: var(--color-white); - font-size: 0.8rem; - font-weight: 700; - padding: 4px 14px; - border-radius: 20px; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.service-icon { - color: var(--color-primary-light); - margin-bottom: 20px; -} - -.service-card h3 { - font-size: 1.35rem; - font-weight: 700; - color: var(--color-text-heading); - margin-bottom: 12px; -} - -.service-card p { - color: var(--color-text-muted); - margin-bottom: 20px; - font-size: 0.95rem; -} - -.service-features { - list-style: none; -} - -.service-features li { - padding: 6px 0; - color: var(--color-text); - font-size: 0.9rem; - border-bottom: 1px solid rgba(30, 58, 95, 0.5); -} - -.service-features li:last-child { - border-bottom: none; -} - -/* === Features (Miksi me) === */ -.features-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 32px; -} - -.feature { - text-align: center; - padding: 24px; -} - -.feature-icon { - color: var(--color-primary-light); - margin-bottom: 16px; - display: flex; - justify-content: center; -} - -.feature h3 { - font-size: 1.15rem; - font-weight: 700; - color: var(--color-text-heading); - margin-bottom: 10px; -} - -.feature p { - color: var(--color-text-muted); - font-size: 0.95rem; - line-height: 1.6; -} - -/* === Pricing === */ -.pricing-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 24px; - align-items: start; -} - -.pricing-card { - background: var(--color-bg-card); - border: 1px solid var(--color-border); - border-radius: var(--radius); - padding: 36px 28px; - text-align: center; - transition: all var(--transition); - position: relative; -} - -.pricing-card:hover { - transform: translateY(-4px); - box-shadow: var(--shadow-lg); -} - -.pricing-featured { - border-color: var(--color-primary); - background: linear-gradient(180deg, rgba(26, 115, 232, 0.1) 0%, var(--color-bg-card) 100%); - transform: scale(1.04); -} - -.pricing-featured:hover { - transform: scale(1.04) translateY(-4px); -} - -.pricing-badge { - position: absolute; - top: -12px; - left: 50%; - transform: translateX(-50%); - background: var(--color-primary); - color: var(--color-white); - font-size: 0.8rem; - font-weight: 700; - padding: 4px 18px; - border-radius: 20px; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.pricing-header h3 { - font-size: 1.3rem; - font-weight: 700; - color: var(--color-text-heading); - margin-bottom: 16px; -} - -.price { - margin-bottom: 28px; -} - -.price-amount { - font-size: 3rem; - font-weight: 800; - color: var(--color-white); - line-height: 1; -} - -.price-period { - font-size: 1.1rem; - color: var(--color-text-muted); - font-weight: 400; -} - -.pricing-features { - list-style: none; - text-align: left; - margin-bottom: 28px; -} - -.pricing-features li { - display: flex; - align-items: center; - gap: 10px; - padding: 8px 0; - font-size: 0.95rem; - color: var(--color-text); - border-bottom: 1px solid rgba(30, 58, 95, 0.4); -} - -.pricing-features li:last-child { - border-bottom: none; -} - -.pricing-features svg { - color: var(--color-accent); - flex-shrink: 0; -} - -.pricing-note { - text-align: center; - color: var(--color-text-muted); - font-size: 0.9rem; - margin-top: 40px; - max-width: 700px; - margin-left: auto; - margin-right: auto; -} - -/* === Contact === */ -.contact-grid { - display: grid; - grid-template-columns: 1.2fr 0.8fr; - gap: 48px; - align-items: start; -} - -.contact-form { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 20px; -} - -.form-group { - display: flex; - flex-direction: column; -} - -.form-group-full { - grid-column: 1 / -1; -} - -.form-group label { - font-size: 0.9rem; - font-weight: 600; - color: var(--color-text); - margin-bottom: 6px; -} - -.form-group input, -.form-group textarea { - background: var(--color-bg-card); - border: 1px solid var(--color-border); - border-radius: var(--radius-sm); - padding: 12px 16px; - color: var(--color-text); - font-family: inherit; - font-size: 1rem; - transition: border-color var(--transition); -} - -.form-group input:focus, -.form-group textarea:focus { - outline: none; - border-color: var(--color-primary); - box-shadow: 0 0 0 3px rgba(26, 115, 232, 0.15); -} - -.form-group textarea { - resize: vertical; - min-height: 120px; -} - -.btn-submit { - grid-column: 1 / -1; - margin-top: 4px; -} - -.form-status { - grid-column: 1 / -1; - font-size: 0.95rem; - padding: 8px 0; -} - -.form-status.success { - color: var(--color-accent); -} - -.form-status.error { - color: #f87171; -} - -.contact-info { - display: flex; - flex-direction: column; - gap: 28px; -} - -.contact-item { - display: flex; - gap: 16px; - align-items: flex-start; -} - -.contact-item svg { - color: var(--color-primary-light); - flex-shrink: 0; - margin-top: 2px; -} - -.contact-item strong { - display: block; - color: var(--color-text-heading); - font-size: 0.95rem; - margin-bottom: 4px; -} - -.contact-item p { - color: var(--color-text-muted); - font-size: 0.9rem; - line-height: 1.5; -} - -/* === Footer === */ -.footer { - background: var(--color-bg); - border-top: 1px solid var(--color-border); - padding-top: 56px; -} - -.footer-inner { - display: grid; - grid-template-columns: 2fr 1fr 1fr; - gap: 48px; - padding-bottom: 40px; -} - -.footer-brand .logo { - margin-bottom: 12px; -} - -.footer-brand p { - color: var(--color-text-muted); - font-size: 0.95rem; -} - -.footer-links h4 { - color: var(--color-text-heading); - font-size: 0.95rem; - font-weight: 700; - margin-bottom: 16px; -} - -.footer-links a { - display: block; - color: var(--color-text-muted); - font-size: 0.9rem; - padding: 4px 0; -} - -.footer-links a:hover { - color: var(--color-primary-light); -} - -.footer-bottom { - border-top: 1px solid var(--color-border); - padding: 20px 0; -} - -.footer-bottom p { - color: var(--color-text-muted); - font-size: 0.85rem; - text-align: center; -} - -/* === Konesali Page === */ -.page-hero { - padding: 140px 0 60px; - background: linear-gradient(135deg, var(--color-bg) 0%, var(--color-bg-light) 100%); - text-align: center; -} - -.page-hero h1 { - font-size: clamp(1.8rem, 4vw, 2.8rem); - font-weight: 800; - color: var(--color-white); - margin-bottom: 12px; - letter-spacing: -0.02em; -} - -.page-hero p { - font-size: 1.15rem; - color: var(--color-text-muted); -} - -.specs-overview { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 24px; - text-align: center; -} - -.spec-highlight { - background: var(--color-bg-card); - border: 1px solid var(--color-border); - border-radius: var(--radius); - padding: 32px 20px; -} - -.spec-highlight-value { - font-size: 2rem; - font-weight: 800; - color: var(--color-primary-light); - margin-bottom: 8px; -} - -.spec-highlight-label { - font-size: 0.9rem; - color: var(--color-text-muted); -} - -.spec-section { - max-width: 800px; - margin: 0 auto; -} - -.spec-section-header { - display: flex; - gap: 20px; - align-items: flex-start; - margin-bottom: 32px; -} - -.spec-section-icon { - color: var(--color-primary-light); - flex-shrink: 0; -} - -.spec-section-header h2 { - font-size: 1.8rem; - font-weight: 800; - color: var(--color-text-heading); - margin-bottom: 8px; -} - -.spec-section-header p { - color: var(--color-text-muted); - font-size: 1rem; -} - -.spec-table { - background: var(--color-bg-card); - border: 1px solid var(--color-border); - border-radius: var(--radius); - overflow: hidden; -} - -.spec-table table { - width: 100%; - border-collapse: collapse; -} - -.spec-table tr { - border-bottom: 1px solid var(--color-border); -} - -.spec-table tr:last-child { - border-bottom: none; -} - -.spec-table td { - padding: 16px 20px; - font-size: 0.95rem; - color: var(--color-text); - vertical-align: top; -} - -.spec-label { - font-weight: 600; - color: var(--color-text-heading); - width: 200px; - white-space: nowrap; -} - -@media (max-width: 768px) { - .specs-overview { - grid-template-columns: repeat(2, 1fr); - } - - .spec-section-header { - flex-direction: column; - align-items: center; - text-align: center; - } - - .spec-label { - width: auto; - white-space: normal; - display: block; - padding-bottom: 4px; - } - - .spec-table td { - display: block; - padding: 8px 16px; - } - - .spec-table tr { - padding: 8px 0; - } - - .spec-table td:first-child { - padding-bottom: 0; - } -} - -@media (max-width: 480px) { - .specs-overview { - grid-template-columns: 1fr 1fr; - } -} - -/* === Animations === */ -.fade-in { - opacity: 0; - transform: translateY(20px); - transition: opacity 0.6s ease, transform 0.6s ease; -} - -.fade-in.visible { - opacity: 1; - transform: translateY(0); -} - -/* === Responsive === */ -@media (max-width: 1024px) { - .services-grid, - .pricing-grid, - .features-grid { - grid-template-columns: repeat(2, 1fr); - } - - .pricing-featured { - transform: none; - } - - .pricing-featured:hover { - transform: translateY(-4px); - } -} - -@media (max-width: 768px) { - .nav { - display: none; - position: fixed; - top: var(--header-height); - left: 0; - right: 0; - background: var(--color-bg); - flex-direction: column; - padding: 24px; - gap: 0; - border-bottom: 1px solid var(--color-border); - box-shadow: var(--shadow); - } - - .nav.open { - display: flex; - } - - .nav a { - padding: 14px 0; - border-bottom: 1px solid var(--color-border); - font-size: 1.05rem; - } - - .nav a:last-child { - border-bottom: none; - } - - .nav a::after { - display: none; - } - - .nav-toggle { - display: flex; - } - - .nav-toggle.open span:nth-child(1) { - transform: rotate(45deg) translate(5px, 5px); - } - - .nav-toggle.open span:nth-child(2) { - opacity: 0; - } - - .nav-toggle.open span:nth-child(3) { - transform: rotate(-45deg) translate(5px, -5px); - } - - .hero { - padding: 120px 0 60px; - } - - .hero h1 { - font-size: 2rem; - } - - .hero-subtitle { - font-size: 1.05rem; - } - - .hero-actions { - flex-direction: column; - gap: 12px; - } - - .hero-stats { - gap: 24px; - } - - .services-grid, - .pricing-grid, - .features-grid { - grid-template-columns: 1fr; - } - - .section { - padding: 64px 0; - } - - .section-title { - font-size: 1.75rem; - } - - .contact-grid { - grid-template-columns: 1fr; - gap: 40px; - } - - .contact-form { - grid-template-columns: 1fr; - } - - .footer-inner { - grid-template-columns: 1fr; - gap: 32px; - } -} - -@media (max-width: 480px) { - .hero-stats { - flex-direction: column; - gap: 16px; - } - - .stat { - flex-direction: row; - gap: 12px; - align-items: center; - } -}