basic setup

This commit is contained in:
nicwands
2026-05-18 15:13:23 -04:00
parent c4113658f7
commit a54e63323f
33 changed files with 2563 additions and 43 deletions

7
styles/_colors.scss Normal file
View File

@@ -0,0 +1,7 @@
@use 'sass:color';
:root {
@each $name, $color in getColors() {
--#{$name}: #{$color};
}
}

22
styles/_easings.scss Normal file
View File

@@ -0,0 +1,22 @@
:root {
--ease-in-quad: cubic-bezier(0.55, 0.085, 0.68, 0.53);
--ease-in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19);
--ease-in-quart: cubic-bezier(0.895, 0.03, 0.685, 0.22);
--ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06);
--ease-in-expo: cubic-bezier(0.95, 0.05, 0.795, 0.035);
--ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.335);
--ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--ease-out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1);
--ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
--ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
--ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
--ease-out-circ: cubic-bezier(0.075, 0.82, 0.165, 1);
--ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
--ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1);
--ease-in-out-quart: cubic-bezier(0.77, 0, 0.175, 1);
--ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1);
--ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
--ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.15, 0.86);
--ease-custom: cubic-bezier(0.315, 0.365, 0.23, 0.985);
}

31
styles/_font-style.scss Normal file
View File

@@ -0,0 +1,31 @@
@use 'functions' as *;
@mixin size-font($ds, $ms) {
font-size: mobile-vw($ms);
&.vh {
font-size: mobile-vh($ms);
}
@include desktop {
font-size: desktop-vw($ds);
&.vh {
font-size: desktop-vh($ds);
}
}
}
@mixin h1 {
font-family: var(--font-times);
font-weight: 400;
letter-spacing: 0.1em;
@include size-font(42px, 27px);
}
@mixin p {
font-family: var(--font-times);
font-weight: 400;
letter-spacing: 0.03em;
@include size-font(25px, 18px);
}

26
styles/_fonts.scss Normal file
View File

@@ -0,0 +1,26 @@
/*
Font Weights:
100 - Thin
200 - Extra Light (Ultra Light)
300 - Light
400 - Normal
500 - Medium
600 - Semi Bold (Demi Bold)
700 - Bold
800 - Extra Bold (Ultra Bold)
900 - Black (Heavy)
*/
/* OFFICE TIMES */
@font-face {
font-family: 'Office Times';
font-style: normal;
font-weight: 400;
src:
url('/fonts/OfficeTimesRound-Regular.woff2') format('woff2'),
url('/fonts/OfficeTimesRound-Regular.woff') format('woff');
}
:root {
--font-times: 'Office Times', monospace;
}

187
styles/_functions.scss Normal file
View File

@@ -0,0 +1,187 @@
@use 'sass:math';
/* Breakpoints */
$mobile-breakpoint: get('breakpoints.mobile');
// Viewport Sizes
$desktop-width: get('viewports.desktop.width');
$desktop-height: get('viewports.desktop.height');
$mobile-width: get('viewports.mobile.width');
$mobile-height: get('viewports.mobile.height');
// Breakpoint
@mixin mobile {
@media (max-width: #{$mobile-breakpoint * 1px - 1px}) {
@content;
}
}
@mixin desktop {
@media (min-width: #{$mobile-breakpoint * 1px}) {
@content;
}
}
@function mobile-vw($pixels, $base-vw: $mobile-width) {
$px: math.div($pixels, $base-vw);
$perc: math.div($px, 1px);
@return calc($perc * 100vw);
}
@function mobile-vh($pixels, $base-vh: $mobile-height) {
$px: math.div($pixels, $base-vh);
$perc: math.div($px, 1px);
@return calc($perc * 100vh);
}
@function desktop-vw($pixels, $base-vw: $desktop-width) {
$px: math.div($pixels, $base-vw);
$perc: math.div($px, 1px);
@return calc($perc * 100vw);
}
@function desktop-vh($pixels, $base-vh: $desktop-height) {
$px: math.div($pixels, $base-vh);
$perc: math.div($px, 1px);
@return calc($perc * 100vh);
}
@function columns($columns) {
@return calc(
(#{$columns} * var(--layout-column-width)) +
((#{$columns} - 1) * var(--layout-column-gap))
);
}
@mixin child-grid($columns) {
grid-template-columns: repeat($columns, minmax(0, 1fr));
column-gap: var(--layout-columns-gap);
display: grid;
}
@mixin reduced-motion {
@media (prefers-reduced-motion: reduce) {
@content;
}
}
@mixin fill($position: absolute) {
position: #{$position};
bottom: 0;
right: 0;
left: 0;
top: 0;
}
@mixin fade-on-ready($class: 'ready', $duration: 400ms) {
opacity: 0;
transition: opacity $duration ease;
&.#{$class} {
opacity: 1;
}
}
// Clamp text block to number of lines
@mixin line-clamp($lines: 3, $mobile-lines: $lines) {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: $lines;
@include mobile {
-webkit-line-clamp: $mobile-lines;
}
}
// Flip animations
@keyframes flip-r {
50% {
transform: translateX(100%);
opacity: 0;
}
51% {
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes flip-l {
50% {
transform: translateX(-100%);
opacity: 0;
}
51% {
transform: translateX(100%);
opacity: 0;
}
}
@keyframes flip-d {
50% {
transform: translateY(100%);
opacity: 0;
}
51% {
transform: translateY(-100%);
opacity: 0;
}
}
@keyframes flip-u {
50% {
transform: translateY(-100%);
opacity: 0;
}
51% {
transform: translateY(100%);
opacity: 0;
}
}
@mixin flip-animation(
$direction: 'r',
$duration: 600ms,
$easing: var(--ease-out-expo),
$iteration-count: 1
) {
overflow: hidden;
animation: flip-#{$direction} $duration $easing $iteration-count forwards;
}
@mixin link-hover {
position: relative;
&::before {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: var(--theme-fg);
transform-origin: left;
transform: scaleX(0);
transition: transform 300ms var(--ease-out-quad);
}
@include desktop {
&:hover::before {
transform: scaleX(1);
}
}
}
@mixin stagger-animate($stagger: 100, $num-children: 10, $base-delay: 0) {
@for $i from 0 through $num-children {
&:nth-child(#{$i + 1}) {
transition-delay: #{$stagger * $i + $base-delay}ms;
}
}
}
@mixin hover {
@include desktop {
&:hover {
@content;
}
}
}

7
styles/_layers.scss Normal file
View File

@@ -0,0 +1,7 @@
// z-index
.lily-cursor {
z-index: 20;
}
.site-header {
z-index: 10;
}

91
styles/_layout.scss Normal file
View File

@@ -0,0 +1,91 @@
@use 'sass:list';
@use 'functions' as *;
// css variables exposed globally:
// --layout-column-count: columns count in the layout
// --layout-column-gap: gap size between columns
// --layout-margin: layout margin size (left or right)
// --layout-width: 100vw minus 2 * --layout-margin
// --layout-column-width: size of a single column
// css classes exposed globally:
// .layout-block: element takes the whole layout width
// .layout-block-inner: same as .layout-block but using padding instead of margin
// .layout-grid: extends .layout-block with grid behaviour using layout settings
// .layout-grid-inner: same as .layout-grid but using padding instead of margin
@use 'sass:map';
// config to fill
// 'variable': (mobile, desktop)
$layout: (
'columns-count': (
5,
18,
),
'columns-gap': (
20px,
20px,
),
'margin': (
30px,
60px,
),
);
//internal process, do not touch
:root {
--layout-column-count: #{list.nth(map.get($layout, 'columns-count'), 1)};
--layout-column-gap: #{mobile-vw(
list.nth(map.get($layout, 'columns-gap'), 1)
)};
--layout-margin: #{mobile-vw(list.nth(map.get($layout, 'margin'), 1))};
--layout-width: calc(100vw - (2 * var(--layout-margin)));
--layout-column-width: calc(
(
var(--layout-width) -
(
(var(--layout-column-count) - 1) *
var(--layout-column-gap)
)
) /
var(--layout-column-count)
);
@include desktop {
--layout-column-count: #{list.nth(map.get($layout, 'columns-count'), 2)};
--layout-column-gap: #{desktop-vw(
list.nth(map.get($layout, 'columns-gap'), 2)
)};
--layout-margin: #{desktop-vw(list.nth(map.get($layout, 'margin'), 2))};
}
}
.layout-block {
max-width: var(--layout-width);
margin-left: auto;
margin-right: auto;
width: 100%;
}
.layout-block-inner {
padding-left: var(--layout-margin);
padding-right: var(--layout-margin);
width: 100%;
}
.layout-grid {
@extend .layout-block;
display: grid;
grid-template-columns: repeat(var(--layout-column-count), minmax(0, 1fr));
grid-gap: var(--layout-column-gap);
}
.layout-grid-inner {
@extend .layout-block-inner;
display: grid;
grid-template-columns: repeat(var(--layout-column-count), minmax(0, 1fr));
grid-gap: var(--layout-column-gap);
}

99
styles/_reset.scss Normal file
View File

@@ -0,0 +1,99 @@
/***
The new CSS reset - version 1.9 (last updated 19.6.2023)
GitHub page: https://github.com/elad2412/the-new-css-reset
***/
/*
Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property
- The "symbol *" part is to solve Firefox SVG sprite bug
- The "html" element is excluded, otherwise a bug in Chrome breaks the CSS hyphens property (https://github.com/elad2412/the-new-css-reset/issues/36)
*/
*:where(
:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)
) {
all: unset;
display: revert;
}
/* Preferred box-sizing value */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Reapply the pointer cursor for anchor tags */
a,
button {
cursor: revert;
}
/* For images to not be able to exceed their container */
img {
max-inline-size: 100%;
max-block-size: 100%;
}
/* removes spacing between cells in tables */
table {
border-collapse: collapse;
}
/* Safari - solving issue when using user-select:none on the <body> text input doesn't working */
input,
textarea {
-webkit-user-select: auto;
}
/* revert the 'white-space' property for textarea elements on Safari */
textarea {
white-space: revert;
}
/* minimum style to allow to style meter element */
meter {
-webkit-appearance: revert;
appearance: revert;
}
/* preformatted text - use only for this feature */
:where(pre) {
all: revert;
}
/* reset default text opacity of input placeholder */
::placeholder {
color: unset;
}
/* remove default dot (•) sign */
::marker {
content: initial;
}
/* fix the feature of 'hidden' attribute.
display:revert; revert to element instead of attribute */
:where([hidden]) {
display: none;
}
/* revert for bug in Chromium browsers
- fix for the content editable attribute will work properly.
- webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element*/
:where([contenteditable]:not([contenteditable='false'])) {
-moz-user-modify: read-write;
-webkit-user-modify: read-write;
overflow-wrap: break-word;
-webkit-line-break: after-white-space;
-webkit-user-select: auto;
}
/* apply back the draggable feature - exist only in Chromium and Safari */
:where([draggable='true']) {
-webkit-user-drag: element;
}
/* Revert Modal native behavior */
:where(dialog:modal) {
all: revert;
}

34
styles/_scroll.scss Normal file
View File

@@ -0,0 +1,34 @@
html {
&:not(.dev) {
&,
* {
scrollbar-width: none !important;
-ms-overflow-style: none !important;
&::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}
}
}
}
html.lenis {
height: auto;
}
.lenis.lenis-smooth {
scroll-behavior: auto;
}
.lenis.lenis-smooth [data-lenis-prevent] {
overscroll-behavior: contain;
}
.lenis.lenis-stopped {
overflow: hidden;
}
.lenis.lenis-scrolling iframe {
pointer-events: none;
}

11
styles/_themes.scss Normal file
View File

@@ -0,0 +1,11 @@
@use 'sass:color';
:root {
@each $name, $theme in getThemes() {
.theme-#{$name} {
@each $name, $color in $theme {
--theme-#{$name}: #{$color};
}
}
}
}

43
styles/_transitions.scss Normal file
View File

@@ -0,0 +1,43 @@
// Fades
.fade-enter-active,
.fade-leave-active {
transition: opacity 400ms;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.quick-fade-enter-active,
.quick-fade-leave-active {
transition: opacity 100ms;
}
.quick-fade-enter-from,
.quick-fade-leave-to {
opacity: 0;
}
.slow-fade-enter-active,
.slow-fade-leave-active {
transition: opacity 600ms;
}
.slow-fade-enter-from,
.slow-fade-leave-to {
opacity: 0;
}
// Slides
.slide-up-enter-active,
.slide-up-leave-active {
transition: transform 400ms var(--ease-out-quad);
}
.slide-up-enter-from,
.slide-up-leave-to {
transform: translateY(-100%);
}
.slide-left-enter-active,
.slide-left-leave-active {
transition: transform 400ms var(--ease-out-quad);
}
.slide-left-enter-from,
.slide-left-leave-to {
transform: translateX(-100%);
}

42
styles/_utils.scss Normal file
View File

@@ -0,0 +1,42 @@
@use 'functions' as *;
.full-width {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
.overflow-hidden {
overflow: hidden;
}
.relative {
position: relative;
}
.mobile-only {
@include desktop {
display: none !important;
}
}
.desktop-only {
@include mobile {
display: none !important;
}
}
html:not(.has-scroll-smooth) {
.hide-on-native-scroll {
display: none;
}
}
html.has-scroll-smooth {
.hide-on-smooth-scroll {
display: none;
}
}

111
styles/main.scss Normal file
View File

@@ -0,0 +1,111 @@
@use 'colors' as *;
@use 'themes' as *;
@use 'easings' as *;
@use 'reset' as *;
@use 'layers' as *;
@use 'functions' as *;
@use 'utils' as *;
@use 'fonts' as *;
@use 'font-style' as *;
@use 'layout' as *;
@use 'scroll' as *;
@use 'transitions' as *;
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
background: var(--white);
color: var(--black);
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
margin: 0;
min-height: 100vh;
}
// Type
.h1,
h1,
h2,
h3,
h4,
h5,
h6 {
@include h1;
}
.p,
p,
a,
button,
input,
pre {
@include p;
}
.entry {
img {
max-width: 100%;
height: auto;
}
p {
min-height: 1px;
}
a {
text-decoration: underline;
}
& > * {
margin-bottom: 1em;
margin-top: 1em;
}
& > *:first-child {
margin-top: 0;
}
& > *:last-child {
margin-bottom: 0;
}
ul,
ol {
li {
margin-bottom: 1em;
width: desktop-vw(577px);
}
}
ul {
list-style: disc;
padding-left: 1em;
}
}
#app {
min-height: 100vh;
}
@keyframes blink {
5% {
opacity: 0;
}
40% {
opacity: 0;
}
60% {
opacity: 1;
}
95% {
opacity: 1;
}
}
@keyframes bonk {
0% {
transform: rotate(calc(var(--bonk-angle) * -1));
}
50% {
transform: rotate(var(--bonk-angle));
}
}