The Source

This is the Astro source code for the home page.

---
// @ts-nocheck
import Picture from '@components/Picture.astro';
import Layout from '@layouts/Layout.astro';
import LatestPost from '@components/posts/LatestPost.astro';
import TwoPosts from '@components/posts/TwoPosts.astro';
import TwoThings from '~/components/TwoThings.astro';
import Thing from '~/components/Thing.astro';
import ObfuMatic from 'obfumatic/astro';
import * as config from '~/config.js';

import Chevron from '@images/icons/chevron.svg';
import ogImage from '@images/iwantcandy.jpg';
import lollipop from '@images/lollipop.jpg';
import nosering from '@images/lollipop-nose-ring.jpg';
import redlight from '@images/red-light-lollipop.jpg';

---
<Layout bodyClass="home" ogImage={ogImage}>
	<header id="site-head">
		<Picture class="bgimage"
			src={lollipop}
			alt=""
			widths={[800, 1200, 1600, 2400, 3200]}
			sizes="100vw"
			formats={['avif','jpg']}
			quality="high"
			fetchpriority="high"
		/>
		<div class="inner">
			<h1 class="site-title">{config.siteTitle}</h1>
			<div class="site-description">{config.siteDescription}</div>
			<div class="site-menu">
				<a class="btn" href="#intro">Hello</a>
				<a class="btn" href="#latest">Latest</a>
				<a class="btn" href="/blog/">Blog</a>
				<a class="btn" href="/source/">Source</a>
			</div>
			<div id="header-arrow"><Chevron width="90" height="52" /></div>
		</div>
	</header>

	<main>
		<section id="intro">
			<div class="content">
				<h2>Hello</h2>
				<p>Hi there. This is a development site where I’m just playing with stuff.
					If you’re not me, <strong>there’s nothing for you here,</strong> unless you really want
					to see if I’ve broken some CSS again.</p>
				<p>Filler content in the <a href="/blog/">blog</a> section is AI-generated, so don’t
					take it too seriously.</p>
			</div>
		</section>

		<section id="latest">
			<LatestPost />
		</section>

		<section id="more">
			<TwoPosts offset={1} sectionClass="more-posts">
				<Fragment slot="section-header">
					More posts
				</Fragment>
			</TwoPosts>
			<p><a href="/blog/">More posts...</a></p>
		</section>

		<section id="stuff">
			<TwoThings>
				<h3 slot="section-header">Lollipops</h3>
				<Thing slot="left">
					<Picture src={nosering} alt="Woman with nose ring licking a lollipop" maxSize="200" />
					<p>A lollipop is pure magic - a sweet, colorful burst of happiness perched atop a little white stick, ready to transform any ordinary moment into one of childlike wonder.</p>
				</Thing>
				<Thing slot="right">
					<p>The way it slowly dissolves, releasing its sugary bliss while painting your tongue in whimsical hues, makes it impossible not to smile with each delightful lick.</p>
					<Picture src={redlight} alt="Woman lit in red licking a lollipop" maxSize="200" />
				</Thing>
			</TwoThings>
		</section>

		<section id="contact">
			<div class="contact">
				<h2>Contact</h2>
				<p>
					Use this <ObfuMatic email="foo@bar.com" text="fake email link" /> for testing.
				</p>
			</div>
		</section>

	</main>
</Layout>

<style>
#site-head {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100vw;
	height: 100vh;
	background-color: var(--site-head-bg-color);
	margin-bottom: 0;
	text-align: center;
}

#site-head .inner {
	flex: 1 4 80%;
	z-index: 1;
	animation: fadeIn 0.3s;
	position: relative;
	top: 0;
}

.bgimage {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: top center;
	animation: fadeIn 0.5s;
}

.site-title {
	font-family: var(--display-font, var(--header-font, sans-serif));
	font-weight: 700;
	margin: 10px 0 5px 0;
	font-size: var(--step-9);
	letter-spacing: -2px;
	color: var(--site-head-text-color);
	text-shadow: 2px 2px 3px var(--site-head-shadow-color);
}

.site-description {
	margin: 0;
	font-size: 1.65rem;
	line-height: 1.5em;
	font-weight: 400;
	font-family: var(--header-font), serif;
	letter-spacing: 0;
	color: var(--site-head-text-color);
	text-shadow: 2px 2px 3px var(--site-head-shadow-color);
	text-rendering: optimizeLegibility;
}

a.btn {
	text-decoration: none;
	color: var(--button-text-color);
	background-color: var(--button-bg-color);
	position: relative;
	display: inline-block;
	font-size: 16px;
	letter-spacing: 1px;
	border-radius: 6px;
	margin: 0;
	overflow: visible;
	padding: 10px 20px 10px 20px;
	margin-top: 30px;
	font-family: var(--button-font, sans-serif);
	text-transform: uppercase;
	font-weight: 200;
	box-shadow: 1px 1px 2px var(--site-head-shadow-color);
	transition: background-color ease 0.25s;
}

a.btn:hover {
	background-color: var(--button-hover-bg-color);
}

#header-arrow {
	margin: 35px auto;
	width: 90px;
	cursor: pointer;
	opacity: 0.6;
	transition: opacity ease 0.3s;
	/* filter: drop-shadow(2px 2px 3px var(--site-head-shadow-color)); */
}
#header-arrow:hover {
	opacity: 0.9;
}
</style>

<script>
// @ts-nocheck
// Scroll to first section on arrow click
const arrow = document.querySelector('#header-arrow');
if (arrow) {
	arrow.addEventListener('click', (e) => {
		document.querySelector('section:not(section section):first-of-type')?.scrollIntoView({ behavior: 'smooth' });
		e.preventDefault();
	});
}

// Smooth scroll to anchor links
document.querySelectorAll('a[href^="#"]').forEach((link) => {
	link.addEventListener('click', (e) => {
		document.querySelector(e.currentTarget.hash)?.scrollIntoView({ behavior: 'smooth' });
		e.preventDefault();
	});
});

// Parallax effect on header
document.addEventListener('scroll', () => {
	const offset = -(((window.scrollY / window.innerHeight) * 100) * 0.35);
	document.querySelector('#site-head .inner').style.top = `${offset}px`;
});
</script>