397 lines
8.6 KiB
SCSS
397 lines
8.6 KiB
SCSS
:host {
|
|
display: block;
|
|
block-size: 100%;
|
|
}
|
|
|
|
/* Fits the viewport instead of growing it, so the bag scrolls inside its own
|
|
panel rather than dragging the whole screen down. Same measure the combat
|
|
stage uses for the shell chrome above and below. */
|
|
.inventory-page {
|
|
display: flex;
|
|
flex-direction: column;
|
|
block-size: max(34rem, calc(100dvh - 12rem));
|
|
min-block-size: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.inventory-page__title {
|
|
margin: 0 0 var(--ar-space-4);
|
|
color: var(--ar-text);
|
|
font-family: Georgia, 'Times New Roman', serif;
|
|
font-size: clamp(1.5rem, 2.6vw, 2rem);
|
|
font-weight: 400;
|
|
letter-spacing: 0.04em;
|
|
text-shadow: 0 0.1rem 0.6rem rgb(0 0 0 / 0.8);
|
|
}
|
|
|
|
/* Three rails: what you wear, what you carry, what you are looking at. */
|
|
.inventory-page__columns {
|
|
display: grid;
|
|
flex: 1 1 auto;
|
|
grid-template-columns: minmax(18rem, 21rem) minmax(0, 1fr) minmax(16rem, 19rem);
|
|
gap: var(--ar-space-4);
|
|
align-items: stretch;
|
|
min-block-size: 0;
|
|
}
|
|
|
|
/* The doll takes the slack; the derived values sit under it like a plate. */
|
|
.inventory-page__rail {
|
|
display: grid;
|
|
grid-template-rows: 1fr auto;
|
|
gap: var(--ar-space-4);
|
|
min-block-size: 0;
|
|
}
|
|
|
|
/* Panel chrome (.ar-panel) lives in styles.scss — every screen shares it. */
|
|
|
|
.panel--doll {
|
|
display: grid;
|
|
grid-template-rows: auto 1fr;
|
|
min-block-size: 0;
|
|
}
|
|
|
|
/* Title, cells, then the count pinned to the bottom edge. */
|
|
.panel--bag {
|
|
display: grid;
|
|
grid-template-rows: auto auto 1fr;
|
|
min-block-size: 0;
|
|
}
|
|
|
|
/* ---------- paper doll ---------- */
|
|
|
|
.doll {
|
|
display: grid;
|
|
grid-template-columns: auto minmax(3.5rem, 1fr) auto;
|
|
grid-template-rows: minmax(0, 1fr) auto;
|
|
gap: var(--ar-space-2) var(--ar-space-3);
|
|
min-block-size: 0;
|
|
}
|
|
|
|
.doll__column {
|
|
display: grid;
|
|
grid-row: 1;
|
|
gap: var(--ar-space-3);
|
|
align-content: center;
|
|
}
|
|
|
|
/* The same warrior that fights on the combat screen stands here wearing the
|
|
result. Frame 0 of the six-frame attack sheet is the resting stance; the box
|
|
is kept square so that frame lands at its own proportions and never smears. */
|
|
.doll__figure {
|
|
grid-row: 1;
|
|
grid-column: 2;
|
|
z-index: 0;
|
|
place-self: center;
|
|
aspect-ratio: 1;
|
|
/* Wider than its column: the character stands behind the sockets rather than
|
|
squeezed between them, as in the concept. */
|
|
inline-size: 165%;
|
|
max-block-size: 100%;
|
|
pointer-events: none;
|
|
background-image: url('/images/combat/sprites/warrior-attack-sheet-384.png');
|
|
background-repeat: no-repeat;
|
|
background-position: left center;
|
|
background-size: 600% 100%;
|
|
filter: drop-shadow(0 0.4rem 0.9rem rgb(0 0 0 / 0.75));
|
|
}
|
|
|
|
.doll__below {
|
|
grid-row: 2;
|
|
grid-column: 2;
|
|
justify-self: center;
|
|
}
|
|
|
|
.socket {
|
|
position: relative;
|
|
z-index: 1;
|
|
display: grid;
|
|
gap: 0.15rem;
|
|
justify-items: center;
|
|
}
|
|
|
|
.socket__label {
|
|
color: var(--ar-text-muted);
|
|
font-size: 0.62rem;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.socket__frame {
|
|
display: grid;
|
|
place-items: center;
|
|
inline-size: 3.35rem;
|
|
block-size: 3.35rem;
|
|
padding: 0.2rem;
|
|
border: 1px solid var(--ar-border);
|
|
background: linear-gradient(180deg, #1b1f22, #0d1012);
|
|
box-shadow: inset 0 0.15rem 0.5rem rgb(0 0 0 / 0.75);
|
|
}
|
|
|
|
.socket__frame img {
|
|
inline-size: 100%;
|
|
block-size: 100%;
|
|
object-fit: contain;
|
|
}
|
|
|
|
/* An empty socket is a recess, not a pattern — quiet enough that a filled
|
|
one is what the eye lands on. */
|
|
.socket__frame--empty {
|
|
border-color: rgb(85 74 57 / 0.55);
|
|
background: linear-gradient(180deg, #141719, #0a0d0f);
|
|
}
|
|
|
|
.socket__frame--filled {
|
|
border-color: var(--ar-border-highlight);
|
|
}
|
|
|
|
.socket__frame--filled:hover {
|
|
border-color: var(--ar-gold);
|
|
}
|
|
|
|
.socket__frame--rare {
|
|
border-color: var(--ar-blue);
|
|
}
|
|
|
|
.socket__frame--epic {
|
|
border-color: var(--ar-gold);
|
|
}
|
|
|
|
.socket__frame--selected {
|
|
outline: 1px solid var(--ar-blue);
|
|
outline-offset: 1px;
|
|
}
|
|
|
|
/* ---------- values ---------- */
|
|
|
|
.values {
|
|
display: grid;
|
|
gap: 0.1rem;
|
|
margin: 0;
|
|
}
|
|
|
|
.values__row {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: var(--ar-space-3);
|
|
padding-block: 0.3rem;
|
|
}
|
|
|
|
.values__row + .values__row {
|
|
border-block-start: 1px solid rgb(85 74 57 / 0.32);
|
|
}
|
|
|
|
.values dt {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: var(--ar-space-2);
|
|
color: var(--ar-text-muted);
|
|
font-size: var(--ar-font-sm);
|
|
}
|
|
|
|
.values__glyph {
|
|
color: var(--ar-border-highlight);
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
.values dd {
|
|
margin: 0;
|
|
color: var(--ar-text);
|
|
font-family: Georgia, 'Times New Roman', serif;
|
|
font-size: 1.05rem;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* ---------- the bag ---------- */
|
|
|
|
.bag {
|
|
display: grid;
|
|
grid-template-columns: repeat(8, minmax(0, 1fr));
|
|
gap: var(--ar-space-2);
|
|
align-content: start;
|
|
min-block-size: 0;
|
|
overflow-y: auto;
|
|
scrollbar-color: var(--ar-border) transparent;
|
|
scrollbar-width: thin;
|
|
/* Room for the scrollbar so cells never sit under it. */
|
|
padding-inline-end: var(--ar-space-2);
|
|
}
|
|
|
|
.cell {
|
|
position: relative;
|
|
aspect-ratio: 1;
|
|
padding: 0.42rem;
|
|
border: 1px solid var(--ar-border);
|
|
background: linear-gradient(180deg, #1b1f22, #0d1012);
|
|
box-shadow: inset 0 0.15rem 0.5rem rgb(0 0 0 / 0.7);
|
|
}
|
|
|
|
.cell--empty {
|
|
border-color: rgb(85 74 57 / 0.45);
|
|
background: linear-gradient(180deg, #141719, #0a0d0f);
|
|
}
|
|
|
|
.cell.inventory-page__slot:hover {
|
|
border-color: var(--ar-border-highlight);
|
|
}
|
|
|
|
.cell--rare {
|
|
border-color: rgb(92 169 216 / 0.75);
|
|
}
|
|
|
|
.cell--epic {
|
|
border-color: rgb(201 164 95 / 0.8);
|
|
}
|
|
|
|
.cell--selected {
|
|
border-color: var(--ar-blue);
|
|
box-shadow:
|
|
inset 0 0.15rem 0.5rem rgb(0 0 0 / 0.7),
|
|
0 0 0 1px var(--ar-blue),
|
|
0 0 0.7rem rgb(92 169 216 / 0.45);
|
|
}
|
|
|
|
.cell__icon {
|
|
inline-size: 100%;
|
|
block-size: 100%;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.cell__quantity {
|
|
position: absolute;
|
|
inset-block-end: 0.1rem;
|
|
inset-inline-end: 0.25rem;
|
|
color: var(--ar-text);
|
|
font-size: 0.72rem;
|
|
font-variant-numeric: tabular-nums;
|
|
text-shadow: 0 0 0.3rem #000, 0 0 0.2rem #000;
|
|
}
|
|
|
|
/* Equipped pieces live on the doll; in the bag they carry a quiet gold notch. */
|
|
.cell__equipped {
|
|
position: absolute;
|
|
inset-block-start: 0;
|
|
inset-inline-start: 0;
|
|
inline-size: 0;
|
|
block-size: 0;
|
|
border-block-start: 0.55rem solid var(--ar-gold);
|
|
border-inline-end: 0.55rem solid transparent;
|
|
}
|
|
|
|
.bag__footer {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--ar-space-3);
|
|
align-items: end;
|
|
justify-content: space-between;
|
|
align-self: end;
|
|
inline-size: 100%;
|
|
margin-block-start: var(--ar-space-4);
|
|
padding-block-start: var(--ar-space-3);
|
|
border-block-start: 1px solid rgb(85 74 57 / 0.5);
|
|
color: var(--ar-text-muted);
|
|
font-size: var(--ar-font-sm);
|
|
}
|
|
|
|
.bag__count {
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
.bag__hint {
|
|
font-style: italic;
|
|
}
|
|
|
|
/* ---------- notices ---------- */
|
|
|
|
.inventory-page__notice {
|
|
padding: var(--ar-space-4);
|
|
color: var(--ar-text-muted);
|
|
text-align: center;
|
|
}
|
|
|
|
.inventory-page__notice--error {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--ar-space-4);
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-block-start: var(--ar-space-4);
|
|
border: 1px solid var(--ar-danger);
|
|
background: var(--ar-panel);
|
|
color: var(--ar-danger);
|
|
text-align: start;
|
|
}
|
|
|
|
.inventory-page__notice--error p {
|
|
margin: 0;
|
|
}
|
|
|
|
.inventory-page__notice--error button {
|
|
padding: var(--ar-space-2) var(--ar-space-4);
|
|
border: 1px solid var(--ar-border-highlight);
|
|
border-radius: var(--ar-radius-sm);
|
|
color: var(--ar-text);
|
|
background: linear-gradient(180deg, #23282c, #14181b);
|
|
font-family: Georgia, 'Times New Roman', serif;
|
|
}
|
|
|
|
.inventory-page__notice--error button:hover {
|
|
border-color: var(--ar-gold);
|
|
color: var(--ar-gold);
|
|
}
|
|
|
|
/* ---------- responsive ---------- */
|
|
|
|
/* Once the columns start stacking the screen is taller than the viewport, so
|
|
the page goes back to scrolling as a whole and the bag stops scrolling
|
|
inside itself — two nested scrollers would fight each other. */
|
|
@media (width < 76rem) {
|
|
.inventory-page {
|
|
block-size: auto;
|
|
overflow: visible;
|
|
}
|
|
|
|
.inventory-page__columns {
|
|
grid-template-columns: minmax(16rem, 18rem) minmax(0, 1fr);
|
|
align-items: start;
|
|
}
|
|
|
|
.inventory-page__detail {
|
|
grid-column: 1 / -1;
|
|
}
|
|
|
|
.bag {
|
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
overflow-y: visible;
|
|
}
|
|
|
|
.panel--doll,
|
|
.panel--bag {
|
|
grid-template-rows: none;
|
|
}
|
|
|
|
.doll {
|
|
grid-template-rows: none;
|
|
}
|
|
|
|
.doll__figure {
|
|
inline-size: 100%;
|
|
min-block-size: 12rem;
|
|
}
|
|
}
|
|
|
|
@media (width < 52rem) {
|
|
.inventory-page {
|
|
padding: var(--ar-space-3);
|
|
}
|
|
|
|
.inventory-page__columns {
|
|
grid-template-columns: minmax(0, 1fr);
|
|
}
|
|
|
|
.bag {
|
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
}
|
|
}
|