Improved card design.
This commit is contained in:
@@ -3,6 +3,60 @@ import { createPortal } from 'react-dom'
|
|||||||
import type { Card } from '../types'
|
import type { Card } from '../types'
|
||||||
import { artFor } from '../petArt'
|
import { artFor } from '../petArt'
|
||||||
|
|
||||||
|
// The suit's "hat" — the trade-in symbol printed on the real cards, tinted to
|
||||||
|
// the suit's colour. Drawn as a tiny sun-hat SVG so it scales crisply.
|
||||||
|
const SUIT_HAT: Record<string, { fill: string; band: string }> = {
|
||||||
|
red: { fill: '#e5563f', band: '#b62c1f' },
|
||||||
|
blue: { fill: '#4d8ce3', band: '#2b5fb0' },
|
||||||
|
yellow: { fill: '#f2c24d', band: '#d9992f' },
|
||||||
|
}
|
||||||
|
|
||||||
|
function SuitHat({ suit }: { suit: string }) {
|
||||||
|
const c = SUIT_HAT[suit] ?? SUIT_HAT.yellow
|
||||||
|
return (
|
||||||
|
<svg className="card-hat" viewBox="0 0 28 18" aria-hidden>
|
||||||
|
<path
|
||||||
|
d="M7 12.5 Q7 3.5 14 3.5 Q21 3.5 21 12.5 Z"
|
||||||
|
fill={c.fill}
|
||||||
|
stroke="rgba(50,25,8,.45)"
|
||||||
|
strokeWidth="1"
|
||||||
|
/>
|
||||||
|
<path d="M7.4 11 Q14 13 20.6 11 L20.6 12.6 Q14 14.6 7.4 12.6 Z" fill={c.band} />
|
||||||
|
<ellipse
|
||||||
|
cx="14"
|
||||||
|
cy="13.4"
|
||||||
|
rx="12.6"
|
||||||
|
ry="3.7"
|
||||||
|
fill={c.fill}
|
||||||
|
stroke="rgba(50,25,8,.45)"
|
||||||
|
strokeWidth="1"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The tier shown as a die face (1–6 pips), like the real cards' corner marker.
|
||||||
|
const DIE_PIPS: Record<number, [number, number][]> = {
|
||||||
|
1: [[15, 15]],
|
||||||
|
2: [[9, 9], [21, 21]],
|
||||||
|
3: [[9, 9], [15, 15], [21, 21]],
|
||||||
|
4: [[9, 9], [21, 9], [9, 21], [21, 21]],
|
||||||
|
5: [[9, 9], [21, 9], [15, 15], [9, 21], [21, 21]],
|
||||||
|
6: [[9, 9], [21, 9], [9, 15], [21, 15], [9, 21], [21, 21]],
|
||||||
|
}
|
||||||
|
|
||||||
|
function TierDie({ tier }: { tier: number }) {
|
||||||
|
const pips = DIE_PIPS[tier] ?? DIE_PIPS[1]
|
||||||
|
return (
|
||||||
|
<svg className="card-die" viewBox="0 0 30 30" aria-hidden>
|
||||||
|
<rect x="1.5" y="1.5" width="27" height="27" rx="6.5" fill="#fff" stroke="#2c1c0e" strokeWidth="2" />
|
||||||
|
{pips.map(([cx, cy], i) => (
|
||||||
|
<circle key={i} cx={cx} cy={cy} r="2.9" fill="#2c1c0e" />
|
||||||
|
))}
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// useFitText shrinks the effect text until it fits its band, so long abilities
|
// useFitText shrinks the effect text until it fits its band, so long abilities
|
||||||
// (and the smaller battle cards) render in full instead of being clipped by
|
// (and the smaller battle cards) render in full instead of being clipped by
|
||||||
// the fixed card height. It never grows past the CSS size, only shrinks toward
|
// the fixed card height. It never grows past the CSS size, only shrinks toward
|
||||||
@@ -177,6 +231,9 @@ export function CardView({
|
|||||||
// Shrink long ability text to fit the (fixed-height) card, re-fitting when
|
// Shrink long ability text to fit the (fixed-height) card, re-fitting when
|
||||||
// the text or card size changes. Only the branch that renders attaches it.
|
// the text or card size changes. Only the branch that renders attaches it.
|
||||||
const effectRef = useFitText(`${size}|${card.effectText ?? ''}|${card.food ?? ''}`)
|
const effectRef = useFitText(`${size}|${card.effectText ?? ''}|${card.food ?? ''}`)
|
||||||
|
// Long single-word names (e.g. Calygreyhound) shrink to fit the name row
|
||||||
|
// instead of wrapping into a ragged stack.
|
||||||
|
const nameRef = useFitText(`${size}|${card.name}`)
|
||||||
const classes = [
|
const classes = [
|
||||||
'card',
|
'card',
|
||||||
`card-${size}`,
|
`card-${size}`,
|
||||||
@@ -206,23 +263,32 @@ export function CardView({
|
|||||||
onMouseLeave={preview ? undefined : () => setHover(null)}
|
onMouseLeave={preview ? undefined : () => setHover(null)}
|
||||||
>
|
>
|
||||||
{previewEl}
|
{previewEl}
|
||||||
<div className="card-top">
|
{/* Upper illustration: a stylised landscape with the pet as a sticker and
|
||||||
<span className="card-tier">{card.tier ? `T${card.tier}` : '·'}</span>
|
the red starburst attack badge floating at the top, like the real
|
||||||
{card.suit && <span className={`suit-dot suit-${card.suit}`} title={`${card.suit} suit`} />}
|
cards. */}
|
||||||
</div>
|
<div className="card-scene">
|
||||||
{/* Power sits in a spiky burst badge on its own centered row (pets only),
|
|
||||||
with any battle damage marker beside it, so it never overlaps the art,
|
|
||||||
name, or ability text. */}
|
|
||||||
{card.kind === 'pet' && (
|
{card.kind === 'pet' && (
|
||||||
<div className="card-combat">
|
|
||||||
<span className={`card-power ${bonus > 0 ? 'is-buffed' : ''}`}>{power}</span>
|
<span className={`card-power ${bonus > 0 ? 'is-buffed' : ''}`}>{power}</span>
|
||||||
{damage > 0 && !dead && <span className="card-damage">−{damage}</span>}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
{damage > 0 && !dead && <span className="card-damage">−{damage}</span>}
|
||||||
<div className="card-art" aria-hidden>
|
<div className="card-art" aria-hidden>
|
||||||
{artFor(card.name)}
|
{artFor(card.name)}
|
||||||
</div>
|
</div>
|
||||||
<div className="card-name">{card.name}</div>
|
</div>
|
||||||
|
{/* Lower panel: the suit hat, name, and tier die on one row, the ability
|
||||||
|
beneath — a white card in a rounded green frame. */}
|
||||||
|
<div className="card-panel">
|
||||||
|
<div className="card-panel-head">
|
||||||
|
{card.suit ? (
|
||||||
|
<SuitHat suit={card.suit} />
|
||||||
|
) : (
|
||||||
|
<span className="card-panel-slot" aria-hidden />
|
||||||
|
)}
|
||||||
|
<span className="card-name" ref={nameRef}>
|
||||||
|
{card.name}
|
||||||
|
</span>
|
||||||
|
{card.tier ? <TierDie tier={card.tier} /> : <span className="card-panel-slot" aria-hidden />}
|
||||||
|
</div>
|
||||||
<div className="card-effect" ref={effectRef}>
|
<div className="card-effect" ref={effectRef}>
|
||||||
{card.effectText
|
{card.effectText
|
||||||
? renderEffect(card.effectText)
|
? renderEffect(card.effectText)
|
||||||
@@ -234,6 +300,7 @@ export function CardView({
|
|||||||
? 'Takes 1 extra damage'
|
? 'Takes 1 extra damage'
|
||||||
: ''}
|
: ''}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{selected && <div className="card-check">✓</div>}
|
{selected && <div className="card-check">✓</div>}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
+219
-132
@@ -980,46 +980,36 @@ h3 {
|
|||||||
/* Thick printed stock: a warm parchment face, a soft ink border with an inner
|
/* Thick printed stock: a warm parchment face, a soft ink border with an inner
|
||||||
keyline, a physical shadow, and a lit sheen along the top. */
|
keyline, a physical shadow, and a lit sheen along the top. */
|
||||||
|
|
||||||
|
/* Cards echo the printed board-game cards: a chunky golden frame around a
|
||||||
|
landscape illustration up top and a green-framed rule panel below. */
|
||||||
.card {
|
.card {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 108px;
|
width: 114px;
|
||||||
height: 148px;
|
height: 154px;
|
||||||
background: linear-gradient(168deg, #fdf6e3, var(--cream) 45%, var(--cream-dark));
|
background: linear-gradient(165deg, #f8c451, #f0a828 55%, #e2941c);
|
||||||
border: 2px solid var(--cocoa);
|
|
||||||
border-radius: var(--card-radius);
|
border-radius: var(--card-radius);
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
padding: 5px;
|
||||||
padding: 7px 6px;
|
gap: 4px;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
inset 0 0 0 1.5px rgba(255, 255, 255, 0.55),
|
inset 0 0 0 1px rgba(255, 255, 255, 0.5),
|
||||||
inset 0 -8px 14px rgba(180, 140, 80, 0.22),
|
inset 0 0 0 2.5px rgba(150, 92, 18, 0.55),
|
||||||
var(--shadow-card);
|
var(--shadow-card);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
transition: transform 130ms cubic-bezier(0.34, 1.4, 0.5, 1), box-shadow 130ms ease;
|
transition: transform 130ms cubic-bezier(0.34, 1.4, 0.5, 1), box-shadow 130ms ease;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A faint printed sheen sweeping across the top of every card. */
|
|
||||||
.card::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 1.5px 1.5px auto 1.5px;
|
|
||||||
height: 42%;
|
|
||||||
border-radius: 11px 11px 40% 40%;
|
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.5), transparent);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-lg {
|
.card-lg {
|
||||||
width: 132px;
|
width: 140px;
|
||||||
height: 180px;
|
height: 190px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-sm {
|
.card-sm {
|
||||||
width: 84px;
|
width: 88px;
|
||||||
height: 116px;
|
height: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.is-clickable {
|
.card.is-clickable {
|
||||||
@@ -1029,8 +1019,8 @@ h3 {
|
|||||||
.card.is-clickable:hover {
|
.card.is-clickable:hover {
|
||||||
transform: translateY(-8px) rotate(-1.2deg);
|
transform: translateY(-8px) rotate(-1.2deg);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
inset 0 0 0 1.5px rgba(255, 255, 255, 0.6),
|
inset 0 0 0 1px rgba(255, 255, 255, 0.5),
|
||||||
inset 0 -8px 14px rgba(180, 140, 80, 0.22),
|
inset 0 0 0 2.5px rgba(150, 92, 18, 0.55),
|
||||||
0 18px 30px -8px rgba(20, 12, 4, 0.6),
|
0 18px 30px -8px rgba(20, 12, 4, 0.6),
|
||||||
0 4px 8px rgba(20, 12, 4, 0.4);
|
0 4px 8px rgba(20, 12, 4, 0.4);
|
||||||
}
|
}
|
||||||
@@ -1040,8 +1030,8 @@ h3 {
|
|||||||
outline-offset: 1px;
|
outline-offset: 1px;
|
||||||
transform: translateY(-8px);
|
transform: translateY(-8px);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
inset 0 0 0 1.5px rgba(255, 255, 255, 0.6),
|
inset 0 0 0 2.5px rgba(150, 92, 18, 0.55),
|
||||||
0 0 20px rgba(246, 201, 78, 0.45),
|
0 0 20px rgba(246, 201, 78, 0.5),
|
||||||
var(--shadow-card);
|
var(--shadow-card);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1053,109 +1043,188 @@ h3 {
|
|||||||
filter: grayscale(1);
|
filter: grayscale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-top {
|
/* --- Upper illustration: a stylised landscape --- */
|
||||||
width: 100%;
|
.card-scene {
|
||||||
display: flex;
|
position: relative;
|
||||||
/* Tier sits at the top-left, suit dot at the top-right. */
|
/* Fixed share of the card so the panel below (and the ability text inside it)
|
||||||
justify-content: space-between;
|
stays height-bounded — that's what lets useFitText shrink long abilities. */
|
||||||
align-items: center;
|
flex: 0 0 58%;
|
||||||
gap: 5px;
|
min-height: 0;
|
||||||
font-size: 0.72rem;
|
border-radius: 7px;
|
||||||
z-index: 1;
|
overflow: hidden;
|
||||||
min-height: 14px;
|
box-shadow: inset 0 0 0 1.5px rgba(90, 55, 15, 0.35);
|
||||||
}
|
|
||||||
|
|
||||||
/* Combat stats (power badge + battle damage marker) get their own centered
|
|
||||||
row just under the tier/suit line, so they never overlap the art or text. */
|
|
||||||
.card-combat {
|
|
||||||
z-index: 2;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 4px;
|
background:
|
||||||
margin: 2px 0 1px;
|
radial-gradient(120% 70% at 50% -8%, rgba(255, 255, 255, 0.4), transparent 55%),
|
||||||
|
linear-gradient(
|
||||||
|
180deg,
|
||||||
|
#c2e8f8 0%,
|
||||||
|
#a7dcf0 24%,
|
||||||
|
#74bf68 44%,
|
||||||
|
#57a44b 58%,
|
||||||
|
#e0a751 66%,
|
||||||
|
#d5942f 86%,
|
||||||
|
#57a44b 90%,
|
||||||
|
#4c9640 100%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-tier {
|
/* Distant mountain silhouette in the hills band. */
|
||||||
font-family: var(--font-display);
|
.card-scene::before {
|
||||||
font-size: 0.68rem;
|
|
||||||
color: rgba(74, 44, 20, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-suit {
|
|
||||||
font-size: 0.95rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The art sits in a soft printed halo so it reads as the card's hero. */
|
|
||||||
.card-art {
|
|
||||||
position: relative;
|
|
||||||
font-size: 2rem;
|
|
||||||
line-height: 1;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
margin-top: 1px;
|
|
||||||
z-index: 1;
|
|
||||||
filter: drop-shadow(0 3px 3px rgba(0, 0, 0, 0.28));
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-art::before {
|
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: -2%;
|
||||||
top: 52%;
|
right: -2%;
|
||||||
width: 2.5em;
|
top: 24%;
|
||||||
height: 2.5em;
|
height: 22%;
|
||||||
transform: translate(-50%, -50%);
|
background: linear-gradient(180deg, #6ea0c6, #5388b2);
|
||||||
border-radius: 50%;
|
clip-path: polygon(
|
||||||
background: radial-gradient(circle, rgba(246, 201, 78, 0.32), transparent 68%);
|
0 100%, 10% 45%, 20% 78%, 34% 22%, 47% 66%, 60% 30%, 73% 72%, 85% 40%, 100% 82%, 100% 100%
|
||||||
z-index: -1;
|
);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A row of rounded bush tops where the greenery begins. */
|
||||||
|
.card-scene::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 40%;
|
||||||
|
height: 12%;
|
||||||
|
background: radial-gradient(circle at 50% 100%, #3f8f3a 0 45%, transparent 47%) 0 0 / 21% 100% repeat-x;
|
||||||
|
opacity: 0.92;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The pet reads as a die-cut sticker: a white outline hugging the art. */
|
||||||
|
.card-art {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
line-height: 1;
|
||||||
|
transform: translateY(8%);
|
||||||
|
filter:
|
||||||
|
drop-shadow(0 0 1.5px #fff) drop-shadow(0 0 1.5px #fff) drop-shadow(0 0 1.5px #fff)
|
||||||
|
drop-shadow(0 3px 3px rgba(0, 0, 0, 0.35));
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-lg .card-art {
|
.card-lg .card-art {
|
||||||
font-size: 2.7rem;
|
font-size: 3.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-sm .card-art {
|
.card-sm .card-art {
|
||||||
font-size: 1.9rem;
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Lower rule panel --- */
|
||||||
|
.card-panel {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
background: #fbf7ee;
|
||||||
|
border: 2px solid #4e9a3f;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 3px 4px 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Small cards (no ability text) get a compact name plate and a taller scene. */
|
||||||
|
.card-sm .card-scene {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-sm .card-panel {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-panel-head {
|
||||||
|
display: grid;
|
||||||
|
/* minmax(0, 1fr) lets the name column shrink below its min-content so a long
|
||||||
|
name wraps instead of shoving the tier die out past the card edge. */
|
||||||
|
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
border-bottom: 1.5px solid rgba(78, 154, 63, 0.4);
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-hat {
|
||||||
|
width: 20px;
|
||||||
|
height: 13px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-die {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
display: block;
|
||||||
|
justify-self: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-panel-slot {
|
||||||
|
display: block;
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-lg .card-hat {
|
||||||
|
width: 23px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-lg .card-die,
|
||||||
|
.card-lg .card-panel-slot {
|
||||||
|
width: 17px;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-sm .card-hat {
|
||||||
|
width: 16px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-sm .card-die,
|
||||||
|
.card-sm .card-panel-slot {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-name {
|
.card-name {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-size: 0.84rem;
|
font-size: 0.78rem;
|
||||||
line-height: 1.05;
|
line-height: 1.05;
|
||||||
margin-top: 3px;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
z-index: 1;
|
|
||||||
color: var(--cocoa);
|
color: var(--cocoa);
|
||||||
/* Always center the name — including when a long name wraps to two lines, so
|
|
||||||
the second line stays centered instead of drifting off to one side. */
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
min-width: 0;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
/* Cap the name at ~two lines; useFitText shrinks longer names to fit. */
|
||||||
|
max-height: 2.1em;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-lg .card-name {
|
.card-lg .card-name {
|
||||||
font-size: 0.94rem;
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-sm .card-name {
|
||||||
|
font-size: 0.66rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-effect {
|
.card-effect {
|
||||||
font-size: 0.55rem;
|
font-size: 0.52rem;
|
||||||
line-height: 1.2;
|
line-height: 1.18;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--ink-soft);
|
color: var(--ink-soft);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 2px 3px 0;
|
padding: 2px 1px 0;
|
||||||
z-index: 1;
|
/* Grow to fill the panel and center short abilities; long ones top-align so
|
||||||
/* Grow into the space between the name and the power badge and center the
|
the leading words are never the clipped ones. */
|
||||||
text there, so long effects use the whole middle band instead of being
|
|
||||||
clipped just under the name. */
|
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
/* Stack multiple abilities (e.g. Squirrel's Buy and Sell) vertically rather
|
|
||||||
than side by side. */
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
/* Center short text in the band, but fall back to top-aligned when the text
|
|
||||||
is taller than the band, so the leading words are never the ones clipped. */
|
|
||||||
align-items: safe center;
|
align-items: safe center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -1167,7 +1236,7 @@ h3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card-lg .card-effect {
|
.card-lg .card-effect {
|
||||||
font-size: 0.63rem;
|
font-size: 0.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-sm .card-effect {
|
.card-sm .card-effect {
|
||||||
@@ -1200,75 +1269,89 @@ h3 {
|
|||||||
background: radial-gradient(circle at 35% 28%, #ffdd6b, #e6ac1f);
|
background: radial-gradient(circle at 35% 28%, #ffdd6b, #e6ac1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The power badge is a fiery starburst — like a little explosion — carrying the
|
/* The power badge is a red starburst floating at the top of the illustration,
|
||||||
pet's attack. The spikes are cut with clip-path, so the drop shadow lives on
|
like a little explosion carrying the pet's attack. The spikes are cut with
|
||||||
`filter` (a box-shadow would be clipped away with the corners). */
|
clip-path, so the drop shadow lives on `filter`. */
|
||||||
.card-power {
|
.card-power {
|
||||||
|
position: absolute;
|
||||||
|
top: 4%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
z-index: 3;
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
background: radial-gradient(circle at 38% 30%, #ffcf6b 4%, var(--coral) 42%, var(--coral-dark));
|
background: radial-gradient(circle at 40% 30%, #ff8a6b 2%, #e23b28 44%, #bd2716);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-shadow: 0 1px 2px rgba(120, 45, 5, 0.7);
|
-webkit-text-stroke: 0.5px rgba(120, 20, 5, 0.85);
|
||||||
width: 32px;
|
text-shadow: 0 1px 1px rgba(120, 20, 5, 0.8);
|
||||||
height: 32px;
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
font-size: 0.9rem;
|
font-size: 0.92rem;
|
||||||
clip-path: polygon(
|
clip-path: polygon(
|
||||||
50% 0%, 61% 18%, 82% 12%, 78% 34%, 100% 43%, 83% 58%,
|
50% 0%, 61% 18%, 82% 12%, 78% 34%, 100% 43%, 83% 58%,
|
||||||
93% 79%, 70% 76%, 62% 98%, 50% 82%, 38% 98%, 30% 76%,
|
93% 79%, 70% 76%, 62% 98%, 50% 82%, 38% 98%, 30% 76%,
|
||||||
7% 79%, 17% 58%, 0% 43%, 22% 34%, 18% 12%, 39% 18%
|
7% 79%, 17% 58%, 0% 43%, 22% 34%, 18% 12%, 39% 18%
|
||||||
);
|
);
|
||||||
filter: drop-shadow(0 2px 2px rgba(20, 12, 4, 0.5));
|
filter: drop-shadow(0 1.5px 2px rgba(20, 12, 4, 0.55));
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-power.is-buffed {
|
.card-power.is-buffed {
|
||||||
background: radial-gradient(circle at 38% 30%, #c9ffd4 4%, #4fd07f 42%, #1f9e55);
|
background: radial-gradient(circle at 40% 30%, #c9ffd4 4%, #4fd07f 42%, #1f9e55);
|
||||||
text-shadow: 0 1px 2px rgba(15, 60, 30, 0.7);
|
-webkit-text-stroke: 0.5px rgba(15, 60, 30, 0.85);
|
||||||
|
text-shadow: 0 1px 1px rgba(15, 60, 30, 0.7);
|
||||||
filter: drop-shadow(0 0 5px rgba(80, 220, 120, 0.75));
|
filter: drop-shadow(0 0 5px rgba(80, 220, 120, 0.75));
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-lg .card-power {
|
.card-lg .card-power {
|
||||||
width: 37px;
|
width: 35px;
|
||||||
height: 37px;
|
height: 35px;
|
||||||
font-size: 1.02rem;
|
font-size: 1.02rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-sm .card-power {
|
.card-sm .card-power {
|
||||||
width: 27px;
|
width: 24px;
|
||||||
height: 27px;
|
height: 24px;
|
||||||
font-size: 0.76rem;
|
font-size: 0.74rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-damage {
|
.card-damage {
|
||||||
|
position: absolute;
|
||||||
|
top: 5%;
|
||||||
|
right: 5%;
|
||||||
|
z-index: 3;
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: linear-gradient(180deg, #e85c49, var(--red));
|
background: linear-gradient(180deg, #e85c49, var(--red));
|
||||||
border: 1.5px solid rgba(120, 20, 10, 0.4);
|
border: 1.5px solid rgba(120, 20, 10, 0.4);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 2px 7px;
|
padding: 1px 6px;
|
||||||
font-size: 0.8rem;
|
font-size: 0.72rem;
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Food cards get a rosy stock so they read apart from pets at a glance. */
|
/* Food cards swap the golden frame for a warm terracotta one, ailments a cold
|
||||||
|
violet one, so the three kinds read apart at a glance. */
|
||||||
.card-food {
|
.card-food {
|
||||||
background: linear-gradient(168deg, #fff0ea, #ffe0d1 55%, #ffceba);
|
background: linear-gradient(165deg, #f3a67a, #e07f4f 55%, #cf6a3a);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-food::before {
|
.card-food .card-panel {
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.6), transparent);
|
border-color: #c96a3a;
|
||||||
}
|
|
||||||
|
|
||||||
.card-food .card-effect {
|
|
||||||
color: #8a3320;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-food .card-effect,
|
||||||
.card-food .card-name {
|
.card-food .card-name {
|
||||||
color: #8a3320;
|
color: #8a3320;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-food .card-art::before {
|
.card-ailment .card-panel {
|
||||||
background: radial-gradient(circle, rgba(255, 140, 100, 0.28), transparent 68%);
|
border-color: #6f57b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-ailment .card-effect,
|
||||||
|
.card-ailment .card-name {
|
||||||
|
color: #45308a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-check {
|
.card-check {
|
||||||
@@ -1402,13 +1485,10 @@ h3 {
|
|||||||
width: fit-content;
|
width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unicorn ailment cards: a cold, spectral palette distinct from foods/pets. */
|
/* Unicorn ailment cards: a cold violet frame (panel + text colours are set
|
||||||
|
with the other card-kind overrides above). */
|
||||||
.card-ailment {
|
.card-ailment {
|
||||||
background: linear-gradient(168deg, #e9e6f7, #cfc7ec 55%, #b3a8dd);
|
background: linear-gradient(165deg, #b9a6e6, #9a83d9 55%, #7d64c6);
|
||||||
}
|
|
||||||
.card-ailment .card-effect,
|
|
||||||
.card-ailment .card-name {
|
|
||||||
color: #45308a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ailment badges pinned to a battle unit. */
|
/* Ailment badges pinned to a battle unit. */
|
||||||
@@ -2161,7 +2241,7 @@ h3 {
|
|||||||
shrinking the decorative art; useFitText then keeps the text at a larger
|
shrinking the decorative art; useFitText then keeps the text at a larger
|
||||||
size before it has to shrink to fit. */
|
size before it has to shrink to fit. */
|
||||||
.battle-unit .card-art {
|
.battle-unit .card-art {
|
||||||
font-size: 1.5rem;
|
font-size: 1.95rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A pet flips face-up off its deck: it starts over the stack (outer edge) still
|
/* A pet flips face-up off its deck: it starts over the stack (outer edge) still
|
||||||
@@ -2666,6 +2746,13 @@ h3 {
|
|||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Keep the illustration a healthy size while the panel grows to fit the full,
|
||||||
|
unclipped ability text. */
|
||||||
|
.card-magnify .card-scene {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
height: 104px;
|
||||||
|
}
|
||||||
|
|
||||||
.card-magnify .card-effect {
|
.card-magnify .card-effect {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
|||||||
Reference in New Issue
Block a user