/*
 Theme Name:   Printerland Astra Child
 Theme URI:    https://printerland.md
 Description:  Brand-matched child theme for the Printerland WooCommerce evaluation site.
 Author:       Printerland
 Template:     astra
 Version:      1.0.0
 Text Domain:  printerland-astra-child
*/

/* Montserrat — self-hosted replacement for Geist (which was 100% Astra
   Customizer state, not visible anywhere in this repo's own code — see
   docs/memory/conventions.md). Chosen over Sofia Pro (the original ask):
   Sofia Pro is a paid commercial font, free for personal use only: using
   it on a live commercial site needs a purchased webfont license this
   project doesn't have. Montserrat is consistently rated one of the
   closest free matches (geometric-sans character, same premium ecommerce
   positioning) and — critically for a RO/RU/EN trilingual site — actually
   has Cyrillic glyph coverage; the first candidate considered (Poppins)
   does not, which would've silently broken typography on every Russian
   page. Only latin + cyrillic subsets are self-hosted (matches this
   site's actual 3 languages — RO's diacritics fall in the latin subset's
   extended range already covered here); Google also ships
   greek/vietnamese/latin-ext subsets this project has no use for. */
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('assets/fonts/montserrat-400-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('assets/fonts/montserrat-400-cyrillic.woff2') format('woff2');
	unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('assets/fonts/montserrat-500-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('assets/fonts/montserrat-500-cyrillic.woff2') format('woff2');
	unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('assets/fonts/montserrat-600-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('assets/fonts/montserrat-600-cyrillic.woff2') format('woff2');
	unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('assets/fonts/montserrat-700-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('assets/fonts/montserrat-700-cyrillic.woff2') format('woff2');
	unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

:root {
	--pl-font: 'Montserrat', sans-serif;
	/* Slate-navy palette (2026-08 redesign, impeccable skill pass) — prior
	   iterations only ever adjusted LIGHTNESS of a plain royal-blue hue
	   (~205°) and papered the banner gradient with a white radial "sheen",
	   which reads patchy/washed rather than designed (mixing white into a
	   saturated hue desaturates/muddies it). This pass shifts hue toward a
	   muted slate-indigo (~210°, lower chroma) — ref: Wise/Revolut navy-on-
	   white restraint — and replaces the sheen with a real 3-stop
	   same-family gradient (ink -> navy -> mid), no white mixed in. */
	--pl-ink: #12283d;    /* gradient dark stop */
	--pl-navy: #23496b;   /* primary — headings/buttons/topbar/text, ~8:1 both directions on white */
	--pl-navy-rgb: 35, 73, 107;
	--pl-navy-mid: #3d6a91;   /* gradient midpoint */
	--pl-navy-light: #7ba3c4; /* gradient light stop — a real light BLUE, not white */
	--pl-mist: #eaf2f8;       /* light panel tint — icon circles, hover fills */
	/* Deepened slightly to hold its own against the richer navy (was
	   #d56c4d, tuned against the lighter/brighter navy of the prior pass). */
	--pl-accent: #c85a3c;
	--pl-accent-hover: #ad4a2f;
	/* Small navy/accent buttons, badges, and pills were flat solid fills
	   with no depth, disconnected from the gradient bands. Consistency
	   pass (2026-08): every clickable/badge navy or accent surface gets a
	   matching 2-stop gradient + a tinted shadow (not generic black —
	   navy-tinted, so it reads as the brand's own shadow, not a default). */
	--pl-accent-gradient: linear-gradient(135deg, var(--pl-accent) 0%, var(--pl-accent-hover) 100%);
	--pl-shadow-chip: 0 3px 10px rgb(var(--pl-navy-rgb) / 0.28);
	--pl-radius-card: 26px;
	--pl-radius-sm: 8px; /* replaces the ad-hoc 0.5rem/8px/0.75rem/0.85rem scattered across small chips/rows */
	--pl-gray-600: #6b7280; /* muted text — replaces #888/#666/#556/#667/#555 */
	--pl-gray-100: #f5f7fa; /* light surface — replaces #fafbfc/#f0f0f0/#eef0f3/#eee */
	/* Deepened per feedback — the original was too subtle to read as a
	   clear card edge on a white page (white card + white page + a barely-
	   there shadow). Same token everywhere, so this ripples sitewide. */
	--pl-shadow-card: 0 6px 16px -2px rgb(0 0 0 / 0.12), 0 2px 6px -2px rgb(0 0 0 / 0.08);
	--pl-shadow-card-lg: 0 4px 24px 0 rgb(0 0 0 / 0.12);
	/* Homepage section rhythm — was a flat 1.5rem margin-top AND
	   margin-bottom on every section, which (adjacent-sibling margin
	   collapsing) only ever produced a 1.5rem/24px gap regardless of
	   section weight, tight enough that the navy .ph-deal-bleed band read as
	   colliding with the section above it. -gap is the default vertical
	   rhythm between in-flow homepage sections; -gap-lg is used around
	   full-bleed colored band sections, which need more visual air than a
	   plain white-on-white section boundary. */
	--pl-section-gap: 2.5rem;
	--pl-section-gap-lg: 4rem;
	/* Subtle premium gradient variants of the two dominant surface colors —
	   applied to large banners/cards (deal band, footer, mega-menu panel,
	   product cards) in place of a flat fill, not to buttons, badges, form
	   inputs, or product-image wells (those stay flat so photos/text read
	   cleanly). Shallow angle and close stops keep it a subtle sheen, not a
	   loud effect. */
	/* Small flat elements (mega-menu toggle, maps CTA) — 2-stop, same family. */
	--pl-navy-gradient: linear-gradient(135deg, var(--pl-navy) 0%, var(--pl-navy-mid) 100%);
	/* Large full-bleed banners (deal strip, newsletter, footer, sale promo
	   card, mobile nav drawer) — real 3-stop same-family gradient (ink ->
	   navy -> mid), replacing the old white-radial "sheen" hack. No white
	   mixed in, so it reads as one designed gradient instead of a patched-
	   on highlight; var name kept as -sheen so call sites didn't need
	   touching. */
	--pl-navy-sheen: linear-gradient(150deg, var(--pl-ink) 0%, var(--pl-navy) 55%, var(--pl-navy-mid) 100%);
	--pl-white-gradient: linear-gradient(135deg, #ffffff 0%, var(--pl-gray-100) 100%);
	/* For gray PANEL backgrounds (not cards) — --pl-white-gradient starts at
	   pure white, which would fade to near-invisible at one corner of a
	   panel meant to contrast against the white page itself. Two close gray
	   tones instead, so contrast against white tiles stays consistent
	   everywhere in the panel while still reading as a soft sheen rather
	   than one flat fill. */
	--pl-gray-gradient: linear-gradient(135deg, var(--pl-gray-100) 0%, #eef1f6 100%);
}

/* !important — Astra's own typography system (Customizer-driven) sets
   font-family directly on body AND separately on headings (its own
   heading-font Customizer setting, not inherited from body) — confirmed
   live, h1-h3 still computed to Geist after the body rule alone. Same
   override class fought repeatedly elsewhere in this file (search input,
   hero dots, etc. — see docs/memory/conventions.md). Headings need their
   own explicit rule, not just body. */
body,
h1, h2, h3, h4, h5, h6 {
	font-family: var(--pl-font) !important;
}

/* Primary CTAs — pill shape, brand accent color, matching the live site's
   rounded-full convention across cart/checkout/PDP. */
.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce #respond input#submit.alt,
.astra-cart-drawer-checkout,
a.wp-block-button__link {
	background-color: var(--pl-accent) !important;
	border-color: var(--pl-accent) !important;
	border-radius: 9999px !important;
	font-weight: 600;
}
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
.woocommerce #respond input#submit.alt:hover {
	background-color: var(--pl-accent-hover) !important;
	border-color: var(--pl-accent-hover) !important;
}

/* Secondary buttons — navy, still pill-shaped. */
.woocommerce a.button:not(.alt),
.woocommerce button.button:not(.alt) {
	border-radius: 9999px !important;
	border-color: var(--pl-navy);
	color: var(--pl-navy);
}

/* Header chrome — mini-cart dropdown (Astra's built-in cart widget). */
.ast-site-header-cart .widget_shopping_cart,
.astra-cart-drawer {
	border-radius: var(--pl-radius-card) !important;
	box-shadow: var(--pl-shadow-card-lg) !important;
	border: none !important;
}
.widget_shopping_cart .quantity {
	color: var(--pl-navy);
}

/* Header chrome — mobile off-canvas menu (Astra's built-in mobile menu). */
.ast-mobile-popup-drawer,
.ast-flyout-svg-container {
	box-shadow: var(--pl-shadow-card-lg) !important;
}
.ast-mobile-popup-drawer .main-header-bar-navigation a {
	color: var(--pl-navy);
}

/* Sitewide H1 (category archive title, PDP title, page title) — bumped to
   700 weight with tight negative tracking for more visual presence/"solid"
   feel with the Montserrat swap; size (32px, Astra's own default) already
   reasonable, left alone. */
h1 {
	font-weight: 700;
	letter-spacing: -0.02em;
}

/* Static content pages — headings + content-block cards inherit the same
   token pass rather than per-page overrides. */
.ast-single-post .entry-content h1,
.page .entry-content h1,
.page .entry-content h2 {
	color: var(--pl-navy);
}
.page .entry-content .wp-block-group,
.page .entry-content .wp-block-columns > .wp-block-column {
	border-radius: var(--pl-radius-card);
	box-shadow: var(--pl-shadow-card);
	padding: 1.5rem;
}

/* Hero carousel (see inc/hero-carousel.php shortcode + assets/hero-carousel.js).
   Superseded the earlier static block-pattern hero (functions.php still
   registers printerland_register_hero_pattern for the block inserter, but
   the homepage uses the [printerland_hero] shortcode instead now). */
.printerland-hero-wrap {
	max-width: 1280px;
	margin: 0.5rem auto;
	padding: 0 1rem;
}
.printerland-hero-carousel {
	position: relative;
	aspect-ratio: 4 / 3;
	background: var(--pl-gray-100);
	border-radius: var(--pl-radius-card);
	box-shadow: var(--pl-shadow-card-lg);
	overflow: hidden;
}
@media (min-width: 640px) {
	.printerland-hero-carousel { aspect-ratio: 21 / 9; }
}

/* Hero row: carousel (~70%) + 2 product side-cards (~30%), matching
   printerra.md's layout (inc/homepage-sections.php printerland_hero_row_shortcode).
   The carousel markup/JS inside .ph-herorow-main is untouched — only nested
   sizing changes here. */
.ph-herorow {
	max-width: 1280px;
	/* Small top gap (right below the header), full section-gap below — see
	   --pl-section-gap comment in :root. */
	margin: 0.5rem auto var(--pl-section-gap);
	padding: 0 1rem;
	display: grid;
	grid-template-columns: 1fr;
	gap: 1rem;
}
/* .printerland-hero-wrap carries its own max-width/margin/padding for
   contexts where it's used standalone — nested inside .ph-herorow (which
   already provides that same outer spacing), it was double-applying that
   padding at every width below 1024px, visibly shrinking the carousel on
   mobile/tablet. Unconditional, not just at the desktop breakpoint. */
.ph-herorow .printerland-hero-wrap { max-width: none; margin: 0; padding: 0; }
@media (min-width: 1024px) {
	.ph-herorow { grid-template-columns: minmax(0, 7fr) minmax(0, 3fr); }
	.ph-herorow .printerland-hero-carousel { aspect-ratio: 16 / 7; }
}
.ph-herorow-side {
	display: grid;
	grid-template-rows: 1fr 1fr;
	gap: 1rem;
}
.ph-sidecard {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 0.3rem;
	background: var(--pl-white-gradient);
	box-shadow: var(--pl-shadow-card);
	border-radius: var(--pl-radius-card);
	padding: 1rem 6.5rem 1rem 1rem;
	min-height: 110px;
	text-decoration: none;
	overflow: hidden;
}
.ph-sidecard:hover { box-shadow: var(--pl-shadow-card-lg); }
.ph-sidecard-badge {
	align-self: flex-start;
	background: var(--pl-accent-gradient);
	box-shadow: var(--pl-shadow-chip);
	color: #fff;
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	padding: 0.15rem 0.5rem;
	border-radius: 9999px;
}
.ph-sidecard-name {
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--pl-navy);
	line-height: 1.3;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.ph-sidecard-prices { font-size: 0.9rem; font-weight: 800; color: var(--pl-navy); }
.ph-sidecard-prices del { color: var(--pl-gray-600); font-weight: 400; font-size: 0.85em; margin-right: 0.3em; }
.ph-sidecard-prices ins { text-decoration: none; }
.ph-sidecard-link { font-size: 0.78rem; color: var(--pl-accent); font-weight: 600; }
.ph-sidecard-img {
	position: absolute;
	right: 0.75rem;
	top: 50%;
	transform: translateY(-50%);
	width: 5.5rem;
	height: 5.5rem;
	display: flex;
	align-items: center;
	justify-content: center;
	/* White, not gray — product/category images already have their own
	   white background baked in on this catalog, so a gray container
	   showed as a visible mismatched box around every photo. Same fix
	   already applied to the main shop grid (assets/shop.css). */
	background: #fff;
	border-radius: calc(var(--pl-radius-card) - 8px);
}
.ph-sidecard-img img { max-width: 80%; max-height: 80%; object-fit: contain; }
.ph-slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity 0.7s ease-in-out;
	pointer-events: none;
}
.ph-slide.is-active {
	opacity: 1;
	pointer-events: auto;
	z-index: 1;
}
.ph-slide-img, .ph-slide-link {
	display: block;
	width: 100%;
	height: 100%;
}
.ph-slide-img {
	object-fit: cover;
}
.ph-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
	/* !important — same Astra global <button> padding override fought on
	   .ph-dot below; happened to render close to the intended size here by
	   coincidence of box-sizing, but the padding was still leaking through. */
	width: 2.25rem !important;
	height: 2.25rem !important;
	padding: 0 !important;
	min-width: 0 !important;
	min-height: 0 !important;
	border: none;
	border-radius: 9999px;
	background: rgba(0, 0, 0, 0.25);
	backdrop-filter: blur(4px);
	color: #fff;
	cursor: pointer;
	display: none;
	align-items: center;
	justify-content: center;
}
@media (min-width: 640px) {
	.ph-arrow { display: flex; }
}
.ph-arrow-prev { left: 0.75rem; }
.ph-arrow-next { right: 0.75rem; }
.ph-dots {
	position: absolute;
	bottom: 0.75rem;
	left: 50%;
	transform: translateX(-50%);
	z-index: 2;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	background: rgba(0, 0, 0, 0.25);
	backdrop-filter: blur(4px);
	border-radius: 9999px;
	padding: 0.375rem 0.75rem;
}
/* !important — Astra's global <button> reset (padding, min sizing) was
   winning over this plain class selector, rendering each dot as a 36×24px
   button with 12px/18px padding instead of a 6px circle (confirmed live
   via computed style) — same class of override already fought elsewhere
   in this file (.ph-mega-menu-back). */
.ph-dot {
	width: 0.375rem !important;
	height: 0.375rem !important;
	padding: 0 !important;
	min-width: 0 !important;
	min-height: 0 !important;
	border-radius: 9999px !important;
	border: none !important;
	background: rgba(255, 255, 255, 0.5) !important;
	cursor: pointer;
	transition: width 0.3s ease;
}
.ph-dot.is-active {
	width: 1.25rem !important;
	background: #fff !important;
}
.ph-progress-track {
	position: absolute;
	bottom: 0;
	left: 0;
	right: 0;
	z-index: 2;
	height: 3px;
	background: rgba(0, 0, 0, 0.1);
}
.ph-progress-fill {
	height: 100%;
	width: 0;
	background: rgba(255, 255, 255, 0.6);
}
@keyframes printerlandHeroProgress {
	from { width: 0%; }
	to { width: 100%; }
}

/* Homepage sections (see inc/homepage-sections.php) — category icon strip
   and Reduceri/Rate promo banners, modeled on printerland.md's real
   homepage structure but in this theme's own navy/coral visual language. */
.ph-catstrip-wrap {
	position: relative;
	max-width: 1280px;
	/* Larger gap below — the next section (.ph-deal-bleed) is a full-bleed
	   navy band, which needs more separation than a plain section boundary
	   to avoid reading as colliding with the strip above it. */
	margin: 0 auto var(--pl-section-gap-lg);
	/* Gray panel backdrop — every white tile inside sat directly on the
	   page's own white background with nothing behind it, so contrast
	   depended entirely on each tile's own (necessarily subtle) shadow/
	   border — reported repeatedly as low-contrast/hard to see. Same fix
	   already proven on the v2 homepage's category grid (.phv2-catgrid-wrap):
	   a light gray backdrop so white tiles read as cards sitting ON a
	   surface, not floating on the bare page. Applies to both this
	   curated-8 homepage strip and .ph-catstrip-wrap-archive (every
	   category page) for one consistent treatment everywhere this
	   component appears. Gradient, not a flat fill, for a softer/more
	   premium sheen — matches the gradient treatment already used on other
	   surfaces this session. */
	background: var(--pl-gray-gradient);
	border-radius: var(--pl-radius-card);
	padding: 1.25rem;
	display: flex;
	align-items: center;
	gap: 0.5rem;
}
.ph-catstrip {
	flex: 1;
	min-width: 0;
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 140px;
	gap: 0.75rem;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
}
.ph-catstrip::-webkit-scrollbar { display: none; }
/* .ph-catstrip-wrap-archive (category archive pages,
   printerland_category_children_strip()) reuses this same component for
   the CURRENT category's real subcategory count — unlike the curated
   homepage strip below (always exactly 8, fine as a horizontal-scroll
   strip even on mobile), that can be anywhere from 1 to 20+ (e.g.
   "Accesorii și piese de schimb" has 21). Wraps onto rows with a denser
   tile at EVERY width, not just desktop — scrolling sideways through 21
   items on mobile was worse than wrapping+collapsing there too, and this
   keeps the pattern consistent at every viewport instead of switching
   behavior at 1024px. The show-more/less toggle (assets/homepage.js)
   collapses it to 2 rows at any width when there's a 3rd to hide. */
.ph-catstrip-wrap-archive .ph-catstrip {
	display: grid;
	grid-auto-flow: row;
	grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
	/* Wider than the base 0.5rem — at 0.5rem, the shadows of adjacent
	   compact tiles visually merged into what read as a flat gray fill
	   rather than individual card shadows (reported/confirmed live:
	   "shadows very near and look gray"). */
	gap: 0.65rem;
	overflow-x: visible;
}
.ph-catstrip-wrap-archive .ph-catstrip-arrow { display: none; }
.ph-catstrip-wrap-archive .ph-catstrip-item {
	gap: 0.35rem;
	padding: 0.65rem 0.4rem;
	/* Lighter than the base --pl-shadow-card, which is tuned for larger,
	   more spaced-out cards — too heavy at this tile size even with the
	   wider gap above. A crisp border reads at a glance even before the
	   (now subtle) shadow does, per feedback on this specific tile size. */
	border: 1px solid rgb(var(--pl-navy-rgb) / 0.1);
	box-shadow: 0 2px 6px -2px rgb(0 0 0 / 0.08);
}
.ph-catstrip-wrap-archive .ph-catstrip-item:hover {
	border-color: rgb(var(--pl-navy-rgb) / 0.2);
	box-shadow: 0 4px 10px -2px rgb(0 0 0 / 0.12);
}
.ph-catstrip-wrap-archive .ph-catstrip-name { font-size: 0.75rem; }
.ph-catstrip-wrap-archive .ph-catstrip-count { font-size: 0.66rem; }
@media (min-width: 1024px) {
	/* Enough room for all 8 tiles — fill the container edge-to-edge instead
	   of leaving trailing whitespace after a fixed 96px tile width. */
	.ph-catstrip { grid-auto-columns: minmax(0, 1fr); overflow-x: visible; }
	.ph-catstrip-wrap-archive .ph-catstrip { grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); }
}
.ph-catstrip-item {
	scroll-snap-align: start;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.5rem;
	padding: 1rem 0.5rem;
	background: #fff;
	box-shadow: var(--pl-shadow-card);
	border-radius: var(--pl-radius-card);
	text-decoration: none;
	text-align: center;
	transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.ph-catstrip-item:hover {
	box-shadow: var(--pl-shadow-card-lg);
	transform: translateY(-2px);
}
.ph-catstrip-photo {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 1;
	border-radius: calc(var(--pl-radius-card) - 8px);
	background: #fff;
	color: var(--pl-navy);
	overflow: hidden;
}
.ph-catstrip-photo img {
	max-width: 80%;
	max-height: 80%;
	object-fit: contain;
}
.ph-catstrip-name {
	font-size: 0.8rem;
	font-weight: 600;
	color: var(--pl-navy);
	line-height: 1.25;
	/* Single-word category names ("Multifuncționale") have no space to wrap
	   at, so they rendered on one line wider than the ~78px card and bled
	   into the next card (confirmed live via getBoundingClientRect: name
	   width 108px inside a 78px card). width:100% + break-word forces a
	   mid-word wrap instead, same as the multi-word names already do. */
	width: 100%;
	overflow-wrap: break-word;
	word-break: break-word;
	hyphens: auto;
}
.ph-catstrip-count {
	font-size: 0.7rem;
	color: var(--pl-gray-600);
}
.ph-catstrip-arrow {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.25rem;
	height: 2.25rem;
	border-radius: 9999px;
	border: none;
	background: #fff;
	color: var(--pl-navy);
	box-shadow: var(--pl-shadow-card);
	cursor: pointer;
}
.ph-catstrip-arrow:hover { box-shadow: var(--pl-shadow-card-lg); }
.ph-catstrip-arrow[hidden] { display: none; }
/* Show more/less toggle for .ph-catstrip-wrap-archive when a category has
   enough subcategories to overflow the collapsed row count
   (assets/homepage.js printerlandInitCatstripCollapse()) — only inserted
   into the DOM when actually needed, so this never shows for a category
   with few subcategories. */
/* Compact centered pill, not a full-width bar — at 100% width with only a
   faint 15%-opacity border and no fill, this read as a flat gray box
   rather than a button (confirmed live/reported). A visible tinted fill
   plus content-width sizing reads as an actual control. */
.ph-catstrip-toggle {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	width: auto;
	margin: 0.75rem auto 0;
	padding: 0.5rem 1.1rem;
	/* Stronger than the original 6%-opacity fill (same low-contrast-on-
	   white-page issue as the tiles above) — a visible border plus a
	   slightly bolder tint reads clearly as a real button. */
	background: rgb(var(--pl-navy-rgb) / 0.08);
	border: 1px solid rgb(var(--pl-navy-rgb) / 0.18);
	border-radius: 9999px;
	color: var(--pl-navy);
	font-weight: 600;
	font-size: 0.82rem;
	cursor: pointer;
}
.ph-catstrip-toggle:hover,
.ph-catstrip-toggle:focus {
	background: rgb(var(--pl-navy-rgb) / 0.16);
	border-color: rgb(var(--pl-navy-rgb) / 0.3);
	color: var(--pl-navy);
}
.ph-catstrip-toggle .ph-cat-chevron { transition: transform 0.2s ease; }
.ph-catstrip-toggle.is-open .ph-cat-chevron { transform: rotate(180deg); }
@media (min-width: 1024px) {
	/* All 8 tiles fit without scrolling at this width — arrows would be
	   decorative, so hide them; homepage.js also hides them dynamically
	   whenever content doesn't overflow. */
	.ph-catstrip-arrow { display: none; }
}

.ph-promo-banners {
	max-width: 1280px;
	margin: 0 auto var(--pl-section-gap);
	padding: 0 1rem;
	display: grid;
	grid-template-columns: 1fr;
	gap: 1rem;
}
@media (min-width: 640px) {
	.ph-promo-banners { grid-template-columns: 1fr 1fr; }
	/* Credit installments banner removed along with the Credit page — a
	   single remaining banner shouldn't half-fill the two-column grid it
	   used to share. */
	.ph-promo-banners-single { grid-template-columns: 1fr; }
}
.ph-promo-banner {
	display: block;
	min-height: 140px;
	padding: 1.5rem;
	border-radius: var(--pl-radius-card);
	text-decoration: none;
	background: var(--pl-navy-sheen);
	box-shadow: var(--pl-shadow-card-lg);
	transition: transform 0.2s ease;
}
.ph-promo-banner:hover { transform: translateY(-2px); }
.ph-promo-banner-text {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	max-width: 70%;
}
.ph-promo-banner-title {
	font-size: 1.5rem;
	font-weight: 800;
	color: #fff;
}
.ph-promo-banner-sub {
	font-size: 0.85rem;
	color: rgba(255, 255, 255, 0.75);
}
.ph-promo-banner-cta {
	margin-top: 0.5rem;
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-weight: 700;
	font-size: 0.85rem;
	color: var(--pl-accent);
}

.ph-brandstrip {
	max-width: 1280px;
	margin: 0 auto var(--pl-section-gap);
	padding: 0 1rem;
}
.ph-brandstrip-title {
	font-size: 1.1rem;
	font-weight: 700;
	color: var(--pl-navy);
	margin-bottom: 0.75rem;
}
.ph-brandstrip-row {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
}
.ph-brandstrip-item {
	padding: 0.5rem 1.1rem;
	border-radius: 9999px;
	border: 1px solid rgb(0 0 0 / 0.08);
	color: var(--pl-navy);
	font-weight: 700;
	font-size: 0.9rem;
	text-decoration: none;
	transition: border-color 0.2s ease, color 0.2s ease;
}
.ph-brandstrip-item:hover {
	border-color: var(--pl-accent);
	color: var(--pl-accent);
}

/* Footer trust strip (inc/footer-extras.php) — shipping/returns/warranty/
   installments row below the footer. Payment methods are styled text
   chips, not brand logos — real Visa/Mastercard SVGs are trademarked
   assets not in this repo and won't be fabricated (matches the existing
   PDP .printerland-payment-chips pattern). */
.ph-footer-trust-bleed {
	background: #10233a;
}
.ph-footer-trust-bleed .ph-bleed-inner {
	padding: 1.5rem 1rem;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
}
.ph-footer-trust {
	display: flex;
	flex-wrap: wrap;
	gap: 1.25rem;
}
.ph-footer-trust-item {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	color: rgba(255, 255, 255, 0.85);
	font-size: 0.82rem;
}
.ph-footer-pay {
	display: flex;
	gap: 0.5rem;
}
.ph-footer-pay-chip {
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: var(--pl-radius-sm);
	padding: 0.3rem 0.65rem;
	font-size: 0.75rem;
	color: rgba(255, 255, 255, 0.7);
}

/* Reference homepage has no visible page title — "Acasă"/"Главная"/"Home"
   was rendering above the category strip on every language homepage. */
.home .entry-title { display: none; }

/* calc(-50vw + 50%) full-bleed sections below introduce a few px of
   horizontal scroll on some viewports (confirmed: 20px overflow on a
   390px mobile viewport, whole page shifted left) — 100vw's relationship
   to the actual rendered width isn't perfectly exact everywhere. Hiding
   overflow-x is the correct fix here, not widening the container (that
   would just move the mismatch instead of removing it). */
html, body { overflow-x: hidden !important; max-width: 100%; }

/* WooCommerce's price del/ins markup carries a .screen-reader-text span
   ("Original price was: X. Current price is: Y.") meant to be visually
   invisible — clipped, not display:none, so screen readers still get it.
   Astra/WP core only define the legacy `clip: rect(...)` half of this
   technique; some browsers' copy/text-extraction (and apparently some
   render paths) don't fully treat clip-rect alone as excluded. Adding the
   modern clip-path pairing WP core itself now ships is the actual fix —
   redeclared here with !important since this must always win regardless
   of where it's nested (deal boxes, side-cards, price displays). */
.screen-reader-text {
	border: 0 !important;
	clip: rect(1px, 1px, 1px, 1px) !important;
	clip-path: inset(50%) !important;
	height: 1px !important;
	width: 1px !important;
	overflow: hidden !important;
	position: absolute !important;
	word-wrap: normal !important;
	margin: -1px !important;
	padding: 0 !important;
}
/* Belt-and-braces: even if reader-only text somehow renders in some
   environment, these price containers can never visually exceed their box. */
.ph-deal-box-price,
.ph-deal-box-alt-price,
.ph-sidecard-prices {
	overflow: hidden;
}

/* Full-bleed band utility — breaks a section out of the .ast-container
   (which caps content at 1320px) to span the full viewport width, while
   keeping its content aligned to the same 1320px column other sections
   use. Copies Astra's own known-good idiom for this container (its
   .ast-article-image-container--full uses the same calc()). */
.ph-bleed {
	/* calc(-50vw + 50%) only cancels out correctly when the element's own
	   containing block equals the full viewport width — it doesn't here,
	   Astra's .ast-container/.entry-content carries its own horizontal
	   padding, so "50%" and "50vw" weren't actually equal-and-opposite.
	   Confirmed live: elements using this sat at x:20-410 on a 390px
	   viewport instead of 0-390 — visually clipped on the right by
	   overflow-x:hidden, not caught by any page-level scroll check.
	   position:relative + left:50% + translateX(-50%) is the version that
	   correctly handles a padded, centered parent: left:50% shifts from
	   the element's static (already-padded) position by half the
	   container's width, and the transform pulls back by half the
	   element's own (100vw) width — net result lands on the true
	   viewport edges regardless of the parent's padding. */
	position: relative;
	left: 50%;
	transform: translateX(-50%);
	width: 100vw;
	max-width: 100vw;
}
.ph-bleed-inner {
	max-width: 1320px;
	margin: 0 auto;
	padding: 2.5rem 1rem;
}

/* Deal strip — two boxes ("Oferta săptămânii" + "Produse populare"), each a
   main pick plus up to 3 alternates, on a full-bleed navy band. Mirrors
   printerra.md's homepage layout (inc/homepage-sections.php). */
/* Top margin left at 0 — .ph-catstrip-wrap above already carries the
   section-gap-lg needed here via its own margin-bottom. */
.ph-deal-bleed { background: var(--pl-navy-sheen); margin: 0 0 var(--pl-section-gap-lg); }
.ph-deal-bleed .ph-bleed-inner { padding: 2.5rem 1rem; }
.ph-deal-section {
	display: grid;
	/* minmax(0, 1fr), not plain 1fr — a bare 1fr grid track still respects
	   its content's min-content width by default. Real bug found live: the
	   right box (.ph-deal-box-info's own min-width:180px, below, plus the
	   fixed-width image/gaps/padding around it) added up to ~340-390px of
	   unshrinkable content, wider than a 390px mobile viewport, so the box
	   rendered cut off past the right edge instead of wrapping/shrinking. */
	grid-template-columns: minmax(0, 1fr);
	gap: 1.5rem;
}
@media (min-width: 900px) {
	.ph-deal-section { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.ph-deal-box {
	min-width: 0;
	background: var(--pl-white-gradient);
	border-radius: var(--pl-radius-card);
	padding: 1.5rem;
	box-shadow: var(--pl-shadow-card-lg);
}
.ph-deal-box-eyebrow {
	display: block;
	color: var(--pl-accent);
	font-weight: 700;
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	margin-bottom: 1rem;
}
.ph-deal-box-main {
	display: flex;
	flex-wrap: wrap;
	gap: 1.25rem;
	align-items: center;
	padding-bottom: 1.25rem;
	border-bottom: 1px solid var(--pl-gray-100);
	margin-bottom: 1.25rem;
}
.ph-deal-box-image {
	position: relative;
	background: #fff;
	border-radius: calc(var(--pl-radius-card) - 8px);
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 140px;
	height: 140px;
}
.ph-deal-box-image img {
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;
	padding: 0.75rem;
}
.ph-deal-box-badge {
	position: absolute;
	top: 0.5rem;
	left: 0.5rem;
	background: var(--pl-accent-gradient);
	box-shadow: var(--pl-shadow-chip);
	color: #fff;
	font-weight: 800;
	font-size: 0.85rem;
	padding: 0.25rem 0.6rem;
	border-radius: 9999px;
}
.ph-deal-box-info {
	flex: 1 1 180px;
	/* Was min-width:180px — the actual overflow driver on narrow viewports
	   (see .ph-deal-section comment above). 0 lets it shrink and wrap the
	   product name instead of forcing the row past the container edge. */
	min-width: 0;
}
.ph-deal-box-info h3 {
	margin: 0 0 0.5rem;
	font-size: 1.1rem;
}
.ph-deal-box-info h3 a {
	color: var(--pl-navy);
	text-decoration: none;
}
.ph-deal-box-price {
	color: var(--pl-navy);
	font-weight: 800;
	font-size: 1.25rem;
	margin-bottom: 0.85rem;
}
.ph-deal-box-cta {
	display: inline-flex;
	background: var(--pl-accent-gradient);
	box-shadow: var(--pl-shadow-chip);
	color: #fff;
	font-weight: 700;
	padding: 0.6rem 1.4rem;
	border-radius: 9999px;
	text-decoration: none;
	font-size: 0.9rem;
}
.ph-deal-box-alts {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.75rem;
}
.ph-deal-box-alts li a {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	text-decoration: none;
	color: inherit;
	min-width: 0;
}
.ph-deal-box-alts img {
	width: 44px;
	height: 44px;
	object-fit: contain;
	background: #fff;
	border-radius: var(--pl-radius-sm);
	flex-shrink: 0;
}
.ph-deal-box-alt-name {
	flex: 1;
	min-width: 0;
	font-size: 0.85rem;
	color: var(--pl-navy);
	line-height: 1.3;
}
.ph-deal-box-alt-price {
	font-size: 0.85rem;
	font-weight: 700;
	color: var(--pl-navy);
	white-space: nowrap;
}

/* Product grid rows (inc/homepage-sections.php printerland_product_rows())
   — alternating full-bleed backgrounds, replacing the flat h2+[products]
   siblings that used to live in the homepage post_content (couldn't be
   banded there). Grid/card styling for ul.products itself comes from
   assets/shop.css, already enqueued on the front page. */
.ph-prow { background: #fff; }
.ph-prow-alt { background: var(--pl-gray-100); }
/* These 4 rows (Recomandate/Imprimante/Cartușe/Populare) stack with zero
   margin between them, distinguished only by an alternating background —
   2rem padding gave a 64px combined gap, which read as cramped next to a
   dense 4-column product grid (measured live, not guessed: last product
   card and the next section's heading sat closer than the breathing room
   used elsewhere on the page). Bumped to 3rem for real separation. */
.ph-prow .ph-bleed-inner { padding: 3rem 1rem; }
.entry-content h2.ph-prow-title {
	/* Astra's .entry-content h2 default (36px) otherwise wins over a bare
	   .ph-prow-title class on specificity — this runs inside .entry-content
	   since it's prepended via the_content. Bumped size/weight and tightened
	   tracking with the Montserrat swap — more presence for section titles,
	   tight negative tracking is the standard "premium" heading treatment. */
	text-align: left;
	color: var(--pl-navy);
	font-size: 1.6rem;
	font-weight: 700;
	letter-spacing: -0.01em;
	margin: 0 0 1.25rem;
}

/* SEO/about text block (inc/homepage-sections.php) — full-bleed light band.
   Collapsed <details>: fully indexed by crawlers, one-line toggle for visitors. */
.ph-seo-bleed { background: var(--pl-gray-100); margin: var(--pl-section-gap-lg) 0 0; }
.ph-seo-text {
	color: var(--pl-gray-600);
	font-size: 0.9rem;
	line-height: 1.7;
	padding: 1.25rem 0;
}
.ph-seo-text summary {
	cursor: pointer;
	font-weight: 600;
	color: var(--pl-navy);
	list-style: revert;
}
.ph-seo-text p { margin: 1rem 0 0; }

/* Category/subcategory/brand archive term-description (inc/archive-
   description-collapse.php) — same collapsed-<details> treatment as
   .ph-seo-text above, scoped to the shop-loop intro instead of the homepage. */
.printerland-archive-copy {
	margin: 0 0 1.5rem;
	color: var(--pl-gray-600);
	font-size: 0.9rem;
	line-height: 1.7;
}
.printerland-archive-copy summary {
	cursor: pointer;
	font-weight: 600;
	color: var(--pl-navy);
	list-style: revert;
}
.printerland-archive-copy p { margin: 1rem 0 0; }

/* Newsletter signup (inc/homepage-sections.php + assets/newsletter.js).
   No top margin — sits directly against .ph-seo-bleed above; both are
   full-bleed colored bands, so a gap here would show a strip of plain page
   background wedged between two bands rather than reading as intentional
   spacing. */
.ph-newsletter-bleed {
	background: var(--pl-navy-sheen);
	margin: 0;
}
.ph-newsletter-bleed .ph-bleed-inner { padding: 2.5rem 1.5rem; }
.ph-newsletter {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	max-width: 1280px;
	margin: 0 auto;
}
.ph-newsletter-text h3 { color: #fff; margin: 0 0 0.35rem; font-size: 1.25rem; }
.ph-newsletter-text p { color: rgba(255,255,255,0.75); margin: 0; font-size: 0.9rem; }
.ph-newsletter-form {
	display: flex;
	gap: 0.5rem;
	flex: 1;
	max-width: 26rem;
}
.ph-newsletter-form input {
	flex: 1;
	padding: 0.75rem 1.1rem;
	border-radius: 9999px;
	border: none;
	font-size: 0.9rem;
}
.ph-newsletter-form button {
	background: var(--pl-accent-gradient);
	box-shadow: var(--pl-shadow-chip);
	color: #fff;
	border: none;
	font-weight: 700;
	padding: 0.75rem 1.5rem;
	border-radius: 9999px;
	cursor: pointer;
	white-space: nowrap;
}
.ph-newsletter-message {
	width: 100%;
	text-align: center;
	font-size: 0.85rem;
	margin-top: 1rem;
	color: #fff;
}
.ph-newsletter-message.is-error { color: var(--pl-accent); }

/* Header (see inc/header.php + assets/header.js) — replaces Astra's default header. */
.ph-topbar {
	background: var(--pl-navy-gradient);
	color: #fff;
	font-size: 0.8rem;
}
.ph-topbar-inner {
	max-width: 1280px;
	margin: 0 auto;
	padding: 0.4rem 1rem;
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 1rem;
}
.ph-topbar-contact a {
	color: #fff;
	text-decoration: none;
	white-space: nowrap;
}
/* Utility links (Credit/Showroom/Promoții/Livrare/Contact) used to be
   display:none below 768px — only the phone number showed, which read as
   "language switching doesn't reach these" since their translated labels
   were simply never rendered on mobile at all. Compact horizontal scroll
   instead of hiding outright. */
.ph-topbar-nav {
	display: flex;
	gap: 1rem;
	overflow-x: auto;
	scrollbar-width: none;
	min-width: 0;
	position: relative;
}
.ph-topbar-nav::-webkit-scrollbar { display: none; }
@media (max-width: 767px) {
	/* Hidden scrollbar gives no hint there's more to the right (Promoții,
	   Contact) — a fade at the edge is the standard affordance for a
	   horizontally-scrollable row like this. */
	.ph-topbar-inner { position: relative; }
	.ph-topbar-inner::after {
		content: "";
		position: absolute;
		top: 0;
		right: 0;
		bottom: 0;
		width: 1.5rem;
		background: linear-gradient(to right, transparent, var(--pl-navy) 85%);
		pointer-events: none;
	}
}
@media (min-width: 768px) {
	.ph-topbar-nav { gap: 1.5rem; overflow-x: visible; }
}
.ph-topbar-nav a {
	color: rgba(255, 255, 255, 0.85);
	text-decoration: none;
	white-space: nowrap;
}
.ph-topbar-nav a:hover { color: #fff; }

/* Astra's own below-header nav row (Astra core rendering the 'primary' menu
   location — this theme has no wp_nav_menu() call of its own). Its 5 links
   are now merged into the topbar above (inc/header.php) — same links,
   fewer rows — so this whole row is redundant. */
.ast-primary-header-bar {
	display: none !important;
}

.ph-header {
	background: #fff;
	border-bottom: 1px solid var(--pl-gray-100);
	position: sticky;
	top: 0;
	z-index: 999;
}
.ph-header-inner {
	max-width: 1280px;
	margin: 0 auto;
	padding: 0.75rem 1rem;
	display: flex;
	align-items: center;
	gap: 1rem;
	flex-wrap: wrap;
}
.ph-logo {
	font-weight: 900;
	font-size: 1.35rem;
	color: var(--pl-navy);
	text-decoration: none;
	white-space: nowrap;
}
.ph-logo-accent { color: var(--pl-accent); }

/* Catalog menu is reachable at every breakpoint now — it used to be
   display:none below 768px, meaning there was no way to browse categories
   on mobile except Astra's generic hamburger drawer, which doesn't know
   about product categories at all. */
.ph-mega-menu-wrap { position: relative; }
/* Hides the header Catalog button ONLY on the v2 homepage's desktop
   layout, where its own persistent sidebar (.phv2-sidebar,
   assets/home-v2.css) does the same job — matches that sidebar's exact
   breakpoint (display:none below this) so mobile visitors on v2 always
   have one category-nav entry point, never zero. inc/header.php only
   adds this class on is_front_page() + v2, so it never applies anywhere
   else (v1 homepage, category/product/cart/search pages keep this
   button unconditionally at every width). */
@media (min-width: 1024px) {
	.ph-mega-menu-wrap-v2-home { display: none; }
}
.ph-mega-menu-toggle {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.65rem 1.25rem;
	background: var(--pl-navy-gradient);
	box-shadow: var(--pl-shadow-chip);
	color: #fff;
	border: none;
	border-radius: var(--pl-radius-card);
	font-weight: 600;
	cursor: pointer;
	transition: background 0.15s ease;
}
.ph-mega-menu-toggle:hover,
.ph-mega-menu-toggle[aria-expanded="true"] {
	background: var(--pl-accent);
}
/* Dropdown affordance — nothing on the button previously signaled it opens
   a menu rather than navigating away. */
.ph-mega-menu-toggle .ph-svg-icon {
	width: 16px;
	height: 16px;
	transition: transform 0.15s ease;
}
.ph-mega-menu-toggle[aria-expanded="true"] .ph-svg-icon {
	transform: rotate(180deg);
}
.ph-mega-menu {
	position: absolute;
	top: 100%;
	left: 0;
	margin-top: 0.5rem;
	background: var(--pl-white-gradient);
	border-radius: var(--pl-radius-card);
	box-shadow: var(--pl-shadow-card-lg);
	/* Left padding tightened — was the same 1.5rem as every other side,
	   reading as more empty space before the category list than needed.
	   Top/right/bottom stay 1.5rem — .ph-mega-menu-right's negative margin
	   bleed trick (below) is keyed to those three, not this one. */
	padding: 1.5rem 1.5rem 1.5rem 1.15rem;
	display: flex;
	gap: 1.5rem;
	/* `width: max-content` computed preferred size from content (including
	   long unwrapped product names) and only clamped AFTER that — in
	   practice still overflowed the viewport. An explicit width, capped by
	   max-width, is predictable regardless of content length. */
	width: 920px;
	max-width: calc(100vw - 2rem);
	/* Each pane scrolls independently (see .ph-mega-menu-categories /
	   .ph-mega-menu-right below) — this used to be overflow-y:auto here,
	   which scrolled BOTH columns as one unit: opening a category with many
	   subcategories (e.g. "Accesorii și piese de schimb", 21 items) scrolled
	   the left category list out of view along with the right-hand list. */
	align-items: stretch;
	overflow: hidden;
	z-index: 1000;
}
/* The `hidden` attribute (assets/header.js toggles it on open/close) has the
   same 0,1,0 specificity as the class rule above, and author styles always
   win ties over the UA stylesheet's default `[hidden]{display:none}` — so
   without this, the dropdown rendered open on every page load, for every
   visitor, until first click. */
.ph-mega-menu[hidden] { display: none; }
.ph-mega-menu-categories {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	min-width: 220px;
	flex-shrink: 0;
	padding-right: 1rem;
	/* Darkened from 0.06 — at that opacity the pane split was barely
	   perceptible next to the .ph-mega-menu-right background change. */
	border-right: 1px solid rgb(0 0 0 / 0.1);
	/* Scrolls independently from .ph-mega-menu-right — see note on
	   .ph-mega-menu above. Caps to the panel's own max-height (70vh) minus
	   its vertical padding (1.5rem top + bottom). */
	max-height: calc(70vh - 3rem);
	overflow-y: auto;
}
.ph-mega-menu-category-item {
	padding: 0.5rem 0.5rem;
	border-radius: var(--pl-radius-sm);
}
.ph-mega-menu-category-item.is-active,
.ph-mega-menu-category-item:hover {
	background: rgb(var(--pl-navy-rgb) / 0.06);
}
.ph-mega-menu-category {
	font-weight: 700;
	color: var(--pl-navy);
	text-decoration: none;
	display: flex;
	align-items: center;
	gap: 0.6rem;
}
.ph-mega-menu-category-icon {
	width: 28px;
	height: 28px;
	object-fit: contain;
	border-radius: var(--pl-radius-sm);
	background: #fff;
	flex-shrink: 0;
}
/* Right-hand pane — all of the active category's subcategories as a plain
   list (was a wrapping grid of bordered pill tiles — changed per request
   to a simple list, same row style as the left-hand category list, not
   card-shaped tiles). Two columns on wide screens once there are enough
   items to make one long column awkward. */
.ph-mega-menu-right {
	flex: 1;
	display: flex;
	flex-direction: column;
	min-width: 0;
	/* Slightly darker than the left category list (plain white) — a flat
	   two-pane panel with no background difference read as one
	   undifferentiated block; this gives the primary/secondary nav split
	   real visual separation, common practice in mega-menus. */
	background: var(--pl-gray-100);
	border-radius: 0 var(--pl-radius-card) var(--pl-radius-card) 0;
	margin: -1.5rem -1.5rem -1.5rem 0;
	padding: 1.5rem;
	/* Inset shadow along the shared edge, on top of the border-right on
	   .ph-mega-menu-categories — one flat border alone read as too subtle a
	   split between the two panes. */
	box-shadow: inset 6px 0 10px -10px rgb(0 0 0 / 0.15);
	/* Scrolls independently from .ph-mega-menu-categories — see note on
	   .ph-mega-menu above. */
	max-height: calc(70vh - 3rem);
	overflow-y: auto;
}
/* Thin, visibly-scrollable scrollbar on both panes — native default
   scrollbars are easy to miss at this panel size, which is part of why the
   old single-scroll layout read as "broken" rather than "has more below". */
.ph-mega-menu-categories,
.ph-mega-menu-right {
	scrollbar-width: thin;
	scrollbar-color: rgb(var(--pl-navy-rgb) / 0.25) transparent;
}
.ph-mega-menu-categories::-webkit-scrollbar,
.ph-mega-menu-right::-webkit-scrollbar {
	width: 6px;
}
.ph-mega-menu-categories::-webkit-scrollbar-thumb,
.ph-mega-menu-right::-webkit-scrollbar-thumb {
	background: rgb(var(--pl-navy-rgb) / 0.25);
	border-radius: 9999px;
}
.ph-mega-menu-subcats {
	display: grid;
	/* Narrowed from 220px — the right pane is ~600px wide, so 220px only
	   ever fit 2 columns. At 190px a category with many subcategories (e.g.
	   "Accesorii și piese de schimb", 21 items) flows into 3 columns instead
	   of one long scrolling ribbon. */
	grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
	gap: 0.15rem 1rem;
	align-content: start;
}
.ph-mega-menu-subcats[hidden] { display: none; }
.ph-mega-menu-subcat-pill {
	display: flex;
	align-items: flex-start;
	gap: 0.85rem;
	padding: 0.6rem 0.75rem;
	border-radius: var(--pl-radius-sm);
	font-size: 0.92rem;
	font-weight: 500;
	color: var(--pl-navy);
	text-decoration: none;
}
.ph-mega-menu-subcat-pill:hover {
	background: #fff;
	color: var(--pl-accent);
	box-shadow: var(--pl-shadow-card);
}
.ph-mega-menu-subcat-pill span {
	/* Was nowrap + ellipsis — long labels ("Imprimante cu jet de
	   cerneală") got silently cut off, losing information a visitor can't
	   recover without clicking through. Wrapping to 2 lines instead never
	   hides text; line-clamp caps runaway wrapping. */
	line-height: 1.3;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	padding-top: 0.15rem;
}

/* Thumbnail per subcategory row — real category photo
   (printerland_category_image_url(), same source the homepage strip and
   shop-page subcategory grid already use). Bumped up from 22px (near-
   illegible at that size) to a size that actually reads as a photo. */
.ph-mega-menu-subcat-img {
	width: 40px;
	height: 40px;
	object-fit: contain;
	border-radius: var(--pl-radius-sm);
	background: var(--pl-gray-100);
	flex-shrink: 0;
}

/* Mobile drilldown chrome — hidden on desktop, where the "back" step and
   category-name header don't apply (both panes sit side by side there). */
.ph-mega-menu-back,
.ph-mega-menu-subcats-head {
	display: none;
}
/* Fullscreen-only close button (mobile) — desktop's dropdown closes via
   outside-click, same as it always has, no dedicated button needed there. */
.ph-mega-menu-close {
	display: none;
}

@media (max-width: 767px) {
	/* Fullscreen takeover instead of a positioned popover (2026-08 refactor)
	   — the previous version anchored `top` from a JS-measured header
	   height and capped height with a `bottom` inset, which worked but
	   still followed the header's position. `inset: 0` removes that
	   dependency entirely: no offset to compute, no constant to drift
	   stale, matches the site's other mobile fullscreen drawer
	   (assets/shop.css .ph-filter-toggle / #secondary), same z-index tier. */
	.ph-mega-menu {
		position: fixed;
		inset: 0;
		/* Desktop's base rule sets margin-top:0.5rem (dropdown-under-button
		   spacing) — fixed-position elements still respect margin even with
		   inset:0, so without this override the panel rendered a few px
		   short of the true viewport top. */
		margin: 0;
		z-index: 1200;
		width: auto;
		max-width: none;
		max-height: none;
		border-radius: 0;
		box-shadow: none;
		flex-direction: column;
		gap: 0;
		/* Top padding clears the fixed .ph-mega-menu-close button (2.75rem
		   tall + its own 1rem inset) so the category list doesn't render
		   underneath it — same amount .ph-filter-close's host (#secondary,
		   assets/shop.css) reserves for the equivalent close button there. */
		padding: calc(5.5rem + env(safe-area-inset-top)) 1rem calc(1rem + env(safe-area-inset-bottom));
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
	}
	body.ph-catalog-open {
		overflow: hidden;
	}
	.ph-mega-menu-close {
		display: flex;
		align-items: center;
		justify-content: center;
		position: fixed;
		top: calc(1rem + env(safe-area-inset-top));
		right: 1rem;
		z-index: 1201;
		width: 3.5rem;
		height: 3.5rem;
		border: 2px solid rgb(255 255 255 / 0.35);
		border-radius: 9999px;
		background: var(--pl-navy-gradient);
		box-shadow: var(--pl-shadow-chip);
		color: #fff;
		cursor: pointer;
	}
	/* Only one pane is visible at a time here (drilldown) — unlike desktop
	   (both panes visible side-by-side, genuinely needing independent
	   scroll), nesting a second scroll container inside the outer one here
	   just gave two max-height calcs that drift out of sync (confirmed
	   live: the last subcategory sometimes uncrollable-to, clipped between
	   the inner pane's own boundary and the outer one's). The outer
	   `.ph-mega-menu` is the only scroll container on mobile now; panes
	   size to their natural content height instead. */
	.ph-mega-menu-categories,
	.ph-mega-menu-right {
		max-height: none;
		overflow-y: visible;
	}
	.ph-mega-menu-categories {
		min-width: 0;
		border-right: none;
		padding-right: 0;
	}
	.ph-mega-menu-right { display: none; }
	.ph-mega-menu.is-drilldown .ph-mega-menu-categories { display: none; }
	.ph-mega-menu.is-drilldown .ph-mega-menu-right { display: flex; }
	/* Subcategory pills stack full-width on mobile — easier to tap than a
	   wrapped grid. */
	.ph-mega-menu-subcats { grid-template-columns: 1fr; }
	/* Fullscreen has the room a 220px popover column never did — bigger
	   rows, bigger photos, easier to tap/scan than the compact desktop size. */
	.ph-mega-menu-category-item { padding: 0.85rem 0.75rem; }
	.ph-mega-menu-category { gap: 1rem; font-size: 1.05rem; }
	.ph-mega-menu-category-icon { width: 48px; height: 48px; }
	.ph-mega-menu-subcat-pill { padding: 0.9rem 0.75rem; gap: 1rem; font-size: 1rem; }
	.ph-mega-menu-subcat-img { width: 56px; height: 56px; }
	.ph-mega-menu-back,
	.ph-mega-menu-subcats-head {
		display: block;
		text-decoration: none;
	}
	.ph-mega-menu-back {
		/* !important — Astra's parent-theme global button style (customizer
		   color, pill shape) otherwise wins on this bare <button> element.
		   Bigger/clearer per feedback — was a small plain-text link (0.85rem,
		   no background), easy to miss above the subcategory list; now a
		   proper tappable pill matching the rest of the fullscreen catalog's
		   sizing. */
		display: inline-flex !important;
		align-items: center;
		gap: 0.35rem;
		background: var(--pl-mist) !important;
		border: none !important;
		border-radius: 9999px !important;
		color: var(--pl-navy) !important;
		font-weight: 700;
		font-size: 1rem;
		padding: 0.65rem 1.1rem !important;
		margin-bottom: 0.5rem;
		width: auto !important;
		cursor: pointer;
		text-align: left;
	}
	.ph-mega-menu-subcats-head {
		color: var(--pl-navy);
		font-weight: 700;
		font-size: 1rem;
		padding: 0.3rem 0 0.75rem;
	}
}

.ph-search-wrap {
	position: relative;
	flex: 1;
	max-width: 32rem;
	/* Was display:none below 768px with no mobile alternative at all —
	   search was completely absent on phones. Now shown as its own full-
	   width row directly under the logo row (order:1, below logo+catalog
	   toggle which stay at the default order:0) instead of squeezing into
	   the same row (no space for a real input there next to logo+3 icons+
	   hamburger on a narrow screen) — and instead of sorting last, below
	   the icons/hamburger row, which read as "not near the top". */
	display: block;
	order: 1;
	flex-basis: 100%;
	max-width: 100%;
	margin-top: 0.6rem;
}
@media (max-width: 767px) {
	.ph-header-icons {
		order: 2;
		/* Logo+Catalog row and the icon row both left-align by default
		   (flex-wrap's per-line justify-content default), leaving a dead
		   gap on the right on narrow screens — the search row already
		   spans full width so this only affects those two rows.
		   margin-left:auto (desktop's push-to-the-right-of-the-search-bar
		   trick) has to go too, or centering only shifts the icon cluster
		   within whatever leftover space auto-margin already claimed. */
		flex-basis: 100%;
		margin-left: 0;
		justify-content: center;
	}
	.ph-header-inner { justify-content: center; }
}
@media (min-width: 768px) {
	.ph-search-wrap {
		order: 0;
		flex-basis: auto;
		max-width: 32rem;
		margin-top: 0;
	}
}
/* !important on radius — Astra's own input[type] default styling was
   winning over this class selector (computed to 4px live), same override
   class documented in docs/memory/conventions.md. Border color also had
   the OLD navy hardcoded as a literal rgb triple — same stale-tint bug as
   the 4 hover tints fixed earlier, fixed here too via --pl-navy-rgb. */
.ph-search-input {
	width: 100%;
	height: 3rem;
	padding: 0 1.25rem;
	border-radius: var(--pl-radius-card) !important;
	border: 1px solid rgb(var(--pl-navy-rgb) / 0.1);
	background: var(--pl-gray-100);
}
.ph-search-input:focus {
	outline: none;
	background: #fff;
	box-shadow: 0 0 0 2px rgb(var(--pl-navy-rgb) / 0.15);
}
.ph-search-form { position: relative; display: flex; }
.ph-search-submit {
	position: absolute;
	right: 0.25rem;
	top: 50%;
	transform: translateY(-50%);
	background: none;
	border: none;
	cursor: pointer;
	font-size: 1rem;
	padding: 0.5rem 0.75rem;
	/* Astra's global button reset sets white text/icon color for filled
	   buttons — this button has no background, so the white icon was
	   rendering invisible against the search input's light background. */
	color: var(--pl-navy);
}
.ph-search-submit:hover {
	/* Astra's global button:hover rule fills the background with the accent
	   color; without an explicit override here it collides with the accent
	   text color below, making the icon invisible against its own bg. */
	background: none !important;
	color: var(--pl-accent);
}
.ph-search-results {
	position: absolute;
	left: 0;
	right: 0;
	margin-top: 0.5rem;
	background: #fff;
	border-radius: var(--pl-radius-card);
	box-shadow: var(--pl-shadow-card-lg);
	overflow: hidden;
	z-index: 60;
}
.ph-search-result {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.75rem 1rem;
	text-decoration: none;
	color: inherit;
	border-bottom: 1px solid var(--pl-gray-100);
}
.ph-search-result img { width: 40px; height: 40px; object-fit: cover; border-radius: var(--pl-radius-sm); }
.ph-search-result strong { margin-left: auto; color: var(--pl-navy); }
.ph-search-empty { padding: 1rem; color: var(--pl-gray-600); font-size: 0.9rem; }
.ph-search-view-all {
	display: block;
	text-align: center;
	padding: 0.75rem 1rem;
	color: var(--pl-accent);
	font-weight: 600;
	font-size: 0.9rem;
	text-decoration: none;
}
.ph-search-view-all:hover { background: var(--pl-gray-100); }

.ph-lang-switcher { position: relative; }
.ph-lang-current {
	background: none;
	border: 1px solid rgb(0 0 0 / 0.1);
	border-radius: var(--pl-radius-card);
	color: var(--pl-navy);
	font-weight: 600;
	font-size: 0.8rem;
	padding: 0.4rem 0.75rem;
	cursor: pointer;
}
/* Astra's global button:hover fills a solid accent background — clashes with
   the subtle navy-tint hover language used by every other header control
   (.ph-icon, .ph-lang-option, .ph-mobile-menu-toggle). Override explicitly. */
.ph-lang-current:hover {
	background: rgb(var(--pl-navy-rgb) / 0.06) !important;
	color: var(--pl-navy) !important;
	border-color: rgb(var(--pl-navy-rgb) / 0.1);
}
.ph-lang-options {
	position: absolute;
	top: 100%;
	right: 0;
	margin-top: 0.4rem;
	background: #fff;
	/* Floating panel, same family as .ph-search-results/.ph-mega-menu —
	   card radius, not the small 8px used for tight inline chips. */
	border-radius: var(--pl-radius-card);
	box-shadow: var(--pl-shadow-card-lg);
	padding: 0.4rem;
	display: flex;
	flex-direction: column;
	min-width: 8rem;
	z-index: 1000;
}
.ph-lang-options[hidden] { display: none; }
.ph-lang-option {
	color: var(--pl-navy);
	text-decoration: none;
	padding: 0.4rem 0.6rem;
	border-radius: var(--pl-radius-sm);
	font-size: 0.85rem;
}
.ph-lang-option:hover { background: rgb(var(--pl-navy-rgb) / 0.06); }
.ph-lang-option.is-active { color: var(--pl-accent); font-weight: 700; }

.ph-header-icons {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin-left: auto;
}
/* Bare icon, no hit-target boundary or hover feedback — every other header
   control (lang switcher, mega-menu toggle) is a pill with a visible hover
   state, so these read as dead/unclickable next to them. Give wishlist/
   compare/cart the same circular pill treatment, sized to a comfortable
   44px tap target. */
.ph-icon {
	position: relative;
	background: none;
	border: none;
	font-size: 1.25rem;
	cursor: pointer;
	color: var(--pl-navy);
	text-decoration: none;
	width: 2.75rem;
	height: 2.75rem;
	/* Card radius (26px), not a full circle — matches the Catalog button,
	   search bar and every other primary header control. */
	border-radius: var(--pl-radius-card);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: background-color 0.15s ease, color 0.15s ease;
}
.ph-icon:hover {
	background: rgb(var(--pl-navy-rgb) / 0.06);
	color: var(--pl-accent);
}
.ph-svg-icon { display: block; flex-shrink: 0; }
.ph-loop-action, .ph-pdp-action, .ph-mobile-menu-toggle { display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem; }
.ph-icon-badge {
	position: absolute;
	top: -0.25rem;
	right: -0.25rem;
	background: var(--pl-accent-gradient);
	box-shadow: var(--pl-shadow-chip);
	color: #fff;
	font-size: 0.65rem;
	min-width: 1.1rem;
	height: 1.1rem;
	border-radius: 9999px;
	display: flex;
	align-items: center;
	justify-content: center;
}
.ph-icon-badge[hidden] { display: none; }
.ph-mobile-menu-toggle {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	border-radius: var(--pl-radius-card);
	background: none;
	border: none;
	font-size: 1.5rem;
	cursor: pointer;
	color: var(--pl-navy);
	transition: background-color 0.15s ease;
}
.ph-mobile-menu-toggle:hover,
.ph-mobile-menu-toggle:focus {
	/* Astra's global `button:focus, button:hover { color: ... }` rule beats
	   this class on specificity (a pseudo-class counts same as a class,
	   button:focus = 0,1,1 vs .ph-mobile-menu-toggle = 0,1,0) and was
	   turning the icon white — invisible against this button's own
	   transparent/light background once tapped (confirmed live, icon
	   vanished after opening the mobile menu). */
	background: rgb(var(--pl-navy-rgb) / 0.06);
	color: var(--pl-navy) !important;
}
@media (min-width: 922px) {
	/* Matches the breakpoint the rest of the header (search row, icon
	   cluster) reflows at. */
	.ph-mobile-menu-toggle { display: none; }
}

.ph-mobile-nav-drawer {
	position: absolute;
	top: 100%;
	left: 1rem;
	right: 1rem;
	margin-top: 0.5rem;
	background: var(--pl-navy-sheen);
	border-radius: var(--pl-radius-card);
	box-shadow: var(--pl-shadow-card-lg);
	padding: 0.5rem;
	display: flex;
	flex-direction: column;
	z-index: 1000;
}
.ph-mobile-nav-drawer[hidden] { display: none; }
.ph-mobile-nav-drawer a {
	color: rgba(255, 255, 255, 0.85);
	text-decoration: none;
	font-weight: 600;
	padding: 0.75rem 1rem;
	border-radius: var(--pl-radius-sm);
}
.ph-mobile-nav-drawer a:hover { background: rgb(255 255 255 / 0.1); color: #fff; }
@media (min-width: 922px) {
	.ph-mobile-nav-drawer { display: none; }
}

/* WooCommerce archive pages (shop/category) get Astra's default
   "separate containers" top spacing (.content-area.primary margin-top,
   ~58px on mobile) — makes sense as breathing room under a plain theme
   header, but this theme's own header already ends with clean white
   space before the breadcrumb, so it read as a large dead gap before
   anything started. Homepage/static pages don't use this wrapper (0px
   there already) — scoped to WooCommerce archives only. */
@media (max-width: 767px) {
	body.woocommerce .content-area.primary,
	body.woocommerce-page .content-area.primary {
		margin-top: 1rem !important;
	}
}

/* Wishlist / compare virtual pages (see inc/wishlist-compare.php). */
.ph-page-shell { max-width: 1200px; margin: 0 auto; padding: 2rem 1.5rem 4rem; }
.ph-empty-state { color: var(--pl-gray-600); padding: 2rem 0; }

/* Static content pages (Despre/Livrare/Credit/etc. — see
   inc/static-page-icons.php). */
.ph-page-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 3rem;
	height: 3rem;
	margin-bottom: 1rem;
	border-radius: 9999px;
	background: color-mix(in srgb, var(--pl-navy) 8%, transparent);
	color: var(--pl-navy);
}
.ph-page-icon svg { width: 22px; height: 22px; }
.ph-wishlist-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
	gap: 1.25rem;
}
.ph-wishlist-card {
	background: var(--pl-white-gradient);
	box-shadow: var(--pl-shadow-card);
	border-radius: var(--pl-radius-card);
	padding: 1rem;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}
.ph-wishlist-card img { width: 100%; aspect-ratio: 1; object-fit: contain; background: #fff; border-radius: var(--pl-radius-sm); }
.ph-wishlist-card-name { color: var(--pl-navy); font-weight: 600; text-decoration: none; font-size: 0.95rem; }
.ph-wishlist-card-price { color: var(--pl-accent); font-weight: 700; }
.ph-wishlist-remove {
	border: 1px solid rgb(0 0 0 / 0.1);
	border-radius: 9999px;
	background: none;
	padding: 0.4rem 0.9rem;
	font-size: 0.8rem;
	cursor: pointer;
	color: var(--pl-gray-600);
}
.ph-wishlist-remove:hover {
	background: rgb(var(--pl-navy-rgb) / 0.06) !important;
	color: var(--pl-navy) !important;
}
.ph-compare-table { width: 100%; border-collapse: collapse; }
.ph-compare-table th, .ph-compare-table td {
	padding: 0.85rem 1rem;
	border-bottom: 1px solid var(--pl-gray-100);
	text-align: left;
	vertical-align: middle;
}
.ph-compare-table th { color: var(--pl-gray-600); font-weight: 600; font-size: 0.85rem; white-space: nowrap; }
.ph-compare-table img { width: 80px; height: 80px; object-fit: contain; background: #fff; border-radius: var(--pl-radius-sm); }
.ph-compare-remove {
	border: 1px solid rgb(0 0 0 / 0.1);
	border-radius: 9999px;
	background: none;
	padding: 0.35rem 0.85rem;
	font-size: 0.8rem;
	cursor: pointer;
	color: var(--pl-gray-600);
}
.ph-compare-remove:hover {
	background: rgb(var(--pl-navy-rgb) / 0.06) !important;
	color: var(--pl-navy) !important;
}

/* [product_categories] grid — used on the homepage, loaded here (not
   shop.css) since is_shop()/is_product_category() etc. don't cover the
   front page. Source product images vary wildly in native size, so
   without a forced aspect-ratio the tiles rendered at wildly inconsistent
   visual sizes (a small connector part next to a full product box shot). */
/* Matches li.product's card treatment (assets/shop.css) instead of
   rendering flat/borderless — when a category archive shows subcategory
   tiles mixed into the same grid as real products (WooCommerce's "show
   subcategories" / "show both" display setting), the two card types used
   to look like they belonged to different sites. Also resets the
   width/margin/float WooCommerce core sets on li.product-category by
   default — li.product already cancels these (assets/shop.css) but
   nothing previously did for li.product-category, leaving it to a
   percentage float width inside this theme's display:grid parent. */
.woocommerce ul.products li.product-category {
	text-align: center;
	border: none !important;
	border-radius: var(--pl-radius-card);
	box-shadow: var(--pl-shadow-card);
	padding: 1rem;
	transition: box-shadow 0.2s ease;
	width: auto !important;
	margin: 0 !important;
	float: none !important;
}
.woocommerce ul.products li.product-category:hover {
	box-shadow: var(--pl-shadow-card-lg);
}
.woocommerce ul.products li.product-category img {
	width: 100% !important;
	height: auto !important;
	aspect-ratio: 1 !important;
	object-fit: contain !important;
	border-radius: var(--pl-radius-sm);
	background: #fff;
}
.woocommerce ul.products li.product-category .woocommerce-loop-category__title {
	color: var(--pl-navy);
	font-weight: 600;
}

/* Astra's native mobile header row (id="ast-mobile-header") — its logo is
   gone now (see functions.php custom_logo removal) but the trigger button
   inside it is still needed in the DOM: header.js's hamburger delegates a
   click to it. Left visible it was just a redundant lone hamburger row
   under our own custom header — hide it, keep it clickable via JS. */
@media (max-width: 921px) {
	#ast-mobile-header {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
	}
}

/* PDP description tab (inc/pdp-description-format.php) — the formatter's
   own output classes (.ph-spec-grid, .ph-compat-chips, etc.) had never
   been styled at all, so even a paragraph it successfully classified
   still rendered as a bare unstyled <dl>/<ul>. */
.ph-spec-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	border: 1px solid var(--pl-gray-100);
	border-radius: var(--pl-radius-card);
	overflow: hidden;
	margin: 0 0 1.5rem;
}
/* display:contents — the wrapping row div isn't itself a grid item, its
   dt/dd children are, so they land in the 2-column grid directly. Doesn't
   affect :nth-child matching, which still walks the DOM regardless of box
   generation. */
/* !important — Astra applies its own display:flex to dl > div children on
   mobile (confirmed live: computed style showed display:flex overriding
   this at 390px, laying dt/dd side by side instead of stacking with the
   single-column grid below), the same class of override already fought
   elsewhere in this file (.ph-mega-menu-back). */
.ph-spec-row { display: contents !important; }
.ph-spec-row dt,
.ph-spec-row dd {
	margin: 0;
	padding: 0.75rem 1rem;
	font-size: 0.9rem;
	border-bottom: 1px solid var(--pl-gray-100);
}
.ph-spec-row dt { font-weight: 600; color: var(--pl-navy); background: var(--pl-gray-100); }
/* Astra's own WooCommerce styles right-align <dd> by default — fine
   stacked in a 2-column grid, wrong once stacked to 1 column on mobile. */
.ph-spec-row dd { color: var(--pl-gray-600); text-align: right !important; }
.ph-spec-row:last-child dt,
.ph-spec-row:last-child dd { border-bottom: none; }
@media (max-width: 480px) {
	/* Long labels next to long values get cramped in two narrow columns
	   on a phone — stack label above value instead. */
	.ph-spec-grid { grid-template-columns: 1fr; }
	.ph-spec-row dt { border-bottom: none; padding-bottom: 0.25rem; }
	.ph-spec-row dd { padding-top: 0; text-align: left !important; }
}

.ph-desc-bullets {
	margin: 0 0 1.5rem;
	padding: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}
.ph-desc-bullets li {
	position: relative;
	padding-left: 1.25rem;
	color: var(--pl-gray-600);
	line-height: 1.6;
}
.ph-desc-bullets li::before {
	content: '';
	position: absolute;
	left: 0;
	top: 0.6em;
	width: 6px;
	height: 6px;
	border-radius: 9999px;
	background: var(--pl-accent);
}

.ph-desc-heading,
.ph-compat-heading {
	font-size: 1.05rem;
	font-weight: 700;
	color: var(--pl-navy);
	margin: 1.5rem 0 0.75rem;
}
.ph-compat-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0 0 1.5rem;
}
.ph-compat-chip {
	border: 1px solid rgb(0 0 0 / 0.1);
	border-radius: 9999px;
	padding: 0.35rem 0.9rem;
	font-size: 0.82rem;
	color: var(--pl-navy);
}

.ph-desc-text {
	color: var(--pl-gray-600);
	line-height: 1.7;
	max-width: 68ch;
	margin: 0 0 1rem;
}

/* Astra's native scroll-to-top button — set via the Customizer as a plain
   near-square (2px radius) with the OLD navy hardcoded as a literal color,
   not this stylesheet's --pl-navy token, so it silently went stale/
   mismatched the moment the palette was refreshed. Pull it onto the same
   token and shape system as everything else. */
#ast-scroll-top {
	border-radius: var(--pl-radius-card) !important;
	background-color: var(--pl-navy) !important;
}
#ast-scroll-top:hover {
	background-color: var(--pl-accent) !important;
}

/* Astra "Above Header" builder row (Customizer-configured plain text,
   "Livrare gratuită pentru comenzi peste 300 lei") — redundant with the
   same message already in the topbar/footer trust strip in this theme's
   own header. Hiding just the inner text element left its OUTER wrapper
   (.ast-above-header-bar) still rendering as an empty 32px light-gray
   bar — confirmed live, that wrapper has its own background/min-height
   independent of its (now empty) content. Hide the whole row. */
.ast-above-header-bar { display: none !important; }

/* Contact page form (inc/contact-form.php). */
.ph-contact-form-wrap {
	max-width: 40rem;
	margin: 2rem 0;
	background: #fff;
	box-shadow: var(--pl-shadow-card);
	border-radius: var(--pl-radius-card);
	padding: 1.75rem;
}
.ph-contact-form-row {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	margin-bottom: 1.1rem;
}
.ph-contact-form-row label {
	font-weight: 600;
	color: var(--pl-navy);
	font-size: 0.9rem;
}
.ph-contact-form-row input,
.ph-contact-form-row textarea {
	border: 1px solid rgba(0, 0, 0, 0.12);
	border-radius: var(--pl-radius-sm);
	padding: 0.65rem 0.9rem;
	font: inherit;
	color: var(--pl-navy);
	resize: vertical;
}
.ph-contact-form-row input:focus,
.ph-contact-form-row textarea:focus {
	outline: none;
	border-color: var(--pl-navy);
	box-shadow: 0 0 0 2px rgb(var(--pl-navy-rgb) / 0.15);
}
.ph-contact-form-submit {
	background: var(--pl-accent-gradient) !important;
	box-shadow: var(--pl-shadow-chip);
	color: #fff !important;
	border: none !important;
	border-radius: 9999px !important;
	padding: 0.85rem 2rem !important;
	font-weight: 700 !important;
	cursor: pointer;
}
.ph-contact-form-submit:hover { background: var(--pl-accent-hover) !important; }
/* Honeypot — visually hidden but still present/focusable in the DOM (real
   `display:none`/`hidden` fields are the first thing spam bots skip when
   deciding which fields to fill; off-screen positioning is harder to
   detect programmatically). */
.ph-contact-form-honeypot {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}
.ph-contact-form-notice {
	border-radius: var(--pl-radius-sm);
	padding: 0.85rem 1.1rem;
	margin-bottom: 1.25rem;
	font-weight: 600;
}
/* Semantic status colors, not the brand accent — coral already means
   "sale/CTA" elsewhere on the site; reusing it for an error state would
   read as a promo, not a problem. */
.ph-contact-form-notice-success { background: rgb(22 131 62 / 0.1); color: #16833e; }
.ph-contact-form-notice-error { background: rgb(200 40 40 / 0.1); color: #c82828; }

/* Footer — was a real accessibility bug, not just unbranded: the widget
   column headings were pure white and links a pale gray (#e5e7eb),
   clearly designed for a dark background that was never actually applied
   — confirmed live, footer background computed transparent (inheriting
   the white page), giving link text a 1.24:1 contrast ratio against
   white (near-invisible). Giving the footer the brand navy fixes both the
   accessibility failure and the "looks unbranded/disconnected" complaint
   in one move — the existing white/light-gray text scheme becomes exactly
   what it was clearly meant to be. */
.site-footer {
	background: var(--pl-navy-sheen);
	/* .ph-newsletter-bleed sits directly above this and is the same navy —
	   with no seam between them they read as one uninterrupted band rather
	   than two distinct sections, confirmed live (the "Subscribe" band and
	   the footer visually fused into a single oversized block). A thin
	   light seam is enough to separate them without reintroducing a plain
	   page-background gap between two same-color bands. */
	border-top: 1px solid rgb(255 255 255 / 0.12);
}
/* Astra's own "content top/bottom spacing" Customizer setting adds 60px
   margin-top AND margin-bottom on #primary — invisible on normal pages
   (white content on white page background), but on the homepage: the
   bottom one sits BELOW the full-bleed .ph-bleed sections (those only
   escape horizontally, this margin is untouched) and reintroduced a large
   plain-white gap between the navy newsletter band and the footer even
   after the border-top seam fix above; the top one stacked with
   .phv2-herorow's own intentional 0.5rem top margin, measured live as an
   84px gap below the header instead of the ~8px the hero row's own CSS
   comment says it should be. Scoped to the front page only via
   WordPress's own `.home` body class (added whenever is_front_page() is
   true) — every other page keeps Astra's normal top/bottom spacing.
   !important — Astra's own rule for this has higher specificity/its own
   !important (same recurring Astra-override gotcha as elsewhere in this
   file); a plain override was confirmed live to not win. */
.home #primary { margin-top: 0 !important; margin-bottom: 0 !important; }
.footer-widget-area a {
	color: rgb(255 255 255 / 0.75);
	text-decoration: none;
	transition: color 0.15s ease;
}
.footer-widget-area a:hover {
	color: #fff;
}
.footer-widget-area h6,
.footer-widget-area .wp-block-spectra-content {
	color: #fff;
	font-weight: 700;
	letter-spacing: 0.04em;
}
.site-below-footer-wrap {
	border-top: 1px solid rgb(255 255 255 / 0.12);
}
.site-below-footer-wrap,
.site-below-footer-wrap * {
	color: rgb(255 255 255 / 0.6);
}
