feat: replace toned background with cropped product photo banner on facility cards
This commit is contained in:
parent
e444be05c0
commit
221ed97415
3 changed files with 117 additions and 54 deletions
|
|
@ -91,74 +91,105 @@
|
|||
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
|
||||
}
|
||||
|
||||
/* Card Backdrop Art (Dimmed Photographic Watermark) */
|
||||
.card-backdrop-art {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-radius: inherit;
|
||||
/* Facility Card Cropped Product Banner */
|
||||
.card-photo-banner {
|
||||
position: relative;
|
||||
height: 72px;
|
||||
width: calc(100% + 32px);
|
||||
margin: -16px -16px 10px -16px;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
background: var(--bg-surface-sub);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.card-backdrop-img {
|
||||
.card-banner-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center 25%;
|
||||
opacity: 0.08;
|
||||
object-position: center 35%;
|
||||
display: block;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.facility-card:hover .card-banner-img {
|
||||
transform: scale(1.05);
|
||||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .card-backdrop-img {
|
||||
opacity: 0.12;
|
||||
filter: brightness(0.9) contrast(1.1);
|
||||
}
|
||||
|
||||
.card-backdrop-overlay {
|
||||
.card-banner-gradient {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.4) 0%, transparent 60%, rgba(255, 255, 255, 0.6) 100%);
|
||||
background: linear-gradient(to bottom, rgba(15, 23, 42, 0.15) 0%, rgba(15, 23, 42, 0.45) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .card-backdrop-overlay {
|
||||
background: linear-gradient(135deg, rgba(17, 24, 39, 0.5) 0%, transparent 60%, rgba(17, 24, 39, 0.7) 100%);
|
||||
[data-theme="dark"] .card-banner-gradient {
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.2) 0%, rgba(11, 15, 25, 0.65) 100%);
|
||||
}
|
||||
|
||||
.facility-card:hover .card-backdrop-img {
|
||||
opacity: 0.14;
|
||||
transform: scale(1.08);
|
||||
.card-banner-sector-tag {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 10px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 0.65rem;
|
||||
font-weight: 700;
|
||||
padding: 2px 7px;
|
||||
border-radius: 4px;
|
||||
backdrop-filter: blur(4px);
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
background: rgba(15, 23, 42, 0.65);
|
||||
color: #ffffff !important;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .facility-card:hover .card-backdrop-img {
|
||||
opacity: 0.20;
|
||||
.card-banner-tier-tag {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 10px;
|
||||
font-size: 0.62rem;
|
||||
font-weight: 800;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
background: rgba(15, 23, 42, 0.75);
|
||||
color: #f8fafc;
|
||||
letter-spacing: 0.03em;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Locked Card Banner */
|
||||
.card-photo-banner.locked-banner .card-banner-img {
|
||||
filter: grayscale(60%) brightness(0.8);
|
||||
}
|
||||
|
||||
.card-banner-lock-badge {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
background: rgba(15, 23, 42, 0.45);
|
||||
color: #ffffff;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
z-index: 2;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.card-banner-lock-badge iconify-icon {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.facility-card.locked-card {
|
||||
opacity: 0.88;
|
||||
opacity: 0.92;
|
||||
background: var(--bg-surface-sub);
|
||||
}
|
||||
|
||||
.facility-card.locked-card .card-backdrop-img {
|
||||
filter: grayscale(45%) contrast(0.95);
|
||||
opacity: 0.06;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .facility-card.locked-card .card-backdrop-img {
|
||||
opacity: 0.09;
|
||||
}
|
||||
|
||||
/* Ensure all interactive card contents sit above the background watermark */
|
||||
.facility-card > *:not(.card-backdrop-art) {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.facility-header {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
|
|
|
|||
|
|
@ -8,13 +8,26 @@ import { CHEMICALS_SECTOR, CHEMICALS_PRODUCTS } from './sectors/chemicals.js';
|
|||
import { ELECTRONICS_SECTOR, ELECTRONICS_PRODUCTS } from './sectors/electronics.js';
|
||||
import { HEAVY_INDUSTRY_SECTOR, HEAVY_INDUSTRY_PRODUCTS } from './sectors/heavyIndustry.js';
|
||||
|
||||
import { ENERGY_SECTOR, ENERGY_PRODUCTS } from './sectors/energy.js';
|
||||
import { CONSTRUCTION_SECTOR, CONSTRUCTION_PRODUCTS } from './sectors/construction.js';
|
||||
import { AEROSPACE_SECTOR, AEROSPACE_PRODUCTS } from './sectors/aerospace.js';
|
||||
import { BIOTECH_SECTOR, BIOTECH_PRODUCTS } from './sectors/biotech.js';
|
||||
import { CONSUMER_GOODS_SECTOR, CONSUMER_GOODS_PRODUCTS } from './sectors/consumer_goods.js';
|
||||
import { AUTOMATION_SECTOR, AUTOMATION_PRODUCTS } from './sectors/automation.js';
|
||||
|
||||
export const SECTORS = [
|
||||
AGRICULTURE_SECTOR,
|
||||
MATERIALS_SECTOR,
|
||||
MINING_SECTOR,
|
||||
CHEMICALS_SECTOR,
|
||||
ELECTRONICS_SECTOR,
|
||||
HEAVY_INDUSTRY_SECTOR
|
||||
HEAVY_INDUSTRY_SECTOR,
|
||||
ENERGY_SECTOR,
|
||||
CONSTRUCTION_SECTOR,
|
||||
AEROSPACE_SECTOR,
|
||||
BIOTECH_SECTOR,
|
||||
CONSUMER_GOODS_SECTOR,
|
||||
AUTOMATION_SECTOR
|
||||
];
|
||||
|
||||
export const PRODUCTS = [
|
||||
|
|
@ -23,7 +36,13 @@ export const PRODUCTS = [
|
|||
...MINING_PRODUCTS,
|
||||
...CHEMICALS_PRODUCTS,
|
||||
...ELECTRONICS_PRODUCTS,
|
||||
...HEAVY_INDUSTRY_PRODUCTS
|
||||
...HEAVY_INDUSTRY_PRODUCTS,
|
||||
...ENERGY_PRODUCTS,
|
||||
...CONSTRUCTION_PRODUCTS,
|
||||
...AEROSPACE_PRODUCTS,
|
||||
...BIOTECH_PRODUCTS,
|
||||
...CONSUMER_GOODS_PRODUCTS,
|
||||
...AUTOMATION_PRODUCTS
|
||||
];
|
||||
|
||||
// Helper to look up a product by ID
|
||||
|
|
|
|||
|
|
@ -8,18 +8,22 @@ export function renderFacilityCardHtml(p, pState, state, buyMode) {
|
|||
const isSelected = state.selectedProductId === p.id;
|
||||
|
||||
const productImgPath = `assets/images/products/${p.id}_product.jpg`;
|
||||
const backdropArtHtml = `
|
||||
<div class="card-backdrop-art" aria-hidden="true">
|
||||
<img src="${productImgPath}" alt="" class="card-backdrop-img" onerror="this.parentElement.style.display='none';">
|
||||
<div class="card-backdrop-overlay"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
if (!pState.unlocked) {
|
||||
const canAffordUnlock = state.cash >= p.unlockCost;
|
||||
return `
|
||||
<div class="facility-card locked-card ${isSelected ? 'selected' : ''}" id="card-${p.id}" data-product="${p.id}">
|
||||
${backdropArtHtml}
|
||||
<!-- Cropped Product Header Banner (Locked) -->
|
||||
<div class="card-photo-banner locked-banner">
|
||||
<img src="${productImgPath}" alt="${p.name}" class="card-banner-img" onerror="this.parentElement.style.display='none';">
|
||||
<div class="card-banner-gradient"></div>
|
||||
<div class="card-banner-lock-badge">
|
||||
<iconify-icon icon="lucide:lock"></iconify-icon>
|
||||
<span>Permit Required</span>
|
||||
</div>
|
||||
<span class="card-banner-tier-tag">Tier ${p.tier}</span>
|
||||
</div>
|
||||
|
||||
<div class="facility-header">
|
||||
<div class="facility-icon-wrap" style="background: ${p.color}15; color: ${p.color};">
|
||||
<iconify-icon icon="${p.icon}" class="icon-lg"></iconify-icon>
|
||||
|
|
@ -108,7 +112,16 @@ export function renderFacilityCardHtml(p, pState, state, buyMode) {
|
|||
|
||||
return `
|
||||
<div class="facility-card active-card ${isSelected ? 'selected' : ''}" id="card-${p.id}" data-product="${p.id}">
|
||||
${backdropArtHtml}
|
||||
<!-- Cropped Product Header Banner (Active) -->
|
||||
<div class="card-photo-banner">
|
||||
<img src="${productImgPath}" alt="${p.name}" class="card-banner-img" onerror="this.parentElement.style.display='none';">
|
||||
<div class="card-banner-gradient"></div>
|
||||
<span class="card-banner-sector-tag" style="background: ${p.color}25; color: ${p.color};">
|
||||
<iconify-icon icon="${p.icon}"></iconify-icon> ${sector?.name}
|
||||
</span>
|
||||
<span class="card-banner-tier-tag">Tier ${p.tier}</span>
|
||||
</div>
|
||||
|
||||
<div class="facility-header">
|
||||
<div class="facility-icon-wrap" style="background: ${p.color}15; color: ${p.color};">
|
||||
<iconify-icon icon="${p.icon}" class="icon-lg"></iconify-icon>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue