thats adam
Complex UI Sections
Self-contained sections of the interface built from multiple molecules and atoms. Organisms can stand alone and be reused across templates — the navigation, footer, stats bar, and CTA section all exist here.
Stats Bar
Full-bleed horizontal row of stat items. Bordered top and bottom. Horizontally scrollable on mobile with scroll-snap. Used on the homepage below the hero.
<div class="stats-bar">
<div class="stats-bar__item">
<span class="stats-bar__value">17+</span>
<span class="stats-bar__label label-s">Årelang erfaring</span>
</div>
<div class="stats-bar__item">
<span class="stats-bar__value">50+</span>
<span class="stats-bar__label label-s">Projekter afsluttet</span>
</div>
<div class="stats-bar__item">
<span class="stats-bar__value">3</span>
<span class="stats-bar__label label-s">Designpriser</span>
</div>
<div class="stats-bar__item">
<span class="stats-bar__value">3</span>
<span class="stats-bar__label label-s">Forskellige genrer</span>
</div>
</div>/* template-parts/components/stats-bar.php */
.stats-bar {
display: flex; width: 100%;
border-top: 1px solid var(--surface-branding-primary-30);
border-bottom: 1px solid var(--surface-branding-primary-30);
padding-block: 65px;
}
/* .stats-bar__item — see Stat Item */
@media (max-width: 768px) {
.stats-bar { overflow-x: auto; scrollbar-width: none; padding-block: var(--space-2xl); }
.stats-bar::-webkit-scrollbar { display: none; }
.stats-bar__item { flex: 0 0 148px; }
.stats-bar__item:first-child { padding-left: var(--space-l); }
}<?php thats_adam_part( 'components/stats-bar' ); ?>CTA Section
Reusable call-to-action block. Blur glass background creates depth against the page canvas. Included at the bottom of every primary template via thats_adam_part('components/cta-section').
Kontakt os, og lad os arbejde sammen :)
Lige nu tilgængelig for freelancejobs og kreative partnerskaber verden over. Lad os bygge noget exceptionelt sammen.
<section class="cta-section">
<div class="cta-section__blur" aria-hidden="true"></div>
<div class="cta-section__content">
<h2 class="cta-section__heading heading-xxl">Kontakt os, og lad os arbejde sammen :)</h2>
<p class="cta-section__body body-m">Lige nu tilgængelig for freelancejobs og kreative partnerskaber verden over. Lad os bygge noget exceptionelt sammen.</p>
</div>
<a href="/da/contact/" class="btn btn-secondary">Lad os tale</a>
</section>/* template-parts/components/cta-section.php */
.cta-section { position: relative; display: flex; flex-direction: column; align-items: center; gap: var(--space-1xl); padding: var(--space-4xl) var(--space-l); border-radius: 16px; text-align: center; overflow: hidden; }
.cta-section__blur {
position: absolute; top: 50px; left: 50%; transform: translateX(-50%);
width: 800px; height: 300px;
background: var(--surface-branding-primary-15);
filter: blur(60px); border-radius: 12px;
pointer-events: none; z-index: 0;
}
.cta-section__content { position: relative; z-index: 1; display: flex; flex-direction: column; gap: var(--space-m); align-items: center; max-width: 685px; }
.cta-section__heading { color: var(--text-on-dark-primary); text-align: center; }
.cta-section__body { font-size: 18px; line-height: 28px; text-align: center; max-width: 612px; }
.cta-section .btn { position: relative; z-index: 1; }<!-- Last element before the footer on every primary template -->
<div class="container" style="padding-bottom:var(--space-4xl)">
<?php thats_adam_part( 'components/cta-section' ); ?>
</div>Always place the CTA section as the final element before the footer on any primary page template.
Don't modify the CTA heading per-page — shared copy ensures brand consistency across the site.
Hero Canvas Background
Procedural animated background. Generates a random maze via depth-first search, then animates glowing particles through paths. Interactive: click events trigger particle bursts. Theme-aware — reads colour values from CSS custom properties via getComputedStyle at runtime.
Modes
- Animated (homepage) — full particle + glow animation, click interactions, 30-second game mechanic with score tracking
- Static (services page) — maze renders once, no animation, passed via
['static' => true]
<!-- The parent must be position:relative — the canvas fills it -->
<section class="hero" style="position:relative;">
<canvas id="hcbg-a1b2c3" class="hero-canvas-bg" data-static="0" aria-hidden="true"></canvas>
…hero content…
</section>/* template-parts/components/hero-canvas-bg.php */
.hero-canvas-bg {
position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: block;
pointer-events: none; z-index: 0;
mask-image: linear-gradient(to bottom, black 0%, black 55%, transparent 88%);
-webkit-mask-image: linear-gradient(to bottom, black 0%, black 55%, transparent 88%);
}<?php thats_adam_part( 'components/hero-canvas-bg' ); ?> <!-- animated -->
<?php thats_adam_part( 'components/hero-canvas-bg', [ 'static' => true ] ); ?> <!-- static -->Project Grid
2-column CSS grid of project cards. Includes a header row with section label + heading left, "All projects" ghost link bottom-right. WP_Query driven — shows published portfolio posts.
Anatomy
- Header row — label + heading left; "All projects"
.btn-ghostright,align-items: flex-end - Grid —
grid-template-columns: repeat(2, 1fr), gap:var(--space-2xl)row /var(--space-1xl)column - Cards — Project Card molecule, WP_Query loop of
portfolioCPT
<div class="work-grid-wrap container">
<div class="work-grid" id="work-grid">
<article class="project-card" style="grid-column:1/4" …>…</article>
<article class="project-card project-card--flip" style="grid-column:1/4" …>…</article>
</div>
<p class="work-grid__empty body-m" id="work-grid-empty" style="display:none">Ingen projekter matcher dette filter.</p>
</div>/* archive-portfolio.php */
.work-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5xl) var(--space-1xl); }
@media (max-width: 768px) {
.work-grid { grid-template-columns: 1fr; }
}<div class="work-grid" id="work-grid">
<?php foreach ( $posts_data as $i => $p ) :
thats_adam_part( 'components/project-card', [ 'post_id' => $p['post_id'], 'index' => $i ] );
endforeach; ?>
</div>Homepage Hero
947px tall hero. Left column = audience selector (7 items, extralight, active = blue glow). Right column = heading + bio + CTA row. Animated geometric maze canvas background. Clicking a glow particle explodes it.
Anatomy
- Canvas BG — hero-canvas-bg.php (animated=true), position:absolute, mask fades at 55% down
- Audience selector (left) — 240px col · 7 items · var(--text-2xl) · var(--fw-extralight) · active = var(--color-active-glow) + glow shadow
- Hero text (right) — label-m + .heading-xxxl (responsive) + .body-l + CTA row (btn-primary + btn-secondary)
- Height — min-height: 947px on production; hero fills viewport minus nav
GeneralUnique heading, bio, and CTA labelUdviklereUnique heading, bio, and CTA labelHiring managersUnique heading, bio, and CTA labelDesignereUnique heading, bio, and CTA labelProjektledereUnique heading, bio, and CTA labelLøsningsarkitekterUnique heading, bio, and CTA labelKollegerUnique heading, bio, and CTA label<section class="home2-hero" id="home2-hero">
<div class="home2-hero__bg" aria-hidden="true">
<img src="/wp-content/themes/thats-adam/assets/hero-photo.png" alt="" class="home2-hero__photo">
</div>
<div class="home2-hero__grid">
<div class="home2-hero__left">
<div class="home2-hero__row">
<div class="home2-hero__as" id="home2-hero-as">
<p class="home2-hero__as-text" id="home2-hero-as-text">As a <strong>Designer</strong></p>
</div>
<div class="home2-hero__for">
<div class="home2-hero__for-label" id="home2-hero-for-label">…</div>
<ul class="home2-hero__audience-list" id="home2-hero-audience-list">…</ul>
</div>
</div>
<p class="home2-hero__body" id="home2-hero-body">So that you can quickly get a genuine sense of how I think, design and deliver — whoever you are and whatever brought you here today.</p>
</div>
<div class="home2-hero__name" aria-hidden="true">…</div>
</div>
</section>/* front-page.php */
.home2-hero { position: relative; height: 100vh; display: flex; align-items: flex-end; overflow: hidden; }
.home2-hero__bg { position: absolute; inset: 0; }
.home2-hero__photo {
position: absolute; right: 0; bottom: 0; height: 100%; width: auto; max-width: none;
object-fit: cover; object-position: bottom right;
filter: grayscale(1); opacity: 0.5;
}
.home2-hero__grid {
position: relative; display: grid; grid-template-columns: repeat(3, 1fr);
align-items: center; width: 100%; height: 100%; gap: var(--space-xl);
padding: var(--space-4xl) 0 var(--space-2xl) var(--space-4xl);
}
.home2-hero__left { display: flex; flex-direction: column; gap: var(--space-4xl); max-width: 900px; grid-column: 1 / 3; justify-self: center; position: relative; z-index: 2; }
.home2-hero__audience-list { list-style: none; display: flex; flex-direction: column; gap: 12px; width: 340px; flex-shrink: 0; }
.home2-hero__body { font-size: var(--text-xl); font-weight: var(--fw-extralight); line-height: 43px; max-width: 845px; transition: opacity .2s ease; }
.home2-hero__name { position: relative; height: 100%; width: 217px; flex-shrink: 0; grid-column: 3 / 4; justify-self: end; }