Files
my-protfolio/src/components/IsometricFooter/IsoElements.tsx

499 lines
21 KiB
TypeScript

import React from 'react';
import type {
IsoBoxProps,
MountainClusterProps,
PineTreeProps,
IsoPencilProps,
IsoMonitorProps,
IsoTowerProps,
IsoSignpostProps,
} from './IsoTypes';
/**
* Single isometric box: top diamond + two shaded side faces.
* (x, y) is the TOP vertex of the diamond. s = half-width, h = height.
*/
export function IsoBox({ x, y, s, h, top, left, right, stroke = 'none' }: IsoBoxProps) {
const topPts = `${x},${y} ${x + s},${y + s / 2} ${x},${y + s} ${x - s},${y + s / 2}`;
const leftPts = `${x - s},${y + s / 2} ${x},${y + s} ${x},${y + s + h} ${x - s},${y + s / 2 + h}`;
const rightPts = `${x + s},${y + s / 2} ${x},${y + s} ${x},${y + s + h} ${x + s},${y + s / 2 + h}`;
return (
<g>
<polygon points={leftPts} fill={left} stroke={stroke} strokeWidth={stroke === 'none' ? '0' : '1'} />
<polygon points={rightPts} fill={right} stroke={stroke} strokeWidth={stroke === 'none' ? '0' : '1'} />
<polygon points={topPts} fill={top} stroke={stroke} strokeWidth={stroke === 'none' ? '0' : '1'} />
</g>
);
}
/**
* Mountain Cluster
* Four stacked isometric boxes forming the mountain peak and foothills
*/
export function MountainCluster({ x, y, flip = false, scale = 1 }: MountainClusterProps) {
const f = flip ? -1 : 1;
const boxes = [
{ dx: 15 * f, dy: -45, s: 95, h: 130 },
{ dx: -60 * f, dy: 52, s: 58, h: 70 },
{ dx: 85 * f, dy: 65, s: 55, h: 60 },
{ dx: 0, dy: 98, s: 46, h: 46 },
];
return (
<g transform={`translate(${x} ${y}) scale(${scale})`}>
{boxes.map((b, i) => (
<IsoBox
key={i}
x={b.dx}
y={b.dy}
s={b.s}
h={b.h}
top="var(--hero-illus-cube-top, #9DCDFD)"
left="var(--hero-illus-cube-front, #2066AB)"
right="var(--hero-illus-cube-side, #0E4073)"
stroke="none"
/>
))}
</g>
);
}
/**
* Pine tree
* Features signature smooth teardrop/conical foliage and rounded capsule trunk
*/
export function PineTree({ x, y, scale = 1, dark = false }: PineTreeProps) {
const foliageColor = dark
? 'var(--hero-illus-tree-dark, #104179)'
: 'var(--hero-illus-tree-light, #2166A9)';
const trunkColor = 'var(--hero-illus-tree-trunk, #08234B)';
return (
<g transform={`translate(${x} ${y}) scale(${scale})`}>
{/* Capsule Trunk */}
<path
d="M-4.044 -8.583C-4.044 -10.544 -2.455 -12.133 -0.494 -12.133H0.494C2.455 -12.133 4.044 -10.544 4.044 -8.583V-3.551C4.044 -1.59 2.455 0 0.494 0H-0.494C-2.455 0 -4.044 -1.59 -4.044 -3.551Z"
fill={trunkColor}
/>
{/* Foliage */}
<path
d="M12.551 -18.365L0 -56.958L-12.551 -18.365C-13.154 -16.509 -13.163 -14.402 -11.681 -13.133C-9.714 -11.447 -6.067 -9.774 0 -9.774C6.067 -9.774 9.714 -11.447 11.681 -13.133C13.163 -14.402 13.154 -16.509 12.551 -18.365Z"
fill={foliageColor}
/>
</g>
);
}
/**
* Modern SVG Icons for Top Contact Bar and Signposts
*/
export const PhoneIcon: React.FC<{ size?: number; color?: string }> = ({
size = 20,
color = 'currentColor',
}) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
<path d="M6.62 10.79a15.46 15.46 0 0 0 6.59 6.59l2.2-2.2a1.02 1.02 0 0 1 1.02-.24c1.12.37 2.33.57 3.57.57a1 1 0 0 1 1 1V20a1 1 0 0 1-1 1C10.61 21 3 13.39 3 4a1 1 0 0 1 1-1h3.5a1 1 0 0 1 1 1c0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2Z" />
</svg>
);
export const LinkedInIcon: React.FC<{ size?: number; color?: string }> = ({
size = 20,
color = 'currentColor',
}) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
<path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14m-.5 15.5v-5.3a3.26 3.26 0 0 0-3.26-3.26c-.85 0-1.84.52-2.28 1.3v-1.11h-2.79v8.37h2.79v-4.93c0-.77.62-1.4 1.39-1.4a1.4 1.4 0 0 1 1.4 1.4v4.93h2.75M6.88 8.56a1.68 1.68 0 0 0 1.68-1.68c0-.93-.75-1.69-1.68-1.69a1.69 1.69 0 0 0-1.69 1.69c0 .93.76 1.68 1.69 1.68m1.39 9.94v-8.37H5.5v8.37h2.77z" />
</svg>
);
export const GitHubIcon: React.FC<{ size?: number; color?: string }> = ({
size = 20,
color = 'currentColor',
}) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
<path d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34-.46-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.87 1.52 2.34 1.07 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.92 0-1.11.38-2 1.03-2.71-.1-.25-.45-1.29.1-2.64 0 0 .84-.27 2.75 1.02.79-.22 1.65-.33 2.5-.33.85 0 1.71.11 2.5.33 1.91-1.29 2.75-1.02 2.75-1.02.55 1.35.2 2.39.1 2.64.65.71 1.03 1.6 1.03 2.71 0 3.82-2.34 4.66-4.57 4.91.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2z" />
</svg>
);
export const TelegramIcon: React.FC<{ size?: number; color?: string }> = ({
size = 20,
color = 'currentColor',
}) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
<path d="M9.8 15.6l-.4 5.3c.6 0 .8-.2 1.1-.5l2.7-2.6 5.6 4.1c1 .6 1.7.3 2-.9l3.7-17.3c.4-1.5-.5-2.2-1.5-1.8L1.6 10.3c-1.5.6-1.5 1.5-.2 1.9l5.5 1.7 12.8-8.1c.6-.4 1.1-.2.7.2z" />
</svg>
);
export const MailIcon: React.FC<{ size?: number; color?: string }> = ({
size = 18,
color = 'currentColor',
}) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
<path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z" />
</svg>
);
/**
* Upright Majestic Faceted Pencil matching reference
* Blue faceted hexagonal shaft, cool white wood collar, and royal blue conical tip.
*/
export function IsoUprightPencil({ x, y, height = 84, width = 18 }: IsoPencilProps) {
const hw = width / 2;
const bodyH = height - 26;
const collarH = 14;
const tipH = 12;
const baseY = y;
const collarBaseY = baseY - bodyH;
const tipBaseY = collarBaseY - collarH;
const tipY = tipBaseY - tipH;
const p1 = `${x - hw},${baseY - 2} ${x - hw * 0.25},${baseY + 1} ${x - hw * 0.25},${collarBaseY} ${x - hw},${collarBaseY - 2}`;
const p2 = `${x - hw * 0.25},${baseY + 1} ${x + hw * 0.25},${baseY + 1} ${x + hw * 0.25},${collarBaseY} ${x - hw * 0.25},${collarBaseY}`;
const p3 = `${x + hw * 0.25},${baseY + 1} ${x + hw},${baseY - 2} ${x + hw},${collarBaseY - 2} ${x + hw * 0.25},${collarBaseY}`;
const woodLeft = `${x - hw},${collarBaseY - 2} ${x - hw * 0.25},${collarBaseY} ${x},${tipBaseY}`;
const woodMid = `${x - hw * 0.25},${collarBaseY} ${x + hw * 0.25},${collarBaseY} ${x},${tipBaseY}`;
const woodRight = `${x + hw * 0.25},${collarBaseY} ${x + hw},${collarBaseY - 2} ${x},${tipBaseY}`;
const leadLeft = `${x - hw * 0.32},${tipBaseY} ${x},${tipBaseY} ${x},${tipY}`;
const leadRight = `${x},${tipBaseY} ${x + hw * 0.32},${tipBaseY} ${x},${tipY}`;
return (
<g className="iso-pencil">
{/* Ground Contact Shadow */}
<polygon
points={`${x - hw * 1.2},${baseY - 1} ${x},${baseY + 3} ${x + hw * 1.2},${baseY - 1} ${x},${baseY - 4}`}
fill="var(--hero-illus-cube-shadow, #0C234F)"
opacity={0.18}
/>
{/* Shaft Facets (Light / Front / Dark matching 3D isometric lighting) */}
<polygon points={p1} fill="var(--hero-illus-cube-top, #9DCDFD)" stroke="var(--hero-illus-cube-front, #2066AB)" strokeWidth={0.4} />
<polygon points={p2} fill="var(--hero-illus-cube-front, #2066AB)" stroke="var(--hero-illus-cube-side, #0E4073)" strokeWidth={0.4} />
<polygon points={p3} fill="var(--hero-illus-cube-side, #0E4073)" stroke="var(--hero-illus-cube-shadow, #0C234F)" strokeWidth={0.4} />
{/* Scalloped Wood Facets */}
<polygon points={woodLeft} fill="var(--bg-subtle, #E6F0FE)" stroke="var(--border-default, #D9E2EF)" strokeWidth={0.3} />
<polygon points={woodMid} fill="var(--bg-raised, #FCFDFF)" stroke="var(--border-default, #D9E2EF)" strokeWidth={0.3} />
<polygon points={woodRight} fill="var(--color-border-light, #D9E2EF)" stroke="var(--border-strong, #A9BEDA)" strokeWidth={0.3} />
{/* Lead Tip */}
<polygon points={leadLeft} fill="var(--hero-illus-cube-front, #2066AB)" stroke="var(--hero-illus-cube-side, #0E4073)" strokeWidth={0.3} />
<polygon points={leadRight} fill="var(--hero-illus-cube-side, #0E4073)" stroke="var(--hero-illus-cube-shadow, #0C234F)" strokeWidth={0.3} />
</g>
);
}
/**
* Isometric Workstation Monitor matching reference
* Sizable flat panel screen angled in 3D, standing proudly on Tile 1
*/
export function IsoMonitorDisplay({ x, y, scale = 1 }: IsoMonitorProps) {
const baseW = 20;
const baseH = 10;
// Stand Base diamond
const sbFront = `${x},${y + baseH / 2}`;
const sbLeft = `${x - baseW / 2},${y}`;
const sbRight = `${x + baseW / 2},${y}`;
const sbBack = `${x},${y - baseH / 2}`;
const sbTop = `${sbBack} ${sbRight} ${sbFront} ${sbLeft}`;
const sbLeftDrop = `${sbLeft} ${sbFront} ${x},${y + baseH / 2 + 2} ${x - baseW / 2},${y + 2}`;
const sbRightDrop = `${sbFront} ${sbRight} ${x + baseW / 2},${y + 2} ${x},${y + baseH / 2 + 2}`;
// Monitor Display Panel (sleek, well-proportioned, clear of pencil)
const panCx = x;
const panCy = y - 24;
const hw = 21;
const hh = 15;
const slopeDy = 10.5; // 21 * 0.5 = 10.5
const depth = 3.5;
// Stand Neck column (extends from base plate up solidly behind the opaque screen panel)
const neckTop = panCy + 4;
const neckFront = `${x - 2},${neckTop} ${x + 2},${neckTop + 2} ${x + 2},${y} ${x - 2},${y - 2}`;
const neckSide = `${x + 2},${neckTop + 2} ${x + 4},${neckTop + 1} ${x + 4},${y - 1} ${x + 2},${y}`;
const fTopLeft = `${panCx - hw},${panCy - hh - slopeDy}`;
const fTopRight = `${panCx + hw},${panCy - hh + slopeDy}`;
const fBottomRight = `${panCx + hw},${panCy + hh + slopeDy}`;
const fBottomLeft = `${panCx - hw},${panCy + hh - slopeDy}`;
const pFront = `${fTopLeft} ${fTopRight} ${fBottomRight} ${fBottomLeft}`;
const bTopLeft = `${panCx - hw + depth},${panCy - hh - slopeDy - depth * 0.5}`;
const bTopRight = `${panCx + hw + depth},${panCy - hh + slopeDy - depth * 0.5}`;
const pTop = `${fTopLeft} ${bTopLeft} ${bTopRight} ${fTopRight}`;
const bBottomRight = `${panCx + hw + depth},${panCy + hh + slopeDy - depth * 0.5}`;
const pRight = `${fTopRight} ${bTopRight} ${bBottomRight} ${fBottomRight}`;
return (
<g
className="iso-monitor"
transform={scale !== 1 ? `translate(${x}, ${y}) scale(${scale}) translate(${-x}, ${-y})` : undefined}
>
{/* Ground Contact Shadow */}
<polygon
points={`${x - baseW * 0.7},${y} ${x},${y + baseH * 0.7} ${x + baseW * 0.7},${y} ${x},${y - baseH * 0.7}`}
fill="var(--hero-illus-cube-shadow, #0C234F)"
opacity={0.16}
/>
{/* Stand Base Drop Faces */}
<polygon points={sbLeftDrop} fill="var(--hero-illus-cube-front, #2066AB)" stroke="var(--hero-illus-cube-side, #0E4073)" strokeWidth={0.4} />
<polygon points={sbRightDrop} fill="var(--hero-illus-cube-side, #0E4073)" stroke="var(--hero-illus-cube-shadow, #0C234F)" strokeWidth={0.4} />
<polygon points={sbTop} fill="var(--hero-illus-cube-top, #9DCDFD)" stroke="var(--color-blue-300, #82B5FF)" strokeWidth={0.6} />
{/* Stand Neck Column */}
<polygon points={neckFront} fill="var(--hero-illus-cube-top, #9DCDFD)" stroke="var(--hero-illus-cube-front, #2066AB)" strokeWidth={0.4} />
<polygon points={neckSide} fill="var(--hero-illus-cube-side, #0E4073)" stroke="var(--hero-illus-cube-shadow, #0C234F)" strokeWidth={0.4} />
{/* Monitor Display Bezel & Screen Face */}
<polygon points={pTop} fill="var(--hero-illus-cube-top, #9DCDFD)" stroke="var(--color-blue-300, #82B5FF)" strokeWidth={0.6} />
<polygon points={pRight} fill="var(--hero-illus-cube-side, #0E4073)" stroke="var(--hero-illus-cube-shadow, #0C234F)" strokeWidth={0.6} />
<polygon points={pFront} fill="var(--accent-default, #3D8AFA)" stroke="var(--color-blue-500, #1557A6)" strokeWidth={0.8} />
</g>
);
}
/**
* Isometric PC Tower Unit matching reference
* Vertical rectangular prism sitting on a clean white pedestal plate
*/
export function IsoPCTower({ x, y, size = 20, height = 40 }: IsoTowerProps) {
const hs = size / 2;
const plateW = size + 10;
const plateH = (size + 10) * 0.5;
// Base Pedestal Plate
const plFront = `${x},${y + plateH / 2}`;
const plLeft = `${x - plateW / 2},${y}`;
const plRight = `${x + plateW / 2},${y}`;
const plBack = `${x},${y - plateH / 2}`;
const plTop = `${plBack} ${plRight} ${plFront} ${plLeft}`;
const plLeftDrop = `${plLeft} ${plFront} ${x},${y + plateH / 2 + 2.5} ${x - plateW / 2},${y + 2.5}`;
const plRightDrop = `${plFront} ${plRight} ${x + plateW / 2},${y + 2.5} ${x},${y + plateH / 2 + 2.5}`;
// Cube Base corners
const baseY = y - 1;
const cFront = `${x},${baseY + hs * 0.5}`;
const cLeft = `${x - hs},${baseY}`;
const cRight = `${x + hs},${baseY}`;
const cBack = `${x},${baseY - hs * 0.5}`;
// Cube Top corners
const topY = baseY - height;
const tFront = `${x},${topY + hs * 0.5}`;
const tLeft = `${x - hs},${topY}`;
const tRight = `${x + hs},${topY}`;
const tBack = `${x},${topY - hs * 0.5}`;
const faceTop = `${tBack} ${tRight} ${tFront} ${tLeft}`;
const faceLeft = `${cLeft} ${cFront} ${tFront} ${tLeft}`;
const faceRight = `${cFront} ${cRight} ${tRight} ${tFront}`;
return (
<g className="iso-pc-tower">
{/* Pedestal Plate */}
<polygon points={plLeftDrop} fill="var(--hero-illus-cube-front, #2066AB)" stroke="var(--hero-illus-cube-side, #0E4073)" strokeWidth={0.4} />
<polygon points={plRightDrop} fill="var(--hero-illus-cube-side, #0E4073)" stroke="var(--hero-illus-cube-shadow, #0C234F)" strokeWidth={0.4} />
<polygon points={plTop} fill="var(--bg-raised, #FCFDFF)" stroke="var(--border-strong, #A9BEDA)" strokeWidth={0.7} />
{/* Main Vertical Tower Body */}
<polygon points={faceLeft} fill="var(--hero-illus-cube-front, #2066AB)" stroke="var(--hero-illus-cube-side, #0E4073)" strokeWidth={0.6} />
<polygon points={faceRight} fill="var(--hero-illus-cube-side, #0E4073)" stroke="var(--hero-illus-cube-shadow, #0C234F)" strokeWidth={0.6} />
<polygon points={faceTop} fill="var(--hero-illus-cube-top, #9DCDFD)" stroke="var(--hero-illus-cube-front, #2066AB)" strokeWidth={0.7} />
</g>
);
}
/**
* Isometric Signpost
* True 3D item with elevated 3D cylindrical base plate and shaded 3D cylindrical metallic pole
*/
export function IsoSignpost({
id: _id,
x,
y,
postHeight = 48,
facing = 'right',
backdropDirection,
icon,
label: _label,
isActive = false,
onMouseEnter,
onMouseLeave,
onClick,
}: IsoSignpostProps) {
const isRight = facing === 'right';
const postTopY = y - postHeight;
const cardSize = 32;
const radius = 6;
// 3D Isometric Shear Matrix:
// facing="right" (SE): slope +0.5 -> matrix(1, 0.5, 0, 1, 0, 0)
// facing="left" (SW): slope -0.5 -> matrix(1, -0.5, 0, 1, 0, 0)
const shearSlope = isRight ? 0.5 : -0.5;
const gradId = `standPoleGrad-${_id}`;
// Directional Backdrop Offset:
// Rightside items (GitHub, Telegram): 'left-top' (backShiftX = -3.5, backShiftY = -3.2)
// Leftside items (Phone, LinkedIn): 'right-top' (backShiftX = +3.5, backShiftY = -3.2)
const dir = backdropDirection ?? (isRight ? 'right-top' : 'left-top');
const isRightTop = dir === 'right-top';
const backShiftX = isRightTop ? 3.5 : -3.5;
const backShiftY = -3.2;
return (
<g
className={`iso-signpost ${isActive ? 'active' : ''}`}
data-footer-contact={_id}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onClick={onClick}
style={{ cursor: 'pointer', touchAction: 'manipulation' }}
>
<defs>
{/* 3D Cylindrical Metallic Gradient for Upright Pole */}
<linearGradient id={gradId} x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="var(--hero-illus-cube-top, #9DCDFD)" />
<stop offset="35%" stopColor="var(--accent-default, #3D8AFA)" />
<stop offset="70%" stopColor="var(--hero-illus-cube-front, #2066AB)" />
<stop offset="100%" stopColor="var(--hero-illus-cube-side, #0E4073)" />
</linearGradient>
</defs>
{/* Expanded invisible touch hit box */}
<rect
x={x - 28}
y={postTopY - cardSize - 10}
width={56}
height={cardSize + postHeight + 16}
fill="transparent"
/>
{/* 3D Ground Base Assembly */}
{/* 1. 3D Cylindrical Disc Drop Apron (Thickness = 4px) */}
<path
d={`M ${x - 11.5},${y} A 11.5 5.75 0 0 0 ${x + 11.5},${y} L ${x + 11.5},${y + 4} A 11.5 5.75 0 0 1 ${x - 11.5},${y + 4} Z`}
fill={isActive ? 'var(--hero-illus-cube-side, #0E4073)' : 'var(--hero-illus-cube-front, #2066AB)'}
stroke="var(--hero-illus-cube-side, #0E4073)"
strokeWidth={0.6}
/>
{/* Center ridge divider on the cylinder drop */}
<line x1={x} y1={y + 5.75} x2={x} y2={y + 9.75} stroke="var(--hero-illus-cube-shadow, #0C234F)" strokeWidth={0.8} />
{/* 3. 3D Disc Top Surface */}
<ellipse
cx={x}
cy={y}
rx={11.5}
ry={5.75}
fill={isActive ? 'var(--color-blue-300, #82B5FF)' : 'var(--bg-subtle, #E6F0FE)'}
stroke={isActive ? 'var(--hero-illus-cube-front, #2066AB)' : 'var(--border-strong, #A9BEDA)'}
strokeWidth={1}
/>
{/* 4. Concentric Socket Collar / Ring where pole enters */}
<path
d={`M ${x - 4.5},${y - 0.5} A 4.5 2.25 0 0 0 ${x + 4.5},${y - 0.5} L ${x + 4.5},${y + 1.5} A 4.5 2.25 0 0 1 ${x - 4.5},${y + 1.5} Z`}
fill="var(--hero-illus-cube-shadow, #0C234F)"
/>
<ellipse
cx={x}
cy={y - 0.5}
rx={4.5}
ry={2.25}
fill="var(--hero-illus-cube-front, #2066AB)"
stroke="var(--hero-illus-cube-side, #0E4073)"
strokeWidth={0.6}
/>
<ellipse
cx={x}
cy={y - 0.5}
rx={2}
ry={1}
fill="var(--hero-illus-cube-shadow, #0C234F)"
/>
{/* 3D Cylindrical Metallic Pole (extends seamlessly up behind the card body) */}
<rect
x={x - 1.4}
y={postTopY - 16}
width={2.8}
height={y - (postTopY - 16)}
rx={1.4}
fill={`url(#${gradId})`}
/>
{/* Left-edge specular highlight glint line */}
<line
x1={x - 0.7}
y1={y - 2}
x2={x - 0.7}
y2={postTopY - 14}
stroke="var(--color-blue-white, #F8FAFF)"
strokeWidth={0.6}
opacity={0.65}
/>
{/* 3D Rotated Isometric Signboard */}
<g
transform={isActive ? 'translate(0, -3)' : 'translate(0, 0)'}
style={{ transition: 'transform 0.25s cubic-bezier(0.16, 1, 0.3, 1)' }}
>
{/* 1. Backdrop Layer (Positioned to left-top for rightside items, right-top for leftside items) */}
<g transform={`translate(${x + backShiftX}, ${postTopY - 18 + backShiftY}) matrix(1, ${shearSlope}, 0, 1, 0, 0)`}>
{/* Subtle Ambient Shadow behind the backdrop plate */}
<rect
x={-cardSize / 2 + (isRightTop ? 1.2 : -1.2)}
y={-cardSize / 2 + 1}
width={cardSize}
height={cardSize}
rx={radius}
fill="var(--hero-illus-cube-shadow, #0C234F)"
opacity={isActive ? 0.35 : 0.18}
/>
{/* 3D Backdrop Plate with signature royal blue fill and darker border */}
<rect
x={-cardSize / 2}
y={-cardSize / 2}
width={cardSize}
height={cardSize}
rx={radius}
fill={isActive ? 'var(--hero-illus-cube-side, #0E4073)' : 'var(--hero-illus-cube-front, #2066AB)'}
stroke={isActive ? 'var(--hero-illus-cube-shadow, #0C234F)' : 'var(--hero-illus-cube-side, #0E4073)'}
strokeWidth={1}
/>
</g>
{/* 2. Front Card Layer (Centered flush on the pole axis at x, postTopY - 18) */}
<g transform={`translate(${x}, ${postTopY - 18}) matrix(1, ${shearSlope}, 0, 1, 0, 0)`}>
{/* Crisp Opaque Card Body with Blue Border */}
<rect
x={-cardSize / 2}
y={-cardSize / 2}
width={cardSize}
height={cardSize}
rx={radius}
fill="var(--bg-raised, #FCFDFF)"
stroke={isActive ? 'var(--accent-default, #3D8AFA)' : 'var(--border-strong, #A9BEDA)'}
strokeWidth={isActive ? 2 : 1.6}
/>
{/* 3D Rotated Icon inside Card */}
<g
transform="translate(0, 0)"
color={isActive ? 'var(--accent-default, #3D8AFA)' : 'var(--hero-illus-cube-front, #2066AB)'}
>
<g transform="translate(-8.5, -8.5) scale(0.85)">
{icon}
</g>
</g>
</g>
</g>
</g>
);
}