Added WIP Menu

This commit is contained in:
2025-09-29 15:20:46 +02:00
parent 1773687814
commit bfbe687b63
56 changed files with 4726 additions and 1070 deletions

View File

@@ -0,0 +1,142 @@
{
"items": [
{
"name": "Metatron",
"path": "/meta",
"gridPosition": "area_1",
"variant": "meta",
"sublinks": {
"discriminant": false
},
"subtitle": {
"discriminant": false
}
},
{
"name": "Kitchensink",
"path": "/",
"gridPosition": "area_2",
"variant": "kitchensink",
"sublinks": {
"discriminant": true,
"value": [
{
"name": "The Pomarj",
"path": "/kitchensink/the-pomarj"
},
{
"name": "Burning Pavis",
"path": "/kitchensink/burning-pavis"
},
{
"name": "SLA Armies",
"path": "/kitchensink/sla-armies"
}
]
},
"subtitle": {
"discriminant": false
}
},
{
"name": "AWQ",
"path": "/awq",
"gridPosition": "area_3",
"variant": "awq",
"sublinks": {
"discriminant": true,
"value": [
{
"name": "The Crunch",
"path": "/awq/core-rules"
},
{
"name": "Sigmar's Heirs",
"path": "/awq/character"
},
{
"name": "Armory",
"path": "/awq/equipment"
},
{
"name": "The Winds of Magic",
"path": "/awq/magic"
},
{
"name": "Beastiary",
"path": "/awq/bestiary"
},
{
"name": "Duveldal",
"path": "/awq/pregens"
},
{
"name": "Plundered Vaults",
"path": "/awq/expansions"
},
{
"name": "Tools",
"path": "/awq/tools"
}
]
},
"subtitle": {
"discriminant": false
}
},
{
"name": "Worldburner",
"path": "/worldburner",
"gridPosition": "area_4",
"variant": "worldburner",
"sublinks": {
"discriminant": true,
"value": [
{
"name": "Burning Lands",
"path": "/worldburner/geography"
},
{
"name": "Burning People",
"path": "/worldburner/cultures"
},
{
"name": "Burning Faiths",
"path": "/worldburner/religion"
},
{
"name": "Burning Witches",
"path": "/worldburner/magic"
},
{
"name": "Burning Realms",
"path": "/worldburner/states"
}
]
},
"subtitle": {
"discriminant": false
}
},
{
"name": "Chainbreaker",
"path": "/chainbreaker",
"gridPosition": "area_5",
"variant": "chainbreaker",
"background": "/images/categories/items/4/background.png",
"sublinks": {
"discriminant": false
},
"subtitle": {
"discriminant": true,
"value": {
"content": "Spear & Animism",
"divider": {
"discriminant": true,
"value": "⎊"
}
}
}
}
]
}

View File

@@ -1,8 +1,11 @@
import { config } from '@keystatic/core'; import { config } from '@keystatic/core';
import navigation from '@/keystatic/singletons/navigation';
export default config({ export default config({
storage: { storage: {
kind: 'local', kind: 'local',
}, },
collections: {}, collections: {},
singletons: { navigation },
}); });

View File

@@ -14,7 +14,7 @@ import customFunctions from './src/lib/postcss/functions';
const plugins = [ const plugins = [
postcssGlobalData({ postcssGlobalData({
files: ['./src/styles/variables/custom-media.css'], files: ['./src/styles/globals/custom-media.css'],
}), }),
postcssMixins({ postcssMixins({
mixinsDir: './src/styles/mixins/', mixinsDir: './src/styles/mixins/',

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 MiB

View File

@@ -1,5 +1,6 @@
import { MenuProvider } from '@/contexts/MenuContext'; import { MenuProvider } from '@/contexts/MenuContext';
import PageHeader from '@/components/Page/Header'; import PageHeader from '@/components/Page/Header';
import PageMenu from '@/components/Page/Menu';
export default function SiteLayout({ export default function SiteLayout({
children, children,
@@ -7,6 +8,7 @@ export default function SiteLayout({
return ( return (
<MenuProvider> <MenuProvider>
<PageHeader /> <PageHeader />
<PageMenu />
<main>{children}</main> <main>{children}</main>
</MenuProvider> </MenuProvider>
); );

View File

@@ -1,3 +1,82 @@
.wrapper { .wrapper {
@mixin responsive-wrapper; @mixin responsive-wrapper;
& body {
margin: 0;
padding: 2rem;
font-family: monospace;
color: #1a1a1d;
background: #f7f9fb;
}
& h1 {
margin-bottom: 2rem;
font-weight: 900;
text-transform: uppercase;
letter-spacing: 0.1em;
}
& .grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-bottom: 3rem;
}
& .demoCard {
border: 3px solid #1a1a1d;
background: white;
}
& .demoTitle {
margin: 0;
padding: 0.5rem 1rem;
font-size: 0.875rem;
font-weight: bold;
color: white;
text-transform: uppercase;
letter-spacing: 0.05em;
background: #1a1a1d;
}
& .imageContainer {
cursor: pointer;
position: relative;
overflow: hidden;
width: 100%;
height: 200px;
}
& .demoImage {
width: 100%;
height: 100%;
object-fit: cover;
filter: grayscale(100) contrast(150) brightness(100);
transition: none;
}
& .instructions {
margin-top: 2rem;
padding: 1rem;
font-family: monospace;
color: white;
background: #1a1a1d;
}
& .instructions h2 {
margin-top: 0;
text-transform: uppercase;
letter-spacing: 0.1em;
}
} }

View File

@@ -3,9 +3,491 @@ import styles from './page.module.css';
export default function Home() { export default function Home() {
return ( return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
<p> <h1>
DAVE! DAVE! Do Not Let Us Die In The Dark Night Of This Cold Winter! DAVE! DAVE! Do Not Let Us Die In The Dark Night Of This Cold Winter!
</p> </h1>
<h2>Background / Image effects</h2>
<div className={styles.grid}>
<div className={`${styles.demoCard}`}>
<h3 className={styles.demoTitle}>Overexposure Blast</h3>
<div className={styles.imageContainer}>
<img
className={`${styles.demoImage} anim-overexposure`}
src="https://images.pexels.com/photos/1096925/pexels-photo-1096925.jpeg"
alt="Demo"
/>
</div>
</div>
<div className={`${styles.demoCard}`}>
<h3 className={styles.demoTitle}>Contrast Slam</h3>
<div className={styles.imageContainer}>
<img
className={`${styles.demoImage} anim-contrastslam`}
src="https://images.pexels.com/photos/119809/pexels-photo-119809.jpeg"
alt="Demo"
/>
</div>
</div>
<div className={`${styles.demoCard}`}>
<h3 className={styles.demoTitle}>Colorbleed</h3>
<div className={styles.imageContainer}>
<img
className={`${styles.demoImage} anim-colorbleed`}
src="https://images.pexels.com/photos/12924931/pexels-photo-12924931.jpeg"
alt="Demo"
/>
</div>
</div>
<div className={`${styles.demoCard}`}>
<h3 className={styles.demoTitle}>Film Burn</h3>
<div className={styles.imageContainer}>
<img
className={`${styles.demoImage} anim-filmburn`}
src="https://images.pexels.com/photos/1031357/pexels-photo-1031357.jpeg"
alt="Demo"
/>
</div>
</div>
<div className={`${styles.demoCard}`}>
<h3 className={styles.demoTitle}>Photocopier Malfunction</h3>
<div className={styles.imageContainer}>
<img
className={`${styles.demoImage} anim-malfunction`}
src="https://images.pexels.com/photos/3054252/pexels-photo-3054252.jpeg"
alt="Demo"
/>
</div>
</div>
<div className={`${styles.demoCard}`}>
<h3 className={styles.demoTitle}>Toner Starvation</h3>
<div className={styles.imageContainer}>
<img
className={`${styles.demoImage} anim-tonerstarvation`}
src="https://images.pexels.com/photos/3822728/pexels-photo-3822728.jpeg"
alt="Demo"
/>
</div>
</div>
<div className={`${styles.demoCard}`}>
<h3 className={styles.demoTitle}>Digital Corruption</h3>
<div className={styles.imageContainer}>
<img
className={`${styles.demoImage} anim-corruption`}
src="https://images.pexels.com/photos/220793/pexels-photo-220793.jpeg"
alt="Demo"
/>
</div>
</div>
<div className={`${styles.demoCard}`}>
<h3 className={styles.demoTitle}>Stark Flash</h3>
<div className={styles.imageContainer}>
<img
className={`${styles.demoImage} anim-starkflash`}
src="https://images.pexels.com/photos/13744675/pexels-photo-13744675.jpeg"
alt="Demo"
/>
</div>
</div>
</div>
<div className={styles.instructions}>
<h2>Instructions</h2>
<p>
Hover over each image to see the effect. These are designed to work
with your base filter:
</p>
<code>filter: grayscale(1) contrast(150%) brightness(120%)</code>
<p>
You can replace the demo images with your own by changing the src
attributes. All effects use stepped animations or sharp transitions to
maintain that industrial, non-digital feel.
</p>
<p>
The effects range from subtle (Contrast Slam) to more dramatic
(Digital Corruption). Choose based on how aggressive you want the
interaction to feel.
</p>
</div>
<h2>Link Effects</h2>
<div className={styles.grid}>
{/* Your Ideas */}
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Strikethrough Mark (Marker)</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-strikethroughmarker">
strikethrough link
</a>{' '}
in the middle of it.
</p>
</div>
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Strikethrough Mark (Industrial)</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-strikethroughindustrial">
strikethrough link
</a>{' '}
in the middle of it.
</p>
</div>
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Marker Highlight [Industrial]</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-markerhighlightindustrial">
marker highlight link
</a>{' '}
in the middle of it.
</p>
</div>
{/* Stamping/Punching Effects */}
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Label Maker</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-labelmaker">
label maker link
</a>{' '}
in the middle of it.
</p>
</div>
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Rubber Stamp</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-rubberstamp">
rubber stamp link
</a>{' '}
in the middle of it.
</p>
</div>
{/* Industrial/Mechanical */}
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Press/Stamp</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-pressstamp">
pressed link
</a>{' '}
in the middle of it.
</p>
</div>
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Typewriter Underline</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-typewriter">
typewriter link
</a>{' '}
in the middle of it.
</p>
</div>
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Hard Invert</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-hardInvert">
hard invert link
</a>{' '}
in the middle of it.
</p>
</div>
{/* Marking/Annotation */}
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Bracket Annotation</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-pointer">
bracket link
</a>{' '}
in the middle of it.
</p>
</div>
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Corner Box</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-cornerbox">
corner box link
</a>{' '}
in the middle of it.
</p>
</div>
{/* Glitch/Digital */}
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Character Glitch</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-characterglitch">
glitch link
</a>{' '}
in the middle of it.
</p>
</div>
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Pixel Shift</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-pixelshift">
shifting link
</a>{' '}
in the middle of it.
</p>
</div>
{/* Extra Ideas */}
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>Redacted/Censored</h3>
<p>
This is some text with a{' '}
<a href="#" className="anim-redacted">
redacted link
</a>{' '}
in the middle of it.
</p>
</div>
<div className={styles.demoCard}>
<h3 className={styles.demoTitle}>X-Ray/Negative</h3>
<p>
This is some text with an{' '}
<a href="#" className="anim-xray">
x-ray link
</a>{' '}
in the middle of it.
</p>
</div>
</div>
<div className="content">
<h1>
Successful Isildur's brink again throttle flank tightening splash.
</h1>
<p>
Help illusion embrace liquor tightening intelligence Maggot's whips
bit forests. 17 sing impassable helps Southrons beheading. What's the
Elvish word for 'friend'?
</p>
<h2>Give Hobbitses lend yours lads picking uniting sometime.</h2>
<p>
Inferno shaken skin undo wars close circles verse suck Dwarves. I gave
you the chance of aiding me willingly, but you have elected the way of
pain! Precautions tower tied Rivendell everyone agents wouldn't?
</p>
<h3>Doorway Mithrandir clearing wielder strengths floor?</h3>
<p>
Pillaged pointy-eared mix charm Grond confounded able-bodied tact
glimpse instruction open dear. Suffering powerful capable gulls
famousest stroke breathes Bilbo squeaked pace chances. Let the
Ring-bearer decide.
</p>
<ul>
<li>Mirkwood.</li>
<li>Tom.</li>
<li>Bilbo's.</li>
<li>Gandalf's.</li>
<li>Dwarvish.</li>
</ul>
<ul>
<li>Queen wants Oin loose heads decay piety!</li>
<li>Large happening arrived owes legends wit war bled Durin's.</li>
<li>
Pursuit exactly during relief mission meats cause Noldorin ablaze
tracked.
</li>
<li>Darken knife midday meat Goblinses.</li>
<li>
Your Rabble-rousers greatest could beast thirty-four t wizards
slumbers reforge.
</li>
</ul>
<h3>Late vagabond knowing Ent legends there flattened cultured?</h3>
<p>
Swords are no more use here. Deny Chubbs restored. Scare rebuild
Argonath tracked day's large.
</p>
<ol>
<li>Easterlings!</li>
<li>Bill.</li>
<li>Dúnedain!</li>
<li>Gandalf.</li>
<li>Orcrist.</li>
</ol>
<ol>
<li>Answers feelings Elrond conjurer runs.</li>
<li>Sul nudge powerless jelly dumping hair grows log forgave?</li>
<li>
Retaken succumbed funeral courtyard Glóin incident mere somewhere
commander assistance?
</li>
<li>Bore outrun stead fight Athelas guardroom willing contains.</li>
<li>Hunted Angmar wager noose arguing?</li>
</ol>
<h3>Elros next own wisp whence cakehole right!</h3>
<p>
Thank hid its lessened lined tells prefers were Stone-Giants thousand
troubles. Earendil staff pines bog finest mushroom consumption.
Mistaken streaming fates paths arts puppet Barad-dûr uniting? You
shall not pass!
</p>
<table>
<thead>
<tr>
<th></th>
<th>Ales</th>
<th>Deeply</th>
<th>Mortality</th>
<th>Open</th>
<th>Single-handedly</th>
</tr>
</thead>
<tbody>
<tr>
<td>Band</td>
<td>appeared</td>
<td>waited</td>
<td>whose</td>
<td>plate</td>
<td>marshaling</td>
</tr>
<tr>
<td>Meat</td>
<td>nest</td>
<td>thatched</td>
<td>rallying</td>
<td>claimed</td>
<td>hungers</td>
</tr>
<tr>
<td>Mouse</td>
<td>also</td>
<td>birdses</td>
<td>moons</td>
<td>strain</td>
<td>brightest</td>
</tr>
<tr>
<td>Hate</td>
<td>different</td>
<td>arrangements</td>
<td>chiefest</td>
<td>think</td>
<td>try</td>
</tr>
<tr>
<td>Something's</td>
<td>task</td>
<td>here's</td>
<td>decent</td>
<td>someone</td>
<td>uses</td>
</tr>
<tr>
<td>Shirt</td>
<td>tonight</td>
<td>bay</td>
<td>beautifully</td>
<td>tad</td>
<td>cloaks</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>revenge</td>
<td>teaching</td>
<td>mischief</td>
<td>shores</td>
<td>dreams</td>
<td>tested</td>
</tr>
</tfoot>
</table>
<h4>Stage dishcloth 20 horses Tooks souls crawl crime.</h4>
<p>
Approve Sul wilderness grave embellishment greatly over these rack
struggle. End ringing bell Anor halls pairs thirst fortress curtain
cleared? Dwelt language 1296 Underhill nasty. I gave you the chance of
aiding me willingly, but you have elected the way of pain!
</p>
<blockquote>
<p>You are full of surprises, Master Baggins.</p>
<footer>
Girion, <cite>warmongering appears</cite>
</footer>
</blockquote>
<h5>
Sung outscoring fingers Fundin reaction inquiries buggers deadliest.
</h5>
<p>
Mustn't powerless pierces Muil sorry crossing diamond brandy. Rip
rockets hinder Braga go had web ought sakes hail. A wizard is never
late, Frodo Baggins. Nor is he early. He arrives precisely when he
means to. Ashes tie Gamgee dicky!
</p>
<pre>
Rhudaur fancy tilled heart beggars. Dwarf nothing talked foot club.
Slaughtered flatten Hobbit journey's four-day?
</pre>
<h6>Pearl tact tomb bits Arwen Evenstar worry?</h6>
<p>
Times unspoiled <time>defenses</time> Silvan.{' '}
<del>Sigrid Pippin Gandalf</del> thin stubbornness noises easily
spread. Eldar warriors <code>won answered</code> filth yourself
pocket. Showing store consistency <kbd>M</kbd> crevice. Decision
feverfew <sup>giving</sup> Misty Mountain lord supplant. Gorgoroth{' '}
<dfn>load born fulfilled plenty</dfn> fates serpent. Doorstep Pippin's{' '}
<cite>pity bridge</cite> long weak weep? Brightest <abbr>Chubbs</abbr>{' '}
jewels understand. Somewhat Erebor <sub>noise</sub> squealing moved?
Pippin's <mark>feels overrun</mark> hours brown burns. <var>Anor</var>{' '}
turning pick prophecy. Surrounded <q>entered needlessly weary</q> vile
hmm Bagshot Row. Consent <ins>outwitted dotage slug</ins> Homely hear.
Parapet <strong>protected favored defied roam</strong> quiet Dori sick
bent. <samp>Homage store hurricane</samp> prove ferret Helm's Deep
lately? <small>Excellent regret fun often</small> returned Wood-elves
apocalypse. Théodred's rights rat drawing{' '}
<a>examine dared bygone residence deeply</a>.{' '}
<em>Greenway Girion Rohirrim</em> trammel waiting edge.
</p>
<hr />
<dl>
<dt>Turn</dt>
<dd>
Bare protuberance arrived forging funny salvage Cair except first
banners.
</dd>
<dt>Foes</dt>
<dd>Bore river large house shadows it's Tuckborough warn.</dd>
<dd>
Stirring Greenwood nest sapphire grant gob flagon famous mean!
</dd>
<dt>Unprepared</dt>
<dd>
Single-handed wriggling creatures lock canopy anytime horses defense
Hobbit's?
</dd>
<dd>
Nûmenor dungeons achieving encourage fretting dines believes
understand.
</dd>
<dd>Ease love shine legs wee harbor Udùn adventure tumble stays.</dd>
</dl>
</div>
</div> </div>
); );
} }

View File

@@ -1,4 +1,6 @@
@import url("../styles/variables.css"); @layer reset, tokens, base, layout, content, components, utilities, animations;
@import url("../styles/utilities.css");
@import url("../styles/foundation.css"); @import url("../styles/tokens.css");
@import url("../styles/base.css"); @import url("../styles/globals/foundation.css");
@import url("../styles/globals/base.css");
@import url("../styles/globals/content.css");

View File

@@ -1,93 +1,77 @@
.header { @layer components {
@mixin py var(--spacing-tight); .header {
@mixin py var(--el-header-paddingY);
width: var(--dim-full); position: sticky;
color: var(--color-text-inverse); z-index: 9;
background-color: var(--color-surface-inverse); top: 0;
}
.inner { width: var(--dim-full);
@mixin responsive-wrapper;
display: flex; color: var(--color-text-inverse);
flex-direction: row;
gap: var(--spacing-cozy);
align-items: center;
justify-content: flex-start;
}
.logo { background-color: var(--color-surface-inverse);
font-family: var(--font-mono);
animation:
logo-pulse 5s cubic-bezier(0.4, 0, 0.6, 1) infinite,
logo-glitch 15s linear infinite;
animation-delay: 0s, 3s;
&:hover {
transform: translate(0, 0);
color: var(--color-secondary);
opacity: 1;
transition: all 0.2s ease;
animation: none;
} }
}
.pagename { .inner {
font-family: var(--font-mono); @mixin responsive-wrapper;
display: flex;
flex-direction: row;
gap: var(--spacing-cozy);
align-items: center;
justify-content: flex-start;
font-size: var(--el-header-font-size);
line-height: var(--el-header-line-height);
& .bracket {
color: var(--color-secondary);
} }
}
.menutoggle { .logo {
@mixin ml auto; @mixin anim-txt-characterglitch;
& button {
cursor: pointer;
font-family: var(--font-mono); font-family: var(--font-mono);
transition: color 0.2s ease-out; animation:
logo-pulse 5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
&:hover { &:hover {
color: var(--color-primary); transform: translate(0, 0);
} color: var(--color-secondary);
&:active {
transform: scale(0.95);
transition: transform 0.1s ease-out;
} }
} }
}
@keyframes logo-pulse { .pagename {
0% { opacity: 1; } font-family: var(--font-mono);
25% { opacity: 0.66; }
50% { opacity: 0.33; }
75% { opacity: 0.66; }
100% { opacity: 1; }
}
@keyframes logo-glitch { & .bracket {
0% { color: var(--color-secondary);
transform: translate(0, 0); }
color: inherit;
} }
2% { .menutoggle {
transform: translate(-2px, -2px); @mixin ml auto;
color: var(--color-primary);
& button {
cursor: pointer;
font-family: var(--font-mono);
transition: color 0.2s ease-out;
&:hover {
color: var(--color-primary);
}
&:active {
transform: scale(0.95);
transition: transform 0.1s ease-out;
}
}
} }
4% { @keyframes logo-pulse {
transform: translate(0, 0); 0% { opacity: 1; }
color: inherit; 25% { opacity: 0.66; }
} 50% { opacity: 0.33; }
75% { opacity: 0.66; }
100% { 100% { opacity: 1; }
transform: translate(0, 0);
color: inherit;
} }
} }

View File

@@ -0,0 +1,403 @@
@layer components {
/* === MenuGrid === */
.menu {
pointer-events: none;
position: fixed;
z-index: 9;
top: var(--el-header-height);
left: 0;
display: grid;
grid-auto-columns: 1fr;
grid-template-areas:
"area_1"
"area_2"
"area_3"
"area_4"
"area_5";
grid-template-columns: 1fr;
grid-template-rows: repeat(5, auto);
gap: 0;
gap: var(--spacing-cozy);
width: 100vw;
height: 100%;
max-height: calc(100vh - var(--el-header-height));
visibility: hidden;
opacity: 0;
background-color: var(--color-palette-charcoal-gray);
transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
&.isOpen {
pointer-events: auto;
visibility: visible;
opacity: 1;
}
@media screen and (--bp-tablet) {
@mixin px var(--spacing-comfortable);
grid-template-areas:
"area_1"
"area_2"
"area_3"
"area_4"
"area_5";
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: var(--spacing-comfortable);
}
@media screen and (--bp-desktop) {
display: grid;
grid-template-areas:
"area_4 area_4 area_3 area_3 area_3 area_3 area_2"
"area_4 area_4 area_3 area_3 area_3 area_3 area_2"
"area_5 area_5 area_3 area_3 area_3 area_3 area_2"
"area_5 area_5 area_3 area_3 area_3 area_3 area_1"
"area_5 area_5 area_3 area_3 area_3 area_3 area_1";
grid-template-columns: 2.5fr 1fr 3fr 1.5fr 1fr 1fr 4fr;
grid-template-rows: 3fr 1fr 2.5fr 1.5fr 2fr;
}
}
/* === MenuArea === */
.area {
/* === AREA VARIABLES === */
--area-bg: transparent;
--area-border: transparent;
--area-animation-keyframe: none;
--area-animation-duration: 0s;
--area-animation-timing: linear;
--area-bg-filter: grayscale(100%) contrast(150) brightness(150);
/** === TITLE VARIABLES === */
--title-color: var(--color-palette-light-silver);
--title-font: var(--font-header);
--title-font-size: var(--typo-size-2xl);
--title-font-weight: var(--typo-weight-black);
--title-line-height: 1;
--title-transform: uppercase;
--title-spacing: var(--typo-spacing-comfortable);
--title-hover-color: var(--color-tertiary);
--title-current-color: var(--color-primary);
--title-current-bg: var(--color-primary);
/** === SUBLINK VARIABLES === */;
--sublink-color: var(--color-palette-light-silver);
--sublink-font: var(--font-header);
--sublink-font-size: var(--typo-size-2xl);
--sublink-font-weight: var(--typo-weight-black);
--sublink-transform: uppercase;
--sublink-spacing: var(--typo-spacing-relaxed);
--sublink-line-height: var(--typo-leading-relaxed);
--sublink-letter-spacing: var(--typo-spacing-relaxed);
--sublink-current-color: var(--color-primary);
--sublink-current-bg: var(--color-primary);
/** === SUBTITLE VARIABLES === **/
--divider-color: var(--color-palette-light-silver);
--divider-width: var(--size-6);
--divider-height: var(--size-2);
--divider-font: var(--font-mono);
--divider-symbol: ;
--divider-font-size: var(--typo-size-2xl);
--divider-padding: 0 var(--typo-spacing-cozy);
--subtitle-color: var(--color-palette-light-silver);
--subtitle-font: var(--font-mono);
--subtitle-font-size: var(--typo-size-2xl);
--subtitle-text-transform: uppercase;
--subtitle-letter-spacing: var(--typo-spacing-cozy);
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: var(--size-1) solid var(--area-border);
text-align: center;
background: var(--area-bg);
transition: all 0.2s ease-in-out;
&:not(.current) {
&:hover {
animation: var(--area-animation-keyframe) var(--area-animation-duration) var(--area-animation-timing);
}
}
}
.area_1 { grid-area: area_1; }
.area_2 { grid-area: area_2; }
.area_3 { grid-area: area_3; }
.area_4 { grid-area: area_4; }
.area_5 { grid-area: area_5; }
.hasBGImg {
&:hover {
.bgImg {
animation: var(--area-animation-keyframe) var(--area-animation-duration) var(--area-animation-timing);
}
}
}
.bgImg {
position: absolute;
z-index: -1;
width: 100%;
height: 100%;
object-fit: cover;
filter: var(--area-bg-filter);
@media screen and (--bp-tablet-down) {
display: none;
}
}
/* === MenuTitle === */
.title {
position: relative;
}
.mainlink {
position: relative;
font-family: var(--title-font);
font-size: var(--title-font-size);
font-weight: var(--title-font-weight);
line-height: var(--title-line-height);
color: var(--title-color);
text-transform: var(--title-transform);
letter-spacing: var(--title-spacing);
transition: any 0.5s ease-in-out;
&:focus {
&:hover {
color: var(--title-current-color);
}
@media screen and (--bp-tablet-down) {
outline: none;
&:hover {
color: var(--title-current-color);
}
}
}
&.current {
pointer-events: none;
@media screen and (--bp-tablet-down) {
&:hover {
color: var(--title-current-color);
}
}
@media screen and (--bp-desktop) {
}
}
@media screen and (--bp-tablet-down) {
transition: border 0.5s ease-in-out;
}
}
/* === MenuSublinks === */
.list {
@media screen and (--bp-tablet-down) {
display: none;
}
}
.item {
position: relative;
}
.sublink {
position: relative;
font-family: var(--sublink-font);
font-size: var(--sublink-font-size);
font-weight: var(--sublink-font-weight);
line-height: var(--sublink-line-height);
color: var(--sublink-color);
text-transform: var(--sublink-transform);
letter-spacing: var(--sublink-spacing);;
&:not(.current),
&:not(.focus) {
transition: var(--sublink-hover-transition);
&::after,
&::before {
position: absolute;
font-family: var(--sublink-hover-decorator-font);
opacity: 0;
transition: var(--sublink-hover-decorator-transition);
}
&::before {
content: var(--sublink-hover-decorator-left-symbol);
left: 0;
}
&::after {
content: var(--sublink-hover-decorator-right-symbol);
right: 0;
}
&:hover {
color: var(--sublink-hover-color);
&::before {
top: var(--sublink-hover-decorator-left-pos-y);
left: var(--sublink-hover-decorator-left-pos-x);
transform: var(--sublink-hover-decorator-left-transform);
opacity: 1;
}
&::after {
top: var(--sublink-hover-decorator-right-pos-y);
right: var(--sublink-hover-decorator-rightt-pos-x);
transform: var(--sublink-hover-decorator-right-transform);
opacity: 1;
}
}
&:focus {
&:hover {
color: var(--sublink-current-color);
}
}
&.current {
pointer-events: none;
}
}
}
/* === MenuSubtitle === */
.wrapper {
position: relative;
@media screen and (--bp-tablet-down) {
display: none;
}
}
/* === UTILITY Classes */
@media screen and (--bp-desktop) {
.pos_tr {
position: absolute;
top: 1em;
right: 1em;
}
.pos_tc {
position: absolute;
top: 1em;
left: 50%;
transform: translateX(-50%);
}
.pos_tl {
position: absolute;
top: 1em;
left: 1em;
}
.pos_cr {
position: absolute;
top: 50%;
right: 1em;
transform: translateY(-50%);
}
.pos_c {
position: absolute;
bottom: 50%;
left: 50%;
transform: translate(-50%, 50%);
}
.pos_cl {
position: absolute;
top: 50%;
right: 1em;
transform: translateY(-50%);
}
.pos_br {
position: absolute;
right: 1em;
bottom: 1em;
}
.pos_bc {
position: absolute;
bottom: 1em;
left: 50%;
transform: translateX(-50%);
}
.pos_bl {
position: absolute;
bottom: 1em;
left: 1em;
}
.vertical-rl {
writing-mode: vertical-rl;
& * {
writing-mode: vertical-rl;
}
}
.vertical-lr {
writing-mode: vertical-lr;
& * {
writing-mode: vertical-lr;
}
}
.sideways-rl {
writing-mode: sideways-rl;
& * {
writing-mode: sideways-rl;
}
}
.sideways-lr {
writing-mode: sideways-lr;
& * {
writing-mode: sideways-lr;
}
}
}
/* === CATEGORY Variants === */
@media screen and (--bp-desktop) {
.meta {}
.kitchensink {}
.awq {}
.worldburner {}
.chainbreaker {}
}
}

View File

@@ -0,0 +1,121 @@
@layer components {
.area {
--area-bg: transparent;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
background: var(--area-bg);
@media screen and (--bp-tablet-down) {
border-bottom: var(--size-1) solid var(--color-palette-gunmetal);
&:last-child {
border-bottom: none;
}
}
}
.area_1 {
position: relative;
grid-area: area_1;
}
.area_2 {
position: relative;
grid-area: area_2;
}
.area_3 {
position: relative;
grid-area: area_3;
}
.area_4 {
position: relative;
grid-area: area_4;
}
.area_5 {
position: relative;
grid-area: area_5;
}
.hasBGImg {
position: relative;
&:hover {
& .bgImg {
animation: var(--area-animation-keyframe) var(--area-animation-duration) var(--area-animation-timing);
}
}
}
.bgImg {
--area-bg-animation-keyframe: none;
--area-bg--animation-duration: 0s;
--area-bg--animation-timing: linear;
--area-bg-filter: grayscale(100%) contrast(150) brightness(150);
position: absolute;
z-index: -1;
width: 100%;
height: 100%;
object-fit: cover;
filter: var(--area-bg-filter);
@media screen and (--bp-tablet-down) {
display: none;
}
}
@media screen and (--bp-desktop) {
.chainbreaker {
--area-animation-keyframe: var(--kf-color-bleed);
--area-animation-duration: var(--img-colorbleed-duration);
--area-animation-timing: var(--img-colorbleed-timing);
& .bgImg {
z-index: -2;
}
&.hasBGImg {
--divider-color: transparent;
--title-color: transparent;
--subtitle-color: transparent;
--subtitle-transition: all 0.3s ease-in-out;
--title-transition: color 0.3s ease-in-out;
&::before {
content: "";
position: absolute;
z-index: -1;
width: 100%;
height: 100%;
opacity: 0;
background: alpharize(var(--grid-bg), 0.66);
}
&:hover {
--divider-color: var(--color-tertiary);
--title-color: var(--color-tertiary);
--subtitle-color: var(--color-tertiary);
&::before {
opacity: 1;
}
}
}
}
}
}

View File

@@ -0,0 +1,46 @@
import React from 'react';
import MenuItem from '@/components/Page/Menu//MenuItem/';
import { useCurrentPath } from '@/hooks/useCurrentPath';
import styles from './MenuArea.module.css';
import { NavigationItem } from '@/lib/types/navigation';
interface MenuAreaProps {
item: NavigationItem;
}
const MenuArea = React.memo(({ item }: MenuAreaProps) => {
const hasBGImg = !!item.background;
const { isCurrentPath } = useCurrentPath();
const areaClasses = React.useMemo(() => {
return [
styles.area,
styles[item.gridPosition],
styles[item.variant],
isCurrentPath(item.path) ? styles.current : '',
item.background ? styles.hasBGImg : null,
]
.filter(Boolean)
.join(' ');
}, [item.background, isCurrentPath]);
return (
<section className={areaClasses}>
{hasBGImg && (
<img
className={styles.bgImg}
src={item.background}
alt={`Background Image for ${item.name}`}
/>
)}
<MenuItem item={item} />
</section>
);
});
MenuArea.displayName = 'MenuArea';
export default MenuArea;

View File

@@ -0,0 +1,97 @@
@layer components {
.menu {
--grid-bg: var(--color-palette-charcoal-gray);
--grid-fg: var(--color-palette-light-silver);
/* === MenuTitle Vars === */
--title-color: var(--grid-fg);
--title-font: var(--font-mono);
--title-font-size: var(--typo-size-2xl);
--title-font-weight: var(--typo-weight-black);
--title-line-height: 1;
--title-transform: uppercase;
--title-spacing: var(--typo-spacing-comfortable);
--title-hover-fg: var(--primary);
--title-hover-bg: transparent;
--title-current-bg: var(--color-tertiary);
--title-current-fg: var(--grid-bg);
--title-focus-fg: var(--color-secondary);
--title-focus-bg: var(--grid-bg);
--title-transition: none;
/* === MenuSublinks Vars === */
--sublink-color: var(--grid-fg);
--sublink-font: var(--font-mono);
--sublink-font-size: var(--typo-size-xl);
--sublink-font-weight: var(--typo-weight-light);
--sublink-transform: uppercase;
--sublink-line-height: var(--typo-leading-relaxed);
--sublink-spacing: var(--typo-spacing-loosest);
--sublink-hover-fg: var(--color-tertiary);
--sublink-hover-bg: transparent;
--sublink-current-fg: var(--grid-bg);
--sublink-current-bg: var(--color-primary);
--sublink-focus-fg: var(--color-secondary);
--sublink-focus-bg: var(--grid-bg);
--sublink-transition: none;
/* === MenuSubtitle Vars === */
--divider-color: var(--grid-fg);
--divider-width: var(--size-12);
--divider-height: var(--size-2);
--divider-font: var(--font-mono);
--divider-font-size: var(--typo-size-2xl);
--divider-padding: 0 var(--typo-spacing-cozy);
--subtitle-font: var(--font-mono);
--subtitle-color: var(--grid-fg);
--subtitle-font-size: var(--typo-size-xl);
--subtitle-text-transform: uppercase;
--subtitle-letter-spacing: var(--typo-spacing-cozy);
--subtitle-transition: none;
pointer-events: none;
position: fixed;
z-index: 9;
top: var(--el-header-height);
left: 0;
display: grid;
grid-auto-columns: 1fr;
grid-template-areas:
"area_1"
"area_2"
"area_3"
"area_4"
"area_5";
grid-template-columns: 1fr;
grid-template-rows: repeat(5, auto);
width: 100vw;
height: calc(100vh - var(--el-header-height));
color: var(--grid-fg);
visibility: hidden;
opacity: 0;
background-color: var(--grid-bg);
&.isOpen {
pointer-events: auto;
visibility: visible;
opacity: 1;
}
@media screen and (--bp-desktop) {
display: grid;
grid-template-areas:
"area_4 area_4 area_3 area_3 area_3 area_3 area_2"
"area_4 area_4 area_3 area_3 area_3 area_3 area_2"
"area_5 area_5 area_3 area_3 area_3 area_3 area_2"
"area_5 area_5 area_3 area_3 area_3 area_3 area_1"
"area_5 area_5 area_3 area_3 area_3 area_3 area_1";
grid-template-columns: 2.5fr 1fr 3fr 1.5fr 1fr 1fr 4fr;
grid-template-rows: 3fr 1fr 2.5fr 1.5fr 2fr;
}
}
}

View File

@@ -0,0 +1,67 @@
'use client';
import React from 'react';
import { useMenu } from '@/contexts/MenuContext';
import MenuArea from '@/components/Page/Menu/MenuArea/';
import styles from './MenuGrid.module.css';
interface MenuGridProps {
navigationData: Awaited<
ReturnType<
typeof import('@/lib/readers/system/navigation').getNavigationData
>
>;
}
export default function MenuGrid({ navigationData }: MenuGridProps) {
const { isMenuOpen, closeMenu } = useMenu();
const menuRef = React.useRef<HTMLElement>(null);
const [isClosing, setIsClosing] = React.useState(false);
const handleClose = React.useCallback(() => {
setIsClosing(true);
setTimeout(() => {
closeMenu();
setIsClosing(false);
}, 800);
}, [closeMenu]);
React.useEffect(() => {
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape' && isMenuOpen) {
handleClose();
}
};
document.addEventListener('keydown', handleEscape);
return () => document.removeEventListener('keydown', handleEscape);
}, [isMenuOpen, handleClose]);
React.useEffect(() => {
if (isMenuOpen && menuRef.current) {
const initialFocus = menuRef.current.querySelector(
'a, button'
) as HTMLElement;
initialFocus?.focus();
}
}, [isMenuOpen]);
if (!navigationData) return null;
const { items } = navigationData;
return (
<nav
ref={menuRef}
className={`${styles.menu} ${isMenuOpen ? styles.isOpen : ''} ${isClosing ? styles.isClosing : ''}`}
aria-hidden={!isMenuOpen}
aria-label="Main navigation"
>
{items.map((item, index) => (
<MenuArea key={item.gridPosition} item={item} />
))}
</nav>
);
}

View File

@@ -0,0 +1,24 @@
import { hasSublinks, hasSubtitle } from '@/lib/types/navigation';
import MenuTitle from '@/components/Page/Menu/MenuTitle/';
import MenuSublinks from '@/components/Page/Menu/MenuSublinks/';
import MenuSubtitle from '@/components/Page/Menu/MenuSubtitle/';
import { NavigationItem } from '@/lib/types/navigation';
interface MenuItem {
item: NavigationItem;
}
export default function MenuItem({ item }: MenuItem) {
return (
<>
<MenuTitle path={item.path} name={item.name} variant={item.variant} />
{hasSublinks(item) && (
<MenuSublinks sublinks={item.sublinks.value} variant={item.variant} />
)}
{hasSubtitle(item) && (
<MenuSubtitle subtitle={item.subtitle.value} variant={item.variant} />
)}
</>
);
}

View File

@@ -0,0 +1,57 @@
@layer components {
.list {
@media screen and (--bp-tablet-down) {
@util hide-visually;
}
}
.item {
position: relative;
}
.sublink {
font-family: var(--sublink-font);
font-size: var(--sublink-font-size);
font-weight: var(--sublink-font-weight);
line-height: var(--sublink-line-height);
color: var(--sublink-color);
text-transform: var(--sublink-transform);
letter-spacing: var(--sublink-spacing);
&.current {
padding: var(--spacing-snug) var(--spacing-tight);
color: var(--title-current-fg);
animation: var(--kf-text-glitch) 5s infinite;
&::before {
content: "⟩";
}
}
&:not(.current) {
--pointer-left-symbol: "▶";
--pointer-right-symbol: "◀";
--pointer-distance: 1em;
@mixin anim-txt-pointer_focus;
@mixin px var(--spacing-tight);
&:focus {
color: var(--sublink-focus-fg);
outline: none;
}
&:not(:focus) {
--pointer-left-symbol: "{";
--pointer-right-symbol: "}";
--pointer-distance: 0.5em;
@mixin anim-txt-pointer;
&:hover {
--sublink-color: var(--color-primary);
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
import Link from 'next/link';
import styles from './MenuSublinks.module.css';
import { SubNavigationItem } from '@/lib/types/navigation';
import { useCurrentPath } from '@/hooks/useCurrentPath';
interface MenuSublinks {
sublinks: readonly SubNavigationItem[];
variant: string;
}
export default function MenuSublinks({ sublinks, variant }: MenuSublinks) {
const { isCurrentPath } = useCurrentPath();
return (
<ul className={`${styles.list} ${styles[`${variant}`]}`}>
{sublinks.map((sublink: SubNavigationItem) => (
<li className={styles.item} key={sublink.path}>
<Link
href={sublink.path}
className={`${styles.sublink} ${isCurrentPath(sublink.path) ? styles.current : ''}`}
>
{sublink.name}
</Link>
</li>
))}
</ul>
);
}

View File

@@ -0,0 +1,57 @@
@layer components {
.claim {
@media screen and (--bp-tablet-down) {
display: none;
}
}
.divider {
position: relative;
width: 100%;
text-align: center;
}
.dividersymbol {
position: relative;
font-family: var(--divider-font);
font-size: var(--divider-font-size);
line-height: var(--divider-line-height);
color: var(--divider-color);
transition: var(--subtitle-transition);
&::before,
&::after {
content: '';
position: absolute;
top: 50%;
transform: translateY(-50%);
width: var(--divider-width);
height: var(--divider-height);
background-color: var(--divider-color);
}
&::before {
left: calc(var(--divider-width) *-1);
}
&::after {
right: calc(var(--divider-width) *-1);
}
}
.subtitle {
font-family: var(--subtitle-font);
font-size: var(--subtitle-font-size);
color: var(--subtitle-color);
text-transform: var(--subtitle-text-transform);
letter-spacing: var(--subtitle-letter-spacing);
transition: var(--subtitle-transition);
}
}

View File

@@ -0,0 +1,26 @@
import { Subtitle, hasDivider } from '@/lib/types/navigation';
import styles from './MenuSubtitle.module.css';
interface MenuSubtitleProps {
subtitle: Subtitle;
variant: string;
}
export default function MenuSubtitle({ subtitle, variant }: MenuSubtitleProps) {
const divider = hasDivider(subtitle) ? (
<div className={styles.divider}>
<span className={`${styles.dividersymbol}`}>
{subtitle.divider.value}
</span>
</div>
) : (
''
);
return (
<div className={`${styles.claim} ${styles[`${variant}`]}`}>
{divider}
<p className={`${styles.subtitle}`}>{subtitle.content}</p>
</div>
);
}

View File

@@ -0,0 +1,63 @@
@layer components {
.heading {
position: relative;
&:has(+ ul) {
@mixin my var(--spacing-comfortable);
}
}
.mainlink {
position: relative;
border: none;
font-family: var(--title-font);
font-size: var(--title-font-size);
font-weight: var(--title-font-weight);
line-height: var(--title-line-height);
color: var(--title-color);
text-transform: var(--title-transform);
letter-spacing: var(--title-spacing);
background: transparent;
transition: var(--title-transition);
&.current {
padding: var(--spacing-snug) var(--spacing-tight);
color: var(--title-current-fg);
animation: var(--kf-text-glitch) 5s infinite;
&::before {
content: "⟩";
}
}
&:not(.current) {
--pointer-left-symbol: "▶";
--pointer-right-symbol: "◀";
--pointer-distance: 1em;
@mixin anim-txt-pointer_focus;
@mixin px var(--spacing-tight);
&:focus {
color: var(--title-focus-fg);
outline: none;
}
&:not(:focus) {
--pointer-left-symbol: "{";
--pointer-right-symbol: "}";
--pointer-distance: 0.5em;
@mixin anim-txt-pointer;
&:hover {
--title-color: var(--color-primary);
}
}
}
}
}

View File

@@ -0,0 +1,25 @@
import Link from 'next/link';
import styles from './MenuTitle.module.css';
import { useCurrentPath } from '@/hooks/useCurrentPath';
interface MenuTitleProps {
name: string;
path: string;
variant: string;
}
export default function MenuTitle({ name, path, variant }: MenuTitleProps) {
const { isCurrentPath } = useCurrentPath();
return (
<h2 className={`${styles.heading} ${styles[`${variant}`]}`}>
<Link
className={`${styles.mainlink} ${isCurrentPath(path) ? styles.current : ''}`}
href={path}
>
{name}
</Link>
</h2>
);
}

View File

@@ -0,0 +1,7 @@
import { getNavigationData } from '@/lib/readers/system/navigation';
import MenuGrid from '@/components/Page/Menu/MenuGrid';
export default async function Menu() {
const navigation = await getNavigationData();
return <MenuGrid navigationData={navigation} />;
}

View File

@@ -16,7 +16,7 @@ interface MenuProviderProps {
} }
export const MenuProvider = ({ children }: MenuProviderProps) => { export const MenuProvider = ({ children }: MenuProviderProps) => {
const [isMenuOpen, setIsMenuOpen] = React.useState(false); const [isMenuOpen, setIsMenuOpen] = React.useState(true);
const toggleMenu = () => setIsMenuOpen(!isMenuOpen); const toggleMenu = () => setIsMenuOpen(!isMenuOpen);
const closeMenu = () => setIsMenuOpen(false); const closeMenu = () => setIsMenuOpen(false);
@@ -33,16 +33,6 @@ export const MenuProvider = ({ children }: MenuProviderProps) => {
}; };
}, [isMenuOpen]); }, [isMenuOpen]);
useEffect(() => {
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape' && isMenuOpen) {
closeMenu();
}
};
document.addEventListener('keydown', handleEscape);
return () => document.removeEventListener('keydown', handleEscape);
}, [isMenuOpen]);
return ( return (
<MenuContext.Provider <MenuContext.Provider
value={{ isMenuOpen, toggleMenu, openMenu, closeMenu }} value={{ isMenuOpen, toggleMenu, openMenu, closeMenu }}

View File

@@ -0,0 +1,8 @@
import { usePathname } from 'next/navigation';
export const useCurrentPath = () => {
const pathname = usePathname();
const isCurrentPath = (path: string) => path === pathname;
return { isCurrentPath, pathname };
};

View File

@@ -0,0 +1,116 @@
// ============= KEYSTATIC SCHEMA =============
import { fields, singleton } from '@keystatic/core';
export default singleton({
label: 'Navigation',
path: 'content/system/navigation',
format: 'json',
schema: {
items: fields.array(
fields.object({
name: fields.text({
label: 'Name',
validation: { isRequired: true },
}),
path: fields.url({
label: 'Path',
description: 'Omit starting slash (/)',
validation: { isRequired: true },
}),
gridPosition: fields.select({
label: 'Grid Position',
defaultValue: '',
options: [
{ label: 'None', value: '' },
{ label: 'Area 1', value: 'area_1' },
{ label: 'Area 2', value: 'area_2' },
{ label: 'Area 3', value: 'area_3' },
{ label: 'Area 4', value: 'area_4' },
{ label: 'Area 5', value: 'area_5' },
],
}),
variant: fields.select({
label: 'Style Variant',
description: 'Visual style and animations for this menu item',
defaultValue: 'default',
options: [
{ label: 'Default', value: 'default' },
{ label: 'Advanced Warhammer Quest', value: 'awq' },
{ label: 'The Metatron', value: 'meta' },
{ label: 'Kitchensink', value: 'kitchensink' },
{ label: 'Worldburner', value: 'worldburner' },
{ label: 'Chainbreaker', value: 'chainbreaker' },
],
}),
background: fields.image({
label: 'Background Image',
description: 'Optional background image for this menu area',
directory: 'public/images/categories',
publicPath: '/images/categories',
}),
sublinks: fields.conditional(
fields.checkbox({ label: 'Show Sublinks' }),
{
false: fields.empty(),
true: fields.array(
fields.object({
name: fields.text({
label: 'Name',
validation: { isRequired: true },
}),
path: fields.url({
label: 'Path',
validation: { isRequired: true },
}),
}),
{
label: 'Sub Navigation Items',
itemLabel: (props) =>
props.fields.name.value || 'Untitled Sub Item',
}
),
}
),
subtitle: fields.conditional(
fields.checkbox({ label: 'Show Subtitle' }),
{
false: fields.empty(),
true: fields.object({
content: fields.text({
label: 'Subtitle Text',
validation: { isRequired: true },
}),
divider: fields.conditional(
fields.checkbox({
label: 'Show Divider',
defaultValue: false,
}),
{
true: fields.text({
label: 'Symbol',
description: 'Decorative symbol (e.g., ⚡, ◆, ▲)',
defaultValue: '◆',
}),
false: fields.empty(),
}
),
}),
}
),
}),
{
label: 'Menu Items',
itemLabel: (props) =>
`${props.fields.name.value || 'Untitled'} (${props.fields.gridPosition.value || 'No Position'})`,
}
),
},
});

View File

@@ -1,5 +1,5 @@
module.exports = { module.exports = {
alpharize: (color: string, opacity: number) => { alpharize: (color: string, opacity: number) => {
return `oklch(from ${color} l c h / ${opacity}`; return `oklch(from ${color} l c h / ${opacity})`;
}, },
}; };

6
src/lib/readers/base.ts Normal file
View File

@@ -0,0 +1,6 @@
import { createReader } from '@keystatic/core/reader';
import { cache } from 'react';
import keystaticConfig from '~/keystatic.config';
export const reader = createReader(process.cwd(), keystaticConfig);
export { cache };

View File

@@ -0,0 +1,5 @@
import { cache, reader } from '../base';
export const getNavigationData = cache(async () => {
return await reader.singletons.navigation.read();
});

View File

@@ -0,0 +1,70 @@
export type MenuVariant =
| 'default'
| 'awq'
| 'meta'
| 'kitchensink'
| 'worldburner'
| 'chainbreaker';
export type GridPosition =
| 'area_1'
| 'area_2'
| 'area_3'
| 'area_4'
| 'area_5'
| '';
export interface SubNavigationItem {
readonly name: string;
readonly path: string;
}
export interface Subtitle {
readonly content: string;
readonly divider:
| { readonly discriminant: true; readonly value: string }
| { readonly discriminant: false };
}
export interface NavigationItem {
readonly name: string;
readonly path: string;
readonly gridPosition: GridPosition;
readonly variant: MenuVariant;
readonly background: string | null;
readonly sublinks:
| { readonly discriminant: false }
| {
readonly discriminant: true;
readonly value: readonly SubNavigationItem[];
};
readonly subtitle:
| { readonly discriminant: false }
| { readonly discriminant: true; readonly value: Subtitle };
}
export interface Navigation {
readonly items: readonly NavigationItem[];
}
// Type guards for conditional fields
export function hasSublinks(item: NavigationItem): item is NavigationItem & {
readonly sublinks: {
readonly discriminant: true;
readonly value: readonly SubNavigationItem[];
};
} {
return item.sublinks.discriminant === true;
}
export function hasSubtitle(item: NavigationItem): item is NavigationItem & {
readonly subtitle: { readonly discriminant: true; readonly value: Subtitle };
} {
return item.subtitle.discriminant === true;
}
export function hasDivider(subtitle: Subtitle): subtitle is Subtitle & {
readonly divider: { readonly discriminant: true; readonly value: string };
} {
return subtitle.divider.discriminant === true;
}

View File

@@ -0,0 +1,8 @@
export const mapClassnames = (
classnames: readonly string[],
styles: Record<string, string>
) =>
classnames
.map((cn) => styles[cn])
.filter(Boolean)
.join(' ');

View File

@@ -1,13 +0,0 @@
html {
font-size: var(--font-size-base);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
font-family: var(--font-geist-sans);
font-weight: var(--typo-weight-normal);
color: var(--color-text-primary);
background-color: var(--color-surface-base);
}

View File

@@ -1,370 +0,0 @@
/*
Foundation inspired by Tailwind CSS Preflight. (https://tailwindcss.com/docs/preflight)
*/
/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/
*,
::before,
::after {
box-sizing: border-box; /* 1 */
border-style: solid; /* 2 */
border-width: 0; /* 2 */
}
/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the system's `sans` font-family by default.
*/
html {
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */
line-height: 1.5; /* 1 */
text-size-adjust: 100%; /* 2 */
tab-size: 4; /* 3 */
}
/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/
body {
margin: 0; /* 1 */
line-height: inherit; /* 2 */
}
/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/
hr {
height: 0; /* 1 */
border-top-width: 1px; /* 3 */
color: inherit; /* 2 */
}
/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/
abbr:where([title]) {
text-decoration: underline dotted;
}
/*
Remove the default font size and weight for headings.
*/
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
/*
Reset links to optimize for opt-in styling instead of opt-out.
*/
a {
color: inherit;
text-decoration: inherit;
}
/*
Add the correct font weight in Edge and Safari.
*/
b,
strong {
font-weight: bolder;
}
/*
1. Use the system's `mono` font family by default.
2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
"Liberation Mono", "Courier New", monospace; /* 1 */
font-size: 1em; /* 2 */
}
/*
Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/
table {
border-collapse: collapse; /* 3 */
border-color: inherit; /* 2 */
text-indent: 0; /* 1 */
}
/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/
button,
input,
optgroup,
select,
textarea {
margin: 0; /* 2 */
padding: 0; /* 3 */
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
font-weight: inherit; /* 1 */
line-height: inherit; /* 1 */
color: inherit; /* 1 */
}
/*
Remove the inheritance of text transform in Edge and Firefox.
*/
button,
select {
text-transform: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
appearance: auto; /* 1 */
background-color: transparent; /* 2 */
background-image: none; /* 2 */
}
/*
Use the modern Firefox focus style for all focusable elements.
*/
:-moz-focusring {
outline: auto;
}
/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/
:-moz-ui-invalid {
box-shadow: none;
}
/*
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
vertical-align: baseline;
}
/*
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type="search"] {
appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/*
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
appearance: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
font: inherit; /* 2 */
appearance: auto; /* 1 */
}
/*
Add the correct display in Chrome and Safari.
*/
summary {
display: list-item;
}
/*
Removes the default spacing and border for appropriate elements.
*/
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
fieldset {
margin: 0;
padding: 0;
}
legend {
padding: 0;
}
ol,
ul,
menu {
margin: 0;
padding: 0;
list-style: none;
}
/*
Prevent resizing textareas horizontally by default.
*/
textarea {
resize: vertical;
}
/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
*/
input::placeholder,
textarea::placeholder {
opacity: 1; /* 1 */
}
/*
Set the default cursor for buttons.
*/
button,
[role="button"] {
cursor: pointer;
}
/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
cursor: default;
}
/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
This can trigger a poorly considered lint error in some tools but is included by design.
*/
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block; /* 1 */
vertical-align: middle; /* 2 */
}
/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/
img,
video {
max-width: 100%;
height: auto;
}
/*
Make elements with the HTML hidden attribute stay hidden by default.
*/
[hidden] {
display: none;
}

View File

@@ -0,0 +1,418 @@
@layer animations {
:root {
/* === IMAGE ANIMATION VARIABLES === */
--img-overexposure-duration: 0.3s;
--img-overexposure-timing: ease-out forwards;
--img-contrastslam-duration: 0.1s;
--img-contrastslam-timing: steps(3, end);
--img-colorbleed-duration: 0.5s;
--img-colorbleed-timing: steps(6, end) forwards;
--img-filmburn-duration: 0.4s;
--img-filmburn-timing: steps(4, end) forwards;
--img-malfunction-duration: 0.6s;
--img-malfunction-timing: steps(6, end) forwards;
--img-tonerstarvation-duration: 0.5s;
--img-tonerstarvation-timing: steps(5, end) forwards;
--img-corruption-duration: 0.4s;
--img-corruption-timing: steps(8, end) forwards;
--img-starkflash-duration: 0.2s;
--img-starkflash-timing: linear forwards;
/* == Base filter values == */
--base-grayscale: 100;
--base-contrast: 150;
--base-brightness: 120;
/* === TEXT ANIMATION VARIABLES === */
/* == Strike Variables == */
--strike-color: var(--color-primary);
--strike-duration: 0.3s;
--strike-timing: cubic-bezier(0.4, 0, 0.2, 1);
--strike-radius: 50% / 0.25em 0.5em 0.9em 0.7em;
--strike-border-width: 0.25em;
--strike-height: 0.1875em;
/* == Marker Highlight Variables == */
--marker-bg: var(--color-surface-inverse);
--marker-fg: var(--color-text-inverse);
--marker-duration: 0.4s;
--marker-timing: cubic-bezier(0.68, -0.55, 0.265, 1.55);
/* == Label Maker Variables == */
--label-duration: 0.1s;
--label-timing: cubic-bezier(0.68, -0.55, 0.265, 1.55);
--label-bg: var(--color-surface-inverse);
--label-fg: var(--color-text-inverse);
--label-margin: -0.2em -0.4em;
--label-padding: 0.2em 0.4em;
--label-border-width: 0.125em;
--label-weight: bold;
--label-transform: uppercase;
--label-spacing: 0.05em;
--label-shadow-offset: 0.125em 0.125em;
--label-shadow-color: alpharize(var(--label-bg), 0.3);
/* == Rubber Stamp Variables == */
--stamp-duration: 0.08s;
--stamp-timing: steps(2, end);
--stamp-bg: var(--color-surface-inverse);
--stamp-fg: var(--color-text-inverse);
--stamp-rotate: -2deg;
--stamp-scale: 0.95;
--stamp-translate: 1px;
--stamp-margin: -0.2em -0.4em;
--stamp-padding: 0.2em 0.4em;
--stamp-border-width: 0.25em;
--stamp-weight: 900;
--stamp-transform: uppercase;
--stamp-spacing: 0.2em;
--stamp-shadow-offset: 0.125em 0.125em;
--stamp-shadow-color: alpharize(var(--stamp-fg), 0.8);
/* Press Stamp Variables */
--press-duration: 0.06s;
--press-timing: c linear;
--press-bg: var(--color-surface-elevated-4);
--press-fg: var(--color-text-inverse);
--press-scale-y: 0.85;
--press-scale-x: 1.05;
--press-translate: 3px;
--press-margin: -0.05em -0.15em;
--press-padding: 0.05em 0.15em;
--press-weight: 900;
--press-spacing: 0.1em;
--press-border-color: var(--color-surface-elevated-4);
--press-shadow-1: var(--color-surface-inverse);
--press-shadow-2: alpharize(var(--stamp-fg), 0.7);
/* Typewriter Variables */
--typewriter-color: var(--color-text-primary);
--typewriter-duration: 0.6s;
--typewriter-timing: steps(15, end);
--typewriter-offset: -3px;
--typewriter-height: 2px;
--typewriter-dash-length: 0.4em;
--typewriter-gap-length: 0.45em;
/* Hard Invert Variables */
--invert-duration: 0.8s;
--invert-timing: steps(2, end);
--invert-bg: var(--color-surface-inverse);
--invert-fg: var(--color-text-inverse);
--invert-scale: 1.02;
--invert-weight: 900;
--invert-spacing: 0.05em;
/* Pointer Variables */
--pointer-color: inherit;
--pointer-transition: all 0.3s ease-out;
--pointer-left-symbol: '[';
--pointer-right-symbol: ']';
--pointer-distance: 0.375em;
/* Corner Box Variables */
--corner-margin: -0.3em;
--corner-padding: 0.3em;
--corner-size: 0.5em;
--corner-border: 2px solid var(--color-text-primary);
--corner-transition: all 0.75s ease-out;
--corner-font-weight: 600;
/* Character Glitch Variables */
--glitch-duration: 0.3s;
--glitch-timing: steps(8, end);
--glitch-text-shadow-1: 2px 0 var(--color-palette-heliotrope), -2px 0 var(--color-palette-electric-blue);
--glitch-text-shadow-2: 1px 0 var(--color-palette-ruby), -1px 0 var(--color-palette-electric-green);
--glitch-fg-step: var(--color-text-inverse);
--glitch-bg-step: var(--color-surface-inverse);
/* Pixel Shift Variables */
--pixel-bg: var(--color-surface-inverse);
--pixel-fg: var(--color-text-inverse);
--pixel-duration: 0.5s;
--pixel-timing: steps(2, start) forwards;
--pixel-line-height: 0.5em;
--pixel-text-shadow: 2px 0 var(--color-primary), -1px 0 var(--color-secondary);
--pixel-line-color-step: var(--color-primary);
--pixel-line-color-end: var(--color-text-inverse);
/* Redacted Variables */
--redacted-bg: var(--color-text-primary);
--redacted-duration: 0.4s;
--redacted-timing: steps(3, end);
--redacted-shadow: 0 0 8px alpharize(var(--color-palette-woodsmoke), 0.5);
/* X-Ray Variables */
--xray-duration: 0.2s;
--xray-timing: steps(3, end);
--xray-bg: var(--color-palette-ice-blue);
--xray-fg: var(--color-text-inverse);
--xray-weight: 900;
--xray-glow: var(--color-surface-inverse);
--xray-invert: 1;
--xray-contrast: 300%;
--xray-brightness: 150%;
--xray-saturate: 0;
--xray-border: var(--color-surface-inverse);
--xray-outer-glow: alpharize(var(--color-palette-ice-blue), 0.5);
/* === KEYFRAME NAME VARIABLES === */
--kf-overexposure: overexposure;
--kf-color-bleed: color-bleed;
--kf-film-burn: film-burn;
--kf-malfunction: malfunction;
--kf-toner-fade: toner-fade;
--kf-digital-corrupt: digital-corrupt;
--kf-stark-flash: stark-flash;
--kf-bd-overexposure: bd-overexposure;
--kf-bd-color-bleed: bd-color-bleed;
--kf-bd-film-burn: bd-film-burn;
--kf-bd-malfunction: bd-malfunction;
--kf-bd-toner-fade: bd-toner-fade;
--kf-bd-digital-corrupt: bd-digital-corrupt;
--kf-bd-stark-flash: bd-stark-flash;
--kf-strike-slam: strike-slam;
--kf-text-glitch: text-glitch;
--kf-char-scramble: char-scramble;
--kf-glitch-line: glitch-line;
--kf-text-entry-glitch: text-entry-glitch;
}
/* === IMAGE KEYFRAMES === */
@keyframes overexposure {
0% { filter: grayscale(var(--base-grayscale)) contrast(var(--base-contrast)) brightness(var(--base-brightness)); }
50% { filter: grayscale(var(--base-grayscale)) contrast(100%) brightness(350%); }
100% { filter: grayscale(var(--base-grayscale)) contrast(200%) brightness(180%); }
}
@keyframes color-bleed {
0% { filter: grayscale(var(--base-grayscale)) contrast(var(--base-contrast)) brightness(var(--base-brightness)); }
16% { filter: grayscale(0.7) contrast(200%) brightness(180%) saturate(300); }
33% { filter: grayscale(0.4) contrast(300%) brightness(150%) saturate(500) hue-rotate(15deg); }
50% { filter: grayscale(0.8) contrast(250%) brightness(200%) saturate(400) hue-rotate(-10deg); }
66% { filter: grayscale(0.3) contrast(400%) brightness(160%) saturate(600) hue-rotate(25deg); }
83% { filter: grayscale(0.6) contrast(300%) brightness(180%) saturate(300) hue-rotate(-5deg); }
100% { filter: grayscale(0.5) contrast(250%) brightness(170%) saturate(400); }
}
@keyframes film-burn {
0% { filter: grayscale(var(--base-grayscale)) contrast(var(--base-contrast)) brightness(var(--base-brightness)); }
25% { filter: invert(1) contrast(200%) brightness(150%); }
50% { filter: grayscale(var(--base-grayscale)) contrast(300%) brightness(80%); }
75% { filter: grayscale(var(--base-grayscale)) contrast(100%) brightness(250%); }
100% { filter: grayscale(var(--base-grayscale)) contrast(200%) brightness(160%); }
}
@keyframes malfunction {
0% {
transform: scaleX(1);
filter: grayscale(var(--base-grayscale)) contrast(var(--base-contrast)) brightness(var(--base-brightness));
}
16% {
transform: scaleX(0.95) translateX(2px);
filter: grayscale(var(--base-grayscale)) contrast(200%) brightness(200%);
}
33% {
transform: scaleX(1.05) translateX(-2px);
filter: grayscale(var(--base-grayscale)) contrast(300%) brightness(80%);
}
50% {
transform: scaleX(0.98) translateX(1px);
filter: grayscale(var(--base-grayscale)) contrast(100%) brightness(250%);
}
66% {
transform: scaleX(1.02) translateX(-1px);
filter: grayscale(var(--base-grayscale)) contrast(250%) brightness(100%);
}
100% {
transform: scaleX(1) translateX(0);
filter: grayscale(var(--base-grayscale)) contrast(180%) brightness(140%);
}
}
@keyframes toner-fade {
0% { filter: grayscale(var(--base-grayscale)) contrast(var(--base-contrast)) brightness(var(--base-brightness)); }
20% { filter: grayscale(var(--base-grayscale)) contrast(80%) brightness(180%); }
40% { filter: grayscale(var(--base-grayscale)) contrast(50%) brightness(220%); }
60% { filter: grayscale(var(--base-grayscale)) contrast(100%) brightness(160%); }
80% { filter: grayscale(var(--base-grayscale)) contrast(120%) brightness(140%); }
100% { filter: grayscale(var(--base-grayscale)) contrast(200%) brightness(130%); }
}
@keyframes digital-corrupt {
0% { filter: grayscale(var(--base-grayscale)) contrast(var(--base-contrast)) brightness(var(--base-brightness)); }
12.5% { filter: grayscale(var(--base-grayscale)) contrast(300%) brightness(50%) blur(1px); }
25% { filter: grayscale(var(--base-grayscale)) contrast(80%) brightness(300%) saturate(2); }
37.5% { filter: grayscale(var(--base-grayscale)) contrast(400%) brightness(80%) hue-rotate(180deg); }
50% { filter: grayscale(var(--base-grayscale)) contrast(100%) brightness(400%) invert(0.3); }
62.5% { filter: grayscale(var(--base-grayscale)) contrast(500%) brightness(60%); }
75% { filter: grayscale(var(--base-grayscale)) contrast(200%) brightness(200%) blur(0.5px); }
87.5% { filter: grayscale(var(--base-grayscale)) contrast(180%) brightness(150%); }
100% { filter: grayscale(var(--base-grayscale)) contrast(200%) brightness(140%); }
}
@keyframes stark-flash {
0% { filter: grayscale(var(--base-grayscale)) contrast(var(--base-contrast)) brightness(var(--base-brightness)); }
30% { filter: grayscale(var(--base-grayscale)) contrast(800%) brightness(800%) invert(1); }
70% { filter: grayscale(var(--base-grayscale)) contrast(600%) brightness(600%); }
100% { filter: grayscale(var(--base-grayscale)) contrast(300%) brightness(180%); }
}
/* === TEXT KEYFRAMES === */
@keyframes strike-slam {
0% {
left: 0;
width: 0%;
}
100% {
left: -0.125em;
width: calc(100% + 0.25em);
}
}
@keyframes text-glitch {
0% {
transform: translateX(0);
color: var(--color-palette-light-silver);
}
50% {
transform: translateX(-2px);
color: var(--pixel-fg);
text-shadow: var(--pixel-text-shadow);
}
100% {
transform: translateX(0);
color: var(--pixel-fg);
}
}
@keyframes char-scramble {
0% {
transform: translateX(0);
text-shadow: none;
filter: none;
}
12.5% {
font-family: monospace;
text-shadow: var(--glitch-text-shadow-1);
}
25% {
transform: translateX(2px);
filter: contrast(200%) brightness(150%);
}
37.5% {
transform: translateX(-1px) scaleY(1.1);
letter-spacing: 0.2em;
}
50% {
transform: translateX(1px) scaleX(0.9);
color: var(--glitch-fg-step);
background: var(--glitch-bg-step);
}
62.5% {
transform: translateX(-2px);
filter: invert(1) contrast(300%);
}
75% {
transform: translateX(1px);
text-shadow: var(--glitch-text-shadow-2);
}
87.5% {
letter-spacing: 0.1em;
filter: contrast(150%) brightness(120%);
}
100% {
transform: translateX(0);
color: var(--color-text-primary);
text-shadow: none;
filter: none;
}
}
@keyframes glitch-line {
0% {
transform: translateX(0) scaleX(1);
opacity: 0;
}
50% {
transform: translateX(3px) scaleX(0.7);
opacity: 1;
background: var(--pixel-line-color-step);
}
100% {
transform: translateX(0) scaleX(1);
opacity: 1;
background: var(--pixel-line-color-end);
}
}
}
@keyframes text-entry-glitch {
0% {
transform: translateX(-10px) scale(0.8);
color: transparent;
opacity: 0;
filter: blur(2px);
}
25% {
transform: translateX(3px) scale(1.05);
color: var(--color-palette-light-silver);
text-shadow: 2px 0 var(--color-primary), -1px 0 var(--color-secondary);
opacity: 0.7;
filter: blur(1px);
}
50% {
transform: translateX(-2px) scale(0.95);
color: var(--pixel-fg);
text-shadow: var(--pixel-text-shadow);
opacity: 0.9;
filter: blur(0.5px);
}
75% {
transform: translateX(1px) scale(1.02);
color: var(--color-text-inverse);
text-shadow: 1px 0 var(--color-primary);
opacity: 1;
filter: none;
}
100% {
transform: translateX(0) scale(1);
color: var(--pixel-line-color-end);
text-shadow: none;
opacity: 1;
filter: none;
}
}

View File

@@ -0,0 +1,16 @@
@layer base {
html {
font-size: var(--font-size-base);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
font-family: var(--font-geist-sans);
font-weight: var(--typo-weight-normal);
color: var(--color-text-primary);
background-color: var(--color-surface-base);
}
}

View File

@@ -0,0 +1,155 @@
@layer tokens {
:root {
/* === Default Palette === */
/* == Blacks, Grays & Off-Whites == */
--color-palette-woodsmoke: oklch(15.5% 0.009 274.276deg); /* Woodsmoke: #0B0C10 */
--color-palette-black-ink: oklch(21.9% 0.006 285.911deg); /* Shark: #1A1A1D */
--color-palette-charcoal: oklch(26.6% 0.008 240.166deg); /* Shark2: #222629 */
--color-palette-charcoal-gray: oklch(33.7% 0.026 266.801deg); /* Bright Gray: #313745 */
--color-palette-slate-gray: oklch(33.3% 0 89.876deg); /* Mineshaft: #363636 */
--color-palette-gunmetal: oklch(41.1% 0.008 248.035deg); /* Abbey2: #474B4F */
--color-palette-carbon: oklch(39.8% 0 89.876deg); /* Tundora: #474747 */
--color-palette-steel-gray: oklch(42.5% 0.003 286.26deg); /* Abbey: #4e4e50 */
--color-palette-dusty-black: oklch(43.7% 0.013 17.672deg); /* DonJuan: #594F4F */
--color-palette-stone: oklch(64.3% 0.005 91.471deg); /* Natural Gray: #8E8D8A */
--color-palette-cloud-gray: oklch(53.6% 0.005 236.565deg); /* Nevada: #6B6E70 */
--color-palette-silver: oklch(72.9% 0.001 17.185deg); /* Silver Chalice: #A8A7A7 */
--color-palette-light-silver: oklch(82.6% 0.002 247.844deg); /* Silversand: #C5C6C7 */
--color-palette-pale-gray: oklch(91.3% 0.004 91.449deg); /* Westar: #E3E2DF */
--color-palette-pale-stone: oklch(89.7% 0.004 106.481deg); /* Quillgray: #DDDDDA */
--color-palette-very-pale-gray: oklch(94.3% 0 89.876deg); /* Gallery: #ECECEC */
--color-palette-off-white: oklch(98.1% 0.003 247.858deg); /* Catskill White: #F7F9fB */
--color-palette-cat-squeeze: oklch(98.3% 0.004 236.496deg); /* Cat Squeeze: #F7FAFC */
/* == Reds == */
--color-palette-oxblood: oklch(30.5% 0.122 12.109deg); /* Bordeaux: #5D001E */
--color-palette-deep-maroon: oklch(37.6% 0.109 11.682deg); /* Crown of Thorns: #6F2232 */
--color-palette-crimson: oklch(43.2% 0.169 7.14deg); /* Monarch: #950740 */
--color-palette-cherry-red: oklch(45.4% 0.168 1.454deg); /* Disco: #9A1750 */
--color-palette-ruby: oklch(52.1% 0.206 15.782deg); /* Shiraz: #C3073F */
--color-palette-red-clay: oklch(65.1% 0.178 27.507deg); /* Burnt Sienna: #E85A4F */
--color-palette-lava: oklch(63.6% 0.193 17.075deg); /* Mandy: #E84A5F */
--color-palette-vivid-scarlet: oklch(66.6% 0.221 15.669deg); /* Radical Red: #FE4365 */
/* == Pinks & Magentas == */
--color-palette-heliotrope: oklch(68.3% 0.217 353.666deg); /* Heliotrope: #F74FA3 */
--color-palette-hot-pink: oklch(65.4% 0.2 6.69deg); /* French Rose: #EE4C7C */
--color-palette-cerise: oklch(60.7% 0.23 18.554deg); /* Amaranth: #EC2049 */
--color-palette-fuchsia: oklch(49.6% 0.181 351.176deg); /* Hibiscus: #A7226E */
--color-palette-dusty-rose: oklch(63.2% 0.11 2.384deg); /* Turkish Rose: #C06C84 */
--color-palette-berry: oklch(60.8% 0.159 2.621deg); /* Mulberry: #CC527A */
--color-palette-petal-pink: oklch(80.5% 0.063 1.992deg); /* Rose Fog: #E3AFBC */
--color-palette-coral-pink: oklch(71.2% 0.162 15.607deg); /* Froly: #F67280 */
--color-palette-sweet-pink: oklch(79.2% 0.114 21.911deg); /* Sweet Pink: #FC9D9A */
/* == Oranges & Browns == */
--color-palette-persimmon: oklch(68.6% 0.179 40.01deg); /* Flamingo: #F26B38 */
--color-palette-terracotta: oklch(71.3% 0.131 27.646deg); /* Apricot: #E98074 */
--color-palette-tan: oklch(82.7% 0.047 76.752deg); /* Akaroa: #D8C3A5 */
--color-palette-peach: oklch(88.5% 0.072 57.746deg); /* Flesh: #FECEAB */
--color-palette-pastel-orange: oklch(82.1% 0.092 42.408deg); /* Rosebud: #F8B195 */
--color-palette-light-apricot: oklch(87.8% 0.066 57.778deg); /* Vivid Tangerine: #F9CDAD */
--color-palette-bone-white: oklch(92.7% 0.015 94.206deg); /* Satin Linen: #EAE7DC */
/* == Yellows == */
--color-palette-ripe-lemon: oklch(83.9% 0.167 91.469deg); /* Ripe Lemon: #F2C51D */
--color-palette-bright-canary: oklch(89% 0.157 97.726deg); /* Energy Yellow: #F7DB4F */
--color-palette-pale-lemon: oklch(95.6% 0.104 121.573deg); /* Mimosa: #E5FCAD */
/* == Greens == */
--color-palette-forest-green: oklch(58.1% 0.127 130.001deg); /* Crete: #61892F */
--color-palette-lime-green: oklch(74.6% 0.18 129.939deg); /* Atlantis: #86C232 */
--color-palette-electric-green: oklch(87.7% 0.227 137.099deg); /* Screaming Green: #87f74f */
--color-palette-sage: oklch(75.1% 0.056 144.175deg); /* Norway: #87f74f */
--color-palette-mint-green: oklch(84.8% 0.098 151.333deg); /* Chinook: #9de0ad */
--color-palette-olive-drab: oklch(82.5% 0.042 107.285deg); /* Olive Drap: #C8C8A9 */
--color-palette-seafoam: oklch(71.6% 0.056 165.214deg); /* Acapulco: #83AF9B */
/* == Blues & Teals == */
--color-palette-dark-navy: oklch(27.3% 0.024 253.693deg); /* Ebony Clay: #1F2833 */
--color-palette-deep-teal: oklch(32.4% 0.018 225.132deg); /* Outer Space: #2A363B */
--color-palette-royal-blue: oklch(46.1% 0.07 245.64deg); /* Ming: #355C7D */
--color-palette-sky-blue: oklch(76.3% 0.129 233.891deg); /* Picton Blue: #4FBFF7 */
--color-palette-slate-blue: oklch(55.1% 0.043 210.602deg); /* Cutty Sark: #547980 */
--color-palette-turquoise: oklch(61.5% 0.091 198.865deg); /* Lochinvar: #2F9599 */
--color-palette-aqua: oklch(68.6% 0.095 190.758deg); /* Keppel: #45ADA8 */
--color-palette-electric-blue: oklch(90.8% 0.128 188.419deg); /* Aquamarine: #66FCF1 */
--color-palette-powder-blue: oklch(88.2% 0.062 187.276deg); /* Powder Blue: #a9e6df */
--color-palette-ice-blue: oklch(99.9% 0.001 197.139deg); /* Twilight Blue: #feffff */
/* === Semantic Colors === */
/* == Primary Colors == */
--color-primary: var(--color-palette-lava);
--color-primary-surface: oklch(from var(--color-primary) calc(l + 0.1) c h);
--color-primary-emphasis: oklch(from var(--color-primary) calc(l - 0.15) c h);
/* == Secondary Colors == */
--color-secondary: var(--color-palette-slate-blue);
--color-secondary-surface: oklch(from var(--color-secondary) calc(l + 0.1) c h);
--color-secondary-emphasis: oklch(from var(--color-secondary) calc(l - 0.15) c h);
/* == Tertiary Colors == */
--color-tertiary: var(--color-palette-bright-canary);
--color-tertiary-surface: oklch(from var(--color-tertiary) calc(l + 0.1) c h);
--color-tertiary-emphasis: oklch(from var(--color-tertiary) calc(l - 0.15) c h);
/* == Text Base Colors == */
--color-text-primary: var(--color-palette-black-ink); /* Main Body Texts, headlines */
--color-text-secondary: var(--color-palette-charcoal); /* Subheading, Secondary Info */
--color-text-tertiary: var(--color-palette-charcoal-gray); /* Captions, Meta Text */
--color-text-quarternary: var(--color-palette-carbon); /* Placeholder Text */
--color-text-inverse: var(--color-palette-ice-blue); /* Text on dark backgrounds */
--color-text-disabled: var(--color-palette-cloud-gray); /* Disabled form labels, inactive text */
/* == Surface Base Colors == */
--color-surface-base: var(--color-palette-ice-blue); /* Main page background */
--color-surface-elevated-1: var(--color-palette-off-white); /* Cards, Panels */
--color-surface-elevated-2: var(--color-palette-very-pale-gray); /* Modals, Dropdowns */
--color-surface-elevated-3: var(--color-palette-pale-gray); /* Tooltips, popovers */
--color-surface-elevated-4: var(--color-palette-light-silver); /* Highest Elevation */
--color-surface-inverse: var(--color-palette-black-ink); /* Darkest Surface for Contrast */
/* == Border Base Colors == */
--color-border-subtle: var(--color-palette-silver); /* Subtle Dividers, Card Borders */
--color-border-normal: var(--color-palette-stone); /* Standard Borders, form fields */
--color-border-strong: var(--color-palette-charcoal-gray); /* Emphasized Borders */
/* == State Colors == */
--color-state-error: var(--color-palette-cerise); /* Error Text, Container, icons */
--color-state-warning: var(--color-palette-persimmon); /* Warning Text, Container, Icons */
--color-state-success: var(--color-palette-lime-green); /* Success Text, Container, Icons */
--color-state-info: var(--color-palette-royal-blue); /* Info Text, Container, Icons */
/* == Link Colors == */
--color-text-link: var(--color-text-tertiary);
--color-text-link-hover: var(--color-secondary);
--color-text-link-visited: var(--color-palette-fuchsia);
/* == Focus States == */
--color-focus-ring: var(--color-primary);
--color-focus-ring-offset: var(--color-primary);
--color-focus-indicator: var(--color-primary-emphasis)
/* == Overlays == */;
--color-utility-overlay-light: oklch(15.5% 0.009 274.276deg / 10%); /* Light overlays */
--color-utility-overlay-medium: oklch(15.5% 0.009 274.276deg / 30%); /* Medium overlays */
--color-utility-overlay-heavy: oklch(15.5% 0.009 274.276deg / 60%); /* Heavy overlays, modal backdrops */
--color-surface-overlay: var(--color-utility-overlay-medium); /* Modal overlays, backdrop */
--color-surface-backdrop: var(--color-utility-overlay-heavy); /* Full screen overlays */
/* == Dividers == */
--color-utility-divider: var(--color-border-subtle); /* Section dividers, HR elements */
--color-utility-divider-strong: var(--color-border-normal); /* Emphasized dividers */
/* == Shadows == */
--color-utility-shadow-light: oklch(15.5% 0.009 274.276deg / 10%); /* Drop shadows */
--color-utility-shadow-medium: oklch(15.5% 0.009 274.276deg / 20%); /* Drop shadows */
--color-utility-shadow-strong: oklch(15.5% 0.009 274.276deg / 25%); /* Strong shadows */
/* == Highlights == */
--color-utility-highlight: var(--color-tertiary-surface); /* Text highlighting, search results */
--color-utility-highlight-strong: var(--color-tertiary); /* Strong highlighting */
}
}

View File

@@ -0,0 +1,555 @@
@layer content {
.content {
& h1 {
margin-block: var(--el-h1-vspace-top) var(--el-h1-vspace-bottom);
padding-bottom: var(--spacing-snug);
border-bottom: var(--size-4) solid var(--el-h1-color);
font-family: var(--el-h1-font-family), serif;
font-size: var(--el-h1-font-size);
font-weight: var(--el-h1-font-weight);
line-height: var(--el-h1-line-height);
color: var(--el-h1-color);
text-transform: var(--el-h1-text-transform);
letter-spacing: var(--el-h1-letter-spacing);
& + p,
& + ul,
& + ol,
& + blockquote {
margin-block:
calc(1em * var(--typo-leading-normal) * var(--vspace-tight))
calc(1em * var(--typo-leading-normal) * var(--vspace-snug));
}
& + h2 {
margin-block:
calc(1em * var(--el-h1-line-height) * var(--vspace-snug))
calc(1em * var(--el-h1-line-height) * var(--vspace-normal));
}
}
& h2 {
margin-block: var(--el-h2-vspace-top) var(--el-h2-vspace-bottom);
padding-left: var(--spacing-snug);
border-left: var(--size-4) solid var(--el-h2-color);
font-family: var(--el-h2-font-family), serif;
font-size: var(--el-h2-font-size);
font-weight: var(--el-h2-font-weight);
line-height: var(--el-h2-line-height);
color: var(--el-h2-color);
text-transform: var(--el-h2-text-transform);
letter-spacing: var(--el-h2-letter-spacing);
& + p,
& + ul,
& + ol,
& + blockquote {
margin-block:
calc(1em * var(--typo-leading-normal) * var(--vspace-tight))
calc(1em * var(--typo-leading-normal) * var(--vspace-snug));
}
& + h3 {
margin-block:
calc(1em * var(--el-h1-line-height) * var(--vspace-compressed))
calc(1em * var(--el-h1-line-height) * var(--vspace-snug));
}
}
& h3 {
margin-block: var(--el-h3-vspace-top) var(--el-h3-vspace-bottom);
padding: var(--spacing-tight) var(--spacing-snug);
font-family: var(--el-h3-font-family), serif;
font-size: var(--el-h3-font-size);
font-weight: var(--el-h3-font-weight);
line-height: var(--el-h3-line-height);
color: var(--color-surface-base);
text-transform: var(--el-h3-text-transform);
letter-spacing: var(--el-h3-letter-spacing);
background: var(--el-h3-color);
}
& h4 {
margin-block: var(--el-h4-vspace-top) var(--el-h4-vspace-bottom);
padding: var(--spacing-tight) var(--spacing-snug);
border-top: var(--size-3 ) solid var(--el-h4-color);
border-bottom: var(--size-3 ) solid var(--el-h4-color);
font-family: var(--el-h4-font-family), serif;
font-size: var(--el-h4-font-size);
font-weight: var(--el-h4-font-weight);
line-height: var(--el-h4-line-height);
text-transform: var(--el-h4-text-transform);
letter-spacing: var(--el-h4-letter-spacing);
}
& h5 {
margin-block: var(--el-h5-vspace-top) var(--el-h5-vspace-bottom);
padding: var(--spacing-tight) var(--spacing-snug);
font-family: var(--el-h5-font-family), serif;
font-size: var(--el-h5-font-size);
font-weight: var(--el-h5-font-weight);
line-height: var(--el-h5-line-height);
color: var(--el-h5-color);
text-transform: var(--el-h5-text-transform);
letter-spacing: var(--el-h5-letter-spacing);
&::before,
&::after {
content: "";
padding-right: var(--spacing-tight);
line-height: 1;
}
&::before {
content: "❭";
}
&::after {
content: "";
}
}
& h6 {
margin-block: var(--el-h6-vspace-top) var(--el-h6-vspace-bottom);
font-family: var(--el-h6-font-family), serif;
font-size: var(--el-h6-font-size);
font-weight: var(--el-h6-font-weight);
line-height: var(--el-h6-line-height);
color: var(--el-h6-color);
text-transform: var(--el-h6-text-transform);
letter-spacing: var(--el-h6-letter-spacing);
}
& h3,
& h4,
& h5,
& h6 {
& + p,
& + ul,
& + ol,
& + blockquote {
margin-block:
calc(1em * var(--typo-leading-normal) * var(--vspace-compressed))
calc(1em * var(--typo-leading-normal) * var(--vspace-snug));
}
}
& p {
margin-block: var(--el-p-vspace-top) var(--el-p-vspace-bottom);
font-family: var(--el-p-font-family), sans-serif;
font-size: var(--el-p-font-size);
font-weight: var(--el-p-font-weight);
line-height: var(--el-p-line-height);
color: var(--el-p-color);
text-align: var(--el-p-text-align);
}
& blockquote {
margin-block: var(--el-p-vspace-top) var(--el-p-vspace-bottom);
padding: var(--spacing-snug) 0 var(--spacing-snug) var(--spacing-comfortable);
border-left: var(--size-4) solid var(--color-text-tertiary);
font-family: var(--el-blockquote-font-family), serif;
font-size: var(--el-blockquote-font-size);
font-weight: var(--el-blockquote-font-weight);
font-style: var(--el-blockquote-font-style);
line-height: var(--el-blockquote-line-height);
color: var(--el-blockquote-color);
}
& pre {
margin-block: var(--el-pre-vspace-top) var(--el-pre-vspace-bottom);
padding: var(--spacing-comfortable);
font-family: var(--el-pre-font-family), monospace;
font-size: var(--el-pre-font-size);
line-height: var(--el-pre-line-height);
color: var(--el-pre-color);
background: var(--el-pre-background);
}
& ul,
& ol {
margin-block: var(--el-list-vspace-top) var(--el-list-vspace-bottom);
font-size: var(--el-list-font-size);
line-height: var(--el-list-line-height);
color: var(--el-list-color);
& ul,
& ol {
margin-block: var(--el-list-nested-vspace-top) var(--el-list-nested-vspace-bottom);
}
& li {
margin-block: var(--el-li-vspace-top) var(--el-li-vspace-bottom);
list-style-position: outside;
& li {
margin-block: var(--el-li-nested-vspace-top) var(--el-li-nested-vspace-bottom);
}
}
}
& ul {
padding-left: var(--el-ul-indent-l1);
list-style: none;
& li {
padding-left: var(--el-ul-item-padding);
&::marker {
content: var(--el-ul-symbol-l1);
color: var(--el-ul-symbol-l1-color);
}
}
& ul,
& ol {
padding-left: var(--el-ul-indent-l2);
& li::marker {
content: var(--el-ul-symbol-l2);
color: var(--el-ul-symbol-l2-color);
}
& ul,
& ol {
padding-left: var(--el-ul-indent-l3);
& li::marker {
content: var(--el-ul-symbol-l3);
color: var(--el-ul-symbol-l3-color);
}
& ul,
& ol {
padding-left: var(--el-ul-indent-l4);
& li::marker {
content: var(--el-ul-symbol-l4);
color: var(--el-ul-symbol-l4-color);
}
}
}
}
}
ol {
counter-reset: ol-l1;
contain: style;
padding-left: var(--el-ol-indent-l1);
list-style: none;
& > li {
counter-increment: ol-l1;
margin-left: var(--el-ol-item-indent-l1);
padding-left: var(--el-ol-item-padding);
&::marker {
content: var(--el-ol-prefix-l1) counter(ol-l1, var(--el-ol-style-l1)) var(--el-ol-suffix-l1);
color: var(--el-ol-marker-color-l1);
}
& > ol {
counter-reset: ol-l2;
padding-left: var(--el-ol-indent-l2);
& > li {
counter-increment: ol-l2;
margin-left: var(--el-ol-item-indent-l2);
&::marker {
content: var(--el-ol-prefix-l2) counter(ol-l2, var(--el-ol-style-l2)) var(--el-ol-suffix-l2);
color: var(--el-ol-marker-color-l2);
}
& > ol {
counter-reset: ol-l3;
margin-left: var(--el-ol-item-indent-l3);
padding-left: var(--el-ol-indent-l3);
& > li {
counter-increment: ol-l3;
&::marker {
content: var(--el-ol-prefix-l3) counter(ol-l3, var(--el-ol-style-l3)) var(--el-ol-suffix-l3);
color: var(--el-ol-marker-color-l3);
}
& > ol {
counter-reset: ol-l4;
margin-left: var(--el-ol-item-indent-l4);
padding-left: var(--el-ol-indent-l4);
& > li {
counter-increment: ol-l4;
&::marker {
content: var(--el-ol-prefix-l4) counter(ol-l4, var(--el-ol-style-l4)) var(--el-ol-suffix-l4);
color: var(--el-ol-marker-color-l4);
}
}
}
& > ul {
padding-left: var(--el-ol-indent-l4);
}
}
}
& > ul {
padding-left: var(--el-ol-indent-l3);
}
}
}
& > ul {
padding-left: var(--el-ol-indent-l2);
}
}
}
& dl {
margin-block: var(--el-dl-vspace-top) var(--el-dl-vspace-bottom);
font-size: var(--el-dl-font-size);
line-height: var(--el-dl-line-height);
}
& dt {
margin-block: var(--el-dt-vspace-top) var(--el-dt-vspace-bottom);
padding: var(--el-dt-padding);
font-family: var(--el-dt-font-family), serif;
font-size: var(--el-dt-font-size);
font-weight: var(--el-dt-font-weight);
line-height: var(--el-dt-line-height);
color: var(--el-dt-color);
text-transform: var(--el-dt-text-transform);
letter-spacing: var(--el-dt-letter-spacing);
background: var(--el-dt-background);
}
& dd {
margin-block: var(--el-dd-vspace-top) var(--el-dd-vspace-bottom);
padding: var(--el-dd-indent);
font-family: var(--el-dd-font-family), sans-serif;
font-size: var(--el-dd-font-size);
line-height: var(--el-dd-line-height);
color: var(--el-dd-color);
}
& table {
border-collapse: collapse;
width: 100%;
margin-block: var(--el-table-vspace-top) var(--el-table-vspace-bottom);
border: var(--el-table-border);
font-size: var(--el-table-font-size);
line-height: var(--el-table-line-height);
& thead th,
& th {
padding: var(--el-th-padding);
font-family: var(--el-th-font-family), serif;
font-size: var(--el-th-font-size);
font-weight: var(--el-th-font-weight);
line-height: var(--el-th-line-height);
color: var(--el-th-color);
text-transform: var(--el-th-text-transform);
background: var(--el-th-background);
}
& tbody td,
& td {
padding: var(--el-td-padding);
border: var(--el-td-border);
font-family: var(--el-td-font-family), monospace;
font-size: var(--el-td-font-size);
line-height: var(--el-td-line-height);
color: var(--el-td-color);
text-align: center;
}
}
& hr{
position: relative;
overflow: visible;
height: var(--hr-height);
margin-block: var(--hr-margin);
border: none;
background: var(--hr-color);
&::after {
content: var(--hr-symbol-content);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: var(--hr-symbol-space);
font-size: var(--hr-symbol-size);
line-height: var(--hr-symbol-line-height);
color: var(--hr-symbol-color);
background: var(--hr-symbol-background);
}
}
& em,
& i {
padding: 0.1em 0.2em;
font-style: normal;
color: var(--color-text-inverse);
background: var(--color-surface-inverse);
}
& strong,
& b {
font-weight: var(--typo-weight-black);
letter-spacing: var(--typo-spacing-relaxed);
}
a {
@mixin anim-txt-pixelshift 0.6s steps(15, end), var(--color-primary);
color: var(--color-text-tertiary);
transition: color 0.2s ease-in-out;
&:hover {
cursor: pointer;
color: var(--color-primary);
}
&:visited,
&:active {
color: var(--color-primary-emphasis);
}
}
& code {
padding: 0.1em 0.3em;
font-family: var(--font-mono), monospace;
font-size: var(--typo-size-sm);
color: var(--color-text-inverse);
background: var(--color-surface-inverse);
}
& kbd {
padding: 0.1em 0.3em;
border: 1px solid var(--color-text-primary);
border-radius: 2px;
font-family: var(--font-mono), monospace;
font-size: var(--typo-size-xs);
color: var(--color-text-inverse);
text-transform: uppercase;
background: var(--color-surface-inverse);
}
& samp {
padding: 0.1em 0.3em;
border-left: var(--size-1) solid var(--color-text-tertiary);
font-family: var(--font-mono), monospace;
font-size: var(--typo-size-sm);
color: var(--color-text-primary);
background: var(--color-surface-elevated-2);
}
& var {
font-family: var(--font-mono), monospace;
font-weight: var(--typo-weight-semibold);
font-style: normal;
color: var(--color-text-secondary);
}
& small {
font-size: var(--typo-size-xs);
color: var(--color-text-tertiary);
}
& sub,
& sup {
font-size: var(--typo-size-2xs);
font-weight: var(--typo-weight-semibold);
color: var(--color-text-secondary);
}
& del,
& s {
color: var(--color-text-disabled);
text-decoration: line-through;
text-decoration-thickness: var(--size-1);
}
& ins {
font-weight: var(--typo-weight-semibold);
color: var(--color-text-primary);
text-decoration: underline;
text-decoration-color: var(--color-primary);
text-decoration-thickness: var(--size-1);
background: transparent;
}
& abbr {
cursor: help;
text-decoration: underline dotted;
text-underline-offset: var(--size-1);
}
& dfn {
font-weight: var(--typo-weight-bold);
font-style: normal;
color: var(--color-text-primary);
}
& cite {
font-weight: var(--typo-weight-semibold);
font-style: normal;
color: var(--color-text-secondary);
}
& q {
font-style: normal;
&::before {
content: "»";
}
&::after {
content: "«";
}
}
& time {
font-family: var(--font-mono), monospace;
font-size: var(--typo-size-sm);
color: var(--color-text-secondary);
}
}
}

View File

@@ -0,0 +1,7 @@
@layer tokens {
@custom-media --bp-mobile (width < 48rem);
@custom-media --bp-tablet (width >= 48rem) and (width < 80rem);
@custom-media --bp-tablet-up (width >= 48rem);
@custom-media --bp-tablet-down (width < 80rem);
@custom-media --bp-desktop (width >= 80rem);
}

View File

@@ -0,0 +1,95 @@
@layer tokens {
:root {
/* === DIMENSIONS === */
/* == Base Size Units == */
--size-0: 0;
--size-px: 1px;
--size-05: 0.125rem;
--size-1: 0.25rem;
--size-2: 0.5rem;
--size-3: 0.75rem;
--size-4: 1rem;
--size-5: 1.25rem;
--size-6: 1.5rem;
--size-8: 2rem;
--size-10: 2.5rem;
--size-12: 3rem;
--size-16: 4rem;
--size-20: 5rem;
--size-24: 6rem;
--size-32: 8rem;
--size-40: 10rem;
--size-48: 12rem;
--size-64: 16rem;
--size-80: 20rem;
--size-96: 24rem;
--size-128: 32rem;
--size-160: 40rem;
--size-192: 48rem;
--size-256: 64rem;
--size-320: 80rem;
--size-384: 96rem;
--size-360: 90rem;
--size-400: 100rem;
--size-480: 120rem;
/* == Flexible Dimensions == */
--dim-full: 100%;
--dim-1-2: 50%;
--dim-1-3: 33.3333%;
--dim-2-3: 66.6667%;
--dim-1-4: 25%;
--dim-2-4: var(--dim-1-2);
--dim-3-4: 75%;
--dim-1-5: 20%;
--dim-2-5: 40%;
--dim-3-5: 60%;
--dim-4-5: 80%;
--dim-1-6: 16.6667%;
--dim-2-6: var(--dim-1-3);
--dim-3-6: var(--dim-1-2);
--dim-4-6: var(--dim-2-3);
--dim-5-6: 83.3333%;
--dim-1-8: 12.5%;
--dim-2-8: var(--dim-1-4);
--dim-3-8: 37.5%;
--dim-4-8: var(--dim-1-2);
--dim-5-8: 62.5%;
--dim-6-8: var(--dim-3-4);
--dim-7-8: 87.5%;
--dim-1-10: 10%;
--dim-2-10: var(--dim-1-5);
--dim-3-10: 30%;
--dim-4-10: var(--dim-2-5);
--dim-5-10: var(--dim-1-2);
--dim-6-10: var(--dim-3-5);
--dim-7-10: 70%;
--dim-8-10: var(--dim-4-5);
--dim-9-10: 90%;
--dim-1-12: 8.3333%;
--dim-2-12: var(--dim-1-6);
--dim-3-12: var(--dim-1-4);
--dim-4-12: var(--dim-1-3);
--dim-5-12: 41.6667%;
--dim-6-12: var(--dim-1-2);
--dim-7-12: 58.3333%;
--dim-8-12: var(--dim-2-3);
--dim-9-12: var(--dim-3-4);
--dim-10-12: 83.3333%;
--dim-11-12: 91.6667%;
/* == Semantic Spacing == */;
--spacing-none: var(--size-0);
--spacing-hairline: var(--size-px);
--spacing-tight: var(--size-1);
--spacing-snug: var(--size-2);
--spacing-cozy: var(--size-4);
--spacing-comfortable: var(--size-6);
--spacing-relaxed: var(--size-8);
--spacing-spacious: var(--size-12);
--spacing-generous: var(--size-16);
--spacing-luxurious: var(--size-24);
--spacing-expansive: var(--size-32);
}
}

View File

@@ -0,0 +1,266 @@
@layer tokens {
:root {
/* === H1 VARIABLES === */
--el-h1-color: var(--color-text-primary);
--el-h1-font-family: var(--font-display);
--el-h1-font-size: var(--typo-size-7xl);
--el-h1-font-weight: var(--typo-weight-black);
--el-h1-letter-spacing: -0.0137em;
--el-h1-line-height: 1.125;
--el-h1-text-transform: uppercase;
--el-h1-vspace-base: calc(1em * var(--el-h1-line-height));
--el-h1-vspace-top: calc(var(--el-h1-vspace-base) * var(--vspace-spacious));
--el-h1-vspace-bottom: calc(var(--el-h1-vspace-base) * var(--vspace-comfortable));
/* === H2 VARIABLES === */
--el-h2-color: var(--color-text-primary);
--el-h2-font-family: var(--font-header);
--el-h2-font-size: var(--typo-size-5xl);
--el-h2-font-weight: var(--typo-weight-black);
--el-h2-letter-spacing: -0.0096em;;
--el-h2-line-height: 1.1765;
--el-h2-text-transform: uppercase;
--el-h2-vspace-base: calc(1em * var(--el-h2-line-height));
--el-h2-vspace-top: calc(var(--el-h2-vspace-base) * var(--vspace-snug));
--el-h2-vspace-bottom: calc(var(--el-h2-vspace-base) * var(--vspace-compressed));
/* === H3 VARIABLES === */
--el-h3-color: var(--color-text-secondary);
--el-h3-font-family: var(--font-header);
--el-h3-font-size: var(--typo-size-4xl);
--el-h3-font-weight: var(--typo-weight-extrabold);
--el-h3-letter-spacing: -0.004em;
--el-h3-line-height: 1.2;
--el-h3-text-transform: uppercase;
--el-h3-vspace-base: calc(1em * var(--el-h3-line-height));
--el-h3-vspace-top: calc(var(--el-h3-vspace-base) * var(--vspace-cozy));
--el-h3-vspace-bottom: calc(var(--el-h3-vspace-base) * var(--vspace-snug));
/* === H4 VARIABLES === */
--el-h4-color: var(--color-text-secondary);
--el-h4-font-family: var(--font-header);
--el-h4-font-size: var(--typo-size-3xl);
--el-h4-font-weight: var(--typo-weight-extrabold);
--el-h4-letter-spacing: 0.0025em;
--el-h4-line-height: 1.125;
--el-h4-text-transform: uppercase;
--el-h4-vspace-base: calc(1em * var(--el-h4-line-height));
--el-h4-vspace-top: calc(var(--el-h4-vspace-base) * var(--vspace-normal));
--el-h4-vspace-bottom: calc(var(--el-h4-vspace-base) * var(--vspace-tight));
/* === H5 VARIABLES === */
--el-h5-color: var(--color-text-secondary);
--el-h5-font-family: var(--font-header);
--el-h5-font-size: var(--typo-size-2xl);
--el-h5-font-weight: var(--typo-weight-extrabold);
--el-h5-letter-spacing: 0.05em;
--el-h5-line-height: 1.28;
--el-h5-text-transform: uppercase;
--el-h5-vspace-base: calc(1em * var(--el-h5-line-height));
--el-h5-vspace-top: calc(var(--el-h5-vspace-base) * var(--vspace-cozy));
--el-h5-vspace-bottom: calc(var(--el-h5-vspace-base) * var(--vspace-tight));
/* === H6 VARIABLES === */
--el-h6-color: var(--color-text-secondary);
--el-h6-font-family: var(--font-header);
--el-h6-font-size: var(--typo-size-xl);
--el-h6-font-weight: var(--typo-weight-black);
--el-h6-letter-spacing: 0.035em;
--el-h6-line-height: 1.4;
--el-h6-text-transform: uppercase;
--el-h6-vspace-base: calc(1em * var(--el-h6-line-height));
--el-h6-vspace-top: calc(var(--el-h6-vspace-base) * var(--vspace-snug));
--el-h6-vspace-bottom: calc(var(--el-h6-vspace-base) * var(--vspace-compressed));
/* === PARAGRAPH VARIABLES === */
--el-p-color: var(--color-text-primary);
--el-p-font-family: var(--font-body);
--el-p-font-size: var(--typo-size-md);
--el-p-font-weight: var(--typo-weight-regular);
--el-p-line-height: var(--typo-leading-normal);
--el-p-text-align: justify;
--el-p-vspace-base: calc(1em * var(--el-p-line-height));
--el-p-vspace-top: calc(var(--el-p-vspace-base) * var(--vspace-snug));
--el-p-vspace-bottom: calc(var(--el-p-vspace-base) * var(--vspace-snug));
/* === BLOCKQUOTE VARIABLES === */
--el-blockquote-color: var(--color-text-tertiary);
--el-border-color: var(--color-text-tertiary);
--el-blockquote-font-family: var(--font-body);
--el-blockquote-font-size: var(--typo-size-md);
--el-blockquote-font-style: var(--typo-weight-regular);
--el-blockquote-font-weight: var(--typo-weight-medium);
--el-blockquote-line-height: var(--typo-leading-comfortable);
--el-blockquote-vspace-base: calc(1em * var(--el-blockquote-line-height));
--el-blockquote-vspace-top: calc(var(--el-blockquote-vspace-base) * var(--vspace-snug));
--el-blockquote-vspace-bottom: calc(var(--el-blockquote-vspace-base) * var(--vspace-snug));
/* === PRE VARIABLES === */
--el-pre-color: var(--color-text-inverse);
--el-pre-background: var(--color-surface-inverse);
--el-pre-font-family: var(--font-mono);
--el-pre-font-size: var(--typo-size-sm);
--el-pre-line-height: 1.5385;
--el-pre-vspace-base: calc(1em * var(--el-pre-line-height));
--el-pre-vspace-top: calc(var(--el-pre-vspace-base) * var(--vspace-normal));
--el-pre-vspace-bottom: calc(var(--el-pre-vspace-base) * var(--vspace-normal));
/* === CODE VARIABLES === */
--el-code-color: var(--color-text-inverse);
--el-code-background: var(--color-surface-inverse);
--el-code-font-family: var(--font-mono);
--el-code-font-size: var(--typo-size-sm);
/* === List Variables (For UL/OL) === */
--el-list-color: var(--color-text-primary);
--el-list-line-height: var(--typo-leading-normal);
--el-list-font-size: var(--typo-size-md);
--el-list-vspace-base: calc(1em * var(--el-list-line-height));
--el-list-vspace-top: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-list-vspace-bottom: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-list-nested-vspace-top: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-list-nested-vspace-bottom: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-li-vspace-top: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-li-vspace-bottom: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-li-nested-vspace-top: calc(var(--el-list-vspace-base) * var(--vspace-tight));
--el-li-nested-vspace-bottom: calc(var(--el-list-vspace-base) * var(--vspace-tight));
/* === UL VARIABLES === */
--el-ul-indent-l1: var(--spacing-cozy);
--el-ul-indent-l2: var(--spacing-cozy);
--el-ul-indent-l3: var(--spacing-cozy);
--el-ul-indent-l4: var(--spacing-cozy);
--el-ul-item-padding: var(--spacing-cozy);
--el-ul-symbol-l1: '⯃';
--el-ul-symbol-l1-color: var(--color-text-primary);
--el-ul-symbol-l2: '⯁';
--el-ul-symbol-l2-color: var(--color-text-primary);
--el-ul-symbol-l3: '⯆';
--el-ul-symbol-l3-color: var(--color-text-primary);
--el-ul-symbol-l4: '⯀';
--el-ul-symbol-l4-color: var(--color-text-primary);
/* === OL VARIABLES === */
--el-ol-indent-l1: var(--spacing-cozy);
--el-ol-item-indent-l1: 1.5em;
--el-ol-indent-l2: var(--spacing-cozy);
--el-ol-item-indent-l2: 0.825em;
--el-ol-indent-l3: var(--spacing-cozy);
--el-ol-item-indent-l3: 0;
--el-ol-indent-l4: var(--spacing-cozy);
--el-ol-item-indent-l4: 0;
--el-ol-item-padding: var(--spacing-cozy);
--el-ol-line-height: var(--typo-leading-normal);
--el-ol-marker-color-l1: var(--color-text-primary);
--el-ol-prefix-l1: '';
--el-ol-style-l1: decimal-leading-zero;
--el-ol-suffix-l1: '.)';
--el-ol-marker-color-l2: var(--color-text-primary);
--el-ol-prefix-l2: '';
--el-ol-style-l2: lower-alpha;
--el-ol-suffix-l2: '.)';
--el-ol-marker-color-l3: var(--color-text-primary);
--el-ol-prefix-l3: '';
--el-ol-style-l3: upper-roman;
--el-ol-suffix-l3: '.)';
--el-ol-marker-color-l4: var(--color-text-primary);
--el-ol-prefix-l4: '';
--el-ol-style-l4: lower-greek;
--el-ol-suffix-l4: '.)';
/* === DL VARIABLES === */
--el-dl-font-size: var(--typo-size-md);
--el-dl-line-height: var(--typo-leading-normal);
--el-dl-vspace-base: calc(1em * var(--el-dl-line-height));
--el-dl-vspace-top: calc(var(--el-dl-vspace-base) * var(--vspace-snug));
--el-dl-vspace-bottom: calc(var(--el-dl-vspace-base) * var(--vspace-compressed));
/* === DT VARIABLES === */
--el-dt-color: var(--color-text-inverse);
--el-dt-background: var(--color-surface-inverse);
--el-dt-font-family: var(--font-header);
--el-dt-font-size: var(--typo-size-lg);
--el-dt-font-weight: var(--typo-weight-bold);
--el-dt-line-height: 1.4;
--el-dt-text-transform: uppercase;
--el-dt-letter-spacing: 0.035em;
--el-dt-padding: var(--spacing-snug);
--el-dt-vspace-base: calc(1em * var(--el-dt-line-height));
--el-dt-vspace-top: calc(var(--el-dt-vspace-base) * var(--vspace-snug));
--el-dt-vspace-bottom: calc(var(--el-dt-vspace-base) * var(--vspace-compressed));
/* === DD VARIABLES === */
--el-dd-color: var(--color-text-primary);
--el-dd-font-family: var(--font-body);
--el-dd-font-size: var(--typo-size-md);
--el-dd-line-height: var(--typo-leading-normal);
--el-dd-indent: 0 var(--spacing-comfortable);
--el-dd-vspace-base: calc(1em * var(--el-dd-line-height));
--el-dd-vspace-top: calc(var(--el-dd-vspace-base) * var(--vspace-compressed));
--el-dd-vspace-bottom: calc(var(--el-dd-vspace-base) * var(--vspace-tight));
/* === TABLE VARIABLES === */
--el-table-font-size: var(--typo-size-sm);
--el-table-line-height: 1.2;
--el-table-border: var(--size-2) solid var(--color-text-primary);
--el-table-vspace-top: var(--spacing-tight);
--el-table-vspace-bottom: var(--spacing-tight);
/* === TH VARIABLES === */
--el-th-color: var(--color-text-inverse);
--el-th-background: var(--color-surface-inverse);
--el-th-font-family: var(--font-header);
--el-th-font-size: var(--typo-size-sm);
--el-th-font-weight: var(--typo-weight-black);
--el-th-text-transform: uppercase;
--el-th-line-height: var(--el-table-line-height);
--el-th-padding: 0 var(--spacing-snug) var(--spacing-snug);
/* === TD VARIABLES === */
--el-td-color: var(--color-text-primary);
--el-td-font-family: var(--font-mono);
--el-td-font-size: var(--typo-size-sm);
--el-td-line-height: var(--el-table-line-height);
--el-td-padding: var(--spacing-snug);
--el-td-border: var(--size-1) solid var(--color-text-secondary);
/* === CAPTION VARIABLES === */
--el-caption-color: var(--color-text-tertiary);
--el-caption-font-family: var(--font-body);
--el-caption-font-size: var(--typo-size-sm);
--el-caption-font-style: italic;
--el-caption-text-align: center;
/* === FIGCAPTION VARIABLES === */
--el-figcaption-color: var(--color-text-tertiary);
--el-figcaption-font-family: var(--font-body);
--el-figcaption-font-size: var(--typo-size-xs);
--el-figcaption-font-style: italic;
--el-figcaption-text-align: center;
/* === SMALL VARIABLES === */
--el-small-color: var(--color-text-tertiary);
--el-small-font-family: var(--font-body);
--el-small-font-size: var(--typo-size-xs);
/* HR */
--hr-height: var(--size-3);
--hr-margin: var(--spacing-relaxed) 0;
--hr-color: var(--color-text-tertiary);
--hr-symbol-content: "▼";
--hr-symbol-size: var(--typo-size-4xl);
--hr-symbol-space: 0 0.25em;
--hr-symbol-line-height: var(--typo-leading-compressed);
--hr-symbol-color: var(--color-text-tertiary);
--hr-symbol-background: var(--color-surface-base);
/* Header */
--el-header-font-size: var(--typo-size-responsive);
--el-header-line-height: var(--typo-leading-snug);
--el-header-paddingY: var(--spacing-snug);
--el-header-height: calc(
(var(--typo-size-responsive) * var(--el-header-line-height)) +
(var(--el-header-paddingY) * 2)
);
}
}

373
src/styles/globals/foundation.css vendored Normal file
View File

@@ -0,0 +1,373 @@
@layer reset {
/*
Foundation inspired by Tailwind CSS Preflight. (https://tailwindcss.com/docs/preflight)
*/
/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/
*,
::before,
::after {
box-sizing: border-box; /* 1 */
border-style: solid; /* 2 */
border-width: 0; /* 2 */
}
/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the system's `sans` font-family by default.
*/
html {
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */
line-height: 1.5; /* 1 */
text-size-adjust: 100%; /* 2 */
tab-size: 4; /* 3 */
}
/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/
body {
margin: 0; /* 1 */
line-height: inherit; /* 2 */
}
/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/
hr {
height: 0; /* 1 */
border-top-width: 1px; /* 3 */
color: inherit; /* 2 */
}
/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/
abbr:where([title]) {
text-decoration: underline dotted;
}
/*
Remove the default font size and weight for headings.
*/
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
/*
Reset links to optimize for opt-in styling instead of opt-out.
*/
a {
color: inherit;
text-decoration: inherit;
}
/*
Add the correct font weight in Edge and Safari.
*/
b,
strong {
font-weight: bolder;
}
/*
1. Use the system's `mono` font family by default.
2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
"Liberation Mono", "Courier New", monospace; /* 1 */
font-size: 1em; /* 2 */
}
/*
Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/
table {
border-collapse: collapse; /* 3 */
border-color: inherit; /* 2 */
text-indent: 0; /* 1 */
}
/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/
button,
input,
optgroup,
select,
textarea {
margin: 0; /* 2 */
padding: 0; /* 3 */
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
font-weight: inherit; /* 1 */
line-height: inherit; /* 1 */
color: inherit; /* 1 */
}
/*
Remove the inheritance of text transform in Edge and Firefox.
*/
button,
select {
text-transform: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
appearance: auto; /* 1 */
background-color: transparent; /* 2 */
background-image: none; /* 2 */
}
/*
Use the modern Firefox focus style for all focusable elements.
*/
:-moz-focusring {
outline: auto;
}
/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/
:-moz-ui-invalid {
box-shadow: none;
}
/*
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
vertical-align: baseline;
}
/*
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type="search"] {
appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/*
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
appearance: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
font: inherit; /* 2 */
appearance: auto; /* 1 */
}
/*
Add the correct display in Chrome and Safari.
*/
summary {
display: list-item;
}
/*
Removes the default spacing and border for appropriate elements.
*/
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
fieldset {
margin: 0;
padding: 0;
}
legend {
padding: 0;
}
ol,
ul,
menu {
margin: 0;
padding: 0;
list-style: none;
}
/*
Prevent resizing textareas horizontally by default.
*/
textarea {
resize: vertical;
}
/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
*/
input::placeholder,
textarea::placeholder {
opacity: 1; /* 1 */
}
/*
Set the default cursor for buttons.
*/
button,
[role="button"] {
cursor: pointer;
}
/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
cursor: default;
}
/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
This can trigger a poorly considered lint error in some tools but is included by design.
*/
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block; /* 1 */
vertical-align: middle; /* 2 */
}
/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/
img,
video {
max-width: 100%;
height: auto;
}
/*
Make elements with the HTML hidden attribute stay hidden by default.
*/
[hidden] {
display: none;
}
}

View File

@@ -0,0 +1,73 @@
@layer tokens {
:root {
/* === TYPOGRAPHY === */
/* == Font Families == */
--font-header: var(--font-geist-sans);
--font-display: var(--font-blaka);
--font-body: var(--font-iosevka-slab);
--font-mono: var(--font-iosevka-mono);
/* == Font Sizes == */
--typo-size-responsive: clamp(1rem, 2.5vw, 1.25rem);
--typo-size-base: 16px;
--typo-size-8xl: 8em;
--typo-size-7xl: 6.375em;
--typo-size-6xl: 5.0625em;
--typo-size-5xl: 4em;
--typo-size-4xl: 3.1875em;
--typo-size-3xl: 2.5em;
--typo-size-2xl: 2em;
--typo-size-xl: 1.5625em;
--typo-size-lg: 1.25em;
--typo-size-md: 1em;
--typo-size-sm: 0.8125em;
--typo-size-xs: 0.625em;
--typo-size-2xs: 0.5em;
/* == Font Weights == */
--typo-weight-thin: 100;
--typo-weight-extralight: 200;
--typo-weight-light: 300;
--typo-weight-normal: 400;
--typo-weight-medium: 500;
--typo-weight-semibold: 600;
--typo-weight-bold: 700;
--typo-weight-extrabold: 800;
--typo-weight-black: 900;
/* == Letter Spacing == */
--typo-spacing-tightest: -0.05em;
--typo-spacing-tighter: -0.025em;
--typo-spacing-tight: -0.0125em;
--typo-spacing-normal: 0em;
--typo-spacing-relaxed: 0.025em;
--typo-spacing-comfortable: 0.05em;
--typo-spacing-loose: 0.1em;
--typo-spacing-looser: 0.15em;
--typo-spacing-loosest: 0.2em;
/* == Line Height == */
--typo-leading-compressed: 1.0;
--typo-leading-tight: 1.125;
--typo-leading-snug: 1.25;
--typo-leading-cozy: 1.375;
--typo-leading-normal: 1.5;
--typo-leading-relaxed: 1.625;
--typo-leading-comfortable: 1.75;
--typo-leading-loose: 1.875;
--typo-leading-spacious: 2.0;
/* == Vertical Spacing == */
--vspace-compressed: 0.25;
--vspace-tight: 0.5;
--vspace-snug: 0.75;
--vspace-cozy: 1;
--vspace-normal: 1.25;
--vspace-relaxed: 1.5;
--vspace-comfortable: 1.75;
--vspace-loose: 2;
--vspace-spacious: 2.5;
}
}

View File

@@ -0,0 +1,688 @@
@define-mixin anim-img-overexposure {
&:hover {
animation: var(--kf-overexposure) var(--img-overexposure-timing);
}
}
@define-mixin anim-img-contrastslam {
&:hover {
filter: grayscale(var(--base-grayscale)) contrast(var(--contrast-amount)) brightness(var(--brightness-amount));
transition: filter var(--img-contrastslam-duration) var(--img-contrastslam-timing);
}
}
@define-mixin anim-img-colorbleed {
&:hover {
animation: var(--kf-color-bleed) var(--img-colorbleed-duration) var(--img-colorbleed-timing);
}
}
@define-mixin anim-img-filmburn {
&:hover {
animation: var(--kf-film-burn) var(--img-filmburn-duration) var(--img-filmburn-timing);
}
}
@define-mixin anim-img-malfunction {
&:hover {
animation: var(--kf-malfunction) var(--img-malfunction-duration) var(--img-malfunction-timing);
}
}
@define-mixin anim-img-tonerstarvation {
&:hover {
animation: var(--kf-toner-fade) var(--img-tonerstarvation-duration) var(--img-tonerstarvation-timing);
}
}
@define-mixin anim-img-corruption {
&:hover {
animation: var(--kf-digital-corrupt) var(--img-corruption-duration) var(--img-corruption-timing);
}
}
@define-mixin anim-img-starkflash {
&:hover {
animation: var(--kf-stark-flash) var(--img-starkflash-duration) var(--img-starkflash-timing);
}
}
/* === TEXT ANIMATION MIXINS === */
@define-mixin anim-txt-strikethrough-marker {
position: relative;
&::after {
content: '';
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
width: 0%;
height: 1px;
border: 0 solid var(--strike-color);
border-radius: var(--strike-radius);
border-bottom-right-radius: 16px;
background: var(--strike-color);
transition: width var(--strike-duration) var(--strike-timing), border-width var(--strike-duration) var(--strike-timing);
corner-shape: bevel;
}
&:hover::after {
width: 100%;
border-width: var(--strike-border-width);
}
}
@define-mixin anim-txt-strikethrough-industrial {
position: relative;
&:hover::after {
content: '';
position: absolute;
top: 50%;
right: -0.125em;
left: -0.125em;
transform: translateY(-50%);
height: var(--strike-height);
background: var(--strike-color);
animation: var(--kf-strike-slam) var(--strike-duration) var(--strike-timing);
}
}
@define-mixin anim-txt-markerhighlight {
background: linear-gradient(to right, var(--marker-bg) 0%, var(--marker-bg) 0%);
background-repeat: no-repeat;
background-size: 0% 100%;
transition: background-size var(--marker-duration) var(--marker-timing) , color var(--marker-duration) var(--marker-timing) ;
&:hover {
color: var(--marker-fg);
background-size: 100% 100%;
}
}
@define-mixin anim-txt-labelmaker {
transition: all var(--label-duration) var(--label-timing);
&:hover {
margin: var(--label-margin);
padding: var(--label-padding);
border: var(--label-border-width) solid var(--label-bg);
font-weight: var(--label-weight);
color: var(--label-fg);
text-transform: var(--label-transform);
letter-spacing: var(--label-spacing);
background: var(--label-bg);
box-shadow: var(--label-shadow-offset) 0 var(--label-shadow-color);
}
}
@define-mixin anim-txt-rubberstamp {
transition: all var(--stamp-duration) var(--stamp-timing);
&:hover {
transform: rotate(var(--stamp-rotate)) scale(var(--stamp-scale)) translateY(var(--stamp-translate));
margin: var(--stamp-margin);
padding: var(--stamp-padding);
border: var(--stamp-border-width) solid var(--stamp-bg);
font-weight: var(--stamp-weight);
color: var(--stamp-fg);
text-transform: var(--stamp-transform);
letter-spacing: var(--stamp-spacing);
background: var(--stamp-bg);
box-shadow: inset 0 0 0 2px var(--stamp-fg), var(--stamp-shadow-offset) 0 var(--stamp-shadow-color);
}
}
@define-mixin anim-txt-pressstamp {
transition: all var(--press-duration) var(--press-timing);
&:hover {
transform: scaleY(var(--press-scale-y)) scaleX(var(--press-scale-x)) translateY(var(--press-translate));
margin: var(--press-margin);
padding: var(--press-padding);
font-weight: var(--press-weight);
color: var(--press-fg);
letter-spacing: var(--press-spacing);
background: var(--press-bg);
box-shadow: 0 0 0 1px var(--press-border-color), 0 2px 0 var(--press-shadow-1), 0 4px 0 var(--press-shadow-2);
}
}
@define-mixin anim-txt-typewriter {
position: relative;
&::after {
content: '';
position: absolute;
bottom: var(--typewriter-offset);
left: 0;
width: 0%;
height: var(--typewriter-height);
background: repeating-linear-gradient(to right, var(--typewriter-color) 0, var(--typewriter-color) var(--typewriter-dash-length), transparent var(--typewriter-dash-length), transparent var(--typewriter-gap-length));
transition: width var(--typewriter-duration) var(--typewriter-timing);
}
&:hover::after {
width: 100%;
}
}
@define-mixin anim-txt-hardinvert {
transition: all var(--invert-duration) var(--invert-timing);
&:hover {
transform: scale(var(--invert-scale));
font-weight: var(--invert-weight);
color: var(--invert-fg);
letter-spacing: var(--invert-spacing);
background: var(--invert-bg);
}
}
@define-mixin anim-txt-pointer {
position: relative;
&::before,
&::after {
position: absolute;
color: var(--pointer-color);
opacity: 0;
transition: var(--pointer-transition);
}
&::before {
content: var(--pointer-left-symbol);
left: 0;
}
&::after {
content: var(--pointer-right-symbol);
right: 0;
}
&:hover::before {
transform: translateX(calc(var(--pointer-distance) * -1));
opacity: 1;
}
&:hover::after {
transform: translateX(var(--pointer-distance));
opacity: 1;
}
}
@define-mixin anim-txt-cornerbox {
position: relative;
margin: var(--corner-margin);
padding: var(--corner-padding);
&::before,
&::after {
content: '';
position: absolute;
width: var(--corner-size);
height: var(--corner-size);
border: var(--corner-border);
opacity: 0;
transition: var(--corner-transition);
}
&::before {
top: 0;
left: 0;
border-right: none;
border-bottom: none;
}
&::after {
right: 0;
bottom: 0;
border-top: none;
border-left: none;
}
&:hover {
&::before,
&::after {
opacity: 1;
}
}
}
@define-mixin anim-txt-characterglitch {
&:hover {
animation: var(--kf-char-scramble) var(--glitch-duration) var(--glitch-timing);
}
}
@define-mixin anim-txt-pixelshift {
position: relative;
&::before {
content: '';
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: var(--pixel-line-height);
opacity: 0;
background: var(--pixel-bg);
}
&:hover {
color: var(--pixel-fg);
animation: var(--kf-text-glitch) var(--pixel-duration) var(--pixel-timing);
&::before {
opacity: 1;
animation: var(--kf-glitch-line) var(--pixel-duration) var(--pixel-timing);
}
}
}
@define-mixin anim-txt-redacted {
transition: all var(--redacted-duration) var(--redacted-timing);
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 0%;
height: 100%;
background: var(--redacted-bg);
transition: width var(--redacted-duration) var(--redacted-timing);
}
&:hover {
color: transparent;
text-shadow: var(--redacted-shadow);
&::after {
width: 100%;
}
}
}
@define-mixin anim-txt-xray {
transition: all var(--xray-duration) var(--xray-timing);
&:hover {
font-weight: var(--xray-weight);
color: var(--xray-fg);
text-shadow: 0 0 2px var(--xray-glow);
background: var(--xray-bg);
filter: invert(var(--xray-invert)) contrast(var(--xray-contrast)) brightness(var(--xray-brightness)) saturate(var(--xray-saturate));
box-shadow: inset 0 0 0 1px var(--xray-border), 0 0 15px var(--xray-outer-glow);
}
}
@define-mixin anim-txt-strikethrough-marker_focus {
position: relative;
&::after {
content: '';
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
width: 0%;
height: 1px;
border: 0 solid var(--strike-color);
border-radius: var(--strike-radius);
border-bottom-right-radius: 16px;
background: var(--strike-color);
transition: width var(--strike-duration) var(--strike-timing), border-width var(--strike-duration) var(--strike-timing);
corner-shape: bevel;
}
&:focus::after {
width: 100%;
border-width: var(--strike-border-width);
}
}
@define-mixin anim-txt-strikethrough-industrial_focus {
position: relative;
&:focus::after {
content: '';
position: absolute;
top: 50%;
right: -0.125em;
left: -0.125em;
transform: translateY(-50%);
height: var(--strike-height);
background: var(--strike-color);
animation: var(--kf-strike-slam) var(--strike-duration) var(--strike-timing);
}
}
@define-mixin anim-txt-markerhighlight_focus {
background: linear-gradient(to right, var(--marker-bg) 0%, var(--marker-bg) 0%);
background-repeat: no-repeat;
background-size: 0% 100%;
transition: background-size var(--marker-duration) var(--marker-timing) , color var(--marker-duration) var(--marker-timing) ;
&:focus {
color: var(--marker-fg);
background-size: 100% 100%;
}
}
@define-mixin anim-txt-labelmaker_focus {
transition: all var(--label-duration) var(--label-timing);
&:focus {
margin: var(--label-margin);
padding: var(--label-padding);
border: var(--label-border-width) solid var(--label-bg);
font-weight: var(--label-weight);
color: var(--label-fg);
text-transform: var(--label-transform);
letter-spacing: var(--label-spacing);
background: var(--label-bg);
box-shadow: var(--label-shadow-offset) 0 var(--label-shadow-color);
}
}
@define-mixin anim-txt-rubberstamp_focus {
transition: all var(--stamp-duration) var(--stamp-timing);
&:focus {
transform: rotate(var(--stamp-rotate)) scale(var(--stamp-scale)) translateY(var(--stamp-translate));
margin: var(--stamp-margin);
padding: var(--stamp-padding);
border: var(--stamp-border-width) solid var(--stamp-bg);
font-weight: var(--stamp-weight);
color: var(--stamp-fg);
text-transform: var(--stamp-transform);
letter-spacing: var(--stamp-spacing);
background: var(--stamp-bg);
box-shadow: inset 0 0 0 2px var(--stamp-fg), var(--stamp-shadow-offset) 0 var(--stamp-shadow-color);
}
}
@define-mixin anim-txt-pressstamp_focus {
transition: all var(--press-duration) var(--press-timing);
&:focus {
transform: scaleY(var(--press-scale-y)) scaleX(var(--press-scale-x)) translateY(var(--press-translate));
margin: var(--press-margin);
padding: var(--press-padding);
font-weight: var(--press-weight);
color: var(--press-fg);
letter-spacing: var(--press-spacing);
background: var(--press-bg);
box-shadow: 0 0 0 1px var(--press-border-color), 0 2px 0 var(--press-shadow-1), 0 4px 0 var(--press-shadow-2);
}
}
@define-mixin anim-txt-typewriter_focus {
position: relative;
&::after {
content: '';
position: absolute;
bottom: var(--typewriter-offset);
left: 0;
width: 0%;
height: var(--typewriter-height);
background: repeating-linear-gradient(to right, var(--typewriter-color) 0, var(--typewriter-color) var(--typewriter-dash-length), transparent var(--typewriter-dash-length), transparent var(--typewriter-gap-length));
transition: width var(--typewriter-duration) var(--typewriter-timing);
}
&:focus::after {
width: 100%;
}
}
@define-mixin anim-txt-hardinvert_focus {
transition: all var(--invert-duration) var(--invert-timing);
&:focus {
transform: scale(var(--invert-scale));
font-weight: var(--invert-weight);
color: var(--invert-fg);
letter-spacing: var(--invert-spacing);
background: var(--invert-bg);
}
}
@define-mixin anim-txt-pointer_focus {
position: relative;
&::before,
&::after {
position: absolute;
color: var(--pointer-color);
opacity: 0;
transition: var(--pointer-transition);
}
&::before {
content: var(--pointer-left-symbol);
left: 0;
}
&::after {
content: var(--pointer-right-symbol);
right: 0;
}
&:focus::before {
transform: translateX(calc(var(--pointer-distance) * -1));
opacity: 1;
}
&:focus::after {
transform: translateX(var(--pointer-distance));
opacity: 1;
}
}
@define-mixin anim-txt-cornerbox_focus {
position: relative;
margin: var(--corner-margin);
padding: var(--corner-padding);
&::before,
&::after {
content: '';
position: absolute;
width: var(--corner-size);
height: var(--corner-size);
border: var(--corner-border);
opacity: 0;
transition: var(--corner-transition);
}
&::before {
top: 0;
left: 0;
border-right: none;
border-bottom: none;
}
&::after {
right: 0;
bottom: 0;
border-top: none;
border-left: none;
}
&:focus {
&::before,
&::after {
opacity: 1;
}
}
}
@define-mixin anim-txt-characterglitch_focus {
&:focus {
animation: var(--kf-char-scramble) var(--glitch-duration) var(--glitch-timing);
}
}
@define-mixin anim-txt-pixelshift {
position: relative;
&::before {
content: '';
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: var(--pixel-line-height);
opacity: 0;
background: var(--pixel-bg);
}
&:hover {
color: var(--pixel-fg);
animation: var(--kf-text-glitch) var(--pixel-duration) var(--pixel-timing);
&::before {
opacity: 1;
animation: var(--kf-glitch-line) var(--pixel-duration) var(--pixel-timing);
}
}
}
@define-mixin anim-txt-pixelshift_focus {
position: relative;
&::before {
content: '';
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: var(--pixel-line-height);
opacity: 0;
background: var(--pixel-bg);
}
&:focus {
color: var(--pixel-fg);
animation: var(--kf-text-glitch) var(--pixel-duration) var(--pixel-timing);
&::before {
opacity: 1;
animation: var(--kf-glitch-line) var(--pixel-duration) var(--pixel-timing);
}
}
}
@define-mixin anim-txt-redacted_focus {
transition: all var(--redacted-duration) var(--redacted-timing);
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 0%;
height: 100%;
background: var(--redacted-bg);
transition: width var(--redacted-duration) var(--redacted-timing);
}
&:focus {
color: transparent;
text-shadow: var(--redacted-shadow);
&::after {
width: 100%;
}
}
}
@define-mixin anim-txt-xray_focus {
transition: all var(--xray-duration) var(--xray-timing);
&:focus {
font-weight: var(--xray-weight);
color: var(--xray-fg);
text-shadow: 0 0 2px var(--xray-glow);
background: var(--xray-bg);
filter: invert(var(--xray-invert)) contrast(var(--xray-contrast)) brightness(var(--xray-brightness)) saturate(var(--xray-saturate));
box-shadow: inset 0 0 0 1px var(--xray-border), 0 0 15px var(--xray-outer-glow);
}
}

View File

@@ -1,8 +1,8 @@
@define-mixin responsive-wrapper $vspacing: 0, $hspacing: var(--spacing-cozy) { @define-mixin responsive-wrapper $vspacing: 0, $hspacing: var(--spacing-cozy), $fontSize: var(--typo-size-responsive) {
@mixin mx auto; @mixin mx auto;
max-width: clamp(60ch, 90vw, 90ch); max-width: clamp(60ch, 90vw, 90ch);
padding: $vspacing $hspacing; padding: $vspacing $hspacing;
font-family: var(--font-body); font-family: var(--font-body);
font-size: var(--typo-size-responsive); font-size: $fontSize;
} }

View File

@@ -0,0 +1,49 @@
@define-mixin decorator-bb {
padding: var(--bb-spacing, 0);
border: var(--bb-border, var(--size-1) solid var(--color-primary));
border-top-left-radius: var(--bb-radius-tl, var(--size-1));
border-top-right-radius: var(--bb-radius-tr, 0);
border-bottom-right-radius: var(--bb-radius-br, 0);
border-bottom-left-radius: var(--bb-radius-bl, 0);
color: var(--bb-fg, var(--color-text-primary));
background-color: var(--bb-bg, var(--color-primary));
corner-shape: var(--bb-shapes, bevel);
}
@define-mixin decorator-torn {
position: relative;
transform: rotate(1.5deg);
display: block;
padding: 0.4em 0.8em;
border-radius: 0.3em 0.6em 0.4em 0.5em / 0.5em 0.4em 0.6em 0.3em;
color: var(--torn-fg);
background: var(--torn-bg);
clip-path: polygon(
8px 0%,
12px 8%,
6px 18%,
14px 32%,
4px 45%,
12px 58%,
7px 72%,
15px 85%,
8px 100%,
calc(100% - 8px) 100%,
calc(100% - 15px) 85%,
calc(100% - 7px) 72%,
calc(100% - 12px) 58%,
calc(100% - 4px) 45%,
calc(100% - 14px) 32%,
calc(100% - 6px) 18%,
calc(100% - 12px) 8%,
calc(100% - 8px) 0%
);
box-shadow: 2px 2px 4px rgb(0 0 0 / 30%);
}

View File

@@ -1,11 +1,11 @@
@define-mixin grid-col $col $spacing { @define-mixin grid-col $col, $spacing {
display: grid; display: grid;
grid-template-columns: repeat($col, minmax(0, 1fr)); grid-template-columns: repeat($col, minmax(0, 1fr));
gap: $spacing; gap: $spacing;
} }
@define-mixin grid-rows $row $spacing { @define-mixin grid-rows $row, $spacing {
display: grid; display: grid;
grid-template-rows: repeat(1, minmax(0, 1fr)); grid-template-rows: repeat(1, minmax(0, 1fr));
gap: $spacing; gap: $spacing;

View File

@@ -0,0 +1,4 @@
@define-mixin position $position: absolute, $inset-values {
position: $position;
inset: $inset-values;
}

View File

@@ -1,4 +1,4 @@
@efine-mixin m $spacing { @efine-mixin ma $spacing {
margin: $spacing; margin: $spacing;
} }
@@ -41,7 +41,7 @@
} }
} }
@efine-mixin p $spacing { @efine-mixin pa $spacing {
padding: $spacing; padding: $spacing;
} }
@@ -77,7 +77,7 @@
padding-line-end: $spacing; padding-line-end: $spacing;
} }
@define-mixin space-y $spacing $reverse: 0 { @define-mixin space-y $spacing, $reverse: 0 {
& > :not(:last-child) { & > :not(:last-child) {
margin-block-start: calc($spacing * $reverse); margin-block-start: calc($spacing * $reverse);
margin-block-end: calc($spacing * (1 - $reverse)); margin-block-end: calc($spacing * (1 - $reverse));

View File

@@ -40,37 +40,37 @@
letter-spacing: 0.0025em; letter-spacing: 0.0025em;
} }
@define-mixin text-xl { @define-mixin text-xl $leading:1{
font-size: var(--typo-size-xl); font-size: var(--typo-size-xl);
line-height: calc($leading * 1.28); line-height: calc($leading * 1.28);
letter-spacing: 0.0116em; letter-spacing: 0.0116em;
} }
@define-mixin text-lg { @define-mixin text-lg $leading:1 {
font-size: var(--typo-size-lg); font-size: var(--typo-size-lg);
line-height: calc($leading * 1.4); line-height: calc($leading * 1.4);
letter-spacing: 0.022em; letter-spacing: 0.022em;
} }
@define-mixin text-md { @define-mixin text-md $leading:1 {
font-size: var(--typo-size-md); font-size: var(--typo-size-md);
line-height: calc($leading * 1.5); line-height: calc($leading * 1.5);
letter-spacing: 0.035em; letter-spacing: 0.035em;
} }
@define-mixin text-sm { @define-mixin text-sm $leading:1 {
font-size: var(--typo-size-sm); font-size: var(--typo-size-sm);
line-height: calc($leading * 1.5385); line-height: calc($leading * 1.5385);
letter-spacing: 0.05em; letter-spacing: 0.05em;
} }
@define-mixin text-xs { @define-mixin text-xs $leading:1 {
font-size: var(--typo-size-xs); font-size: var(--typo-size-xs);
line-height: calc($leading * 2); line-height: calc($leading * 2);
letter-spacing: 0.074em; letter-spacing: 0.074em;
} }
@define-mixin text-2xs { @define-mixin text-2xs $leading:1 {
font-size: var(--typo-size-2xs); font-size: var(--typo-size-2xs);
line-height: calc($leading * 2); line-height: calc($leading * 2);
letter-spacing: 0.1em; letter-spacing: 0.1em;

6
src/styles/tokens.css Normal file
View File

@@ -0,0 +1,6 @@
@import url('globals/custom-media.css');
@import url('globals/typography.css');
@import url('globals/colors.css');
@import url('globals/dimensions.css');
@import url('globals/elements.css');
@import url('globals/animations.css');

View File

@@ -1,5 +0,0 @@
@import url('./variables/custom-media.css');
@import url('./variables/typography.css');
@import url('./variables/colors.css');
@import url('./variables/dimensions.css');
@import url('./variables/elements.css');

View File

@@ -1,156 +0,0 @@
:root {
/* === Default Palette === */
/* == Blacks, Grays & Off-Whites == */
--color-palette-woodsmoke: oklch(15.5% 0.009 274.276deg); /* Woodsmoke: #0B0C10 */
--color-palette-black-ink: oklch(21.9% 0.006 285.911deg); /* Shark: #1A1A1D */
--color-palette-charcoal: oklch(26.6% 0.008 240.166deg); /* Shark2: #222629 */
--color-palette-charcoal-gray: oklch(33.7% 0.026 266.801deg); /* Bright Gray: #313745 */
--color-palette-slate-gray: oklch(33.3% 0 89.876deg); /* Mineshaft: #363636 */
--color-palette-gunmetal: oklch(41.1% 0.008 248.035deg); /* Abbey2: #474B4F */
--color-palette-carbon: oklch(39.8% 0 89.876deg); /* Tundora: #474747 */
--color-palette-steel-gray: oklch(42.5% 0.003 286.26deg); /* Abbey: #4e4e50 */
--color-palette-dusty-black: oklch(43.7% 0.013 17.672deg); /* DonJuan: #594F4F */
--color-palette-stone: oklch(64.3% 0.005 91.471deg); /* Natural Gray: #8E8D8A */
--color-palette-cloud-gray: oklch(53.6% 0.005 236.565deg); /* Nevada: #6B6E70 */
--color-palette-silver: oklch(72.9% 0.001 17.185deg); /* Silver Chalice: #A8A7A7 */
--color-palette-light-silver: oklch(82.6% 0.002 247.844deg); /* Silversand: #C5C6C7 */
--color-palette-pale-gray: oklch(91.3% 0.004 91.449deg); /* Westar: #E3E2DF */
--color-palette-pale-stone: oklch(89.7% 0.004 106.481deg); /* Quillgray: #DDDDDA */
--color-palette-very-pale-gray: oklch(94.3% 0 89.876deg); /* Gallery: #ECECEC */
--color-palette-off-white: oklch(98.1% 0.003 247.858deg); /* Catskill White: #F7F9fB */
--color-palette-cat-squeeze: oklch(98.3% 0.004 236.496deg); /* Cat Squeeze: #F7FAFC */
/* == Reds == */
--color-palette-oxblood: oklch(30.5% 0.122 12.109deg); /* Bordeaux: #5D001E */
--color-palette-deep-maroon: oklch(37.6% 0.109 11.682deg); /* Crown of Thorns: #6F2232 */
--color-palette-crimson: oklch(43.2% 0.169 7.14deg); /* Monarch: #950740 */
--color-palette-cherry-red: oklch(45.4% 0.168 1.454deg); /* Disco: #9A1750 */
--color-palette-ruby: oklch(52.1% 0.206 15.782deg); /* Shiraz: #C3073F */
--color-palette-red-clay: oklch(65.1% 0.178 27.507deg); /* Burnt Sienna: #E85A4F */
--color-palette-lava: oklch(63.6% 0.193 17.075deg); /* Mandy: #E84A5F */
--color-palette-vivid-scarlet: oklch(66.6% 0.221 15.669deg); /* Radical Red: #FE4365 */
/* == Pinks & Magentas == */
--color-palette-heliotrope: oklch(68.3% 0.217 353.666deg); /* Heliotrope: #F74FA3 */
--color-palette-hot-pink: oklch(65.4% 0.2 6.69deg); /* French Rose: #EE4C7C */
--color-palette-cerise: oklch(60.7% 0.23 18.554deg); /* Amaranth: #EC2049 */
--color-palette-fuchsia: oklch(49.6% 0.181 351.176deg); /* Hibiscus: #A7226E */
--color-palette-dusty-rose: oklch(63.2% 0.11 2.384deg); /* Turkish Rose: #C06C84 */
--color-palette-berry: oklch(60.8% 0.159 2.621deg); /* Mulberry: #CC527A */
--color-palette-petal-pink: oklch(80.5% 0.063 1.992deg); /* Rose Fog: #E3AFBC */
--color-palette-coral-pink: oklch(71.2% 0.162 15.607deg); /* Froly: #F67280 */
--color-palette-sweet-pink: oklch(79.2% 0.114 21.911deg); /* Sweet Pink: #FC9D9A */
/* == Oranges & Browns == */
--color-palette-persimmon: oklch(68.6% 0.179 40.01deg); /* Flamingo: #F26B38 */
--color-palette-terracotta: oklch(71.3% 0.131 27.646deg); /* Apricot: #E98074 */
--color-palette-tan: oklch(82.7% 0.047 76.752deg); /* Akaroa: #D8C3A5 */
--color-palette-peach: oklch(88.5% 0.072 57.746deg); /* Flesh: #FECEAB */
--color-palette-pastel-orange: oklch(82.1% 0.092 42.408deg); /* Rosebud: #F8B195 */
--color-palette-light-apricot: oklch(87.8% 0.066 57.778deg); /* Vivid Tangerine: #F9CDAD */
--color-palette-bone-white: oklch(92.7% 0.015 94.206deg); /* Satin Linen: #EAE7DC */
/* == Yellows == */
--color-palette-ripe-lemon: oklch(83.9% 0.167 91.469deg); /* Ripe Lemon: #F2C51D */
--color-palette-bright-canary: oklch(89% 0.157 97.726deg); /* Energy Yellow: #F7DB4F */
--color-palette-pale-lemon: oklch(95.6% 0.104 121.573deg); /* Mimosa: #E5FCAD */
/* == Greens == */
--color-palette-forest-green: oklch(58.1% 0.127 130.001deg); /* Crete: #61892F */
--color-palette-lime-green: oklch(74.6% 0.18 129.939deg); /* Atlantis: #86C232 */
--color-palette-electric-green: oklch(87.7% 0.227 137.099deg); /* Screaming Green: #87f74f */
--color-palette-sage: oklch(75.1% 0.056 144.175deg); /* Norway: #87f74f */
--color-palette-mint-green: oklch(84.8% 0.098 151.333deg); /* Chinook: #9de0ad */
--color-palette-olive-drab: oklch(82.5% 0.042 107.285deg); /* Olive Drap: #C8C8A9 */
--color-palette-seafoam: oklch(71.6% 0.056 165.214deg); /* Acapulco: #83AF9B */
/* == Blues & Teals == */
--color-palette-dark-navy: oklch(27.3% 0.024 253.693deg); /* Ebony Clay: #1F2833 */
--color-palette-deep-teal: oklch(32.4% 0.018 225.132deg); /* Outer Space: #2A363B */
--color-palette-royal-blue: oklch(46.1% 0.07 245.64deg); /* Ming: #355C7D */
--color-palette-sky-blue: oklch(76.3% 0.129 233.891deg); /* Picton Blue: #4FBFF7 */
--color-palette-slate-blue: oklch(55.1% 0.043 210.602deg); /* Cutty Sark: #547980 */
--color-palette-turquoise: oklch(61.5% 0.091 198.865deg); /* Lochinvar: #2F9599 */
--color-palette-aqua: oklch(68.6% 0.095 190.758deg); /* Keppel: #45ADA8 */
--color-palette-electric-blue: oklch(90.8% 0.128 188.419deg); /* Aquamarine: #66FCF1 */
--color-palette-powder-blue: oklch(88.2% 0.062 187.276deg); /* Powder Blue: #a9e6df */
--color-palette-ice-blue: oklch(99.9% 0.001 197.139deg); /* Twilight Blue: #feffff */
/* === Semantic Colors === */
/* == Primary Colors == */
--color-primary: var(--color-palette-lava);
--color-primary-surface: oklch(from var(--color-primary) calc(l + 0.1) c h);
--color-primary-emphasis: oklch(from var(--color-primary) calc(l - 0.15) c h);
/* == Secondary Colors == */
--color-secondary: var(--color-palette-olive-drab);
--color-secondary-surface: oklch(from var(--color-secondary) calc(l + 0.1) c h);
--color-secondary-emphasis: oklch(from var(--color-secondary) calc(l - 0.15) c h);
/* == Tertiary Colors == */
--color-tertiary: var(--color-palette-bright-canary);
--color-tertiary-surface: oklch(from var(--color-tertiary) calc(l + 0.1) c h);
--color-tertiary-emphasis: oklch(from var(--color-tertiary) calc(l - 0.15) c h);
/* == Text Base Colors == */
--color-text-primary: var(--color-palette-black-ink); /* Main Body Texts, headlines */
--color-text-secondary: var(--color-palette-charcoal); /* Subheading, Secondary Info */
--color-text-tertiary: var(--color-palette-charcoal-gray); /* Captions, Meta Text */
--color-text-quarternary: var(--color-palette-carbon); /* Placeholder Text */
--color-text-inverse: var(--color-palette-ice-blue); /* Text on dark backgrounds */
--color-text-disabled: var(--color-palette-cloud-gray); /* Disabled form labels, inactive text */
/* == Surface Base Colors == */
--color-surface-base: var(--color-palette-ice-blue); /* Main page background */
--color-surface-elevated-1: var(--color-palette-off-white); /* Cards, Panels */
--color-surface-elevated-2: var(--color-palette-very-pale-gray); /* Modals, Dropdowns */
--color-surface-elevated-3: var(--color-palette-pale-gray); /* Tooltips, popovers */
--color-surface-elevated-4: var(--color-palette-light-silver); /* Highest Elevation */
--color-surface-inverse: var(--color-palette-black-ink); /* Darkest Surface for Contrast */
/* == Border Base Colors == */
--color-border-subtle: var(--color-palette-silver); /* Subtle Dividers, Card Borders */
--color-border-normal: var(--color-palette-stone); /* Standard Borders, form fields */
--color-border-strong: var(--color-palette-charcoal-gray); /* Emphasized Borders */
/* == State Colors == */
--color-state-error: var(--color-palette-cerise); /* Error Text, Container, icons */
--color-state-warning: var(--color-palette-persimmon); /* Warning Text, Container, Icons */
--color-state-success: var(--color-palette-lime-green); /* Success Text, Container, Icons */
--color-state-info: var(--color-palette-royal-blue); /* Info Text, Container, Icons */
/* == Link Colors == */
--color-text-link: var(--color-text-tertiary);
--color-text-link-hover: var(--color-secondary);
--color-text-link-visited: var(--color-palette-fuchsia);
/* == Focus States == */
--color-focus-ring: var(--color-primary);
--color-focus-ring-offset: var(--color-primary);
--color-focus-indicator: var(--color-primary-emphasis)
/* == Overlays == */;
--color-utility-overlay-light: oklch(0% 0 0deg / 10%); /* Light overlays */
--color-utility-overlay-medium: oklch(0% 0 0deg / 30%); /* Medium overlays */
--color-utility-overlay-heavy: oklch(0% 0 0deg / 60%); /* Heavy overlays, modal backdrops */
--color-surface-overlay: var(--color-utility-overlay-medium); /* Modal overlays, backdrop */
--color-surface-backdrop: var(--color-utility-overlay-heavy); /* Full screen overlays */
/* == Loading/Skeleton == */
--color-utility-skeleton-base: var(--color-surface-elevated-2); /* Skeleton loader base */
--color-utility-skeleton-shimmer: var(--color-surface-elevated-1); /* Skeleton shimmer effect */
/* == Dividers == */
--color-utility-divider: var(--color-border-subtle); /* Section dividers, HR elements */
--color-utility-divider-strong: var(--color-border-normal); /* Emphasized dividers */
/* == Shadows == */
--color-utility-shadow: oklch(0% 0 0deg / 10%); /* Drop shadows */
--color-utility-shadow-strong: oklch(0% 0 0deg / 25%); /* Strong shadows */
/* == Highlights == */
--color-utility-highlight: var(--color-tertiary-surface); /* Text highlighting, search results */
--color-utility-highlight-strong: var(--color-tertiary); /* Strong highlighting */
}

View File

@@ -1,5 +0,0 @@
@custom-media --bp-mobile (width < 48rem);
@custom-media --bp-tablet (width >= 48rem) and (width < 80rem);
@custom-media --bp-tablet-up (width >= 48rem);
@custom-media --bp-tablet-down (width < 80rem);
@custom-media --bp-desktop (width >= 80rem);

View File

@@ -1,93 +0,0 @@
:root {
/* === DIMENSIONS === */
/* == Base Size Units == */
--size-0: 0;
--size-px: 1px;
--size-05: 0.125rem;
--size-1: 0.25rem;
--size-2: 0.5rem;
--size-3: 0.75rem;
--size-4: 1rem;
--size-5: 1.25rem;
--size-6: 1.5rem;
--size-8: 2rem;
--size-10: 2.5rem;
--size-12: 3rem;
--size-16: 4rem;
--size-20: 5rem;
--size-24: 6rem;
--size-32: 8rem;
--size-40: 10rem;
--size-48: 12rem;
--size-64: 16rem;
--size-80: 20rem;
--size-96: 24rem;
--size-128: 32rem;
--size-160: 40rem;
--size-192: 48rem;
--size-256: 64rem;
--size-320: 80rem;
--size-384: 96rem;
--size-360: 90rem;
--size-400: 100rem;
--size-480: 120rem;
/* == Flexible Dimensions == */
--dim-full: 100%;
--dim-1-2: 50%;
--dim-1-3: 33.3333%;
--dim-2-3: 66.6667%;
--dim-1-4: 25%;
--dim-2-4: var(--dim-1-2);
--dim-3-4: 75%;
--dim-1-5: 20%;
--dim-2-5: 40%;
--dim-3-5: 60%;
--dim-4-5: 80%;
--dim-1-6: 16.6667%;
--dim-2-6: var(--dim-1-3);
--dim-3-6: var(--dim-1-2);
--dim-4-6: var(--dim-2-3);
--dim-5-6: 83.3333%;
--dim-1-8: 12.5%;
--dim-2-8: var(--dim-1-4);
--dim-3-8: 37.5%;
--dim-4-8: var(--dim-1-2);
--dim-5-8: 62.5%;
--dim-6-8: var(--dim-3-4);
--dim-7-8: 87.5%;
--dim-1-10: 10%;
--dim-2-10: var(--dim-1-5);
--dim-3-10: 30%;
--dim-4-10: var(--dim-2-5);
--dim-5-10: var(--dim-1-2);
--dim-6-10: var(--dim-3-5);
--dim-7-10: 70%;
--dim-8-10: var(--dim-4-5);
--dim-9-10: 90%;
--dim-1-12: 8.3333%;
--dim-2-12: var(--dim-1-6);
--dim-3-12: var(--dim-1-4);
--dim-4-12: var(--dim-1-3);
--dim-5-12: 41.6667%;
--dim-6-12: var(--dim-1-2);
--dim-7-12: 58.3333%;
--dim-8-12: var(--dim-2-3);
--dim-9-12: var(--dim-3-4);
--dim-10-12: 83.3333%;
--dim-11-12: 91.6667%;
/* == Semantic Spacing == */;
--spacing-none: var(--size-0);
--spacing-hairline: var(--size-px);
--spacing-tight: var(--size-1);
--spacing-snug: var(--size-2);
--spacing-cozy: var(--size-4);
--spacing-comfortable: var(--size-6);
--spacing-relaxed: var(--size-8);
--spacing-spacious: var(--size-12);
--spacing-generous: var(--size-16);
--spacing-luxurious: var(--size-24);
--spacing-expansive: var(--size-32);
}

View File

@@ -1,255 +0,0 @@
:root {
/* === H1 VARIABLES === */
--el-h1-color: var(--color-text-primary);
--el-h1-font-family: var(--font-display);
--el-h1-font-size: var(--typo-size-7xl);
--el-h1-font-weight: var(--typo-weight-black);
--el-h1-letter-spacing: -0.0137em;
--el-h1-line-height: 1.125;
--el-h1-text-transform: uppercase;
--el-h1-vspace-base: calc(1em * var(--el-h1-line-height));
--el-h1-vspace-top: calc(var(--el-h1-vspace-base) * var(--vspace-spacious));
--el-h1-vspace-bottom: calc(var(--el-h1-vspace-base) * var(--vspace-comfortable));
/* === H2 VARIABLES === */
--el-h2-color: var(--color-text-primary);
--el-h2-font-family: var(--font-heading);
--el-h2-font-size: var(--typo-size-5xl);
--el-h2-font-weight: var(--typo-weight-black);
--el-h2-letter-spacing: -0.0096em;;
--el-h2-line-height: 1.1765;
--el-h2-text-transform: uppercase;
--el-h2-vspace-base: calc(1em * var(--el-h2-line-height));
--el-h2-vspace-top: calc(var(--el-h2-vspace-base) * var(--vspace-snug));
--el-h2-vspace-bottom: calc(var(--el-h2-vspace-base) * var(--vspace-compressed));
/* === H3 VARIABLES === */
--el-h3-color: var(--color-text-secondary);
--el-h3-font-family: var(--font-heading);
--el-h3-font-size: var(--typo-size-4xl);
--el-h3-font-weight: var(--typo-weight-extrabold);
--el-h3-letter-spacing: -0.004em;
--el-h3-line-height: 1.2;
--el-h3-text-transform: uppercase;
--el-h3-vspace-base: calc(1em * var(--el-h3-line-height));
--el-h3-vspace-top: calc(var(--el-h3-vspace-base) * var(--vspace-cozy));
--el-h3-vspace-bottom: calc(var(--el-h3-vspace-base) * var(--vspace-snug));
/* === H4 VARIABLES === */
--el-h4-color: var(--color-text-secondary);
--el-h4-font-family: var(--font-heading);
--el-h4-font-size: var(--typo-size-3xl);
--el-h4-font-weight: var(--typo-weight-extrabold);
--el-h4-letter-spacing: 0.0025em;
--el-h4-line-height: 1.125;
--el-h4-text-transform: uppercase;
--el-h4-vspace-base: calc(1em * var(--el-h4-line-height));
--el-h4-vspace-top: calc(var(--el-h4-vspace-base) * var(--vspace-normal));
--el-h4-vspace-bottom: calc(var(--el-h4-vspace-base) * var(--vspace-tight));
/* === H5 VARIABLES === */
--el-h5-color: var(--color-text-secondary);
--el-h5-font-family: var(--font-heading);
--el-h5-font-size: var(--typo-size-2xl);
--el-h5-font-weight: var(--typo-weight-extrabold);
--el-h5-letter-spacing: 0.05em;
--el-h5-line-height: 1.28;
--el-h5-text-transform: uppercase;
--el-h5-vspace-base: calc(1em * var(--el-h5-line-height));
--el-h5-vspace-top: calc(var(--el-h5-vspace-base) * var(--vspace-cozy));
--el-h5-vspace-bottom: calc(var(--el-h5-vspace-base) * var(--vspace-tight));
/* === H6 VARIABLES === */
--el-h6-color: var(--color-text-secondary);
--el-h6-font-family: var(--font-heading);
--el-h6-font-size: var(--typo-size-xl);
--el-h6-font-weight: var(--typo-weight-black);
--el-h6-letter-spacing: 0.035em;
--el-h6-line-height: 1.4;
--el-h6-text-transform: uppercase;
--el-h6-vspace-base: calc(1em * var(--el-h6-line-height));
--el-h6-vspace-top: calc(var(--el-h6-vspace-base) * var(--vspace-snug));
--el-h6-vspace-bottom: calc(var(--el-h6-vspace-base) * var(--vspace-compressed));
/* === PARAGRAPH VARIABLES === */
--el-p-color: var(--color-text-primary);
--el-p-font-family: var(--font-body);
--el-p-font-size: var(--typo-size-md);
--el-p-font-weight: var(--typo-weight-regular);
--el-p-line-height: var(--typo-leading-normal);
--el-p-text-align: justify;
--el-p-vspace-base: calc(1em * var(--el-p-line-height));
--el-p-vspace-top: calc(var(--el-p-vspace-base) * var(--vspace-snug));
--el-p-vspace-bottom: calc(var(--el-p-vspace-base) * var(--vspace-snug));
/* === BLOCKQUOTE VARIABLES === */
--el-blockquote-color: var(--color-text-tertiary);
--el-border-color: var(--color-text-tertiary);
--el-blockquote-font-family: var(--font-body);
--el-blockquote-font-size: var(--typo-size-md);
--el-blockquote-font-style: var(--typo-weight-regular);
--el-blockquote-font-weight: var(--typo-weight-medium);
--el-blockquote-line-height: var(--typo-leading-comfortable);
--el-blockquote-vspace-base: calc(1em * var(--el-blockquote-line-height));
--el-blockquote-vspace-top: calc(var(--el-blockquote-vspace-base) * var(--vspace-snug));
--el-blockquote-vspace-bottom: calc(var(--el-blockquote-vspace-base) * var(--vspace-snug));
/* === PRE VARIABLES === */
--el-pre-color: var(--color-text-inverse);
--el-pre-background: var(--color-surface-inverse);
--el-pre-font-family: var(--font-mono);
--el-pre-font-size: var(--typo-size-sm);
--el-pre-line-height: 1.5385;
--el-pre-vspace-base: calc(1em * var(--el-pre-line-height));
--el-pre-vspace-top: calc(var(--el-pre-vspace-base) * var(--vspace-normal));
--el-pre-vspace-bottom: calc(var(--el-pre-vspace-base) * var(--vspace-normal));
/* === CODE VARIABLES === */
--el-code-color: var(--color-text-inverse);
--el-code-background: var(--color-surface-inverse);
--el-code-font-family: var(--font-mono);
--el-code-font-size: var(--typo-size-sm);
/* === List Variables (For UL/OL) === */
--el-list-color: var(--color-text-primary);
--el-list-line-height: var(--typo-leading-normal);
--el-list-font-size: var(--typo-size-md);
--el-list-vspace-base: calc(1em * var(--el-list-line-height));
--el-list-vspace-top: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-list-vspace-bottom: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-list-nested-vspace-top: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-list-nested-vspace-bottom: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-li-vspace-top: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-li-vspace-bottom: calc(var(--el-list-vspace-base) * var(--vspace-snug));
--el-li-nested-vspace-top: calc(var(--el-list-vspace-base) * var(--vspace-tight));
--el-li-nested-vspace-bottom: calc(var(--el-list-vspace-base) * var(--vspace-tight));
/* === UL VARIABLES === */
--el-ul-indent-l1: var(--spacing-cozy);
--el-ul-indent-l2: var(--spacing-cozy);
--el-ul-indent-l3: var(--spacing-cozy);
--el-ul-indent-l4: var(--spacing-cozy);
--el-ul-item-padding: var(--spacing-cozy);
--el-ul-symbol-l1: '⯃';
--el-ul-symbol-l1-color: var(--color-text-primary);
--el-ul-symbol-l2: '⯁';
--el-ul-symbol-l2-color: var(--color-text-primary);
--el-ul-symbol-l3: '⯆';
--el-ul-symbol-l3-color: var(--color-text-primary);
--el-ul-symbol-l4: '⯀';
--el-ul-symbol-l4-color: var(--color-text-primary);
/* === OL VARIABLES === */
--el-ol-indent-l1: var(--spacing-cozy);
--el-ol-item-indent-l1: 1.5em;
--el-ol-indent-l2: var(--spacing-cozy);
--el-ol-item-indent-l2: 0.825em;
--el-ol-indent-l3: var(--spacing-cozy);
--el-ol-item-indent-l3: 0;
--el-ol-indent-l4: var(--spacing-cozy);
--el-ol-item-indent-l4: 0;
--el-ol-item-padding: var(--spacing-cozy);
--el-ol-line-height: var(--typo-leading-normal);
--el-ol-marker-color-l1: var(--color-text-primary);
--el-ol-prefix-l1: '';
--el-ol-style-l1: decimal-leading-zero;
--el-ol-suffix-l1: '.)';
--el-ol-marker-color-l2: var(--color-text-primary);
--el-ol-prefix-l2: '';
--el-ol-style-l2: lower-alpha;
--el-ol-suffix-l2: '.)';
--el-ol-marker-color-l3: var(--color-text-primary);
--el-ol-prefix-l3: '';
--el-ol-style-l3: upper-roman;
--el-ol-suffix-l3: '.)';
--el-ol-marker-color-l4: var(--color-text-primary);
--el-ol-prefix-l4: '';
--el-ol-style-l4: lower-greek;
--el-ol-suffix-l4: '.)';
/* === DL VARIABLES === */
--el-dl-font-size: var(--typo-size-md);
--el-dl-line-height: var(--typo-leading-normal);
--el-dl-vspace-base: calc(1em * var(--el-dl-line-height));
--el-dl-vspace-top: calc(var(--el-dl-vspace-base) * var(--vspace-snug));
--el-dl-vspace-bottom: calc(var(--el-dl-vspace-base) * var(--vspace-compressed));
/* === DT VARIABLES === */
--el-dt-color: var(--color-text-inverse);
--el-dt-background: var(--color-surface-inverse);
--el-dt-font-family: var(--font-heading);
--el-dt-font-size: var(--typo-size-lg);
--el-dt-font-weight: var(--typo-weight-bold);
--el-dt-line-height: 1.4;
--el-dt-text-transform: uppercase;
--el-dt-letter-spacing: 0.035em;
--el-dt-padding: var(--spacing-snug);
--el-dt-vspace-base: calc(1em * var(--el-dt-line-height));
--el-dt-vspace-top: calc(var(--el-dt-vspace-base) * var(--vspace-snug));
--el-dt-vspace-bottom: calc(var(--el-dt-vspace-base) * var(--vspace-compressed));
/* === DD VARIABLES === */
--el-dd-color: var(--color-text-primary);
--el-dd-font-family: var(--font-body);
--el-dd-font-size: var(--typo-size-md);
--el-dd-line-height: var(--typo-leading-normal);
--el-dd-indent: 0 var(--spacing-comfortable);
--el-dd-vspace-base: calc(1em * var(--el-dd-line-height));
--el-dd-vspace-top: calc(var(--el-dd-vspace-base) * var(--vspace-compressed));
--el-dd-vspace-bottom: calc(var(--el-dd-vspace-base) * var(--vspace-tight));
/* === TABLE VARIABLES === */
--el-table-font-size: var(--typo-size-sm);
--el-table-line-height: 1.2;
--el-table-border: var(--size-2) solid var(--color-text-primary);
--el-table-vspace-top: var(--spacing-tight);
--el-table-vspace-bottom: var(--spacing-tight);
/* === TH VARIABLES === */
--el-th-color: var(--color-text-inverse);
--el-th-background: var(--color-surface-inverse);
--el-th-font-family: var(--font-heading);
--el-th-font-size: var(--typo-size-sm);
--el-th-font-weight: var(--typo-weight-black);
--el-th-text-transform: uppercase;
--el-th-line-height: var(--el-table-line-height);
--el-th-padding: 0 var(--spacing-snug) var(--spacing-snug);
/* === TD VARIABLES === */
--el-td-color: var(--color-text-primary);
--el-td-font-family: var(--font-mono);
--el-td-font-size: var(--typo-size-sm);
--el-td-line-height: var(--el-table-line-height);
--el-td-padding: var(--spacing-snug);
--el-td-border: var(--size-1) solid var(--color-text-secondary);
/* === CAPTION VARIABLES === */
--el-caption-color: var(--color-text-tertiary);
--el-caption-font-family: var(--font-body);
--el-caption-font-size: var(--typo-size-sm);
--el-caption-font-style: italic;
--el-caption-text-align: center;
/* === FIGCAPTION VARIABLES === */
--el-figcaption-color: var(--color-text-tertiary);
--el-figcaption-font-family: var(--font-body);
--el-figcaption-font-size: var(--typo-size-xs);
--el-figcaption-font-style: italic;
--el-figcaption-text-align: center;
/* === SMALL VARIABLES === */
--el-small-color: var(--color-text-tertiary);
--el-small-font-family: var(--font-body);
--el-small-font-size: var(--typo-size-xs);
/* HR */
--hr-height: var(--size-3);
--hr-margin: var(--spacing-relaxed) 0;
--hr-color: var(--color-text-tertiary);
--hr-symbol-content: "▼";
--hr-symbol-size: var(--typo-size-4xl);
--hr-symbol-space: 0 0.25em;
--hr-symbol-line-height: var(--typo-leading-compressed);
--hr-symbol-color: var(--color-text-tertiary);
--hr-symbol-background: var(--color-surface-base);
}

View File

@@ -1,71 +0,0 @@
:root {
/* === TYPOGRAPHY === */
/* == Font Families == */
--font-header: var(--font-geist-sans);
--font-display: var(--font-blaka);
--font-body: var(--font-iosevka-slab);
--font-mono: var(--font-iosevka-mono);
/* == Font Sizes == */
--typo-size-responsive: clamp(1rem, 2.5vw, 1.25rem);
--typo-size-base: 16px;
--typo-size-8xl: 8em;
--typo-size-7xl: 6.375em;
--typo-size-6xl: 5.0625em;
--typo-size-5xl: 4em;
--typo-size-4xl: 3.1875em;
--typo-size-3xl: 2.5em;
--typo-size-2xl: 2em;
--typo-size-xl: 1.5625em;
--typo-size-lg: 1.25em;
--typo-size-md: 1em;
--typo-size-sm: 0.8125em;
--typo-size-xs: 0.625em;
--typo-size-2xs: 0.5em;
/* == Font Weights == */
--typo-weight-thin: 100;
--typo-weight-extralight: 200;
--typo-weight-light: 300;
--typo-weight-normal: 400;
--typo-weight-medium: 500;
--typo-weight-semibold: 600;
--typo-weight-bold: 700;
--typo-weight-extrabold: 800;
--typo-weight-black: 900;
/* == Letter Spacing == */
--typo-spacing-tightest: -0.05em;
--typo-spacing-tighter: -0.025em;
--typo-spacing-tight: -0.0125em;
--typo-spacing-normal: 0em;
--typo-spacing-relaxed: 0.025em;
--typo-spacing-comfortable: 0.05em;
--typo-spacing-loose: 0.1em;
--typo-spacing-looser: 0.15em;
--typo-spacing-loosest: 0.2em;
/* == Line Height == */
--typo-leading-compressed: 1.0;
--typo-leading-tight: 1.125;
--typo-leading-snug: 1.25;
--typo-leading-cozy: 1.375;
--typo-leading-normal: 1.5;
--typo-leading-relaxed: 1.625;
--typo-leading-comfortable: 1.75;
--typo-leading-loose: 1.875;
--typo-leading-spacious: 2.0;
/* == Vertical Spacing == */
--vspace-compressed: 0.25;
--vspace-tight: 0.5;
--vspace-snug: 0.75;
--vspace-cozy: 1;
--vspace-normal: 1.25;
--vspace-relaxed: 1.5;
--vspace-comfortable: 1.75;
--vspace-loose: 2;
--vspace-spacious: 2.5;
}