feat(ui): electric Bat-Computer redesign — cyan→magenta theme
build-and-deploy / build (push) Failing after 11m29s
build-and-deploy / build (push) Failing after 11m29s
Cinematic full-page backdrop: per-theme Bat-Computer board image, scroll-panned (S→E→SE→NE) via CSS scroll-driven animation behind a legibility scrim — replaces the grid/aura motif. - Accent retuned royal-blue → the board's cyan→magenta; headline runs a cyan→magenta electric sweep; gradient primary CTA + scroll-progress line. - Display face: self-hosted Chakra Petch (OFL) on hero + section titles. - Skill chips reworked as circuit-node chips (glowing via + gradient hover outline); frosted-glass cards with a cyan→magenta hover hairline; section eyebrows get a gradient tick. - Remove unused BackgroundGrid component + grid assets. All CSS-only / zero external requests / no inline JS — strict CSP and A+ security headers preserved.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 282 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 284 KiB |
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2018 The Chakra Petch Project Authors (https://github.com/m4rc1e/Chakra-Petch.git)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,67 +0,0 @@
|
|||||||
---
|
|
||||||
// Cheap, CSS-only topology motif: a faint grid + slow-drifting accent glows.
|
|
||||||
// No canvas, no WebGL, no JS. Fully disabled under prefers-reduced-motion.
|
|
||||||
---
|
|
||||||
|
|
||||||
<div class="bg" aria-hidden="true">
|
|
||||||
<div class="bg__grid"></div>
|
|
||||||
<div class="bg__glow bg__glow--a"></div>
|
|
||||||
<div class="bg__glow bg__glow--b"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.bg {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
z-index: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.bg__grid {
|
|
||||||
position: absolute;
|
|
||||||
inset: -2px;
|
|
||||||
background-image:
|
|
||||||
linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
|
|
||||||
linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
|
|
||||||
background-size: 46px 46px;
|
|
||||||
/* Fade the grid out toward the edges so it reads as a motif, not a table. */
|
|
||||||
mask-image: radial-gradient(120% 90% at 50% 0%, #000 35%, transparent 78%);
|
|
||||||
-webkit-mask-image: radial-gradient(120% 90% at 50% 0%, #000 35%, transparent 78%);
|
|
||||||
}
|
|
||||||
.bg__glow {
|
|
||||||
position: absolute;
|
|
||||||
width: 46rem;
|
|
||||||
height: 46rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
filter: blur(60px);
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
.bg__glow--a {
|
|
||||||
top: -22rem;
|
|
||||||
left: -10rem;
|
|
||||||
background: radial-gradient(circle, var(--accent-glow), transparent 62%);
|
|
||||||
animation: drift-a 26s var(--ease) infinite alternate;
|
|
||||||
}
|
|
||||||
.bg__glow--b {
|
|
||||||
top: -16rem;
|
|
||||||
right: -14rem;
|
|
||||||
background: radial-gradient(circle, var(--accent-glow), transparent 65%);
|
|
||||||
opacity: 0.35;
|
|
||||||
animation: drift-b 32s var(--ease) infinite alternate;
|
|
||||||
}
|
|
||||||
@keyframes drift-a {
|
|
||||||
to {
|
|
||||||
transform: translate(6rem, 4rem) scale(1.12);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes drift-b {
|
|
||||||
to {
|
|
||||||
transform: translate(-5rem, 3rem) scale(1.08);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
.bg__glow {
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
---
|
---
|
||||||
import BackgroundGrid from "./BackgroundGrid.astro";
|
|
||||||
import { site } from "../data/site";
|
import { site } from "../data/site";
|
||||||
import { cvAvailable } from "../lib/assets";
|
import { cvAvailable } from "../lib/assets";
|
||||||
---
|
---
|
||||||
|
|
||||||
<section class="hero">
|
<section class="hero">
|
||||||
<BackgroundGrid />
|
|
||||||
<div class="container hero__inner">
|
<div class="container hero__inner">
|
||||||
<p class="eyebrow hero__eyebrow">{site.role}</p>
|
<p class="eyebrow hero__eyebrow">{site.role}</p>
|
||||||
|
|
||||||
@@ -53,16 +51,32 @@ import { cvAvailable } from "../lib/assets";
|
|||||||
margin-bottom: var(--space-4);
|
margin-bottom: var(--space-4);
|
||||||
}
|
}
|
||||||
.hero__title {
|
.hero__title {
|
||||||
|
font-family: var(--font-display);
|
||||||
font-size: var(--step-5);
|
font-size: var(--step-5);
|
||||||
line-height: 1.12;
|
line-height: 1.12;
|
||||||
letter-spacing: -0.03em;
|
/* Chakra Petch is geometric/wide — looser tracking than Inter's -0.03em. */
|
||||||
|
letter-spacing: -0.005em;
|
||||||
/* Extend the paint box below the baseline so background-clip:text doesn't
|
/* Extend the paint box below the baseline so background-clip:text doesn't
|
||||||
crop glyph descenders (the "g" in Wright). */
|
crop glyph descenders (the "g" in Wright). */
|
||||||
padding-bottom: 0.14em;
|
padding-bottom: 0.14em;
|
||||||
background: linear-gradient(180deg, var(--text), color-mix(in srgb, var(--text) 62%, var(--accent)));
|
/* Electric kinetic fill: light text with a cyan→magenta band — the same
|
||||||
|
sweep as the Bat-Computer board — gliding across once on load (heroSheen)
|
||||||
|
over an electric halo, tying the headline into the backdrop. */
|
||||||
|
background: linear-gradient(
|
||||||
|
100deg,
|
||||||
|
var(--text) 0%,
|
||||||
|
var(--text) 34%,
|
||||||
|
var(--accent) 46%,
|
||||||
|
var(--accent-2) 56%,
|
||||||
|
var(--text) 66%,
|
||||||
|
var(--text) 100%
|
||||||
|
);
|
||||||
|
background-size: 230% 100%;
|
||||||
|
background-position: 130% 0;
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
filter: drop-shadow(0 0 26px var(--accent-glow));
|
||||||
}
|
}
|
||||||
.hero__positioning {
|
.hero__positioning {
|
||||||
margin-top: var(--space-5);
|
margin-top: var(--space-5);
|
||||||
@@ -103,8 +117,11 @@ import { cvAvailable } from "../lib/assets";
|
|||||||
.hero__cta {
|
.hero__cta {
|
||||||
animation: heroIn 0.7s var(--ease) both;
|
animation: heroIn 0.7s var(--ease) both;
|
||||||
}
|
}
|
||||||
|
/* Entrance + a one-shot electric sheen sweeping across the name. */
|
||||||
.hero__title {
|
.hero__title {
|
||||||
animation-delay: 0.06s;
|
animation:
|
||||||
|
heroIn 0.7s var(--ease) 0.06s both,
|
||||||
|
heroSheen 1.6s var(--ease) 0.7s both;
|
||||||
}
|
}
|
||||||
.hero__positioning {
|
.hero__positioning {
|
||||||
animation-delay: 0.14s;
|
animation-delay: 0.14s;
|
||||||
@@ -126,4 +143,13 @@ import { cvAvailable } from "../lib/assets";
|
|||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* A bright royal band sweeps left→right across the glyphs, then rests. */
|
||||||
|
@keyframes heroSheen {
|
||||||
|
from {
|
||||||
|
background-position: 130% 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-position: 0% 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -25,11 +25,27 @@ const { id, eyebrow, title, index } = Astro.props;
|
|||||||
.section__head {
|
.section__head {
|
||||||
margin-bottom: var(--space-6);
|
margin-bottom: var(--space-6);
|
||||||
}
|
}
|
||||||
|
/* A short cyan→magenta tick leads each section eyebrow — board palette. */
|
||||||
|
.section__head .eyebrow {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6rem;
|
||||||
|
}
|
||||||
|
.section__head .eyebrow::before {
|
||||||
|
content: "";
|
||||||
|
width: 1.7rem;
|
||||||
|
height: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: linear-gradient(90deg, var(--accent), var(--accent-2));
|
||||||
|
box-shadow: 0 0 8px var(--accent-glow);
|
||||||
|
}
|
||||||
.section__index {
|
.section__index {
|
||||||
color: var(--text-faint);
|
color: var(--text-faint);
|
||||||
margin-right: 0.6rem;
|
margin-right: 0.6rem;
|
||||||
}
|
}
|
||||||
.section__title {
|
.section__title {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
letter-spacing: -0.01em;
|
||||||
margin-top: var(--space-3);
|
margin-top: var(--space-3);
|
||||||
font-size: var(--step-3);
|
font-size: var(--step-3);
|
||||||
max-width: 22ch;
|
max-width: 22ch;
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ const { group } = Astro.props;
|
|||||||
<h3 class="skill__title">{group.title}</h3>
|
<h3 class="skill__title">{group.title}</h3>
|
||||||
<p class="skill__blurb">{group.blurb}</p>
|
<p class="skill__blurb">{group.blurb}</p>
|
||||||
<ul class="skill__items">
|
<ul class="skill__items">
|
||||||
{group.items.map((item) => <li class="tag">{item}</li>)}
|
{group.items.map((item) => (
|
||||||
|
<li class="chip"><span class="chip__node" aria-hidden="true"></span>{item}</li>
|
||||||
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
@@ -40,6 +42,53 @@ const { group } = Astro.props;
|
|||||||
margin: var(--space-2) 0 0;
|
margin: var(--space-2) 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Circuit-node chips — a glowing cyan→magenta node + mono label, wired to the
|
||||||
|
board palette. Gradient border via padding-box/border-box layering so the
|
||||||
|
radius survives. Lights to a full gradient outline + glow on hover. */
|
||||||
|
.chip {
|
||||||
|
--chip-grad: linear-gradient(100deg, var(--accent), var(--accent-2));
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
gap: 0.45rem;
|
gap: 0.45rem;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
color: var(--text-dim);
|
||||||
|
padding: 0.3rem 0.62rem 0.3rem 0.55rem;
|
||||||
|
border-radius: 7px;
|
||||||
|
border: 1px solid var(--accent-line);
|
||||||
|
background: color-mix(in srgb, var(--surface-2) 88%, var(--accent) 12%);
|
||||||
|
transition: color 0.2s var(--ease), transform 0.2s var(--ease),
|
||||||
|
border-color 0.2s var(--ease), box-shadow 0.2s var(--ease),
|
||||||
|
background 0.2s var(--ease);
|
||||||
|
}
|
||||||
|
/* The node: a small cyan→magenta square that glows, like a lit via/pad. */
|
||||||
|
.chip__node {
|
||||||
|
flex: none;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: var(--chip-grad);
|
||||||
|
box-shadow: 0 0 7px var(--accent-glow);
|
||||||
|
}
|
||||||
|
.chip:hover {
|
||||||
|
color: var(--text);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
border-color: transparent;
|
||||||
|
/* dark fill (padding-box) inside a live gradient border (border-box) */
|
||||||
|
background: linear-gradient(var(--surface-2), var(--surface-2)) padding-box,
|
||||||
|
var(--chip-grad) border-box;
|
||||||
|
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.32), 0 0 16px var(--accent-glow);
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.chip {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
.chip:hover {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -56,6 +56,14 @@ const ogImage = new URL(site.ogImage, site.url).href;
|
|||||||
<script is:inline src="/site.js"></script>
|
<script is:inline src="/site.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!-- PRO scroll UI (CSS-only, CSP-safe): a top progress line + a page-wide
|
||||||
|
flowing aurora that drifts continuously and parallaxes on scroll. -->
|
||||||
|
<div class="scroll-progress" aria-hidden="true"></div>
|
||||||
|
<div class="site-bg" aria-hidden="true">
|
||||||
|
<img class="site-bg__img site-bg__img--dark" src="/batcore-dark.webp" alt="" decoding="async" />
|
||||||
|
<img class="site-bg__img site-bg__img--light" src="/batcore-light.webp" alt="" decoding="async" />
|
||||||
|
<div class="site-bg__scrim"></div>
|
||||||
|
</div>
|
||||||
<a class="skip-link" href="#main">Skip to content</a>
|
<a class="skip-link" href="#main">Skip to content</a>
|
||||||
<Nav />
|
<Nav />
|
||||||
<main id="main">
|
<main id="main">
|
||||||
|
|||||||
+181
-4
@@ -1,6 +1,24 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@import "./tokens.css";
|
@import "./tokens.css";
|
||||||
|
|
||||||
|
/* ---- Display face: Chakra Petch (self-hosted woff2, OFL — see public/fonts) -
|
||||||
|
Latin subset, ~10KB/weight. font-display:swap so text paints instantly in the
|
||||||
|
sans fallback and swaps when the face loads (zero layout-shift on the headline). */
|
||||||
|
@font-face {
|
||||||
|
font-family: "Chakra Petch";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
font-display: swap;
|
||||||
|
src: url("/fonts/chakra-petch-600.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Chakra Petch";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
font-display: swap;
|
||||||
|
src: url("/fonts/chakra-petch-700.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- Base ---------------------------------------------------------------- */
|
/* ---- Base ---------------------------------------------------------------- */
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -120,25 +138,65 @@ svg {
|
|||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
.btn--primary {
|
.btn--primary {
|
||||||
background: var(--accent);
|
background: linear-gradient(100deg, var(--accent), var(--accent-2));
|
||||||
color: var(--accent-ink);
|
color: var(--accent-ink);
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
.btn--primary:hover {
|
.btn--primary:hover {
|
||||||
background: var(--accent-strong);
|
filter: brightness(1.08);
|
||||||
|
box-shadow: 0 8px 22px var(--accent-glow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- Cards / tags -------------------------------------------------------- */
|
/* ---- Cards / tags -------------------------------------------------------- */
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
background: var(--surface);
|
position: relative;
|
||||||
|
/* Frosted glass over the Bat-Computer board — semi-opaque surface + blur so a
|
||||||
|
hint of the circuitry diffuses through without hurting legibility. */
|
||||||
|
background: color-mix(in srgb, var(--surface) 86%, transparent);
|
||||||
|
backdrop-filter: blur(14px) saturate(1.1);
|
||||||
|
-webkit-backdrop-filter: blur(14px) saturate(1.1);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
transition: border-color 0.25s var(--ease), transform 0.25s var(--ease);
|
transition: border-color 0.25s var(--ease), transform 0.25s var(--ease),
|
||||||
|
box-shadow 0.25s var(--ease);
|
||||||
|
}
|
||||||
|
/* A cyan→magenta hairline that ignites along the top edge on hover. Inset from
|
||||||
|
the corners so it stays inside the border radius (no clip needed). */
|
||||||
|
.card::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 16px;
|
||||||
|
right: 16px;
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent,
|
||||||
|
var(--accent),
|
||||||
|
var(--accent-2),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.25s var(--ease);
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.card:hover {
|
.card:hover {
|
||||||
border-color: var(--accent-line);
|
border-color: var(--accent-line);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--shadow), 0 0 22px var(--accent-glow);
|
||||||
|
}
|
||||||
|
.card:hover::before {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.card {
|
||||||
|
transition: border-color 0.25s var(--ease);
|
||||||
|
}
|
||||||
|
.card:hover {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag {
|
.tag {
|
||||||
@@ -269,3 +327,122 @@ svg {
|
|||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- PRO scroll UI — flowing aurora + scroll progress (CSS-only, CSP-safe) -
|
||||||
|
Native scroll-driven animations (animation-timeline). Degrades to a gentle
|
||||||
|
continuous drift where unsupported; fully disabled under reduced-motion. */
|
||||||
|
|
||||||
|
/* A thin royal line at the very top that fills as the page scrolls. */
|
||||||
|
.scroll-progress {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0 0 auto 0;
|
||||||
|
height: 2px;
|
||||||
|
z-index: 200;
|
||||||
|
background: linear-gradient(90deg, var(--accent), var(--accent-2));
|
||||||
|
box-shadow: 0 0 14px var(--accent-glow);
|
||||||
|
transform: scaleX(0);
|
||||||
|
transform-origin: 0 50%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
@supports (animation-timeline: scroll()) {
|
||||||
|
.scroll-progress {
|
||||||
|
animation: progressGrow linear both;
|
||||||
|
animation-timeline: scroll(root block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes progressGrow {
|
||||||
|
to {
|
||||||
|
transform: scaleX(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Cinematic backing: the Bat-Computer board, panned by scroll -----------
|
||||||
|
A fixed full-screen image (dark/light per theme) that pans S → E → SE → NE as
|
||||||
|
the page scrolls. A scrim keeps text legible (darker on the left for the hero
|
||||||
|
headline). GPU transform only; static + legible under reduced-motion. */
|
||||||
|
.site-bg {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: -2;
|
||||||
|
overflow: hidden;
|
||||||
|
background: var(--bg);
|
||||||
|
}
|
||||||
|
.site-bg__img {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 168%;
|
||||||
|
height: 168%;
|
||||||
|
object-fit: cover;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
.site-bg__img--light {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
[data-theme="light"] .site-bg__img--dark {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
[data-theme="light"] .site-bg__img--light {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.site-bg__scrim {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background:
|
||||||
|
linear-gradient(
|
||||||
|
90deg,
|
||||||
|
rgba(9, 12, 20, 0.85) 0%,
|
||||||
|
rgba(9, 12, 20, 0.52) 44%,
|
||||||
|
rgba(9, 12, 20, 0.34) 100%
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(9, 12, 20, 0.18) 0%,
|
||||||
|
rgba(9, 12, 20, 0.5) 58%,
|
||||||
|
rgba(9, 12, 20, 0.82) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
[data-theme="light"] .site-bg__scrim {
|
||||||
|
background:
|
||||||
|
linear-gradient(
|
||||||
|
90deg,
|
||||||
|
rgba(246, 248, 251, 0.86) 0%,
|
||||||
|
rgba(246, 248, 251, 0.56) 44%,
|
||||||
|
rgba(246, 248, 251, 0.4) 100%
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(246, 248, 251, 0.22) 0%,
|
||||||
|
rgba(246, 248, 251, 0.54) 58%,
|
||||||
|
rgba(246, 248, 251, 0.82) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@supports (animation-timeline: scroll()) {
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.site-bg__img {
|
||||||
|
animation: bgPan linear both;
|
||||||
|
animation-timeline: scroll(root block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes bgPan {
|
||||||
|
0% {
|
||||||
|
transform: translate(-50%, -38%);
|
||||||
|
}
|
||||||
|
35% {
|
||||||
|
transform: translate(-50%, -62%);
|
||||||
|
}
|
||||||
|
68% {
|
||||||
|
transform: translate(-62%, -62%);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(-62%, -38%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.scroll-progress {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+21
-14
@@ -17,22 +17,26 @@
|
|||||||
--text-dim: #9aa7b8;
|
--text-dim: #9aa7b8;
|
||||||
--text-faint: #61708a;
|
--text-faint: #61708a;
|
||||||
|
|
||||||
/* Accent — single restrained teal */
|
/* Accent — electric cyan→magenta, merged with the Bat-Computer board */
|
||||||
--accent: #5eead4;
|
--accent: #3fbaf5; /* cyan-blue (the board's left side) */
|
||||||
--accent-strong: #2dd4bf;
|
--accent-2: #e879f9; /* magenta (the board's right side) */
|
||||||
--accent-ink: #042f2a; /* text on an accent fill */
|
--accent-strong: #1f9fe0;
|
||||||
--accent-dim: rgba(94, 234, 212, 0.12);
|
--accent-ink: #04161f; /* text on an accent fill */
|
||||||
--accent-line: rgba(94, 234, 212, 0.28);
|
--accent-dim: rgba(63, 186, 245, 0.12);
|
||||||
--accent-glow: rgba(45, 212, 191, 0.22);
|
--accent-line: rgba(63, 186, 245, 0.3);
|
||||||
|
--accent-glow: rgba(63, 186, 245, 0.32);
|
||||||
|
|
||||||
/* Grid / topology motif */
|
/* Grid / topology motif */
|
||||||
--grid-line: rgba(148, 163, 184, 0.06);
|
--grid-line: rgba(148, 163, 184, 0.06);
|
||||||
|
|
||||||
/* Fonts — system stacks only (zero external requests). */
|
/* Fonts — system stacks (zero external requests) + one self-hosted display face. */
|
||||||
--font-sans: "Inter var", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
|
--font-sans: "Inter var", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
|
||||||
Roboto, Helvetica, Arial, sans-serif;
|
Roboto, Helvetica, Arial, sans-serif;
|
||||||
--font-mono: ui-monospace, "JetBrains Mono", "Cascadia Code", "SF Mono",
|
--font-mono: ui-monospace, "JetBrains Mono", "Cascadia Code", "SF Mono",
|
||||||
Menlo, Consolas, "Liberation Mono", monospace;
|
Menlo, Consolas, "Liberation Mono", monospace;
|
||||||
|
/* Display face — Chakra Petch (self-hosted woff2, OFL). Used ONLY on the hero
|
||||||
|
name + section titles; body stays in --font-sans for readability. */
|
||||||
|
--font-display: "Chakra Petch", var(--font-sans);
|
||||||
|
|
||||||
/* Fluid type scale */
|
/* Fluid type scale */
|
||||||
--step--1: clamp(0.8rem, 0.76rem + 0.2vw, 0.9rem);
|
--step--1: clamp(0.8rem, 0.76rem + 0.2vw, 0.9rem);
|
||||||
@@ -77,12 +81,15 @@
|
|||||||
--text-dim: #475467;
|
--text-dim: #475467;
|
||||||
--text-faint: #6b7689;
|
--text-faint: #6b7689;
|
||||||
|
|
||||||
--accent: #0d9488;
|
/* Accent — same electric cyan→magenta as dark, dropped in value for contrast
|
||||||
--accent-strong: #0f766e;
|
on the light sandstone board. */
|
||||||
--accent-ink: #ecfdf5;
|
--accent: #0c8fce; /* deeper cyan reads on white */
|
||||||
--accent-dim: rgba(13, 148, 136, 0.1);
|
--accent-2: #c026d3; /* magenta partner */
|
||||||
--accent-line: rgba(13, 148, 136, 0.3);
|
--accent-strong: #0a72a6;
|
||||||
--accent-glow: rgba(13, 148, 136, 0.16);
|
--accent-ink: #f2fbff;
|
||||||
|
--accent-dim: rgba(12, 143, 206, 0.1);
|
||||||
|
--accent-line: rgba(12, 143, 206, 0.32);
|
||||||
|
--accent-glow: rgba(192, 38, 211, 0.16);
|
||||||
|
|
||||||
--grid-line: rgba(15, 23, 42, 0.05);
|
--grid-line: rgba(15, 23, 42, 0.05);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user