/*
 * Liked trips — the heart on a card, the heart in a trip hero, and the Saved
 * trips tab in My Account.
 *
 * WHAT THIS FILE DRESSES. One control in four variants, plus the screen that
 * lists what it saved:
 *
 *   .pbt-like--card   the overlay heart on a trip card in the trips grid.
 *   .pbt-like--chip   the heart in the trip hero's chips row, over the photo.
 *   .pbt-like--list   the remove control on a row of the Saved trips tab.
 *   .pbt-like--guest  the same control for a signed-out visitor, which is an
 *                     <a> to My Account rather than a <button>.
 *   .pbt-likes        the Saved trips tab itself.
 *
 * WHY IT LIVES IN THE PLUGIN AT ALL. CONTEXT.md's rule is that the theme owns
 * styling. This is the same stated exception as assets/addons/trip-addons.css
 * and account-reviews.css: the control is injected into a block-rendered card
 * and into a core WooCommerce account template by plugin code, the theme
 * carries no override for either, and a heart whose CSS lived in a switchable
 * theme would be an unstyled word floating over somebody's holiday photo.
 *
 * IT INVENTS NO COLOURS. Every value resolves to one of the theme's own custom
 * properties, mapped once in the token block below, each with a literal
 * fallback — so a renamed token leaves the control legible while somebody
 * notices rather than white-on-white.
 *
 * NO `elements.link` AND NO has-link-color. The palette has a slug named
 * `link`, so core emits `.has-link-color { color: … !important }`; anything
 * here that relied on it would be repainted out from under it. That matters
 * most for the chip variant, which sits on a dark hero.
 *
 * FOCUS RINGS ARE NOT SET HERE. The theme's motion.css carries a site-wide
 * :where(…):focus-visible ring at zero specificity, and anything stated here
 * would win silently and give these controls a ring unlike the rest of the
 * site.
 *
 * STATE IS NEVER CARRIED BY COLOUR ALONE. Two hearts are rendered into every
 * control, outline and solid, and the rules below show exactly one of them
 * based on [aria-pressed] — a shape and weight difference that survives
 * greyscale, a photograph behind it and any form of colour blindness. The
 * accessible name changes with it, in JavaScript and in PHP.
 */

/* --- Tokens ------------------------------------------------------------- */

.pbt-like,
.pbt-likes,
.pbt-like-notice {
	--pbt-like-ground: var(--wp--preset--color--base, #fbfbf7);
	--pbt-like-raised: var(--wp--preset--color--base-raised, #fdfdfa);
	--pbt-like-sunken: var(--wp--preset--color--base-sunken, #eeece4);
	--pbt-like-ink: var(--wp--preset--color--contrast, #142826);
	--pbt-like-ink-muted: var(--wp--preset--color--contrast-muted, #4b5f5e);
	--pbt-like-line: var(--wp--preset--color--line, rgba(20, 40, 38, 0.12));
	--pbt-like-on: var(--wp--preset--color--alert, #a8442a);
	--pbt-like-radius: var(--wp--custom--radius--pill, 999px);
}

/* --- The control, in every variant -------------------------------------- */

/*
 * THE BUTTON RESET IS AT ZERO SPECIFICITY, ON PURPOSE.
 *
 * The chip variant is handed the theme's .pickleball-trip-chip--glass, whose
 * whole job is a background and a border. A plain `.pbt-like { background:
 * none; border: 0 }` is (0,1,0) — the same weight — so which one won would
 * come down to the order two separately enqueued stylesheets happened to print
 * in, and the losing outcome is a glass chip with no glass.
 *
 * :where() forces this block to (0,0,0), so every real class beats it and the
 * reset only ever removes a user-agent default nobody has restyled.
 */
:where(.pbt-like) {
	background: none;
	border: 0;
	color: inherit;
	font: inherit;
	margin: 0;
	padding: 0;
}

.pbt-like {
	align-items: center;
	cursor: pointer;
	display: inline-flex;
	gap: 0.5rem;
	justify-content: center;
	line-height: 1;
	text-decoration: none;
}

.pbt-like__icon {
	align-items: center;
	display: inline-flex;
	justify-content: center;
}

.pbt-like__heart {
	display: block;
	height: 22px;
	width: 22px;
}

/*
 * Exactly one heart is ever in the box. The solid one is the saved state and
 * the outline one the unsaved state, and `display: none` rather than opacity
 * so a screen magnifier and a high-contrast renderer see one glyph, not two
 * stacked. The guest variant carries no [aria-pressed] at all — nothing is
 * being toggled — so it falls through to the outline heart by default.
 */
.pbt-like .pbt-like__heart--on {
	display: none;
}

.pbt-like[aria-pressed="true"] .pbt-like__heart--on {
	display: block;
}

.pbt-like[aria-pressed="true"] .pbt-like__heart--off {
	display: none;
}

.pbt-like[aria-pressed="true"] {
	color: var(--pbt-like-on);
}

/*
 * A request in flight is visible but not disabled. Disabling a focused button
 * moves focus to the body in several browsers, which loses a keyboard user's
 * place in a grid of eighteen cards — see the note in likes.js.
 */
.pbt-like[data-pbt-like-pending] {
	opacity: 0.72;
}

/* --- The card overlay --------------------------------------------------- */

/*
 * THE CARD NEEDS A POSITIONING CONTEXT AND DOES NOT HAVE ONE.
 * .pickleball-trip-card in blocks/trips-grid/style.css sets overflow: hidden
 * and no position, so an absolutely positioned child would anchor to the page
 * instead — eighteen hearts stacked in the top corner of the document.
 *
 * Stated through the list wrapper (0,2,0) rather than as a bare
 * .pickleball-trip-card (0,1,0), because both stylesheets are enqueued from
 * the same render and their order in <head> is not something this file can
 * promise. A higher-specificity selector wins either way.
 *
 * The heart is a SIBLING of .pickleball-card__link, not a child: a <button>
 * inside an <a> is invalid HTML and the anchor would swallow the click. It is
 * placed over the media's free top-right corner — .pickleball-card__region
 * owns top-left and .pickleball-card__spots owns bottom-right.
 */
.pickleball-trips-grid__list .pickleball-trip-card {
	position: relative;
}

.pbt-like--card {
	background: var(--pbt-like-raised);
	block-size: 2.5rem;
	border-radius: var(--pbt-like-radius);
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.22);
	color: var(--pbt-like-ink);
	inline-size: 2.5rem;
	inset-block-start: 0.75rem;
	inset-inline-end: 0.75rem;
	position: absolute;
	transition: background-color 0.18s ease, transform 0.18s ease;
	/* Above .pickleball-card__link, which is the whole card and would otherwise
	 * cover this. */
	z-index: 2;
}

.pbt-like--card:hover {
	background: var(--pbt-like-ground);
	transform: scale(1.06);
}

/*
 * The name is hidden visually, NOT semantically, and it is real text rather
 * than an aria-label: an aria-label is invisible to automatic translation and
 * to voice control, which matches on what is on screen. The clip-path pair is
 * the standard technique — `display: none` would take it out of the
 * accessibility tree with it.
 */
.pbt-like--card .pbt-like__label {
	block-size: 1px;
	clip-path: inset(50%);
	inline-size: 1px;
	overflow: hidden;
	position: absolute;
	white-space: nowrap;
}

/* --- The trip hero's chips row ------------------------------------------ */

/*
 * The chip variant is handed the theme's own .pickleball-trip-chip and
 * --glass classes by trip-hero.php, so its shape, padding and translucency are
 * the theme's and this file only adds what a button needs on top of a
 * paragraph's styling. It must not restate the chip's background or border, or
 * the three chips beside it would stop matching the moment the theme retuned
 * them.
 */
.pbt-like--chip {
	-webkit-appearance: none;
	appearance: none;
	transition: transform 0.18s ease;
}

.pbt-like--chip:hover {
	transform: translateY(-1px);
}

/*
 * On the dark hero the saved heart cannot use --pbt-like-on: the alert red is
 * a mid-tone chosen against a light ground and it goes muddy over a dimmed
 * photograph. The chips row is already base-on-dark, so the saved state reads
 * through the SOLID glyph and the changed label instead, which is the rule
 * this whole file is built on anyway.
 */
.pbt-like--chip[aria-pressed="true"] {
	color: var(--pbt-like-ground);
}

/* --- The Saved trips tab ------------------------------------------------ */

.pbt-likes__list {
	display: grid;
	gap: 1rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.pbt-likes__item {
	align-items: center;
	background: var(--pbt-like-raised);
	border: 1px solid var(--pbt-like-line);
	border-radius: var(--wp--custom--radius--card, 20px);
	display: grid;
	gap: 1rem;
	grid-template-columns: 7.5rem 1fr auto;
	padding: 0.75rem;
}

.pbt-likes__media {
	display: block;
	line-height: 0;
}

.pbt-likes__image {
	aspect-ratio: 3 / 2;
	border-radius: var(--wp--custom--radius--chip, 12px);
	display: block;
	height: auto;
	object-fit: cover;
	width: 100%;
}

.pbt-likes__image--empty {
	background: var(--pbt-like-sunken);
}

.pbt-likes__body {
	min-width: 0;
}

.pbt-likes__title {
	font-size: var(--wp--preset--font-size--base, 1rem);
	margin: 0;
}

.pbt-likes__title a {
	color: var(--pbt-like-ink);
	text-decoration: none;
}

.pbt-likes__title a:hover {
	text-decoration: underline;
}

.pbt-likes__dates,
.pbt-likes__price {
	color: var(--pbt-like-ink-muted);
	font-size: var(--wp--preset--font-size--sm, 0.875rem);
	margin: 0.25rem 0 0;
}

.pbt-like--list {
	color: var(--pbt-like-ink-muted);
	padding: 0.5rem;
}

.pbt-like--list .pbt-like__label {
	font-size: var(--wp--preset--font-size--sm, 0.875rem);
}

.pbt-likes__empty {
	color: var(--pbt-like-ink-muted);
	margin-block-start: 0;
}

/* Narrow screens: the thumbnail and the remove control both give way before
 * the title does. */
@media (max-width: 599px) {
	.pbt-likes__item {
		grid-template-columns: 4.5rem 1fr;
	}

	.pbt-like--list {
		grid-column: 2;
		justify-self: start;
		padding-inline: 0;
	}
}

/* --- The announcement --------------------------------------------------- */

/*
 * One region for the whole page, created by likes.js on first failure. It is
 * `hidden` until there is something to say, so it costs nothing on a page
 * where every save worked — which is every page.
 */
.pbt-like-notice {
	align-items: center;
	background: var(--pbt-like-ink);
	border-radius: var(--wp--custom--radius--chip, 12px);
	box-shadow: 0 6px 20px rgba(0, 0, 0, 0.26);
	color: var(--pbt-like-ground);
	display: flex;
	font-size: var(--wp--preset--font-size--sm, 0.875rem);
	gap: 0.75rem;
	inset-block-end: 1rem;
	inset-inline: 1rem auto;
	max-inline-size: min(28rem, calc(100vw - 2rem));
	padding: 0.75rem 1rem;
	position: fixed;
	z-index: 9999;
}

.pbt-like-notice__action {
	background: none;
	border: 1px solid currentColor;
	border-radius: var(--pbt-like-radius);
	color: inherit;
	cursor: pointer;
	flex: 0 0 auto;
	font: inherit;
	padding: 0.25rem 0.75rem;
	text-decoration: none;
	white-space: nowrap;
}

/* --- Motion ------------------------------------------------------------- */

/*
 * The save pulse. Only the saving direction gets it and only once, set by
 * likes.js for 500ms — see the note there on why unsaving and the server's
 * confirmation are silent.
 */
@keyframes pbt-like-pulse {
	0% {
		transform: scale(1);
	}

	40% {
		transform: scale(1.28);
	}

	100% {
		transform: scale(1);
	}
}

.pbt-like[data-pbt-like-just-saved] .pbt-like__icon {
	animation: pbt-like-pulse 0.45s ease;
}

/*
 * Nothing moves for anyone who asked for that. The state still reads — the
 * glyph swaps and the label changes — because neither of those is animation.
 * Stated here rather than left to the theme's motion.css, which cannot know
 * about selectors that ship in this plugin.
 */
@media (prefers-reduced-motion: reduce) {
	.pbt-like,
	.pbt-like:hover,
	.pbt-like__icon,
	.pbt-like[data-pbt-like-just-saved] .pbt-like__icon {
		animation: none;
		transform: none;
		transition: none;
	}
}
