Add existing to tracked

This commit is contained in:
Jay
2026-08-11 09:53:42 -04:00
parent afe07f3055
commit ffd6e3d73c
8531 changed files with 4396230 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
# Side Cards — art direction
The approved visual reference is the J/Q/K of Hearts family in `concepts/`.
Court figures are final raster illustrations generated locally with Draw Things;
they are not hand-traced. `tools/build_deck.py` embeds each illustration inside
a standalone SVG and adds dependable card geometry.
## Look
- Original Anglo-American court-card illustration
- Crisp flat fills with strong black keylines
- Traditional two-way composition
- Ornate garments without photorealistic lighting or 3D rendering
- Restrained red, black, gold, muted-blue and warm-skin palette
- No generated rank letters, typography, logos or watermarks
Approximate palette sampled from the approved family:
| Role | Colour |
|---|---|
| Stock | `#fcfcfa` |
| Keyline | `#0e0d0d` |
| Red | `#a21b1e` |
| Gold | `#b99a34` |
| Muted blue | `#354c58` |
| Skin | `#f0d2b6` |
These values guide generation; the raster art is not mechanically recoloured.
## Court family
| Rank | Figure | Prop |
|---|---|---|
| Jack | young knave, shoulder-length hair | upright halberd |
| Queen | crowned queen | stylized flower |
| King | mature bearded king, crowned | upright sword |
Diamonds emphasize angular red-and-gold ornament. Clubs and Spades emphasize
black and muted blue with red-and-gold accents. All twelve should feel related,
but they do not need identical faces or frames.
## Deterministic card elements
`tools/build_deck.py`, not the image model, owns:
- corner rank indices
- suit marks and number-card pip layouts
- one continuous inner court frame
- final 5:7 card geometry
- the outer card edge
The outer card and artwork clip use a 24-unit circular radius on the 500 x 700
viewBox, equivalent to approximately 3.05 mm on a 63.5 x 88.9 mm poker card.
The two-unit inset outline uses radius 22 so its curve remains concentric. The
gallery expresses the same circular curve as `4.8% / 3.4286%`; a single CSS
percentage would create an elliptical radius on a 5:7 element.
Rank indices use Roboto Slab SemiBold, converted to SVG outlines during the
build without synthetic horizontal distortion. This provides large, clear slab
forms without depending on an installed font. Roboto Slab is distributed under
Apache License 2.0; the local license copy is
`assets/fonts/RobotoSlab-Apache-2.0.txt`.
Rank outlines share a font baseline at y=85 and are sized from cap height,
rather than top-aligned or fitted around descenders. This lets Q retain its
natural tail and weight without a synthetic outline. Single ranks have a
63-unit width allowance so the naturally wide A/K reach full cap height; the
two-character `10` has 76 units so it also remains comparable.
Mini suits remain centred at y=127 and are optically scaled by silhouette
(S 0.78, H 0.71, D 0.92, C 0.78), rather than being forced to one geometric
scale. Their rendered footprints—not equal ink density—are checked as a group
during the deck audit so dense marks are not made visually undersized.
The Heart is a purpose-drawn, classic silhouette with a pronounced cleft,
distinct lobes, a near-square proportion, and a long sharp point. Number-card
field pips are likewise optically balanced by suit (S 1.50, H 1.28, D 1.75,
C 1.43).
Ace and court marks have their own role-specific optical scales so each Ace
carries comparable ink and the fuller Heart does not crowd a court figure.
The Club follows the familiar traditional card form rather than an equilateral
trefoil: equal lower lobes sit wider and lower than the top lobe, a smaller
central boss joins the three, and a short flared stem finishes the mark. Its
required symmetry is bilateral, not three-fold rotational symmetry.
Generated suit pips are replaced with the correct SVG suit mark. Generated
frame segments are locally inpainted out while the figure is extracted, then
one continuous SVG frame is drawn behind the figure. The approved upper figure
is rotated exactly 180 degrees for the lower end, with a symmetric blended join
through the centre.
The assembly step also normalizes the generated figure envelope around the
card centre using uniform scaling only: K♣/K♦ use 0.95 and K♥/K♠ use 0.97.
Jacks and Queens remain at native scale. The resulting painted areas stay
within roughly five percent without distorting faces or garments. Club and
Spade field emblems receive a five-pixel optical shift away from the figure;
their mirrored lower marks are derived from the same coordinates.
## Generation settings
- Model: `qwen_image_2512_bf16_i8x.ckpt`
- Working size: 640×896
- Sampler: DPMPP2MTrailing
- Steps: 30
- Guidance: 4.0
- img2img strength: 0.68
The corresponding Heart card is the composition/style reference for every
non-Heart court. Run `tools/render_court.py --remaining` to create missing
renders without overwriting existing ones.
## Output sizes
No smallest production size has been chosen. The SVG cards scale freely; court
illustrations remain 640×896 raster artwork inside them. If a future use needs
large-format print, upscale or regenerate the courts for that real requirement.
Do not build alternate thumbnail art until the game actually needs it.
`masters/queen-hearts.svg` is an archived hand-vector experiment and is not
part of the current deck pipeline.
+263
View File
@@ -0,0 +1,263 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 500 700" width="500" height="700">
<title>Side Cards — Queen of Hearts (vector master)</title>
<desc>
Full-detail master. Card is 5:7 (500x700 user units); all geometry is
proportional, so it scales to any output size.
Construction: only the UPPER half of the court figure exists
(g#court-half). The lower half is a single &lt;use&gt; of it rotated
exactly 180 degrees about the card centre (250,350). Never draw the lower
half by hand — edit the upper half and the mirror follows, which is what
guarantees identical faces, hands, ornament and line weight.
Editable groups: frame, indices, veil, garments, ornament, props,
hair-back, face, hair-front, crown, keylines.
Palette is the six inks plus stock, defined once in the stylesheet below.
Change an ink there and it changes everywhere.
</desc>
<style>
/* ---- palette: the only place colour is defined ---- */
.ink { fill: #0e0d0d; } /* keyline black */
.red { fill: #a21b1e; }
.gold { fill: #b99a34; }
.blue { fill: #354c58; }
.skin { fill: #f0d2b6; }
.stock { fill: #fcfcfa; } /* card stock / veil highlight */
.s-ink { stroke: #0e0d0d; }
.s-gold { stroke: #b99a34; }
/* ---- line weights, proportional to the 500-unit card width ----
Main keyline 3.0 = 0.60% of card width, inside the 0.47-0.62%
measured on the concept family. Detail 1.6 = 0.32%. */
.k { stroke: #0e0d0d; stroke-width: 3.0; stroke-linejoin: round;
stroke-linecap: round; }
.k-fine { stroke: #0e0d0d; stroke-width: 1.6; stroke-linejoin: round;
stroke-linecap: round; fill: none; }
.k-hair { stroke: #0e0d0d; stroke-width: 1.1; stroke-linecap: round;
fill: none; }
.no-fill { fill: none; }
</style>
<defs>
<!-- Upper half only. The clip travels with the group, so the rotated
instance is clipped to the lower half automatically. -->
<clipPath id="clip-upper">
<rect x="0" y="0" width="500" height="350"/>
</clipPath>
<!-- suit symbol, drawn at origin, nominal 40 units tall -->
<g id="suit-heart">
<path class="red" d="M0,15 C-19,-2 -14,-21 0,-12 C14,-21 19,-2 0,15 Z"/>
</g>
<!-- rank glyph, geometric so it needs no font at render time -->
<g id="glyph-q">
<circle class="no-fill s-ink" cx="0" cy="0" r="12.5" stroke-width="5.5"
style="stroke:#a21b1e"/>
<path d="M5,7 L15,19" style="stroke:#a21b1e;stroke-width:5.5;
stroke-linecap:round" fill="none"/>
</g>
<!-- corner index: rank over pip, sits outside the inner panel -->
<g id="index">
<use xlink:href="#glyph-q" href="#glyph-q" x="52" y="60"/>
<use xlink:href="#suit-heart" href="#suit-heart" x="52" y="104"
transform="translate(0,0)"/>
</g>
<!-- ================= COURT FIGURE — UPPER HALF ================= -->
<g id="court-half" clip-path="url(#clip-upper)">
<!-- veil: two cloth panels falling behind the hair to the seam.
Kept as separate open panels, not a closed silhouette. -->
<g id="veil">
<path class="stock k" d="M228,168
C200,176 182,200 174,232
C168,258 164,300 160,352
L196,352 C198,306 202,266 210,238
C216,214 224,190 236,176 Z"/>
<path class="stock k" d="M272,168
C300,176 318,200 326,232
C332,258 336,300 340,352
L304,352 C302,306 298,266 290,238
C284,214 276,190 264,176 Z"/>
<path class="k-fine" d="M186,244 C180,282 176,318 174,352"/>
<path class="k-fine" d="M314,244 C320,282 324,318 326,352"/>
</g>
<!-- garments: robe, mantle, sleeve, central placket -->
<g id="garments">
<!-- neck sits under the collar -->
<path class="skin k" d="M236,242 L264,242 L264,272
C256,278 244,278 236,272 Z"/>
<!-- red robe body, flaring to the panel edges at the seam -->
<path class="red k" d="M250,286
C204,286 168,306 146,332
C136,342 130,348 127,352
L373,352
C370,348 364,342 354,332
C332,306 296,286 250,286 Z"/>
<!-- blue mantle over the outer shoulders -->
<path class="blue k" d="M196,300 C172,314 150,334 133,352
L192,352 C196,332 204,314 214,300 Z"/>
<path class="blue k" d="M304,300 C328,314 350,334 367,352
L308,352 C304,332 296,314 286,300 Z"/>
<!-- left sleeve, carrying the arm out to the flower hand -->
<path class="blue k" d="M210,292 C188,296 168,306 157,318
C168,328 186,330 202,322 C206,310 208,300 210,292 Z"/>
<!-- gold placket down the centre -->
<path class="gold k" d="M228,292 L272,292 L282,352 L218,352 Z"/>
<!-- collar -->
<path class="gold k" d="M226,268 C238,280 262,280 274,268
L288,290 C266,306 234,306 212,290 Z"/>
</g>
<!-- ornament: jewels and filigree. Full detail — do not thin this out
for small sizes; make a separate thumbnail variant instead. -->
<g id="ornament">
<!-- placket jewels -->
<circle class="red k-fine" cx="250" cy="308" r="9"/>
<circle class="blue k-fine" cx="250" cy="330" r="7.5"/>
<circle class="red k-fine" cx="250" cy="348" r="6"/>
<!-- collar beading -->
<circle class="stock k-hair" cx="230" cy="283" r="3.4"/>
<circle class="stock k-hair" cx="242" cy="290" r="3.4"/>
<circle class="stock k-hair" cx="258" cy="290" r="3.4"/>
<circle class="stock k-hair" cx="270" cy="283" r="3.4"/>
<!-- mantle folds -->
<path class="k-fine" d="M190,314 C180,328 170,340 160,352"/>
<path class="k-fine" d="M206,312 C198,326 192,340 188,352"/>
<path class="k-fine" d="M310,314 C320,328 330,340 340,352"/>
<path class="k-fine" d="M294,312 C302,326 308,340 312,352"/>
<!-- robe diaper pattern -->
<path class="gold k-hair" d="M212,322 L220,332 L212,342 L204,332 Z"/>
<path class="gold k-hair" d="M288,322 L296,332 L288,342 L280,332 Z"/>
<path class="gold k-hair" d="M196,344 L203,352 L189,352 Z"/>
<path class="gold k-hair" d="M304,344 L311,352 L297,352 Z"/>
</g>
<!-- props: the Queen's flower, held viewer-left.
Petals are separated by radial cuts rather than overlapping stroked
circles, so the outline stays clean at every scale. -->
<g id="props">
<!-- hand emerging from the sleeve -->
<path class="skin k" d="M152,302 C162,296 173,301 174,311
C175,322 165,330 155,327 C145,324 143,308 152,302 Z"/>
<path class="k-hair" d="M157,308 L169,307 M157,314 L171,313
M159,320 L170,319"/>
<!-- stem and leaf -->
<path class="s-gold" d="M154,302 L146,270" stroke-width="3.4"
fill="none" stroke-linecap="round"/>
<path class="blue k-hair" d="M150,288 C140,285 135,277 137,271
C143,271 149,277 151,285 Z"/>
<!-- rosette -->
<g transform="translate(144,256)">
<circle class="red k" cx="0" cy="0" r="18"/>
<path class="k-hair" d="M0,-18 L0,-6 M17,-6 L6,-2
M11,15 L4,5 M-11,15 L-4,5 M-17,-6 L-6,-2"/>
<circle class="gold k-fine" cx="0" cy="0" r="6.5"/>
</g>
</g>
<!-- hair behind the face -->
<g id="hair-back">
<path class="ink k" d="M250,150
C212,150 192,178 190,216
C189,242 196,268 206,286
L218,262 C210,226 214,190 232,172
C240,164 260,164 268,172
C286,190 290,226 282,262
L294,286 C304,268 311,242 310,216
C308,178 288,150 250,150 Z"/>
</g>
<!-- face -->
<g id="face">
<ellipse class="skin k" cx="250" cy="208" rx="38" ry="45"/>
<!-- brows -->
<path class="k-fine" d="M232,195 C237,190 245,190 249,194"/>
<path class="k-fine" d="M268,195 C263,190 255,190 251,194"/>
<!-- eyes: almond, lid line heavier than the lower lash -->
<path class="k-fine" d="M234,206 C238,201 246,201 250,206
C246,210 238,210 234,206 Z"/>
<path class="k-fine" d="M250,206 C254,201 262,201 266,206
C262,210 254,210 250,206 Z"/>
<circle class="ink" cx="242" cy="206" r="2.4"/>
<circle class="ink" cx="258" cy="206" r="2.4"/>
<!-- nose -->
<path class="k-fine" d="M250,212 L247,226 C248,228 252,228 253,226"/>
<!-- mouth -->
<path class="red k-fine" d="M243,236 C246,233 254,233 257,236
C254,240 246,240 243,236 Z"/>
<!-- earrings -->
<circle class="gold k-hair" cx="213" cy="216" r="4.5"/>
<circle class="gold k-hair" cx="287" cy="216" r="4.5"/>
</g>
<!-- hair falling in front of the shoulders -->
<g id="hair-front">
<path class="ink k" d="M216,198 C208,216 208,242 214,264
C218,278 218,290 214,300
C205,290 200,268 200,242 C200,220 206,204 216,198 Z"/>
<path class="ink k" d="M284,198 C292,216 292,242 286,264
C282,278 282,290 286,300
C295,290 300,268 300,242 C300,220 294,204 284,198 Z"/>
<path class="k-hair" d="M211,216 C206,234 207,256 212,272"/>
<path class="k-hair" d="M289,216 C294,234 293,256 288,272"/>
</g>
<!-- crown -->
<g id="crown">
<path class="gold k" d="M196,152 L304,152 L300,170 L200,170 Z"/>
<path class="gold k" d="M196,152 L204,114 L222,144 L250,102
L278,144 L296,114 L304,152 Z"/>
<circle class="red k-fine" cx="204" cy="118" r="5.5"/>
<circle class="blue k-fine" cx="250" cy="108" r="6.5"/>
<circle class="red k-fine" cx="296" cy="118" r="5.5"/>
<circle class="blue k-hair" cx="224" cy="161" r="4.5"/>
<circle class="red k-hair" cx="250" cy="161" r="4.5"/>
<circle class="blue k-hair" cx="276" cy="161" r="4.5"/>
</g>
<!-- interior linework drawn on top of the fills -->
<g id="keylines">
<path class="k-fine" d="M228,292 L218,352 M272,292 L282,352"/>
<path class="k-fine" d="M214,302 C208,320 204,338 202,352"/>
<path class="k-fine" d="M286,302 C292,320 296,338 298,352"/>
</g>
</g>
</defs>
<!-- ============================ CARD ============================ -->
<g id="card">
<rect id="stock" class="stock" x="0" y="0" width="500" height="700" rx="26"/>
<g id="frame" fill="none">
<rect class="k" x="10" y="10" width="480" height="680" rx="20"
stroke-width="2.2"/>
<rect class="k" x="86" y="88" width="328" height="524" rx="6"/>
<rect class="k-fine" x="92" y="94" width="316" height="512" rx="4"/>
</g>
<!-- upper half, then the same artwork rotated 180 about the card centre -->
<g id="figure">
<use xlink:href="#court-half" href="#court-half"/>
<use xlink:href="#court-half" href="#court-half"
transform="rotate(180 250 350)"/>
</g>
<g id="seam">
<path class="k-fine" d="M92,350 L408,350"/>
</g>
<g id="indices">
<use xlink:href="#index" href="#index"/>
<use xlink:href="#index" href="#index" transform="rotate(180 250 350)"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB