Migrate live changes from facere-website and add deploy configs

Bring in the newer app.jsx/styles.css/facere.html that were edited
directly on the deployed copy, rename Facere.html -> facere.html to
match the nginx index, and check in the docker-compose + nginx.conf
that drives the container.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 01:41:50 +08:00
parent 75aad16a26
commit 8ea175fa78
5 changed files with 182 additions and 105 deletions

View File

@@ -41,7 +41,14 @@ a { color: inherit; text-decoration: none; }
background: var(--bg);
}
.scene-stack { position: absolute; inset: 0; }
.scene-slot { position: absolute; inset: 0; }
.scene-slot {
position: absolute;
inset: 0;
will-change: opacity;
transform: translateZ(0);
backface-visibility: hidden;
contain: layout paint;
}
.scene {
position: absolute;
@@ -58,14 +65,29 @@ a { color: inherit; text-decoration: none; }
overflow: hidden;
transform-origin: 65% 50%;
will-change: transform;
transform: translateZ(0);
}
.scene-product .bg-wrap { transform-origin: 50% 60%; }
.scene-install .bg-wrap { transform-origin: 78% 50%; }
/* Image-aspect frame: replicates `background-size: cover` geometry as an
actual box, so any %-positioned overlay (smoke, sparks, chip pulses…)
stays locked to the image content regardless of viewport aspect.
Uses vw/vh because the bg-wrap is always 100vw × 100vh of the stage. */
.image-frame {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) translateZ(0);
aspect-ratio: 1672 / 941;
width: max(100vw, calc(100vh * 1672 / 941));
will-change: transform;
}
.bg-image {
position: absolute;
inset: 0;
background-size: cover;
background-size: 100% 100%;
background-position: center center;
background-repeat: no-repeat;
/* Crisp pixel-art feel without softening the source */
@@ -159,63 +181,63 @@ a { color: inherit; text-decoration: none; }
mix-blend-mode: screen;
opacity: 0;
}
.ghost-r { animation: glitch-r 3.0s steps(1) infinite; }
.ghost-c { animation: glitch-c 3.0s steps(1) infinite; }
.ghost-r { animation: glitch-r 12s steps(1) infinite; }
.ghost-c { animation: glitch-c 12s steps(1) infinite; }
/* Many-band signal breakage. Multiple bursts per cycle, each band offset
independently from the others. Some frames near-fully corrupt. */
@keyframes glitch-r {
0%, 6% { opacity: 0; transform: translate(0, 0); clip-path: none; }
8% { opacity: 0.9; transform: translate(40px, 0); clip-path: inset(5% 0 78% 0); }
9% { opacity: 0.7; transform: translate(-20px, 0); clip-path: inset(15% 0 70% 0); }
8% { opacity: 0.9; transform: translate(8px, 0); clip-path: inset(5% 0 78% 0); }
9% { opacity: 0.7; transform: translate(-4px, 0); clip-path: inset(15% 0 70% 0); }
10% { opacity: 0; }
18% { opacity: 0.85; transform: translate(55px, 0); clip-path: inset(28% 0 58% 0); }
18% { opacity: 0.85; transform: translate(11px, 0); clip-path: inset(28% 0 58% 0); }
19% { opacity: 0; }
24% { opacity: 0.7; transform: translate(-35px, 0); clip-path: inset(48% 0 38% 0); }
25% { opacity: 0.5; transform: translate(15px, 0); clip-path: inset(52% 0 36% 0); }
24% { opacity: 0.7; transform: translate(-7px, 0); clip-path: inset(48% 0 38% 0); }
25% { opacity: 0.5; transform: translate(3px, 0); clip-path: inset(52% 0 36% 0); }
26% { opacity: 0; }
/* small quiet patch */
36% { opacity: 0.65; transform: translate(25px, 0); clip-path: inset(62% 0 24% 0); }
36% { opacity: 0.65; transform: translate(5px, 0); clip-path: inset(62% 0 24% 0); }
37% { opacity: 0; }
44% { opacity: 0.95; transform: translate(-45px, 0); clip-path: inset(72% 0 14% 0); }
45% { opacity: 0.6; transform: translate(20px, 0); clip-path: inset(78% 0 8% 0); }
44% { opacity: 0.95; transform: translate(-9px, 0); clip-path: inset(72% 0 14% 0); }
45% { opacity: 0.6; transform: translate(4px, 0); clip-path: inset(78% 0 8% 0); }
46% { opacity: 0; }
56% { opacity: 0.55; transform: translate(10px, 0); clip-path: inset(18% 0 70% 0); }
56% { opacity: 0.55; transform: translate(2px, 0); clip-path: inset(18% 0 70% 0); }
57% { opacity: 0; }
64% { opacity: 0.9; transform: translate(-50px, 0); clip-path: inset(35% 0 50% 0); }
64% { opacity: 0.9; transform: translate(-10px, 0); clip-path: inset(35% 0 50% 0); }
65% { opacity: 0; }
72% { opacity: 0.7; transform: translate(30px, 0); clip-path: inset(58% 0 30% 0); }
72% { opacity: 0.7; transform: translate(6px, 0); clip-path: inset(58% 0 30% 0); }
73% { opacity: 0; }
/* full corruption flash */
82% { opacity: 0.85; transform: translate(35px, 0); clip-path: none; }
82% { opacity: 0.85; transform: translate(7px, 0); clip-path: none; }
83% { opacity: 0; }
90% { opacity: 0.6; transform: translate(-15px, 0); clip-path: inset(68% 0 22% 0); }
90% { opacity: 0.6; transform: translate(-3px, 0); clip-path: inset(68% 0 22% 0); }
91%, 100% { opacity: 0; transform: translate(0, 0); clip-path: none; }
}
@keyframes glitch-c {
0%, 6% { opacity: 0; transform: translate(0, 0); clip-path: none; }
8% { opacity: 0.85; transform: translate(-40px, 0); clip-path: inset(5% 0 78% 0); }
9% { opacity: 0.65; transform: translate(20px, 0); clip-path: inset(15% 0 70% 0); }
8% { opacity: 0.85; transform: translate(-8px, 0); clip-path: inset(5% 0 78% 0); }
9% { opacity: 0.65; transform: translate(4px, 0); clip-path: inset(15% 0 70% 0); }
10% { opacity: 0; }
18% { opacity: 0.8; transform: translate(-55px, 0); clip-path: inset(28% 0 58% 0); }
18% { opacity: 0.8; transform: translate(-11px, 0); clip-path: inset(28% 0 58% 0); }
19% { opacity: 0; }
24% { opacity: 0.65; transform: translate(35px, 0); clip-path: inset(48% 0 38% 0); }
25% { opacity: 0.45; transform: translate(-15px, 0); clip-path: inset(52% 0 36% 0); }
24% { opacity: 0.65; transform: translate(7px, 0); clip-path: inset(48% 0 38% 0); }
25% { opacity: 0.45; transform: translate(-3px, 0); clip-path: inset(52% 0 36% 0); }
26% { opacity: 0; }
36% { opacity: 0.6; transform: translate(-25px, 0); clip-path: inset(62% 0 24% 0); }
36% { opacity: 0.6; transform: translate(-5px, 0); clip-path: inset(62% 0 24% 0); }
37% { opacity: 0; }
44% { opacity: 0.9; transform: translate(45px, 0); clip-path: inset(72% 0 14% 0); }
45% { opacity: 0.55; transform: translate(-20px, 0); clip-path: inset(78% 0 8% 0); }
44% { opacity: 0.9; transform: translate(9px, 0); clip-path: inset(72% 0 14% 0); }
45% { opacity: 0.55; transform: translate(-4px, 0); clip-path: inset(78% 0 8% 0); }
46% { opacity: 0; }
56% { opacity: 0.5; transform: translate(-10px, 0); clip-path: inset(18% 0 70% 0); }
56% { opacity: 0.5; transform: translate(-2px, 0); clip-path: inset(18% 0 70% 0); }
57% { opacity: 0; }
64% { opacity: 0.85; transform: translate(50px, 0); clip-path: inset(35% 0 50% 0); }
64% { opacity: 0.85; transform: translate(10px, 0); clip-path: inset(35% 0 50% 0); }
65% { opacity: 0; }
72% { opacity: 0.65; transform: translate(-30px, 0); clip-path: inset(58% 0 30% 0); }
72% { opacity: 0.65; transform: translate(-6px, 0); clip-path: inset(58% 0 30% 0); }
73% { opacity: 0; }
82% { opacity: 0.8; transform: translate(-35px, 0); clip-path: none; }
82% { opacity: 0.8; transform: translate(-7px, 0); clip-path: none; }
83% { opacity: 0; }
90% { opacity: 0.55; transform: translate(15px, 0); clip-path: inset(68% 0 22% 0); }
90% { opacity: 0.55; transform: translate(3px, 0); clip-path: inset(68% 0 22% 0); }
91%, 100% { opacity: 0; transform: translate(0, 0); clip-path: none; }
}
@@ -230,7 +252,7 @@ a { color: inherit; text-decoration: none; }
}
.logo-wrap {
position: relative;
animation: logo-jitter 3.0s steps(1) infinite, logo-flicker 2.4s ease-in-out infinite, logo-dropout 7s steps(1) infinite;
animation: logo-jitter 12s steps(1) infinite, logo-flicker 10s ease-in-out infinite, logo-dropout 28s steps(1) infinite;
}
/* Brightness flicker — frequent dips like signal loss */
@keyframes logo-flicker {
@@ -255,28 +277,28 @@ a { color: inherit; text-decoration: none; }
/* Logo body — many independent band shears, frequent bursts. */
@keyframes logo-jitter {
0%, 6%, 100% { transform: translate(0, 0); clip-path: none; }
8% { transform: translate(25px, 0); clip-path: inset(5% 0 78% 0); }
9% { transform: translate(-15px, 0); clip-path: inset(15% 0 70% 0); }
8% { transform: translate(5px, 0); clip-path: inset(5% 0 78% 0); }
9% { transform: translate(-3px, 0); clip-path: inset(15% 0 70% 0); }
10% { transform: translate(0, 0); clip-path: none; }
18% { transform: translate(-30px, 0); clip-path: inset(28% 0 58% 0); }
19% { transform: translate(10px, 0); clip-path: none; }
24% { transform: translate(20px, 0); clip-path: inset(48% 0 38% 0); }
25% { transform: translate(-10px, 0); clip-path: inset(52% 0 36% 0); }
18% { transform: translate(-6px, 0); clip-path: inset(28% 0 58% 0); }
19% { transform: translate(2px, 0); clip-path: none; }
24% { transform: translate(4px, 0); clip-path: inset(48% 0 38% 0); }
25% { transform: translate(-2px, 0); clip-path: inset(52% 0 36% 0); }
26% { transform: translate(0, 0); clip-path: none; }
36% { transform: translate(-15px, 0); clip-path: inset(62% 0 24% 0); }
36% { transform: translate(-3px, 0); clip-path: inset(62% 0 24% 0); }
37% { transform: translate(0, 0); clip-path: none; }
44% { transform: translate(35px, 0); clip-path: inset(72% 0 14% 0); }
45% { transform: translate(-20px, 0); clip-path: inset(78% 0 8% 0); }
44% { transform: translate(7px, 0); clip-path: inset(72% 0 14% 0); }
45% { transform: translate(-4px, 0); clip-path: inset(78% 0 8% 0); }
46% { transform: translate(0, 0); clip-path: none; }
56% { transform: translate(-10px, 0); clip-path: inset(18% 0 70% 0); }
56% { transform: translate(-2px, 0); clip-path: inset(18% 0 70% 0); }
57% { transform: translate(0, 0); clip-path: none; }
64% { transform: translate(40px, 0); clip-path: inset(35% 0 50% 0); }
65% { transform: translate(-15px, 0); clip-path: none; }
72% { transform: translate(-25px, 0); clip-path: inset(58% 0 30% 0); }
73% { transform: translate(10px, 0); clip-path: none; }
82% { transform: translate(-20px, 0) skewX(-1deg); }
64% { transform: translate(8px, 0); clip-path: inset(35% 0 50% 0); }
65% { transform: translate(-3px, 0); clip-path: none; }
72% { transform: translate(-5px, 0); clip-path: inset(58% 0 30% 0); }
73% { transform: translate(2px, 0); clip-path: none; }
82% { transform: translate(-4px, 0) skewX(-0.2deg); }
83% { transform: translate(0, 0); }
90% { transform: translate(15px, 0); clip-path: inset(68% 0 22% 0); }
90% { transform: translate(3px, 0); clip-path: inset(68% 0 22% 0); }
91% { transform: translate(0, 0); clip-path: none; }
}
@@ -317,7 +339,7 @@ a { color: inherit; text-decoration: none; }
linear-gradient(rgba(2,7,13,0.95), rgba(2,7,13,0.95)) 0 68% / 100% 3% no-repeat,
linear-gradient(rgba(2,7,13,0.95), rgba(2,7,13,0.95)) 0 84% / 100% 4% no-repeat;
opacity: 0;
animation: pixel-break 3.0s steps(1) infinite;
animation: pixel-break 12s steps(1) infinite;
}
@keyframes pixel-break {
0%, 7% { opacity: 0; }
@@ -365,29 +387,29 @@ a { color: inherit; text-decoration: none; }
rgba(33,234,255,0.10) 88%,
transparent 100%);
opacity: 0;
animation: scan-tear 3.0s steps(1) infinite;
animation: scan-tear 12s steps(1) infinite;
}
@keyframes scan-tear {
0%, 7% { opacity: 0; top: -8%; transform: translateX(0); }
8% { opacity: 0.9; top: 8%; transform: translateX(-60px); }
8% { opacity: 0.9; top: 8%; transform: translateX(-12px); }
10% { opacity: 0; }
18% { opacity: 0.85; top: 26%; transform: translateX(70px); }
18% { opacity: 0.85; top: 26%; transform: translateX(14px); }
20% { opacity: 0; }
24% { opacity: 0.95; top: 44%; transform: translateX(-50px); }
24% { opacity: 0.95; top: 44%; transform: translateX(-10px); }
26% { opacity: 0; }
36% { opacity: 0.7; top: 60%; transform: translateX(40px); }
36% { opacity: 0.7; top: 60%; transform: translateX(8px); }
37% { opacity: 0; }
44% { opacity: 0.95; top: 74%; transform: translateX(-70px); }
44% { opacity: 0.95; top: 74%; transform: translateX(-14px); }
46% { opacity: 0; }
56% { opacity: 0.6; top: 16%; transform: translateX(50px); }
56% { opacity: 0.6; top: 16%; transform: translateX(10px); }
57% { opacity: 0; }
64% { opacity: 0.9; top: 38%; transform: translateX(-40px); }
64% { opacity: 0.9; top: 38%; transform: translateX(-8px); }
65% { opacity: 0; }
72% { opacity: 0.7; top: 56%; transform: translateX(60px); }
72% { opacity: 0.7; top: 56%; transform: translateX(12px); }
73% { opacity: 0; }
82% { opacity: 0.95; top: 70%; transform: translateX(-50px); }
82% { opacity: 0.95; top: 70%; transform: translateX(-10px); }
83% { opacity: 0; }
90% { opacity: 0.6; top: 88%; transform: translateX(30px); }
90% { opacity: 0.6; top: 88%; transform: translateX(6px); }
91%, 100% { opacity: 0; }
}
.logo-scanlines {
@@ -618,18 +640,18 @@ a { color: inherit; text-decoration: none; }
flex-direction: column;
justify-content: center;
padding: 0 8vw;
max-width: 640px;
max-width: 780px;
}
.tag {
display: inline-flex;
align-items: center;
gap: 10px;
font-size: 11px;
font-size: 13px;
letter-spacing: 0.28em;
color: var(--cyan);
margin-bottom: 32px;
padding: 7px 14px;
padding: 8px 16px;
border: 1px solid rgba(33, 234, 255, 0.25);
background: rgba(33, 234, 255, 0.03);
width: fit-content;
@@ -648,7 +670,7 @@ a { color: inherit; text-decoration: none; }
.headline {
font-family: "VT323", "IBM Plex Mono", monospace;
font-size: clamp(20px, 2vw, 30px);
font-size: clamp(36px, 4vw, 64px);
white-space: nowrap;
line-height: 1.05;
letter-spacing: 0.01em;
@@ -656,7 +678,7 @@ a { color: inherit; text-decoration: none; }
text-shadow:
0 0 12px rgba(33, 234, 255, 0.6),
0 0 32px rgba(33, 234, 255, 0.3);
margin: 0 0 24px;
margin: 0 0 28px;
font-weight: 400;
}
.headline .bracket {
@@ -674,7 +696,7 @@ a { color: inherit; text-decoration: none; }
.body, .subheadline {
color: var(--ink-mid);
font-size: clamp(13px, 1.05vw, 16px);
font-size: clamp(17px, 1.4vw, 22px);
line-height: 1.55;
letter-spacing: 0.04em;
max-width: none;
@@ -684,7 +706,7 @@ a { color: inherit; text-decoration: none; }
.subheadline {
margin-bottom: 32px;
letter-spacing: 0.18em;
font-size: 13px;
font-size: 16px;
text-transform: uppercase;
}
@@ -697,8 +719,8 @@ a { color: inherit; text-decoration: none; }
backdrop-filter: blur(2px);
cursor: pointer;
font-family: "IBM Plex Mono", monospace;
font-size: 14px;
max-width: 560px;
font-size: 17px;
max-width: 720px;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
box-shadow:
0 0 0 1px rgba(33, 234, 255, 0.05),
@@ -772,7 +794,7 @@ a { color: inherit; text-decoration: none; }
align-items: center;
gap: 8px;
color: var(--cyan);
font-size: 13px;
font-size: 15px;
letter-spacing: 0.16em;
text-transform: uppercase;
border-bottom: 1px solid rgba(33, 234, 255, 0.25);