diff --git a/content/system/navigation.json b/content/system/navigation.json
new file mode 100644
index 0000000..1d4bb5e
--- /dev/null
+++ b/content/system/navigation.json
@@ -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": "⎊"
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/keystatic.config.ts b/keystatic.config.ts
index aa6a5db..3243832 100644
--- a/keystatic.config.ts
+++ b/keystatic.config.ts
@@ -1,8 +1,11 @@
import { config } from '@keystatic/core';
+import navigation from '@/keystatic/singletons/navigation';
+
export default config({
storage: {
kind: 'local',
},
collections: {},
+ singletons: { navigation },
});
diff --git a/postcss.config.mjs b/postcss.config.mjs
index 1d3a37e..6d7265c 100644
--- a/postcss.config.mjs
+++ b/postcss.config.mjs
@@ -10,11 +10,11 @@ import postcssNesting from 'postcss-nesting';
import postcssPresetEnv from 'postcss-preset-env';
import postcssUtilities from 'postcss-utilities';
import postcssFunctions from 'postcss-functions';
-import customFunctions from './src/postcss/functions';
+import customFunctions from './src/lib/postcss/functions';
const plugins = [
postcssGlobalData({
- files: ['./src/styles/variables/custom-media.css'],
+ files: ['./src/styles/globals/custom-media.css'],
}),
postcssMixins({
mixinsDir: './src/styles/mixins/',
diff --git a/public/images/categories/items/4/background.png b/public/images/categories/items/4/background.png
new file mode 100644
index 0000000..feb1e55
Binary files /dev/null and b/public/images/categories/items/4/background.png differ
diff --git a/src/app/(site)/layout.tsx b/src/app/(site)/layout.tsx
index 51631c6..6864755 100644
--- a/src/app/(site)/layout.tsx
+++ b/src/app/(site)/layout.tsx
@@ -1,5 +1,15 @@
+import { MenuProvider } from '@/contexts/MenuContext';
+import PageHeader from '@/components/Page/Header';
+import PageMenu from '@/components/Page/Menu';
+
export default function SiteLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
- return
- Language Sméagol where? Forest cesspits talked reclaim verse dungeon - Envenom 60 then venerable prolonging! There is only one Lord of the - Ring. -
-- East dry because slinker deeper quarry knocks Sit. Treachery Front whim. - Even the smallest person can change the course of the future. -
-- Do not take me for some conjurer of cheap tricks. Room aged Hobbitses! - Wall odds force simply shield hmm Tuckborough pearl privilege grows. - Ride amazing seeps lake guardian pretty Arwen retrieve stroke steps? -
-- You shall not pass! Pelennor squash least crunchable feel faithless - years well-done fun. Rock ending almost shared extend crooked alliances - possible nightfall Dwarf fine risky. -
-- Possibly Moon effect utterly tipsy overcrowd next misplaced? Covet - parting Brandybuck hungers crevice hours pork haven't tempted - clothing. All right, then. Keep your secrets. -
-| - | Unfold | -Grumbling | -Ago | -Lifetime | -Pillaged | -
|---|---|---|---|---|---|
| Lad | -whip | -arrows | -fairer | -begged | -stabs | -
| Appreciation | -trouble-making | -alone | -horrid | -prove | -they'll | -
| Filthy | -tombs | -vest | -torches | -barrels | -powerful | -
| Instead | -foretold | -ranks | -stare | -joy | -unequaled | -
| Knew | -relations | -fighting | -spirits | -gongs | -bears | -
| Seasoning | -nut | -one's | -approve | -gray | -blessing | -
| beheading | -disturber | -laid | -forth | -watching | -domains | -
- Born revenge utterly that'll Goblin-town gladness. Chips sustained - times apocalypse closest Alfrid grow. I can cut across country easily - enough. Clearing toss unhappy Smeagol's gifted? -
---Sam... I'm glad you are with me.
- -
++); } diff --git a/src/app/globals.css b/src/app/globals.css index 1e03b83..da26779 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,4 +1,6 @@ -@import url("../styles/variables.css"); -@import url("../styles/utilities.css"); -@import url("../styles/foundation.css"); -@import url("../styles/base.css"); \ No newline at end of file +@layer reset, tokens, base, layout, content, components, utilities, animations; + +@import url("../styles/tokens.css"); +@import url("../styles/globals/foundation.css"); +@import url("../styles/globals/base.css"); +@import url("../styles/globals/content.css"); \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 75d5948..595dfbd 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -69,12 +69,11 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - - {children} - + + {children} ); } diff --git a/src/components/Page/Header/Header.module.css b/src/components/Page/Header/Header.module.css new file mode 100644 index 0000000..b5f7ecd --- /dev/null +++ b/src/components/Page/Header/Header.module.css @@ -0,0 +1,77 @@ +@layer components { + .header { + @mixin py var(--el-header-paddingY); + + position: sticky; + z-index: 9; + top: 0; + + width: var(--dim-full); + + color: var(--color-text-inverse); + + background-color: var(--color-surface-inverse); + } + + .inner { + @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); + + } + + .logo { + @mixin anim-txt-characterglitch; + + font-family: var(--font-mono); + animation: + logo-pulse 5s cubic-bezier(0.4, 0, 0.6, 1) infinite; + + &:hover { + transform: translate(0, 0); + color: var(--color-secondary); + } + } + + .pagename { + font-family: var(--font-mono); + + & .bracket { + color: var(--color-secondary); + } + } + + .menutoggle { + @mixin ml auto; + + & 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; + } + } + } + + @keyframes logo-pulse { + 0% { opacity: 1; } + 25% { opacity: 0.66; } + 50% { opacity: 0.33; } + 75% { opacity: 0.66; } + 100% { opacity: 1; } + } +} \ No newline at end of file diff --git a/src/components/Page/Header/index.tsx b/src/components/Page/Header/index.tsx new file mode 100644 index 0000000..4413f00 --- /dev/null +++ b/src/components/Page/Header/index.tsx @@ -0,0 +1,48 @@ +'use client'; + +import Link from 'next/link'; + +import { useMenu } from '@/contexts/MenuContext'; +import styles from './Header.module.css'; + +export default function Header() { + const { isMenuOpen, closeMenu, openMenu, startClosing, resetClosing } = + useMenu(); + + const handleMenuToggle = () => { + if (isMenuOpen) { + startClosing(); + setTimeout(() => { + closeMenu(); + resetClosing(); + }, 800); + } else { + openMenu(); + } + }; + return ( ++ DAVE! DAVE! Do Not Let Us Die In The Dark Night Of This Cold Winter! +
+Background / Image effects
+++ +++ +Overexposure Blast
++++
++ +Contrast Slam
++++
++ +Colorbleed
++++
++ +Film Burn
++++
++ +Photocopier Malfunction
++++
++ +Toner Starvation
++++
++ +Digital Corruption
++++
++Stark Flash
++++
++Instructions
++ Hover over each image to see the effect. These are designed to work + with your base filter: +
+filter: grayscale(1) contrast(150%) brightness(120%)++ 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. +
++ The effects range from subtle (Contrast Slam) to more dramatic + (Digital Corruption). Choose based on how aggressive you want the + interaction to feel. +
+Link Effects
++ {/* Your Ideas */} ++++Strikethrough Mark (Marker)
- More glad painted Sauron the White troop holidays captive has. Many - pierced repel bathroom absence glimpse Tom. All right, then. Keep - your secrets. + This is some text with a{' '} + + strikethrough link + {' '} + in the middle of it.
- -- Common saying among veteran adventurers in the Undercity. - - --+Equipment Requirements
-- All adventurers must carry a minimum of: one weapon (melee or ranged), - basic armor or protective gear, emergency rations for 3 days, torch or - light source, 50 feet of rope, and a first aid kit. -
-- Optional but recommended: lockpicks, crowbar, grappling hook, healing - potions, and backup weapon. -
-++Strikethrough Mark (Industrial)
++ This is some text with a{' '} + + strikethrough link + {' '} + in the middle of it. +
++-Marker Highlight [Industrial]
++ This is some text with a{' '} + + marker highlight link + {' '} + in the middle of it. +
+-Combat Mechanics Overview
-Initiative System
-Roll 1d10 + Initiative characteristic. Highest goes first.
+ {/* Stamping/Punching Effects */} ++-Label Maker
++ This is some text with a{' '} + + label maker link + {' '} + in the middle of it. +
+Attack Resolution
+++ + {/* Industrial/Mechanical */} +Rubber Stamp
++ This is some text with a{' '} + + rubber stamp link + {' '} + in the middle of it. +
+++ +Press/Stamp
++ This is some text with a{' '} + + pressed link + {' '} + in the middle of it. +
+++ +Typewriter Underline
++ This is some text with a{' '} + + typewriter link + {' '} + in the middle of it. +
+++ + {/* Marking/Annotation */} +Hard Invert
++ This is some text with a{' '} + + hard invert link + {' '} + in the middle of it. +
+++ +Bracket Annotation
++ This is some text with a{' '} + + bracket link + {' '} + in the middle of it. +
+++ + {/* Glitch/Digital */} +Corner Box
++ This is some text with a{' '} + + corner box link + {' '} + in the middle of it. +
+++ +Character Glitch
++ This is some text with a{' '} + + glitch link + {' '} + in the middle of it. +
+++ + {/* Extra Ideas */} +Pixel Shift
++ This is some text with a{' '} + + shifting link + {' '} + in the middle of it. +
+++ +Redacted/Censored
++ This is some text with a{' '} + + redacted link + {' '} + in the middle of it. +
+++X-Ray/Negative
++ This is some text with an{' '} + + x-ray link + {' '} + in the middle of it. +
+++ Successful Isildur's brink again throttle flank tightening splash. +
- Roll percentile dice under your relevant skill. Success means you hit, - failure means you miss. + Help illusion embrace liquor tightening intelligence Maggot's whips + bit forests. 17 sing impassable helps Southrons beheading. What's the + Elvish word for 'friend'? +
+Give Hobbitses lend yours lads picking uniting sometime.
++ 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? +
+Doorway Mithrandir clearing wielder strengths floor?
++ 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.
--
- - -- Melee combat uses Weapon Skill
-- Ranged combat uses Ballistic Skill
-- Damage equals weapon damage + Strength bonus
+- Mirkwood.
+- Tom.
+- Bilbo's.
+- Gandalf's.
+- Dwarvish.
--Currently Expanded Section
++
+- Queen wants Oin loose heads decay piety!
+- Large happening arrived owes legends wit war bled Durin's.
+- + Pursuit exactly during relief mission meats cause Noldorin ablaze + tracked. +
+- Darken knife midday meat Goblinses.
+- + Your Rabble-rousers greatest could beast thirty-four t wizards + slumbers reforge. +
+Late vagabond knowing Ent legends there flattened cultured?
- This details element starts open to test the expanded state styling. + Swords are no more use here. Deny Chubbs restored. Scare rebuild + Argonath tracked day's large.
-- Raised Morgoth powerless roaming sing fire-breather regurgitation was. -
-- More glad painted Sauron the White troop holidays captive has. Many - pierced repel bathroom absence glimpse Tom. All right, then. Keep your - secrets. -
-- Prepared Tilda adventure characters crush. Wilds overlook blessed walk - requested. Ligulas sat eavesdropping breathes exceeding dim. Deeper - clever becomes regain Dimholt fronts. --Resilient closest regret vile birthright innards Middle-earth.
-- Shire herald dear hard army carry without proposition. - Thranduil faint me chiefest{' '} - middle hey-diddle-diddle squeaked sawed landlord.{' '} -
-Hallway clot-head's injuryjourney Minas Morgul hasty? - Ring sight fit Boffins S. Manage Bifur ways{' '} - pity's swarming doubt. Wilderness breathing woe liege - Khazad-dum King's handy! Join corpses{' '} -rack tongs knockers gongsfour-day Théoden's idiot.{' '} - Hooded Kingsfoil biding may. Extra{' '} - passion cutting skinned. Hurry problem{' '} - delays Bucklebury. Corks hell hundred deal{' '} - Barahir unprepared. What'll Dwarvish down - bought haunted steps. Master's given Hobbit{' '} - afterwards bodies gibbet. Towers stars productive{' '} - Baggins. Juicy opinion note Déagol tough books spreads. - Decide imaginableGoblin-mutant Silvanfellow.{' '} - Sit Agreed thick drink pearl tale. Legolas approve - night's - retrieve endless. -
--
- +- How
-- - Looks resilient eggs Tauriel higher supplant evisceration idiot - barely. -
-- Names
-- Slugs play Dwalin late parapet ending how morning?
-- - Holidays even disease thunder-battle nice irregular cooked - trouble'll Minas Tirith mistaken! -
-- Mice
-- - Productive Sit mend ones raiding hutch couldn't thirty-four. -
-- - Facing others act doing lives usually pity Legolas laws daughter. -
-- - Lords embalmed nature we'd grievances Thror shelter tragedy. -
-+
+- Easterlings!
+- Bill.
+- Dúnedain!
+- Gandalf.
+- Orcrist.
++
+- Answers feelings Elrond conjurer runs.
+- Sul nudge powerless jelly dumping hair grows log forgave?
+- + Retaken succumbed funeral courtyard Glóin incident mere somewhere + commander assistance? +
+- Bore outrun stead fight Athelas guardroom willing contains.
+- Hunted Angmar wager noose arguing?
+Elros next own wisp whence cakehole right!
++ 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! +
++ +
++ + + ++ Ales +Deeply +Mortality +Open +Single-handedly ++ +Band +appeared +waited +whose +plate +marshaling ++ +Meat +nest +thatched +rallying +claimed +hungers ++ +Mouse +also +birdses +moons +strain +brightest ++ +Hate +different +arrangements +chiefest +think +try ++ +Something's +task +here's +decent +someone +uses ++ + + +Shirt +tonight +bay +beautifully +tad +cloaks ++ + +revenge +teaching +mischief +shores +dreams +tested +Stage dishcloth 20 horses Tooks souls crawl crime.
++ 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! +
+++You are full of surprises, Master Baggins.
+ ++ Sung outscoring fingers Fundin reaction inquiries buggers deadliest. +
++ 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! +
++ Rhudaur fancy tilled heart beggars. Dwarf nothing talked foot club. + Slaughtered flatten Hobbit journey's four-day? ++Pearl tact tomb bits Arwen Evenstar worry?
++ Times unspoiled Silvan.{' '} +
+Sigrid Pippin Gandalfthin stubbornness noises easily + spread. Eldar warriorswon answeredfilth yourself + pocket. Showing store consistency M crevice. Decision + feverfew giving Misty Mountain lord supplant. Gorgoroth{' '} + load born fulfilled plenty fates serpent. Doorstep Pippin's{' '} + pity bridge long weak weep? Brightest Chubbs{' '} + jewels understand. Somewhat Erebor noise squealing moved? + Pippin's feels overrun hours brown burns. Anor{' '} + turning pick prophecy. Surroundedentered needlessly wearyvile + hmm Bagshot Row. Consent outwitted dotage slug Homely hear. + Parapet protected favored defied roam quiet Dori sick + bent. Homage store hurricane prove ferret Helm's Deep + lately? Excellent regret fun often returned Wood-elves + apocalypse. Théodred's rights rat drawing{' '} + examine dared bygone residence deeply.{' '} + Greenway Girion Rohirrim trammel waiting edge. +
++
+- Turn
+- + Bare protuberance arrived forging funny salvage Cair except first + banners. +
+- Foes
+- Bore river large house shadows it's Tuckborough warn.
+- + Stirring Greenwood nest sapphire grant gob flagon famous mean! +
+- Unprepared
+- + Single-handed wriggling creatures lock canopy anytime horses defense + Hobbit's? +
+- + Nûmenor dungeons achieving encourage fretting dines believes + understand. +
+- Ease love shine legs wee harbor Udùn adventure tumble stays.
++ + ); +} diff --git a/src/components/Page/Menu/Menu.module.css b/src/components/Page/Menu/Menu.module.css new file mode 100644 index 0000000..adeeaf9 --- /dev/null +++ b/src/components/Page/Menu/Menu.module.css @@ -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 {} + } +} \ No newline at end of file diff --git a/src/components/Page/Menu/MenuArea/MenuArea.module.css b/src/components/Page/Menu/MenuArea/MenuArea.module.css new file mode 100644 index 0000000..d43f901 --- /dev/null +++ b/src/components/Page/Menu/MenuArea/MenuArea.module.css @@ -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; + } + } + } + } + } +} \ No newline at end of file diff --git a/src/components/Page/Menu/MenuArea/index.tsx b/src/components/Page/Menu/MenuArea/index.tsx new file mode 100644 index 0000000..ec21f9c --- /dev/null +++ b/src/components/Page/Menu/MenuArea/index.tsx @@ -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 ( ++++ ◬ +++ + dave [dmg + ] + +++ +++ {hasBGImg && ( + + ); +}); + +MenuArea.displayName = 'MenuArea'; + +export default MenuArea; diff --git a/src/components/Page/Menu/MenuGrid/MenuGrid.module.css b/src/components/Page/Menu/MenuGrid/MenuGrid.module.css new file mode 100644 index 0000000..6e22f62 --- /dev/null +++ b/src/components/Page/Menu/MenuGrid/MenuGrid.module.css @@ -0,0 +1,115 @@ +@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); + clip-path: inset(0 0 100% 0); + + transition: clip-path 0.35s steps(8, end); + + + &.isOpen { + pointer-events: auto; + + transform: translateY(0); + + visibility: visible; + opacity: 1; + clip-path: inset(0 0 0 0); + } + + &.isClosing { + clip-path: inset(0 0 100% 0); + transition: clip-path 0.25s steps(6, end); + + &.isOpen { + clip-path: inset(0 0 100% 0); + transition: clip-path 0.25s steps(6, end); + } + } + + @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; + } + } +} \ No newline at end of file diff --git a/src/components/Page/Menu/MenuGrid/index.tsx b/src/components/Page/Menu/MenuGrid/index.tsx new file mode 100644 index 0000000..19068d1 --- /dev/null +++ b/src/components/Page/Menu/MenuGrid/index.tsx @@ -0,0 +1,66 @@ +'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, isClosing, startClosing, resetClosing } = + useMenu(); + const menuRef = React.useRef+ )} + +
(null); + const handleClose = React.useCallback(() => { + startClosing(); + setTimeout(() => { + closeMenu(); + resetClosing(); + }, 800); + }, [closeMenu, startClosing, resetClosing]); + + 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 ( + + ); +} diff --git a/src/components/Page/Menu/MenuItem/index.tsx b/src/components/Page/Menu/MenuItem/index.tsx new file mode 100644 index 0000000..ff69c54 --- /dev/null +++ b/src/components/Page/Menu/MenuItem/index.tsx @@ -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 ( + <> + + {hasSublinks(item) && ( + + )} + {hasSubtitle(item) && ( + + )} + > + ); +} diff --git a/src/components/Page/Menu/MenuSublinks/MenuSublinks.module.css b/src/components/Page/Menu/MenuSublinks/MenuSublinks.module.css new file mode 100644 index 0000000..4b36fc1 --- /dev/null +++ b/src/components/Page/Menu/MenuSublinks/MenuSublinks.module.css @@ -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); + } + } + } + } +} \ No newline at end of file diff --git a/src/components/Page/Menu/MenuSublinks/index.tsx b/src/components/Page/Menu/MenuSublinks/index.tsx new file mode 100644 index 0000000..e917fb9 --- /dev/null +++ b/src/components/Page/Menu/MenuSublinks/index.tsx @@ -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 ( + + {sublinks.map((sublink: SubNavigationItem) => ( +
+ ); +} diff --git a/src/components/Page/Menu/MenuSubtitle/MenuSubtitle.module.css b/src/components/Page/Menu/MenuSubtitle/MenuSubtitle.module.css new file mode 100644 index 0000000..d527720 --- /dev/null +++ b/src/components/Page/Menu/MenuSubtitle/MenuSubtitle.module.css @@ -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); + } +} \ No newline at end of file diff --git a/src/components/Page/Menu/MenuSubtitle/index.tsx b/src/components/Page/Menu/MenuSubtitle/index.tsx new file mode 100644 index 0000000..c238b06 --- /dev/null +++ b/src/components/Page/Menu/MenuSubtitle/index.tsx @@ -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) ? ( +- + + {sublink.name} + +
+ ))} ++ + {subtitle.divider.value} + ++ ) : ( + '' + ); + + return ( ++ {divider} ++ ); +} diff --git a/src/components/Page/Menu/MenuTitle/MenuTitle.module.css b/src/components/Page/Menu/MenuTitle/MenuTitle.module.css new file mode 100644 index 0000000..f325277 --- /dev/null +++ b/src/components/Page/Menu/MenuTitle/MenuTitle.module.css @@ -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); + } + } + } + } +} \ No newline at end of file diff --git a/src/components/Page/Menu/MenuTitle/index.tsx b/src/components/Page/Menu/MenuTitle/index.tsx new file mode 100644 index 0000000..82763a6 --- /dev/null +++ b/src/components/Page/Menu/MenuTitle/index.tsx @@ -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 ( +{subtitle.content}
++ + {name} + +
+ ); +} diff --git a/src/components/Page/Menu/index.tsx b/src/components/Page/Menu/index.tsx new file mode 100644 index 0000000..4a1dceb --- /dev/null +++ b/src/components/Page/Menu/index.tsx @@ -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; +} diff --git a/src/contexts/MenuContext.tsx b/src/contexts/MenuContext.tsx new file mode 100644 index 0000000..6ddcc63 --- /dev/null +++ b/src/contexts/MenuContext.tsx @@ -0,0 +1,62 @@ +'use client'; + +import React, { useContext, useEffect } from 'react'; + +interface MenuContextType { + isMenuOpen: boolean; + isClosing: boolean; + closeMenu: () => void; + openMenu: () => void; + startClosing: () => void; + resetClosing: () => void; +} + +const MenuContext = React.createContext (undefined); + +interface MenuProviderProps { + children: React.ReactNode; +} + +export const MenuProvider = ({ children }: MenuProviderProps) => { + const [isMenuOpen, setIsMenuOpen] = React.useState(false); + const [isClosing, setIsClosing] = React.useState(false); + + const closeMenu = () => setIsMenuOpen(false); + const openMenu = () => setIsMenuOpen(true); + const startClosing = () => setIsClosing(true); + const resetClosing = () => setIsClosing(false); + + useEffect(() => { + if (isMenuOpen) { + document.body.style.overflow = 'hidden'; + } else { + document.body.style.overflow = 'unset'; + } + return () => { + document.body.style.overflow = 'unset'; + }; + }, [isMenuOpen]); + + return ( + + {children} + + ); +}; + +export const useMenu = () => { + const context = useContext(MenuContext); + if (context === undefined) { + throw new Error('useMenu must be used within a MenuProvider'); + } + return context; +}; diff --git a/src/hooks/useCurrentPath.ts b/src/hooks/useCurrentPath.ts new file mode 100644 index 0000000..b072af8 --- /dev/null +++ b/src/hooks/useCurrentPath.ts @@ -0,0 +1,8 @@ +import { usePathname } from 'next/navigation'; + +export const useCurrentPath = () => { + const pathname = usePathname(); + const isCurrentPath = (path: string) => path === pathname; + + return { isCurrentPath, pathname }; +}; diff --git a/src/keystatic/singletons/navigation.ts b/src/keystatic/singletons/navigation.ts new file mode 100644 index 0000000..7a00e5c --- /dev/null +++ b/src/keystatic/singletons/navigation.ts @@ -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'})`, + } + ), + }, +}); diff --git a/src/postcss/functions/index.ts b/src/lib/postcss/functions/index.ts similarity index 59% rename from src/postcss/functions/index.ts rename to src/lib/postcss/functions/index.ts index 55de2ad..bf4e31a 100644 --- a/src/postcss/functions/index.ts +++ b/src/lib/postcss/functions/index.ts @@ -1,5 +1,5 @@ module.exports = { alpharize: (color: string, opacity: number) => { - return `oklch(from ${color} l c h / ${opacity}`; + return `oklch(from ${color} l c h / ${opacity})`; }, }; diff --git a/src/lib/readers/base.ts b/src/lib/readers/base.ts new file mode 100644 index 0000000..efcfba7 --- /dev/null +++ b/src/lib/readers/base.ts @@ -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 }; diff --git a/src/lib/readers/system/navigation.ts b/src/lib/readers/system/navigation.ts new file mode 100644 index 0000000..bc738f5 --- /dev/null +++ b/src/lib/readers/system/navigation.ts @@ -0,0 +1,5 @@ +import { cache, reader } from '../base'; + +export const getNavigationData = cache(async () => { + return await reader.singletons.navigation.read(); +}); diff --git a/src/lib/types/navigation.ts b/src/lib/types/navigation.ts new file mode 100644 index 0000000..c7fb3f8 --- /dev/null +++ b/src/lib/types/navigation.ts @@ -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; +} diff --git a/src/lib/utils/classnames.ts b/src/lib/utils/classnames.ts new file mode 100644 index 0000000..63c7643 --- /dev/null +++ b/src/lib/utils/classnames.ts @@ -0,0 +1,8 @@ +export const mapClassnames = ( + classnames: readonly string[], + styles: Record+) => + classnames + .map((cn) => styles[cn]) + .filter(Boolean) + .join(' '); diff --git a/src/styles/base.css b/src/styles/base.css deleted file mode 100644 index 94011cb..0000000 --- a/src/styles/base.css +++ /dev/null @@ -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); -} - diff --git a/src/styles/foundation.css b/src/styles/foundation.css deleted file mode 100644 index 3e78ac4..0000000 --- a/src/styles/foundation.css +++ /dev/null @@ -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; -} diff --git a/src/styles/globals/animations.css b/src/styles/globals/animations.css new file mode 100644 index 0000000..62c8b02 --- /dev/null +++ b/src/styles/globals/animations.css @@ -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; + } +} \ No newline at end of file diff --git a/src/styles/globals/base.css b/src/styles/globals/base.css new file mode 100644 index 0000000..cc29197 --- /dev/null +++ b/src/styles/globals/base.css @@ -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); + } + + +} \ No newline at end of file diff --git a/src/styles/globals/colors.css b/src/styles/globals/colors.css new file mode 100644 index 0000000..08cdbe3 --- /dev/null +++ b/src/styles/globals/colors.css @@ -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 */ + } +} \ No newline at end of file diff --git a/src/styles/globals/content.css b/src/styles/globals/content.css new file mode 100644 index 0000000..3911e3b --- /dev/null +++ b/src/styles/globals/content.css @@ -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); + } + } +} \ No newline at end of file diff --git a/src/styles/globals/custom-media.css b/src/styles/globals/custom-media.css new file mode 100644 index 0000000..cddf695 --- /dev/null +++ b/src/styles/globals/custom-media.css @@ -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); +} \ No newline at end of file diff --git a/src/styles/globals/dimensions.css b/src/styles/globals/dimensions.css new file mode 100644 index 0000000..c9d69b8 --- /dev/null +++ b/src/styles/globals/dimensions.css @@ -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); + } +} \ No newline at end of file diff --git a/src/styles/globals/elements.css b/src/styles/globals/elements.css new file mode 100644 index 0000000..cfb3ef6 --- /dev/null +++ b/src/styles/globals/elements.css @@ -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) + ); + } +} \ No newline at end of file diff --git a/src/styles/globals/foundation.css b/src/styles/globals/foundation.css new file mode 100644 index 0000000..2328308 --- /dev/null +++ b/src/styles/globals/foundation.css @@ -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; + } + +} \ No newline at end of file diff --git a/src/styles/globals/typography.css b/src/styles/globals/typography.css new file mode 100644 index 0000000..dd245eb --- /dev/null +++ b/src/styles/globals/typography.css @@ -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; + + } +} \ No newline at end of file diff --git a/src/styles/mixins/animations.css b/src/styles/mixins/animations.css new file mode 100644 index 0000000..e7e060c --- /dev/null +++ b/src/styles/mixins/animations.css @@ -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); + } +} diff --git a/src/styles/mixins/containers.css b/src/styles/mixins/containers.css index b690974..20e4145 100644 --- a/src/styles/mixins/containers.css +++ b/src/styles/mixins/containers.css @@ -1,7 +1,8 @@ -@define-mixin responsive-wrapper $vspacing: 0 $hspacing: var(--spacing-comfortable) { +@define-mixin responsive-wrapper $vspacing: 0, $hspacing: var(--spacing-cozy), $fontSize: var(--typo-size-responsive) { @mixin mx auto; max-width: clamp(60ch, 90vw, 90ch); padding: $vspacing $hspacing; - font-size: var(--typo-size-responsive); + font-family: var(--font-body); + font-size: $fontSize; } \ No newline at end of file diff --git a/src/styles/mixins/decorators.css b/src/styles/mixins/decorators.css new file mode 100644 index 0000000..f20a632 --- /dev/null +++ b/src/styles/mixins/decorators.css @@ -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%); +} \ No newline at end of file diff --git a/src/styles/mixins/grids.css b/src/styles/mixins/grids.css index 837753d..190b6de 100644 --- a/src/styles/mixins/grids.css +++ b/src/styles/mixins/grids.css @@ -1,11 +1,11 @@ -@define-mixin grid-col $col $spacing { +@define-mixin grid-col $col, $spacing { display: grid; grid-template-columns: repeat($col, minmax(0, 1fr)); gap: $spacing; } -@define-mixin grid-rows $row $spacing { +@define-mixin grid-rows $row, $spacing { display: grid; grid-template-rows: repeat(1, minmax(0, 1fr)); gap: $spacing; diff --git a/src/styles/mixins/position.css b/src/styles/mixins/position.css new file mode 100644 index 0000000..3ffc414 --- /dev/null +++ b/src/styles/mixins/position.css @@ -0,0 +1,4 @@ +@define-mixin position $position: absolute, $inset-values { + position: $position; + inset: $inset-values; +} \ No newline at end of file diff --git a/src/styles/mixins/spacing.css b/src/styles/mixins/spacing.css index 013c23e..5bcb086 100644 --- a/src/styles/mixins/spacing.css +++ b/src/styles/mixins/spacing.css @@ -1,4 +1,4 @@ -@∂efine-mixin m $spacing { +@∂efine-mixin ma $spacing { margin: $spacing; } @@ -41,7 +41,7 @@ } } -@∂efine-mixin p $spacing { +@∂efine-mixin pa $spacing { padding: $spacing; } @@ -77,7 +77,7 @@ padding-line-end: $spacing; } -@define-mixin space-y $spacing $reverse: 0 { +@define-mixin space-y $spacing, $reverse: 0 { & > :not(:last-child) { margin-block-start: calc($spacing * $reverse); margin-block-end: calc($spacing * (1 - $reverse)); diff --git a/src/styles/mixins/typography.css b/src/styles/mixins/typography.css index 4e6f2cd..3ef2b0e 100644 --- a/src/styles/mixins/typography.css +++ b/src/styles/mixins/typography.css @@ -40,37 +40,37 @@ letter-spacing: 0.0025em; } -@define-mixin text-xl { +@define-mixin text-xl $leading:1{ font-size: var(--typo-size-xl); line-height: calc($leading * 1.28); letter-spacing: 0.0116em; } -@define-mixin text-lg { +@define-mixin text-lg $leading:1 { font-size: var(--typo-size-lg); line-height: calc($leading * 1.4); letter-spacing: 0.022em; } -@define-mixin text-md { +@define-mixin text-md $leading:1 { font-size: var(--typo-size-md); line-height: calc($leading * 1.5); letter-spacing: 0.035em; } -@define-mixin text-sm { +@define-mixin text-sm $leading:1 { font-size: var(--typo-size-sm); line-height: calc($leading * 1.5385); letter-spacing: 0.05em; } -@define-mixin text-xs { +@define-mixin text-xs $leading:1 { font-size: var(--typo-size-xs); line-height: calc($leading * 2); letter-spacing: 0.074em; } -@define-mixin text-2xs { +@define-mixin text-2xs $leading:1 { font-size: var(--typo-size-2xs); line-height: calc($leading * 2); letter-spacing: 0.1em; diff --git a/src/styles/tokens.css b/src/styles/tokens.css new file mode 100644 index 0000000..c598797 --- /dev/null +++ b/src/styles/tokens.css @@ -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'); \ No newline at end of file diff --git a/src/styles/utilities.css b/src/styles/utilities.css deleted file mode 100644 index e69de29..0000000 diff --git a/src/styles/variables.css b/src/styles/variables.css deleted file mode 100644 index 25eee5d..0000000 --- a/src/styles/variables.css +++ /dev/null @@ -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'); \ No newline at end of file diff --git a/src/styles/variables/colors.css b/src/styles/variables/colors.css deleted file mode 100644 index bc9d6ac..0000000 --- a/src/styles/variables/colors.css +++ /dev/null @@ -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-electric-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(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 */ -} \ No newline at end of file diff --git a/src/styles/variables/custom-media.css b/src/styles/variables/custom-media.css deleted file mode 100644 index a70ea2c..0000000 --- a/src/styles/variables/custom-media.css +++ /dev/null @@ -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); \ No newline at end of file diff --git a/src/styles/variables/dimensions.css b/src/styles/variables/dimensions.css deleted file mode 100644 index 8309be2..0000000 --- a/src/styles/variables/dimensions.css +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/src/styles/variables/elements.css b/src/styles/variables/elements.css deleted file mode 100644 index 4cb0a32..0000000 --- a/src/styles/variables/elements.css +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/src/styles/variables/typography.css b/src/styles/variables/typography.css deleted file mode 100644 index aa5e8ae..0000000 --- a/src/styles/variables/typography.css +++ /dev/null @@ -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; - -} \ No newline at end of file