Skiply.ai/skiply/skiply-connected-systems.css

553 lines
11 KiB
CSS

/* =============================================
Skiply.ai — Connected Systems section
Figma: SG-DEV
============================================= */
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--navy-deep: #06152c;
--blue: #0060ef;
--text-white: #ffffff;
--text-dim: rgba(255, 255, 255, 0.65);
--line: rgba(255, 255, 255, 0.5);
--font-main: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
--font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
--content-w: 1320px;
}
html {
font-family: var(--font-main);
-webkit-font-smoothing: antialiased;
}
body {
background: var(--navy-deep);
}
/* ── Section shell ──────────────────────────── */
.connected {
background: var(--navy-deep);
padding: 96px 32px 80px;
}
.connected__inner {
max-width: var(--content-w);
margin: 0 auto;
}
/* ── Heading ────────────────────────────────── */
.connected__header {
text-align: center;
margin-bottom: 32px;
}
.connected__eyebrow {
font-size: 0.95rem;
font-weight: 400;
color: var(--text-dim);
margin-bottom: 12px;
}
.connected__title {
font-family: var(--font-display);
font-size: 2.6rem;
font-weight: 400;
line-height: 1.2;
color: var(--text-white);
max-width: 780px;
margin: 0 auto;
}
/* ── Banner / scan stage ─────────────────────── */
.connected__banner {
max-width: 720px;
margin: 0 auto;
}
.shoe-stage {
position: relative;
width: 100%;
aspect-ratio: 631/527;
}
.shoe-stage__glow {
position: absolute;
left: 50%;
top: 50%;
width: 85%;
height: 85%;
transform: translate(-50%, -50%);
background: radial-gradient(ellipse, rgba(0, 96, 239, 0.35) 0%, rgba(0, 96, 239, 0) 70%);
filter: blur(20px);
animation: shoeGlowPulse 4s ease-in-out infinite;
pointer-events: none;
}
@keyframes shoeGlowPulse {
0%,
100% {
opacity: 0.7;
}
50% {
opacity: 1;
}
}
.shoe-stage__img {
position: absolute;
z-index: 2;
inset: 0;
width: 100%;
height: 100%;
object-fit: contain;
filter: drop-shadow(0 0 14px rgba(110, 165, 255, 0.8)) drop-shadow(0 0 36px rgba(70, 120, 255, 0.4));
animation: shoeGlow 2s ease-in-out infinite;
}
@keyframes shoeGlow {
0%,
100% {
filter:
drop-shadow(rgba(110, 165, 255, 0.5) 0px 0px 10px) drop-shadow(rgba(70, 120, 255, 0.25) 0px 0px 25px);
}
50% {
filter:
drop-shadow(rgba(110, 165, 255, 1) 0px 0px 20px) drop-shadow(rgba(70, 120, 255, 0.65) 0px 0px 50px);
}
}
/* Outer layer: a plain rectangular clip that reveals left-to-right in
step with the scan beam via --reveal (kept separate from the alpha
mask below — combining both in one multi-layer mask is unreliable
across engines). */
.shoe-stage__mesh-clip {
--reveal: 0%;
position: absolute;
inset: 0;
clip-path: inset(0 calc(100% - var(--reveal)) 0 0);
pointer-events: none;
}
/* Inner layer: the wireframe grid, clipped to the shoe's own alpha
silhouette so it only ever paints on the shoe itself. */
.shoe-stage__mesh {
position: absolute;
inset: 0;
opacity: 0;
background-image:
repeating-linear-gradient(0deg, rgba(140, 190, 255, 0.4) 0 1px, transparent 1px 22px),
repeating-linear-gradient(90deg, rgba(140, 190, 255, 0.4) 0 1px, transparent 1px 22px);
mix-blend-mode: screen;
filter: drop-shadow(0 0 5px rgba(96, 160, 255, 0.6));
-webkit-mask-image: url(../assets/connected-systems/shoe-clean.png);
-webkit-mask-size: 100% 100%;
-webkit-mask-repeat: no-repeat;
mask-image: url(../assets/connected-systems/shoe-clean.png);
mask-size: 100% 100%;
mask-repeat: no-repeat;
mask-mode: alpha;
pointer-events: none;
}
/* Horizon beam: a persistent glowing line that appears to pass through
the shoe once the scan finishes, extending past its silhouette on
both sides. Grows outward from center. */
.shoe-stage__horizon {
position: absolute;
left: -18%;
right: -18%;
top: 45%;
height: 3px;
margin-top: -1.5px;
opacity: 0;
transform: scaleX(0);
transform-origin: center;
z-index: 3;
pointer-events: none;
border-top: 2px solid;
border-image-slice: 2;
border-image-source: linear-gradient(90deg,
rgba(255, 255, 255, 0) 0%,
#fff 15.38%,
#fff 85.58%,
rgba(255, 255, 255, 0) 100%);
filter:
drop-shadow(0 0 4px rgba(255, 255, 255, 0.9)) drop-shadow(0 0 12px rgba(110, 165, 255, 0.8)) drop-shadow(0 0 30px rgba(70, 120, 255, 0.5));
overflow: visible;
}
/* Moving wave */
.shoe-stage__horizon::after {
content: "";
position: absolute;
top: -2px;
left: -10%;
width: 20%;
height: 5px;
background: linear-gradient(90deg,
transparent,
rgba(255, 255, 255, 0.9),
rgba(110, 165, 255, 0.8),
transparent);
filter: blur(5px);
opacity: 0;
animation: horizonWave 2.5s ease-in-out infinite;
}
@keyframes horizonWave {
0% {
left: -10%;
opacity: 0;
transform: scaleY(0.5);
}
20% {
opacity: 1;
}
50% {
transform: scaleY(1.5);
}
80% {
opacity: 1;
}
100% {
left: 90%;
opacity: 0;
transform: scaleY(0.5);
}
}
.shoe-stage__particles {
position: absolute;
inset: 0;
pointer-events: none;
}
.scan-particle {
position: absolute;
width: 3px;
height: 3px;
border-radius: 50%;
background: #cfe2ff;
box-shadow: 0 0 6px 1px rgba(150, 195, 255, 0.9);
opacity: 0;
}
/* ── Ambient dust: a persistent field of dots, independent of the
scroll-triggered scan sequence, that keeps the banner feeling alive.
Color is a light cyan-white chosen for contrast against the dark
navy banner backdrop. ── */
.shoe-stage__ambient {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 1;
}
.ambient-particle {
position: absolute;
border-radius: 50%;
background: #e4f0ff;
box-shadow: 0 0 5px 1.5px rgba(150, 195, 255, 0.85);
animation: ambientFloat var(--dur, 3.5s) ease-in-out infinite;
animation-delay: var(--delay, 0s);
animation-fill-mode: backwards;
}
@keyframes ambientFloat {
0%,
100% {
transform: translate(0, 0) scale(0.7);
opacity: 0.12;
}
50% {
transform: translate(var(--dx, 8px), var(--dy, -14px)) scale(1.2);
opacity: 0.85;
}
}
@media (prefers-reduced-motion: reduce) {
.ambient-particle {
animation: none;
opacity: 0.4;
}
}
/* ── Scan labels: icon + two-line chip, matching Figma node 328:820 ── */
.scan-label {
position: absolute;
z-index: 4;
display: inline-flex;
align-items: center;
gap: 12px;
font-size: 0.85rem;
font-weight: 400;
color: rgba(255, 255, 255, 0.85);
border: 1px solid rgba(255, 255, 255, 0.35);
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9), 0 0 10px rgba(0, 0, 0, 0.7);
opacity: 0;
white-space: nowrap;
border-radius: 7px;
background: rgba(255, 255, 255, 0.10);
padding: 10px 20px;
backdrop-filter: blur(3px);
-webkit-backdrop-filter: blur(3px);
}
.scan-label__icon {
width: 26px;
height: 26px;
flex-shrink: 0;
object-fit: contain;
}
.scan-label__text {
display: flex;
flex-direction: column;
line-height: 1.3;
}
.scan-label__key {
font-size: 0.8rem;
font-weight: 400;
color: rgba(255, 255, 255, 0.75);
}
.scan-label__value {
font-size: 1rem;
font-weight: 700;
color: var(--text-white);
}
.scan-label--condition {
left: -1%;
top: 0;
}
.scan-label--resale {
right: 2%;
top: 18%;
}
.scan-label--market {
left: 10%;
top: 66%;
}
.scan-label--value {
right: -4%;
top: 65%;
}
/* ── Light connector: carries the horizon beam into the tree ──── */
.connected__flow {
position: relative;
width: 3px;
height: 56px;
margin: 0 auto;
overflow: visible;
}
.connected__flow-line {
position: absolute;
inset: 0;
background: linear-gradient(to bottom,
transparent,
rgba(150, 195, 255, 0.95) 25%,
rgba(150, 195, 255, 0.95) 75%,
transparent);
box-shadow: 0 0 12px 3px rgba(110, 165, 255, 0.7);
transform: scaleY(0);
transform-origin: top center;
opacity: 0;
}
.connected__flow-dot {
position: absolute;
left: 50%;
top: 0;
width: 8px;
height: 8px;
margin: -4px 0 0 -4px;
border-radius: 50%;
background: #eaf2ff;
box-shadow: 0 0 10px 3px #6ba8ff, 0 0 20px 8px #3f7bff;
opacity: 0;
}
/* ── Distribution tree ──────────────────────── */
.connected__tree {
position: relative;
margin-top: -250px;
}
.connected__branches {
display: block;
width: 100%;
height: auto;
opacity: 0;
}
/* Each branch reveals top-to-bottom independently, staggered in JS,
so the five lines visibly draw in one after another. */
.connected__branch-group {
clip-path: inset(0 0 100% 0);
}
.connected__node {
opacity: 0;
transform-box: fill-box;
transform-origin: center;
}
/* ── Route pills ─────────────────────────────── */
.connected__routes {
display: flex;
gap: 15px;
list-style: none;
}
.route {
flex: 1 1 0;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
gap: 24px;
min-height: 150px;
padding: 40px 20px;
background: var(--blue);
border-radius: 16px;
transition: transform 0.4s ease;
}
.route.is-lit {
transform: translateY(-4px);
}
.route__badge {
flex-shrink: 0;
width: 52px;
height: 52px;
border-radius: 7px;
background: #ffffff;
border: 1px solid #e2dede;
box-shadow: 0 4px 4px rgba(0, 0, 0, 0.15), inset 1px -1px 4px rgba(0, 0, 0, 0.15);
transform: rotate(45deg);
display: flex;
align-items: center;
justify-content: center;
}
.route__badge img {
width: 24px;
height: 24px;
transform: rotate(-45deg);
}
.route__label {
font-size: 1.1rem;
font-weight: 400;
color: var(--text-white);
}
/* ═══════════════════════════════════════════════
Responsive
═══════════════════════════════════════════════ */
@media (max-width: 1024px) {
.connected__title {
font-size: 2.1rem;
}
.connected__routes {
flex-wrap: wrap;
}
.route {
flex: 1 1 calc(33.333% - 10px);
}
}
@media (max-width: 640px) {
.connected {
padding: 64px 20px 56px;
}
.connected__title {
font-size: 1.6rem;
}
.connected__eyebrow {
font-size: 0.8rem;
}
.connected__branches {
display: none;
}
.scan-label {
font-size: 0.7rem;
gap: 8px;
padding: 6px 12px;
}
.scan-label__icon {
width: 18px;
height: 18px;
}
.scan-label__key {
font-size: 0.65rem;
}
.scan-label__value {
font-size: 0.8rem;
}
.connected__routes {
flex-direction: column;
gap: 12px;
}
.route {
flex: 1 1 auto;
width: 100%;
flex-direction: row;
align-items: center;
justify-content: flex-start;
min-height: auto;
gap: 16px;
padding: 14px 20px;
}
.route__label {
font-size: 1rem;
}
}