mirror of
https://github.com/Such-Software/such.software.git
synced 2026-10-17 05:32:05 +02:00
- Voice unified on the title-tag register: the homepage h1 now says what we sell (Custom E-commerce, Apps & Crypto Tools); 'Precision engineering for everyone' is demoted to the supporting line. The structured-data and manifest descriptions now match the OG description instead of carrying their own registers. - The off-palette cyan/blue gradients are gone: .hero-title and the new .brand-gradient-text use the four-colour system (light palette on light, dark palette on dark, per the pack). Splash cover text, services and portfolio headings, the hero aura, and button shadows all follow. - The splash now dismisses once 40% scrolled past instead of requiring the whole screen to leave the viewport (it was already once-per-session and reduced-motion-skipping). - Portfolio: heading 'Portfolio', subtitle 'Products & projects', meta title to match; grid grows to three columns on xl in a max-w-6xl container. - anim3_matrix slimmed: single-layer glow, unfiltered crackle and orbs, and the border cycles stroke colour instead of animating filter:hue-rotate -- the filter animation forced a full filter re-render per frame and pegged a core on the page hosting it.
318 lines
9.3 KiB
CSS
318 lines
9.3 KiB
CSS
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
@layer base {
|
|
:root {
|
|
--background: 0 0% 100%;
|
|
--foreground: 222.2 84% 4.9%;
|
|
|
|
--card: 0 0% 100%;
|
|
--card-foreground: 222.2 84% 4.9%;
|
|
|
|
--popover: 0 0% 100%;
|
|
--popover-foreground: 222.2 84% 4.9%;
|
|
|
|
--primary: 222.2 47.4% 11.2%;
|
|
--primary-foreground: 210 40% 98%;
|
|
|
|
--secondary: 210 40% 96.1%;
|
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
|
|
--muted: 210 40% 96.1%;
|
|
--muted-foreground: 215.4 16.3% 46.9%;
|
|
|
|
--accent: 210 40% 96.1%;
|
|
--accent-foreground: 222.2 47.4% 11.2%;
|
|
|
|
--destructive: 0 84.2% 60.2%;
|
|
--destructive-foreground: 210 40% 98%;
|
|
|
|
--border: 214.3 31.8% 91.4%;
|
|
--input: 214.3 31.8% 91.4%;
|
|
--ring: 222.2 84% 4.9%;
|
|
|
|
--radius: 0.5rem;
|
|
}
|
|
|
|
.dark {
|
|
--background: 222.2 84% 4.9%;
|
|
--foreground: 210 40% 98%;
|
|
|
|
--card: 222.2 84% 4.9%;
|
|
--card-foreground: 210 40% 98%;
|
|
|
|
--popover: 222.2 84% 4.9%;
|
|
--popover-foreground: 210 40% 98%;
|
|
|
|
--primary: 210 40% 98%;
|
|
--primary-foreground: 222.2 47.4% 11.2%;
|
|
|
|
--secondary: 217.2 32.6% 17.5%;
|
|
--secondary-foreground: 210 40% 98%;
|
|
|
|
--muted: 217.2 32.6% 17.5%;
|
|
--muted-foreground: 215 20.2% 65.1%;
|
|
|
|
--accent: 217.2 32.6% 17.5%;
|
|
--accent-foreground: 210 40% 98%;
|
|
|
|
--destructive: 0 62.8% 30.6%;
|
|
--destructive-foreground: 210 40% 98%;
|
|
|
|
--border: 217.2 32.6% 17.5%;
|
|
--input: 217.2 32.6% 17.5%;
|
|
--ring: 212.7 26.8% 83.9%;
|
|
}
|
|
}
|
|
|
|
@layer base {
|
|
* {
|
|
@apply border-border;
|
|
}
|
|
body {
|
|
@apply bg-background text-foreground;
|
|
}
|
|
}
|
|
@layer components {
|
|
/* High-contrast content masking for accessibility and streamer protection */
|
|
.mask-backdrop {
|
|
background-color: hsl(var(--card) / 0.98);
|
|
backdrop-filter: blur(64px);
|
|
-webkit-backdrop-filter: blur(64px);
|
|
border-width: 2px;
|
|
border-color: hsl(var(--border) / 0.5);
|
|
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
|
position: relative;
|
|
overflow: hidden;
|
|
transition: transform 300ms cubic-bezier(0.16, 1, 0.3, 1),
|
|
box-shadow 300ms cubic-bezier(0.16, 1, 0.3, 1),
|
|
border-color 300ms ease;
|
|
}
|
|
|
|
.section-container {
|
|
@apply mask-backdrop rounded-[2.5rem] p-12 md:p-20 text-card-foreground;
|
|
}
|
|
|
|
.glass-card {
|
|
@apply mask-backdrop rounded-[2rem] p-10 text-card-foreground;
|
|
}
|
|
|
|
.glass-card:hover {
|
|
border-color: hsl(var(--primary) / 0.3);
|
|
}
|
|
|
|
/* Bento grid entrance animation */
|
|
@keyframes bento-enter {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(16px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.bento-item {
|
|
animation: bento-enter 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
}
|
|
|
|
/* Quiet bento: at rest the card chrome (opaque bg, 64px frost, border, shadow) is
|
|
nearly invisible so only the title + the 3D render/image float on the page; the
|
|
glass lights up on hover / focus / tap. Title + image keep their own visibility.
|
|
Higher specificity than .mask-backdrop, so it wins at rest without !important. */
|
|
.bento-item .glass-card {
|
|
background-color: transparent;
|
|
backdrop-filter: none;
|
|
-webkit-backdrop-filter: none;
|
|
border-color: transparent;
|
|
box-shadow: none;
|
|
transition: background-color 0.3s ease, backdrop-filter 0.3s ease,
|
|
border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease;
|
|
}
|
|
.bento-item:hover .glass-card,
|
|
.bento-item:focus-within .glass-card {
|
|
backdrop-filter: blur(64px);
|
|
-webkit-backdrop-filter: blur(64px);
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 32px 64px -16px rgb(0 0 0 / 0.3);
|
|
}
|
|
|
|
/* Focus-visible ring for keyboard navigation */
|
|
.bento-item:focus-visible {
|
|
outline: 2px solid hsl(var(--ring));
|
|
outline-offset: 4px;
|
|
border-radius: 2.5rem;
|
|
}
|
|
|
|
/* Respect reduced motion preferences */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.bento-item {
|
|
animation: none;
|
|
}
|
|
.bento-item:hover .glass-card {
|
|
transform: none;
|
|
}
|
|
.glass-card {
|
|
transition: border-color 300ms;
|
|
}
|
|
.glass-card .object-contain,
|
|
.glass-card .object-cover {
|
|
transition: none !important;
|
|
}
|
|
}
|
|
|
|
/* Typography customization for blog posts */
|
|
.prose {
|
|
--tw-prose-body: hsl(var(--foreground));
|
|
--tw-prose-headings: hsl(var(--foreground));
|
|
--tw-prose-lead: hsl(var(--muted-foreground));
|
|
--tw-prose-links: hsl(var(--primary));
|
|
--tw-prose-bold: hsl(var(--foreground));
|
|
--tw-prose-counters: hsl(var(--muted-foreground));
|
|
--tw-prose-bullets: hsl(var(--muted-foreground));
|
|
--tw-prose-hr: hsl(var(--border));
|
|
--tw-prose-quotes: hsl(var(--foreground));
|
|
--tw-prose-quote-borders: hsl(var(--border));
|
|
--tw-prose-captions: hsl(var(--muted-foreground));
|
|
--tw-prose-code: hsl(var(--foreground));
|
|
--tw-prose-pre-code: hsl(var(--foreground));
|
|
--tw-prose-pre-bg: hsl(var(--muted));
|
|
--tw-prose-th-borders: hsl(var(--border));
|
|
--tw-prose-td-borders: hsl(var(--border));
|
|
}
|
|
|
|
.prose h2 {
|
|
@apply text-xl font-semibold mt-10 mb-4 pb-2 border-b border-border;
|
|
}
|
|
|
|
.prose h3 {
|
|
@apply text-lg font-medium mt-6 mb-3;
|
|
}
|
|
|
|
.prose p {
|
|
@apply leading-relaxed mb-4;
|
|
}
|
|
|
|
.prose ul {
|
|
@apply my-4 ml-4 space-y-2;
|
|
}
|
|
|
|
.prose li {
|
|
@apply leading-relaxed;
|
|
}
|
|
|
|
.prose a {
|
|
@apply text-emerald-600 dark:text-emerald-400 underline underline-offset-2 hover:text-emerald-700 dark:hover:text-emerald-300 transition-colors;
|
|
}
|
|
|
|
.prose strong {
|
|
@apply font-semibold;
|
|
}
|
|
|
|
.prose hr {
|
|
@apply my-8 border-border;
|
|
}
|
|
|
|
.prose table {
|
|
@apply w-full my-6 text-sm;
|
|
}
|
|
|
|
.prose thead th {
|
|
@apply text-left font-semibold p-3 bg-muted/50 border-b border-border;
|
|
}
|
|
|
|
.prose tbody td {
|
|
@apply p-3 border-b border-border;
|
|
}
|
|
|
|
.prose tbody tr:hover {
|
|
@apply bg-muted/30;
|
|
}
|
|
}
|
|
|
|
/* Respect users who prefer reduced motion */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
transition-duration: 0.01ms !important;
|
|
scroll-behavior: auto !important;
|
|
}
|
|
}
|
|
|
|
/* Splash logo zoom on click-to-enter (CSS, so the logo needs no framer-motion
|
|
wrapper and stays a clean LCP candidate). */
|
|
@keyframes splash-zoom { 0% { transform: scale(1); } 50% { transform: scale(1.06); } 100% { transform: scale(1.14); } }
|
|
.splash-zoom { animation: splash-zoom 0.8s ease-in-out forwards; }
|
|
|
|
/* Click-to-enter Cherenkov wash (was framer-motion; now CSS so the splash ships no
|
|
JS animation library). */
|
|
@keyframes splash-wash { 0% { opacity: 0; } 50% { opacity: 0.9; } 100% { opacity: 0; } }
|
|
.splash-wash { animation: splash-wash 0.8s ease-in-out forwards; }
|
|
|
|
/* Tiny terminal inside the nebula monitor: type "such" once, backspace, then a blinking
|
|
caret on the left. width via steps() is the typewriter; border-right is the caret. */
|
|
.nebula-term {
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
font-size: 9px;
|
|
line-height: 1;
|
|
letter-spacing: 0.5px;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
width: 0;
|
|
border-right: 1.5px solid currentColor;
|
|
/* type "such", hold, backspace (nebula-type, once); blink a finite number of times
|
|
(nebula-caret); then fade the whole thing out so it stops being distracting. */
|
|
/* blink ~4 times, type "such", backspace, blink ~4 more, then fade away. */
|
|
animation:
|
|
nebula-type 2.2s steps(4, end) 3.2s forwards,
|
|
nebula-caret 0.8s steps(1, end) 11,
|
|
nebula-term-out 0.6s ease-in 8.4s forwards;
|
|
}
|
|
@keyframes nebula-type {
|
|
0% { width: 0; }
|
|
36% { width: 4ch; }
|
|
64% { width: 4ch; }
|
|
90% { width: 0; }
|
|
100% { width: 0; }
|
|
}
|
|
@keyframes nebula-caret { 0%, 50% { border-color: currentColor; } 50.01%, 100% { border-color: transparent; } }
|
|
@keyframes nebula-term-out { to { opacity: 0; } }
|
|
|
|
/* Hero title: an animated gradient sheen. LCP-safe — the text paints immediately with the
|
|
gradient; only the gradient POSITION animates, which never delays the largest paint. The
|
|
global reduced-motion rule freezes it to the base gradient. */
|
|
/* The brand's four-colour system (S green, U magenta, C blue, H teal), one per glyph.
|
|
Light theme uses the light palette; .dark swaps in the dark palette, which is the
|
|
same hues lifted for contrast on near-black -- from packs/such-software/pack.json. */
|
|
.hero-title {
|
|
background-image: linear-gradient(110deg, #1a5c38 0%, #b83670 30%, #176a92 55%, #12857e 80%, #1a5c38 100%);
|
|
background-size: 220% auto;
|
|
-webkit-background-clip: text;
|
|
background-clip: text;
|
|
color: transparent;
|
|
animation: hero-sheen 9s ease-in-out infinite;
|
|
}
|
|
.dark .hero-title {
|
|
background-image: linear-gradient(110deg, #35925c 0%, #e8689e 30%, #4aade0 55%, #3ad4c6 80%, #35925c 100%);
|
|
}
|
|
.brand-gradient-text {
|
|
background-image: linear-gradient(90deg, #1a5c38, #b83670, #176a92, #12857e);
|
|
-webkit-background-clip: text;
|
|
background-clip: text;
|
|
color: transparent;
|
|
}
|
|
.dark .brand-gradient-text {
|
|
background-image: linear-gradient(90deg, #35925c, #e8689e, #4aade0, #3ad4c6);
|
|
}
|
|
@keyframes hero-sheen {
|
|
0%, 100% { background-position: 0% center; }
|
|
50% { background-position: 100% center; }
|
|
}
|
|
/* Soft aura behind the hero title (decorative). Gentle breathing scale/opacity. */
|
|
@keyframes hero-aura { 0%, 100% { opacity: 0.55; transform: translateX(-50%) scale(1); } 50% { opacity: 0.8; transform: translateX(-50%) scale(1.08); } }
|
|
.hero-aura { animation: hero-aura 7s ease-in-out infinite; } |