/**
 * An opt-in button treatment for hand-built elements.
 *
 * The plugin no longer injects a header button — that one is an Elementor
 * widget in the header template, where an editor can see and change it. This
 * exists only so such a widget can carry the visualizer's own styling without
 * anyone rebuilding it by hand.
 *
 * To use it, add `animart-viz-button` to the widget's CSS Classes field
 * (Elementor → Advanced → CSS Classes). Elementor puts that class on the
 * widget's wrapper rather than on the link inside it, so both cases are
 * handled below.
 *
 * Nothing on the site is required to use this. If the header button is styled
 * entirely in Elementor instead, this file can be deleted along with the
 * enqueue in Animart_Viz_Entry_Points::enqueue().
 *
 * Tokens match CLAUDE.md §6: apticon pink, Lato, the kit's 3px radius.
 */

.animart-viz-button,
.animart-viz-button .elementor-button,
.animart-viz-button a {
	display: inline-flex;
	align-items: center;
	gap: 9px;

	padding: 9px 16px;
	border: 1px solid #ED2079;
	border-radius: 3px;

	color: #FFFFFF;
	background: transparent;
	text-decoration: none;

	font-family: "Lato", Helvetica, Arial, sans-serif;
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	line-height: 1;
	white-space: nowrap;

	transition: background-color 0.16s ease, color 0.16s ease;
}

.animart-viz-button:hover,
.animart-viz-button:focus,
.animart-viz-button .elementor-button:hover,
.animart-viz-button .elementor-button:focus,
.animart-viz-button a:hover,
.animart-viz-button a:focus {
	background: #ED2079;
	color: #FFFFFF;
	text-decoration: none;
}

/*
 * The theme's global .elementor-button rule paints a rainbow gradient border
 * through ::after (CLAUDE.md §6). Suppress it here so the flat pink outline
 * is what shows.
 */
.animart-viz-button .elementor-button::before,
.animart-viz-button .elementor-button::after {
	display: none;
}

.animart-viz-button svg {
	display: block;
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
}

/* Below the tablet breakpoint, keep any icon and drop the wording. */
@media (max-width: 1100px) {
	.animart-viz-button,
	.animart-viz-button .elementor-button,
	.animart-viz-button a {
		padding: 8px 10px;
		gap: 0;
	}

	.animart-viz-button .elementor-button-text {
		display: none;
	}
}

/*
 * The label keeps its own capitals.
 *
 * Every button this plugin puts on a theme page wears the theme's
 * `.elementor-button` class so it matches the buttons beside it, and the
 * site's global snippet (custom-css-js post 9880) styles that class with
 * `text-transform: uppercase !important`. On a label that is already all
 * capitals that does nothing; on this one it is wrong whenever `button_label`
 * carries the brand — it was "apticon® VISUAL LAB" until 2026-09-30 and is
 * "VISUAL LAB" now — because the brand is lowercase (§6). Uppercasing it
 * prints APTICON®.
 *
 * The capitals that belong in the label are typed into the setting, so there
 * is nothing here to add — this only has to stop 9880 taking the brand with
 * it. `none` and not `lowercase`: the rest of the label is capitals in the
 * string and has to stay that way.
 *
 * WEIGHT. 9880's `.elementor-button` is (0,1,0) and `!important`, and this
 * stylesheet is enqueued in the head while 9880 prints after it — source
 * order is against us, so specificity and `!important` have to carry it
 * alone. The two buttons need different selectors because they are built
 * differently:
 *
 *   - `animart_viz_get_button()` wraps the label in a span of its own, and
 *     9880 never matches that span; it reaches it by inheritance from the
 *     anchor. A declaration on the element beats an inherited value whatever
 *     its weight, so the span is the cheap place to do this. The descendant
 *     form is (0,2,0) regardless, which stays a class clear of anything that
 *     starts matching `.elementor-button-text` directly later. The bare class
 *     is listed beside it because `$args['class']` on the anchor is the
 *     caller's and need not contain `.elementor-button` at all.
 *
 *   - The lightbox button has no such span: the script writes the label onto
 *     the anchor as a bare text node, so 9880 matches it directly and
 *     inheritance never comes into it. Our class plus the theme's own is
 *     (0,2,0), one class ahead of 9880.
 *
 * The theme's sibling ADD TO MOODBOARD button is deliberately not in this
 * selector. It is the theme's, its label has no brand in it, and it stays
 * uppercase — the same reason its orange fill is left alone (§7).
 *
 * Both selectors are plugin-owned classes, so although this file loads on
 * every front-end page, nothing outside our own buttons can be reached.
 */
.elementor-button .animart-viz-button-label,
.animart-viz-button-label,
.animart-viz-lightbox-btn.elementor-button {
	text-transform: none !important;
}

/*
 * The brand sets solid; the rest of the label keeps the button's tracking.
 *
 * 9880's `.elementor-button` also carries `letter-spacing: 0.28em !important`,
 * which is the site's button tracking and is meant to stay. It is wrong on
 * one word only: "apticon®" is a wordmark and has to set solid, the same
 * reason it stays lowercase two rules up.
 *
 * `animart_viz_get_button()` wraps whatever leading brand token the label has
 * in this span, so the scope is exactly one word and the tracking of
 * "VISUAL LAB" — and of the space between them, which stays outside the span
 * — is left to 9880. A label with no brand in it never gets the span, and
 * this rule then matches nothing.
 *
 * WEIGHT. As with the transform above, 9880 reaches this span by inheritance
 * from the anchor rather than matching it, so a declaration here wins on the
 * cascade whatever its specificity. `!important` is on it anyway: the plugin's
 * own 440px rule below sets `letter-spacing` on the lightbox anchors with
 * `!important`, and that inherits down here too — this has to sit above
 * anything the anchor is given, now or later.
 */
.animart-viz-button-brand {
	letter-spacing: 0 !important;
}

/*
 * The header button keeps the text the editor typed.
 *
 * This is the one rule in this file that styles something the plugin does not
 * emit, so it is worth saying why it is here. The header button is a
 * hand-placed Elementor widget in the "Apticon" header template — the plugin
 * used to inject it and deliberately stopped (§7) — and `topbutton` is the
 * class the editor put in its CSS Classes field. 9880 already keys on that
 * class for the font size, so it is an established hook, not one invented here.
 *
 * There is nowhere better to put it: 9880 is the client's, §8 forbids editing
 * the theme, and a second custom-css-js post correcting the first is worse than
 * one selector in a stylesheet that already loads on every page.
 *
 * WHAT IT FIXES. The widget's text field holds `apticon®<br>VISUAL LAB`.
 * 9880's uppercase transform does nothing to VISUAL LAB, which is already
 * capitals, and is wrong on the brand, which prints APTICON®. Switching the
 * transform off leaves exactly what the editor typed, which is the whole point:
 * the capitals belong in the field, not in CSS (§6, §7).
 *
 * It is switched off on the text span rather than the anchor for the reason the
 * rules above give — 9880 matches the anchor and reaches the span only by
 * inheritance, which a declaration on the span outranks. The selector is the
 * one 9880 itself uses for this button, a class clear of `.elementor-button`.
 *
 * ONLY THE CASING. The button's tracking still comes from 9880, so "apticon®"
 * is still set at 0.28em here. Setting it solid needs a span around the brand,
 * which means editing the widget's text field to
 * `<span class="animart-viz-button-brand">apticon®</span><br>VISUAL LAB`; the
 * rule above is site-wide and would pick it up with no further change.
 */
.topbutton .elementor-button-text {
	text-transform: none !important;
}

/*
 * Lightbox action row.
 *
 * The script moves the theme's "Add to Moodboard" anchor and ours into a
 * wrapper it creates, and lays that wrapper out inline. Styling the theme's
 * own overlay was tried first and did not hold — even with the container
 * laid out and both anchors pinned, the anchors kept taking a line each.
 * Owning the wrapper removes the site's CSS from the question entirely.
 *
 * The script sets only the structural declarations inline — display, width,
 * position. Arrangement is set here instead, because it changes at 440px and
 * a media query cannot override an inline style. The anchors are the opposite
 * case: their inline styles are load-bearing (see pinFlexItem) and must stay.
 */
.animart-viz-lightbox-actions {
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	align-items: center;
	justify-content: center;
	gap: 10px;
	width: max-content;
	max-width: none;
	margin-left: auto;
	margin-right: auto;
	white-space: nowrap;
}

.animart-viz-lightbox-actions > a {
	flex: 0 0 auto;
	width: auto;
	max-width: none;
}

/*
 * Desktop and tablet font size.
 *
 * This was an inline style until the mobile treatment below needed to raise
 * it: the script measured the theme's button and applied `size - 2` to both
 * inline with `!important`, which no stylesheet can outrank. 12px is that same
 * value made static — the theme's button is 14px from 9880's
 * `font-size: 14px !important`, and nothing else sets it above 440px — so
 * appearance here is unchanged.
 *
 * The selector is explained at the media query; it is the same one, and it
 * needs the same weight to beat 9880.
 */
.animart-viz-lightbox-actions .animart-viz-lightbox-item.elementor-button.elementor-size-sm {
	font-size: 12px !important;
}

/*
 * Phones: a full-width touch target, deliberately NOT the theme's.
 *
 * 440px is still the theme's own breakpoint — the one the Categories CSS
 * (custom-css-js post 10633) uses to shrink its button to a 20px-tall, 10px
 * strip. Earlier this file reproduced those dimensions so the pair matched.
 * That is reversed: 10633's mobile sizing is what made these unusable, so the
 * lightbox now overrides it on both buttons and sizes them for a thumb.
 *
 * Both anchors are targeted together, which is what `animart-viz-lightbox-item`
 * exists for — the script adds it to the theme's anchor as well as ours, since
 * no selector otherwise reaches both. Everything below applies to the pair, so
 * they cannot drift apart.
 *
 *   WEIGHT. Our stylesheet is enqueued in the head and 10633 prints after it,
 *   so source order is against us and every contested property has to win on
 *   specificity alone. 10633 uses
 *   `.elementor-button.elementor-size-sm.addtomoodboard` — three classes,
 *   (0,3,0), all !important. The selector here is our wrapper, our marker and
 *   the two theme classes 10633 itself keys on: four classes, (0,4,0). It wins
 *   by exactly one class, and only where 10633 could apply at all.
 *
 * Property by property, what each declaration is beating:
 *
 *   width           inline `width: auto` from pinFlexItem (not important).
 *                   80vw on both is what makes them equal, and it is set
 *                   rather than left to `stretch` so equality does not depend
 *                   on the wrapper's width resolving first.
 *   height          10633's `height: 20px !important`. 46px sits in the
 *                   44-48px touch range.
 *   padding         10633's four longhands !important, and the theme's inline
 *                   `padding: 10px 20px` copied onto our button. Zero vertical
 *                   padding is correct here because the height is explicit and
 *                   the text is centred by flex, not by padding.
 *   font-size       9880's `font-size: 14px !important` and 10633's 10px. The
 *                   12px rule above is overridden here too.
 *   letter-spacing  10633's 0.1em. 0.28em is the desktop value from 9880, kept
 *                   so the phone treatment reads as the same button.
 *   box-sizing      Not contested; declared so 80vw stays 80vw whatever the
 *                   inherited box model, since padding is non-zero.
 *
 * Text centring needs nothing new: pinFlexItem already sets `align-items` and
 * `justify-content` to center inline, and a flex item's `inline-flex` is
 * blockified to `flex`, so both axes are already centred inside the 46px box.
 *
 * The stack is centred by the wrapper — `width: 80vw` with `margin: 0 auto`,
 * inside an overlay that relaxOverlay lets size to its content and the theme
 * centres with translateX(-50%).
 */
@media (max-width: 440px) {
	.animart-viz-lightbox-actions {
		flex-direction: column;
		align-items: center;
		gap: 12px;
		width: 80vw;
	}

	.animart-viz-lightbox-actions .animart-viz-lightbox-item.elementor-button.elementor-size-sm {
		box-sizing: border-box !important;
		width: 80vw !important;
		max-width: none !important;
		height: 46px !important;
		padding: 0 12px !important;
		font-size: 14px !important;
		line-height: 1 !important;
		letter-spacing: 0.28em !important;
	}
}

/*
 * The button beside the categories search bar.
 *
 * `.search-container` is a flex row with `justify-content: flex-end`, and
 * `.search-box` already carries a 30px right margin — so the gap is the
 * theme's, not ours. Only the cross-axis alignment needs setting, and it is
 * set on our own element rather than on the theme's container, so nothing
 * else in that row changes behaviour.
 */
.animart-viz-search-button {
	align-self: center;
	flex: 0 0 auto;
}

/*
 * That row, stacked on phones: field at 80% centred, button the same width
 * directly below it, and the category headings centred to match.
 *
 * BREAKPOINT. 768px is the Categories page's own — post 10633 uses it four
 * times and CLAUDE.md §6 names it as the site's mobile breakpoint. The 440px
 * one used for the lightbox buttons belongs to a single rule about the
 * moodboard button and is not a general mobile boundary. The 80%-and-centred
 * treatment is also this page's existing idiom: 10633 already does exactly
 * this for `.modalinput, .elementor2-button` under 650px.
 *
 * SCOPE. This stylesheet is enqueued site-wide, and neither class is unique:
 * `.search-container` also appears in inspirations.php and categoriesdev.php,
 * `.categories-title` in six templates. A bare rule would restyle all of them.
 * Our button exists in exactly one of those rows, so its presence is the
 * scope — `:has()` reads as "the row that is ours", needs no page id, and
 * survives the page being rebuilt. A page-id-10619 selector would be shorter
 * and would rot the first time that page is recreated.
 *
 * If :has() is unsupported the whole block simply does not apply and the row
 * stays as it is today, which is a degraded layout rather than a broken one.
 *
 * WEIGHT. Our stylesheet is enqueued in the head and 10633 prints after it,
 * so specificity has to carry every override on its own. `:has()` takes the
 * specificity of its argument, so each selector below lands at two or three
 * classes against 10633's one.
 */
@media (max-width: 768px) {
	.search-container:has( .animart-viz-search-button ) {
		flex-direction: column;
		align-items: center;
		justify-content: flex-start;
	}

	/* 10633 sets `margin-right: 30px` for the desktop row; it would sit the
	   centred field 30px off-centre. */
	.search-container:has( .animart-viz-search-button ) .search-box {
		width: 80%;
		margin-right: 0;
	}

	/* The magnifier is absolutely positioned at the box's right edge, so the
	   padding keeps typed text from running under it at this width. */
	.search-container:has( .animart-viz-search-button ) .search-box input {
		width: 100%;
		box-sizing: border-box;
		padding-right: 36px;
	}

	.animart-viz-search-button {
		width: 80%;
		margin-top: 14px;
	}

	.animart-viz-search-button .elementor-button {
		width: 100%;
		box-sizing: border-box;
		text-align: center;
	}

	/*
	 * The suggestions list, which categories.php inserts with
	 * `$('.search-box').after(dropdown)` — so it is already a flex child
	 * between the field and our button.
	 *
	 * It is absolutely positioned at `top: 60px; right: 40px; width: 235px`,
	 * measured for the single-line desktop row. Stacking the row makes that
	 * land on top of the button. Returning it to the flow is the fix rather
	 * than a new magic offset: it then sits under the field because that is
	 * where the markup already puts it. The height cap is because it has none
	 * of its own and nothing above it constrains the list.
	 */
	.search-container:has( .animart-viz-search-button ) .search-results-dropdown {
		position: static;
		width: 80%;
		right: auto;
		top: auto;
		margin: 6px auto 0;
		max-height: 50vh;
	}

	/*
	 * Headings. 10633 gives these `text-align: left` and `padding-left: 40px`;
	 * both have to go or "centred" is centred within a 40px-indented box.
	 */
	body:has( .animart-viz-search-button ) .categories-title {
		text-align: center;
		padding-left: 0;
	}
}
