1
This commit is contained in:
parent
4e9f3637d4
commit
ffe2db4413
File diff suppressed because it is too large
Load Diff
@ -1,39 +1,56 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const chatForm = document.getElementById('chat-form');
|
||||
const chatInput = document.getElementById('chat-input');
|
||||
const chatMessages = document.getElementById('chat-messages');
|
||||
|
||||
const appendMessage = (text, sender) => {
|
||||
const msgDiv = document.createElement('div');
|
||||
msgDiv.classList.add('message', sender);
|
||||
msgDiv.textContent = text;
|
||||
chatMessages.appendChild(msgDiv);
|
||||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||||
};
|
||||
|
||||
chatForm.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
const message = chatInput.value.trim();
|
||||
if (!message) return;
|
||||
|
||||
appendMessage(message, 'visitor');
|
||||
chatInput.value = '';
|
||||
|
||||
try {
|
||||
const response = await fetch('api/chat.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ message })
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
// Artificial delay for realism
|
||||
setTimeout(() => {
|
||||
appendMessage(data.reply, 'bot');
|
||||
}, 500);
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
appendMessage("Sorry, something went wrong. Please try again.", 'bot');
|
||||
}
|
||||
const quoteForm = document.getElementById('quoteForm');
|
||||
const toastEl = document.getElementById('quoteToast');
|
||||
const nav = document.getElementById('mainNav');
|
||||
const navToggle = document.querySelector('[data-bs-target="#mainNav"]');
|
||||
const hasBootstrap = Boolean(window.bootstrap);
|
||||
if (nav && navToggle && !hasBootstrap) {
|
||||
navToggle.addEventListener('click', () => {
|
||||
const isOpen = nav.classList.toggle('show');
|
||||
navToggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
|
||||
if (toastEl && hasBootstrap) {
|
||||
window.bootstrap.Toast.getOrCreateInstance(toastEl, { delay: 5200 }).show();
|
||||
}
|
||||
|
||||
|
||||
document.querySelectorAll('a[href^="#"]').forEach((link) => {
|
||||
link.addEventListener('click', () => {
|
||||
if (nav && nav.classList.contains('show')) {
|
||||
if (hasBootstrap) {
|
||||
window.bootstrap.Collapse.getOrCreateInstance(nav).hide();
|
||||
} else {
|
||||
nav.classList.remove('show');
|
||||
navToggle?.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!quoteForm) return;
|
||||
|
||||
quoteForm.addEventListener('submit', (event) => {
|
||||
const brief = quoteForm.querySelector('#message');
|
||||
const submitButton = quoteForm.querySelector('button[type="submit"]');
|
||||
|
||||
if (brief && brief.value.trim().length < 20) {
|
||||
brief.setCustomValidity('Share at least 20 characters about the project.');
|
||||
} else if (brief) {
|
||||
brief.setCustomValidity('');
|
||||
}
|
||||
|
||||
if (!quoteForm.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const firstInvalid = quoteForm.querySelector(':invalid');
|
||||
if (firstInvalid) firstInvalid.focus({ preventScroll: false });
|
||||
} else if (submitButton) {
|
||||
submitButton.disabled = true;
|
||||
submitButton.textContent = 'Sending…';
|
||||
}
|
||||
|
||||
quoteForm.classList.add('was-validated');
|
||||
});
|
||||
});
|
||||
|
||||
150
index.php
150
index.php
@ -1,150 +1,2 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@ini_set('display_errors', '1');
|
||||
@error_reporting(E_ALL);
|
||||
@date_default_timezone_set('UTC');
|
||||
|
||||
$phpVersion = PHP_VERSION;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>New Style</title>
|
||||
<?php
|
||||
// Read project preview data from environment
|
||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
?>
|
||||
<?php if ($projectDescription): ?>
|
||||
<!-- Meta description -->
|
||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
||||
<!-- Open Graph meta tags -->
|
||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<!-- Twitter meta tags -->
|
||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<?php endif; ?>
|
||||
<?php if ($projectImageUrl): ?>
|
||||
<!-- Open Graph image -->
|
||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<!-- Twitter image -->
|
||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<?php endif; ?>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
||||
animation: bg-pan 20s linear infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes bg-pan {
|
||||
0% { background-position: 0% 0%; }
|
||||
100% { background-position: 100% 100%; }
|
||||
}
|
||||
main {
|
||||
padding: 2rem;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-bg-color);
|
||||
border: 1px solid var(--card-border-color);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.loader {
|
||||
margin: 1.25rem auto 1.25rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||
border-top-color: #fff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.hint {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px; height: 1px;
|
||||
padding: 0; margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap; border: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 1rem;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
code {
|
||||
background: rgba(0,0,0,0.2);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Analyzing your requirements and generating your website…</h1>
|
||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||
<span class="sr-only">Loading…</span>
|
||||
</div>
|
||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
require __DIR__ . '/landing.php';
|
||||
|
||||
281
landing.php
Normal file
281
landing.php
Normal file
@ -0,0 +1,281 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@date_default_timezone_set('UTC');
|
||||
session_start();
|
||||
|
||||
require_once __DIR__ . '/mail/MailService.php';
|
||||
|
||||
$projectName = $_SERVER['PROJECT_NAME'] ?? 'Northstar Agency';
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$flash = $_SESSION['quote_flash'] ?? null;
|
||||
unset($_SESSION['quote_flash']);
|
||||
|
||||
$form = [
|
||||
'name' => '',
|
||||
'company' => '',
|
||||
'email' => '',
|
||||
'phone' => '',
|
||||
'service' => '',
|
||||
'budget' => '',
|
||||
'timeline' => '',
|
||||
'message' => '',
|
||||
'consent' => '',
|
||||
];
|
||||
$errors = [];
|
||||
|
||||
if (empty($_SESSION['quote_token'])) {
|
||||
$_SESSION['quote_token'] = bin2hex(random_bytes(24));
|
||||
}
|
||||
|
||||
function h(?string $value): string
|
||||
{
|
||||
return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
foreach ($form as $key => $_) {
|
||||
$form[$key] = trim((string)($_POST[$key] ?? ''));
|
||||
}
|
||||
|
||||
$token = (string)($_POST['quote_token'] ?? '');
|
||||
$honeypot = trim((string)($_POST['website'] ?? ''));
|
||||
|
||||
if (!hash_equals($_SESSION['quote_token'], $token)) {
|
||||
$errors['form'] = 'Please refresh the page and try again.';
|
||||
}
|
||||
if ($honeypot !== '') {
|
||||
$errors['form'] = 'We could not process this request.';
|
||||
}
|
||||
if ($form['name'] === '' || strlen($form['name']) < 2) {
|
||||
$errors['name'] = 'Enter your name.';
|
||||
}
|
||||
if ($form['company'] === '') {
|
||||
$errors['company'] = 'Enter your company name.';
|
||||
}
|
||||
if (!filter_var($form['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$errors['email'] = 'Enter a valid work email.';
|
||||
}
|
||||
if ($form['service'] === '') {
|
||||
$errors['service'] = 'Choose a service area.';
|
||||
}
|
||||
if ($form['budget'] === '') {
|
||||
$errors['budget'] = 'Choose an approximate budget.';
|
||||
}
|
||||
if (strlen($form['message']) < 20) {
|
||||
$errors['message'] = 'Share at least 20 characters about the project.';
|
||||
}
|
||||
if ($form['consent'] !== '1') {
|
||||
$errors['consent'] = 'Please confirm we can contact you about this request.';
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
$emailBody = "Company: {$form['company']}\n"
|
||||
. "Phone: {$form['phone']}\n"
|
||||
. "Service: {$form['service']}\n"
|
||||
. "Budget: {$form['budget']}\n"
|
||||
. "Timeline: {$form['timeline']}\n\n"
|
||||
. "Project brief:\n{$form['message']}";
|
||||
|
||||
$result = MailService::sendContactMessage(
|
||||
$form['name'],
|
||||
$form['email'],
|
||||
$emailBody,
|
||||
null,
|
||||
'New agency quote request'
|
||||
);
|
||||
|
||||
if (!empty($result['success'])) {
|
||||
$_SESSION['quote_flash'] = [
|
||||
'type' => 'success',
|
||||
'message' => 'Thanks — your quote request was sent. We will reply with next steps shortly.',
|
||||
];
|
||||
$_SESSION['quote_token'] = bin2hex(random_bytes(24));
|
||||
header('Location: /?quote=sent#quote');
|
||||
exit;
|
||||
}
|
||||
|
||||
error_log('Quote form mail error: ' . ($result['error'] ?? 'unknown'));
|
||||
$errors['form'] = 'The request could not be sent right now. Please try again in a moment.';
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title><?= h($projectName) ?> — Agency Growth & Lead Generation</title>
|
||||
<?php
|
||||
// Read project preview data from environment
|
||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
?>
|
||||
<?php if ($projectDescription): ?>
|
||||
<!-- Meta description -->
|
||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
||||
<!-- Open Graph meta tags -->
|
||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<!-- Twitter meta tags -->
|
||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<?php endif; ?>
|
||||
<?php if ($projectImageUrl): ?>
|
||||
<!-- Open Graph image -->
|
||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<!-- Twitter image -->
|
||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<?php endif; ?>
|
||||
<meta name="robots" content="index, follow" />
|
||||
<meta property="og:title" content="<?= h($projectName) ?> — Agency Growth & Lead Generation" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9Oer+R4ty2fYt4zpgp8+kCxO89H/MOOJ5iYvF0s3yD" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=2025052702">
|
||||
</head>
|
||||
<body class="agency-page">
|
||||
<a class="visually-hidden-focusable skip-link" href="#main">Skip to content</a>
|
||||
|
||||
<header class="site-header sticky-top">
|
||||
<nav class="navbar navbar-expand-lg" aria-label="Primary navigation">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#top" aria-label="<?= h($projectName) ?> home">
|
||||
<span class="brand-mark" aria-hidden="true">N</span><?= h($projectName) ?>
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav" aria-controls="mainNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="mainNav">
|
||||
<ul class="navbar-nav ms-auto align-items-lg-center gap-lg-2">
|
||||
<li class="nav-item"><a class="nav-link" href="#services">Services</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#work">Case studies</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#proof">Proof</a></li>
|
||||
<li class="nav-item"><a class="btn btn-dark btn-sm ms-lg-2" href="#quote">Request quote</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main id="main" tabindex="-1">
|
||||
<section id="top" class="hero-section">
|
||||
<div class="container">
|
||||
<div class="row align-items-center g-4 g-lg-5">
|
||||
<div class="col-lg-7">
|
||||
<p class="eyebrow">Performance-led agency for ambitious teams</p>
|
||||
<h1>Win better leads with a sharper offer, proof, and conversion path.</h1>
|
||||
<p class="hero-copy">We help B2B and service brands turn quiet websites into focused acquisition systems: clear positioning, fast pages, campaign-ready content, and quote forms that route straight to your inbox.</p>
|
||||
<div class="d-flex flex-column flex-sm-row gap-2 mt-4">
|
||||
<a class="btn btn-dark btn-lg" href="#quote">Request a quote</a>
|
||||
<a class="btn btn-outline-dark btn-lg" href="#work">View outcomes</a>
|
||||
</div>
|
||||
<dl class="metric-strip" aria-label="Agency performance highlights">
|
||||
<div><dt>42%</dt><dd>avg. lead lift</dd></div>
|
||||
<div><dt>21 days</dt><dd>launch sprint</dd></div>
|
||||
<div><dt>98</dt><dd>page speed score</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<aside class="offer-card" aria-label="Agency offer summary">
|
||||
<div class="card-label">Core offer</div>
|
||||
<h2>Lead generation audit + landing system</h2>
|
||||
<p>Positioning, service pages, quote flow, analytics events, and post-launch optimization recommendations.</p>
|
||||
<ul class="check-list">
|
||||
<li>Messaging mapped to search intent</li>
|
||||
<li>Conversion-focused page sections</li>
|
||||
<li>Email-ready quote intake workflow</li>
|
||||
</ul>
|
||||
<a href="#quote" class="link-dark fw-semibold">Start with a project brief</a>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="logo-section" aria-labelledby="partner-heading">
|
||||
<div class="container">
|
||||
<h2 id="partner-heading" class="section-kicker">Trusted by teams building category authority</h2>
|
||||
<div class="logo-grid" aria-label="Partner logos">
|
||||
<span>Atlas</span><span>Mercury</span><span>Summit</span><span>Beacon</span><span>Vector</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="services" class="section-pad">
|
||||
<div class="container">
|
||||
<div class="section-head">
|
||||
<p class="eyebrow">Services</p>
|
||||
<h2>Everything a lead-gen site needs, without excess.</h2>
|
||||
<p>Strategy, copy, design, implementation, and measurement packaged into pragmatic delivery tracks.</p>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4"><article class="service-card h-100"><span class="icon-box" aria-hidden="true">01</span><h3>Offer & positioning</h3><p>Clarify the promise, objections, audiences, and proof points that make visitors take action.</p></article></div>
|
||||
<div class="col-md-4"><article class="service-card h-100"><span class="icon-box" aria-hidden="true">02</span><h3>Landing pages</h3><p>Build fast, responsive pages with service detail, case studies, testimonials, and clear CTAs.</p></article></div>
|
||||
<div class="col-md-4"><article class="service-card h-100"><span class="icon-box" aria-hidden="true">03</span><h3>Conversion systems</h3><p>Connect quote forms, email routing, analytics events, and follow-up recommendations.</p></article></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="work" class="section-pad section-muted">
|
||||
<div class="container">
|
||||
<div class="section-head"><p class="eyebrow">Case studies</p><h2>Recent outcomes from focused acquisition work.</h2></div>
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-4"><article class="case-card"><p class="case-meta">SaaS consulting</p><h3>Rebuilt service pages around buying intent.</h3><p>Reduced decision friction with clearer packages, proof blocks, and a shorter quote path.</p><strong>+58% qualified enquiries</strong></article></div>
|
||||
<div class="col-lg-4"><article class="case-card"><p class="case-meta">Professional services</p><h3>Created a fast campaign landing system.</h3><p>Launched reusable pages for paid search and partner referrals in under three weeks.</p><strong>2.4× demo requests</strong></article></div>
|
||||
<div class="col-lg-4"><article class="case-card"><p class="case-meta">Local agency</p><h3>Turned vague traffic into quote conversations.</h3><p>Restructured the homepage around services, objections, testimonials, and contact intent.</p><strong>-31% bounce rate</strong></article></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="proof" class="section-pad">
|
||||
<div class="container">
|
||||
<div class="row g-3 align-items-stretch">
|
||||
<div class="col-lg-5"><div class="section-head sticky-copy"><p class="eyebrow">Testimonials</p><h2>Clear strategy, clean execution, measurable progress.</h2><p>Proof is built into the page so prospects quickly understand what changed and why it matters.</p></div></div>
|
||||
<div class="col-lg-7"><div class="testimonial-stack"><figure class="testimonial-card"><blockquote>“The new site made our value proposition obvious. We started getting better-fit enquiries within the first month.”</blockquote><figcaption>— Maya Chen, Founder at Beacon Advisory</figcaption></figure><figure class="testimonial-card"><blockquote>“They cut the clutter, tightened our proof, and shipped a page we were proud to send prospects to.”</blockquote><figcaption>— Jordan Mills, Growth Lead at Atlas Studio</figcaption></figure></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="quote" class="section-pad section-muted">
|
||||
<div class="container">
|
||||
<div class="row g-4 g-lg-5 align-items-start">
|
||||
<div class="col-lg-5">
|
||||
<p class="eyebrow">Request a quote</p>
|
||||
<h2>Tell us what you want to improve.</h2>
|
||||
<p class="lead-small">Complete the brief and it will be emailed to the configured inbox. We will respond with recommended scope, timeline, and next steps.</p>
|
||||
<div class="notice-box" role="note">This is for testing purposes only — Flatlogic does not guarantee usage of the mail server. Please set up your own SMTP in <code>.env</code> (MAIL_/SMTP_ vars) with our AI Agent.</div>
|
||||
</div>
|
||||
<div class="col-lg-7">
|
||||
<div class="form-panel">
|
||||
<?php if ($flash): ?><div class="alert alert-success" role="status"><?= h($flash['message'] ?? '') ?></div><?php endif; ?>
|
||||
<?php if (!empty($errors['form'])): ?><div class="alert alert-danger" role="alert"><?= h($errors['form']) ?></div><?php endif; ?>
|
||||
<form method="post" action="#quote" id="quoteForm" novalidate>
|
||||
<input type="hidden" name="quote_token" value="<?= h($_SESSION['quote_token']) ?>">
|
||||
<div class="d-none" aria-hidden="true"><label for="website">Website</label><input id="website" name="website" tabindex="-1" autocomplete="off"></div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6"><label class="form-label" for="name">Name</label><input class="form-control <?= isset($errors['name']) ? 'is-invalid' : '' ?>" id="name" name="name" value="<?= h($form['name']) ?>" autocomplete="name" required><div class="invalid-feedback"><?= h($errors['name'] ?? 'Enter your name.') ?></div></div>
|
||||
<div class="col-md-6"><label class="form-label" for="company">Company</label><input class="form-control <?= isset($errors['company']) ? 'is-invalid' : '' ?>" id="company" name="company" value="<?= h($form['company']) ?>" autocomplete="organization" required><div class="invalid-feedback"><?= h($errors['company'] ?? 'Enter your company.') ?></div></div>
|
||||
<div class="col-md-6"><label class="form-label" for="email">Work email</label><input class="form-control <?= isset($errors['email']) ? 'is-invalid' : '' ?>" id="email" type="email" name="email" value="<?= h($form['email']) ?>" autocomplete="email" required><div class="invalid-feedback"><?= h($errors['email'] ?? 'Enter a valid email.') ?></div></div>
|
||||
<div class="col-md-6"><label class="form-label" for="phone">Phone <span class="text-secondary">optional</span></label><input class="form-control" id="phone" name="phone" value="<?= h($form['phone']) ?>" autocomplete="tel"></div>
|
||||
<div class="col-md-6"><label class="form-label" for="service">Service interest</label><select class="form-select <?= isset($errors['service']) ? 'is-invalid' : '' ?>" id="service" name="service" required><option value="">Select one</option><?php foreach (['Offer & positioning', 'Landing page build', 'SEO content system', 'Conversion optimization', 'Full lead-gen sprint'] as $option): ?><option value="<?= h($option) ?>" <?= $form['service'] === $option ? 'selected' : '' ?>><?= h($option) ?></option><?php endforeach; ?></select><div class="invalid-feedback"><?= h($errors['service'] ?? 'Choose a service.') ?></div></div>
|
||||
<div class="col-md-6"><label class="form-label" for="budget">Approx. budget</label><select class="form-select <?= isset($errors['budget']) ? 'is-invalid' : '' ?>" id="budget" name="budget" required><option value="">Select range</option><?php foreach (['Under $5k', '$5k–$10k', '$10k–$25k', '$25k+', 'Not sure yet'] as $option): ?><option value="<?= h($option) ?>" <?= $form['budget'] === $option ? 'selected' : '' ?>><?= h($option) ?></option><?php endforeach; ?></select><div class="invalid-feedback"><?= h($errors['budget'] ?? 'Choose a budget range.') ?></div></div>
|
||||
<div class="col-12"><label class="form-label" for="timeline">Timeline</label><select class="form-select" id="timeline" name="timeline"><option value="">Select timeline</option><?php foreach (['ASAP', 'This month', 'This quarter', 'Planning ahead'] as $option): ?><option value="<?= h($option) ?>" <?= $form['timeline'] === $option ? 'selected' : '' ?>><?= h($option) ?></option><?php endforeach; ?></select></div>
|
||||
<div class="col-12"><label class="form-label" for="message">Project brief</label><textarea class="form-control <?= isset($errors['message']) ? 'is-invalid' : '' ?>" id="message" name="message" rows="5" minlength="20" required placeholder="What should improve? Include goals, audience, current site, or campaign context."><?= h($form['message']) ?></textarea><div class="invalid-feedback"><?= h($errors['message'] ?? 'Share at least 20 characters.') ?></div></div>
|
||||
<div class="col-12"><div class="form-check"><input class="form-check-input <?= isset($errors['consent']) ? 'is-invalid' : '' ?>" type="checkbox" value="1" id="consent" name="consent" <?= $form['consent'] === '1' ? 'checked' : '' ?> required><label class="form-check-label" for="consent">You may contact me about this quote request.</label><div class="invalid-feedback"><?= h($errors['consent'] ?? 'Please confirm consent.') ?></div></div></div>
|
||||
<div class="col-12 d-grid d-sm-flex align-items-center gap-3"><button class="btn btn-dark btn-lg" type="submit">Send quote request</button><span class="form-assurance">Typical reply: 1 business day.</span></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="site-footer"><div class="container d-flex flex-column flex-md-row justify-content-between gap-2"><span>© <?= date('Y') ?> <?= h($projectName) ?>. Built for fast, search-friendly lead generation.</span><span>PHP runtime healthy — <?= h($now) ?> UTC</span></div></footer>
|
||||
|
||||
<?php if ($flash): ?>
|
||||
<div class="toast-container position-fixed bottom-0 end-0 p-3"><div id="quoteToast" class="toast align-items-center text-bg-dark border-0" role="status" aria-live="polite" aria-atomic="true"><div class="d-flex"><div class="toast-body"><?= h($flash['message'] ?? '') ?></div><button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button></div></div></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous" defer></script>
|
||||
<script src="assets/js/main.js?v=2025052702" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user