/* stylelint-disable function-name-case */
// typography mixins

// until this chromium issue with paint-order is resolved, text-stroke is functionally useless: https://bugs.chromium.org/p/chromium/issues/detail?id=815111
// yes, i am bitter, because even safari has supported it for ~4 years at this point :)
// in the mean time, we can fake a 1px solid outside stroke by stacking text-shadow or drop-shadow filters. be cautious with overusing it; they're not blurred, so the computational cost isn't *too* bad, but that's still 6x as many shadows as we want to be drawing.
// if you want this + a soft shadow, LESS can combine them with square bracket notation to access the text-shadow property.
// generated with owumaro.github.io/text-stroke-generator/
.textStrokeMixin(@color: var(--ironsworn-color-text-stroke)) {
	text-shadow: 1px 0 0 @color, 0.540302px 0.841471px 0 @color,
		-0.416147px 0.909297px 0 @color, -0.989993px 0.14112px 0 @color,
		-0.653644px -0.756803px 0 @color, 0.283662px -0.958924px 0 @color,
		0.96017px -0.279416px 0 @color;
}

.initial-caps {
	&::first-letter {
		text-transform: uppercase;
	}
}

// special effects

// used to mark focused fields
.borderGlowExteriorMixin(@spread:6px) {
	box-shadow: 0 0 @spread var(--ironsworn-color-cool);
}

// used inside block/tab like elements. it's inset so that both the focus effect and the hover effect can be visible at once.
.borderGlowInteriorMixin(@spread:5px,@blur:0,@color:var(--ironsworn-color-cool)) {
	box-shadow: inset 0 0 @spread @blur @color;
}

// sets border colours, modelled after the hover effect on FVTT's canvas buttons.
.borderAccentColorMixin(@warm:var(--ironsworn-color-warm),@cool:var(--ironsworn-color-cool)) {
	border-color: @warm;
	border-bottom-color: @cool;
}

.textGlowMixin(@color:var(--ironsworn-color-fg-highlight),@spread:10px) {
	text-shadow: 0 0 @spread @color;
}

// used for e.g. hover effects. resembles a transparent overlay (with a subtle gradient) without having to do any interpolation or set additional variables.
.overlayGlowMixin(@blockSize:50px) {
	.borderGlowInteriorMixin(calc(@blockSize / 2),0,var(--ironsworn-color-thematic,var(--ironsworn-color-clickable-block-bg-hover)));
}

.borderFloatingMixin {
	border-style: outset;
	border-color: var(--ironsworn-color-border);
}

.tabBaseMixin(@glowSpread: 5px, @glowBlur: 1px,@borderWidth: var(--ironsworn-border-width-md)) {
	border-width: @borderWidth;

	&:hover {
		.borderGlowInteriorMixin(@glowSpread, @glowBlur, var(--ironsworn-color-clickable-block-bg-selected));

		border-color: var(--ironsworn-color-fg-muted);
	}

	&[aria-selected='true'],
	&.active {
		.borderGlowInteriorMixin(@glowSpread, @glowBlur, var(--ironsworn-color-cool));

		border-color: var(--ironsworn-color-warm);
	}
}

.tabTopMixin(@borderRadius:var(--ironsworn-border-radius-lg)) {
	.tabBaseMixin();

	border-bottom-width: 0;
	border-top-left-radius: @borderRadius;
	border-top-right-radius: @borderRadius;
}
.tabBottomMixin(@borderRadius:var(--ironsworn-border-radius-lg)) {
	.tabBaseMixin();

	border-top-width: 0;
	border-bottom-left-radius: @borderRadius;
	border-bottom-right-radius: @borderRadius;
}
.tabLeftMixin(@borderRadius:var(--ironsworn-border-radius-lg)) {
	.tabBaseMixin();

	border-right-width: 0;
	border-top-left-radius: @borderRadius;
	border-bottom-left-radius: @borderRadius;
}
.tabRightMixin(@borderRadius:var(--ironsworn-border-radius-lg)) {
	.tabBaseMixin();

	border-left-width: 0;
	border-top-right-radius: @borderRadius;
	border-bottom-right-radius: @borderRadius;
}

.borderMixin(@color:var(--ironsworn-color-border),@width:var(--ironsworn-border-width-md)) {
	border-width: @width;
	border-style: solid;
	color: @color;
}

// CLICKABLE MIXINS

.interactiveMixin {
	transition: var(--ironsworn-transition);
	&.disabled, // FIXME: ditch this class, its redundant with more semantic options
    &:disabled,
    &[aria-disabled="true"] {
		opacity: 0.35;
		cursor: not-allowed;
		color: inherit;
		pointer-events: none;
	}
}

.textHoverMixin {
	color: var(--ironsworn-color-clickable-text-hover);
	filter: var(--ironsworn-filter-highlight);
}

.textFocusMixin {
	.focusOutlineMixin();
}

.textActiveMixin {
	color: var(--ironsworn-color-clickable-text-selected);
	filter: var(--ironsworn-filter-highlight);
}

.clickableTextMixin {
	--ironsworn-color-text-stroke: transparent;

	transition-duration: var(--ironsworn-transition-duration);
	transition-property: color, filter, text-shadow, text-stroke;
	transition-timing-function: var(--ironsworn-transition-timing-function);
	margin: 0;
	border-width: 0;
	box-shadow: none !important;
	// .textStrokeMixin();
	background: transparent;
	color: var(--ironsworn-color-clickable-text);

	&:hover,
	&.hover {
		--ironsworn-color-text-stroke: var(--ironsworn-color-warm-50);
		.textHoverMixin();
	}

	&:focus,
	&:focus-within {
		--ironsworn-color-text-stroke: var(--ironsworn-color-warm-50);
		.textFocusMixin();
	}
	// we can't do much about the paint order here, but that's fine -- the overlap of a transparent color creates a nice effect here.
	&[aria-selected='true'],
	&.selected,
	&.active {
		--ironsworn-color-text-stroke: var(--ironsworn-color-warm-50);
		.textActiveMixin();
	}
	.interactiveMixin();
}

.blockHoverMixin(@blockSize:50px) {
	z-index: var(--ironsworn-z-index-higher);
	border-color: var(--ironsworn-color-clickable-block-border-hover);
	background-color: var(--ironsworn-color-clickable-block-bg-hover);
	color: var(--ironsworn-color-clickable-block-fg-hover);
}

.blockFocusMixin {
	z-index: var(--ironsworn-z-index-highest);
	.focusOutlineMixin();
}

.blockActiveMixin {
	z-index: var(--ironsworn-z-index-high);
	outline: none;
	border-color: var(--ironsworn-color-clickable-block-border-selected);
	background-color: var(
		--ironsworn-color-thematic,
		var(--ironsworn-color-clickable-block-bg-selected)
	);
	color: var(--ironsworn-color-clickable-block-fg-selected);
}

// For the block's 'default' state.
.blockMixin(@blockSize:50px) {
	.interactiveMixin();

	border-style: solid;
	border-color: var(--ironsworn-color-clickable-block-border);
	box-shadow: none;
	background-color: var(--ironsworn-color-clickable-block-bg);
	overflow-y: visible;
	color: var(--ironsworn-color-clickable-block-fg);

	&.vertical-text {
		writing-mode: initial !important; // prevents this fix from breaking the button layout in FF
		flex-direction: column;

		& > * {
			writing-mode: vertical-lr !important;
		}
	}
}

.iconButtonBaseMixin {
	display: flex;
	flex-flow: row nowrap;
	align-content: center;
	align-items: center;
	justify-content: center;
	padding: var(--ironsworn-spacer-xs);
	text-align: center;

	&::before {
		width: var(--ironsworn-icon-size);
		height: var(--ironsworn-icon-size);
		line-height: 1;
	}

	&:not(:empty) {
		gap: var(--ironsworn-spacer-xs);
	}

	&:empty {
		flex-grow: 0;
		// restricts width + removes border if there's no text
		border: none !important;
		width: max-content;
		height: max-content;
		line-height: 1;
	}
	// override to compensate for chrome user agent stylesheet bug: https://bugs.chromium.org/p/chromium/issues/detail?id=681917
	.button-text {
		// makes this seamless with existing buttons that don't need this styling
		display: inline;

		strong {
			white-space: nowrap;
		}
	}

	&.vertical-text {
		writing-mode: initial !important; // prevents this fix from breaking the button layout in FF
		flex-direction: column;

		.button-text {
			display: inherit;
			line-height: inherit;
			writing-mode: inherit;
		}
	}
}

.clickableBlockMixin(@blockSize:50px) {
	.blockMixin(@blockSize);

	&:hover,
	&.hover {
		.blockHoverMixin(@blockSize);
	}

	&:focus,
	&:focus-within {
		.blockFocusMixin();
	}

	&[aria-selected='true'],
	&.selected,
	&.active {
		.blockActiveMixin();
	}
}

// input mixins

.inputFieldFocusMixin(@spread: 6px) {
	.borderGlowExteriorMixin(@spread);
	.borderAccentColorMixin(var(--ironsworn-color-warm-50), var(--ironsworn-color-cool-50));

	outline: var(--ironsworn-border-width-md) solid var(--ironsworn-color-warm);
}

.inputFieldStaticMixin() {
	border-width: var(--ironsworn-border-width-md);
	border-style: var(--ironsworn-input-border-style);
	border-radius: var(--ironsworn-border-radius-md);
	border-color: var(--ironsworn-color-input-border);
	background: var(--ironsworn-color-input-bg);
	color: var(--ironsworn-color-fg);
}

.inputFieldMixin(@spread:6px) {
	// specify invisible outline to stop jitter from border width transition
	outline-width: var(--ironsworn-border-width-md);
	outline-style: solid;
	outline-color: transparent;
	.interactiveMixin();
	.inputFieldStaticMixin();

	cursor: initial;

	&::placeholder {
		opacity: 0.5;
		color: var(--ironsworn-color-fg);
	}

	&[readonly],
	&[aria-readonly='true'] {
		cursor: default;
	}

	&:not([readonly], [aria-readonly='true']) {
		&:hover {
			border-color: var(--ironsworn-color-clickable-block-border-hover);
			.borderGlowInteriorMixin(@spread, 0, var(--ironsworn-color-cool));
		}

		&:focus,
		&:focus-within {
			.inputFieldFocusMixin();
			.borderAccentColorMixin(var(--ironsworn-color-warm-80), var(--ironsworn-color-cool-80));

			&:hover {
				box-shadow: .inputFieldFocusMixin() [box-shadow],
					.borderGlowInteriorMixin(@spread, 0, var(--ironsworn-color-cool))
						[box-shadow];
			}
		}
	}
}

.marginMixin(@direction) {
	@spacer: var(--ironsworn-spacer-md);

	position: relative;
	flex: 0;
	border-@{direction}-style: solid;
	border-@{direction}-width: var(--ironsworn-border-width-md);
	margin-@{direction}: @spacer;
	border-@{direction}-color: var(--ironsworn-color-border);
}

.focusOutlineMixin() {
	// outline disabled for now
	// outline: 1px solid var(--ironsworn-color-cool) !important;
	z-index: var(--ironsworn-z-index-highest);
}

// used on draggables, highlighted table rows in chat. set opacity in increments of 10 (because otherwise the CSS variable won't exist).
// since gradients are *images*, they're overlaid on top of background-colour. great for a lazy tint on a highlighted element.
// we *could* just make it a single-color 'gradient', but i think the subtle colour movement is kinda fun. :)
// only problem is they're not currently animatable... at least, not without getting some sorcery w/ pseudo-elements involved.
.staticHighlightMixin(@opacity:20,@direction:'to bottom') {
	background-image: e(
		%(
			'linear-gradient(%s, var(--ironsworn-color-warm-%s), var(--ironsworn-color-cool-%s))',
			@direction,
			@opacity,
			@opacity
		)
	);
	background-blend-mode: overlay;
}

.overlayMixin() {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: var(--ironsworn-z-index-highest);
	content: '';
	pointer-events: none;
}

.textCompactMixin() {
	ol,
	ul {
		--ironsworn-compact-list-indent: 1em;

		padding: 0;
		padding-left: var(--ironsworn-compact-list-indent);

		li {
			margin: 0.2em 0;

			&:last-child {
				margin-bottom: 0;
			}

			&:first-child {
				margin-top: 0;
			}
		}
	}

	ul {
		list-style-type: disc;

		ul {
			list-style-type: circle;

			ul {
				list-style-type: square;
			}
		}
	}
}
