feat(combat): rebuild the combat screen around the reference layout
Move both health bars to a status row at the top of the scene with a circular portrait beside each, and place full-body sprites for the player and the monster standing on the location background instead of square portraits. The Angriff action now uses the ornate HUD frame art, with the keybind in the frame's own tab. Sprite and icon derivatives are keyed by monster key so both seeded monsters resolve; the Aschenratte body art still carries its original backdrop until a cut-out version replaces it at the same path.
This commit is contained in:
@@ -1,24 +1,27 @@
|
||||
:host {
|
||||
display: block;
|
||||
min-block-size: 100%;
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
.combat-page {
|
||||
.combat {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) clamp(13rem, 17vw, 17rem);
|
||||
gap: var(--ar-space-4);
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
.combat-page__scene {
|
||||
/* ---------- stage ---------- */
|
||||
|
||||
.combat__stage {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
align-items: end;
|
||||
grid-template-rows: auto minmax(0, 1fr) auto;
|
||||
gap: var(--ar-space-4);
|
||||
min-block-size: clamp(18rem, 40vh, 26rem);
|
||||
padding: var(--ar-space-5);
|
||||
min-block-size: 26rem;
|
||||
padding: var(--ar-space-4);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--ar-border);
|
||||
background-color: #151718;
|
||||
background-color: var(--ar-bg);
|
||||
background-image: url('/images/backgrounds/Aschestrasse.png');
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
@@ -31,201 +34,370 @@
|
||||
url('/images/backgrounds/runtime/Aschestrasse-960.jpg') type('image/jpeg') 1x
|
||||
)
|
||||
) {
|
||||
.combat-page__scene {
|
||||
.combat__stage {
|
||||
background-image: image-set(
|
||||
url('/images/backgrounds/runtime/Aschestrasse-960.jpg') type('image/jpeg') 1x
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.combat-page__scene::before {
|
||||
.combat__stage::before {
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
inset: 0;
|
||||
content: '';
|
||||
background: linear-gradient(180deg, rgb(4 6 8 / 0.15), rgb(4 6 8 / 0.6));
|
||||
background:
|
||||
linear-gradient(180deg, rgb(4 6 8 / 0.72) 0%, rgb(4 6 8 / 0.1) 26%, rgb(4 6 8 / 0.66) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.combat-page__combatant {
|
||||
/* ---------- combatant status ---------- */
|
||||
|
||||
.combat__status {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: 2;
|
||||
display: grid;
|
||||
gap: var(--ar-space-2);
|
||||
justify-items: center;
|
||||
text-align: center;
|
||||
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
||||
align-items: start;
|
||||
gap: var(--ar-space-4);
|
||||
}
|
||||
|
||||
.combat-page__combatant--player {
|
||||
justify-self: start;
|
||||
.fighter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--ar-space-3);
|
||||
min-inline-size: 0;
|
||||
}
|
||||
|
||||
.combat-page__combatant--monster {
|
||||
justify-self: end;
|
||||
.fighter--monster {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.combat-page__portrait {
|
||||
inline-size: clamp(6rem, 14vw, 10rem);
|
||||
block-size: clamp(6rem, 14vw, 10rem);
|
||||
.fighter__icon {
|
||||
flex: 0 0 auto;
|
||||
inline-size: clamp(2.75rem, 5vw, 3.75rem);
|
||||
block-size: clamp(2.75rem, 5vw, 3.75rem);
|
||||
object-fit: cover;
|
||||
border: 2px solid var(--ar-border-highlight);
|
||||
border-radius: var(--ar-radius-md);
|
||||
box-shadow: var(--ar-shadow-raised);
|
||||
border-radius: 50%;
|
||||
box-shadow:
|
||||
0 0 0 1px var(--ar-border-highlight),
|
||||
0 0.3rem 0.9rem rgb(0 0 0 / 0.8);
|
||||
}
|
||||
|
||||
.combat-page__info {
|
||||
.fighter__meter {
|
||||
display: grid;
|
||||
gap: var(--ar-space-1);
|
||||
min-inline-size: 10rem;
|
||||
color: var(--ar-text);
|
||||
text-shadow: 0 0.1rem 0.4rem rgb(0 0 0 / 0.85);
|
||||
gap: 0.3rem;
|
||||
min-inline-size: 0;
|
||||
flex: 1 1 auto;
|
||||
max-inline-size: 22rem;
|
||||
}
|
||||
|
||||
.combat-page__name {
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-size: 1.15rem;
|
||||
.fighter--monster .fighter__meter {
|
||||
justify-items: end;
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.combat-page__level {
|
||||
color: var(--ar-gold);
|
||||
font-size: var(--ar-font-sm);
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.combat-page__hp {
|
||||
display: grid;
|
||||
gap: var(--ar-space-1);
|
||||
font-size: var(--ar-font-sm);
|
||||
}
|
||||
|
||||
.combat-page__hp-track {
|
||||
display: block;
|
||||
inline-size: 100%;
|
||||
block-size: 0.5rem;
|
||||
.fighter__name {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--ar-border);
|
||||
border-radius: var(--ar-radius-sm);
|
||||
background: rgb(0 0 0 / 0.5);
|
||||
}
|
||||
|
||||
.combat-page__hp-value {
|
||||
display: block;
|
||||
block-size: 100%;
|
||||
background: var(--ar-success);
|
||||
}
|
||||
|
||||
.combat-page__hp-value--monster {
|
||||
background: var(--ar-danger);
|
||||
}
|
||||
|
||||
.combat-page__round {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
align-self: start;
|
||||
justify-self: center;
|
||||
padding: var(--ar-space-1) var(--ar-space-3);
|
||||
border: 1px solid var(--ar-border-highlight);
|
||||
border-radius: var(--ar-radius-sm);
|
||||
color: var(--ar-gold);
|
||||
background: rgb(9 11 13 / 0.75);
|
||||
color: var(--ar-text);
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-size: clamp(0.95rem, 1.5vw, 1.15rem);
|
||||
letter-spacing: 0.02em;
|
||||
text-overflow: ellipsis;
|
||||
text-shadow: 0 0.1rem 0.5rem rgb(0 0 0 / 0.95);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.fighter__level {
|
||||
color: var(--ar-gold);
|
||||
font-family: system-ui, sans-serif;
|
||||
font-size: var(--ar-font-sm);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.combat-page__actions {
|
||||
/* ---------- hp bars ---------- */
|
||||
|
||||
.bar {
|
||||
position: relative;
|
||||
display: block;
|
||||
inline-size: 100%;
|
||||
block-size: 1.25rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--ar-border);
|
||||
background: linear-gradient(180deg, rgb(0 0 0 / 0.85), rgb(0 0 0 / 0.6));
|
||||
box-shadow: inset 0 0 0.6rem rgb(0 0 0 / 0.9);
|
||||
}
|
||||
|
||||
.bar__fill {
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
inset-block: 0;
|
||||
inset-inline-start: 0;
|
||||
display: block;
|
||||
background: linear-gradient(180deg, #d0564a, #8e2b23);
|
||||
}
|
||||
|
||||
.bar--monster .bar__fill {
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: 0;
|
||||
}
|
||||
|
||||
.bar__text {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.combat-page__attack {
|
||||
padding: var(--ar-space-3) var(--ar-space-6);
|
||||
border: 1px solid var(--ar-border-highlight);
|
||||
border-radius: var(--ar-radius-sm);
|
||||
block-size: 100%;
|
||||
place-items: center;
|
||||
color: var(--ar-text);
|
||||
background: linear-gradient(180deg, #263b4b, #17232d);
|
||||
cursor: pointer;
|
||||
font-size: var(--ar-font-sm);
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: 0.04em;
|
||||
text-shadow: 0 0.05rem 0.25rem rgb(0 0 0 / 1);
|
||||
}
|
||||
|
||||
/* ---------- round marker ---------- */
|
||||
|
||||
.combat__round {
|
||||
margin: 0;
|
||||
align-self: center;
|
||||
padding: var(--ar-space-1) var(--ar-space-5);
|
||||
border-block: 1px solid var(--ar-border-highlight);
|
||||
color: var(--ar-gold);
|
||||
background: linear-gradient(90deg, transparent, rgb(9 11 13 / 0.9) 18%, rgb(9 11 13 / 0.9) 82%, transparent);
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-size: 1.1rem;
|
||||
font-size: clamp(0.95rem, 1.4vw, 1.1rem);
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ---------- battlefield ---------- */
|
||||
|
||||
.combat__field {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
align-items: end;
|
||||
min-block-size: 0;
|
||||
}
|
||||
|
||||
.sprite {
|
||||
display: block;
|
||||
max-block-size: 100%;
|
||||
inline-size: auto;
|
||||
object-fit: contain;
|
||||
filter: drop-shadow(0 1rem 1.5rem rgb(0 0 0 / 0.75));
|
||||
}
|
||||
|
||||
.sprite--player {
|
||||
justify-self: start;
|
||||
block-size: clamp(11rem, 30vh, 19rem);
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.sprite--monster {
|
||||
justify-self: end;
|
||||
block-size: clamp(9rem, 24vh, 15rem);
|
||||
}
|
||||
|
||||
/* ---------- action bar ---------- */
|
||||
|
||||
.combat__actions {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
gap: var(--ar-space-3);
|
||||
min-block-size: clamp(6.5rem, 11vw, 8.5rem);
|
||||
}
|
||||
|
||||
.action {
|
||||
position: relative;
|
||||
inline-size: clamp(6.5rem, 11vw, 8.5rem);
|
||||
aspect-ratio: 1;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent url('/images/hud/runtime/fight-action-frame-360.png') center / 100% 100%
|
||||
no-repeat;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action__icon {
|
||||
position: absolute;
|
||||
inset-block-start: 32%;
|
||||
inset-inline-start: 50%;
|
||||
inline-size: 34%;
|
||||
translate: -50% -50%;
|
||||
border-radius: 50%;
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
.action__label {
|
||||
position: absolute;
|
||||
inset-block-start: 62%;
|
||||
inset-inline-start: 50%;
|
||||
translate: -50% -50%;
|
||||
color: var(--ar-text);
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-size: clamp(0.85rem, 1.2vw, 1rem);
|
||||
letter-spacing: 0.03em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.combat-page__attack:hover:not(:disabled) {
|
||||
border-color: #d6b26b;
|
||||
background: linear-gradient(180deg, #315067, #1a2c3a);
|
||||
.action__key {
|
||||
position: absolute;
|
||||
inset-block-start: 90%;
|
||||
inset-inline-start: 50%;
|
||||
translate: -50% -50%;
|
||||
color: var(--ar-text-muted);
|
||||
font-size: var(--ar-font-sm);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.combat-page__attack:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
.action:hover:not(:disabled) .action__label,
|
||||
.action:focus-visible .action__label {
|
||||
color: var(--ar-gold);
|
||||
}
|
||||
|
||||
.combat-page__result {
|
||||
.action:focus-visible {
|
||||
outline: 2px solid var(--ar-gold);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
.action:disabled {
|
||||
cursor: progress;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
/* ---------- outcome overlay ---------- */
|
||||
|
||||
.outcome {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
inset-block-start: 50%;
|
||||
inset-inline-start: 50%;
|
||||
display: grid;
|
||||
gap: var(--ar-space-2);
|
||||
max-inline-size: 30rem;
|
||||
justify-items: center;
|
||||
inline-size: min(26rem, 80%);
|
||||
padding: var(--ar-space-5);
|
||||
translate: -50% -50%;
|
||||
border: 1px solid var(--ar-border-highlight);
|
||||
background: var(--ar-panel);
|
||||
background: rgb(9 11 13 / 0.94);
|
||||
box-shadow: var(--ar-shadow-raised);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.combat-page__result h2 {
|
||||
.outcome p {
|
||||
margin: 0;
|
||||
color: var(--ar-text-muted);
|
||||
}
|
||||
|
||||
.outcome__title {
|
||||
margin: 0;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-size: 1.6rem;
|
||||
font-size: clamp(1.5rem, 3vw, 2rem);
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.combat-page__result--won h2 {
|
||||
color: var(--ar-success);
|
||||
.outcome--won .outcome__title {
|
||||
color: var(--ar-gold);
|
||||
}
|
||||
|
||||
.combat-page__result--lost h2 {
|
||||
.outcome--lost .outcome__title {
|
||||
color: var(--ar-danger);
|
||||
}
|
||||
|
||||
.combat-page__result-hint {
|
||||
color: var(--ar-text-muted);
|
||||
.outcome__hint {
|
||||
font-size: var(--ar-font-sm);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.combat-page__log {
|
||||
.outcome__button {
|
||||
margin-block-start: var(--ar-space-2);
|
||||
padding: var(--ar-space-2) var(--ar-space-5);
|
||||
border: 1px solid var(--ar-border-highlight);
|
||||
border-radius: var(--ar-radius-sm);
|
||||
color: var(--ar-text);
|
||||
background: linear-gradient(180deg, #23282c, #14181b);
|
||||
cursor: pointer;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.outcome__button:hover {
|
||||
border-color: var(--ar-gold);
|
||||
color: var(--ar-gold);
|
||||
}
|
||||
|
||||
/* ---------- combat log ---------- */
|
||||
|
||||
.combat__log {
|
||||
display: grid;
|
||||
gap: var(--ar-space-1);
|
||||
max-block-size: 16rem;
|
||||
padding: var(--ar-space-4);
|
||||
overflow-y: auto;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
min-block-size: 0;
|
||||
border: 1px solid var(--ar-border);
|
||||
background: var(--ar-panel-muted);
|
||||
box-shadow: var(--ar-shadow-raised);
|
||||
}
|
||||
|
||||
.combat-page__log-round {
|
||||
margin: var(--ar-space-2) 0 0;
|
||||
.combat__log-title {
|
||||
margin: 0;
|
||||
padding: var(--ar-space-3) var(--ar-space-4);
|
||||
border-block-end: 1px solid var(--ar-border);
|
||||
color: var(--ar-gold);
|
||||
font-size: var(--ar-font-sm);
|
||||
letter-spacing: 0.06em;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-size: 1.05rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.combat-page__log-entry {
|
||||
margin: 0;
|
||||
color: var(--ar-text-muted);
|
||||
.combat__log-body {
|
||||
padding: var(--ar-space-3) var(--ar-space-4) var(--ar-space-4);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.combat-page__loading,
|
||||
.combat-page__error {
|
||||
.combat__log-round {
|
||||
margin: var(--ar-space-4) 0 var(--ar-space-2);
|
||||
color: var(--ar-gold);
|
||||
font-size: var(--ar-font-sm);
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.combat__log-round:first-child {
|
||||
margin-block-start: 0;
|
||||
}
|
||||
|
||||
.combat__log-entry {
|
||||
margin: 0 0 var(--ar-space-1);
|
||||
padding-inline-start: var(--ar-space-3);
|
||||
border-inline-start: 2px solid var(--ar-danger);
|
||||
color: var(--ar-text-muted);
|
||||
font-size: var(--ar-font-sm);
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.combat__log-entry--player {
|
||||
border-inline-start-color: var(--ar-border-highlight);
|
||||
}
|
||||
|
||||
/* ---------- notices ---------- */
|
||||
|
||||
.combat__notice {
|
||||
grid-column: 1 / -1;
|
||||
padding: var(--ar-space-4);
|
||||
border: 1px solid var(--ar-border);
|
||||
background: var(--ar-panel);
|
||||
box-shadow: var(--ar-shadow-raised);
|
||||
}
|
||||
|
||||
.combat-page__error {
|
||||
.combat__notice--error {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -233,7 +405,7 @@
|
||||
border-color: var(--ar-danger);
|
||||
}
|
||||
|
||||
.combat-page__error button {
|
||||
.combat__notice--error button {
|
||||
flex: 0 0 auto;
|
||||
padding: var(--ar-space-2) var(--ar-space-3);
|
||||
border: 1px solid var(--ar-border-highlight);
|
||||
@@ -244,20 +416,64 @@
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.combat-page__hp-value {
|
||||
.bar__fill {
|
||||
transition: inline-size var(--ar-motion-base);
|
||||
}
|
||||
|
||||
.action__label {
|
||||
transition: color var(--ar-motion-fast);
|
||||
}
|
||||
}
|
||||
|
||||
@media (width < 720px) {
|
||||
.combat-page__scene {
|
||||
grid-template-columns: 1fr;
|
||||
justify-items: center;
|
||||
text-align: center;
|
||||
@media (width < 60rem) {
|
||||
:host,
|
||||
.combat {
|
||||
block-size: auto;
|
||||
}
|
||||
|
||||
.combat-page__combatant--player,
|
||||
.combat-page__combatant--monster {
|
||||
.combat {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.combat__stage {
|
||||
min-block-size: clamp(24rem, 55vh, 34rem);
|
||||
}
|
||||
|
||||
.combat__log {
|
||||
max-block-size: 18rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (width < 40rem) {
|
||||
.combat__status {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: var(--ar-space-2);
|
||||
}
|
||||
|
||||
.combat__round {
|
||||
order: -1;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.fighter--monster {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.fighter--monster .fighter__meter {
|
||||
justify-items: start;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.bar--monster .bar__fill {
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: auto;
|
||||
}
|
||||
|
||||
.sprite--player {
|
||||
block-size: clamp(8rem, 22vh, 12rem);
|
||||
}
|
||||
|
||||
.sprite--monster {
|
||||
block-size: clamp(7rem, 18vh, 10rem);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user