Compare commits
36 Commits
2cd537a547
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
cf68c88a34 | ||
|
b2ceb8a33f | ||
|
9680a4936c | ||
|
5056d5f5c7 | ||
|
57e1bb8d9d | ||
|
3c22c88396 | ||
|
264529c428 | ||
|
d1218a67b2 | ||
|
e0d613fc4e | ||
|
680d96c601 | ||
|
e6d1ad1ba7 | ||
|
35ac27b24d | ||
|
1a2acf5f5f | ||
|
111410cc7c | ||
|
8ab7882501 | ||
|
3bc28dc5e6 | ||
|
599b53527e | ||
|
828d7a34c4 | ||
|
37d1b3af57 | ||
|
2db0050f44 | ||
|
f2cdc9cdc2 | ||
|
5cf47eb202 | ||
|
04da9dde0b | ||
|
516b893d6d | ||
|
f18867acc4 | ||
|
94db5fccfc | ||
|
1a6bf78e49 | ||
|
1479492753 | ||
|
e70d594e7f | ||
|
a475dde9be | ||
|
4f3a256158 | ||
|
f0fae1d559 | ||
|
26b42cc4a0 | ||
|
5cdf98c389 | ||
|
13e64304d4 | ||
|
5393f58399 |
@@ -1,8 +1,8 @@
|
|||||||
module.exports = function (eleventyConfig) {
|
module.exports = function (eleventyConfig) {
|
||||||
// ✅ Pass through static assets to the root of output
|
|
||||||
eleventyConfig.addPassthroughCopy({ "src/images": "images" });
|
eleventyConfig.addPassthroughCopy({ "src/images": "images" });
|
||||||
eleventyConfig.addPassthroughCopy({ "src/styles": "styles" });
|
eleventyConfig.addPassthroughCopy({ "src/styles": "styles" });
|
||||||
eleventyConfig.addPassthroughCopy({ "src/scripts": "scripts" });
|
eleventyConfig.addPassthroughCopy({ "src/scripts": "scripts" });
|
||||||
|
eleventyConfig.addPassthroughCopy({ "src/_docs": "_docs" })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dir: {
|
dir: {
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -13,3 +13,6 @@ node_modules/
|
|||||||
# NPM debug logs
|
# NPM debug logs
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
|
|
||||||
|
# Privacy Policy Word Doc
|
||||||
|
_privacy-policy.docx
|
14
README.md
14
README.md
@@ -1,4 +1,8 @@
|
|||||||
# [dlseitz.dev](https://dlseitz.dev/): A Frontend Demonstration
|
# [dlseitz.dev](https://dlseitz.dev/): A Frontend Demonstration
|
||||||
|
<a id="top">​</a>
|
||||||
|
|
||||||
|
To learn more about the backend of this two-part project, check out [**dlseitz.dev - A Backend Demonstration**](https://gitea.dlseitz.dev/dereklseitz/dlseitz.dev-backend/src/branch/refactor-modular-app/README.md)
|
||||||
|
---
|
||||||
|
|
||||||
### Table of Contents
|
### Table of Contents
|
||||||
|
|
||||||
@@ -41,7 +45,7 @@ To solve this, I designed and built a full-stack website from the ground up, lev
|
|||||||
|
|
||||||
This project is a multi-phased initiative designed to serve as both a public portfolio and a long-term business asset. The website is architected like a house, with the main landing page acting as the front door—designed to be simple and approachable. The ["About"](https://dlseitz.dev/about/) page, which includes a contact form for client engagement, functions as the foyer, inviting further conversation and providing a more detailed introduction of myself. Individual projects and demos are planned as separate "rooms" (subdomains), each with its own style and purpose, demonstrating a breadth of skills. This vision is a strategic roadmap to not only showcase a robust technical foundation but also to build a professional brand based on the values of **accessibility**, **equity**, and **transparency**, and a pipeline for future client work.
|
This project is a multi-phased initiative designed to serve as both a public portfolio and a long-term business asset. The website is architected like a house, with the main landing page acting as the front door—designed to be simple and approachable. The ["About"](https://dlseitz.dev/about/) page, which includes a contact form for client engagement, functions as the foyer, inviting further conversation and providing a more detailed introduction of myself. Individual projects and demos are planned as separate "rooms" (subdomains), each with its own style and purpose, demonstrating a breadth of skills. This vision is a strategic roadmap to not only showcase a robust technical foundation but also to build a professional brand based on the values of **accessibility**, **equity**, and **transparency**, and a pipeline for future client work.
|
||||||
|
|
||||||
[Back to Top](#dlseitz.dev-a-frontend-demonstration)
|
[Back to Top](#top)
|
||||||
---
|
---
|
||||||
|
|
||||||
## Design & Accessibility
|
## Design & Accessibility
|
||||||
@@ -65,7 +69,7 @@ The user interface is designed to be clean, professional, and intuitive. Key UI/
|
|||||||
### Overall User Flow
|
### Overall User Flow
|
||||||
The overall design of the site creates a clear and intuitive user flow, guiding potential clients through a strategic journey. The [`Home`](https://dlseitz.dev/) page acts as a point of discovery, introducing the business benefits and services in a scannable format. It then directs the user to the [`About`](https://dlseitz.dev/about/) page, which provides more detailed information and the [contact form](https://dlseitz.dev/about/#contact) to initiate a conversation. This intentional flow from general introduction to specific engagement demonstrates a thoughtful approach to user experience and client conversion.
|
The overall design of the site creates a clear and intuitive user flow, guiding potential clients through a strategic journey. The [`Home`](https://dlseitz.dev/) page acts as a point of discovery, introducing the business benefits and services in a scannable format. It then directs the user to the [`About`](https://dlseitz.dev/about/) page, which provides more detailed information and the [contact form](https://dlseitz.dev/about/#contact) to initiate a conversation. This intentional flow from general introduction to specific engagement demonstrates a thoughtful approach to user experience and client conversion.
|
||||||
|
|
||||||
[Back to Top](#dlseitz.dev-a-frontend-demonstration)
|
[Back to Top](#top)
|
||||||
---
|
---
|
||||||
|
|
||||||
## Website Structure & Functionality
|
## Website Structure & Functionality
|
||||||
@@ -84,7 +88,7 @@ The website is a static, multi-page application with several key features that e
|
|||||||
* **Interactive Accordions:** Custom JavaScript is used to create interactive accordion components that allow for a clean, organized presentation of content. These are used to display professional values on the ["About"](https://dlseitz.dev/about/) page and to list services on the ["Home"](https://dlseitz.dev/) page.
|
* **Interactive Accordions:** Custom JavaScript is used to create interactive accordion components that allow for a clean, organized presentation of content. These are used to display professional values on the ["About"](https://dlseitz.dev/about/) page and to list services on the ["Home"](https://dlseitz.dev/) page.
|
||||||
* **Contact Form:** A detailed and functional contact form is embedded on the ["About"](https://dlseitz.dev/about/#contact) page to facilitate direct client inquiries. The form includes input fields for a user's contact information and a detailed message field, providing a clear path for client engagement.
|
* **Contact Form:** A detailed and functional contact form is embedded on the ["About"](https://dlseitz.dev/about/#contact) page to facilitate direct client inquiries. The form includes input fields for a user's contact information and a detailed message field, providing a clear path for client engagement.
|
||||||
|
|
||||||
[Back to Top](#dlseitz.dev-a-frontend-demonstration)
|
[Back to Top](#top)
|
||||||
---
|
---
|
||||||
|
|
||||||
## Key Technology Decisions
|
## Key Technology Decisions
|
||||||
@@ -106,7 +110,7 @@ To ensure a reliable and predictable user experience, the website utilizes a con
|
|||||||
### Modular CSS Architecture
|
### Modular CSS Architecture
|
||||||
The site's styles are organized into reusable CSS files, such as `base.css` and `modules.css`, to promote a highly modular architecture. This approach ensures that the visual design is not only consistent but also highly maintainable. By separating global styles from component-specific ones, you can easily update the site's design or add new sections in the future without creating code redundancy or breaking the existing layout.
|
The site's styles are organized into reusable CSS files, such as `base.css` and `modules.css`, to promote a highly modular architecture. This approach ensures that the visual design is not only consistent but also highly maintainable. By separating global styles from component-specific ones, you can easily update the site's design or add new sections in the future without creating code redundancy or breaking the existing layout.
|
||||||
|
|
||||||
[Back to Top](#dlseitz.dev-a-frontend-demonstration)
|
[Back to Top](#top)
|
||||||
---
|
---
|
||||||
|
|
||||||
## Issues & Lessons Learned
|
## Issues & Lessons Learned
|
||||||
@@ -117,5 +121,5 @@ One of the primary challenges was bridging the gap between my formal training in
|
|||||||
### Reflections
|
### Reflections
|
||||||
This project has been a valuable exercise that has given me a deeper understanding of the interplay between design principles and development realities. By approaching the project as an **MVP** (Minimum Viable Product), I was able to deliver a professional-grade product in a compressed timeline. This reinforced a key lesson: the most effective solutions are not always the most complex, but are instead those that are grounded in thoughtful planning, resourcefulness, and pragmatism. The project is a testament to the idea that a growth mindset and a commitment to continuous learning can overcome gaps in formal training. It also provided me an opportunity to practice my belief that transparency—as demonstrated in this documentation—is not a sign of weakness, but an act of integrity that invites constructive criticism and fosters continuous improvement.
|
This project has been a valuable exercise that has given me a deeper understanding of the interplay between design principles and development realities. By approaching the project as an **MVP** (Minimum Viable Product), I was able to deliver a professional-grade product in a compressed timeline. This reinforced a key lesson: the most effective solutions are not always the most complex, but are instead those that are grounded in thoughtful planning, resourcefulness, and pragmatism. The project is a testament to the idea that a growth mindset and a commitment to continuous learning can overcome gaps in formal training. It also provided me an opportunity to practice my belief that transparency—as demonstrated in this documentation—is not a sign of weakness, but an act of integrity that invites constructive criticism and fosters continuous improvement.
|
||||||
|
|
||||||
[Back to Top](#dlseitz.dev-a-frontend-demonstration)
|
[Back to Top](#top)
|
||||||
---
|
---
|
1681
package-lock.json
generated
1681
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
@@ -1,27 +1,27 @@
|
|||||||
{
|
{
|
||||||
"name": "dereklseitz.github.io",
|
"name": "dlseitz.dev-frontend",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Portfolio website",
|
"description": "Frontend code for Derek L. Seitz’s personal portfolio and web development services.",
|
||||||
"main": "script.js",
|
"main": "script.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"dev": "npm run clean && npm run start",
|
||||||
"build": "npx @11ty/eleventy",
|
|
||||||
"start": "npx @11ty/eleventy --serve",
|
"start": "npx @11ty/eleventy --serve",
|
||||||
"clean": "rimraf _site",
|
"build": "npx @11ty/eleventy",
|
||||||
"dev": "npm run clean && npm run start"
|
"clean": "rimraf _site"
|
||||||
},
|
},
|
||||||
|
"keywords": ["portfolio", "11ty", "eleventy", "web development", "static site", "frontend", "Derek Seitz"],
|
||||||
|
"author": "Derek L. Seitz",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://dlseitz.dev",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/dereklseitz/dereklseitz.github.io.git"
|
"url": "https://gitea.dlseitz.dev/dereklseitz/dlseitz.dev-frontend.git"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/dereklseitz/dereklseitz.github.io/issues"
|
"url": "https://gitea.dlseitz.dev/dereklseitz/dlseitz.dev-frontend/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/dereklseitz/dereklseitz.github.io#readme",
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@11ty/eleventy": "^3.0.0",
|
||||||
"rimraf": "^6.0.1"
|
"rimraf": "^6.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
src/_data/demos.js
Normal file
55
src/_data/demos.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview This file holds the data for demo cards served on https://dlseitz.dev/demos/
|
||||||
|
*/
|
||||||
|
|
||||||
|
const DEMOS = [
|
||||||
|
{
|
||||||
|
"title": "Bloom Valley Nursery",
|
||||||
|
"id": "bvn",
|
||||||
|
"imageFile": "bloom-valley-nursery-demo.jpg",
|
||||||
|
"altText": "A screenshot of the Bloom Valley Nursery Demo landing page",
|
||||||
|
"description": "This demo is a modern e-commerce website (front end) designed to help a fictional family-owned business expand its reach to a broader online audience. It focuses on clean design, data-driven interactivity, and a personal, community-focused touch.",
|
||||||
|
"demoUrl": "https://bloomvalleydemo.dlseitz.dev",
|
||||||
|
"repoUrl": "https://gitea.dlseitz.dev/dereklseitz/BloomValleyNursery",
|
||||||
|
"techstack": [
|
||||||
|
"11ty",
|
||||||
|
"HTML",
|
||||||
|
"CSS",
|
||||||
|
"JavaScript",
|
||||||
|
"Nunjucks",
|
||||||
|
"Node.js",
|
||||||
|
"Font Awesome",
|
||||||
|
"Zoho Calendar API"
|
||||||
|
],
|
||||||
|
"featuresShort": [
|
||||||
|
"Data-driven content",
|
||||||
|
"Interactive carousels",
|
||||||
|
"Shopping cart functionality",
|
||||||
|
"Customer feedback & newsletter subscription",
|
||||||
|
"Third-party API integration",
|
||||||
|
"Web performance optimizations",
|
||||||
|
"Accessibility features",
|
||||||
|
"Modular design"
|
||||||
|
],
|
||||||
|
"featuresLong": [
|
||||||
|
"Data-driven content for products, promotions, testimonials, and events.",
|
||||||
|
"Interactive carousels on the homepage and gallery to showcase featured items, promotions, and testimonials.",
|
||||||
|
"Shopping cart functionality with temporary session storage.",
|
||||||
|
"Customer feedback form with client-side validation and local storage.",
|
||||||
|
"Newsletter subscription with client-side validation.",
|
||||||
|
"Dynamic integration with the Zoho Calendar API to display community events.",
|
||||||
|
"Responsive design that adapts to various screen sizes.",
|
||||||
|
"Accessibility features, including ARIA labels and semantic HTML.",
|
||||||
|
"Web performance optimizations, such as lazy loading for images.",
|
||||||
|
"Modular code and file structure for improved scalability and maintenance."
|
||||||
|
],
|
||||||
|
"category": "e-commerce",
|
||||||
|
"problemStatement": "To help a small, family-owned and operated business with deep roots in community involvement and public service expand their reach to customers who may prefer shopping online.",
|
||||||
|
"solutionSummary": "This front end site is built to emulate a seamless online shopping experience that captures the fictional brand's community-focused story. The design prioritizes accessibility, visual harmony, and usability, while the data-driven functionality allows for a scalable and easily updatable web application.",
|
||||||
|
"isLive": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
DEMOS
|
||||||
|
};
|
BIN
src/_docs/_privacy-policy.pdf
Normal file
BIN
src/_docs/_privacy-policy.pdf
Normal file
Binary file not shown.
@@ -13,14 +13,16 @@
|
|||||||
<link rel="stylesheet" href="/styles/header-footer.css">
|
<link rel="stylesheet" href="/styles/header-footer.css">
|
||||||
<link rel="stylesheet" href="{{ stylesheet }}">
|
<link rel="stylesheet" href="{{ stylesheet }}">
|
||||||
|
|
||||||
|
|
||||||
{% if hCAPTCHA %}
|
{% if hCAPTCHA %}
|
||||||
<script src="{{ hCAPTCHA }}" async defer></script>
|
<script src="{{ hCAPTCHA }}" async defer></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!-- <a href="https://www.svgbackgrounds.com/set/free-svg-backgrounds-and-patterns/">Free SVG Backgrounds and Patterns by SVGBackgrounds.com</a> -->
|
||||||
|
|
||||||
{% include "header.html" %}
|
{% include "header.njk" %}
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
@@ -28,9 +30,7 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{% include "footer.html" %}
|
{% include "footer.njk" %}
|
||||||
|
|
||||||
<!-- <a href="https://www.svgbackgrounds.com/set/free-svg-backgrounds-and-patterns/">Free SVG Backgrounds and Patterns by SVGBackgrounds.com</a> -->
|
|
||||||
|
|
||||||
{% if pageScripts %}
|
{% if pageScripts %}
|
||||||
{% for script in pageScripts %}
|
{% for script in pageScripts %}
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
<footer>
|
<footer>
|
||||||
<ul class="social-links">
|
<ul class="social-links">
|
||||||
<li class="linkedin"><a href="https://linkedin.com/in/dereklseitz" target="_blank">Connect on LinkedIn</a></li>
|
<li class="linkedin"><a href="https://linkedin.com/in/dereklseitz" target="_blank" rel="noopener noreferrer"
|
||||||
<li class="gitea"><a href="https://git.dsnet.pro/dereklseitz" target="_blank">My Project Repos</a></li>
|
>Connect on LinkedIn</a></li>
|
||||||
|
<li class="gitea"><a href="https://gitea.dlseitz.dev/dereklseitz" target="_blank" rel="noopener noreferrer"
|
||||||
|
>My Project Repos</a></li>
|
||||||
|
<li class="campfire"><a href="https://campfire.dlseitz.dev" target=_blank" rel="noopener noreferrer">Campfire Logs</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<nav aria-label="Footer navigation">
|
<nav aria-label="Footer navigation">
|
||||||
@@ -11,6 +14,8 @@
|
|||||||
<li><a href="/about/">About</a></li>
|
<li><a href="/about/">About</a></li>
|
||||||
<li><a href="/demos/">Demos</a></li>
|
<li><a href="/demos/">Demos</a></li>
|
||||||
<li><a href="/about/#contact">Contact</a></li>
|
<li><a href="/about/#contact">Contact</a></li>
|
||||||
|
<li><a href="/privacy-policy/" target="_blank" rel="noopener noreferrer"
|
||||||
|
>Privacy Policy</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
@@ -1,12 +1,15 @@
|
|||||||
<header class="main-header">
|
<header class="main-header top">
|
||||||
|
|
||||||
<nav class="main-nav">
|
<nav class="main-nav">
|
||||||
|
|
||||||
<ul class="nav-list">
|
<ul class="nav-list">
|
||||||
<li class="nav-item nav-logo"><a href="/">Derek L. Seitz</a></li>
|
<li class="nav-item nav-logo"><a href="/">Derek L. Seitz</a></li>
|
||||||
<li class="nav-item nav-about"><a href="/about/">About</a></li>
|
<li class="nav-item nav-about"><a href="/about/">About</a></li>
|
||||||
<li class="nav-item nav-demos"><a href="/demos/">Demos</a></li>
|
<li class="nav-item nav-demos"><a href="/demos/">Demos</a></li>
|
||||||
<li class="nav-item nav-contact"><a href="/about/#contact">Contact</a></li>
|
<li class="nav-item nav-contact"><a href="/about/#contact">Contact</a></li>
|
||||||
|
<li class="nav-item nav-blog"><a href="https://campfire.dlseitz.dev" target="_blank" rel="noopener noreferrer"
|
||||||
|
>Blog</a></li>
|
||||||
|
<li class="nav-item nav-repos"><a href="https://gitea.dlseitz.dev" target="_blank" rel="noopener noreferrer"
|
||||||
|
>My Repos</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</nav>
|
</nav>
|
@@ -108,15 +108,25 @@ pageScripts:
|
|||||||
<fieldset class="message-field">
|
<fieldset class="message-field">
|
||||||
<legend>Message</legend>
|
<legend>Message</legend>
|
||||||
<label for="message">Questions or Feedback</label>
|
<label for="message">Questions or Feedback</label>
|
||||||
<textarea id="message" name="message" rows="15" placeholder="What questions or feedback do you have for me?" required aria-describedby="message-error"></textarea>
|
<textarea id="message" name="message" rows="10" placeholder="What questions or feedback do you have for me?" required aria-describedby="message-error"></textarea>
|
||||||
<span class="error-message" id="message-error" aria-live="polite"></span>
|
<span class="error-message" id="message-error" aria-live="polite"></span>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<div class="checks">
|
||||||
|
<div class="h-captcha" data-sitekey="b63e5b64-c6f2-4154-b5a6-77169a924022"></div>
|
||||||
|
|
||||||
|
<div id="privacy" class="consent-statement">
|
||||||
|
<p>By clicking "Send Message" below, you <strong>accept and agree to</strong> this site's <a href="../privacy-policy/" target="_blank" rel="noopener noreferrer">Privacy Policy</a>.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="submit-reset">
|
<div class="submit-reset">
|
||||||
<button type="submit">Send Message</button>
|
<button type="submit">Send Message</button>
|
||||||
<button type="reset">Reset Form</button>
|
<button type="reset">Reset Form</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="honeypot-field" aria-hidden="true">
|
<div class="honeypot-field" aria-hidden="true">
|
||||||
<label for="url">Website URL</label>
|
<label for="url">Website URL</label>
|
||||||
<input type="text" name="url" id="url" autocomplete="off" tabindex="-1">
|
<input type="text" name="url" id="url" autocomplete="off" tabindex="-1">
|
||||||
|
@@ -6,4 +6,23 @@ stylesheet: /styles/demos.css
|
|||||||
isLandingPage: false
|
isLandingPage: false
|
||||||
---
|
---
|
||||||
|
|
||||||
<h1>Demos Coming Soon!</h1>
|
<h1>Solutions I've Built</h1>
|
||||||
|
{% for demo in demos.DEMOS %}
|
||||||
|
<article id="demo-{{ demo.id }}" class="{{ demo.id }}-demo-card" aria-labelledby="demo-title-{{ demo.id }}">
|
||||||
|
<div class="{{ demo.id }}-demo module">
|
||||||
|
<h2 id="demo-title-{{ demo.id }}" class="demo-title">{{ demo.title }}</h2>
|
||||||
|
<img class="demo-image" src="/images/_demo-thumbs/{{ demo.imageFile }}" alt="{{ demo.altText }}">
|
||||||
|
<p class="demo-description">{{ demo.description}}</p>
|
||||||
|
<h3>Business Problem</h3>
|
||||||
|
<p class="demo-problem">{{ demo.problemStatement }}</p>
|
||||||
|
<h3>Solution</h3>
|
||||||
|
<p class="demo-solution">{{ demo.solutionSummary }}</p>
|
||||||
|
{% if demo.isLive === false %}
|
||||||
|
<p class="coming-soon">Check back soon for full access to this demo!</p>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ demo.demoUrl }}" class="demo-link" target="_blank" rel="noopener noreferrer">Access the live demo here!</a>
|
||||||
|
{% endif %}
|
||||||
|
<a href="{{ demo.repoUrl }}" class="demo-repo" target="_blank" rel="noopener noreferrer">View Demo's Source Code</a>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
{% endfor %}
|
BIN
src/images/_demo-thumbs/bloom-valley-nursery-demo.jpg
Normal file
BIN
src/images/_demo-thumbs/bloom-valley-nursery-demo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 245 KiB |
@@ -2,7 +2,7 @@
|
|||||||
layout: base.njk
|
layout: base.njk
|
||||||
metaDesc: "Elevate your business with a custom, high-quality website. Derek L. Seitz provides professional web design and development to help you grow your online presence."
|
metaDesc: "Elevate your business with a custom, high-quality website. Derek L. Seitz provides professional web design and development to help you grow your online presence."
|
||||||
title: "Derek L. Seitz - Portfolio"
|
title: "Derek L. Seitz - Portfolio"
|
||||||
stylesheet: styles/index.css
|
stylesheet: /styles/index.css
|
||||||
isLandingPage: true
|
isLandingPage: true
|
||||||
pageScripts:
|
pageScripts:
|
||||||
- "/scripts/benefits.js"
|
- "/scripts/benefits.js"
|
||||||
@@ -10,7 +10,7 @@ pageScripts:
|
|||||||
---
|
---
|
||||||
|
|
||||||
<!-- ↓ Start Intro Module ↓ -->
|
<!-- ↓ Start Intro Module ↓ -->
|
||||||
<div id="top"></div>
|
|
||||||
<div class="intro module">
|
<div class="intro module">
|
||||||
<h1>Grow Your Online Presence with Me, <span class="accent-name">Derek L. Seitz</span></h1>
|
<h1>Grow Your Online Presence with Me, <span class="accent-name">Derek L. Seitz</span></h1>
|
||||||
<p>A great website is often your most powerful sales tool. It's the first impression you make and the cornerstone of your online presence.</p>
|
<p>A great website is often your most powerful sales tool. It's the first impression you make and the cornerstone of your online presence.</p>
|
||||||
@@ -61,12 +61,12 @@ pageScripts:
|
|||||||
|
|
||||||
<div class="transition">
|
<div class="transition">
|
||||||
<p>Tackling these areas yourself can demand a huge amount of your time. This is where I come in.</p>
|
<p>Tackling these areas yourself can demand a huge amount of your time. This is where I come in.</p>
|
||||||
<p>Trusting me to focus on getting your website noticed, you can instead focus on what makes your business thrive: the people and communities you serve.</p>
|
<p>Trusting me to focus on getting your website noticed, you can instead focus on what makes your business thrive: <br><span class="thrive">the people and communities you serve</span>.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ↓ Start Services Module ↓ -->
|
<!-- ↓ Start Services Module ↓ -->
|
||||||
<divid="services-section" class="services-section module">
|
<div id="services-section" class="services-section module">
|
||||||
<div class="accordion-container">
|
<div class="accordion-container">
|
||||||
<h2>How I Can Help</h2>
|
<h2>How I Can Help</h2>
|
||||||
<p>Click each button below to see ways I can help!</p>
|
<p>Click each button below to see ways I can help!</p>
|
||||||
|
124
src/privacy-policy.njk
Normal file
124
src/privacy-policy.njk
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
---
|
||||||
|
layout: base.njk
|
||||||
|
metaDesc: "Your privacy is my priority. This policy explains how I securely handle your contact information, what I use it for, and your rights to access or delete your data."
|
||||||
|
title: "Derek L. Seitz - Privacy Policy"
|
||||||
|
stylesheet: "/styles/privacy.css"
|
||||||
|
isLandingPage: false
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="module">
|
||||||
|
<h1>Privacy Policy - dlseitz.dev</h1>
|
||||||
|
|
||||||
|
<strong>Last updated: September 7, 2025</strong>
|
||||||
|
|
||||||
|
<p>This <strong>Privacy Policy</strong> describes my policies and procedures on the collection and use of your information when you use my Service. I use your personal data to communicate with you regarding your inquiries.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div id="toc" class="toc">
|
||||||
|
<h2>Table of Contents</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#definitions">Interpretation and Definitions</a></li>
|
||||||
|
<li><a href="#data-collection">What Information I Collect</a></li>
|
||||||
|
<li><a href="#data-use">How I Use Your Personal Data</a></li>
|
||||||
|
<li><a href="#no-tracking">No Cookies or Tracking</a></li>
|
||||||
|
<li><a href="#data-retention">How Long I Keep Your Information</a></li>
|
||||||
|
<li><a href="#data-protection">How I Protect Your Information</a></li>
|
||||||
|
<li><a href="#privacy-rights">Your Privacy Rights</a></li>
|
||||||
|
<li><a href="#policy-changes">Changes to This Privacy Policy</a></li>
|
||||||
|
<li><a href="#contact">How to Contact Me</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<section id="definitions">
|
||||||
|
<h2>Interpretation and Definitions</h2>
|
||||||
|
<p>For the purposes of this Privacy Policy:</p>
|
||||||
|
<p><strong>"I"</strong>, <strong>"me"</strong>, or <strong>"my"</strong> refers to <strong>Derek L. Seitz</strong>.<br>
|
||||||
|
<p><strong>"Country"</strong> refers to: <strong>Arkansas, United States</strong>.<br>
|
||||||
|
<p><strong>"Personal Data"</strong> is any information that relates to an identified or identifiable individual.<br>
|
||||||
|
<p><strong>"Service(s)"</strong> refers to the <strong>"Website"</strong> and all related services I offer, including client consultation, project discovery, and web development services.<br>
|
||||||
|
<p><strong>"Website"</strong> refers to <strong>Derek L. Seitz</strong>, accessible from <a href="https://dlseitz.dev">https://dlseitz.dev</a>.<br>
|
||||||
|
<p><strong>"You"</strong> or <strong>"Your"</strong> means the individual accessing or using the <strong>"Service"</strong>.<br>
|
||||||
|
</section>
|
||||||
|
<a class="back-to-top" href="./#top" aria-label="Back to top of page">Back to Top</a>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<section id="data-collection">
|
||||||
|
<h2>What Information I Collect</h2>
|
||||||
|
<p>I collect information that you voluntarily provide to me when you express an interest in obtaining information about my Services or otherwise contact me. The personal information I collect includes:</p>
|
||||||
|
<ul class="data-collected">
|
||||||
|
<li>First name and last name</li>
|
||||||
|
<li>Phone number</li>
|
||||||
|
<li>Email address</li>
|
||||||
|
<li>Preferred contact method</li>
|
||||||
|
<li>Organization</li>
|
||||||
|
<li>Your message</li>
|
||||||
|
</ul>
|
||||||
|
<p>I may also collect certain technical information automatically, such as the date and time when a form is submitted, for the purpose of diagnostics and usage analysis.</p>
|
||||||
|
<p class="highlight-statement"><strong>I do not collect any information from third parties.<br>
|
||||||
|
I do not collect or process sensitive personal information.</strong></p>
|
||||||
|
</section>
|
||||||
|
<a class="back-to-top" href="./#top" aria-label="Back to top of page">Back to Top</a>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<section id="data-use">
|
||||||
|
<h2>How I Use Your Personal Data</h2>
|
||||||
|
<p>I process your personal information for a variety of reasons, including:</p>
|
||||||
|
<ul>
|
||||||
|
<li>To respond to inquiries and provide support</li>
|
||||||
|
<li>To deliver and facilitate the services you request</li>
|
||||||
|
<li>To maintain records of communication for continuity</li>
|
||||||
|
<li>To prevent spam or abuse</li>
|
||||||
|
<li>To comply with legal obligations, if necessary</li>
|
||||||
|
</ul>
|
||||||
|
<p><strong>I do not sell, rent, or share your personal information with any third parties.</strong> I may disclose information only when required by law (such as a subpoena or legal process).</p>
|
||||||
|
</section>
|
||||||
|
<section id="no-tracking">
|
||||||
|
<h2>No Cookies or Tracking</h2>
|
||||||
|
<p>My website does not use cookies, tracking scripts, or analytics services. Your visit to my site is not monitored or tracked.</p>
|
||||||
|
</section>
|
||||||
|
<section id="data-retention">
|
||||||
|
<h2>How Long I Keep Your Information</h2>
|
||||||
|
<p>I will only keep your personal information for as long as is necessary for the purposes described in this Privacy Policy. No purpose in this notice will require me to keep your personal information for longer than 1 year, unless required for legal purposes.</p>
|
||||||
|
<p>When I no longer have a legitimate reason to process your data, I will delete it or securely store it until it can be deleted.</p>
|
||||||
|
</section>
|
||||||
|
<section id="data-protection">
|
||||||
|
<h2>How I Protect Your Information</h2>
|
||||||
|
<p>I have implemented reasonable technical and organizational security measures to protect your personal data. A <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy" target="_blank" rel="noopener noreferrer">Content Security Policy (CSP)</a> is used to ensure your submitted data is only ever sent to my server, protecting it from being redirected to any other location. Your information is transmitted from the contact form using <a href="https://developers.google.com/search/docs/crawling-indexing/https" target="_blank" rel="noopener noreferrer">HTTPS encryption</a>, which is enforced by default on this .dev domain.</p>
|
||||||
|
<p>Submitted data undergoes multiple security checks to prevent spam and abuse, including the use of <a href="https://www.hcaptcha.com/" target="_blank" rel="noopener noreferrer">hCaptcha</a> and rate limiting to verify the user is a human and minimize the risk of unauthorized access to stored data. The data is also validated and sanitized to ensure its integrity before it is stored in my database.</p>
|
||||||
|
<p>However, security is an ongoing practice, and no method of electronic transmission or storage is ever absolutely secure. While I strive to protect your data, I cannot guarantee its absolute security.</p>
|
||||||
|
</section>
|
||||||
|
<a class="back-to-top" href="./#top" aria-label="Back to top of page">Back to Top</a>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<section id="privacy-rights">
|
||||||
|
<h2>Your Privacy Rights</h2>
|
||||||
|
<p>You have the right to:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Request access to the personal data I hold about you</li>
|
||||||
|
<li>Request corrections to inaccurate information</li>
|
||||||
|
<li>Request deletion of your personal data</li>
|
||||||
|
</ul>
|
||||||
|
<p>If I decline your request for legal or other reasons, you may contact me to appeal the decision. I will respond with the reason for my decision.</p>
|
||||||
|
</section>
|
||||||
|
<section id="policy-changes">
|
||||||
|
<h2>Changes to This Privacy Policy</h2>
|
||||||
|
<p>I may update this Privacy Policy from time to time. When I do, I will update the "Last updated" date at the top of this page. If I make material changes, I will post a notice on the Website. I encourage you to review this policy periodically to stay informed.</p>
|
||||||
|
</section>
|
||||||
|
<section id="contact">
|
||||||
|
<h2>How to Contact Me</h2>
|
||||||
|
<p>If you have any questions about this Privacy Policy or wish to exercise your privacy rights, you can contact me:</p>
|
||||||
|
<ul>
|
||||||
|
<li>By email: <a href="mailto:contact@dlseitz.dev">contact@dlseitz.dev</a></li>
|
||||||
|
<li>Or via the contact form on my website: <a href="https://dlseitz.dev/about/#contact" target="_blank" rel="noopener noreferrer">https://dlseitz.dev/about/#contact</a></li>
|
||||||
|
</ul>
|
||||||
|
<p>I aim to respond to all privacy-related requests within 5 business days.</p>
|
||||||
|
</section>
|
||||||
|
<a class="back-to-top" href="./#top" aria-label="Back to top of page">Back to Top</a>
|
||||||
|
</div>
|
||||||
|
<a class="download" href="/_docs/_privacy-policy.pdf" download>Download Privacy Policy</a>
|
@@ -3,6 +3,30 @@
|
|||||||
const form = document.getElementById("contact-form");
|
const form = document.getElementById("contact-form");
|
||||||
const resetButton = form.querySelector('button[type="reset"]');
|
const resetButton = form.querySelector('button[type="reset"]');
|
||||||
|
|
||||||
|
// Add a div for non-blocking messages
|
||||||
|
const messageDiv = document.createElement('div');
|
||||||
|
messageDiv.id = 'form-message';
|
||||||
|
messageDiv.style.display = 'none';
|
||||||
|
messageDiv.style.padding = '10px';
|
||||||
|
messageDiv.style.marginTop = '10px';
|
||||||
|
messageDiv.style.border = '1px solid';
|
||||||
|
form.parentNode.insertBefore(messageDiv, form);
|
||||||
|
|
||||||
|
|
||||||
|
// Utility: Show a message to the user
|
||||||
|
function showMessage(text, isError = false) {
|
||||||
|
messageDiv.textContent = text;
|
||||||
|
messageDiv.style.display = 'block';
|
||||||
|
if (isError) {
|
||||||
|
messageDiv.style.backgroundColor = '#f8d7da';
|
||||||
|
messageDiv.style.borderColor = '#f5c6cb';
|
||||||
|
messageDiv.style.color = '#721c24';
|
||||||
|
} else {
|
||||||
|
messageDiv.style.backgroundColor = '#d4edda';
|
||||||
|
messageDiv.style.borderColor = '#c3e6cb';
|
||||||
|
messageDiv.style.color = '#155724';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Utility: Show error for specific input
|
// Utility: Show error for specific input
|
||||||
function showError(inputId, message) {
|
function showError(inputId, message) {
|
||||||
@@ -12,10 +36,12 @@ function showError(inputId, message) {
|
|||||||
if (errorSpan) errorSpan.textContent = message;
|
if (errorSpan) errorSpan.textContent = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility: Clear all errors
|
// Utility: Clear all errors and messages
|
||||||
function clearErrors() {
|
function clearErrors() {
|
||||||
document.querySelectorAll(".error-message").forEach(span => span.textContent = "");
|
document.querySelectorAll(".error-message").forEach(span => span.textContent = "");
|
||||||
document.querySelectorAll("input, textarea").forEach(input => input.classList.remove("error"));
|
document.querySelectorAll("input, textarea").forEach(input => input.classList.remove("error"));
|
||||||
|
messageDiv.style.display = 'none';
|
||||||
|
messageDiv.textContent = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
form.addEventListener("submit", function(event) {
|
form.addEventListener("submit", function(event) {
|
||||||
@@ -24,15 +50,11 @@ form.addEventListener("submit", function(event) {
|
|||||||
clearErrors(); // Clear previous errors
|
clearErrors(); // Clear previous errors
|
||||||
|
|
||||||
const honeypotField = document.getElementById("url").value.trim();
|
const honeypotField = document.getElementById("url").value.trim();
|
||||||
// Add the honeypot check at the top
|
|
||||||
if (honeypotField.length > 0) {
|
if (honeypotField.length > 0) {
|
||||||
console.warn("Honeypot field was filled. Blocking submission.");
|
console.warn("Honeypot field was filled. Blocking submission.");
|
||||||
// You might want to display a message to the user,
|
return;
|
||||||
// but it's often better to fail silently to not alert the bot.
|
|
||||||
return; // This is the most important part: stop the function here.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get values
|
|
||||||
const firstName = document.getElementById("first-name").value.trim();
|
const firstName = document.getElementById("first-name").value.trim();
|
||||||
const lastName = document.getElementById("last-name").value.trim();
|
const lastName = document.getElementById("last-name").value.trim();
|
||||||
const organization = document.getElementById("organization").value.trim();
|
const organization = document.getElementById("organization").value.trim();
|
||||||
@@ -43,7 +65,6 @@ form.addEventListener("submit", function(event) {
|
|||||||
|
|
||||||
let hasErrors = false;
|
let hasErrors = false;
|
||||||
|
|
||||||
// First Name
|
|
||||||
if (!firstName) {
|
if (!firstName) {
|
||||||
showError("first-name", "Please enter your first name.");
|
showError("first-name", "Please enter your first name.");
|
||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
@@ -52,7 +73,6 @@ form.addEventListener("submit", function(event) {
|
|||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last Name
|
|
||||||
if (!lastName) {
|
if (!lastName) {
|
||||||
showError("last-name", "Please enter your last name.");
|
showError("last-name", "Please enter your last name.");
|
||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
@@ -67,72 +87,76 @@ form.addEventListener("submit", function(event) {
|
|||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Email
|
|
||||||
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
if (!emailPattern.test(email)) {
|
if (!emailPattern.test(email)) {
|
||||||
showError("email", "Please enter a valid email address.");
|
showError("email", "Please enter a valid email address.");
|
||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phone — match format: 123-456-7890
|
|
||||||
const phonePattern = /^(\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4})$/;
|
const phonePattern = /^(\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4})$/;
|
||||||
if (!phonePattern.test(phone)) {
|
if (!phonePattern.test(phone)) {
|
||||||
showError("phone", "Phone number must be in the format 123-456-7890.");
|
showError("phone", "Phone number must be in the format 123-456-7890.");
|
||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message
|
|
||||||
if (message.length < 10) {
|
if (message.length < 10) {
|
||||||
showError("message", "Message must be at least 10 characters long.");
|
showError("message", "Message must be at least 10 characters long.");
|
||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasErrors) {
|
const hCaptchaResponse = hcaptcha.getResponse();
|
||||||
// Package the form data into an object
|
// Check for hCaptcha token
|
||||||
const formData = {
|
if (!hCaptchaResponse) {
|
||||||
firstName: firstName,
|
showMessage("Please complete the CAPTCHA.", true);
|
||||||
lastName: lastName,
|
hasErrors = true;
|
||||||
organization: organization,
|
}
|
||||||
email: email,
|
|
||||||
phone: phone,
|
|
||||||
contactMethod: contactMethod,
|
|
||||||
message: message,
|
|
||||||
url: honeypotField,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send the data to the backend using fetch()
|
if (!hasErrors) {
|
||||||
fetch('/api/submit-form', {
|
// Package the form data, including the hCaptcha token
|
||||||
method: 'POST',
|
const formData = {
|
||||||
headers: {
|
firstName: firstName,
|
||||||
'Content-Type': 'application/json',
|
lastName: lastName,
|
||||||
},
|
organization: organization,
|
||||||
body: JSON.stringify(formData), // Convert the data object to a JSON string
|
email: email,
|
||||||
})
|
phone: phone,
|
||||||
.then(response => {
|
contactMethod: contactMethod,
|
||||||
if (response.ok) {
|
message: message,
|
||||||
return response.json(); // Parse the JSON response
|
url: honeypotField,
|
||||||
}
|
hCaptchaResponse: hCaptchaResponse,
|
||||||
throw new Error('Network response was not ok.');
|
};
|
||||||
})
|
|
||||||
.then(data => {
|
// Send the data to the backend using fetch()
|
||||||
// Success: handle the server's response
|
fetch('/api/submit-form', {
|
||||||
console.log('Success:', data);
|
method: 'POST',
|
||||||
alert('Form submitted successfully!');
|
headers: {
|
||||||
form.reset(); // Optionally, reset the form after successful submission
|
'Content-Type': 'application/json',
|
||||||
})
|
},
|
||||||
.catch((error) => {
|
body: JSON.stringify(formData),
|
||||||
// Error: handle any network or server errors
|
})
|
||||||
console.error('Error:', error);
|
.then(response => {
|
||||||
alert('An error occurred during submission. Please try again.');
|
if (response.ok) {
|
||||||
});
|
return response.json();
|
||||||
}
|
}
|
||||||
|
throw new Error('Network response was not ok.');
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log('Success:', data);
|
||||||
|
showMessage('Form submitted successfully!', false);
|
||||||
|
form.reset();
|
||||||
|
hcaptcha.reset();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
showMessage('An error occurred during submission. Please try again.', true);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
form.addEventListener("reset", function (event) {
|
form.addEventListener("reset", function (event) {
|
||||||
const confirmed = confirm("Are you sure you want to clear the form?");
|
const confirmed = window.confirm("Are you sure you want to clear the form?");
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clearErrors();
|
clearErrors();
|
||||||
});
|
});
|
@@ -205,6 +205,19 @@ textarea:focus {
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.checks {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.privacy-checkbox > div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center; /* Vertically aligns items in the center */
|
||||||
|
gap: 10px; /* Adds space between the checkbox and the text */
|
||||||
|
}
|
||||||
|
|
||||||
/* Button */
|
/* Button */
|
||||||
.submit-reset {
|
.submit-reset {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -221,11 +234,13 @@ button[type="submit"], button[type="reset"] {
|
|||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
box-shadow: 0 4px 8px rgba(202, 110, 11, 0.4);
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
button[type="submit"]:hover, button[type="reset"]:hover {
|
button[type="submit"]:hover, button[type="reset"]:hover {
|
||||||
background-color: #2e97be;
|
background-color: #2e97be;
|
||||||
|
box-shadow: 0 4px 8px rgba(46, 151, 190, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.honeypot-field {
|
.honeypot-field {
|
||||||
|
@@ -16,4 +16,97 @@ h1, h2 {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 200px;
|
margin-top: 200px;
|
||||||
font-size: 2.5rem;
|
font-size: 2.5rem;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-card {
|
||||||
|
box-shadow: var(--shadow-small);
|
||||||
|
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: var(--shadow-medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-title {
|
||||||
|
margin-top: 0;
|
||||||
|
font-size: 2rem;
|
||||||
|
color: var(--primary-color);
|
||||||
|
margin-bottom: var(--margin-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-image {
|
||||||
|
width: 70%;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: var(--shadow-small);
|
||||||
|
margin-bottom: var(--margin-medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-description,
|
||||||
|
.demo-problem,
|
||||||
|
.demo-solution,
|
||||||
|
.coming-soon {
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: var(--margin-small);
|
||||||
|
font-size: 1.25rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-problem,
|
||||||
|
.demo-solution {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--primary-color);
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coming-soon {
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--secondary-color);
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-link,
|
||||||
|
.demo-repo {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 8px 25px;
|
||||||
|
margin: 20px 10px;
|
||||||
|
background-color: var(--secondary-color);
|
||||||
|
color: var(--light-bg-color);
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
border-radius: 50px;
|
||||||
|
box-shadow: 0 4px 8px rgba(202, 110, 11, 0.4);
|
||||||
|
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-link:hover,
|
||||||
|
.demo-repo:hover {
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
box-shadow: 0 4px 8px rgba(46, 151, 190, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive tweaks */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-card {
|
||||||
|
padding: var(--padding-medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-link,
|
||||||
|
.demo-repo {
|
||||||
|
display: block;
|
||||||
|
margin: 10px auto;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -29,7 +29,7 @@
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
padding: 8px 15px;
|
padding: 4px 15px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -56,9 +56,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav-logo a:hover {
|
.nav-logo a:hover {
|
||||||
color: var(--secondary-color); /* This will now be applied */
|
color: var(--secondary-color);
|
||||||
background-color: transparent; /* Override the background change */
|
background-color: transparent;
|
||||||
box-shadow: none; /* Remove the shadow */
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*? ↓ Start Footer ↓ */
|
/*? ↓ Start Footer ↓ */
|
||||||
|
@@ -35,6 +35,7 @@ body {
|
|||||||
.intro p {
|
.intro p {
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
color: #495057;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*? ↓ Start Benefits Section ↓ */
|
/*? ↓ Start Benefits Section ↓ */
|
||||||
@@ -135,13 +136,17 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.transition p:first-child {
|
.transition p:first-child {
|
||||||
font-size: 1.3em;
|
font-size: 1.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.transition p:last-child {
|
.transition p:last-child {
|
||||||
font-size: 1.4rem;
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thrive {
|
||||||
|
color: #ca6e0b;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
/*? ↓ Start Services Container ↓ */
|
/*? ↓ Start Services Container ↓ */
|
||||||
|
|
||||||
.services-section.module {
|
.services-section.module {
|
||||||
@@ -164,7 +169,7 @@ body {
|
|||||||
|
|
||||||
.accordion-container p {
|
.accordion-container p {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #333333;
|
color: #495057;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion {
|
.accordion {
|
||||||
@@ -209,7 +214,7 @@ body {
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
color: #333333;
|
color: #495057;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
@@ -226,7 +231,7 @@ body {
|
|||||||
transition: max-height 0.3s ease;
|
transition: max-height 0.3s ease;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
color: #333333;
|
color: #495057;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-content ul {
|
.accordion-content ul {
|
||||||
@@ -237,7 +242,7 @@ body {
|
|||||||
|
|
||||||
.accordion-content li {
|
.accordion-content li {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
color: #333333;
|
color: #495057;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover-list {
|
.hover-list {
|
||||||
@@ -280,18 +285,19 @@ body {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
|
box-shadow: 0 4px 8px rgba(202, 110, 11, 0.4);
|
||||||
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.demos-link:hover,
|
.demos-link:hover,
|
||||||
.cta-button:hover {
|
.cta-button:hover {
|
||||||
background-color: #2e97be;
|
background-color: #2e97be;
|
||||||
box-shadow: 0 4px 8px rgba(46, 151, 190, 0.2);
|
box-shadow: 0 4px 8px rgba(46, 151, 190, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.demos-link:active, .cta-button:active {
|
.demos-link:active, .cta-button:active {
|
||||||
background-color: #ca6e0b;
|
background-color: #ca6e0b;
|
||||||
box-shadow: 0 4px 8px rgba(46, 151, 190, 0.2);
|
box-shadow: 0 4px 8px rgba(202, 110, 11, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-steps {
|
.project-steps {
|
||||||
|
145
src/styles/privacy.css
Normal file
145
src/styles/privacy.css
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/* privacy.css */
|
||||||
|
|
||||||
|
/* Sets the background color for this page */
|
||||||
|
body {
|
||||||
|
background: linear-gradient(to bottom, #9FB8CC 0%, #DAE4F0 30%, #ffffff 50%, #DAE4F0 70%, #9FB8CC 100%);
|
||||||
|
font-family: var(--font-family-body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles the main container that holds the content */
|
||||||
|
.module {
|
||||||
|
margin: var(--margin-medium) auto;
|
||||||
|
padding: var(--padding-large);
|
||||||
|
max-width: 900px;
|
||||||
|
box-shadow: var(--shadow-large);
|
||||||
|
background-color: var(--light-bg-color);
|
||||||
|
border-radius: 15px;
|
||||||
|
border: 1px solid #7B8899;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles the primary heading */
|
||||||
|
h1 {
|
||||||
|
color: var(--text-color);
|
||||||
|
text-align: center;
|
||||||
|
font-size: 2.5em;
|
||||||
|
margin-bottom: var(--margin-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles the secondary headings within sections */
|
||||||
|
h2 {
|
||||||
|
color: var(--primary-color);
|
||||||
|
font-size: 1.8em;
|
||||||
|
margin-top: var(--margin-medium);
|
||||||
|
margin-bottom: var(--margin-small);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* General paragraph and list item styles */
|
||||||
|
.module p,
|
||||||
|
.module li {
|
||||||
|
color: var(--text-color);
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: var(--margin-small);
|
||||||
|
text-align: left;
|
||||||
|
margin-left: 30px;
|
||||||
|
margin-right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emphasizes strong text and headers for readability */
|
||||||
|
strong {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles all links on the page */
|
||||||
|
a {
|
||||||
|
color: var(--secondary-color);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Defines the hover state for all links */
|
||||||
|
a:hover {
|
||||||
|
color: var(--primary-color);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Defines the style for the horizontal rule element */
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
height: 1px;
|
||||||
|
background-color: var(--medium-gray-color);
|
||||||
|
margin: var(--margin-large) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles the Table of Contents container */
|
||||||
|
.toc {
|
||||||
|
border-left: 3px solid var(--secondary-color);
|
||||||
|
padding-left: 15px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
text-align: center;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc li {
|
||||||
|
padding: 2px 0;
|
||||||
|
padding-left: 10px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Correctly indents all other lists */
|
||||||
|
#data-collection ul, #privacy-rights ul, #contact ul, #data-use ul {
|
||||||
|
list-style: disc; /* Re-enable bullet points for all lists inside the module */
|
||||||
|
padding-left: 20px; /* Indent the entire list */
|
||||||
|
margin-left: 10px; /* Adds additional margin */
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-statement {
|
||||||
|
color: var(--primary-color);
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles the "Back to Top" link */
|
||||||
|
.back-to-top {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
margin: var(--margin-large) 0;
|
||||||
|
font-size: 0.9em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--dark-gray-color);
|
||||||
|
text-decoration: underline;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles the hover state for the "Back to Top" link */
|
||||||
|
.back-to-top:hover {
|
||||||
|
color: var(--primary-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--secondary-color);
|
||||||
|
border: solid 1px var(--medium-gray-color);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 5px 20px;
|
||||||
|
box-shadow: var(--shadow-medium);
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--light-gray-color);
|
||||||
|
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download:hover {
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
box-shadow: var(--shadow-large);
|
||||||
|
color: var(--light-gray-color);
|
||||||
|
}
|
Reference in New Issue
Block a user