/* TCB Service Post List — expanding card catalog.
 *
 * Structural only. Colours, spacing, radii and typography come from the widget's
 * Elementor controls so each client site can differ without a plugin change.
 * Anything hard-coded here is layout that must not vary.
 */

.tcb-svc-catalog {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 18px;
	align-items: start;
	width: 100%;
}

/* Each column is an independent stack. This is the whole reason the widget
 * distributes posts into real column elements instead of using one grid: with
 * shared grid rows, expanding a card in column 1 pushes down the cards in
 * columns 2 and 3. Independent columns cannot do that. */
.tcb-svc-col {
	display: flex;
	flex-direction: column;
	gap: 18px;
	min-width: 0;
}

/* Opening and closing are deliberately asymmetric: opening decelerates into place,
 * closing is shorter and eases in. Equal timings in both directions read as sluggish
 * on the way out. Declaring the transition on the base rule governs COLLAPSE (the
 * state being returned to) and on .is-open governs EXPAND. */
.tcb-svc-card {
	overflow: hidden;
	transition: background-color var(--tcb-svc-collapse, 220ms) ease-in,
	            border-radius var(--tcb-svc-collapse, 220ms) ease-in,
	            transform var(--tcb-svc-collapse, 220ms) ease-in,
	            box-shadow var(--tcb-svc-collapse, 220ms) ease-in;
}

.tcb-svc-card.is-open {
	transition: background-color var(--tcb-svc-dur, 280ms) cubic-bezier(.22, .61, .36, 1),
	            border-radius var(--tcb-svc-dur, 280ms) cubic-bezier(.22, .61, .36, 1),
	            transform var(--tcb-svc-dur, 280ms) cubic-bezier(.22, .61, .36, 1),
	            box-shadow var(--tcb-svc-dur, 280ms) cubic-bezier(.22, .61, .36, 1);
}

/* The heading is a real <button> so the control is keyboard reachable and
 * announces its state. */
.tcb-svc-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	width: 100%;
	margin: 0;
	border: 0;
	background: none;
	font: inherit;
	color: inherit;
	text-align: left;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
	/* Themes commonly reset `button { white-space: nowrap }`. Inherited by the
	 * title, that stops long service names wrapping beside the thumbnail — they
	 * run underneath it and clip instead. Reassert normal wrapping here. */
	white-space: normal;
}

/* hello-elementor's reset.css carries
 *   button:hover, button:focus { background-color: #c36; color: #fff }
 * and `button:hover` (0,1,1) outranks `.tcb-svc-head` (0,1,0), so the head
 * paints a crimson panel across the whole card and hides the card's own hover
 * background entirely. The :focus half leaves a card crimson after a click.
 *
 * Two selectors' worth of specificity (0,2,0) takes it back. This belongs here
 * rather than on any one instance: the head is a <button> by design, so every
 * site on this theme family inherits the same collision. */
.tcb-svc-head:hover,
.tcb-svc-head:focus {
	background: none;
	color: inherit;
	text-decoration: none;
}

/* min-width:0 lets the title shrink below its longest word so it wraps instead of
 * forcing the flex row wider than the card; overflow-wrap catches the rare token
 * that still cannot fit, e.g. a long hyphen-free product name. The thumbnail keeps
 * its full width throughout (flex: none), so the title always wraps around it. */
.tcb-svc-title {
	margin: 0;
	min-width: 0;
	white-space: normal;
	overflow-wrap: break-word;
}

/* One thumbnail size for both states, by design decision — the card must not
 * resize its image when opening. */
.tcb-svc-thumb {
	flex: none;
	display: block;
	overflow: hidden;
	line-height: 0;
}

.tcb-svc-thumb img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Reveal via grid-template-rows 0fr -> 1fr. This animates to the content's exact
 * height, so a two-line description and a six-line one take the same time and
 * feel identical. max-height cannot: you must pick a ceiling, and short cards
 * finish early against a long timing curve, which is what reads as choppy. */
.tcb-svc-body {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows var(--tcb-svc-collapse, 220ms) ease-in;
}

.tcb-svc-card.is-open > .tcb-svc-body {
	grid-template-rows: 1fr;
	transition: grid-template-rows var(--tcb-svc-dur, 280ms) cubic-bezier(.22, .61, .36, 1);
}

/* Body content fades in and rises slightly, staggered behind the panel so the text
 * arrives after there is room for it. On collapse the delay is dropped so the text
 * clears out first and the panel is never seen closing over live content. */
.tcb-svc-body-inner > * {
	opacity: 0;
	transform: translateY(6px);
	transition: opacity 160ms ease, transform 160ms ease;
}

.tcb-svc-card.is-open .tcb-svc-body-inner > * {
	opacity: 1;
	transform: none;
	transition-delay: 80ms;
}

.tcb-svc-body-inner {
	overflow: hidden;
	min-height: 0;
	box-sizing: border-box;
}

/* A grid item's automatic minimum size floors at its own padding, so a padded body
 * cannot collapse to zero with grid-template-rows: 0fr — the row settles at the
 * padding height and a sliver of the description shows through. Remove the padding
 * while collapsed. It reappears the instant the card opens, inside the clipped
 * region, so the transition is unaffected.
 *
 * !important is required because the Body Padding control emits
 * `{{WRAPPER}} .tcb-svc-body-inner`, which ties this rule on specificity and wins
 * on source order. */
.tcb-svc-card:not(.is-open) > .tcb-svc-body .tcb-svc-body-inner {
	padding: 0 !important;
}

.tcb-svc-desc {
	margin: 0;
	text-wrap: pretty;
}

.tcb-svc-btn {
	display: inline-block;
	align-self: flex-start;
	text-decoration: none;
	transition: background-color .3s ease, color .3s ease;
}

/* Fallback for engines that cannot interpolate grid-template-rows. */
@supports not (grid-template-rows: 0fr) {
	.tcb-svc-body {
		display: block;
		max-height: 0;
		overflow: hidden;
		transition: max-height var(--tcb-svc-collapse, 220ms) ease-in;
	}
	.tcb-svc-card.is-open > .tcb-svc-body {
		max-height: 900px;
		transition: max-height var(--tcb-svc-dur, 280ms) cubic-bezier(.22, .61, .36, 1);
	}
}

@media (prefers-reduced-motion: reduce) {
	.tcb-svc-card,
	.tcb-svc-card.is-open,
	.tcb-svc-body,
	.tcb-svc-card.is-open > .tcb-svc-body,
	.tcb-svc-body-inner > *,
	.tcb-svc-card.is-open .tcb-svc-body-inner > *,
	.tcb-svc-btn {
		transition: none;
	}

	/* No tween, but the end state must still be reachable — otherwise the body
	 * content stays invisible for anyone with reduced motion enabled. */
	.tcb-svc-body-inner > * {
		opacity: 1;
		transform: none;
	}
}
