/**
 * Porto — TrustedTech · Porto-specific overrides
 * ---------------------------------------------------------------------------
 * VERIFIED against Porto 7.7.1 and re-verified on Porto 7.9.2 /
 * WooCommerce 11.0.1, using the class names reported by
 * Appearance → TrustedTech Diagnostics on the live store.
 *
 * Every card, header and footer selector below still matched after the 7.9.2
 * update. The only structural change was inside the image wrapper, which
 * gained .img-effect and a second .hover-image for the hover swap — handled at
 * the end of section 2.
 *
 * These are no longer guesses. The real card markup is:
 *
 *   ul.products.products-container.grid.ccols-2
 *     li.product.product-col.product-default
 *       div.product-inner
 *         div.product-image
 *           div.labels > div.onhot / .onsale / .onnew
 *           div.inner > img.attachment-woocommerce_thumbnail
 *           a.compare.yith-compare.on-image
 *         div.product-content
 *           span.category-list
 *           a.product-loop-title > h3.woocommerce-loop-product__title
 *           div.rating-wrap > div.star-rating
 *           span.price
 *           span.ttp-vat-note        (this child theme)
 *           span.ttp-stock           (this child theme)
 *           div.add-links-wrap > div.add-links
 *
 * Corrections made after the first diagnostic run:
 *   - #header .header-top / .header-bottom do not exist in 7.7. Header styling
 *     now targets #header and .header-main.
 *   - Porto moved from Owl Carousel to Swiper. All .owl-* rules were dead.
 *   - .btn-primary is not used; .btn is.
 *   - .searchform input.search-field is not the input's class.
 *   - #footer .widget-title / .footer-main / .footer-middle do not exist.
 *   - Sale badges are Porto's .labels block, not WooCommerce's .onsale.
 *
 * Re-run the diagnostics page after any Porto update; if these stop matching,
 * that's why.
 * ---------------------------------------------------------------------------
 */

/* ==========================================================================
   1. PRODUCT LABELS
   Porto renders its own label block and does not call woocommerce_sale_flash,
   so the child theme's percentage badge never reached the page. Style Porto's
   labels instead of fighting for control of them.
   ========================================================================== */

.ttp-skin .product-image .labels > div,
.ttp-skin .labels > div {
	font-family: var(--ttp-font-heading, inherit);
	font-weight: 800;
	font-size: 10px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	border-radius: 5px;
	line-height: 1.3;
	padding: 4px 8px;
	box-shadow: none;
}

/* A discount is the most urgent thing on a card, so it gets the deal colour. */
.ttp-skin .labels .onsale,
.ttp-skin .labels .ondiscount {
	background-color: var(--ttp-deal, #f59e0b) !important;
	color: #1a1206 !important;
}

/* "Hot" and "New" take cooler colours so they can never outrank a price drop. */
.ttp-skin .labels .onhot {
	background-color: var(--ttp-danger, #dc2626) !important;
	color: #fff !important;
}

.ttp-skin .labels .onnew {
	background-color: var(--ttp-accent-soft, #e6f8fb) !important;
	color: #0e7490 !important;
}

.ttp-skin .labels .onstock,
.ttp-skin .labels .outofstock {
	background-color: var(--ttp-canvas, #f6f8fb) !important;
	color: var(--ttp-muted, #64748b) !important;
}

/* ==========================================================================
   2. PRODUCT CARD
   ========================================================================== */

/*
 * EXACTLY ONE element may be the card.
 *
 * Porto uses padding on li.product (.product-col) to create the grid gutter,
 * so a background on the <li> spans the gutter as well as the card. With
 * child.css and skin.css both painting li.product AND this file painting
 * .product-inner, every tile was two nested rounded white boxes with two
 * shadows — the outer one bleeding into the gap between columns and stacking
 * against its neighbour's edge.
 *
 * The <li> is the grid cell. .product-inner is the card. Strip the cell back to
 * nothing and let the inner element carry the surface, radius and elevation.
 */
.ttp-skin ul.products li.product,
.ttp-cards-elevated.ttp-skin ul.products li.product,
.ttp-cards-bordered.ttp-skin ul.products li.product {
	background: transparent !important;
	border: 0 !important;
	border-radius: 0 !important;
	box-shadow: none !important;
	overflow: visible !important;
	transform: none !important;
}

.ttp-skin ul.products.products-container li.product .product-inner {
	background: #fff;
	border-radius: 14px;
	overflow: hidden;
	transition: box-shadow 0.24s ease, transform 0.24s ease;
}

/*
 * Equal-height cards, without `height: 100%`.
 *
 * `height: 100%` was here to make every card in a row the same height. It is
 * only safe when the parent has a definite height — and Porto's loop is
 * floated <li> at a percentage width in some releases, where the <li> height is
 * auto. Measured in the shop rig: the card came out 1000px tall, the exact
 * height of the viewport, because the percentage walked up a chain of auto
 * heights to the initial containing block. Removing it gave 377px.
 *
 * A flex column does the same job with no percentage in it. In a grid the <li>
 * stretches to the row and the card fills it; in a float the <li> is
 * content-height and the card matches. Both correct, neither dependent on
 * which layout Porto shipped.
 *
 * Scoped to `.grid` so the list-view toggle is untouched.
 */
.ttp-skin ul.products.products-container.grid > li.product {
	display: flex;
	flex-direction: column;
}

.ttp-skin ul.products.products-container.grid > li.product > .product-inner {
	flex: 1 1 auto;
	height: auto;
}

.ttp-cards-elevated.ttp-skin ul.products li.product .product-inner {
	box-shadow: 0 1px 2px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.06),
		0 2px 8px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.05);
}

.ttp-cards-elevated.ttp-skin ul.products li.product:hover .product-inner {
	box-shadow: 0 4px 8px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.06),
		0 16px 36px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.11);
	transform: translateY(-3px);
}

.ttp-cards-bordered.ttp-skin ul.products li.product .product-inner {
	border: 1px solid var(--ttp-border, #e2e8f0);
}

/* White plate behind the image so cut-out product shots read cleanly. */
.ttp-skin .product-image,
.ttp-skin .product-image .inner {
	background: #fff;
}

/*
 * Breathing room around the product shot.
 *
 * Porto renders the image flush to the card's edges, so photography with its
 * own light backdrop bleeds into the card and the product reads as though it's
 * been cropped. Inset it instead.
 *
 * The padding goes on .inner, not .product-image — the labels are positioned
 * against .product-image, and padding there would drag the HOT/sale badges away
 * from the corner they're meant to sit in.
 */
.ttp-skin .product-image .inner {
	box-sizing: border-box;
	padding: 10px;
}

@media (min-width: 768px) {
	.ttp-skin .product-image .inner { padding: 16px; }
}

.ttp-skin .product-image .inner img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.ttp-skin .product-content {
	padding: 12px 14px 14px;
}

/* Category eyebrow */
.ttp-skin .product-content .category-list,
.ttp-skin .category-list {
	display: block;
	margin-bottom: 3px;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.08em;
	line-height: 1.4;
	text-transform: uppercase;
	color: var(--ttp-muted, #94a3b8);
}

.ttp-skin .category-list a { color: inherit; }
.ttp-skin .category-list a:hover { color: var(--ttp-primary, #1d4ed8); }

/*
 * Title. Porto nests h3.woocommerce-loop-product__title inside
 * a.product-loop-title, so the clamp belongs on the h3 — clamping the anchor
 * would leave the heading free to overflow it.
 */
.ttp-skin a.product-loop-title h3.woocommerce-loop-product__title,
.ttp-skin h3.woocommerce-loop-product__title {
	margin: 0;
	font-family: var(--ttp-font-heading, inherit);
	font-size: 0.9rem;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: -0.01em;
	color: var(--ttp-ink, #0b1220);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	line-clamp: 2;
	overflow: hidden;
	/* Two lines at the above size and leading. Reserving the space keeps every
	   card in a row the same height even when one title is a single line. */
	min-height: 2.52em;
}

.ttp-skin a.product-loop-title:hover h3.woocommerce-loop-product__title {
	color: var(--ttp-primary, #1d4ed8);
}

/* Rating */
.ttp-skin .rating-wrap { margin-block: 4px; }
.ttp-skin .rating-wrap .star-rating span::before,
.ttp-skin .star-rating span::before { color: var(--ttp-deal, #f59e0b); }

/* Price */
.ttp-skin .product-content span.price,
.ttp-skin li.product span.price {
	display: block;
	margin-top: 4px;
	font-family: var(--ttp-font-heading, inherit);
	font-size: 1.02rem;
	font-weight: 800;
	letter-spacing: -0.015em;
	color: var(--ttp-ink, #0b1220);
	font-variant-numeric: tabular-nums;
}

/* Add-to-cart area */
.ttp-skin .add-links-wrap { margin-top: 10px; }

/*
 * ONE primary action per card.
 *
 * Porto puts add-to-cart, wishlist, compare and quick-view in the same
 * .add-links container. An earlier rule styled `.add-links .button` — which
 * caught all of them — so YITH's Compare link rendered as a second full-width
 * tinted button, visually identical to the buy action. Two equal buttons means
 * neither reads as the thing to press.
 *
 * Only the actual add-to-cart classes get the full-width treatment. Everything
 * else in that container is a secondary utility and is styled as a quiet link.
 */
.ttp-skin .add-links .add_to_cart_button,
.ttp-skin .add-links .product_type_simple,
.ttp-skin .add-links .product_type_variable,
.ttp-skin .add-links .product_type_grouped,
.ttp-skin .add-links .product_type_external,
.ttp-skin .add-links .ajax_add_to_cart {
	display: block !important;
	width: 100% !important;
	box-sizing: border-box;
	margin: 0 !important;
	padding: 0.72em 0.8em !important;
	text-align: center !important;
	background-color: var(--ttp-primary-soft, #edf1fc) !important;
	border-color: transparent !important;
	color: var(--ttp-primary, #1d4ed8) !important;
	border-radius: 8px;
	font-family: var(--ttp-font-heading, inherit);
	font-weight: 700;
	font-size: 0.78rem;
	line-height: 1.25;
}

.ttp-skin .add-links .add_to_cart_button:hover,
.ttp-skin .add-links .product_type_simple:hover,
.ttp-skin .add-links .product_type_variable:hover {
	background-color: var(--ttp-primary, #1d4ed8) !important;
	color: #fff !important;
}

/* Secondary utilities: compare, wishlist, quick view. Quiet, small, inline. */
.ttp-skin .add-links .compare,
.ttp-skin .add-links .quickview,
.ttp-skin .add-links .yith-wcwl-add-to-wishlist a,
.ttp-skin .add-links .yith-wcwl-add-button a {
	display: inline-flex !important;
	align-items: center;
	justify-content: center;
	gap: 4px;
	width: auto !important;
	max-width: none;
	margin: 0 !important;
	padding: 2px 6px !important;
	background: transparent !important;
	border: 0 !important;
	box-shadow: none !important;
	color: var(--ttp-muted, #94a3b8) !important;
	font-family: var(--ttp-font-body, inherit);
	font-size: 0.7rem !important;
	font-weight: 600;
	text-transform: none;
}

.ttp-skin .add-links .compare:hover,
.ttp-skin .add-links .quickview:hover,
.ttp-skin .add-links .yith-wcwl-add-to-wishlist a:hover {
	background: transparent !important;
	color: var(--ttp-primary, #1d4ed8) !important;
	text-decoration: underline;
}

/*
 * Stack the primary button, then the utilities on one centred row beneath it.
 * The gap matters: without it the controls butted together and read as one
 * segmented control.
 */
.ttp-skin .add-links-wrap { width: 100%; }

.ttp-skin .add-links {
	display: flex !important;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	width: 100%;
	text-align: center;
	float: none !important;
}

/*
 * The hover-revealed icon buttons in the action row.
 *
 * Reported as "something moving at the edges of the tile on hover". The probe
 * had already recorded what they are:
 *
 *   .yith-wcwl-add-button   absolute  48x36  z:3   (wishlist)
 *   .quickview              absolute  36x36  z:3
 *
 * `.add-links` above is a centred flex COLUMN, and these two are positioned
 * absolutely, so they take no part in it — Porto anchors them to the row's left
 * and right edges, where `overflow: hidden` on the card clips them to slivers
 * that appear and disappear with the pointer.
 *
 * Hidden rather than re-laid-out. Making them static would stack two more rows
 * under a card that already says "Select options" and "Compare", and a control
 * that only exists on hover is invisible on a phone regardless — which is where
 * most of this store's traffic will be.
 *
 * Wishlist and quick view both still work on the product page itself. To bring
 * them back on the tile, delete this rule and give `.add-links` a row layout so
 * they have somewhere to sit.
 */
.ttp-skin ul.products li.product .add-links .quickview,
.ttp-skin ul.products li.product .add-links .yith-wcwl-add-to-wishlist,
.ttp-skin ul.products li.product .add-links .yith-wcwl-add-button {
	display: none !important;
}

/* The compare control overlaid on the image is a different element and keeps
   its own circular treatment — this must not flatten it. */
.ttp-skin .product-image .compare.on-image {
	display: grid !important;
	width: 32px !important;
	padding: 0 !important;
}

.ttp-skin .add-links .button:hover,
.ttp-skin .add-links .add_to_cart_button:hover,
.ttp-skin .add-links .product_type_variable:hover {
	background-color: var(--ttp-primary, #1d4ed8) !important;
	color: #fff !important;
}

/*
 * Porto 7.9.2 added a hover image swap: .product-image .inner gains
 * .img-effect and a second <img class="porto-lazyload hover-image">.
 *
 * Only the transition is smoothed here — the swap itself is Porto's, and
 * overriding its opacity or positioning would break it. The white plate is
 * applied to the wrapper rather than the images so both frames sit on the same
 * ground and the crossfade doesn't flash grey.
 */
.ttp-skin .product-image .inner.img-effect {
	background: #fff;
}

.ttp-skin .product-image .hover-image {
	transition: opacity 0.3s ease;
}

/* The YITH compare control overlaid on the image. */
.ttp-skin a.compare.on-image {
	background: rgb(255 255 255 / 0.92) !important;
	color: var(--ttp-ink, #0b1220) !important;
	border-radius: 999px;
	box-shadow: 0 1px 4px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.12);
}

.ttp-skin a.compare.on-image:hover {
	background: var(--ttp-primary, #1d4ed8) !important;
	color: #fff !important;
}

/* ==========================================================================
   3. HEADER
   Porto 7.7 has no .header-top or .header-bottom — only .header-main.
   ========================================================================== */

.ttp-skin #header,
.ttp-skin #header .header-main {
	background-color: #fff !important;
	border-bottom: 1px solid var(--ttp-border, #e2e8f0);
}

.ttp-skin #header .header-main { box-shadow: none; }

.ttp-skin #header a { color: var(--ttp-ink, #0b1220); }
.ttp-skin #header a:hover { color: var(--ttp-primary, #1d4ed8); }

.ttp-skin #header .main-menu > li > a {
	font-family: var(--ttp-font-heading, inherit);
	font-weight: 600;
	text-transform: none;
	letter-spacing: 0;
}

.ttp-skin #header .main-menu > li:hover > a,
.ttp-skin #header .main-menu > li.active > a {
	color: var(--ttp-primary, #1d4ed8);
}

/*
 * Search. The input does not carry .search-field in this version, so target
 * any text input inside .searchform.
 */
.ttp-skin .searchform input[type="text"],
.ttp-skin .searchform input[type="search"],
.ttp-skin .searchform input:not([type="submit"]):not([type="hidden"]) {
	height: 44px;
	padding: 0 52px 0 18px;
	border-radius: 999px !important;
	border: 1px solid var(--ttp-border, #e2e8f0) !important;
	background: var(--ttp-canvas, #f6f8fb) !important;
	color: var(--ttp-ink, #0b1220);
	font-size: 15px;
	box-shadow: none;
}

.ttp-skin .searchform input:not([type="submit"]):focus {
	border-color: var(--ttp-primary, #1d4ed8) !important;
	background: #fff !important;
	box-shadow: 0 0 0 4px rgb(var(--ttp-primary-rgb, 29 78 216) / 0.12);
}

.ttp-skin .searchform {
	position: relative;
	border: 0;
	background: transparent;
	border-radius: 999px;
}

.ttp-skin .searchform button,
.ttp-skin .searchform .btn,
.ttp-skin .searchform input[type="submit"] {
	position: absolute;
	top: 50%;
	inset-inline-end: 4px;
	transform: translateY(-50%);
	width: 36px;
	height: 36px;
	min-width: 0;
	padding: 0;
	display: inline-flex !important;
	align-items: center;
	justify-content: center;
	border: 0 !important;
	border-radius: 999px !important;
	background: var(--ttp-primary, #1d4ed8) !important;
	color: #fff !important;
	font-size: 15px;
	line-height: 1;
}

/*
 * Mobile menu toggle.
 *
 * Confirmed present as .mobile-toggle, but it was still rendering as a filled
 * blue square — Porto paints the wrapper and the icon, not just the button, so
 * clearing the button alone left the block colour showing through. Cover the
 * anchor, its container and the icon glyph.
 */
.ttp-skin .mobile-toggle,
.ttp-skin .mobile-toggle-wrap,
.ttp-skin #header .mobile-toggle,
.ttp-skin .header-main .mobile-toggle {
	background: transparent !important;
	background-color: transparent !important;
	background-image: none !important;
	color: var(--ttp-ink, #0b1220) !important;
	border: 0 !important;
	border-radius: 10px !important;
	box-shadow: none !important;
}

.ttp-skin .mobile-toggle i,
.ttp-skin .mobile-toggle span,
.ttp-skin .mobile-toggle::before {
	color: var(--ttp-ink, #0b1220) !important;
	background: transparent !important;
}

.ttp-skin .mobile-toggle:hover,
.ttp-skin .mobile-toggle:focus {
	background: var(--ttp-primary-soft, #edf1fc) !important;
	color: var(--ttp-primary, #1d4ed8) !important;
}

.ttp-skin .mobile-toggle:hover i,
.ttp-skin .mobile-toggle:focus i { color: var(--ttp-primary, #1d4ed8) !important; }

/* --------------------------------------------------------------------------
 * The relocated toggle.
 *
 * inc/header-toggle.php moves the button to be the first child of the header
 * row. Porto lays that row out as a table, so a direct child that isn't a cell
 * is wrapped in an anonymous table-cell automatically — and an anonymous cell
 * inserted before the logo cell is, by definition, the leftmost column. The
 * table does the positioning; there is nothing here to align.
 *
 * Why a DOM move and not CSS: the button lived inside the RIGHT-hand cell, and
 * no CSS property moves a box across a table-cell boundary. Eight rounds of
 * alignment rules failed for that reason, and the ninth — absolute positioning
 * with a reserved gutter — worked only inside the breakpoint I happened to
 * guess. Moving the node is breakpoint-independent, so it holds at whatever
 * width Porto decides to show a mobile header, including Chrome's 980px
 * "Desktop site" viewport.
 *
 * No media query on purpose: where Porto hides the toggle it is display:none,
 * which generates no anonymous cell at all, so this costs the desktop header
 * exactly nothing.
 * ----------------------------------------------------------------------- */
.ttp-skin #header .header-container > .ttp-toggle-cell {
	display: table-cell;
	vertical-align: middle;
	white-space: nowrap;
	padding: 0;

	/*
	 * Size to the button and nothing more.
	 *
	 * `width: 1px` is the standard way to make an auto-layout table column
	 * shrink to its content instead of taking a share of the row's spare width
	 * — without it the new column drags the logo toward the middle, which is
	 * the same failure being fixed, one element over.
	 *
	 * `min-width: max-content` is the belt to that brace. If a Porto header
	 * preset lays this row out as flex rather than a table, `display:
	 * table-cell` blockifies and the 1px would be taken literally; max-content
	 * keeps it the width of the button in every layout mode. It also means the
	 * cell collapses to nothing on desktop, where Porto sets the toggle to
	 * display: none and max-content resolves to zero.
	 */
	width: 1px;
	min-width: max-content;
}

.ttp-skin #header .ttp-toggle-cell .mobile-toggle {
	margin-right: 14px;
}

/*
 * The search field has to be allowed to shrink.
 *
 * Porto's advanced search layout carries an intrinsic minimum width. That was
 * survivable while the toggle sat stacked under the search in the same cell;
 * now that the button holds a column of its own, the row's minimum content
 * width exceeds a phone screen and the field runs off the right edge.
 *
 * Reproduced in docs/preview/header-rig.html: a 501px header row inside a
 * 360px viewport, with the field ending at 486px.
 *
 * A table column cannot be narrower than its content's minimum, so the minimum
 * is what has to go. !important is deliberate and confined to the two sizing
 * properties — Porto sets these from a compiled bundle with an #id in the
 * selector, and matching that specificity everywhere would be worse than
 * forcing two declarations that are safe to force.
 */
.ttp-skin #header .header-right,
.ttp-skin #header .header-right-top,
.ttp-skin #header .searchform-popup,
.ttp-skin #header .searchform {
	min-width: 0 !important;
	max-width: 100% !important;
}

.ttp-skin #header .searchform input,
.ttp-skin #header .searchform .search-field,
.ttp-skin #header .searchform select {
	min-width: 0 !important;
	max-width: 100% !important;
}

/*
 * ...and the row has to stop being a table for that to be possible.
 *
 * The probe measured the header row at 447px inside a 384px viewport, with a
 * -63px right margin where `margin-right: auto` had gone negative to absorb
 * the overflow. The columns: 20 padding + 56 toggle + 150 logo + 201 search.
 * The 56 is the column the relocated button added, and it is almost exactly
 * the overflow.
 *
 * min-width: 0 above cannot fix that on its own, and it is worth being precise
 * about why: a table cell is never laid out narrower than its content's
 * min-content width, whatever min-width says. Porto's advanced search — a
 * category select, a field and a button — has a 201px min-content floor that
 * no sizing property on the cell can get under.
 *
 * A flex item can go below min-content, but only if min-width: 0 overrides the
 * `auto` minimum. That pairing is the whole fix: flex to make shrinking
 * possible, min-width: 0 to permit it, and `flex: 1 1 0` so the search is the
 * thing that gives way rather than the logo.
 *
 * Scoped to the mobile header range. Above it Porto's table is correct and
 * there is width to spare, so it is left alone.
 */
/*
 * Scoped to .ttp-mobile-header, NOT to a width.
 *
 * inc/header-toggle.php sets that class while Porto is actually showing its
 * mobile header, by reading whether the burger is visible. Porto's breakpoint
 * for that is a theme option — on this store it is above 992px, since the
 * burger shows on a 1080px desktop — so `max-width: 991px` stopped applying in
 * the middle of the range it was meant to cover. Chrome's 980px "Desktop site"
 * viewport had already caused the same failure once, and the toggle's position
 * a second time. Reading the real state ends that class of bug.
 */
.ttp-skin.ttp-mobile-header #header .header-main .header-container {
	display: flex !important;
	align-items: center;
	width: 100% !important;
	max-width: 100% !important;
	margin-inline: 0 !important;
}

.ttp-skin.ttp-mobile-header #header .header-main .ttp-toggle-cell {
	display: flex !important;
	flex: 0 0 auto;
	width: auto !important;
}

/*
 * The logo keeps its size; it is the brand and it is already small.
 *
 * `width: auto` matters here. A width set for table layout — Porto uses small
 * or percentage widths on these cells to make them shrink to content — becomes
 * the flex-basis once the row is flex, and a cell carrying `width: 1px`
 * collapses to a 1px column with the logo spilling out of it. Letting the width
 * go back to auto makes the basis the logo's own size.
 */
.ttp-skin.ttp-mobile-header #header .header-main .header-left {
	display: block !important;
	flex: 0 0 auto;
	width: auto !important;
}

/*
 * The right-hand side becomes a row too, not a stack.
 *
 * Porto splits it into .header-right-top and .header-right-bottom, and nests
 * the cart alongside the search inside one of them. Both levels were laying
 * their children out as blocks, which is why the search sat on one line and the
 * cart on another — three visual rows for a burger, a logo, a field and a cart
 * icon, and about 120px of header before any content on a 692px screen.
 *
 * All three levels become rows. The search takes the slack at each one
 * (`flex: 1 1 0` with `min-width: 0`, the same pairing that lets it shrink
 * below min-content at all); everything else keeps its natural size.
 */
.ttp-skin.ttp-mobile-header #header .header-main .header-right,
.ttp-skin.ttp-mobile-header #header .header-main .header-right-top,
.ttp-skin.ttp-mobile-header #header .header-main .header-right-bottom {
	display: flex !important;
	align-items: center;
	justify-content: flex-end;
	gap: 10px;
}

.ttp-skin.ttp-mobile-header #header .header-main .header-right {
	flex: 1 1 0 !important;
	min-width: 0 !important;
}

.ttp-skin.ttp-mobile-header #header .header-main .header-right-top {
	flex: 1 1 0;
	min-width: 0;
}

.ttp-skin.ttp-mobile-header #header .header-main .header-right-bottom {
	flex: 0 0 auto;
}

/* The search itself is the element that gives way inside its row. */
.ttp-skin.ttp-mobile-header #header .searchform-popup {
	flex: 1 1 0;
	min-width: 0;
}

/*
 * Breathing room between the logo and the search.
 *
 * With the row flexed and the right side end-aligned, a full-width search
 * starts exactly where the logo stops. Capping its width from 768px up leaves
 * the gap on the left, where the eye expects it, rather than padding the logo
 * and pushing everything around.
 */
.ttp-skin.ttp-mobile-header #header .header-main .header-left {
	margin-right: 18px;
}

@media (min-width: 768px) {
	.ttp-skin.ttp-mobile-header #header .searchform-popup {
		/*
		 * !important because an earlier rule in this file sets
		 * `max-width: 100% !important` on the same element, to let the search
		 * shrink below Porto's minimum. Without matching that, this cap was
		 * silently ignored and the field ran the full width of the row — which
		 * is the "too close to the logo" complaint it was meant to answer.
		 */
		max-width: 420px !important;
	}
}

/*
 * The form must not be wider than the box holding it.
 *
 * Capping .searchform-popup alone left the submit button stranded hundreds of
 * pixels to the right of the field. max-width on a parent does not constrain a
 * child that carries its own width, and Porto's advanced search form does —
 * it overflowed the capped popup, and since Porto positions the submit button
 * absolutely at the FORM's right edge, the button went with it.
 *
 * So the form is pinned to its container and the field is told to fill the
 * form. Then the button lands where it looks like it belongs: at the end of
 * the pill.
 */
.ttp-skin.ttp-mobile-header #header .searchform {
	width: 100% !important;
	max-width: 100% !important;
}

.ttp-skin.ttp-mobile-header #header .searchform input[type="text"],
.ttp-skin.ttp-mobile-header #header .searchform input[type="search"],
.ttp-skin.ttp-mobile-header #header .searchform .search-field {
	width: 100% !important;
	min-width: 0 !important;
}

/* --------------------------------------------------------------------------
 * COLLAPSED SEARCH (phones)
 *
 * Built by inc/header-search.php. On a 384px screen the inline field gets
 * about 120px after the burger, logo and cart have taken their share — enough
 * to render, not enough to use, which is why the placeholder truncated to
 * "Sear" behind the submit button.
 *
 * So on phones it is an icon, and expands over the header row when tapped.
 * That is a question of available space rather than of which header Porto is
 * showing, which is why this one legitimately uses a width media query.
 * ----------------------------------------------------------------------- */

/* Hidden everywhere by default; the phone block below opts it in. */
.ttp-search-toggle {
	display: none;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	flex: 0 0 auto;
	padding: 0;
	background: transparent;
	border: 0;
	border-radius: 10px;
	color: var(--ttp-ink, #0b1220);
	cursor: pointer;
}

.ttp-search-toggle:hover,
.ttp-search-toggle:focus-visible {
	background: var(--ttp-primary-soft, #edf1fc);
	color: var(--ttp-primary, #1d4ed8);
}

@media (max-width: 767px) {
	.ttp-skin.ttp-mobile-header #header .ttp-search-toggle {
		display: inline-flex;
	}

	.ttp-skin.ttp-mobile-header #header .searchform-popup {
		display: none;
	}

	/* The expanded field is positioned against the header row. */
	/* ----------------------------------------------------------------------
	 * Expanded: the row BECOMES the search field.
	 *
	 * This was an absolutely positioned overlay across the header row, and it
	 * collapsed to a stub sitting on top of the button. The reason is worth
	 * recording: an absolutely positioned box resolves against its nearest
	 * POSITIONED ancestor, and Porto positions elements inside the header. So
	 * `left: 10px; right: 72px` resolved against a 118px-wide .header-right-top
	 * rather than the 384px row, leaving about 31px of field — right where the
	 * button was. Making .header-main relative could not help, because a closer
	 * positioned ancestor always wins.
	 *
	 * Rather than force intermediate ancestors to static and hope none of them
	 * needed to be positioned, the expanded field stays IN FLOW. Everything
	 * else in the row hides, the search takes the space, and there is no
	 * containing block to get wrong.
	 *
	 * :has() is what makes the hiding safe — it hides whatever does not contain
	 * the search or the button, so it does not matter which of Porto's nested
	 * rows the form actually sits in, and no class names are guessed.
	 * -------------------------------------------------------------------- */
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .ttp-toggle-cell,
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .header-left,
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .header-right
		> *:not(:has( .searchform-popup )):not(:has( .ttp-search-toggle )),
	.ttp-skin.ttp-mobile-header.ttp-search-open #header
		*:has( > .searchform-popup ) > *:not(.searchform-popup):not(.ttp-search-toggle) {
		display: none !important;
	}

	/* Every level between the row and the field gives it all its width. */
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .header-right,
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .header-right-top,
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .header-right-bottom {
		flex: 1 1 auto !important;
		width: 100% !important;
		min-width: 0 !important;
		max-width: none !important;
	}

	.ttp-skin.ttp-mobile-header.ttp-search-open #header .searchform-popup {
		display: flex !important;
		flex: 1 1 auto;
		min-width: 0;
		max-width: none !important;
		animation: ttp-search-unfurl 0.18s ease-out;
	}

	.ttp-skin.ttp-mobile-header.ttp-search-open #header .searchform {
		width: 100%;
	}

	/*
	 * Porto's category select costs roughly 90px of a 384px screen. While the
	 * field is open for typing, the words matter more than the filter — and
	 * hiding it in CSS keeps it in the form, so the value still submits and
	 * search behaviour is unchanged.
	 */
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .searchform select,
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .searchform .cat-list,
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .searchform .selectric-wrapper {
		display: none !important;
	}

	.ttp-skin.ttp-mobile-header.ttp-search-open #header .searchform input[type="text"],
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .searchform input[type="search"],
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .searchform .search-field {
		flex: 1 1 auto !important;
		width: 100% !important;
		min-width: 0 !important;
	}
}

/*
 * Revealed from the right edge, so the motion reads as growing out of the
 * icon. clip-path rather than an animated width: the box is already at its
 * final size, so nothing reflows mid-animation.
 */
@keyframes ttp-search-unfurl {
	from { clip-path: inset( 0 0 0 calc( 100% - 42px ) ); }
	to   { clip-path: inset( 0 0 0 0 ); }
}

@media (prefers-reduced-motion: reduce) {
	.ttp-skin.ttp-mobile-header.ttp-search-open #header .searchform-popup {
		animation: none;
	}
}

/* No logo gap on a phone — the row is tight enough already. */
@media (max-width: 767px) {
	.ttp-skin.ttp-mobile-header #header .header-main .header-left {
		margin-right: 0;
	}
}

/*
 * Anything else riding in those rows — cart, wishlist, account, socials —
 * keeps its size rather than being stretched by the flex container.
 */
.ttp-skin.ttp-mobile-header #header .header-right .cart-popup,
.ttp-skin.ttp-mobile-header #header .header-right .my-account,
.ttp-skin.ttp-mobile-header #header .header-right .wishlist,
.ttp-skin.ttp-mobile-header #header .header-right .share-links {
	flex: 0 0 auto;
}

/*
 * A stray control pinned to the bottom-left corner, over the footer.
 *
 * Identified by the probe rather than guessed at:
 *
 *   <a>.side-nav-panel-close   fixed  left:0  22x22   parent: <body>
 *
 * It is Porto's close button for the side-navigation panel, rendered as a
 * direct child of <body> with no panel open for it to close.
 *
 * The `body >` part matters. When the side panel is genuinely in use Porto
 * renders this button inside the panel, where this selector does not reach it
 * — so the control still works if that feature is ever switched on. Only the
 * orphaned copy is hidden.
 */
body > .side-nav-panel-close {
	display: none !important;
}

/*
 * The search icon at the bottom-left of every page.
 *
 * Named by the probe after three wrong guesses:
 *
 *   <div>.cb-search-root   static  384x45  left:0  doc-y:6375   in: body
 *
 * It is not Porto. A plugin mounts a full-width launcher bar as the last
 * element in <body>, which is why it sat below the footer, why a scan filtered
 * on position never saw it (it is static, not floating), and why hiding
 * Porto's own search classes changed nothing.
 *
 * Hidden here rather than removed, because the markup belongs to a plugin and
 * this theme should not fight it — if that search is wanted, the plugin's own
 * settings are the place to configure it, and deleting this rule brings it
 * straight back. The `body >` scope keeps it to the orphaned launcher.
 */
body > .cb-search-root {
	display: none !important;
}

/* --------------------------------------------------------------------------
 * DARK HEADER (opt-in: Customise → TrustedTech → Header)
 *
 * Paints the bar in the deep brand colour and lifts everything on it to white.
 * Every control has to be covered explicitly — a header holds icons, inputs and
 * counters that each set their own colour, and missing one leaves it dark on
 * dark, which is invisible rather than merely wrong.
 * ----------------------------------------------------------------------- */

.ttp-header-dark #header,
.ttp-header-dark #header .header-main,
.ttp-header-dark .header-wrapper {
	background-color: var(--ttp-dark, #101c3d) !important;
	border-bottom-color: rgb(255 255 255 / 0.12) !important;
}

.ttp-header-dark #header,
.ttp-header-dark #header a,
.ttp-header-dark #header .main-menu > li > a,
.ttp-header-dark #header .cart-head,
.ttp-header-dark #header .my-account {
	color: rgb(255 255 255 / 0.88) !important;
}

.ttp-header-dark #header a:hover,
.ttp-header-dark #header .main-menu > li:hover > a {
	color: #fff !important;
}

.ttp-header-dark #header .mobile-toggle,
.ttp-header-dark #header .mobile-toggle i {
	color: #fff !important;
}

.ttp-header-dark #header .mobile-toggle:hover {
	background: rgb(255 255 255 / 0.12) !important;
	color: #fff !important;
}

/* Search sits on the dark bar, so it needs a translucent light field. */
.ttp-header-dark .searchform input[type="text"],
.ttp-header-dark .searchform input[type="search"],
.ttp-header-dark .searchform input:not([type="submit"]):not([type="hidden"]) {
	background: rgb(255 255 255 / 0.1) !important;
	border-color: rgb(255 255 255 / 0.2) !important;
	color: #fff !important;
}

.ttp-header-dark .searchform input::placeholder { color: rgb(255 255 255 / 0.6) !important; }

.ttp-header-dark .searchform input:focus {
	background: rgb(255 255 255 / 0.16) !important;
	border-color: rgb(255 255 255 / 0.5) !important;
	box-shadow: 0 0 0 3px rgb(255 255 255 / 0.14) !important;
}

/*
 * Logo rescue. A logo drawn dark for a white background disappears on navy.
 * brightness(0) crushes it to solid black, invert(1) flips that to solid
 * white — so any artwork becomes a clean white silhouette. It also flattens
 * any colour in the mark, which is why this is opt-in and why a proper light
 * logo file is the better answer.
 */
.ttp-header-dark.ttp-logo-invert #header .logo img {
	filter: brightness(0) invert(1);
}

/* --------------------------------------------------------------------------
 * MOBILE MENU DRAWER
 * ----------------------------------------------------------------------- */

.ttp-skin .mobile-menu-wrapper,
.ttp-skin .mobile-sidebar {
	background: #fff;
}

.ttp-skin .mobile-menu a,
.ttp-skin .side-nav-menu a {
	font-family: var(--ttp-font-heading, inherit);
	font-weight: 550;
	color: var(--ttp-ink, #0b1220);
}

.ttp-skin .mobile-menu a:hover,
.ttp-skin .side-nav-menu a:hover {
	color: var(--ttp-primary, #1d4ed8);
}

/*
 * Social icons in the drawer.
 *
 * Porto tints each one with its network's brand colour, which puts a Facebook
 * blue, a lighter blue and a muddy brown next to each other at the foot of the
 * menu — three unrelated hues competing with the store's own. Neutral by
 * default, brand colour on interaction, so they read as one set.
 */
.ttp-skin .mobile-menu-wrapper .share-links a,
.ttp-skin .mobile-sidebar .share-links a {
	background: var(--ttp-canvas, #f6f8fb) !important;
	color: var(--ttp-ink, #0b1220) !important;
	border: 1px solid var(--ttp-border, #e2e8f0) !important;
	border-radius: 10px;
	transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

.ttp-skin .mobile-menu-wrapper .share-links a:hover,
.ttp-skin .mobile-sidebar .share-links a:hover {
	background: var(--ttp-primary, #1d4ed8) !important;
	color: #fff !important;
	border-color: var(--ttp-primary, #1d4ed8) !important;
	transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
	.ttp-skin .mobile-menu-wrapper .share-links a,
	.ttp-skin .mobile-menu-wrapper .share-links a:hover { transition: none; transform: none; }
}

/*
 * Page title bar — spacing only, no surface.
 *
 * This used to fill .page-top with the canvas colour and rule it off, on the
 * assumption that the element spans the page. On a product-category page it
 * does not: Porto lays the category header out with the title beside the
 * category image, and .page-top shrink-wraps the breadcrumb and heading. The
 * fill then drew a grey box around the words — a panel nobody asked for,
 * floating in an otherwise open header.
 *
 * A band that appears on some templates and not others is worse than no band,
 * and the page wash now separates chrome from content everywhere anyway.
 */
.ttp-skin .page-top {
	background: none !important;
	border-top: 0;
	border-bottom: 0;
	padding-block: 18px;
}

.ttp-skin .page-top .page-title,
.ttp-skin .page-top h1 {
	color: var(--ttp-ink, #0b1220);
	font-family: var(--ttp-font-heading, inherit);
	font-weight: 700;
	letter-spacing: -0.022em;
}

/* ==========================================================================
   4. FOOTER
   #footer and #footer .footer-bottom exist; .footer-main, .footer-middle and
   #footer .widget-title do not.
   ========================================================================== */

/*
 * Discovery returned the real footer vocabulary: .footer-wrapper, .footer,
 * .footer-1, .footer-bottom, .footer-left, .footer-copyright. There are no
 * widget titles on this store's footer at all, which is why every heading
 * selector read zero — the footer holds a logo, a copyright line and the
 * payment badges, nothing else.
 */
.ttp-skin #footer,
.ttp-skin .footer-wrapper,
.ttp-skin .footer,
.ttp-skin .footer-1 {
	background-color: var(--ttp-dark, #101c3d) !important;
	color: rgb(255 255 255 / 0.68);
	border-top: 0;
}

.ttp-skin .footer-copyright,
.ttp-skin .footer-left {
	color: rgb(255 255 255 / 0.55);
	font-size: 0.8rem;
}

.ttp-skin #footer a { color: rgb(255 255 255 / 0.68); }
.ttp-skin #footer a:hover { color: #fff; }

/* Widget titles carry no .widget-title here, so target headings directly. */
.ttp-skin #footer h1,
.ttp-skin #footer h2,
.ttp-skin #footer h3,
.ttp-skin #footer h4,
.ttp-skin #footer h5,
.ttp-skin #footer h6,
.ttp-skin #footer .elementor-heading-title {
	color: #fff !important;
	font-family: var(--ttp-font-heading, inherit);
	font-weight: 700;
	letter-spacing: 0.04em;
}

.ttp-skin #footer .footer-bottom {
	background-color: var(--ttp-dark, #101c3d) !important;
	border-top: 1px solid rgb(255 255 255 / 0.1);
	color: rgb(255 255 255 / 0.55);
}

.ttp-skin #footer .share-links a {
	background: rgb(255 255 255 / 0.08) !important;
	color: #fff !important;
	border: 0 !important;
	border-radius: 999px;
}

.ttp-skin #footer .share-links a:hover {
	background: var(--ttp-primary, #1d4ed8) !important;
}

.ttp-skin #footer .ttp-payments__item {
	background: rgb(255 255 255 / 0.92);
	border-color: transparent;
	color: var(--ttp-dark, #101c3d);
}

/*
 * The payment bar is appended on wp_footer, which lands it AFTER #footer rather
 * than inside it. An earlier rule only darkened it when it was a direct child
 * of body, and Porto nests it one level deeper — so the badges rendered as a
 * white strip hanging off the bottom of a navy footer.
 *
 * Paint it unconditionally instead of depending on where it lands. Sitting
 * immediately below the footer with the same ground, it reads as part of it.
 */
.ttp-skin .ttp-payments-bar {
	background: var(--ttp-dark, #101c3d) !important;
	border-top: 1px solid rgb(255 255 255 / 0.08);
	margin: 0;
}

.ttp-skin .ttp-payments-bar .ttp-payments__item {
	background: rgb(255 255 255 / 0.92);
	border-color: transparent;
	color: var(--ttp-dark, #101c3d);
}

/* ==========================================================================
   5. BUTTONS
   .btn-primary is not used in 7.7; .btn is.
   ========================================================================== */

.ttp-skin .btn {
	font-family: var(--ttp-font-heading, inherit);
	font-weight: 650;
	border-radius: 8px;
	text-transform: none;
	letter-spacing: 0.01em;
}

/*
 * Class discovery on the live home page found the real button vocabulary:
 * .btn-dark, .btn-md, .btn-sm, .btn-borders, .btn-modern, .btn-light,
 * .btn-full-rounded and .btn-special, with the banner CTAs rendered inside
 * .elementor-widget-porto_button. .btn-primary is not used anywhere.
 */
.ttp-skin .btn-primary,
.ttp-skin .btn.btn-primary,
.ttp-skin .btn-dark,
.ttp-skin .btn-special,
.ttp-skin .elementor-widget-porto_button .btn,
.ttp-skin .btn-modern.btn-primary {
	background-color: var(--ttp-primary, #1d4ed8) !important;
	border-color: var(--ttp-primary, #1d4ed8) !important;
	color: #fff !important;
}

.ttp-skin .btn-primary:hover,
.ttp-skin .btn-dark:hover,
.ttp-skin .btn-special:hover,
.ttp-skin .elementor-widget-porto_button .btn:hover {
	background-color: var(--ttp-primary-hover, #1a45be) !important;
	border-color: var(--ttp-primary-hover, #1a45be) !important;
	color: #fff !important;
	box-shadow: 0 6px 16px rgb(var(--ttp-primary-rgb, 29 78 216) / 0.28);
}

/* Outline variants keep a transparent ground and take the brand on the edge. */
.ttp-skin .btn-borders,
.ttp-skin .btn-light {
	background-color: transparent !important;
	border-color: var(--ttp-border-strong, #cbd5e1) !important;
	color: var(--ttp-ink, #0b1220) !important;
}

.ttp-skin .btn-borders:hover,
.ttp-skin .btn-light:hover {
	background-color: var(--ttp-primary-soft, #edf1fc) !important;
	border-color: var(--ttp-primary, #1d4ed8) !important;
	color: var(--ttp-primary, #1d4ed8) !important;
}

/* YITH wishlist buttons on cards — 12 of them on the home page. */
.ttp-skin .yith-wcwl-add-button a,
.ttp-skin .yith-wcwl-add-to-wishlist a {
	color: var(--ttp-muted, #64748b) !important;
}

.ttp-skin .yith-wcwl-add-button a:hover,
.ttp-skin .yith-wcwl-add-to-wishlist a:hover {
	color: var(--ttp-danger, #dc2626) !important;
}

/*
 * Elementor buttons. The homepage banners are Elementor blocks, so the visible
 * "Shop Now" controls are .elementor-button, not Porto's .btn — which is why
 * .btn-primary matched nothing on the diagnostics run.
 *
 * Only geometry and typography are set here. Colour is left to Elementor,
 * because those buttons sit on banner artwork whose contrast the client chose
 * per banner; forcing brand blue onto all of them would break some of them.
 */
.ttp-skin .elementor-button {
	font-family: var(--ttp-font-heading, inherit);
	font-weight: 650;
	letter-spacing: 0.01em;
	border-radius: 8px;
	transition: transform 0.15s ease, box-shadow 0.24s ease, filter 0.15s ease;
}

.ttp-skin .elementor-button:hover {
	transform: translateY(-1px);
	filter: brightness(1.05);
	box-shadow: 0 6px 16px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.18);
}

@media (prefers-reduced-motion: reduce) {
	.ttp-skin .elementor-button,
	.ttp-skin .elementor-button:hover { transition: none; transform: none; }
}

/* ==========================================================================
   6. CAROUSELS
   NOTE: the second diagnostics run found neither Swiper nor Owl classes on
   this store, so Porto 7.7 is using its own carousel markup. The rules below
   cover both libraries as a fallback; the real class names come from the
   class-discovery section of the diagnostics report and will be added once
   confirmed. Nothing here is load-bearing — unmatched selectors leave Porto's
   own control styling in place.
   ========================================================================== */

.ttp-skin .swiper-button-next,
.ttp-skin .swiper-button-prev,
.ttp-skin .porto-carousel .swiper-button-next,
.ttp-skin .porto-carousel .swiper-button-prev {
	width: 38px !important;
	height: 38px !important;
	background: #fff !important;
	color: var(--ttp-ink, #0b1220) !important;
	border: 1px solid var(--ttp-border, #e2e8f0) !important;
	border-radius: 999px !important;
	box-shadow: 0 2px 8px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.1);
	transition: background-color 0.15s ease, color 0.15s ease;
}

.ttp-skin .swiper-button-next:hover,
.ttp-skin .swiper-button-prev:hover {
	background: var(--ttp-primary, #1d4ed8) !important;
	color: #fff !important;
	border-color: var(--ttp-primary, #1d4ed8) !important;
}

.ttp-skin .swiper-button-next::after,
.ttp-skin .swiper-button-prev::after {
	font-size: 14px !important;
	font-weight: 700;
}

.ttp-skin .swiper-pagination-bullet {
	background: var(--ttp-border-strong, #cbd5e1) !important;
	opacity: 1;
}

.ttp-skin .swiper-pagination-bullet-active {
	background: var(--ttp-primary, #1d4ed8) !important;
}

/* ==========================================================================
   7. PAGINATION
   ========================================================================== */

.ttp-skin .page-numbers {
	border-radius: 8px;
	border-color: var(--ttp-border, #e2e8f0);
	color: var(--ttp-ink, #0b1220);
	font-family: var(--ttp-font-heading, inherit);
	font-weight: 650;
}

.ttp-skin .page-numbers.current,
.ttp-skin li .page-numbers.current {
	background: var(--ttp-primary, #1d4ed8) !important;
	border-color: var(--ttp-primary, #1d4ed8) !important;
	color: #fff !important;
}

/* ==========================================================================
   8. THIRD-PARTY REVIEW PLUGIN
   The store runs an "alpus-aprs" review add-on which injects its own blocks
   into the card and product page. Style rather than hide — but keep it from
   dominating the card.
   ========================================================================== */

.ttp-skin .alpus-aprs-review-wrapper { margin: 2px 0; }
.ttp-skin .alpus-aprs-summary-result { font-size: 11px; color: var(--ttp-muted, #94a3b8); }

/* ==========================================================================
   9a. MOBILE HEADER RANGE (up to 991px)
   Porto swaps to its mobile header at the Bootstrap lg breakpoint, 992px — not
   768px. These rules were previously scoped to 767px, which left tablets
   between 768 and 991 rendering the mobile header with none of the fixes
   applied: toggle stranded on the right, full-height chrome. Match Porto's own
   breakpoint instead of assuming one.
   ========================================================================== */

@media (max-width: 991px) {
	/*
	 * Porto's mobile header stacks search, then logo + cart, then the menu
	 * toggle on a row of its own — roughly 280px of chrome before any content,
	 * on a screen that only has about 700px. The row ORDER is a Porto theme
	 * option and isn't touched here, but the padding around it is ours to
	 * reclaim.
	 */
	.ttp-skin #header .header-main { padding-block: 6px; }
	.ttp-skin #header .header-main .container { padding-block: 0; }
	.ttp-skin #header .logo { margin-block: 0; padding-block: 0; }
	.ttp-skin #header .searchform { margin-block: 4px; }

	/*
	 * The row the toggle used to occupy is now empty — inc/header-toggle.php
	 * relocates the button — so collapse it rather than leave a blank strip in
	 * the header.
	 *
	 * The :not(:has()) guard means this only fires when the toggle really was
	 * that row's only element. On a header preset that puts something else
	 * there too, the row keeps its spacing.
	 */
	.ttp-skin #header .header-right-bottom:empty,
	.ttp-skin #header .header-right-bottom:not( :has( > * ) ) {
		min-height: 0 !important;
		padding-block: 0 !important;
		margin-block: 0 !important;
	}
}

/* ==========================================================================
   9b. SMALL SCREENS (up to 767px)
   Card typography only. These are two-up-card compensations and must NOT ride
   along with the header range above — at 900px the cards are three-up and
   comfortably wide, so shrinking their type there would be a regression.
   ========================================================================== */

@media (max-width: 767px) {
	.ttp-skin .product-content { padding: 10px 11px 12px; }

	.ttp-skin a.product-loop-title h3.woocommerce-loop-product__title,
	.ttp-skin h3.woocommerce-loop-product__title { font-size: 0.8rem; }

	.ttp-skin .product-content span.price,
	.ttp-skin li.product span.price { font-size: 0.92rem; }

	.ttp-skin .category-list { font-size: 9px; }

	.ttp-skin .add-links .button { padding: 8px 6px; font-size: 0.72rem; }

	.ttp-skin .labels > div { font-size: 9px; padding: 3px 6px; }

	/* 16px stops iOS zooming the viewport on focus. */
	.ttp-skin input[type="text"],
	.ttp-skin input[type="email"],
	.ttp-skin input[type="tel"],
	.ttp-skin input[type="password"],
	.ttp-skin select,
	.ttp-skin textarea { font-size: 16px; }
}

/* ==========================================================================
   14. SHOP TOOLBAR — PORTO'S DEMO PRODUCT FILTERS
   ========================================================================== */

/*
 * Identified by the probe on the products page:
 *
 *   [0] div.porto-product-filters.style2.mobile-sidebar   310x…  left:318
 *   [1] div.shop-loop-before   display:flex   1420px
 *
 * This is PORTO's product filter, not YITH's — the `.yith-wcan-*` targets in
 * the same probe run came back empty. Worth stating plainly because the
 * earlier diagnosis said YITH, on nothing better than the plugin being active
 * in the body classes.
 *
 * It renders the ALL CATEGORIES and SELECT COLORS dropdowns, populated from
 * attribute terms left behind by Porto's demo import — "Comfortable",
 * "Fashion Design" and the rest, which belong to a clothing shop.
 *
 * Hidden rather than restyled: an empty filter is not worth the row it sits
 * on. The permanent fix is Porto → Theme Options → Shop → Product Filters,
 * which stops the markup being produced at all; this is the interim, and
 * deleting these four lines brings the filter straight back if real
 * attributes are set up later.
 */
.ttp-skin .shop-loop-before .porto-product-filters {
	display: none !important;
}

/*
 * With the filter gone the toolbar holds only the sorting select and the
 * count, so it no longer needs to reserve the height of a filter panel.
 */
.ttp-skin .shop-loop-before {
	align-items: center;
	gap: 12px;
	min-height: 0;
}

/* ==========================================================================
   15. SHOP GRID DENSITY ON WIDE SCREENS
   ========================================================================== */

/*
 * Three columns in a 1440px container gives every product a ~470px card. For
 * chargers, cables and cases that is a poster, not a product tile: four items
 * fill a 983px-tall screen and browsing the catalogue becomes scrolling.
 *
 * Porto's column count is a theme option, and setting it there is still the
 * tidier fix. This is the safety net for the common case where it has been
 * left at the demo's value, and it scales with the screen rather than picking
 * one number for every monitor.
 *
 * The override replaces display and the item widths together, so it works
 * whether Porto lays the loop out with floats, flexbox or grid — the version
 * that ships depends on the Porto release and it is not worth depending on.
 *
 * Scoped to `.grid` deliberately: the toolbar's list-view toggle swaps that
 * class for `.list`, and forcing columns there would flatten the list layout
 * into a grid the moment anyone used the switch.
 */
@media (min-width: 1200px) {
	.ttp-skin.woocommerce ul.products.products-container.grid,
	.ttp-skin .woocommerce ul.products.products-container.grid {
		display: grid !important;
		grid-template-columns: repeat(4, minmax(0, 1fr));
		gap: 22px;
	}

	.ttp-skin.woocommerce ul.products.products-container.grid > li.product,
	.ttp-skin .woocommerce ul.products.products-container.grid > li.product {
		width: auto !important;
		max-width: none !important;
		margin: 0 !important;
		padding: 0 !important;
		float: none !important;
		clear: none !important;
	}
}

@media (min-width: 1600px) {
	.ttp-skin.woocommerce ul.products.products-container.grid,
	.ttp-skin .woocommerce ul.products.products-container.grid {
		grid-template-columns: repeat(5, minmax(0, 1fr));
	}
}

/*
 * A ceiling on image height, independent of the column count.
 *
 * Cards are as tall as their pictures, and a square image in a wide card is
 * what made these so large. Capping the height and letting the width settle
 * keeps the shot centred and the card proportionate — `object-fit: contain`
 * means nothing is cropped, only bounded.
 */
@media (min-width: 992px) {
	.ttp-skin ul.products li.product .product-image .inner img {
		max-height: 260px;
		object-fit: contain;
	}
}

/* ==========================================================================
   16. PRODUCT CARD — REFINEMENT PASS
   The card was correct but flat: a white rectangle, a photo, some text. These
   are the details that make it read as considered rather than default.
   ========================================================================== */

/*
 * A hairline border as well as a shadow.
 *
 * Shadow alone gives a card no edge on a white page — it floats without ever
 * quite landing. A 1px border at low contrast defines the shape, and the
 * shadow then only has to suggest height rather than do both jobs.
 */
.ttp-cards-elevated.ttp-skin ul.products li.product .product-inner,
.ttp-skin ul.products.products-container li.product .product-inner {
	border: 1px solid rgb(var(--ttp-ink-rgb, 11 18 32) / 0.07);
	border-radius: 16px;
	box-shadow: 0 1px 2px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.04);
}

/*
 * Hover: lift, and let the shadow take the brand hue rather than going grey.
 * A neutral drop shadow under a blue-accented card reads as a rendering
 * artefact; tinting it keeps the whole tile on one palette.
 */
.ttp-cards-elevated.ttp-skin ul.products li.product:hover .product-inner {
	border-color: rgb(var(--ttp-primary-rgb, 29 78 216) / 0.22);
	box-shadow: 0 2px 4px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.05),
		0 14px 30px rgb(var(--ttp-primary-rgb, 29 78 216) / 0.13);
	transform: translateY(-4px);
}

/*
 * The image sits on a tinted plate, not on the card itself.
 *
 * Most of this catalogue is cut-out product photography on white. On a white
 * card there is no boundary at all between the photo and the tile, so the
 * product appears to float in an undefined space. A faint plate gives the shot
 * somewhere to sit and separates it from the text beneath.
 */
.ttp-skin ul.products li.product .product-image {
	background: transparent;
	padding: 10px 10px 0;
}

.ttp-skin ul.products li.product .product-image .inner {
	/*
	 * White, to match white product photography.
	 *
	 * This was a tinted plate, on the assumption that a cut-out shot needs
	 * something to sit on. With white-background photography it does the
	 * opposite: the picture covers the middle of the plate and leaves the tint
	 * showing only as a band around it — and on hover, where the image scales
	 * to 1.05 and covers more, that band narrows to a hard line that appears
	 * and disappears with the pointer. That was the "funny line".
	 *
	 * White plate, white photo, no edge. Card separation now comes entirely
	 * from the border, the shadow and the page wash behind it, which is what
	 * those were for.
	 */
	background: #fff;
	border-radius: 12px;
	overflow: hidden;

	/*
	 * clip-path as well as overflow, and it is the clip-path doing the work.
	 *
	 * On hover the card gets `transform: translateY(-4px)` and the photo inside
	 * gets `scale(1.05)`. Once an ancestor is transformed, Chrome promotes the
	 * subtree to its own layer and stops clipping the scaled child to this
	 * element's ROUNDED rectangle reliably — the corners are honoured, the
	 * straight edges leak. That is the grey sliver appearing down the left and
	 * right of the plate under the pointer, and only under the pointer.
	 *
	 * clip-path clips geometrically rather than as a paint-time overflow rule,
	 * so it survives layer promotion. The radius is repeated here because the
	 * two properties do not read each other.
	 */
	clip-path: inset( 0 round 12px );
}

/* A restrained zoom. Enough to acknowledge the pointer, not enough to make a
   shopper feel the page is moving underneath them. */
.ttp-skin ul.products li.product .product-image .inner img {
	transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.ttp-skin ul.products li.product:hover .product-image .inner img {
	transform: scale(1.05);
}

/* --- Text block ----------------------------------------------------------- */

.ttp-skin ul.products li.product .product-content {
	padding: 13px 14px 15px;
}

/* The price is the fact people scan for; give it the weight to be found. */
.ttp-skin ul.products li.product .product-content span.price,
.ttp-skin ul.products li.product span.price {
	display: block;
	margin: 2px 0 0;
	font-family: var(--ttp-font-heading, inherit);
	font-size: 1.05rem;
	font-weight: 800;
	letter-spacing: -0.015em;
	color: var(--ttp-ink, #0b1220);
	font-variant-numeric: tabular-nums;
}

/* A struck-through original only has to be legible, not loud. */
.ttp-skin ul.products li.product span.price del {
	font-size: 0.8em;
	font-weight: 600;
	opacity: 0.45;
}

.ttp-skin ul.products li.product span.price ins {
	text-decoration: none;
	color: var(--ttp-deal, #b45309);
}

.ttp-skin ul.products li.product .rating-wrap {
	margin: 4px 0 2px;
}

/* --- Call to action ------------------------------------------------------- */

/*
 * Tinted at rest, solid on hover. A full-strength button on every tile turns a
 * grid of twenty products into twenty competing calls to action; the quiet
 * state lets the photography lead and the button still answers the pointer.
 */
.ttp-skin ul.products li.product .add-links .button,
.ttp-skin ul.products li.product .add-links .add_to_cart_button,
.ttp-skin ul.products li.product .add-links .product_type_variable,
.ttp-skin ul.products li.product .add-links .product_type_simple {
	border-radius: 10px;
	font-weight: 650;
	letter-spacing: -0.005em;
	transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.2s ease;
}

.ttp-skin ul.products li.product:hover .add-links .button,
.ttp-skin ul.products li.product:hover .add-links .add_to_cart_button,
.ttp-skin ul.products li.product:hover .add-links .product_type_variable {
	box-shadow: 0 4px 12px rgb(var(--ttp-primary-rgb, 29 78 216) / 0.22);
}

/* Keyboard users get the same affordance the pointer gets. */
.ttp-skin ul.products li.product .add-links .button:focus-visible {
	outline: 2px solid var(--ttp-primary, #1d4ed8);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.ttp-skin ul.products li.product .product-inner,
	.ttp-skin ul.products li.product:hover .product-inner,
	.ttp-skin ul.products li.product .product-image .inner img,
	.ttp-skin ul.products li.product:hover .product-image .inner img {
		transition: none;
		transform: none;
	}
}

/* ==========================================================================
   17. BLUE WASH
   The store read as white-on-white: white cards on a white page, separated
   only by hairlines. These are the places blue can carry without shouting.
   ========================================================================== */

/*
 * The page gets a cool off-white and the cards stay pure white.
 *
 * This is the change that does most of the work. A white card on a white page
 * is not a card — it is a rectangle of text, and no amount of shadow fixes
 * that. Dropping the page a couple of percent toward blue makes every white
 * surface on it read as raised, which is why the shadows suddenly look
 * deliberate rather than smudged.
 *
 * Ported through the existing --ttp-canvas token, so it follows the brand
 * colour set in Customise → TrustedTech rather than being a second hardcoded
 * palette to keep in step.
 */
.ttp-skin.ttp-bg-wash,
.ttp-skin.ttp-bg-wash .page-wrapper,
.ttp-skin.ttp-bg-wash #main,
.ttp-skin.ttp-bg-wash .main-content,
.ttp-skin.ttp-bg-wash .content-area {
	background-color: var(--ttp-canvas, #f6f8fb);
}

/*
 * ...and the things that must stay white, stay white. Left to inherit, the
 * wash would flatten the very surfaces it exists to lift.
 */
.ttp-skin #header,
.ttp-skin .header-main,
.ttp-skin ul.products li.product .product-inner,
.ttp-skin .cart_totals,
.ttp-skin .woocommerce-checkout-review-order,
.ttp-skin .single-product div.product .summary,
.ttp-skin .tt-cat-card,
.ttp-skin .tt-usp {
	background-color: #fff;
}

/*
 * Borders pick up the hue too.
 *
 * A neutral grey hairline against a blue-tinted page reads as slightly dirty.
 * Same lightness, a few points of blue in it, and the whole page agrees.
 */
.ttp-skin {
	--ttp-border: rgb(var(--ttp-primary-rgb, 29 78 216) / 0.13);
	--ttp-border-strong: rgb(var(--ttp-primary-rgb, 29 78 216) / 0.24);
}

/* --- Breadcrumb / page title bar ----------------------------------------- */

/* .page-top itself is handled in section 6 — spacing only, no surface. */
.ttp-skin .page-top .breadcrumb > li.active,
.ttp-skin .breadcrumb > li + li::before {
	color: var(--ttp-primary, #1d4ed8);
}

/* --- Shop toolbar --------------------------------------------------------- */

/* It is a control strip, so let it look like one rather than like content. */
.ttp-skin .shop-loop-before {
	background: rgb(var(--ttp-primary-rgb, 29 78 216) / 0.045);
	border: 1px solid rgb(var(--ttp-primary-rgb, 29 78 216) / 0.1);
	border-radius: 12px;
	padding: 8px 14px;
}

/* --- Small blue touches --------------------------------------------------- */

/* Selection in the brand colour rather than the browser's default blue. */
.ttp-skin ::selection {
	background: rgb(var(--ttp-primary-rgb, 29 78 216) / 0.18);
	color: var(--ttp-ink, #0b1220);
}

/* The category eyebrow on each card, which was a neutral grey. */
.ttp-skin ul.products li.product .category-list,
.ttp-skin ul.products li.product .category-list a {
	color: rgb(var(--ttp-primary-rgb, 29 78 216) / 0.72);
}

/* Section headings get a short blue rule, so a run of sections has rhythm. */
.ttp-skin .tt-section-head .tt-section-head__title::after {
	content: "";
	display: block;
	width: 44px;
	height: 3px;
	margin-top: 12px;
	border-radius: 2px;
	background: var(--ttp-primary, #1d4ed8);
}

.ttp-skin .tt-section-head--center .tt-section-head__title::after {
	margin-inline: auto;
}

/*
 * Star ratings.
 *
 * WooCommerce's default gold on a blue-leaning page is the one colour on
 * screen that belongs to no part of the palette. Keeping stars gold is still
 * the right call — shoppers read gold as a rating and nothing else — but the
 * empty half of the rating goes blue-grey so it sits with everything around it.
 */
.ttp-skin .star-rating::before {
	color: rgb(var(--ttp-primary-rgb, 29 78 216) / 0.22);
}

/*
 * Footer: a blue rule above it so the dark band arrives deliberately rather
 * than as an abrupt edge at the end of a pale page.
 */
.ttp-skin #footer {
	border-top: 3px solid var(--ttp-primary, #1d4ed8);
}

/* ==========================================================================
   18. PAGE BACKGROUND — GRADIENT MODE
   Customise → TrustedTech → Skin → Page background → "Blue gradient".
   ========================================================================== */

/*
 * A blue field with the page floating on it as a white panel.
 *
 * Built from the brand tokens rather than fixed hues, so changing the primary
 * colour in the Customiser moves the whole gradient with it instead of leaving
 * a blue background under a differently-blue site.
 *
 * background-attachment: fixed so the gradient belongs to the window rather
 * than the document. Without it a long catalogue page repeats the ramp over
 * and over as you scroll, and the effect reads as a texture instead of a
 * background.
 */
.ttp-skin.ttp-bg-gradient {
	background-color: var(--ttp-gradient-from, #e8f0fe);
	background-image: linear-gradient(
		var(--ttp-gradient-angle, 158deg),
		var(--ttp-gradient-from, #e8f0fe) 0%,
		var(--ttp-gradient-to, #bfd9f5) 100%
	);
	background-attachment: fixed;
}

.ttp-skin.ttp-bg-gradient .page-wrapper,
.ttp-skin.ttp-bg-gradient #main,
.ttp-skin.ttp-bg-gradient .content-area,
.ttp-skin.ttp-bg-gradient .site-main {
	background: transparent;
}

/*
 * The panel.
 *
 * :has() is the whole reason this is safe. The TrustedTech hero, bands and
 * newsletter break out to the full viewport width by design; inside a rounded
 * white panel they would burst straight out of it, corners and all. So a page
 * containing any of them keeps the plain treatment, and only ordinary pages —
 * shop, category, cart, checkout, account, posts — become panels.
 */
.ttp-skin.ttp-bg-gradient .main-content:not(
	:has( .tt-hero, .tt-band, .tt-newsletter, .tt-hero-slider, .tt-rev )
) {
	background: #fff;
	border-radius: clamp(14px, 2vw, 26px);
	padding: clamp(14px, 2.2vw, 38px);
	margin-block: clamp(14px, 2.2vw, 36px);
	box-shadow: 0 24px 70px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.24);
}

/*
 * Chrome that sits OUTSIDE the panel is now on colour, so it inverts.
 *
 * The second rule matters more than the first: where a Porto template puts the
 * breadcrumb inside .main-content instead of above it, the panel is white and
 * white-on-white would be invisible. Restoring inherit there costs nothing when
 * the breadcrumb is outside, and saves the page when it is not.
 */
.ttp-skin.ttp-bg-gradient .page-top,
.ttp-skin.ttp-bg-gradient .page-top a,
.ttp-skin.ttp-bg-gradient .page-top .page-title,
.ttp-skin.ttp-bg-gradient .page-top h1,
.ttp-skin.ttp-bg-gradient .breadcrumb,
.ttp-skin.ttp-bg-gradient .breadcrumb a,
.ttp-skin.ttp-bg-gradient .breadcrumb > li + li::before,
/*
 * The current crumb needs listing explicitly. It is coloured primary blue
 * further up this file by a selector carrying an element — (0,3,1) — which
 * out-specifies a two-class rule however late it appears, so it stayed blue on
 * a blue field and vanished. Matching the element restores the tie-break to
 * source order.
 */
.ttp-skin.ttp-bg-gradient .page-top .breadcrumb > li.active {
	/*
	 * Computed in PHP from the gradient's first stop, so lightening the field
	 * in the Customiser flips this to dark text instead of leaving white
	 * breadcrumbs on pale blue. A hardcoded #fff here was fine only for as long
	 * as the gradient stayed dark, which is exactly one release.
	 */
	color: var(--ttp-on-gradient, #fff);
}

.ttp-skin.ttp-bg-gradient .main-content .page-top,
.ttp-skin.ttp-bg-gradient .main-content .page-top a,
.ttp-skin.ttp-bg-gradient .main-content .page-top .page-title,
.ttp-skin.ttp-bg-gradient .main-content .page-top h1,
.ttp-skin.ttp-bg-gradient .main-content .breadcrumb,
.ttp-skin.ttp-bg-gradient .main-content .breadcrumb a {
	color: inherit;
}

/*
 * The card shadow has to change with the ground under it.
 *
 * A shadow tuned for a pale page disappears against saturated blue — the tile
 * loses its edge and the grid flattens. Deeper and darker restores the lift
 * the design relies on.
 */
.ttp-cards-elevated.ttp-skin.ttp-bg-gradient ul.products li.product .product-inner {
	box-shadow: 0 2px 6px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.12),
		0 10px 24px rgb(var(--ttp-ink-rgb, 11 18 32) / 0.14);
}

/* ==========================================================================
   19. PAGE BACKGROUND — PLAIN WHITE
   For anyone who wants Porto's original flat white back.
   ========================================================================== */

.ttp-skin.ttp-bg-white,
.ttp-skin.ttp-bg-white .page-wrapper,
.ttp-skin.ttp-bg-white #main,
.ttp-skin.ttp-bg-white .main-content,
.ttp-skin.ttp-bg-white .content-area {
	background-color: #fff;
}

/* ==========================================================================
   20. HERO FLUSH TO THE HEADER
   ========================================================================== */

/*
 * A strip of page background was showing between the header and the hero.
 *
 * The hero breaks out to full viewport width and paints its own dark field, so
 * any padding on the wrappers above it does not get painted with it — it shows
 * whatever the page background is. Against a white page that was invisible;
 * against the gradient it became a bright band across the top of the hero,
 * which is what made it obvious.
 *
 * Scoped with :has() to pages that actually open with a hero. On every other
 * page that top padding is doing its job and separating content from the
 * header, so removing it everywhere would be a regression to fix a homepage
 * problem.
 */
.ttp-skin #main:has( .tt-hero, .tt-hero-slider, .tt-rev ),
.ttp-skin .main-content:has( .tt-hero, .tt-hero-slider, .tt-rev ),
.ttp-skin .content-area:has( .tt-hero, .tt-hero-slider, .tt-rev ),
.ttp-skin .site-main:has( .tt-hero, .tt-hero-slider, .tt-rev ),
.ttp-skin .page-wrapper:has( .tt-hero, .tt-hero-slider, .tt-rev ) .page-content {
	padding-top: 0 !important;
	margin-top: 0 !important;
}

/*
 * An empty page-title bar above a hero is a gap and nothing else.
 *
 * Porto still outputs .page-top on a page that has no breadcrumb or title to
 * put in it, and this theme gives it vertical padding. On the homepage that is
 * 36px of nothing between the header and the hero.
 */
.ttp-skin .page-top:not( :has( .breadcrumb, h1, .page-title, .entry-title ) ) {
	display: none !important;
}

/* Elementor and WPBakery both add their own margin to a first section. */
.ttp-skin .tt-hero:first-child,
.ttp-skin .tt-hero-slider:first-child,
.ttp-skin .tt-rev:first-child,
.ttp-skin .elementor-section:first-child .tt-hero,
.ttp-skin .elementor-element:first-child > .tt-hero,
.ttp-skin .vc_row:first-child .tt-hero {
	margin-top: 0 !important;
}

/*
 * No shadow under the image block.
 *
 * Porto casts a drop shadow from .product-image on hover. It made sense in
 * Porto's own design, where the image sits on a tinted plate and the shadow
 * separates the two. Here the plate is white and the card beneath it is white,
 * so there is nothing for it to separate — it just draws a soft grey band
 * across the middle of the card that appears under the pointer and vanishes
 * again.
 *
 * The card's own elevation lives on .product-inner and is untouched; this only
 * clears the inner block. Both the resting and hover states are listed because
 * Porto sets them separately, and clearing one leaves the other to fire.
 */
.ttp-skin ul.products li.product .product-image,
.ttp-skin ul.products li.product .product-image .inner,
.ttp-skin ul.products li.product:hover .product-image,
.ttp-skin ul.products li.product:hover .product-image .inner,
.ttp-skin ul.products li.product:hover .product-image::after,
.ttp-skin ul.products li.product .product-image .img-effect {
	box-shadow: none !important;
	filter: none !important;
}
