Kitt Parker 7 ヶ月 前
コミット
3a6738f262
11 ファイル変更1515 行追加0 行削除
  1. 23 0
      .gitignore
  2. 0 0
      README.md
  3. BIN
      background.jpg
  4. 6 0
      composer.json
  5. 561 0
      composer.lock
  6. 68 0
      contact.php
  7. BIN
      fav_icon.png
  8. BIN
      hero-banner.jpg
  9. 230 0
      index.html
  10. 80 0
      scripts.js
  11. 547 0
      styles.css

+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
+# Composer dependencies
+/vendor/
+
+# Environment variables
+.env
+
+# OS / Editor junk
+.DS_Store
+Thumbs.db
+
+# IDE/editor configs (optional, but common)
+.vscode/
+.idea/
+
+# PHPUnit results & cache
+.phpunit.result.cache
+
+# Logs & temporary files
+*.log
+
+# If you use PHPStan, Psalm, or similar tools
+/.phpstan/cache
+/.psalm/cache

+ 0 - 0
README.md


BIN
background.jpg


+ 6 - 0
composer.json

@@ -0,0 +1,6 @@
+{
+    "require": {
+        "phpmailer/phpmailer": "^6.10",
+        "vlucas/phpdotenv": "^5.6"
+    }
+}

+ 561 - 0
composer.lock

@@ -0,0 +1,561 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "eee9fb53826be0db5352d1f22df4cd54",
+    "packages": [
+        {
+            "name": "graham-campbell/result-type",
+            "version": "v1.1.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/GrahamCampbell/Result-Type.git",
+                "reference": "3ba905c11371512af9d9bdd27d99b782216b6945"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945",
+                "reference": "3ba905c11371512af9d9bdd27d99b782216b6945",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2.5 || ^8.0",
+                "phpoption/phpoption": "^1.9.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "GrahamCampbell\\ResultType\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                }
+            ],
+            "description": "An Implementation Of The Result Type",
+            "keywords": [
+                "Graham Campbell",
+                "GrahamCampbell",
+                "Result Type",
+                "Result-Type",
+                "result"
+            ],
+            "support": {
+                "issues": "https://github.com/GrahamCampbell/Result-Type/issues",
+                "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-07-20T21:45:45+00:00"
+        },
+        {
+            "name": "phpmailer/phpmailer",
+            "version": "v6.10.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/PHPMailer/PHPMailer.git",
+                "reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
+                "reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
+                "shasum": ""
+            },
+            "require": {
+                "ext-ctype": "*",
+                "ext-filter": "*",
+                "ext-hash": "*",
+                "php": ">=5.5.0"
+            },
+            "require-dev": {
+                "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+                "doctrine/annotations": "^1.2.6 || ^1.13.3",
+                "php-parallel-lint/php-console-highlighter": "^1.0.0",
+                "php-parallel-lint/php-parallel-lint": "^1.3.2",
+                "phpcompatibility/php-compatibility": "^9.3.5",
+                "roave/security-advisories": "dev-latest",
+                "squizlabs/php_codesniffer": "^3.7.2",
+                "yoast/phpunit-polyfills": "^1.0.4"
+            },
+            "suggest": {
+                "decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
+                "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
+                "ext-openssl": "Needed for secure SMTP sending and DKIM signing",
+                "greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
+                "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
+                "league/oauth2-google": "Needed for Google XOAUTH2 authentication",
+                "psr/log": "For optional PSR-3 debug logging",
+                "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
+                "thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "PHPMailer\\PHPMailer\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-2.1-only"
+            ],
+            "authors": [
+                {
+                    "name": "Marcus Bointon",
+                    "email": "phpmailer@synchromedia.co.uk"
+                },
+                {
+                    "name": "Jim Jagielski",
+                    "email": "jimjag@gmail.com"
+                },
+                {
+                    "name": "Andy Prevost",
+                    "email": "codeworxtech@users.sourceforge.net"
+                },
+                {
+                    "name": "Brent R. Matzelle"
+                }
+            ],
+            "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
+            "support": {
+                "issues": "https://github.com/PHPMailer/PHPMailer/issues",
+                "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.10.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/Synchro",
+                    "type": "github"
+                }
+            ],
+            "time": "2025-04-24T15:19:31+00:00"
+        },
+        {
+            "name": "phpoption/phpoption",
+            "version": "1.9.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/schmittjoh/php-option.git",
+                "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54",
+                "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2.5 || ^8.0"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28"
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                },
+                "branch-alias": {
+                    "dev-master": "1.9-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "PhpOption\\": "src/PhpOption/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Johannes M. Schmitt",
+                    "email": "schmittjoh@gmail.com",
+                    "homepage": "https://github.com/schmittjoh"
+                },
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                }
+            ],
+            "description": "Option Type for PHP",
+            "keywords": [
+                "language",
+                "option",
+                "php",
+                "type"
+            ],
+            "support": {
+                "issues": "https://github.com/schmittjoh/php-option/issues",
+                "source": "https://github.com/schmittjoh/php-option/tree/1.9.3"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-07-20T21:41:07+00:00"
+        },
+        {
+            "name": "symfony/polyfill-ctype",
+            "version": "v1.32.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-ctype.git",
+                "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
+                "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "provide": {
+                "ext-ctype": "*"
+            },
+            "suggest": {
+                "ext-ctype": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Ctype\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Gert de Pagter",
+                    "email": "BackEndTea@gmail.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for ctype functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "ctype",
+                "polyfill",
+                "portable"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-09T11:45:10+00:00"
+        },
+        {
+            "name": "symfony/polyfill-mbstring",
+            "version": "v1.32.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-mbstring.git",
+                "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
+                "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
+                "shasum": ""
+            },
+            "require": {
+                "ext-iconv": "*",
+                "php": ">=7.2"
+            },
+            "provide": {
+                "ext-mbstring": "*"
+            },
+            "suggest": {
+                "ext-mbstring": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Mbstring\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for the Mbstring extension",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "mbstring",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-12-23T08:48:59+00:00"
+        },
+        {
+            "name": "symfony/polyfill-php80",
+            "version": "v1.32.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-php80.git",
+                "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+                "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php80\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Ion Bazan",
+                    "email": "ion.bazan@gmail.com"
+                },
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2025-01-02T08:10:11+00:00"
+        },
+        {
+            "name": "vlucas/phpdotenv",
+            "version": "v5.6.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/vlucas/phpdotenv.git",
+                "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
+                "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
+                "shasum": ""
+            },
+            "require": {
+                "ext-pcre": "*",
+                "graham-campbell/result-type": "^1.1.3",
+                "php": "^7.2.5 || ^8.0",
+                "phpoption/phpoption": "^1.9.3",
+                "symfony/polyfill-ctype": "^1.24",
+                "symfony/polyfill-mbstring": "^1.24",
+                "symfony/polyfill-php80": "^1.24"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.8.2",
+                "ext-filter": "*",
+                "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2"
+            },
+            "suggest": {
+                "ext-filter": "Required to use the boolean validator."
+            },
+            "type": "library",
+            "extra": {
+                "bamarni-bin": {
+                    "bin-links": true,
+                    "forward-command": false
+                },
+                "branch-alias": {
+                    "dev-master": "5.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Dotenv\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Vance Lucas",
+                    "email": "vance@vancelucas.com",
+                    "homepage": "https://github.com/vlucas"
+                }
+            ],
+            "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
+            "keywords": [
+                "dotenv",
+                "env",
+                "environment"
+            ],
+            "support": {
+                "issues": "https://github.com/vlucas/phpdotenv/issues",
+                "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2025-04-30T23:37:27+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": {},
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": {},
+    "platform-dev": {},
+    "plugin-api-version": "2.6.0"
+}

+ 68 - 0
contact.php

@@ -0,0 +1,68 @@
+<?php
+require 'vendor/autoload.php'; // if you used Composer
+
+use PHPMailer\PHPMailer\PHPMailer;
+use PHPMailer\PHPMailer\Exception;
+
+$mail = new PHPMailer(true);
+
+try {
+    $name     = htmlspecialchars($_POST['name'] ?? '');
+    $email    = htmlspecialchars($_POST['email'] ?? '');
+    $phone    = htmlspecialchars($_POST['phone'] ?? '');
+    $pref     = htmlspecialchars($_POST['preferred_contact'] ?? '');
+    $message  = htmlspecialchars($_POST['message'] ?? '');
+
+    if (!$name || !$email || !$phone || !$pref || !$message) {
+        http_response_code(400);
+        echo "All fields are required.";
+        exit;
+    }
+
+
+    if (!empty($_POST['website'])) {
+        // Bot filled out the honeypot
+        http_response_code(400);
+        die("Bot detected. Submission rejected.");
+    }
+
+
+    $body = <<<EOT
+You have a new contact form submission:
+
+Name: $name
+Email: $email
+Phone: $phone
+Preferred Contact: $pref
+
+Message:
+$message
+EOT;
+
+    // SMTP config
+    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
+    $dotenv->load();
+
+    $mail->isSMTP();
+    $mail->Host       = $_ENV['SMTP_HOST'];
+    $mail->SMTPAuth   = true;
+    $mail->Username   = $_ENV['SMTP_USER'];
+    $mail->Password   = $_ENV['SMTP_PASS'];
+    $mail->SMTPSecure = $_ENV['SMTP_SECURE'];
+    $mail->Port       = $_ENV['SMTP_PORT'];
+
+    // Email headers
+    $mail->setFrom($_ENV['MAIL_TO'], $name);   // sender = SMTP account
+    $mail->addAddress($_ENV['MAIL_TO']);     // recipient
+    $mail->addReplyTo($email, $name);               // visitor’s email
+
+    $mail->Subject = 'New Contact Form Submission From Company Site';
+    $mail->Body    = $body;
+
+    $mail->send();
+    echo "OK";
+
+} catch (Exception $e) {
+    http_response_code(500);
+    echo "Mailer Error: " . $mail->ErrorInfo;
+}

BIN
fav_icon.png


BIN
hero-banner.jpg


+ 230 - 0
index.html

@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8" />
+    <title>ConciseIT Consulting | Modern IT Solutions & Support</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <link rel="stylesheet" href="styles.css" />
+    <link rel="icon" href="/fav_icon.png" type="image/png" />
+</head>
+<body>
+
+<!-- PAGE SHELL: gives rounded "paper" effect -->
+<div class="page-shell">
+    <!-- ===== NAVBAR ===== -->
+    <header class="navbar">
+        <div class="container">
+            <h1 class="logo">Concise<span>IT</span></h1>
+            <nav class="navbar-nav">
+                <div class="nav-left">
+                    <ul>
+                        <li><a href="#services">Services</a></li>
+                        <li><a href="#why">Why Us</a></li>
+                        <li><a href="#ContactMenu" id="ContactMenu">Contact</a></li>
+                        <li><a href="http://invoice.concise-it.com/client/login/IKu53iTBp6w5myUDHQBhKBH7giyRyoUs">Client Invoice Portal</a></li>
+                        <li><a href="#" id="ContactMenu">Client Ticket Portal</a></li>
+                    </ul>
+                </div>
+                <div class="nav-right">
+                    <a href="mailto:info@concise-it.com" class="email-icon" title="Email us">
+                        📧
+                    </a>
+                </div>
+            </nav>
+
+        </div>
+    </header>
+
+
+    <!-- ===== HERO ===== -->
+    <section class="hero">
+        <canvas id="hero-particles" aria-hidden="true"></canvas>
+        <div class="container hero-content">
+            <h2>Future-Proof IT, Delivered Today.</h2>
+            <p>
+                Tailored IT solutions for small to medium businesses — from cloud migrations to 24/7 support,
+                we keep your business fast, reliable, and protected so you can focus on growth.
+            </p>
+        </div>
+    </section>
+
+
+    <!-- ===== SERVICES ===== -->
+    <section id="services" class="services">
+        <div class="container">
+            <h3 class="section-title">Our Core Services</h3>
+            <div class="service-grid">
+                <article>
+                    <div class="service-icon" aria-hidden="true">
+                        <!-- Cloud & Gear -->
+                        <svg viewBox="0 0 24 24"><path d="M4 15a4 4 0 0 1 2-3.464A5 5 0 0 1 9 6a5 5 0 0 1 4.9 4.02A4 4 0 1 1 15 18H7a4 4 0 0 1-3-3Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><circle cx="17" cy="7" r="2" fill="currentColor"/></svg>
+                    </div>
+                    <h4>Cloud & DevOps</h4>
+                    <p>Design, deploy, and automate scalable clouds, or on-prem hybrid architectures.</p>
+                </article>
+
+                <article>
+                    <div class="service-icon" aria-hidden="true">
+                        <!-- Shield Check -->
+                        <svg viewBox="0 0 24 24"><path d="M12 3 4 7v5c0 5 3.5 9 8 9s8-4 8-9V7l-8-4Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/><path d="m9 12 2 2 4-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+                    </div>
+                    <h4>Cybersecurity</h4>
+                    <p>24/7 monitoring, SIEM integration, and compliance audits to keep threats at bay.</p>
+                </article>
+
+                <article>
+                    <div class="service-icon" aria-hidden="true">
+                        <!-- Database Stack -->
+                        <svg viewBox="0 0 24 24"><ellipse cx="12" cy="5" rx="7" ry="3" fill="none" stroke="currentColor" stroke-width="2"/><path d="M5 9c0 1.7 3.1 3 7 3s7-1.3 7-3M5 13c0 1.7 3.1 3 7 3s7-1.3 7-3M5 17c0 1.7 3.1 3 7 3s7-1.3 7-3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
+                    </div>
+                    <h4>Data Engineering</h4>
+                    <p>ETL pipelines, real-time analytics, and optimized SQL tuning for actionable insights.</p>
+                </article>
+
+                <article>
+                    <div class="service-icon" aria-hidden="true">
+                        <!-- Headset -->
+                        <svg viewBox="0 0 24 24"><path d="M4 12a8 8 0 0 1 16 0v5a2 2 0 0 1-2 2h-3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><rect x="2" y="11" width="4" height="6" rx="2" fill="none" stroke="currentColor" stroke-width="2"/><rect x="18" y="11" width="4" height="6" rx="2" fill="none" stroke="currentColor" stroke-width="2"/><path d="M10 19h2" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
+                    </div>
+                    <h4>Managed IT Support</h4>
+                    <p>Proactive maintenance, patch management, and friendly help-desk whenever you need it.</p>
+                </article>
+
+                <article>
+                    <div class="service-icon" aria-hidden="true">
+                        <!-- Compass / Strategy -->
+                        <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"/><polygon points="16 8 14 14 8 16 10 10 16 8" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></svg>
+                    </div>
+                    <h4>IT Strategy & Consulting</h4>
+                    <p>Align your technology roadmap with your business goals for measurable ROI and efficiency.</p>
+                </article>
+
+                <article>
+                    <div class="service-icon" aria-hidden="true">
+                        <!-- Refresh / Disaster Recovery -->
+                        <svg viewBox="0 0 24 24"><polyline points="23 4 23 10 17 10" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><polyline points="1 20 1 14 7 14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M3.51 9a9 9 0 0 1 14.13-3.36L23 10M1 14l5.36 4.36A9 9 0 0 0 20.49 15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+                    </div>
+                    <h4>Disaster Recovery & Continuity</h4>
+                    <p>Prepare, protect, and recover quickly from unexpected outages or disasters with confidence.</p>
+                </article>
+
+                <article>
+                    <div class="service-icon" aria-hidden="true">
+                        <!-- Monitor / Code -->
+                        <svg viewBox="0 0 24 24"><rect x="2" y="3" width="20" height="14" rx="2" ry="2" fill="none" stroke="currentColor" stroke-width="2"/><path d="M8 21h8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><path d="M12 17v4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
+                    </div>
+                    <h4>Website Development</h4>
+                    <p>Design and deploy attractive, mobile‑friendly websites that showcase your brand and convert visitors to customers.</p>
+                </article>
+
+                <article>
+                    <div class="service-icon" aria-hidden="true">
+                        <!-- Network -->
+                        <svg viewBox="0 0 24 24"><path d="M12 20v-6m0 0H6m6 0h6m-6-4V4m0 6h6m-6 0H6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+                    </div>
+                    <h4>Network & Domain Administration</h4>
+                    <p>Manage your networks, domains, and infrastructure for maximum uptime, security, and performance.</p>
+                </article>
+
+                <article>
+                    <div class="service-icon" aria-hidden="true">
+                        <!-- Bar chart -->
+                        <svg viewBox="0 0 24 24"><path d="M4 20V10m4 10V4m4 16v-6m4 6V8m4 12V14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+                    </div>
+                    <h4>Custom Database & Report Development</h4>
+                    <p>Build tailored reports and dashboards — including Acumatica custom reports — to give you actionable insights.</p>
+                </article>
+            </div>
+
+
+        </div>
+    </section>
+
+    <!-- ===== WHY US ===== -->
+    <section id="why" class="why-us">
+        <div class="container">
+            <h3 class="section-title">Why Clients Choose ConciseIT</h3>
+            <ul class="why-list">
+                <li><strong>Proven Expertise </strong>— 20+ years combined experience across DevOps, security & data.</li>
+                <li><strong>No Geek-Speak </strong>— Actionable, executive-level reporting & KPIs.</li>
+                <li><strong>Transparent Pricing </strong>— Flat monthly rates. No “scope drift” surprises.</li>
+                <li><strong>Rapid Response </strong>— 15-minute SLA for critical tickets—day or night.</li>
+                <li><strong>Future-Ready Solutions </strong>— We build scalable, forward-thinking systems that grow with your business.</li>
+                <li><strong>Trusted Partnerships </strong>— Long-term relationships with vendors and clients ensure reliable support & resources.</li>
+            </ul>
+
+        </div>
+    </section>
+
+
+    <!-- ===== TESTIMONIALS =====
+    <section id="testimonials" class="testimonials">
+      <div class="container">
+        <h3 class="section-title">Success Stories</h3>
+        <blockquote>
+          “ConciseIT cut our cloud spend by 37 % while doubling deployment velocity.
+          The ROI was immediate.”<cite>— J. Roberts, CTO, FinTech Co.</cite>
+        </blockquote>
+        <blockquote>
+          “Their security team caught a breach attempt we didn’t even know existed.
+          Top-notch professionals.”<cite>— M. Delgado, COO, Healthcare Group</cite>
+        </blockquote>
+      </div>
+    </section>
+-->
+
+    <!-- Dummy anchor for smooth-scroll target -->
+    <span id="contact-section"></span>
+
+    <!-- ===== FOOTER ===== -->
+    <footer class="footer">
+        <div class="container">
+            <p>&copy; 2025 ConciseIT Consulting · All rights reserved.</p>
+        </div>
+    </footer>
+</div><!--/.page-shell-->
+
+<!-- ===== FLOATING CONTACT FORM (kept outside page so it sits in margin) ===== -->
+<aside id="contact-flyout">
+    <form id="contactForm" class="contact-form" action="contact.php" method="POST">
+        <h4>Let’s Talk Tech</h4>
+
+        <label>Name <input type="text" name="name" required></label>
+        <label>Email <input type="email" name="email" required></label>
+        <label>Phone <input type="tel" name="phone" required></label>
+        <label>
+            Preferred Contact Method
+            <select name="preferred_contact" required>
+                <option value="" disabled selected>Choose one</option>
+                <option value="email">Email</option>
+                <option value="phone">Phone</option>
+            </select>
+        </label>
+        <label>Message <textarea name="message" rows="4" required></textarea></label>
+
+        <button type="submit" class="submit-btn">
+            <span class="btn-text">Send ➜</span>
+            <span class="btn-spinner" style="display:none;"></span>
+        </button>
+
+        <button type="button" id="closeFlyout">✕</button>
+
+        <label class="honeypot">
+            If you’re human, Make sure to fill this out:
+            <input type="text" name="website" autocomplete="off">
+        </label>
+
+    </form>
+</aside>
+
+<div id="formModal" class="form-modal hidden">
+    <div class="form-modal-content">
+        <p id="formModalMessage"></p>
+    </div>
+</div>
+
+<script src="scripts.js" defer></script>
+
+
+</body>
+</html>

+ 80 - 0
scripts.js

@@ -0,0 +1,80 @@
+/* scripts.js */
+document.addEventListener('DOMContentLoaded', () => {
+    const flyout     = document.getElementById('contact-flyout');
+    const closeBtn   = document.getElementById('closeFlyout');
+    const form       = document.getElementById('contactForm');
+    const contactNav = document.getElementById('ContactMenu');
+    const submitBtn  = form.querySelector('.submit-btn');
+    const btnText    = submitBtn.querySelector('.btn-text');
+    const btnSpinner = submitBtn.querySelector('.btn-spinner');
+
+    const modal      = document.getElementById('formModal');
+    const modalMsg   = document.getElementById('formModalMessage');
+
+    closeBtn.addEventListener('click', () => {
+        flyout.style.display = 'none';
+    });
+
+    form.addEventListener('submit', e => {
+        e.preventDefault();
+
+        btnText.style.display = 'none';
+        btnSpinner.style.display = 'inline-block';
+
+        flyout.classList.add('wiggle');
+        setTimeout(() => flyout.classList.remove('wiggle'), 600);
+
+        const formData = new FormData(form);
+
+        fetch(form.action, {
+            method: 'POST',
+            body: formData
+        })
+            .then(response => response.text())
+            .then(result => {
+                if (result.trim() === "OK") {
+                    form.reset();
+                    showModal("✅ Thanks! We’ll be in touch shortly.");
+                } else {
+                    showModal("❌ Error: " + result);
+                }
+            })
+            .catch(() => {
+                showModal("❌ Failed to send message. Please try again.");
+            })
+            .finally(() => {
+                btnText.style.display = 'inline';
+                btnSpinner.style.display = 'none';
+            });
+    });
+
+    function showModal(message) {
+        modalMsg.textContent = message;
+        modal.classList.remove('hidden');
+        setTimeout(() => {
+            modal.classList.add('hidden');
+        }, 4000);
+    }
+
+    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
+        anchor.addEventListener('click', function (e) {
+            e.preventDefault();
+            const target = document.querySelector(this.getAttribute('href'));
+            if (target) {
+                target.scrollIntoView({ behavior: 'smooth' });
+            }
+        });
+    });
+
+    contactNav.addEventListener('click', (e) => {
+        e.preventDefault();
+
+        if (flyout.style.display === 'none' || flyout.style.display === '') {
+            flyout.style.display = 'block';
+        } else {
+            flyout.classList.remove('wiggle');
+            void flyout.offsetWidth;
+            flyout.classList.add('wiggle');
+        }
+    });
+});

+ 547 - 0
styles.css

@@ -0,0 +1,547 @@
+/* ------------ Base reset & palette ------------- */
+*,
+*::before,
+*::after {
+    box-sizing: border-box;
+    margin: 0;
+    padding: 0;
+    line-height: 1.4;
+    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
+}
+
+:root {
+    --primary: #0d6efd;
+    --dark: #121418;
+    --light: #f5f7fa;
+    --accent: #00c27a;
+    --page-radius: 24px;
+    --page-radius-lg: 32px;
+    --page-bg: #ffffff;
+    --body-bg1: #ffe1cf;
+    --body-bg2: #ffd8c2;
+}
+
+/* Body background & responsive outer margin "margin zone" */
+html, body { height: 100%; }
+
+body {
+    background: url('background.jpg') center center / cover no-repeat fixed;
+    padding: clamp(8px, 3vw, 48px);
+}
+body::before {
+    content: "";
+    position: fixed;
+    inset: 0;
+    background: rgba(0,0,0,0.3); /* adjust opacity as needed */
+    z-index: -1;
+}
+
+
+/* The page surface */
+.page-shell {
+    background: var(--page-bg);
+    border-radius: var(--page-radius);
+    overflow: hidden; /* clip hero to rounded edges */
+    box-shadow:
+            0 0 0 1px rgba(0,0,0,.06),
+            0 10px 25px rgba(0,0,0,.08),
+            0 35px 80px rgba(0,0,0,.12);
+    max-width: 1600px;
+    margin-inline: auto;
+}
+@media (min-width: 768px) {
+    .page-shell { border-radius: var(--page-radius-lg); }
+}
+
+/* ------------ Layout helpers ------------- */
+.container {
+    width: min(90%, 1100px);
+    margin-inline: auto;
+}
+
+.section-title {
+    margin-bottom: 1rem;
+    font-size: 1.85rem;
+    color: var(--primary);
+    text-align: center;
+}
+
+/* ------------ Navbar ------------- */
+.navbar {
+    position: sticky;
+    top: 0;
+    background: rgba(255, 255, 255, 0.9);
+    backdrop-filter: blur(6px);
+    border-bottom: 1px solid #e1e5ea;
+    z-index: 50;
+}
+.navbar .logo {
+    font-size: 1.4rem;
+    color: var(--dark);
+}
+.navbar .logo span { color: var(--primary); }
+.navbar nav ul {
+    display: flex;
+    gap: 1.2rem;
+    list-style: none;
+}
+.navbar a {
+    text-decoration: none;
+    color: var(--dark);
+    font-weight: 500;
+    padding: 0.4rem 0.8rem;
+    border-radius: 4px;
+    transition: background-color 0.2s ease, color 0.2s ease;
+}
+
+.navbar a:hover {
+    background-color: rgba(13, 110, 253, 0.1);
+    color: var(--primary);
+}
+
+.navbar a:active {
+    background-color: rgba(13, 110, 253, 0.2);
+    color: var(--primary);
+}
+
+.navbar .container {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0.7rem 0;
+}
+.navbar-nav {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+}
+
+.navbar-nav .nav-left ul {
+    display: flex;
+    gap: 1.2rem;
+    list-style: none;
+    margin: 0;
+    padding: 0;
+}
+
+.navbar-nav .nav-left a {
+    text-decoration: none;
+    color: var(--dark);
+    font-weight: 500;
+    padding: 0.4rem 0.8rem;
+    border-radius: 4px;
+    transition: background-color 0.2s ease, color 0.2s ease;
+}
+
+.navbar-nav .nav-left a:hover {
+    background-color: rgba(13, 110, 253, 0.1);
+    color: var(--primary);
+}
+
+.email-icon {
+    font-size: 1.8rem;
+    text-decoration: none;
+    color: var(--dark);
+    margin-left: 1rem;
+    transition: color 0.2s ease;
+}
+
+.email-icon:hover {
+    color: var(--primary);
+}
+
+
+@media (max-width: 768px) {
+    .navbar .container {
+        flex-direction: column;
+        align-items: flex-start;
+    }
+
+    .navbar-nav {
+        flex-direction: column;
+        width: 100%;
+    }
+
+    .navbar-nav .nav-left ul {
+        flex-direction: column;
+        gap: 0.5rem;
+        width: 100%;
+    }
+
+    .navbar-nav .nav-left a {
+        display: block;
+        width: 100%;
+        padding: 0.75rem;
+    }
+
+    .navbar .logo {
+        margin-bottom: 0.5rem;
+    }
+
+    .email-icon {
+        align-self: flex-end;
+        margin: 0.5rem 0;
+    }
+}
+
+
+
+/* ------------ Hero ------------- */
+/* ------------ Hero (Layered Tech) ------------- */
+.hero {
+    position: relative;
+    overflow: hidden; /* keeps layers inside rounded page-shell */
+    color: #fff;
+    padding: 5rem 0 6rem;
+    text-align: center;
+}
+
+/* Background image layer */
+.hero::before {
+    content: "";
+    position: absolute;
+    inset: 0;
+    background:
+            url('hero-banner.jpg') center/cover no-repeat; /* replace w/ your image; falls back if missing */
+    filter: brightness(0.45) saturate(1.2); /* darken so text pops */
+    z-index: 0;
+}
+
+/* Animated gradient overlay layer */
+.hero::after {
+    content: "";
+    position: absolute;
+    inset: 0;
+    background: linear-gradient(
+            135deg,
+            rgba(13,110,253,0.85) 0%,
+            rgba(77,141,255,0.65) 45%,
+            rgba(0,194,122,0.70) 100%
+    );
+    background-size: 200% 200%;
+    animation: heroGradient 16s ease-in-out infinite alternate;
+    mix-blend-mode: screen; /* try 'overlay' or 'soft-light' if you prefer */
+    z-index: 1;
+}
+@keyframes heroGradient {
+    0%   { background-position: 0% 50%; }
+    100% { background-position: 100% 50%; }
+}
+
+/* Particle canvas sits above background layers, below content */
+#hero-particles {
+    position: absolute;
+    inset: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 2;
+    pointer-events: none;
+}
+
+/* Content on top */
+.hero-content {
+    position: relative;
+    z-index: 3;
+}
+
+.hero h2 { font-size: 2.8rem; margin-bottom: 1rem; }
+.hero p  { font-size: 1.2rem; margin-bottom: 2rem; max-width: 650px; margin-inline: auto; }
+
+.cta-btn {
+    padding: 0.9rem 1.8rem;
+    background: var(--accent);
+    border: none;
+    color: #fff;
+    font-size: 1.05rem;
+    border-radius: 6px;
+    text-decoration: none;
+    transition: transform 0.2s;
+}
+.cta-btn:hover { transform: translateY(-3px); }
+
+/* ------------ Services ------------- */
+.services { padding: 4rem 0 2rem; background: var(--light); }
+.service-grid {
+    display: grid;
+    gap: 2rem;
+    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
+}
+.service-grid article {
+    background: #fff;
+    padding: 1.8rem;
+    border-radius: 8px;
+    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
+    transition: transform 0.25s;
+}
+.service-grid article:hover { transform: translateY(-6px); }
+.service-grid h4 { margin-bottom: 0.6rem; color: var(--primary); }
+.service-grid p { font-size: 0.95rem; }
+
+/* Service Icons */
+.service-icon {
+    width: 32px;
+    height: 32px;
+    margin-inline: auto;
+    margin-bottom: 0.5rem;
+    color: var(--primary);
+}
+.service-icon svg {
+    width: 100%;
+    height: 100%;
+    display: block;
+}
+
+/* ------------ Why Us ------------- */
+.why-us { padding: 4rem 0; }
+.why-list {
+    display: grid;
+    gap: 1rem;
+    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+    list-style: none;
+    font-size: 1.05rem;
+}
+.why-list li { padding-left: 1.3rem; position: relative; }
+.why-list li::before {
+    content: "✓";
+    position: absolute;
+    left: 0;
+    color: var(--accent);
+}
+
+/* ------------ Testimonials ------------- */
+.testimonials { padding: 4rem 0 5rem; background: var(--light); }
+blockquote {
+    background: #fff;
+    padding: 1.5rem 2rem;
+    border-left: 4px solid var(--primary);
+    margin: 1.2rem 0;
+    border-radius: 6px;
+    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.04);
+}
+blockquote cite {
+    display: block;
+    margin-top: 0.8rem;
+    font-style: normal;
+    font-size: 0.9rem;
+    color: #555;
+}
+
+/* ------------ Floating Contact Form ------------- */
+:root {
+    --flyout-right-margin: clamp(8px, 2vw, 24px);
+}
+
+/* … */
+
+#contact-flyout {
+    position: fixed;
+    top: 25%;
+    right: var(--flyout-right-margin);
+    width: 320px;
+    z-index: 100;
+    animation: bob 3.6s ease-in-out infinite;
+}
+
+@keyframes bob {
+    0%, 100% { transform: translateY(-8px); }
+    50%      { transform: translateY(8px); }
+}
+.contact-form {
+    background: #fff;
+    border: 2px solid var(--primary);
+    border-right: none;
+    padding: 1.5rem 1.2rem 1rem;
+    border-radius: 8px 0 0 8px;
+    box-shadow: -4px 6px 16px rgba(0, 0, 0, 0.08);
+    width: 100%;
+}
+.contact-form h4 { margin-bottom: 0.8rem; color: var(--primary); }
+.contact-form label {
+    display: block;
+    margin-bottom: 1rem;
+    font-size: 0.9rem;
+}
+.contact-form input,
+.contact-form textarea {
+    width: 100%;
+    padding: 0.55rem 0.6rem;
+    font-size: 0.9rem;
+    border: 1px solid #ccc;
+    border-radius: 4px;
+}
+.submit-btn {
+    display: block;
+    width: 100%;
+    margin-top: 0.4rem;
+    padding: 0.7rem 0;
+    border: none;
+    background: var(--primary);
+    color: #fff;
+    font-weight: 600;
+    border-radius: 4px;
+    cursor: pointer;
+    transition: background 0.2s;
+}
+.submit-btn:hover { background: #005be0; }
+#closeFlyout {
+    position: absolute;
+    top: 4px;
+    left: -32px;
+    background: var(--primary);
+    color: #fff;
+    border: none;
+    border-radius: 50%;
+    width: 28px;
+    height: 28px;
+    font-size: 0.9rem;
+    cursor: pointer;
+}
+
+/* ------------ Footer ------------- */
+.footer {
+    background: var(--dark);
+    color: #aaa;
+    text-align: center;
+    padding: 1.4rem 0;
+    font-size: 0.85rem;
+}
+
+/* Respect motion preferences */
+@media (prefers-reduced-motion: reduce) {
+    .hero::after {
+        animation: none !important;
+        background-position: 50% 50% !important;
+    }
+    #hero-particles { display: none !important; }
+}
+
+/* wiggle effect for contact flyout */
+#contact-flyout.wiggle {
+    animation: wiggle 0.5s ease;
+}
+
+@keyframes wiggle {
+    0%   { transform: translateY(0) rotate(0deg); }
+    15%  { transform: translateY(-2px) rotate(-2deg); }
+    30%  { transform: translateY(2px) rotate(2deg); }
+    45%  { transform: translateY(-1px) rotate(-1deg); }
+    60%  { transform: translateY(1px) rotate(1deg); }
+    75%  { transform: translateY(-1px) rotate(-1deg); }
+    100% { transform: translateY(0) rotate(0deg); }
+}
+
+/* Submitting spinner */
+.btn-spinner {
+    border: 3px solid #f3f3f3;
+    border-top: 3px solid var(--primary);
+    border-radius: 50%;
+    width: 16px;
+    height: 16px;
+    animation: spin 0.8s linear infinite;
+    display: inline-block;
+    vertical-align: middle;
+}
+
+@keyframes spin {
+    0% { transform: rotate(0deg); }
+    100% { transform: rotate(360deg); }
+}
+
+/* Modal */
+.form-modal {
+    position: fixed;
+    inset: 0;
+    background: rgba(0, 0, 0, 0.6);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    z-index: 9999;
+}
+
+.form-modal.hidden {
+    display: none;
+}
+
+.form-modal-content {
+    background: #fff;
+    padding: 1.5rem 2rem;
+    border-radius: 8px;
+    text-align: center;
+    animation: popin 0.3s ease;
+}
+
+@keyframes popin {
+    0% { transform: scale(0.8); opacity: 0; }
+    100% { transform: scale(1); opacity: 1; }
+}
+
+/* Wiggle (already in your CSS but repeated here for convenience) */
+/* Wiggle */
+#contact-flyout.wiggle {
+    animation: wiggle 0.5s ease;
+}
+
+@keyframes wiggle {
+    0% { transform: translateY(0) rotate(0deg); }
+    15% { transform: translateY(-2px) rotate(-2deg); }
+    30% { transform: translateY(2px) rotate(2deg); }
+    45% { transform: translateY(-1px) rotate(-1deg); }
+    60% { transform: translateY(1px) rotate(1deg); }
+    75% { transform: translateY(-1px) rotate(-1deg); }
+    100% { transform: translateY(0) rotate(0deg); }
+}
+
+.btn-spinner {
+    border: 3px solid #f3f3f3;
+    border-top: 3px solid var(--primary);
+    border-radius: 50%;
+    width: 16px;
+    height: 16px;
+    animation: spin 0.8s linear infinite;
+    display: inline-block;
+    vertical-align: middle;
+}
+
+@keyframes spin {
+    0% { transform: rotate(0deg); }
+    100% { transform: rotate(360deg); }
+}
+
+.form-modal {
+    position: fixed;
+    inset: 0;
+    background: rgba(0, 0, 0, 0.6);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    z-index: 9999;
+}
+
+.form-modal.hidden {
+    display: none;
+}
+
+.form-modal-content {
+    background: #fff;
+    padding: 1.5rem 2rem;
+    border-radius: 8px;
+    text-align: center;
+    animation: popin 0.3s ease;
+}
+
+@keyframes popin {
+    0% { transform: scale(0.8); opacity: 0; }
+    100% { transform: scale(1); opacity: 1; }
+}
+
+.honeypot {
+    position: absolute;
+    left: -9999px;
+    top: -9999px;
+    height: 0;
+    width: 0;
+    overflow: hidden;
+}
+
+
+