Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion public/www/index-214437bf.css

This file was deleted.

1 change: 1 addition & 0 deletions public/www/index-b9e95284.css

Large diffs are not rendered by default.

File renamed without changes.
16 changes: 8 additions & 8 deletions public/www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@
}
</script>
<script>try { if (+sessionStorage.getItem('pest-scroll') > 100) document.documentElement.classList.add('no-intro'); } catch (e) {}</script>
<script type="module" crossorigin src="/www/index.f7d2c35b.js"></script>
<link rel="stylesheet" href="/www/index-214437bf.css">
<script type="module" crossorigin src="/www/index.208c84e2.js"></script>
<link rel="stylesheet" href="/www/index-b9e95284.css">
</head>

<body x-data="{ mobileMenuIsOpen: false }" class="font-synthesis-none overflow-x-clip bg-zinc-900 font-sans text-zinc-200 antialiased selection:bg-rose-600 selection:text-white">
Expand Down Expand Up @@ -179,7 +179,7 @@
</div>

<section class="relative" x-data="{ moveSpot(e) { if (!matchMedia('(hover: hover)').matches) return; const r = $refs.spotlight.getBoundingClientRect(); $refs.spotlight.style.setProperty('--spot-x', (e.clientX - r.left) + 'px'); $refs.spotlight.style.setProperty('--spot-y', (e.clientY - r.top) + 'px'); $refs.spotlight.style.opacity = 1; }, clearSpot() { $refs.spotlight.style.opacity = 0; }, syncSpot() { if (!$refs.developers || !$refs.wordSpot) return; const w = $refs.developers.getBoundingClientRect(); const g = $refs.wordSpot.getBoundingClientRect(); $refs.wordSpot.style.setProperty('--spot-x', (w.left - g.left + w.width / 2) + 'px'); $refs.wordSpot.style.setProperty('--spot-y', (w.top - g.top + w.height / 2 + 49) + 'px'); } }" x-init="$nextTick(() => { syncSpot(); document.fonts && document.fonts.ready.then(() => syncSpot()) })" @resize.window="syncSpot()" @animationend="syncSpot()" @pointermove="moveSpot($event)" @pointerleave="clearSpot()">
<div class="motion-preset-fade motion-duration-1000 lg:motion-delay-[1100ms] motion-reduce:animate-none bg-size-[56px_56px] mask-[radial-gradient(ellipse_90%_80%_at_60%_20%,#000_30%,transparent_75%)] absolute inset-0 -mt-15.5 bg-[linear-gradient(var(--color-zinc-700)_1px,transparent_1px),linear-gradient(90deg,var(--color-zinc-700)_1px,transparent_1px)] opacity-50 overflow-hidden" x-data x-init="[...$el.querySelectorAll('[data-beam]')].forEach(b => { const c = b.cloneNode(); c.style.setProperty('--beam-delay', (3 * Math.random()).toFixed(1) + 's'); $el.appendChild(c) }); $el.querySelectorAll('[data-beam]').forEach(b => { const roll = () => { const h = b.dataset.beam === 'x'; const lines = Math.floor((h ? $el.clientHeight : $el.clientWidth) / 56); b.style[h ? 'top' : 'left'] = 56 * (1 + Math.floor(Math.random() * (lines - 1))) + 'px'; b.style.setProperty('--beam-duration', (1 + 2 * Math.random()).toFixed(1) + 's'); b.style.animationDirection = Math.random() < 0.5 ? 'reverse' : 'normal'; }; roll(); b.addEventListener('animationiteration', roll) })">
<div class="motion-preset-fade motion-duration-1000 lg:motion-delay-[1100ms] motion-reduce:animate-none bg-size-[3.5rem_3.5rem] mask-[radial-gradient(ellipse_90%_80%_at_60%_20%,#000_30%,transparent_75%)] absolute inset-0 -mt-15.5 bg-[linear-gradient(var(--color-zinc-700)_1px,transparent_1px),linear-gradient(90deg,var(--color-zinc-700)_1px,transparent_1px)] opacity-50 overflow-hidden" x-data x-init="[...$el.querySelectorAll('[data-beam]')].forEach(b => { const c = b.cloneNode(); c.style.setProperty('--beam-delay', (3 * Math.random()).toFixed(1) + 's'); $el.appendChild(c) }); $el.querySelectorAll('[data-beam]').forEach(b => { const roll = () => { const h = b.dataset.beam === 'x'; const cell = 3.5 * parseFloat(getComputedStyle(document.documentElement).fontSize); const lines = Math.floor((h ? $el.clientHeight : $el.clientWidth) / cell); b.style[h ? 'top' : 'left'] = cell * (1 + Math.floor(Math.random() * (lines - 1))) + 'px'; b.style.setProperty('--beam-duration', (1 + 2 * Math.random()).toFixed(1) + 's'); b.style.animationDirection = Math.random() < 0.5 ? 'reverse' : 'normal'; }; roll(); b.addEventListener('animationiteration', roll) })">
<span data-beam="x" class="animate-beam-x motion-reduce:hidden absolute -left-40 w-40 top-28 h-px bg-[linear-gradient(90deg,transparent,var(--color-rose-500),transparent)] drop-shadow-[0_0_6px_var(--color-rose-500)] [--beam-duration:7s]"></span>
<span data-beam="x" class="animate-beam-x motion-reduce:hidden absolute -left-40 w-40 top-56 h-px bg-[linear-gradient(90deg,transparent,var(--color-rose-500),transparent)] drop-shadow-[0_0_6px_var(--color-rose-500)] [--beam-duration:11s] [--beam-delay:2.7s]"></span>
<span data-beam="x" class="animate-beam-x motion-reduce:hidden absolute -left-40 w-40 top-84 h-px bg-[linear-gradient(90deg,transparent,var(--color-rose-500),transparent)] drop-shadow-[0_0_6px_var(--color-rose-500)] [--beam-duration:9s] [--beam-delay:1s]"></span>
Expand All @@ -195,8 +195,8 @@
<span data-beam="y" class="animate-beam-y motion-reduce:hidden absolute -top-40 h-40 left-168 w-px bg-[linear-gradient(180deg,transparent,var(--color-rose-500),transparent)] drop-shadow-[0_0_6px_var(--color-rose-500)] [--beam-duration:8s] [--beam-delay:2.3s]"></span>
<span data-beam="y" class="animate-beam-y motion-reduce:hidden absolute -top-40 h-40 left-28 w-px bg-[linear-gradient(180deg,transparent,var(--color-rose-500),transparent)] drop-shadow-[0_0_6px_var(--color-rose-500)] [--beam-duration:10s] [--beam-delay:3s]"></span>
</div>
<div class="bg-size-[56px_56px] mask-[radial-gradient(220px_circle_at_var(--spot-x,50%)_var(--spot-y,50%),#000,transparent),radial-gradient(ellipse_90%_80%_at_60%_20%,#000_30%,transparent_75%)] mask-intersect pointer-events-none absolute inset-0 -mt-15.5 bg-[linear-gradient(var(--color-rose-800)_1px,transparent_1px),linear-gradient(90deg,var(--color-rose-900)_1px,transparent_1px)] opacity-0 transition-opacity duration-300" x-ref="spotlight"></div>
<div class="motion-preset-fade motion-duration-1000 lg:motion-delay-[1100ms] motion-reduce:animate-none bg-size-[56px_56px] mask-[radial-gradient(220px_circle_at_var(--spot-x,-999px)_var(--spot-y,-999px),#000,transparent),radial-gradient(ellipse_90%_80%_at_60%_20%,#000_30%,transparent_75%)] mask-intersect pointer-events-none absolute inset-0 -mt-15.5 bg-[linear-gradient(var(--color-rose-800)_1px,transparent_1px),linear-gradient(90deg,var(--color-rose-800)_1px,transparent_1px)]" x-ref="wordSpot"></div>
<div class="bg-size-[3.5rem_3.5rem] mask-[radial-gradient(220px_circle_at_var(--spot-x,50%)_var(--spot-y,50%),#000,transparent),radial-gradient(ellipse_90%_80%_at_60%_20%,#000_30%,transparent_75%)] mask-intersect pointer-events-none absolute inset-0 -mt-15.5 bg-[linear-gradient(var(--color-rose-800)_1px,transparent_1px),linear-gradient(90deg,var(--color-rose-900)_1px,transparent_1px)] opacity-0 transition-opacity duration-300" x-ref="spotlight"></div>
<div class="motion-preset-fade motion-duration-1000 lg:motion-delay-[1100ms] motion-reduce:animate-none bg-size-[3.5rem_3.5rem] mask-[radial-gradient(220px_circle_at_var(--spot-x,-999px)_var(--spot-y,-999px),#000,transparent),radial-gradient(ellipse_90%_80%_at_60%_20%,#000_30%,transparent_75%)] mask-intersect pointer-events-none absolute inset-0 -mt-15.5 bg-[linear-gradient(var(--color-rose-800)_1px,transparent_1px),linear-gradient(90deg,var(--color-rose-800)_1px,transparent_1px)]" x-ref="wordSpot"></div>
<div aria-hidden="true" class="animate-intro-out pointer-events-none absolute inset-0 hidden items-center justify-center lg:flex motion-reduce:lg:hidden">
<div class="relative w-160">
<svg class="animate-crt-in h-auto w-full fill-zinc-200 opacity-0" viewBox="0 0 381 100" xmlns="http://www.w3.org/2000/svg"><use href="#pest-wordmark" /></svg>
Expand All @@ -208,7 +208,7 @@
<a href="/docs/pest5-now-available" class="motion-preset-slide-up lg:motion-delay-[1100ms] motion-reduce:animate-none flex items-center gap-2.5 font-mono text-xs tracking-widest text-zinc-400 transition-colors hover:text-zinc-200">
<span class="font-bold text-rose-500">//</span> pest 5 — now available
</a>
<h1 class="motion-preset-slide-up motion-delay-100 lg:motion-delay-[1200ms] motion-reduce:animate-none font-display font-stretch-112% mb-4 mt-5 text-[clamp(30px,8.6vw,40px)] font-extrabold leading-[1.05] tracking-tight sm:text-[clamp(34px,4vw,50px)]">
<h1 class="motion-preset-slide-up motion-delay-100 lg:motion-delay-[1200ms] motion-reduce:animate-none font-display font-stretch-112% mb-4 mt-5 text-[clamp(1.875rem,8.6vw,2.5rem)] font-extrabold leading-[1.05] tracking-tight sm:text-[clamp(2.125rem,4vw,3.125rem)]">
The elegant<br>testing framework<br><span class="whitespace-nowrap">for PHP <span x-ref="developers">developers</span></span>
<span class="relative whitespace-nowrap italic text-rose-500 after:absolute after:inset-x-0 after:bottom-1.5 after:-z-10 after:h-2.5 after:bg-rose-950 after:content-['']">and AI agents.</span>
</h1>
Expand All @@ -220,7 +220,7 @@ <h1 class="motion-preset-slide-up motion-delay-100 lg:motion-delay-[1200ms] moti
</div>

<div class="motion-preset-blur-up motion-blur-in-lg motion-delay-[400ms] lg:motion-delay-[1500ms] motion-reduce:animate-none relative overflow-hidden rounded-2xl border border-zinc-700 bg-zinc-800 shadow-[0_24px_60px_-30px_rgba(23,22,27,0.18)]" x-data="{ tab: 'browser' }">
<div class="flex overflow-x-auto border-b border-zinc-700 px-2" role="tablist">
<div class="scrollbar-ghost flex overflow-x-auto border-b border-zinc-700 px-2" role="tablist">
<button @click="tab = 'browser'" :aria-selected="tab === 'browser'" class="cursor-pointer whitespace-nowrap border-b-2 border-transparent px-3 py-3 font-mono text-xs text-zinc-400 transition-colors hover:text-zinc-200 aria-selected:border-rose-500 aria-selected:text-zinc-200" role="tab" type="button">BrowserTest.php</button>
<button @click="tab = 'feature'" :aria-selected="tab === 'feature'" class="cursor-pointer whitespace-nowrap border-b-2 border-transparent px-3 py-3 font-mono text-xs text-zinc-400 transition-colors hover:text-zinc-200 aria-selected:border-rose-500 aria-selected:text-zinc-200" role="tab" type="button">FeatureTest.php</button>
<button @click="tab = 'unit'" :aria-selected="tab === 'unit'" class="cursor-pointer whitespace-nowrap border-b-2 border-transparent px-3 py-3 font-mono text-xs text-zinc-400 transition-colors hover:text-zinc-200 aria-selected:border-rose-500 aria-selected:text-zinc-200" role="tab" type="button">UnitTest.php</button>
Expand Down Expand Up @@ -689,7 +689,7 @@ <h3 class="font-display font-stretch-112% text-balance text-xl font-bold">Loved
<section aria-label="Get started" class="relative border-y border-zinc-700">
<span class="-left-1.25 -top-1.25 size-2.25 before:w-2.25 after:h-2.25 pointer-events-none absolute z-10 before:absolute before:left-0 before:top-1 before:h-px before:bg-rose-500 before:content-[''] after:absolute after:left-1 after:top-0 after:w-px after:bg-rose-500 after:content-['']"></span>
<span class="-right-1.25 -top-1.25 size-2.25 before:w-2.25 after:h-2.25 pointer-events-none absolute z-10 before:absolute before:left-0 before:top-1 before:h-px before:bg-rose-500 before:content-[''] after:absolute after:left-1 after:top-0 after:w-px after:bg-rose-500 after:content-['']"></span>
<div class="bg-size-[56px_56px] mask-[radial-gradient(ellipse_70%_90%_at_50%_45%,#000_30%,transparent_75%)] absolute inset-0 bg-[linear-gradient(var(--color-zinc-700)_1px,transparent_1px),linear-gradient(90deg,var(--color-zinc-700)_1px,transparent_1px)] opacity-50 overflow-hidden" x-data x-init="[...$el.querySelectorAll('[data-beam]')].forEach(b => { const c = b.cloneNode(); c.style.setProperty('--beam-delay', (3 * Math.random()).toFixed(1) + 's'); $el.appendChild(c) }); $el.querySelectorAll('[data-beam]').forEach(b => { const roll = () => { const h = b.dataset.beam === 'x'; const lines = Math.floor((h ? $el.clientHeight : $el.clientWidth) / 56); b.style[h ? 'top' : 'left'] = 56 * (1 + Math.floor(Math.random() * (lines - 1))) + 'px'; b.style.setProperty('--beam-duration', (1 + 2 * Math.random()).toFixed(1) + 's'); b.style.animationDirection = Math.random() < 0.5 ? 'reverse' : 'normal'; }; roll(); b.addEventListener('animationiteration', roll) })">
<div class="bg-size-[3.5rem_3.5rem] mask-[radial-gradient(ellipse_70%_90%_at_50%_45%,#000_30%,transparent_75%)] absolute inset-0 bg-[linear-gradient(var(--color-zinc-700)_1px,transparent_1px),linear-gradient(90deg,var(--color-zinc-700)_1px,transparent_1px)] opacity-50 overflow-hidden" x-data x-init="[...$el.querySelectorAll('[data-beam]')].forEach(b => { const c = b.cloneNode(); c.style.setProperty('--beam-delay', (3 * Math.random()).toFixed(1) + 's'); $el.appendChild(c) }); $el.querySelectorAll('[data-beam]').forEach(b => { const roll = () => { const h = b.dataset.beam === 'x'; const cell = 3.5 * parseFloat(getComputedStyle(document.documentElement).fontSize); const lines = Math.floor((h ? $el.clientHeight : $el.clientWidth) / cell); b.style[h ? 'top' : 'left'] = cell * (1 + Math.floor(Math.random() * (lines - 1))) + 'px'; b.style.setProperty('--beam-duration', (1 + 2 * Math.random()).toFixed(1) + 's'); b.style.animationDirection = Math.random() < 0.5 ? 'reverse' : 'normal'; }; roll(); b.addEventListener('animationiteration', roll) })">
<span data-beam="x" class="animate-beam-x motion-reduce:hidden absolute -left-40 w-40 top-28 h-px bg-[linear-gradient(90deg,transparent,var(--color-rose-500),transparent)] drop-shadow-[0_0_6px_var(--color-rose-500)] [--beam-duration:7s]"></span>
<span data-beam="x" class="animate-beam-x motion-reduce:hidden absolute -left-40 w-40 top-56 h-px bg-[linear-gradient(90deg,transparent,var(--color-rose-500),transparent)] drop-shadow-[0_0_6px_var(--color-rose-500)] [--beam-duration:11s] [--beam-delay:2.7s]"></span>
<span data-beam="y" class="animate-beam-y motion-reduce:hidden absolute -top-40 h-40 left-70 w-px bg-[linear-gradient(180deg,transparent,var(--color-rose-500),transparent)] drop-shadow-[0_0_6px_var(--color-rose-500)] [--beam-duration:13s] [--beam-delay:1.7s]"></span>
Expand Down
75 changes: 59 additions & 16 deletions resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@
--font-display: 'Archivo', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, monospace;

--text-3xs: 9px;
--text-3xs: 0.5625rem;
--text-3xs--line-height: 1.4;
--text-2xs: 11px;
--text-2xs: 0.6875rem;
--text-2xs--line-height: 1.4;
--text-xs-plus: 12.5px;
--text-xs-plus: 0.78125rem;
--text-xs-plus--line-height: 1.4;

/* footer watermark: a neon segment traces the letter outlines (mirrors the landing).
Expand All @@ -81,10 +81,21 @@
html {
height: 100%;
-webkit-tap-highlight-color: transparent;

/* Fluid root — mirrors resources/www/main.css; see the note there. */
font-size: clamp(1rem, 0.8889vw, 2.8rem);

scrollbar-width: thin;
scrollbar-color: var(--color-rose-500) transparent;
}
body {
min-height: 100%;
}
/* scrollbar-color inherits, scrollbar-width does not — without this every inner scroll
pane keeps a 16px native gutter that merely happens to be tinted rose. */
* {
scrollbar-width: thin;
}
[x-cloak] {
display: none;
}
Expand All @@ -99,6 +110,36 @@ button {
}

/* Scrollbars ------------------------------------------------------------- */

/* Ghost scrollbar — for the sticky nav rails (sidebar, partners). The gutter stays
reserved, so revealing the thumb on hover costs no reflow. The ::-webkit-* rules are
the fallback for Safari < 18.2; browsers with scrollbar-color ignore them. */
.scrollbar-ghost {
scrollbar-color: transparent transparent;
}
.scrollbar-ghost:hover,
.scrollbar-ghost:focus-within {
scrollbar-color: var(--color-rose-500) transparent;
}
.scrollbar-ghost::-webkit-scrollbar {
width: 0.375rem;
height: 0.375rem;
}
.scrollbar-ghost::-webkit-scrollbar-track {
background: transparent;
}
.scrollbar-ghost::-webkit-scrollbar-thumb {
@apply rounded-full;
background: transparent;
}
.scrollbar-ghost:hover::-webkit-scrollbar-thumb,
.scrollbar-ghost:focus-within::-webkit-scrollbar-thumb {
background: var(--color-rose-500);
}
.scrollbar-ghost::-webkit-scrollbar-thumb:hover {
background: var(--color-rose-400);
}

.scrollbar::-webkit-scrollbar {
width: 8px;
height: 8px;
Expand All @@ -107,19 +148,21 @@ button {
@apply bg-zinc-900;
}
.scrollbar::-webkit-scrollbar-thumb {
@apply rounded-full bg-zinc-700;
@apply rounded-full bg-rose-500;
}
.scrollbar::-webkit-scrollbar-thumb:hover {
@apply bg-zinc-600;
@apply bg-rose-400;
}

/* ==========================================================================
Crosshair registration marks (reusable helper)
========================================================================== */
.crosshair {
@apply pointer-events-none absolute z-10;
width: 9px;
height: 9px;
/* rem to match the rem offsets in ::before / ::after — a px box would deform as the
root scales. Same value as the landing's `size-2.25`. */
width: 0.5625rem;
height: 0.5625rem;
}
.crosshair::before {
content: '';
Expand Down Expand Up @@ -248,10 +291,10 @@ button {
@apply bg-zinc-900;
}
.docs-main pre code.torchlight::-webkit-scrollbar-thumb {
@apply rounded-full bg-zinc-700;
@apply rounded-full bg-rose-500;
}
.docs-main pre code.torchlight::-webkit-scrollbar-thumb:hover {
@apply bg-zinc-600;
@apply bg-rose-400;
}
/* Non-torchlight (plain) code blocks still get comfortable padding */
.docs-main pre code:not(.torchlight) {
Expand Down Expand Up @@ -279,7 +322,7 @@ button {
.docs-main .code-snippet {
@apply my-6 block flex-1 overflow-x-auto rounded-[10px] border border-zinc-700 bg-zinc-900 py-5;
scrollbar-width: thin;
scrollbar-color: var(--color-zinc-700) var(--color-zinc-900);
scrollbar-color: var(--color-rose-500) var(--color-zinc-900);
}
.docs-main pre + .code-snippet {
@apply mt-4;
Expand All @@ -291,13 +334,13 @@ button {
@apply bg-zinc-900;
}
.docs-main .code-snippet::-webkit-scrollbar-thumb {
@apply rounded-full bg-zinc-700;
@apply rounded-full bg-rose-500;
}
.docs-main .code-snippet:hover::-webkit-scrollbar-thumb {
@apply bg-zinc-600;
@apply bg-rose-400;
}
.docs-main .code-snippet img {
--line-height: 29.6px;
--line-height: 1.85rem;
max-width: inherit;
height: calc(var(--line-height) * var(--lines));
@apply px-5;
Expand Down Expand Up @@ -326,7 +369,7 @@ button {
line-height: 1.9;
color: var(--t-gray);
scrollbar-width: thin;
scrollbar-color: var(--color-zinc-700) var(--color-zinc-900);
scrollbar-color: var(--color-rose-500) var(--color-zinc-900);
@apply my-6 rounded-[10px] border border-zinc-700 bg-zinc-900 px-5.5 py-5 font-mono text-[13px];
}
.docs-main .terminal::-webkit-scrollbar {
Expand All @@ -336,10 +379,10 @@ button {
@apply bg-zinc-900;
}
.docs-main .terminal::-webkit-scrollbar-thumb {
@apply rounded-full bg-zinc-700;
@apply rounded-full bg-rose-500;
}
.docs-main .terminal:hover::-webkit-scrollbar-thumb {
@apply bg-zinc-600;
@apply bg-rose-400;
}
.docs-main .terminal .l {
min-height: 1.9em;
Expand Down
Loading