Initial-commit

This commit is contained in:
Kismet Hasanaj
2026-05-02 23:53:52 +02:00
parent dbf4c80804
commit ec83a0d879
36 changed files with 19889 additions and 1 deletions
+338
View File
@@ -0,0 +1,338 @@
/* ============================================================================
Novarix Networks — Global stylesheet
============================================================================
This file controls the visual *theme* of the site (colours, fonts,
background effects, animations). Most page layout is done with Tailwind
utility classes directly inside `app/page.tsx` — this file only handles
things that don't fit neatly into utilities.
What's in here, top to bottom:
1. Design tokens — brand colours, font, shadows (@theme block)
2. Theme variables — light + dark mode CSS variables
3. Base styles — body font, focus rings, text selection
4. Site shell + ambient — background gradient, floating orbs, grid
5. Brand wordmark swap — light/dark logo switcher
6. Intro overlay — first-visit animated logo
7. Animations — keyframes used above
8. Reduced motion — respect "prefers-reduced-motion" setting
To change the brand colour palette, edit the `--color-brand-*` lines in
the @theme block below. Everything else cascades from those.
============================================================================ */
@import "tailwindcss";
/* ---------------------------------------------------------------------------
1. Design tokens — registered with Tailwind v4 via @theme.
These become utility classes (e.g. `bg-brand-500`, `text-ink-900`) and
custom CSS variables you can use anywhere in the stylesheet.
--------------------------------------------------------------------------- */
@theme {
--font-sans:
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
"Segoe UI", sans-serif;
--color-brand-50: oklch(0.97 0.015 240);
--color-brand-100: oklch(0.93 0.04 240);
--color-brand-200: oklch(0.86 0.07 240);
--color-brand-300: oklch(0.78 0.11 240);
--color-brand-400: oklch(0.7 0.14 240);
--color-brand-500: oklch(0.62 0.16 240);
--color-brand-600: oklch(0.54 0.18 245);
--color-brand-700: oklch(0.46 0.18 250);
--color-ink-50: oklch(0.985 0.003 250);
--color-ink-100: oklch(0.96 0.005 250);
--color-ink-200: oklch(0.92 0.008 250);
--color-ink-300: oklch(0.84 0.012 250);
--color-ink-400: oklch(0.65 0.018 250);
--color-ink-500: oklch(0.5 0.02 250);
--color-ink-600: oklch(0.38 0.022 250);
--color-ink-700: oklch(0.28 0.024 250);
--color-ink-800: oklch(0.2 0.026 250);
--color-ink-900: oklch(0.13 0.028 255);
--color-ink-950: oklch(0.08 0.03 260);
--radius-card: 1.25rem;
--shadow-card: 0 1px 0 0 oklch(1 0 0 / 0.04) inset, 0 12px 32px -12px oklch(0 0 0 / 0.18);
}
/* ---------------------------------------------------------------------------
2. Theme variables (light + dark)
These are the runtime CSS variables read by both this file and
app/page.tsx (via classes like `bg-[var(--surface)]`). Each variable has
a light value here and a dark override further down inside the
`@media (prefers-color-scheme: dark)` block.
--------------------------------------------------------------------------- */
:root {
color-scheme: light dark;
--bg: var(--color-ink-50);
--surface: oklch(1 0 0 / 0.7);
--surface-strong: oklch(1 0 0 / 0.92);
--text: var(--color-ink-900);
--text-soft: var(--color-ink-500);
--border: oklch(0.13 0.028 255 / 0.1);
--border-strong: oklch(0.13 0.028 255 / 0.18);
--accent: var(--color-brand-500);
--accent-soft: oklch(0.62 0.16 240 / 0.12);
--ring: oklch(0.62 0.16 240 / 0.4);
--grid: oklch(0.5 0.02 250 / 0.08);
--button-bg: var(--color-ink-900);
--button-fg: var(--color-ink-50);
--button-hover: var(--color-ink-800);
}
@media (prefers-color-scheme: dark) {
:root {
--bg: var(--color-ink-950);
--surface: oklch(0.13 0.028 255 / 0.55);
--surface-strong: oklch(0.13 0.028 255 / 0.85);
--text: var(--color-ink-100);
--text-soft: var(--color-ink-400);
--border: oklch(1 0 0 / 0.08);
--border-strong: oklch(1 0 0 / 0.16);
--accent: var(--color-brand-400);
--accent-soft: oklch(0.7 0.14 240 / 0.18);
--ring: oklch(0.7 0.14 240 / 0.5);
--grid: oklch(0.84 0.012 250 / 0.06);
--button-bg: var(--color-ink-100);
--button-fg: var(--color-ink-950);
--button-hover: var(--color-ink-50);
}
}
/* ---------------------------------------------------------------------------
3. Base styles — applied to plain HTML elements before any classes hit.
--------------------------------------------------------------------------- */
@layer base {
html {
scroll-behavior: smooth;
}
body {
background: var(--bg);
color: var(--text);
font-family: var(--font-sans);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
overflow-x: hidden;
}
::selection {
background: var(--accent-soft);
color: var(--text);
}
:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 3px;
border-radius: 4px;
}
}
/* ---------------------------------------------------------------------------
4. Site shell + ambient effects
The .site-shell class is on the <main> element in page.tsx. The two
radial gradients here follow the user's mouse via the --mx / --my CSS
variables that page.tsx writes on every mousemove.
--------------------------------------------------------------------------- */
.site-shell {
position: relative;
isolation: isolate;
min-height: 100vh;
background:
radial-gradient(
circle at var(--mx, 50%) var(--my, 22%),
oklch(0.62 0.16 240 / 0.12),
transparent 20%
),
radial-gradient(
circle at calc(var(--mx, 50%) * 0.65) calc(var(--my, 22%) * 1.2),
oklch(0.6 0.14 280 / 0.09),
transparent 24%
),
var(--bg);
}
.ambient-grid {
position: absolute;
inset: 0;
background-image:
linear-gradient(to right, var(--grid) 1px, transparent 1px),
linear-gradient(to bottom, var(--grid) 1px, transparent 1px);
background-size: 56px 56px;
mask-image: linear-gradient(to bottom, oklch(0 0 0 / 0.5), transparent 80%);
}
.ambient-orb {
position: absolute;
border-radius: 9999px;
filter: blur(80px);
opacity: 0.22;
animation: drift 18s ease-in-out infinite;
will-change: transform;
}
.ambient-orb-a {
width: 32rem;
height: 32rem;
top: 4rem;
right: -10rem;
background: linear-gradient(
135deg,
oklch(0.7 0.14 240 / 0.55),
oklch(0.6 0.14 200 / 0.1)
);
}
.ambient-orb-b {
width: 26rem;
height: 26rem;
top: 28rem;
left: -8rem;
background: linear-gradient(
135deg,
oklch(0.6 0.14 280 / 0.35),
oklch(0.78 0.11 200 / 0.12)
);
animation-duration: 22s;
}
/* ---------------------------------------------------------------------------
5. Brand wordmark colour-scheme swap
The header logo has two PNG variants — a colour one for light mode and a
white one for dark mode. The `brand-light` / `brand-dark` classes (set
in page.tsx) live on both <Image> tags; only the matching one is shown.
--------------------------------------------------------------------------- */
.brand-light {
display: block;
}
.brand-dark {
display: none;
}
@media (prefers-color-scheme: dark) {
.brand-light {
display: none;
}
.brand-dark {
display: block;
}
}
/* ---------------------------------------------------------------------------
6. Intro overlay
The first-visit animated SVG wordmark. The SVG itself runs a 3-second
stroke-then-fill animation (defined inside
/public/branding/animated_logo_intro.svg). The overlay fades out at the
3-second mark so the SVG completes before it disappears. Total intro
length is matched in page.tsx's setTimeout (3600ms).
When .intro-running is on the <main> element, the page content
underneath is hidden so it doesn't flash through during the animation.
--------------------------------------------------------------------------- */
.intro-overlay {
position: fixed;
inset: 0;
z-index: 2000;
display: grid;
place-items: center; /* dead-centre the SVG in the viewport */
animation: intro-fade-out 600ms ease 3s forwards;
}
.intro-backdrop {
position: absolute;
inset: 0;
background: var(--bg);
}
.intro-svg {
position: relative; /* sits above .intro-backdrop in the stacking order */
display: block;
width: min(70vw, 900px);
max-height: 70vh;
height: auto;
object-fit: contain;
}
.intro-running .site-header,
.intro-running main > section,
.intro-running main > footer {
opacity: 0;
}
@media (max-width: 720px) {
.intro-svg {
width: min(86vw, 560px);
}
}
@media (max-width: 480px) {
.intro-svg {
width: 92vw;
}
}
/* ---------------------------------------------------------------------------
7. Animations — keyframes used by the orbs and the intro overlay above.
--------------------------------------------------------------------------- */
@keyframes drift {
0%,
100% {
transform: translate3d(0, 0, 0) scale(1);
}
50% {
transform: translate3d(0, 18px, 0) scale(1.06);
}
}
@keyframes intro-wordmark {
0% {
opacity: 0;
transform: translateY(110%) scale(0.98);
}
100% {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@keyframes intro-fade-out {
to {
opacity: 0;
visibility: hidden;
pointer-events: none;
}
}
/* ---------------------------------------------------------------------------
8. Reduced motion
Respects the user's OS-level "reduce motion" preference by disabling
the orb drift, the intro animation, and any transition/animation
durations across the site.
--------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
.ambient-orb,
.intro-overlay,
.intro-wordmark {
animation: none !important;
}
*,
*::before,
*::after {
transition-duration: 0ms !important;
animation-duration: 0ms !important;
}
}