/*
 * MyBB Reactions Plugin
 *
 * Attached to showthread.php and misc.php, which between them render a great deal more
 * than the plugin's own markup - so every rule here is scoped to a .reactions class.
 *
 * Colours lean on the theme where it offers them (Bootstrap's custom properties, on the
 * garrison theme) and fall back to neutral greys where it does not.
 */

.reactions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	/* In the bottom right corner of the post, under the message. */
	justify-content: flex-end;
	gap: 0.5em;
	margin: 0.75em 0 0;
	font-size: 13px;
}

.reactions-icon {
	width: 18px;
	height: 18px;
	vertical-align: middle;
}

/* The summary: the most used reactions, then the count. Side by side rather than
   overlapping: overlapping pictures need a ring in the colour of what is behind them to
   stay apart, and a theme may give a post any background. */

.reactions-summary {
	display: inline-flex;
	align-items: center;
	gap: 0.35em;
	/* Muted, like the post's other furniture (the date, the edit note). */
	color: var(--bs-secondary-color, inherit);
	text-decoration: none;
}

.reactions-summary:hover .reactions-summary-text,
.reactions-summary:focus-visible .reactions-summary-text {
	text-decoration: underline;
}

.reactions-summary-icons {
	display: inline-flex;
	gap: 1px;
}

/* The React button. */

.reactions-controls {
	position: relative;
	display: inline-block;
	/* Out by the button's padding, so its label lines up with the edge of the post's text
	   rather than the edge of its hover background. */
	margin: 0 -0.6em 0 0;
}

.reactions-button {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 0.35em;
	margin: 0;
	padding: 0.3em 0.6em;
	border: 0;
	border-radius: 4px;
	background: transparent;
	color: var(--bs-secondary-color, inherit);
	font: inherit;
	cursor: pointer;
	/* A long press opens the picker, not the browser's own menu or a text selection. */
	-webkit-touch-callout: none;
	-webkit-user-select: none;
	user-select: none;
}

.reactions-button:hover,
.reactions-button:focus-visible {
	background: rgba(127, 127, 127, 0.15);
}

.reactions-button .reactions-icon {
	filter: grayscale(1);
	opacity: 0.65;
}

/* The pictures in the button and the picker are part of them, not things of their own: a
   press that starts on one is a press on the button (a long press, not dragging the
   picture away), and a press that ends on one picks its reaction. The templates mark them
   draggable="false" as well, for browsers that start a drag regardless. */
.reactions-button img,
.reactions-picker-item img {
	pointer-events: none;
	-webkit-user-drag: none;
}

.reactions-button--active {
	font-weight: bold;
	color: var(--bs-primary, #1b74e4);
}

.reactions-button--active .reactions-icon {
	filter: none;
	opacity: 1;
}

.reactions [aria-busy='true'],
.reactions[aria-busy='true'] {
	opacity: 0.6;
}

/* While a reaction is being saved, a spinner stands in for the button's picture. The
   picture keeps its place, hidden, so the button does not change size. */
.reactions[aria-busy='true'] .reactions-button {
	cursor: progress;
}

.reactions[aria-busy='true'] .reactions-button .reactions-icon {
	visibility: hidden;
}

.reactions[aria-busy='true'] .reactions-button::before {
	content: '';
	position: absolute;
	top: 50%;
	/* Over the picture: past the button's padding, and centred in the picture's 18px. */
	left: calc(0.6em + 2px);
	box-sizing: border-box;
	width: 14px;
	height: 14px;
	margin-top: -7px;
	border: 2px solid currentColor;
	border-right-color: transparent;
	border-radius: 50%;
	animation: reactions-spin 0.7s linear infinite;
}

@keyframes reactions-spin {
	to {
		transform: rotate(360deg);
	}
}

/* The picker, which floats above the button. */

.reactions-picker {
	display: none;
	position: absolute;
	bottom: calc(100% + 6px);
	/* The bar is at the right of the post, so the picker opens leftward from it. The
	   script nudges it back on screen where the post is too narrow for that. */
	right: 0;
	z-index: 100;
	gap: 8px;
	padding: 6px 10px;
	border-radius: 999px;
	background: var(--bs-body-bg, #fff);
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
	white-space: nowrap;
}

/* Bridges the gap between the picker and the button, so the pointer can cross it without
   the picker closing. */
.reactions-picker::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 100%;
	height: 8px;
}

.reactions-picker--open {
	display: flex;
	animation: reactions-pop 0.15s ease-out;
}

/* Without the script, hovering or tabbing into the bar shows the picker. */
html:not(.reactions-js) .reactions-controls:hover .reactions-picker,
html:not(.reactions-js) .reactions-controls:focus-within .reactions-picker {
	display: flex;
}

.reactions-picker-item {
	/* How much the reaction pointed at grows. Its name is drawn inside it and shrunk back
	   by the same amount, so the label is the same size whatever the zoom. */
	--reactions-picker-zoom: 1.55;
	position: relative;
	margin: 0;
	padding: 4px;
	border: 0;
	border-radius: 50%;
	background: transparent;
	line-height: 0;
	cursor: pointer;
	transition: transform 0.12s ease-out;
}

.reactions-picker-item img {
	width: 36px;
	height: 36px;
}

.reactions-picker-item:hover,
.reactions-picker-item:focus-visible,
.reactions-picker-item--hover {
	/* Over its neighbours, which it now overlaps. */
	z-index: 1;
	transform: scale(var(--reactions-picker-zoom)) translateY(-9px);
}

/* The name of the reaction pointed at, in a dark pill above it - over a mouse, above a
   finger sliding across the picker (which hides the picture itself), and on a reaction
   reached with the keyboard. Taken from aria-label, which is already the name and no
   markup, so the template does not repeat it. */
.reactions-picker-item::after {
	content: attr(aria-label);
	position: absolute;
	bottom: calc(100% + 4px);
	left: 50%;
	padding: 3px 8px;
	border-radius: 999px;
	background: rgba(0, 0, 0, 0.8);
	color: #fff;
	font-size: 12px;
	font-weight: 600;
	line-height: 1.4;
	white-space: nowrap;
	pointer-events: none;
	opacity: 0;
	transform: translateX(-50%) scale(calc(1 / var(--reactions-picker-zoom)));
	transform-origin: 50% 100%;
	transition: opacity 0.12s ease-out;
}

.reactions-picker-item:hover::after,
.reactions-picker-item:focus-visible::after,
.reactions-picker-item--hover::after {
	opacity: 1;
}

.reactions-picker-item--active::before {
	/* Big enough to take in the whole of a square picture, corners and all - wider than the
	   item, into the gaps between them. */
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: -1;
	width: 52px;
	height: 52px;
	margin: -26px 0 0 -26px;
	border-radius: 50%;
	background: rgba(127, 127, 127, 0.2);
}

@keyframes reactions-pop {
	from {
		opacity: 0;
		transform: translateY(6px) scale(0.9);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.reactions-picker--open {
		animation: none;
	}

	.reactions-picker-item,
	.reactions-picker-item::after {
		transition: none;
	}

	/* Slower rather than still: a spinner that does not turn does not say it is working. */
	.reactions[aria-busy='true'] .reactions-button::before {
		animation-duration: 1.5s;
	}
}

/* Who reacted: the popup over the thread, and the page of its own. Both are a .tborder,
   MyBB's own vocabulary for a box, so they take on the theme's surface. The page's title is
   a .thead, drawn the way the theme draws every other box's. The popup's is not: plugins
   restyle .thead inside a popup (the garrison's avatar popup makes it transparent, under
   white text), so the popup draws its own header, light like a Bootstrap modal's. */

.reactions-who-modal {
	box-sizing: border-box;
	width: 400px;
	max-width: 100%;
}

/* MyBB's popup and the garrison theme each pad .modal; the box draws its own surface,
   in the popup's corners. */
.blocker .reactions-who-modal {
	padding: 0;
}

.reactions-who-box {
	overflow: hidden;
}

.reactions-who-modal .reactions-who-box {
	border: 0;
	border-radius: inherit;
}

/* Once a tab has been picked, the popup stays where it opened rather than being centred:
   the script pins it there, so the header holds still as the list changes height. Both
   ways of centring - MyBB's inline-block beside a full-height strut, and the garrison's
   flexbox - are undone here, and the script sets "top" to put it back where it was. */
.blocker .reactions-who-modal--pinned {
	position: relative;
	align-self: flex-start;
	vertical-align: top;
}

.reactions-who-page {
	max-width: 600px;
	margin: 1em auto;
}

.reactions-who-heading {
	padding: 0.85em 1em;
	line-height: 1.3;
}

.reactions-who-modal .reactions-who-heading {
	/* Clear of the popup's close button, top right. */
	padding: 1.1em 3.5em 0.6em 1.1em;
	font-size: 1.1em;
	font-weight: 600;
}

.reactions-who-tabs {
	position: relative;
	display: flex;
	gap: 0.25em;
	padding: 0 0.5em;
	border-bottom: 1px solid var(--bs-border-color, rgba(127, 127, 127, 0.3));
	/* More reactions than fit scroll sideways rather than wrapping onto a second row - and
	   only sideways: left to itself, overflow-x: auto makes the strip scroll up and down
	   too. */
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: none;
}

.reactions-who-tab,
.reactions-who-tab:link,
.reactions-who-tab:visited,
.reactions-who-tab:hover,
.reactions-who-tab:active {
	display: inline-flex;
	flex: none;
	align-items: center;
	gap: 0.4em;
	padding: 0.7em 0.6em 0.6em;
	border-bottom: 2px solid transparent;
	color: inherit;
	font-size: 0.9em;
	text-decoration: none;
	white-space: nowrap;
}

.reactions-who-tab-label,
.reactions-who-tab-count {
	opacity: 0.65;
}

.reactions-who-tab:hover .reactions-who-tab-label,
.reactions-who-tab:hover .reactions-who-tab-count,
.reactions-who-tab:focus-visible .reactions-who-tab-label,
.reactions-who-tab:focus-visible .reactions-who-tab-count {
	opacity: 0.9;
}

.reactions-who-tab--active,
.reactions-who-tab--active:link,
.reactions-who-tab--active:visited,
.reactions-who-tab--active:hover {
	border-bottom-color: currentColor;
	font-weight: 600;
}

.reactions-who-tab--active .reactions-who-tab-label,
.reactions-who-tab--active .reactions-who-tab-count {
	opacity: 1;
}

/* Once the popup's script has switched tabs, one underline slides between them in place of
   each tab's own. The script sets where it is. */
.reactions-who-tabs--sliding .reactions-who-tab,
.reactions-who-tabs--sliding .reactions-who-tab:hover {
	border-bottom-color: transparent;
}

.reactions-who-tabs--sliding::after {
	content: '';
	position: absolute;
	bottom: 0;
	left: 0;
	width: var(--reactions-who-tab-width, 0);
	height: 2px;
	background: currentColor;
	transform: translateX(var(--reactions-who-tab-left, 0));
	transition:
		transform 0.25s ease,
		width 0.25s ease;
}

.reactions-who-list {
	max-height: 360px;
	transition: height 0.25s ease;
	margin: 0;
	padding: 0.35em 0;
	overflow-y: auto;
	list-style: none;
}

.reactions-who-row,
.reactions-who-empty {
	display: flex;
	align-items: center;
	gap: 0.75em;
	padding: 0.45em 1em;
}

.reactions-who-row:hover {
	background: rgba(127, 127, 127, 0.08);
}

.reactions-who-row[hidden] {
	display: none;
}

/* A tab's rows coming in as it is picked, from the side the tab is on. */
.reactions-who-row--in {
	animation: reactions-who-in 0.22s ease-out both;
	animation-delay: calc(var(--reactions-who-order, 0) * 25ms);
}

@keyframes reactions-who-in {
	from {
		opacity: 0;
		transform: translateX(var(--reactions-who-shift, 0));
	}
}

/* After the rules they override, which would otherwise win. */
@media (prefers-reduced-motion: reduce) {
	.reactions-who-tabs--sliding::after,
	.reactions-who-list {
		transition: none;
	}

	.reactions-who-row--in {
		animation: none;
	}
}

.reactions-who-empty {
	padding: 1.25em 1em;
	opacity: 0.7;
}

/* The member's avatar, with the reaction they picked as a badge on its corner. */
.reactions-who-avatar {
	position: relative;
	flex: none;
	width: 36px;
	height: 36px;
}

.reactions-who-avatar-image {
	display: block;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	object-fit: cover;
}

.reactions-who-avatar .reactions-who-badge {
	position: absolute;
	right: -4px;
	bottom: -4px;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: var(--bs-body-bg, #fff);
	box-shadow: 0 0 0 2px var(--bs-body-bg, #fff);
}

.reactions-who-name {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-weight: 600;
}

.reactions-who-back {
	margin-top: 1em;
}
