diff --git a/css/estimates.css b/css/estimates.css new file mode 100644 index 0000000..997df00 --- /dev/null +++ b/css/estimates.css @@ -0,0 +1,519 @@ +/* ---- Pricing page specific styles ---- */ + +/* Mini hero */ +.pricing-hero { + background: linear-gradient(145deg, var(--purple-deep) 0%, var(--purple-mid) 55%, #5B21B6 100%); + position: relative; + overflow: hidden; + padding: 140px 0 100px; + text-align: center; +} +.pricing-hero-content { + position: relative; + z-index: 2; + max-width: 680px; + margin: 0 auto; + padding: 0 24px; +} +.pricing-hero-content .hero-eyebrow { margin-bottom: 16px; } +.pricing-hero-title { + font-family: var(--font-head); + font-size: clamp(2.4rem, 5vw, 3.8rem); + font-weight: 800; + color: var(--white); + line-height: 1.1; + margin-bottom: 20px; +} +.pricing-hero-title span { + background: linear-gradient(135deg, var(--orange), var(--gold)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} +.pricing-hero-lead { + color: rgba(255,255,255,0.7); + font-size: 1.05rem; + line-height: 1.75; +} +.pricing-hero-wave { + position: absolute; + bottom: -1px; left: 0; right: 0; + z-index: 3; + line-height: 0; +} +.pricing-hero-wave svg { display: block; width: 100%; height: 80px; } + +/* Section backgrounds */ +.section-bg-deep { background: #251D70; } +.section-bg-mid { background: #3B2DA8; } + +/* Nav active state */ +.nav-links a.nav-active { + background: rgba(251,191,36,0.15) !important; + border-color: rgba(251,191,36,0.3) !important; + color: var(--gold) !important; +} + +/* Pricing card grid */ +.pricing-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 28px; +} +.pricing-grid--2col { + grid-template-columns: repeat(2, 1fr); + max-width: 800px; + margin: 28px auto 0; +} + +/* Base pricing card */ +.pricing-card { + background: rgba(255,255,255,0.07); + border: 1px solid rgba(255,255,255,0.12); + border-radius: var(--radius); + padding: 36px 32px; + position: relative; + overflow: hidden; + transition: box-shadow var(--transition), border-color var(--transition), background var(--transition); + display: flex; + flex-direction: column; +} +.pricing-card::after { + content: ''; + position: absolute; + bottom: 0; left: 0; right: 0; + height: 3px; + background: linear-gradient(90deg, var(--gold), var(--orange)); + transform: scaleX(0); + transition: transform var(--transition); + transform-origin: left; +} +.pricing-card:hover { + background: rgba(255,255,255,0.11); + border-color: rgba(255,255,255,0.22); + box-shadow: 0 8px 32px rgba(0,0,0,0.25); +} +.pricing-card:hover::after { transform: scaleX(1); } + +/* Popular highlight */ +.pricing-card--popular { + border-color: var(--gold); + background: rgba(251,191,36,0.07); +} +.pricing-card--popular::before { + content: '\2736 Most Popular'; + position: absolute; + top: 16px; right: 16px; + background: linear-gradient(135deg, var(--gold), var(--orange)); + color: var(--white); + font-family: var(--font-head); + font-size: 0.68rem; + font-weight: 700; + letter-spacing: 0.1em; + text-transform: uppercase; + padding: 5px 12px; + border-radius: 50px; +} +.pricing-card--popular:hover { + border-color: var(--gold); + box-shadow: 0 8px 40px rgba(251,191,36,0.18); +} + +/* Card elements */ +.pricing-emoji { + font-size: 2.2rem; + margin-bottom: 14px; + line-height: 1; +} +.pricing-name { + font-family: var(--font-head); + font-size: 1.1rem; + font-weight: 800; + color: var(--white); + margin-bottom: 8px; +} +.pricing-price { + font-family: var(--font-head); + font-size: 1.55rem; + font-weight: 800; + color: var(--gold); + margin-bottom: 16px; +} +.pricing-price span { + font-size: 0.85rem; + font-weight: 500; + color: rgba(255,255,255,0.45); +} +.pricing-divider { + border: none; + border-top: 1px solid rgba(255,255,255,0.12); + margin: 16px 0; +} +.pricing-includes-label { + font-family: var(--font-head); + font-size: 0.68rem; + font-weight: 700; + letter-spacing: 0.15em; + text-transform: uppercase; + color: rgba(255,255,255,0.4); + margin-bottom: 12px; +} +.pricing-includes { + display: flex; + flex-direction: column; + gap: 9px; + margin-bottom: 20px; + flex-grow: 1; +} +.pricing-includes li { + display: flex; + align-items: flex-start; + gap: 10px; + font-size: 0.88rem; + color: rgba(255,255,255,0.75); + line-height: 1.4; +} +.pricing-includes li::before { + content: '\2736'; + color: var(--gold); + font-size: 0.6rem; + flex-shrink: 0; + margin-top: 4px; +} +.pricing-tagline { + font-size: 0.83rem; + color: rgba(255,255,255,0.4); + font-style: italic; + line-height: 1.55; + margin-top: auto; + padding-top: 14px; + border-top: 1px solid rgba(255,255,255,0.08); +} + +/* Wizard's Bench - wide card */ +.bench-card { + background: rgba(255,255,255,0.07); + border: 1px solid rgba(255,255,255,0.12); + border-radius: var(--radius); + padding: 48px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 48px; + align-items: start; + position: relative; + overflow: hidden; + transition: box-shadow var(--transition), background var(--transition); +} +.bench-card::after { + content: ''; + position: absolute; + bottom: 0; left: 0; right: 0; + height: 3px; + background: linear-gradient(90deg, var(--teal), var(--purple-bright)); +} +.bench-card:hover { + background: rgba(255,255,255,0.1); + box-shadow: 0 8px 32px rgba(0,0,0,0.25); +} +.bench-emoji { font-size: 3rem; margin-bottom: 16px; line-height: 1; } +.bench-name { + font-family: var(--font-head); + font-size: 1.5rem; + font-weight: 800; + color: var(--white); + margin-bottom: 10px; +} +.bench-rate { + font-family: var(--font-head); + font-size: 2.8rem; + font-weight: 800; + color: var(--gold); + line-height: 1; + margin-bottom: 8px; +} +.bench-rate span { + font-size: 1rem; + font-weight: 500; + color: rgba(255,255,255,0.45); +} +.bench-desc { + color: rgba(255,255,255,0.6); + font-size: 0.93rem; + line-height: 1.75; + margin-top: 16px; +} + +/* Protection Charms / ward cards */ +.ward-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 28px; +} +.ward-card { + background: rgba(255,255,255,0.07); + border: 1px solid rgba(255,255,255,0.12); + border-radius: var(--radius); + padding: 36px 32px; + position: relative; + overflow: hidden; + transition: box-shadow var(--transition), border-color var(--transition), background var(--transition); +} +.ward-card::after { + content: ''; + position: absolute; + bottom: 0; left: 0; right: 0; + height: 3px; + background: linear-gradient(90deg, var(--gold), var(--orange)); + transform: scaleX(0); + transition: transform var(--transition); + transform-origin: left; +} +.ward-card:hover { + background: rgba(255,255,255,0.11); + box-shadow: 0 8px 32px rgba(0,0,0,0.25); +} +.ward-card:hover::after { transform: scaleX(1); } +.ward-card--mid { + border-color: rgba(124,58,237,0.55); + background: rgba(124,58,237,0.09); +} +.ward-card--top { + border-color: var(--gold); + background: rgba(251,191,36,0.06); +} +.ward-card--top:hover { border-color: var(--gold); } +.ward-tier { + font-family: var(--font-head); + font-size: 0.68rem; + font-weight: 700; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--gold); + margin-bottom: 6px; +} +.ward-name { + font-family: var(--font-head); + font-size: 1.3rem; + font-weight: 800; + color: var(--white); + margin-bottom: 4px; +} +.ward-price { + font-family: var(--font-head); + font-size: 2rem; + font-weight: 800; + color: var(--gold); + line-height: 1.15; + margin-bottom: 20px; +} +.ward-price span { + font-size: 0.85rem; + font-weight: 500; + color: rgba(255,255,255,0.4); +} + +/* Enquire button on each package */ +.pricing-enquire { + margin-top: 18px; + width: 100%; + justify-content: center; + font-size: 0.85rem; + padding: 12px 18px; +} +.bench-enquire { margin-top: 22px; } +.ward-enquire { margin-top: 20px; } + +/* "See full details" trigger */ +.pkg-details-btn { + background: none; + border: none; + cursor: pointer; + color: var(--gold); + font-family: var(--font-head); + font-size: 0.78rem; + font-weight: 700; + letter-spacing: 0.03em; + display: inline-flex; + align-items: center; + gap: 7px; + margin-top: 16px; + padding: 6px 0; + transition: gap var(--transition), color var(--transition); +} +.pkg-details-btn:hover { gap: 11px; color: var(--white); } +.pricing-card, .ward-card, .bench-card { cursor: pointer; } + +/* Package detail modal */ +.pkg-modal-overlay { + position: fixed; + inset: 0; + background: rgba(10,6,30,0.78); + -webkit-backdrop-filter: blur(4px); + backdrop-filter: blur(4px); + display: flex; + align-items: center; + justify-content: center; + padding: 24px; + z-index: 1000; + opacity: 0; + visibility: hidden; + transition: opacity 0.25s ease, visibility 0.25s ease; +} +.pkg-modal-overlay.open { opacity: 1; visibility: visible; } +.pkg-modal { + background: linear-gradient(160deg, #2D1F6E 0%, #1E1550 100%); + border: 1px solid rgba(251,191,36,0.25); + border-radius: var(--radius); + max-width: 560px; + width: 100%; + max-height: 88vh; + overflow-y: auto; + padding: 40px; + position: relative; + box-shadow: 0 24px 70px rgba(0,0,0,0.5); + transform-origin: 50% 50%; + will-change: transform; +} +@media (prefers-reduced-motion: reduce) { + .pkg-modal { transform: none !important; transition: none !important; } +} +.pkg-sparkle { + position: fixed; + z-index: 1100; + pointer-events: none; + line-height: 1; + transform: translate(-50%, -50%); + text-shadow: 0 0 6px rgba(255,255,255,0.4); + will-change: transform, opacity; +} +.pkg-modal-close { + position: absolute; + top: 18px; right: 18px; + width: 38px; height: 38px; + border-radius: 50%; + border: 1px solid rgba(255,255,255,0.18); + background: rgba(255,255,255,0.06); + color: rgba(255,255,255,0.8); + font-size: 1.3rem; + line-height: 1; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s, color 0.2s; +} +.pkg-modal-close:hover { background: rgba(255,255,255,0.14); color: var(--white); } +.pkg-modal-emoji { font-size: 2.4rem; line-height: 1; margin-bottom: 10px; } +.pkg-modal-name { + font-family: var(--font-head); + font-size: 1.6rem; + font-weight: 800; + color: var(--white); + margin-bottom: 4px; + padding-right: 36px; +} +.pkg-modal-price { + font-family: var(--font-head); + font-size: 1.3rem; + font-weight: 800; + color: var(--gold); + margin-bottom: 12px; +} +.pkg-modal-price span { font-size: 0.85rem; font-weight: 500; color: rgba(255,255,255,0.45); } +.pkg-modal-lead { + color: rgba(255,255,255,0.62); + font-size: 0.93rem; + line-height: 1.65; + margin-bottom: 4px; +} +.pkg-modal-divider { + border: none; + border-top: 1px solid rgba(255,255,255,0.12); + margin: 22px 0; +} +.pkg-range { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; +} +.pkg-range-col { + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.1); + border-radius: 14px; + padding: 16px 18px; +} +.pkg-range-col h4 { + font-family: var(--font-head); + font-size: 0.68rem; + font-weight: 700; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--gold); + margin-bottom: 6px; +} +.pkg-range-col .amt { + font-family: var(--font-head); + font-size: 1.15rem; + font-weight: 800; + color: var(--white); + margin-bottom: 10px; +} +.pkg-range-col p { font-size: 0.84rem; color: rgba(255,255,255,0.72); line-height: 1.5; } +.pkg-specs { display: flex; flex-direction: column; } +.pkg-spec { + display: flex; + justify-content: space-between; + gap: 16px; + font-size: 0.9rem; + padding: 11px 0; + border-bottom: 1px solid rgba(255,255,255,0.08); +} +.pkg-spec:last-child { border-bottom: none; } +.pkg-spec .k { color: rgba(255,255,255,0.5); display: flex; align-items: center; gap: 9px; } +.pkg-spec .k i { color: var(--gold); width: 16px; text-align: center; } +.pkg-spec .v { color: var(--white); font-weight: 600; text-align: right; } +.pkg-modal-enquire { margin-top: 26px; } +html.modal-open { overflow: hidden; } +@media (max-width: 520px) { + .pkg-range { grid-template-columns: 1fr; } + .pkg-modal { padding: 30px 22px; } +} + +/* CTA strip */ +.pricing-cta { + background: linear-gradient(145deg, var(--purple-deep) 0%, #2D1860 100%); + padding: 90px 0; + text-align: center; + position: relative; + overflow: hidden; +} +.pricing-cta::before { + content: ''; + position: absolute; + width: 500px; height: 500px; + background: radial-gradient(circle, rgba(124,58,237,0.2) 0%, transparent 70%); + top: -200px; left: 50%; + transform: translateX(-50%); + pointer-events: none; +} +.pricing-cta-inner { + position: relative; + z-index: 1; + max-width: 600px; + margin: 0 auto; + padding: 0 24px; +} +.pricing-cta .section-lead { margin-bottom: 36px; } + +/* Responsive */ +@media (max-width: 900px) { + .pricing-grid { grid-template-columns: 1fr 1fr; } + .pricing-grid--2col { grid-template-columns: 1fr 1fr; max-width: 100%; margin-top: 28px; } + .bench-card { grid-template-columns: 1fr; gap: 28px; padding: 32px; } + .ward-grid { grid-template-columns: 1fr; } +} +@media (max-width: 600px) { + .pricing-grid { grid-template-columns: 1fr; } + .pricing-grid--2col { grid-template-columns: 1fr; } + .bench-rate { font-size: 2rem; } +} diff --git a/css/noscript.css b/css/noscript.css new file mode 100644 index 0000000..6847bfa --- /dev/null +++ b/css/noscript.css @@ -0,0 +1 @@ +.mascot-teleport { opacity: 1; } diff --git a/css/style.css b/css/style.css index 075fe43..563d91e 100644 --- a/css/style.css +++ b/css/style.css @@ -588,6 +588,7 @@ ul { list-style: none; } .service-wide-plants i:nth-child(3n+1) { color: #5EEAD4; } @media (prefers-reduced-motion: reduce) { .service-wide-plants i { transition: opacity 0.25s ease; transform: none; } + .pricing-teaser-astro img { animation: none; } } /* ================================================ @@ -794,9 +795,55 @@ ul { list-style: none; } /* ================================================ PRICING TEASER ================================================ */ -.pricing-teaser { background: #3B2DA8; } -.pricing-teaser .section-header { margin-bottom: 0; } +.pricing-teaser { + background: #3B2DA8; + position: relative; + overflow: hidden; +} +.pricing-teaser::before { + content: ''; + position: absolute; + width: 420px; + height: 420px; + right: 12%; + top: 50%; + transform: translateY(-50%); + background: radial-gradient(circle, rgba(251,191,36,0.16) 0%, transparent 68%); + pointer-events: none; +} +.pricing-teaser-inner { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(180px, 300px); + gap: 48px; + align-items: center; + position: relative; + z-index: 1; +} +.pricing-teaser-copy { + text-align: left; + max-width: 650px; +} +.pricing-teaser-copy .section-lead { + margin: 0; + max-width: 620px; +} .pricing-teaser-btn { margin-top: 32px; } +.pricing-teaser-astro { + display: flex; + justify-content: center; + pointer-events: none; +} +.pricing-teaser-astro img { + width: min(100%, 280px); + height: auto; + filter: drop-shadow(0 18px 30px rgba(0,0,0,0.3)); + transform: rotate(8deg); + animation: astroFloat 5.8s ease-in-out infinite; +} +@keyframes astroFloat { + 0%, 100% { transform: translateY(0) rotate(8deg); } + 50% { transform: translateY(-16px) rotate(11deg); } +} /* ================================================ CONTACT @@ -1007,6 +1054,18 @@ ul { list-style: none; } grid-template-columns: 1fr; gap: 48px; } + .pricing-teaser-inner { + grid-template-columns: 1fr; + gap: 28px; + text-align: center; + } + .pricing-teaser-copy { + text-align: center; + max-width: 700px; + margin: 0 auto; + } + .pricing-teaser-copy .section-lead { margin: 0 auto; } + .pricing-teaser-astro img { width: 210px; } } /* Medium tablets */ @@ -1052,6 +1111,14 @@ ul { list-style: none; } .services-grid { grid-template-columns: 1fr; } .service-wide { flex-direction: column; text-align: center; gap: 20px; padding: 32px 24px; } .service-wide-text p { max-width: none; } + .pricing-teaser::before { + right: 50%; + transform: translate(50%, -50%); + width: 300px; + height: 300px; + } + .pricing-teaser-inner { gap: 22px; } + .pricing-teaser-astro img { width: 150px; } .project-row { grid-template-columns: 110px 1fr auto; gap: 18px; padding: 20px 0; } .project-row-img { height: 80px; } .project-img-placeholder { font-size: 1.8rem; } diff --git a/css/terms.css b/css/terms.css new file mode 100644 index 0000000..40be84d --- /dev/null +++ b/css/terms.css @@ -0,0 +1,106 @@ +/* ---- Terms page specific styles ---- */ +.terms-hero { + background: linear-gradient(145deg, var(--purple-deep) 0%, var(--purple-mid) 55%, #5B21B6 100%); + position: relative; + overflow: hidden; + padding: 140px 0 100px; + text-align: center; +} +.terms-hero-content { + position: relative; + z-index: 2; + max-width: 680px; + margin: 0 auto; + padding: 0 24px; +} +.terms-hero-content .hero-eyebrow { margin-bottom: 16px; } +.terms-hero-title { + font-family: var(--font-head); + font-size: clamp(2.4rem, 5vw, 3.8rem); + font-weight: 800; + color: var(--white); + line-height: 1.1; + margin-bottom: 20px; +} +.terms-hero-title span { + background: linear-gradient(135deg, var(--orange), var(--gold)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} +.terms-hero-lead { + color: rgba(255,255,255,0.7); + font-size: 1.05rem; + line-height: 1.75; +} +.terms-hero-wave { + position: absolute; + bottom: -1px; left: 0; right: 0; + z-index: 3; + line-height: 0; +} +.terms-hero-wave svg { display: block; width: 100%; height: 80px; } + +.terms-body { + max-width: 800px; + margin: 0 auto; + padding: 0 24px; +} +.terms-updated { + display: inline-block; + font-size: 0.82rem; + font-weight: 600; + color: var(--purple-bright); + background: var(--purple-light); + padding: 6px 14px; + border-radius: 999px; + margin-bottom: 40px; +} +.terms-section { margin-bottom: 40px; } +.terms-section h2 { + font-family: var(--font-head); + font-size: 1.45rem; + font-weight: 700; + color: var(--purple-deep); + margin-bottom: 14px; + display: flex; + align-items: baseline; + gap: 12px; +} +.terms-section h2 .terms-num { + font-size: 1rem; + color: var(--orange); + font-weight: 800; +} +.terms-section p { margin-bottom: 14px; line-height: 1.8; color: var(--text); } +.terms-section ul { + list-style: none; + margin: 0 0 14px; + padding: 0; +} +.terms-section ul li { + position: relative; + padding-left: 28px; + margin-bottom: 10px; + line-height: 1.7; +} +.terms-section ul li::before { + content: "\2728"; + position: absolute; + left: 0; + top: 1px; + font-size: 0.85rem; +} +.terms-section a { color: var(--purple-bright); text-decoration: underline; } +.terms-section a:hover { color: var(--orange); } +.terms-note { + background: var(--gray-50); + border: 1px solid var(--gray-200); + border-left: 4px solid var(--orange); + border-radius: var(--radius-sm); + padding: 18px 22px; + margin-top: 50px; + font-size: 0.92rem; + color: var(--gray-600); + line-height: 1.7; +} diff --git a/estimates.php b/estimates.php index bef5290..cde6c68 100644 --- a/estimates.php +++ b/estimates.php @@ -13,525 +13,7 @@ - + @@ -575,7 +57,7 @@ -
+

Website Design

@@ -695,7 +177,7 @@
-
+

Custom Builds

@@ -745,7 +227,7 @@
-
+

Creative Services

@@ -830,7 +312,7 @@
-
+

Ad-hoc Support

@@ -863,7 +345,7 @@
-
+

Ongoing Care

@@ -948,400 +430,6 @@ - + - + \ No newline at end of file diff --git a/img/astrofly.webp b/img/astrofly.webp new file mode 100644 index 0000000..77012e3 Binary files /dev/null and b/img/astrofly.webp differ diff --git a/img/astrofly2.webp b/img/astrofly2.webp new file mode 100644 index 0000000..ac01f67 Binary files /dev/null and b/img/astrofly2.webp differ diff --git a/index.php b/index.php index b62670a..3359206 100644 --- a/index.php +++ b/index.php @@ -19,7 +19,7 @@ $form_error = isset($_GET['error']) && $_GET['error'] === '1'; - + @@ -265,13 +265,18 @@ $form_error = isset($_GET['error']) && $_GET['error'] === '1';
-
-

Transparent Pricing

-

Spells & Pricing

-

From a simple first website to a full ecommerce empire - plus ongoing care plans and ad-hoc tech support. See clear, honest estimates with no hidden fees, and enquire about any package in a click.

- - View Estimates & Packages - +
+
+

Transparent Pricing

+

Spells & Pricing

+

From a simple first website to a full ecommerce empire - plus ongoing care plans and ad-hoc tech support. See clear, honest estimates with no hidden fees, and enquire about any package in a click.

+ + View Estimates & Packages + +
+
diff --git a/js/estimates.js b/js/estimates.js new file mode 100644 index 0000000..79a02df --- /dev/null +++ b/js/estimates.js @@ -0,0 +1,380 @@ +/* ===== Package detail modals ===== */ +(function () { + var DETAILS = { + 'first-spark': { + emoji: '🌱', name: 'The First Spark', price: 'From £250', + lead: 'A clean, professional first website to get your business online quickly and affordably.', + low: { amt: '£250', desc: 'A tidy 1–3 page, template-based site with your branding, a contact form and one round of revisions.' }, + high: { amt: '~£450', desc: 'Up to 5 pages with light customisation, basic SEO setup and a second round of revisions.' }, + specs: [ + { i: 'fa-file-lines', k: 'Pages', v: 'Up to 5' }, + { i: 'fa-rotate', k: 'Revisions', v: '2 rounds' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '1–2 weeks' }, + { i: 'fa-wand-magic-sparkles', k: 'Platform', v: 'WordPress or Squarespace' } + ] + }, + 'enchanted-workshop': { + emoji: '✨', name: 'The Enchanted Workshop', price: '£750 – £1,500', + lead: 'A custom-designed site for businesses ready to stand out and grow their audience.', + low: { amt: '£750', desc: '5–7 pages with a custom design, a blog or news section and social media links.' }, + high: { amt: '£1,500', desc: 'Up to 10 pages with photo galleries, analytics and full search-engine optimisation.' }, + specs: [ + { i: 'fa-file-lines', k: 'Pages', v: '5 – 10' }, + { i: 'fa-rotate', k: 'Revisions', v: '3 rounds' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '2–4 weeks' }, + { i: 'fa-wand-magic-sparkles', k: 'Platform', v: 'WordPress or Squarespace' } + ] + }, + 'arcane-forge': { + emoji: '🔮', name: 'The Arcane Forge', price: '£1,500 – £3,000', + lead: 'Advanced layouts and bespoke functionality for businesses with bigger ambitions.', + low: { amt: '£1,500', desc: '8–10 pages with advanced layouts, enhanced forms and a tailored design.' }, + high: { amt: '£3,000', desc: '12+ pages with custom functionality, third-party integrations, performance tuning and training.' }, + specs: [ + { i: 'fa-file-lines', k: 'Pages', v: '10+' }, + { i: 'fa-rotate', k: 'Revisions', v: 'Unlimited in scope' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '3–5 weeks' }, + { i: 'fa-plug', k: 'Integrations', v: 'Included' } + ] + }, + 'merchants-portal': { + emoji: '🛒', name: "The Merchant's Portal", price: '£3,000 – £5,000', + lead: 'Everything you need to open a fully working online shop.', + low: { amt: '£3,000', desc: 'Shopify or WooCommerce setup with up to ~50 products, payment gateways and shipping.' }, + high: { amt: '£5,000', desc: 'Up to ~200 products with a custom store design, customer accounts and store-management training.' }, + specs: [ + { i: 'fa-box', k: 'Products', v: 'Up to ~200' }, + { i: 'fa-credit-card', k: 'Payments', v: 'Gateways configured' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '4–6 weeks' }, + { i: 'fa-store', k: 'Platform', v: 'Shopify / WooCommerce' } + ] + }, + 'grand-emporium': { + emoji: '⚡', name: 'The Grand Emporium', price: '£5,000 – £7,500+', + lead: 'A digital flagship for established and high-volume retailers.', + low: { amt: '£5,000', desc: 'Multi-category store with subscription products and advanced customer accounts.' }, + high: { amt: '£7,500+', desc: 'Automation and workflows, marketing integrations, bespoke functionality and full launch support.' }, + specs: [ + { i: 'fa-box', k: 'Products', v: 'Unlimited' }, + { i: 'fa-robot', k: 'Automation', v: 'Workflows & marketing' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '6–10 weeks' }, + { i: 'fa-rocket', k: 'Launch support', v: 'Included' } + ] + }, + 'wizards-bench': { + emoji: '🛠️', name: "The Wizard's Bench", price: '£40 / hour', + lead: 'Pay-as-you-go technical support for websites, email and office tech. Minimum one hour; remote sessions carry no call-out charge.', + specs: [ + { i: 'fa-bolt', k: 'What an hour covers', v: 'Fixes, updates, email & DNS tweaks' }, + { i: 'fa-hourglass-half', k: 'Minimum', v: '1 hour' }, + { i: 'fa-house-laptop', k: 'Remote', v: 'No call-out charge' }, + { i: 'fa-location-dot', k: 'On-site', v: 'Oxfordshire area' }, + { i: 'fa-file-invoice', k: 'Larger jobs', v: 'Quoted upfront' } + ] + }, + 'minor-ward': { + emoji: '🛡️', name: 'Minor Ward', price: '£10 / month', + lead: 'Essential upkeep to keep a simple WordPress site safe and current.', + specs: [ + { i: 'fa-arrows-rotate', k: 'Updates', v: 'WordPress core & plugins' }, + { i: 'fa-shield-halved', k: 'Security', v: 'Monitoring' }, + { i: 'fa-database', k: 'Backups', v: 'Monthly' }, + { i: 'fa-headset', k: 'Support time', v: 'Billed at bench rate' }, + { i: 'fa-circle-check', k: 'Best for', v: 'Brochure sites' } + ] + }, + 'greater-ward': { + emoji: '🛡️', name: 'Greater Ward', price: '£25 / month', + lead: 'Everything in Minor Ward, plus proactive checks and priority support for active business sites.', + specs: [ + { i: 'fa-stethoscope', k: 'Health checks', v: 'Monthly' }, + { i: 'fa-bolt', k: 'Support', v: 'Priority email' }, + { i: 'fa-gauge-high', k: 'Performance', v: 'Monitored' }, + { i: 'fa-clock', k: 'Support allowance', v: '~30 mins / month' }, + { i: 'fa-circle-check', k: 'Best for', v: 'Active business sites' } + ] + }, + 'merchants-ward': { + emoji: '🛡️', name: "Merchant's Ward", price: '£50 / month', + lead: 'Everything in Greater Ward, plus ecommerce-grade monitoring and maintenance for online stores.', + specs: [ + { i: 'fa-cart-shopping', k: 'Ecommerce', v: 'Store monitoring' }, + { i: 'fa-screwdriver-wrench', k: 'Maintenance', v: 'Store upkeep' }, + { i: 'fa-bolt', k: 'Response', v: 'Priority' }, + { i: 'fa-clock', k: 'Support allowance', v: '~1 hour / month' }, + { i: 'fa-circle-check', k: 'Best for', v: 'Online stores' } + ] + }, + 'the-cantrip': { + emoji: '⚙️', name: 'The Cantrip', price: '£750 – £2,000', + lead: 'A focused web tool or mini-app, built to handle one job brilliantly.', + low: { amt: '£750', desc: 'A single-purpose tool with a form, a database and a simple admin view.' }, + high: { amt: '£2,000', desc: 'A richer tool with several features, user logins and a tidy dashboard.' }, + specs: [ + { i: 'fa-screwdriver-wrench', k: 'Type', v: 'Web app / tool' }, + { i: 'fa-user', k: 'Accounts', v: 'Optional logins' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '2–5 weeks' }, + { i: 'fa-server', k: 'Hosting', v: 'Set up for you' } + ] + }, + 'grand-working': { + emoji: '🏗️', name: 'The Grand Working', price: '£3,000 – £10,000+', + lead: 'A full custom web application, designed and built around your business.', + low: { amt: '£3,000', desc: 'A focused custom app with accounts, a database and your core features.' }, + high: { amt: '£10,000+', desc: 'A larger platform with integrations, user roles and ongoing support.' }, + specs: [ + { i: 'fa-gears', k: 'Type', v: 'Full custom app' }, + { i: 'fa-users-gear', k: 'Accounts', v: 'Roles & permissions' }, + { i: 'fa-plug', k: 'Integrations', v: 'APIs included' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '6–12 weeks' }, + { i: 'fa-headset', k: 'Support', v: 'Available after launch' } + ] + }, + 'sigil-workshop': { + emoji: '🎨', name: 'The Sigil Workshop', price: 'From £150', + lead: 'Logos, brand kits and graphics that make your business instantly recognisable.', + low: { amt: '£150', desc: 'A standalone logo with two concepts and the final files.' }, + high: { amt: '~£900', desc: 'A full brand kit: logo suite, colour and font system, templates and stationery.' }, + specs: [ + { i: 'fa-lightbulb', k: 'Concepts', v: '2 – 3' }, + { i: 'fa-rotate', k: 'Revisions', v: '3 rounds' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '1–2 weeks' }, + { i: 'fa-file-export', k: 'Formats', v: 'Vector, web & print' } + ] + }, + 'moving-picture': { + emoji: '🎬', name: 'The Moving Picture', price: 'From £350', + lead: 'Filming and editing for promos, events and social media.', + low: { amt: '£350', desc: 'A short edit from footage you provide, with titles and music.' }, + high: { amt: '£1,500+', desc: 'A full filming day on location, plus edit, colour grade and social cut-downs.' }, + specs: [ + { i: 'fa-video', k: 'Filming', v: 'Half or full day' }, + { i: 'fa-rotate', k: 'Revisions', v: '2 rounds' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '1–3 weeks' }, + { i: 'fa-share-nodes', k: 'Delivery', v: 'Web & social formats' } + ] + }, + 'third-dimension': { + emoji: '🧊', name: 'The Third Dimension', price: 'From £300', + lead: '3D models, product renders and animation for the web and video.', + low: { amt: '£300', desc: 'A single 3D model or a polished product render.' }, + high: { amt: '£2,000+', desc: 'A set of models with animated sequences and high-resolution renders.' }, + specs: [ + { i: 'fa-cube', k: 'Output', v: 'Models, renders, animation' }, + { i: 'fa-rotate', k: 'Revisions', v: '2 – 3 rounds' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '1–4 weeks' }, + { i: 'fa-file-export', k: 'Formats', v: 'Web, video & print' } + ] + }, + 'sonic-alchemy': { + emoji: '🎙️', name: 'Sonic Alchemy', price: 'From £200', + lead: 'Editing, mixing and mastering for podcasts, video and adverts.', + low: { amt: '£200', desc: 'Editing and cleanup of a single recording or podcast episode.' }, + high: { amt: '£800+', desc: 'Full podcast or advert production with music, mixing and mastering.' }, + specs: [ + { i: 'fa-sliders', k: 'Services', v: 'Edit, mix, master' }, + { i: 'fa-rotate', k: 'Revisions', v: '2 rounds' }, + { i: 'fa-clock', k: 'Typical turnaround', v: '3–7 days' }, + { i: 'fa-music', k: 'Delivery', v: 'Broadcast-ready files' } + ] + } + }; + + // Build the modal shell once + var overlay = document.createElement('div'); + overlay.className = 'pkg-modal-overlay'; + overlay.innerHTML = + ''; + document.body.appendChild(overlay); + + var modalBox = overlay.querySelector('.pkg-modal'); + var elEmoji = overlay.querySelector('.pkg-modal-emoji'); + var elName = overlay.querySelector('.pkg-modal-name'); + var elPrice = overlay.querySelector('.pkg-modal-price'); + var elLead = overlay.querySelector('.pkg-modal-lead'); + var elBody = overlay.querySelector('.pkg-modal-body'); + var elEnquire = overlay.querySelector('.pkg-modal-enquire'); + var elClose = overlay.querySelector('.pkg-modal-close'); + var lastFocus = null; + + var REDUCED = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; + var SPARKLE_CHARS = ['✦', '✧', '✶', '✩', '✨']; + var SPARKLE_COLORS = ['rgba(255,255,255,1)', 'rgba(251,191,36,1)', 'rgba(253,224,120,1)', 'rgba(249,115,22,0.95)']; + + function dropSparkle(x, y) { + var sp = document.createElement('span'); + sp.className = 'pkg-sparkle'; + var size = (0.5 + Math.random() * 0.9).toFixed(2); + var col = SPARKLE_COLORS[Math.floor(Math.random() * SPARKLE_COLORS.length)]; + sp.textContent = SPARKLE_CHARS[Math.floor(Math.random() * SPARKLE_CHARS.length)]; + sp.style.left = x + 'px'; + sp.style.top = y + 'px'; + sp.style.fontSize = size + 'rem'; + sp.style.color = col; + document.body.appendChild(sp); + var da = Math.random() * Math.PI * 2; + var dd = 8 + Math.random() * 22; + var ddx = (Math.cos(da) * dd).toFixed(0); + var ddy = (Math.sin(da) * dd).toFixed(0); + sp.animate([ + { opacity: 1, transform: 'translate(-50%, -50%) scale(' + size + ') rotate(0deg)' }, + { opacity: 0, transform: 'translate(calc(-50% + ' + ddx + 'px), calc(-50% + ' + ddy + 'px)) scale(' + (size * 0.25).toFixed(2) + ') rotate(120deg)' } + ], { duration: 460 + Math.random() * 300, easing: 'ease-out' }).onfinish = function () { sp.remove(); }; + } + + function edgeSparkles(box, duration) { + var start = null; + function frame(ts) { + if (!start) start = ts; + var p = Math.min((ts - start) / duration, 1); + var r = box.getBoundingClientRect(); + for (var i = 0; i < 2; i++) { + var side = Math.random(), x, y; + if (side < 0.25) { x = r.left + Math.random() * r.width; y = r.top; } + else if (side < 0.5) { x = r.left + Math.random() * r.width; y = r.bottom; } + else if (side < 0.75) { x = r.left; y = r.top + Math.random() * r.height; } + else { x = r.right; y = r.top + Math.random() * r.height; } + dropSparkle(x, y); + } + if (p < 1) requestAnimationFrame(frame); + } + requestAnimationFrame(frame); + } + + function openModal(slug, ox, oy) { + var d = DETAILS[slug]; + if (!d) return; + + elEmoji.textContent = d.emoji; + elName.textContent = d.name; + elPrice.innerHTML = d.price; + elLead.textContent = d.lead; + + var html = ''; + if (d.low && d.high) { + html += '
' + + '

Lower end

' + d.low.amt + '

' + d.low.desc + '

' + + '

Upper end

' + d.high.amt + '

' + d.high.desc + '

' + + '
'; + } + html += '
'; + d.specs.forEach(function (s) { + html += '
' + s.k + '' + s.v + '
'; + }); + html += '
'; + elBody.innerHTML = html; + + elEnquire.setAttribute('href', 'index.php?package=' + slug + '#contact'); + + lastFocus = document.activeElement; + overlay.classList.add('open'); + document.documentElement.classList.add('modal-open'); + modalBox.scrollTop = 0; + + if (!REDUCED) { + var rect = modalBox.getBoundingClientRect(); + var cx = rect.left + rect.width / 2; + var cy = rect.top + rect.height / 2; + if (typeof ox !== 'number') { ox = cx; oy = cy; } + var tx = ox - cx, ty = oy - cy; + var dist = Math.hypot(tx, ty); + var startAng = Math.atan2(ty, tx); + var maxR = Math.max(55, Math.min(dist * 0.5, 120)); + var turns = 1.25; + var duration = 1000; + + var STEPS = 44, frames = []; + for (var i = 0; i <= STEPS; i++) { + var t = i / STEPS; + var g = Math.pow(t, 1.4); + var baseX = tx * (1 - g); + var baseY = ty * (1 - g); + var amp = maxR * Math.sin(Math.PI * Math.pow(t, 0.7)); + var ang = startAng + turns * 2 * Math.PI * t; + var px = baseX + Math.cos(ang) * amp; + var py = baseY + Math.sin(ang) * amp; + var sc = 0.05 + 0.95 * g; + frames.push({ + transform: 'translate(' + px.toFixed(1) + 'px,' + py.toFixed(1) + 'px) scale(' + sc.toFixed(3) + ')', + opacity: t < 0.08 ? (t / 0.08).toFixed(2) : 1 + }); + } + modalBox.animate(frames, { duration: duration, easing: 'linear' }); + + edgeSparkles(modalBox, duration); + } + + elClose.focus(); + } + + function perimeterBurst(r, n) { + var per = 2 * (r.width + r.height); + for (var i = 0; i < n; i++) { + var d = (i / n) * per + (Math.random() - 0.5) * (per / n); + var x, y; + if (d < r.width) { x = r.left + d; y = r.top; } + else if (d < r.width + r.height) { x = r.right; y = r.top + (d - r.width); } + else if (d < 2 * r.width + r.height){ x = r.right - (d - r.width - r.height); y = r.bottom; } + else { x = r.left; y = r.bottom - (d - 2 * r.width - r.height); } + dropSparkle(x, y); + } + } + + function closeModal() { + if (!REDUCED && overlay.classList.contains('open')) { + perimeterBurst(modalBox.getBoundingClientRect(), 48); + } + overlay.classList.remove('open'); + document.documentElement.classList.remove('modal-open'); + if (lastFocus && lastFocus.focus) lastFocus.focus(); + } + + elClose.addEventListener('click', closeModal); + overlay.addEventListener('click', function (e) { + if (e.target === overlay) closeModal(); + }); + document.addEventListener('keydown', function (e) { + if (e.key === 'Escape' && overlay.classList.contains('open')) closeModal(); + }); + + function clickPoint(e, el) { + if (e && e.clientX) return [e.clientX, e.clientY]; + var r = el.getBoundingClientRect(); + return [r.left + r.width / 2, r.top + r.height / 2]; + } + + document.querySelectorAll('a.pricing-enquire, a.bench-enquire, a.ward-enquire').forEach(function (link) { + var query = ((link.getAttribute('href') || '').split('?')[1] || '').split('#')[0]; + var slug = new URLSearchParams(query).get('package'); + if (!slug || !DETAILS[slug]) return; + + var btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'pkg-details-btn'; + btn.innerHTML = ' See full details'; + btn.addEventListener('click', function (e) { + e.preventDefault(); + e.stopPropagation(); + var pt = clickPoint(e, btn); + openModal(slug, pt[0], pt[1]); + }); + link.parentNode.insertBefore(btn, link); + + var card = link.closest('.pricing-card, .bench-card, .ward-card'); + if (card) { + card.addEventListener('click', function (e) { + if (e.target.closest('a, button')) return; + var pt = clickPoint(e, card); + openModal(slug, pt[0], pt[1]); + }); + } + }); +})(); diff --git a/terms.php b/terms.php index f09f0be..4797a9c 100644 --- a/terms.php +++ b/terms.php @@ -13,114 +13,7 @@ - + @@ -240,7 +133,7 @@
- These terms are provided as a friendly, plain-English summary and don't constitute legal advice. For anything business-critical, it's always worth checking with a qualified professional. Got a question? Drop us a line at wizard@fraxle.net. + These terms are provided as a friendly, plain-English summary and don't constitute legal advice. For anything business-critical, it's always worth checking with a qualified professional. Got a question? Drop us a line at wizard@fraxle.net.