🆙 Small visual updates

This commit is contained in:
DuckieTM
2026-06-06 11:35:02 +02:00
parent 816779a614
commit 0a6aeafe11
4 changed files with 25 additions and 218 deletions
@@ -40,7 +40,17 @@ export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
if(className?.length) if(className?.length)
{ {
const param = (product.productType === ProductTypeEnum.WALL && product.extraParam?.length) ? `_${ product.extraParam }` : ''; let param = '';
if(product.productType === ProductTypeEnum.WALL && product.extraParam?.length)
{
param = `_${ product.extraParam }`;
}
else if(product.productType === ProductTypeEnum.FLOOR && product.furnitureData?.hasIndexedColor && (product.furnitureData.colorIndex > 0))
{
param = `_${ product.furnitureData.colorIndex }`;
}
const configuredIconUrl = GetConfigurationValue<string>('furni.asset.icon.url', ''); const configuredIconUrl = GetConfigurationValue<string>('furni.asset.icon.url', '');
if(configuredIconUrl?.length) if(configuredIconUrl?.length)
@@ -104,6 +114,7 @@ export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
return ( return (
<LayoutGridItem <LayoutGridItem
className={ `group/tile relative ${ itemActive ? 'is-active' : '' }` } className={ `group/tile relative ${ itemActive ? 'is-active' : '' }` }
gap={ 1 }
itemActive={ itemActive } itemActive={ itemActive }
itemCount={ ((offer.pricingModel === Offer.PRICING_MODEL_MULTI) ? product.productCount : 1) } itemCount={ ((offer.pricingModel === Offer.PRICING_MODEL_MULTI) ? product.productCount : 1) }
itemUniqueNumber={ product.uniqueLimitedItemSeriesSize } itemUniqueNumber={ product.uniqueLimitedItemSeriesSize }
@@ -103,7 +103,7 @@ export const CatalogLayoutDefaultView: FC<CatalogLayoutProps> = props =>
<div className="nitro-catalog-classic-grid-shell flex-1 overflow-auto min-h-0"> <div className="nitro-catalog-classic-grid-shell flex-1 overflow-auto min-h-0">
{ GetConfigurationValue('catalog.headers') && { GetConfigurationValue('catalog.headers') &&
<CatalogHeaderView imageUrl={ currentPage.localization.getImage(0) } /> } <CatalogHeaderView imageUrl={ currentPage.localization.getImage(0) } /> }
<CatalogItemGridWidgetView className="nitro-catalog-classic-grid" columnCount={ 7 } columnMinHeight={ 70 } columnMinWidth={ 45 } /> <CatalogItemGridWidgetView className="nitro-catalog-classic-grid" columnCount={ 6 } columnMinHeight={ 80 } columnMinWidth={ 55 } />
</div> </div>
{ currentOffer && { currentOffer &&
@@ -22,7 +22,6 @@ export const InventoryBotView: FC<{
if(!selectedBot || !roomPreviewer) return; if(!selectedBot || !roomPreviewer) return;
const botData = selectedBot.botData; const botData = selectedBot.botData;
roomPreviewer.reset(false); roomPreviewer.reset(false);
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true); roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
roomPreviewer.updateObjectRoom('111', '217', '1.1'); roomPreviewer.updateObjectRoom('111', '217', '1.1');
+12 -215
View File
@@ -12,19 +12,10 @@
--catalog-swf-select-outer: #82d1ed; --catalog-swf-select-outer: #82d1ed;
--catalog-swf-bc: #ff8d00; --catalog-swf-bc: #ff8d00;
--catalog-swf-bc-outer: #ffb53c; --catalog-swf-bc-outer: #ffb53c;
/* Light gray secondary button - cropped from catalog_skin1.png
at (10, 190, 25x22). Drives the gift button "Cadeau", the
preview-room control button and the generic .nitro-catalog-swf-
button via border-image-slice 3 3 3 3 fill. */
--habbo-slice-button-default: url("../../assets/images/catalog/buttons/btn_secondary.png"); --habbo-slice-button-default: url("../../assets/images/catalog/buttons/btn_secondary.png");
--habbo-slice-button-hover: url("../../assets/images/catalog/buttons/btn_secondary_hover.png"); --habbo-slice-button-hover: url("../../assets/images/catalog/buttons/btn_secondary_hover.png");
--habbo-slice-button-pressed: url("../../assets/images/catalog/buttons/btn_secondary_pressed.png"); --habbo-slice-button-pressed: url("../../assets/images/catalog/buttons/btn_secondary_pressed.png");
--habbo-slice-button-disabled: url("../../assets/images/catalog/buttons/btn_secondary_disabled.png"); --habbo-slice-button-disabled: url("../../assets/images/catalog/buttons/btn_secondary_disabled.png");
/* Classic Habbo "Osta!" Buy button - cropped from catalog_skin3.png
yellow band. The historical name says "green" but the user's
skin sheet ships yellow for the action colour, so that's what
we paint. The 27x34 sprite border-image-slices nicely at 6px
since the rounded corner is ~5px. */
--habbo-slice-button-buy: url("../../assets/images/catalog/buttons/buy.png"); --habbo-slice-button-buy: url("../../assets/images/catalog/buttons/buy.png");
--habbo-slice-button-large: url("../../assets/images/catalog/buttons/buy.png"); --habbo-slice-button-large: url("../../assets/images/catalog/buttons/buy.png");
--habbo-slice-button-large-hover: url("../../assets/images/catalog/buttons/buy_hover.png"); --habbo-slice-button-large-hover: url("../../assets/images/catalog/buttons/buy_hover.png");
@@ -48,9 +39,6 @@
--habbo-stepper-minus-hover: url("../../assets/images/catalog/buttons/minus_hover.png"); --habbo-stepper-minus-hover: url("../../assets/images/catalog/buttons/minus_hover.png");
--habbo-stepper-minus-pressed: url("../../assets/images/catalog/buttons/minus_pressed.png"); --habbo-stepper-minus-pressed: url("../../assets/images/catalog/buttons/minus_pressed.png");
--habbo-stepper-minus-disabled: url("../../assets/images/catalog/buttons/minus_disabled.png"); --habbo-stepper-minus-disabled: url("../../assets/images/catalog/buttons/minus_disabled.png");
/* Scrollbar sprites cropped from catalog_skin1.png. The single-piece
thumb has caps + grip baked into one 17x34 image - stretch it
full-height with background-size: 17px 100%. */
--habbo-scrollbar-up: url("../../assets/images/catalog/scrollbar/scroll_v_up.png"); --habbo-scrollbar-up: url("../../assets/images/catalog/scrollbar/scroll_v_up.png");
--habbo-scrollbar-up-pressed: url("../../assets/images/catalog/scrollbar/scroll_v_up_pressed.png"); --habbo-scrollbar-up-pressed: url("../../assets/images/catalog/scrollbar/scroll_v_up_pressed.png");
--habbo-scrollbar-down: url("../../assets/images/catalog/scrollbar/scroll_v_down.png"); --habbo-scrollbar-down: url("../../assets/images/catalog/scrollbar/scroll_v_down.png");
@@ -163,10 +151,6 @@
display: none !important; display: none !important;
} }
/* Publish button: lives inside the catalog window, absolutely
positioned in the header just to the left of the close X. Renders
only when adminMode is true (see CatalogClassicView.tsx). Uses the
Habbo yellow buy-button skin so it matches the Koop button. */
.nitro-catalog-classic-window .nitro-catalog-classic-header-publish { .nitro-catalog-classic-window .nitro-catalog-classic-header-publish {
position: absolute !important; position: absolute !important;
top: 5px !important; top: 5px !important;
@@ -191,17 +175,7 @@
50% { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.65), inset 0 -2px 0 rgba(140, 75, 0, 0.35), 0 0 8px rgba(255, 200, 0, 0.75); } 50% { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.65), inset 0 -2px 0 rgba(140, 75, 0, 0.35), 0 0 8px rgba(255, 200, 0, 0.75); }
} }
/* Catalog default-layout admin row (Pagina bewerken / Nieuwe
aanbieding / Aanbieding bewerken). These are inline text buttons
but the .habbo-swf-window button + .habbo-swf-window
button[class*="success"] global rules were dressing them up as
SWF skin buttons (one yellow!) and forcing min-height: 22px which
broke the layout. Reset and re-skin as compact pill chips. */
.nitro-catalog-classic-window .nitro-catalog-classic-default-admin { .nitro-catalog-classic-window .nitro-catalog-classic-default-admin {
/* Keep all admin buttons on one row so the product-view doesn't
get pushed down into the absolutely-positioned grid-shell. If
a future label makes them overflow, the row scrolls
horizontally instead of wrapping. */
flex-wrap: nowrap !important; flex-wrap: nowrap !important;
align-items: center !important; align-items: center !important;
gap: 6px !important; gap: 6px !important;
@@ -251,8 +225,6 @@
box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.08), 0 0 0 rgba(0, 0, 0, 0) !important; box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.08), 0 0 0 rgba(0, 0, 0, 0) !important;
} }
/* The "Nieuwe aanbieding" button uses text-success - give it the
habbo-yellow buy-button palette to mark it as the create action. */
.nitro-catalog-classic-window .nitro-catalog-classic-default-admin button.text-success, .nitro-catalog-classic-window .nitro-catalog-classic-default-admin button.text-success,
.nitro-catalog-classic-window .nitro-catalog-classic-default-admin button[class*="success"] { .nitro-catalog-classic-window .nitro-catalog-classic-default-admin button[class*="success"] {
border-color: #8a5b00 !important; border-color: #8a5b00 !important;
@@ -282,10 +254,6 @@
margin-left: 4px !important; margin-left: 4px !important;
} }
/* Admin cog tab at the end of the tab strip - only renders when the
user is a mod, so leaving it visible at all times is safe. Style
it as a compact square that sits flush with the other tabs
instead of stretching to flex: 1 like a category tab. */
.nitro-catalog-classic-tabs-shell .nitro-card-tab-item.nitro-catalog-classic-admin-tab { .nitro-catalog-classic-tabs-shell .nitro-card-tab-item.nitro-catalog-classic-admin-tab {
flex: 0 0 auto !important; flex: 0 0 auto !important;
width: 32px !important; width: 32px !important;
@@ -355,9 +323,6 @@
} }
.nitro-catalog-classic-tabs-shell { .nitro-catalog-classic-tabs-shell {
/* Strip just tall enough to hold the 36px tab + 4px of breathing
room above. Trims the dead blue band between the header and
the tabs so the catalog body doesn't lose vertical space. */
flex: 0 0 40px; flex: 0 0 40px;
height: 40px; height: 40px;
min-height: 40px; min-height: 40px;
@@ -365,8 +330,6 @@
gap: 0; gap: 0;
padding: 4px 6px 0 !important; padding: 4px 6px 0 !important;
align-items: flex-end; align-items: flex-end;
/* Horizontal scroll so every category tab stays reachable when the
card is narrower than the total tab width. */
overflow-x: auto; overflow-x: auto;
overflow-y: hidden; overflow-y: hidden;
flex-wrap: nowrap; flex-wrap: nowrap;
@@ -377,8 +340,6 @@
border-bottom: 1px solid #c8c8bf; border-bottom: 1px solid #c8c8bf;
} }
/* The tabs strip uses a slim 6px scrollbar - opt it out of the
17px Habbo-sprite scrollbar applied to the rest of the catalog. */
.nitro-catalog-classic-tabs-shell::-webkit-scrollbar { .nitro-catalog-classic-tabs-shell::-webkit-scrollbar {
width: 6px !important; width: 6px !important;
height: 6px !important; height: 6px !important;
@@ -409,18 +370,11 @@
gap: 4px; gap: 4px;
height: 36px; height: 36px;
min-width: 0; min-width: 0;
/* Equal-width tabs that share the strip exactly - the right
edge of the last tab now lines up with the right edge of the
catalog window, no trailing gap. */
flex: 1 1 0; flex: 1 1 0;
max-width: none; max-width: none;
padding: 6px 6px 7px; padding: 6px 6px 7px;
margin: 0 2px 0 0; margin: 0 2px 0 0;
flex-shrink: 1; flex-shrink: 1;
/* Classic Habbo tab: gray rounded-top rectangle with a 1px black
outline. ubuntu_tab3_*.png isn't shipped, so we draw the
habbo-look ourselves instead of border-image-slicing a missing
sprite. */
border: 1px solid #000 !important; border: 1px solid #000 !important;
border-bottom: 0 !important; border-bottom: 0 !important;
border-radius: 6px 6px 0 0 !important; border-radius: 6px 6px 0 0 !important;
@@ -437,9 +391,6 @@
border-image-source: none !important; border-image-source: none !important;
} }
/* Bring the last tab flush with whatever follows (admin cog, edge),
instead of leaving the negative right margin tugging on empty
space. */
.nitro-catalog-classic-tabs-shell .nitro-card-tab-item:last-of-type { .nitro-catalog-classic-tabs-shell .nitro-card-tab-item:last-of-type {
margin-right: 0; margin-right: 0;
} }
@@ -454,9 +405,6 @@
line-height: 17px; line-height: 17px;
} }
/* Category icon that sits before the label. The blanket "hide every
img/svg inside a tab" rule is gone - we explicitly size the
classic tab icon and let everything else fall through. */
.nitro-catalog-classic-tab-icon { .nitro-catalog-classic-tab-icon {
width: 18px; width: 18px;
height: 18px; height: 18px;
@@ -472,9 +420,6 @@
.nitro-catalog-classic-tabs-shell .nitro-card-tab-item-active { .nitro-catalog-classic-tabs-shell .nitro-card-tab-item-active {
z-index: 2; z-index: 2;
/* Active tab: the catalog-header habbo-blue with the cream catalog
body bleeding up into it. Drop the bottom border so the tab
"merges" with the panel below. */
background: background:
linear-gradient(180deg, #4fb3ff 0%, var(--catalog-swf-blue) 100%) !important; linear-gradient(180deg, #4fb3ff 0%, var(--catalog-swf-blue) 100%) !important;
color: #ffffff !important; color: #ffffff !important;
@@ -502,10 +447,6 @@
.nitro-catalog-classic-stage { .nitro-catalog-classic-stage {
display: grid; display: grid;
/* Sidebar pinned at 184px; the layout column takes the rest of
the stage row so the right edge of the right column lines up
with the right edge of the catalog window instead of leaving a
wide cream strip. */
grid-template-columns: 184px 1fr; grid-template-columns: 184px 1fr;
gap: 8px; gap: 8px;
width: 100%; width: 100%;
@@ -527,14 +468,9 @@
.nitro-catalog-classic-search-shell { .nitro-catalog-classic-search-shell {
position: relative; position: relative;
/* Use flex so the input vertically centers inside the 24px shell
regardless of the input's own intrinsic baseline. */
display: flex; display: flex;
align-items: center; align-items: center;
height: 24px; height: 24px;
/* Outer padding 0, negative horizontal margin bleeds the shell a
couple of pixels past its sidebar column on each side without
touching the grid template - cheap way to look ~4px wider. */
padding: 0; padding: 0;
margin: -2px -1px 0 -1px; margin: -2px -1px 0 -1px;
border: 1px solid #b7b7ae; border: 1px solid #b7b7ae;
@@ -542,10 +478,6 @@
background: #f7f7f2; background: #f7f7f2;
} }
/* Clear the magnifying-glass on the left and the X-clear button on the
right. The shell's own outer padding is essentially zero, so the
input claims the full sidebar column width minus just enough to
keep the icons from overlapping the text. */
.nitro-catalog-classic-search-shell input { .nitro-catalog-classic-search-shell input {
flex: 1 1 auto; flex: 1 1 auto;
width: 100% !important; width: 100% !important;
@@ -562,8 +494,6 @@
vertical-align: middle !important; vertical-align: middle !important;
} }
/* The wrapping div the React component renders is 100% wide so the
input fills the shell instead of shrinking to content. */
.nitro-catalog-classic-search-shell > div { .nitro-catalog-classic-search-shell > div {
width: 100% !important; width: 100% !important;
height: 100% !important; height: 100% !important;
@@ -574,13 +504,10 @@
font-size: 11px !important; font-size: 11px !important;
} }
/* The search icon ships with absolute + left-2; nudge it tight to the
shell edge so the input can keep its left padding small. */
.nitro-catalog-classic-search-shell svg:first-child { .nitro-catalog-classic-search-shell svg:first-child {
left: 4px !important; left: 4px !important;
} }
/* X-clear button on the right edge - keep it tight too. */
.nitro-catalog-classic-search-shell button { .nitro-catalog-classic-search-shell button {
right: 4px !important; right: 4px !important;
} }
@@ -715,20 +642,11 @@
.nitro-catalog-classic-default-layout { .nitro-catalog-classic-default-layout {
position: relative; position: relative;
display: block !important; display: block !important;
/* Fill the layout container in both axes - the stage was
previously 552px wide and this column was pinned at 360px, but
now that the stage uses 1fr, hardcoding 360px would leave a
wide blank strip on the right of every default-layout catalog
page. */
width: 100%; width: 100%;
height: 100%; height: 100%;
min-height: 460px; min-height: 460px;
} }
/* The product-view, grid-shell, price-row and purchase-row inside
the default-layout were each pinned at 360px to match the old
stage width. Widen them in lockstep so they fill the new
1fr-sized container. */
.nitro-catalog-classic-product-view, .nitro-catalog-classic-product-view,
.nitro-catalog-classic-grid-shell, .nitro-catalog-classic-grid-shell,
.nitro-catalog-classic-price-row, .nitro-catalog-classic-price-row,
@@ -768,12 +686,6 @@
height: 100%; height: 100%;
} }
/* Default-3x3 layout: .offer-info is rendered but hidden via the
display: none rule below, so the panel reserved the full width
while only the 360px preview was visible (empty strip on the
right). Center the preview inside the panel instead so the gap
becomes symmetric padding on both sides. Color-grouping doesn't
render .offer-info so its panel keeps the existing layout. */
.nitro-catalog-classic-offer-panel:has(> .nitro-catalog-classic-offer-info) { .nitro-catalog-classic-offer-panel:has(> .nitro-catalog-classic-offer-info) {
justify-content: center; justify-content: center;
} }
@@ -786,13 +698,6 @@
background: #000; background: #000;
} }
/* The default-3x3 layout puts the preview next to .offer-info inside
.offer-panel and needs the 360px column. Scope the pin to that
context so other layouts (color-grouping, etc.) can put the same
preview class inside a flex/grid column and let it track the
container width. Without this scoping the absolute-positioned
rotate/state buttons sit past the column's right edge and get
clipped by overflow: hidden. */
.nitro-catalog-classic-offer-panel > .nitro-catalog-classic-offer-preview { .nitro-catalog-classic-offer-panel > .nitro-catalog-classic-offer-preview {
width: 360px; width: 360px;
min-width: 360px; min-width: 360px;
@@ -858,8 +763,6 @@
position: absolute; position: absolute;
left: 0; left: 0;
top: 245px; top: 245px;
/* Stretch down to just above the price + purchase rows so the
grid soaks up any extra height the bigger window gives us. */
bottom: 68px; bottom: 68px;
width: 360px; width: 360px;
min-height: 0; min-height: 0;
@@ -867,20 +770,12 @@
overflow: auto; overflow: auto;
} }
/* When the admin row is rendered above the product-view it adds
~30px (22px button + flex gap) to the flex column, but the
grid-shell is absolutely positioned and doesn't shift on its own.
Push it (and the bottom-anchored price/purchase rows stay put)
down so the preview panel no longer bleeds into the grid. */
.nitro-catalog-classic-default-layout:has(.nitro-catalog-classic-default-admin) .nitro-catalog-classic-grid-shell { .nitro-catalog-classic-default-layout:has(.nitro-catalog-classic-default-admin) .nitro-catalog-classic-grid-shell {
top: 280px !important; top: 280px !important;
} }
.nitro-catalog-classic-grid { .nitro-catalog-classic-grid {
/* Don't pin a fixed column track here - AutoGrid sets the inline grid-template-columns: repeat(6, 1fr) !important;
grid-template-columns from its columnMinWidth prop. The earlier
`repeat(6, 53px) !important` was clobbering that and freezing
the row at 6 tiles regardless of what the React layout passed. */
grid-auto-rows: var(--nitro-grid-column-min-height, 70px); grid-auto-rows: var(--nitro-grid-column-min-height, 70px);
align-content: start; align-content: start;
justify-content: start; justify-content: start;
@@ -889,11 +784,6 @@
} }
.nitro-catalog-classic-window .layout-grid-item { .nitro-catalog-classic-window .layout-grid-item {
/* Let the tile flex to whatever min/max width the AutoGrid sets
via repeat(auto-fill, minmax(N, 1fr)) - hard-pinning 53x74 was
overriding the layout's columnMinWidth prop, so the row count
never changed when we reduced it. Width is now 100% of the
column cell, height tracks --nitro-grid-column-min-height. */
width: 100% !important; width: 100% !important;
height: var(--nitro-grid-column-min-height, 70px) !important; height: var(--nitro-grid-column-min-height, 70px) !important;
min-width: 0 !important; min-width: 0 !important;
@@ -905,19 +795,10 @@
overflow: visible !important; overflow: visible !important;
} }
/* Furni tiles drive their look from the icon image and need a clear
background. Color-grouping swatches use itemHighlight (.has-highlight)
to ask LayoutGridItem for a solid colour via inline backgroundColor -
keep the transparent override off those so the swatch is visible. */
.nitro-catalog-classic-window .layout-grid-item:not(.has-highlight) { .nitro-catalog-classic-window .layout-grid-item:not(.has-highlight) {
background-color: transparent !important; background-color: transparent !important;
} }
/* Pets breed picker: the pet-head image renders at its native ~81x69px
regardless of the grid cell size. The old grid-cols-6 stretched
each .layout-grid-item to ~150-200px so the head looked huge in
acres of empty tile. Pin each tile just big enough to host the
head and let the container flex-wrap. */
.nitro-catalog-classic-window .nitro-catalog-classic-pet-breeds .layout-grid-item { .nitro-catalog-classic-window .nitro-catalog-classic-pet-breeds .layout-grid-item {
width: 84px !important; width: 84px !important;
min-width: 84px !important; min-width: 84px !important;
@@ -938,12 +819,6 @@
inset -2px -2px 0 #ecece4 !important; inset -2px -2px 0 #ecece4 !important;
} }
/* Habbo-classic colour swatches: small chip with a 1px dark border
and a subtle inner highlight so light tones still read as buttons.
Hover lifts the border; the selected swatch is "pressed" with a
sunken inner shadow and a bright cyan ring matching the catalog
selection accent. The cream inset from the generic .is-active rule
above would wash out the swatch colour, so we replace it here. */
.nitro-catalog-classic-window .layout-grid-item.has-highlight { .nitro-catalog-classic-window .layout-grid-item.has-highlight {
width: 26px !important; width: 26px !important;
height: 26px !important; height: 26px !important;
@@ -975,30 +850,20 @@
} }
.nitro-catalog-classic-grid-offer-icon { .nitro-catalog-classic-grid-offer-icon {
position: absolute;
left: 50%;
top: 20px;
width: auto !important; width: auto !important;
height: auto !important; height: auto !important;
max-width: 36px; image-rendering: pixelated;
max-height: 36px;
object-fit: contain; object-fit: contain;
transform: translate(-50%, -50%);
pointer-events: none; pointer-events: none;
} }
.nitro-catalog-classic-grid-price { .nitro-catalog-classic-grid-price {
position: absolute;
left: 2px;
right: 2px;
top: 36px;
bottom: auto;
display: flex; display: flex;
flex-direction: column; flex-direction: row;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: center;
gap: 0; gap: 3px;
min-height: 24px; width: 100%;
color: #000; color: #000;
font-size: 11px; font-size: 11px;
font-weight: 700; font-weight: 700;
@@ -1007,18 +872,10 @@
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.75); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.75);
} }
/* When the tile shows a full-tile bot/pet avatar (instead of a small
icon), pin the price strip to the bottom of the tile and give it a
translucent backdrop so it doesn't overlap with the avatar body. */
.nitro-catalog-classic-grid .layout-grid-item:has(.avatar-image) .nitro-catalog-classic-grid-price, .nitro-catalog-classic-grid .layout-grid-item:has(.avatar-image) .nitro-catalog-classic-grid-price,
.nitro-catalog-classic-grid .layout-grid-item:has(> .avatar-image) > .nitro-catalog-classic-grid-price, .nitro-catalog-classic-grid .layout-grid-item:has(> .avatar-image) > .nitro-catalog-classic-grid-price,
.nitro-catalog-classic-grid .avatar-image ~ .nitro-catalog-classic-grid-price { .nitro-catalog-classic-grid .avatar-image ~ .nitro-catalog-classic-grid-price {
top: auto !important; top: auto !important;
/* Re-anchor horizontally too: the parent rule's left: 2px /
right: 2px combined with content-sized inner flex was visually
parking the pill at the left side of the tile. Center it via
explicit left/right + transform so it lands smack in the
middle regardless of inner content width. */
left: 50% !important; left: 50% !important;
right: auto !important; right: auto !important;
bottom: 4px !important; bottom: 4px !important;
@@ -1036,10 +893,6 @@
z-index: 5 !important; z-index: 5 !important;
} }
/* Tighten the price entry inside the avatar-tile pill so the number
and currency icon center on the same baseline (the global
.grid-price-entry height: 13px clipped the 15px wallet icon and
pushed it visually below the number). */
.nitro-catalog-classic-grid .layout-grid-item:has(.avatar-image) .nitro-catalog-classic-grid-price-entry, .nitro-catalog-classic-grid .layout-grid-item:has(.avatar-image) .nitro-catalog-classic-grid-price-entry,
.nitro-catalog-classic-grid .avatar-image ~ .nitro-catalog-classic-grid-price .nitro-catalog-classic-grid-price-entry { .nitro-catalog-classic-grid .avatar-image ~ .nitro-catalog-classic-grid-price .nitro-catalog-classic-grid-price-entry {
height: auto !important; height: auto !important;
@@ -1059,11 +912,15 @@
} }
.nitro-catalog-classic-grid-price.is-single-price { .nitro-catalog-classic-grid-price.is-single-price {
height: 19px; height: auto;
min-height: 0;
} }
.nitro-catalog-classic-grid-price.is-multi-price { .nitro-catalog-classic-grid-price.is-multi-price {
height: 38px; height: auto;
min-height: 0;
flex-wrap: wrap;
row-gap: 1px;
} }
.nitro-catalog-classic-grid-price-entry { .nitro-catalog-classic-grid-price-entry {
@@ -1092,8 +949,6 @@
.nitro-catalog-classic-price-row { .nitro-catalog-classic-price-row {
position: absolute; position: absolute;
left: 0; left: 0;
/* Anchored from the bottom so the Aantal/Prezzo row sits just
above the Cadeau/Koop buttons regardless of layout height. */
bottom: 38px; bottom: 38px;
width: 360px; width: 360px;
height: 25px; height: 25px;
@@ -1111,8 +966,6 @@
.nitro-catalog-classic-total-price-slot { .nitro-catalog-classic-total-price-slot {
position: absolute; position: absolute;
/* Anchored to the right of the now-100% wide price row so the
Prezzo + amount stays flush with the right edge of the panel. */
right: 2px; right: 2px;
top: 0; top: 0;
width: auto; width: auto;
@@ -1135,9 +988,6 @@
.nitro-catalog-classic-purchase-row { .nitro-catalog-classic-purchase-row {
position: absolute; position: absolute;
left: 0; left: 0;
/* Anchored to the bottom of the panel with a 4px breathing strip
so the Cadeau / Koop buttons stay flush at the bottom of the
window no matter how tall the catalog is. */
bottom: 4px; bottom: 4px;
width: 360px; width: 360px;
height: 30px; height: 30px;
@@ -1151,9 +1001,6 @@
align-items: flex-start; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
gap: 10px !important; gap: 10px !important;
/* Fill the now-100% wide purchase row instead of staying pinned at
330px (which used to match the old 360px column - 15px each
side). */
width: auto; width: auto;
height: 24px; height: 24px;
margin-left: 15px; margin-left: 15px;
@@ -1213,13 +1060,6 @@
opacity: 1 !important; opacity: 1 !important;
} }
/* Buy / Gift buttons - pure CSS. border-image-slicing the bitmap
sprites produced thin highlight/shadow stripes at the top and
bottom because the source rounded corners are ~5-6px tall but the
buttons render at 22-24px, so the slice rows stretched into a
visible band. CSS gradients give a crisp pixel-art classic-habbo
look without those artefacts. */
.nitro-catalog-classic-window .nitro-catalog-swf-buy-button { .nitro-catalog-classic-window .nitro-catalog-swf-buy-button {
width: 160px !important; width: 160px !important;
min-width: 160px !important; min-width: 160px !important;
@@ -1229,8 +1069,6 @@
border-radius: 4px !important; border-radius: 4px !important;
border-image: none !important; border-image: none !important;
border-image-source: none !important; border-image-source: none !important;
/* Yellow body with the same #f0a318 / #ffd54d tones as the
skin3-yellow Buy sprite. */
background: background:
linear-gradient(180deg, #ffe66b 0%, #ffc828 45%, #f0a318 100%) !important; linear-gradient(180deg, #ffe66b 0%, #ffc828 45%, #f0a318 100%) !important;
box-shadow: box-shadow:
@@ -1257,9 +1095,6 @@
.nitro-catalog-classic-window .nitro-catalog-swf-buy-button.pointer-events-none, .nitro-catalog-classic-window .nitro-catalog-swf-buy-button.pointer-events-none,
.nitro-catalog-classic-window .nitro-catalog-swf-buy-button:disabled { .nitro-catalog-classic-window .nitro-catalog-swf-buy-button:disabled {
/* Stay yellow when disabled - the user wants the action colour
to be recognisable regardless of state. Drop opacity + flip
the cursor so it still reads as non-interactive. */
background: background:
linear-gradient(180deg, #ffe66b 0%, #ffc828 45%, #f0a318 100%) !important; linear-gradient(180deg, #ffe66b 0%, #ffc828 45%, #f0a318 100%) !important;
color: #4a2b00 !important; color: #4a2b00 !important;
@@ -1277,7 +1112,6 @@
border-radius: 4px !important; border-radius: 4px !important;
border-image: none !important; border-image: none !important;
border-image-source: none !important; border-image-source: none !important;
/* Cream / light-gray body matching the catalog cardstock. */
background: background:
linear-gradient(180deg, #ececec 0%, #cfcfc4 100%) !important; linear-gradient(180deg, #ececec 0%, #cfcfc4 100%) !important;
box-shadow: box-shadow:
@@ -1310,19 +1144,12 @@
text-shadow: none !important; text-shadow: none !important;
} }
/* Pet purchase card lives in a tight flex row alongside the price,
so the main 160px Buy button doesn't fit. Shrink it down here. */
.nitro-catalog-classic-pet-card .nitro-catalog-swf-buy-button { .nitro-catalog-classic-pet-card .nitro-catalog-swf-buy-button {
width: auto !important; width: auto !important;
min-width: 0 !important; min-width: 0 !important;
padding: 0 14px !important; padding: 0 14px !important;
} }
/* All catalog grids must scroll vertically only - horizontal overflow
produces a stray horizontal scrollbar at the bottom of the items
strip on narrow columns (e.g. guild_furni). minmax(N, 1fr) usually
contains content but the safety net stops any odd item from
triggering a horizontal bar. */
.nitro-catalog-classic-window .layout-grid, .nitro-catalog-classic-window .layout-grid,
.nitro-catalog-classic-window [class*="grid-cols-["] { .nitro-catalog-classic-window [class*="grid-cols-["] {
overflow-x: hidden !important; overflow-x: hidden !important;
@@ -1369,8 +1196,6 @@
image-rendering: pixelated !important; image-rendering: pixelated !important;
} }
/* react-icons FaMinus/FaPlus glyphs ride inside these buttons; hide
them - the sprite already contains the +/- mark. */
.nitro-catalog-classic-window button.nitro-catalog-swf-spinner-button svg { .nitro-catalog-classic-window button.nitro-catalog-swf-spinner-button svg {
display: none !important; display: none !important;
} }
@@ -1466,9 +1291,6 @@
min-width: 25px; min-width: 25px;
padding: 0 !important; padding: 0 !important;
overflow: hidden; overflow: hidden;
/* font-size: 0 was killing the SVG: react-icons emits
<svg width="1em" height="1em">, so 0em -> 0x0. Use a real
font-size and pin the SVG to explicit pixels below. */
font-size: 14px !important; font-size: 14px !important;
line-height: 1 !important; line-height: 1 !important;
display: inline-flex !important; display: inline-flex !important;
@@ -1495,13 +1317,6 @@
right: 6px; right: 6px;
} }
/* Bulletproof override for the rotate/state buttons. The shared SWF
button rule above lays a transparent body + border-image skin on
top, which works only when the catalog/buttons/btn_secondary*.png
sprites resolve - if they're missing the button renders 0x0
invisible. Pin the box and paint a visible gradient + outline so
the controls are always discoverable, and force z-index above the
room-previewer DIV so they sit on top of the rendered scene. */
.nitro-catalog-classic-window button.nitro-catalog-classic-preview-btn { .nitro-catalog-classic-window button.nitro-catalog-classic-preview-btn {
width: 28px !important; width: 28px !important;
height: 26px !important; height: 26px !important;
@@ -1542,12 +1357,6 @@
height: 17px; height: 17px;
} }
/* ===== Classic catalog scrollbar (pure CSS, no sprites) =====
Drew this with CSS gradients instead of stretching the 17x34
skin1 thumb sprite. The sprite version pixelated into visible
horizontal bands on tall scroll areas because every source row
stretched 5-10x. CSS gradients stay crisp at any height. */
.nitro-catalog-classic-window * { .nitro-catalog-classic-window * {
scrollbar-color: auto !important; scrollbar-color: auto !important;
scrollbar-width: auto; scrollbar-width: auto;
@@ -1566,10 +1375,6 @@
border: 0 !important; border: 0 !important;
} }
/* Habbo thumb: symmetric light-edges -> darker-middle gradient (the
"pinched in the middle" look of the classic Ubuntu scrollbar),
1px near-black outline, three central grip lines via SVG centered
no-repeat. */
.nitro-catalog-classic-window *::-webkit-scrollbar-thumb { .nitro-catalog-classic-window *::-webkit-scrollbar-thumb {
min-height: 28px !important; min-height: 28px !important;
border: 1px solid #2a2a26 !important; border: 1px solid #2a2a26 !important;
@@ -1599,8 +1404,6 @@
inset 0 -1px 0 rgba(255, 255, 255, 0.25) !important; inset 0 -1px 0 rgba(255, 255, 255, 0.25) !important;
} }
/* Arrow buttons: cream cap with a 1px black outline + dark inset
chevron. SVG glyphs so they stay crisp at any zoom. */
.nitro-catalog-classic-window *::-webkit-scrollbar-button:single-button:vertical:decrement { .nitro-catalog-classic-window *::-webkit-scrollbar-button:single-button:vertical:decrement {
display: block !important; display: block !important;
width: 17px !important; width: 17px !important;
@@ -1702,12 +1505,6 @@
padding: 6px !important; padding: 6px !important;
} }
/* Mobile: drop the per-page welcome row (image + localization
blurb shown when no offer is selected). On a narrow viewport
it eats most of the visible space and pushes the actual grid
off-screen. Hide it and also collapse the surrounding
product-view (otherwise its 240px height reservation stays
and leaves a blank strip above the grid). */
.nitro-catalog-classic-welcome { .nitro-catalog-classic-welcome {
display: none !important; display: none !important;
} }