Spaces:
Running on Zero
Running on Zero
Reposition figure callouts to land on articulation points
Browse filesMove callouts inside .figure-img-wrap so coordinates are image-relative
instead of stage-relative — fixes dots drifting off the figure on layouts
where the stage is wider than the image. Anchor each callout by the dot's
vertical center via translateY(-50%) so `top` refers to the dot, not the
container's top edge.
Tuned coordinates (top, right):
- ARTICULATED · ARM: 32%, 47% (on her upper arm holding the lasso)
- BALL-JOINT · KNEE: 46%, 45% (on her bent raised knee)
- SOFT-GOODS · PLASTIC: 60%, 32% (on the horse's body)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- static/action-variants.jsx +20 -18
- static/action.css +7 -5
static/action-variants.jsx
CHANGED
|
@@ -27,34 +27,36 @@ function HeroVariant({ onFile, heroImage }) {
|
|
| 27 |
<div className="grid-lines" />
|
| 28 |
<div className="grain" />
|
| 29 |
|
| 30 |
-
{/* Standing figure — wrapped with aspect-ratio so corner crops align to the image edges
|
|
|
|
|
|
|
|
|
|
| 31 |
<div className="figure-stage">
|
| 32 |
<div className="figure-img-wrap">
|
| 33 |
<span className="figure-crop tl"/><span className="figure-crop tr"/>
|
| 34 |
<span className="figure-crop bl"/><span className="figure-crop br"/>
|
| 35 |
<img className="figure-img" src={heroImage} alt="action figure" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
</div>
|
| 37 |
<div className="plinth"/>
|
| 38 |
<div className="floor"/>
|
| 39 |
</div>
|
| 40 |
|
| 41 |
-
{/* Callouts — positioned for the lasso cowgirl hero (rearing horse, sunset, 5:4 landscape) */}
|
| 42 |
-
<div className="callout" style={{ top: '40%', right: '28%' }}>
|
| 43 |
-
<span className="lbl">ARTICULATED · ARM</span>
|
| 44 |
-
<span className="line"/>
|
| 45 |
-
<span className="dot"/>
|
| 46 |
-
</div>
|
| 47 |
-
<div className="callout" style={{ top: '52%', right: '19%' }}>
|
| 48 |
-
<span className="lbl">BALL-JOINT · KNEE</span>
|
| 49 |
-
<span className="line"/>
|
| 50 |
-
<span className="dot"/>
|
| 51 |
-
</div>
|
| 52 |
-
<div className="callout" style={{ top: '60%', right: '22%' }}>
|
| 53 |
-
<span className="lbl">SOFT-GOODS · PLASTIC</span>
|
| 54 |
-
<span className="line"/>
|
| 55 |
-
<span className="dot"/>
|
| 56 |
-
</div>
|
| 57 |
-
|
| 58 |
<div className="left">
|
| 59 |
<div>
|
| 60 |
<div className="eyebrow"><span className="line"/>SYSTMS / ACTION · v0.9</div>
|
|
|
|
| 27 |
<div className="grid-lines" />
|
| 28 |
<div className="grain" />
|
| 29 |
|
| 30 |
+
{/* Standing figure — wrapped with aspect-ratio so corner crops align to the image edges.
|
| 31 |
+
Callouts live INSIDE the wrap so coordinates are image-relative. Each callout is a
|
| 32 |
+
single flex row: [label][short line][dot]. The container is anchored by its
|
| 33 |
+
right-center, so the `top`/`right` percentages refer to the dot's position. */}
|
| 34 |
<div className="figure-stage">
|
| 35 |
<div className="figure-img-wrap">
|
| 36 |
<span className="figure-crop tl"/><span className="figure-crop tr"/>
|
| 37 |
<span className="figure-crop bl"/><span className="figure-crop br"/>
|
| 38 |
<img className="figure-img" src={heroImage} alt="action figure" />
|
| 39 |
+
|
| 40 |
+
<div className="callout" style={{ top: '32%', right: '47%' }}>
|
| 41 |
+
<span className="lbl">ARTICULATED · ARM</span>
|
| 42 |
+
<span className="line"/>
|
| 43 |
+
<span className="dot"/>
|
| 44 |
+
</div>
|
| 45 |
+
<div className="callout" style={{ top: '46%', right: '45%' }}>
|
| 46 |
+
<span className="lbl">BALL-JOINT · KNEE</span>
|
| 47 |
+
<span className="line"/>
|
| 48 |
+
<span className="dot"/>
|
| 49 |
+
</div>
|
| 50 |
+
<div className="callout" style={{ top: '60%', right: '32%' }}>
|
| 51 |
+
<span className="lbl">SOFT-GOODS · PLASTIC</span>
|
| 52 |
+
<span className="line"/>
|
| 53 |
+
<span className="dot"/>
|
| 54 |
+
</div>
|
| 55 |
</div>
|
| 56 |
<div className="plinth"/>
|
| 57 |
<div className="floor"/>
|
| 58 |
</div>
|
| 59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
<div className="left">
|
| 61 |
<div>
|
| 62 |
<div className="eyebrow"><span className="line"/>SYSTMS / ACTION · v0.9</div>
|
static/action.css
CHANGED
|
@@ -24,11 +24,13 @@
|
|
| 24 |
.v-hero.v-action .lead{max-width:480px}
|
| 25 |
.v-hero.v-action .side{display:none}
|
| 26 |
|
| 27 |
-
/* Figure callout chip —
|
| 28 |
-
.
|
| 29 |
-
|
| 30 |
-
.callout
|
| 31 |
-
.callout .
|
|
|
|
|
|
|
| 32 |
.callout.left-side{flex-direction:row-reverse}
|
| 33 |
.callout.left-side .line{transform:rotate(180deg)}
|
| 34 |
|
|
|
|
| 24 |
.v-hero.v-action .lead{max-width:480px}
|
| 25 |
.v-hero.v-action .side{display:none}
|
| 26 |
|
| 27 |
+
/* Figure callout chip — short label + stub line + dot pinned to an articulation point.
|
| 28 |
+
Lives inside .figure-img-wrap so `top`/`right` are image-relative. The container is
|
| 29 |
+
shifted up by half its height so `top` refers to the dot's vertical centre. */
|
| 30 |
+
.callout{position:absolute;z-index:4;display:flex;align-items:center;gap:10px;transform:translateY(-50%);font-family:'JetBrains Mono',monospace;font-size:9px;letter-spacing:0.22em;color:var(--muted);text-transform:uppercase}
|
| 31 |
+
.callout .dot{width:8px;height:8px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 3px rgba(255,45,30,0.2);flex-shrink:0}
|
| 32 |
+
.callout .line{width:40px;height:1px;background:var(--line-2);flex-shrink:0}
|
| 33 |
+
.callout .lbl{background:rgba(10,10,10,0.85);border:1px solid var(--line-2);padding:4px 8px;border-radius:3px;backdrop-filter:blur(6px);color:var(--text);white-space:nowrap}
|
| 34 |
.callout.left-side{flex-direction:row-reverse}
|
| 35 |
.callout.left-side .line{transform:rotate(180deg)}
|
| 36 |
|