/**
 * The quiet text treatment, and archive card layout.
 *
 * WHY CSS AND NOT SVG
 *
 * The settings chosen for these strings have `stroke-width: 0` and motion off. With no
 * gradient stroke and no animation, nothing here needs SVG — and that matters, because
 * SVG <text> does not wrap. The sizing notice is a full sentence; as SVG it would be one
 * unbroken line running off the page. In CSS it wraps, stays selectable, stays
 * searchable, and costs no JavaScript.
 *
 * Mapping from the SVG settings:
 *   feGaussianBlur stdDeviation 1   ->  2px text-shadow blur (CSS radius = 2 sigma)
 *   feGaussianBlur stdDeviation 2.5 ->  5px, by the same mapping
 * Tight layer first so it paints nearest the glyph, matching the SVG paint order.
 *
 * THE LOCAL TOKEN IS GONE. This file used to carry `--aethyrdancer-quiet-fx` — a hard
 * white core over a magenta 5px/5px drop shadow — which was the treatment settled before
 * the quiet pair existed. It had exactly one consumer, the rule below, and that rule now
 * wears the same violet glow as every other quiet surface on the site, so there was
 * nothing left for a second token to define. `--ad-glow` in tokens.css is the one
 * definition; the derivation note lives there.
 */

/*
 * TRACKING IS PER-ROLE, NOT ONE NUMBER.
 *
 * This block used a flat `letter-spacing: 9.5px`, taken from the lettering variants'
 * `tracking` value. That transplant was the bug: in the SVG, 9.5 is a viewBox unit
 * against a 22–97px glyph, so it reads as roughly 0.28–0.43em. Dropped into CSS at 20px
 * it became 0.48em — nearly half an em on running text — and the file's own note that
 * "words break awkwardly at narrow widths" was the symptom rather than a quirk to work
 * around.
 *
 * The lettering system already has the right precedent for small text: the `card` variant
 * is size 20, tracking 2, which is 0.1em. That is what short labels take here. Sentences
 * take less again, because tracking is a device for labels and a tax on reading.
 */
/*
 * TWO OF THESE HAVE GRADUATED TO THE REAL TREATMENT.
 *
 * The result count and the sizing notice now render as SVG lettering (the `ui` variant),
 * so what this rule gives them is the wrapper's font metrics and nothing that shows. The
 * selectors stay because the layout properties below still apply to the block, and because
 * dropping them would silently change the fallback when `aethyrdancer_lettering()` returns
 * plain text — which it does on any surface that opts out.
 *
 * The `text-shadow` here used to reach the SVG glyphs and paint a second, violet shadow
 * over the lettering's own. lettering.css now refuses all inherited text-shadow; see the
 * note there before adding a treatment that is meant to reach inside the lettering.
 */
/*
 * AMARANTE AT 16, NOT ALMENDRA DISPLAY AT 20 (operator, 2026-09-15).
 *
 * Almendra Display is a display face, and typeface.css says so at the top of the file:
 * one weight, ornate capitals, drawn for headings. At 20px over the artwork grounds these
 * blocks were the hardest text on the page to read — the short description worst, because
 * it is the only one of these five selectors that is a real paragraph rather than a label.
 * Amarante is the face the quiet pair already uses for exactly this role, so this stops
 * being an exception and becomes the rest of the system.
 *
 * TRACKING IS UNCHANGED AND THAT IS THE POINT. 0.1em was picked as the `card` variant's
 * 2-at-20; at 16px the same ratio is 1.6px, which lands on the `meta` variant's locked 1.5
 * rather than drifting away from it. Dropping the size did not cost the setting its
 * derivation.
 *
 * THE PAINT IS THE `meta` LETTERING'S WHOLE STACK, NOT JUST ITS GLOW (2026-09-17).
 *
 * The first version of this rule used `--ad-glow` over `--ad-text-strong`. The computed
 * style was correct and the glow still did not show: an opaque fill covers the violet,
 * and what is left is a 5px halo that disappears on a near-black ground. The category
 * line in the product meta looks the way it does because of the white fill at 72%, which
 * lets the glow show through the letters, and the black drop shadow under it. The
 * operator singled out that drop shadow as good for legibility. `--ad-quiet-fill` and
 * `--ad-quiet-fx` in tokens.css carry all four layers. See the note there.
 */
.woocommerce-result-count,
.woocommerce-product-details__short-description,
.woocommerce-product-details__short-description p,
.aethyrdancer-sizing-notice,
.aethyrdancer-sizing-notice p {
	font-family: 'Amarante', serif;
	font-size: 16px;
	letter-spacing: 0.1em;
	color: var(--ad-quiet-fill);
	text-shadow: var(--ad-quiet-fx);
}

/* Running text: enough to echo the treatment, not enough to slow it down. */
.woocommerce-product-details__short-description,
.woocommerce-product-details__short-description p,
.aethyrdancer-sizing-notice,
.aethyrdancer-sizing-notice p {
	letter-spacing: 0.04em;
}

.woocommerce-result-count,
.woocommerce-product-details__short-description,
.aethyrdancer-sizing-notice {
	overflow-wrap: break-word;
	line-height: 1.6; /* the default leading collides once the glow is on */
}

/* ---------------------------------------------------------------
 * Dropdowns
 * --------------------------------------------------------------- */

/*
 * ONE DEFINITION, EVERY NATIVE SELECT. THERE WAS NOT ONE BEFORE.
 *
 * The dropdowns were dressed by two files at once. `.woocommerce-ordering select` sat in
 * the quiet group above, while `.woocommerce-ordering .orderby` in lettering.css set
 * the face, size, tracking and fill at (0,2,0) against this file's (0,1,1). Specificity
 * beats load order, so lettering.css won everything except `text-shadow` — and the
 * control ended up wearing a shadow stack built for an opaque fill underneath a 72%
 * translucent one. That mismatch was the washed-out look. This block is the single owner
 * now; lettering.css keeps the reasoning and no declarations.
 *
 * THE TWO DROPDOWNS ARE NOT THE SAME CONTROL, so they do not get the same paint.
 *
 * Sorting is chrome: it sits beside the result count, it is the last thing on an archive
 * anyone needs to read, and the archive hides it entirely below five products. It takes
 * the fill and nothing else.
 *
 * The variation select is the size picker. It is the highest-stakes string on a product
 * page — a misread size is a return — and it sits inside the buying form next to the
 * quantity stepper. It gets the glow, and a ground of its own so it reads as a control
 * rather than as text floating on the page.
 */
:root {
	--aethyrdancer-dropdown-fill: rgb(255 255 255 / 72%);

	/*
	 * The quiet pair's glow, translated. The `ui` and `meta` variants in lettering.php
	 * carry #683ffd at stdDeviation 1 / 0.3 and 2.5 / 0.75; this file's mapping at the top
	 * (CSS radius = 2 sigma) makes those 2px and 5px. Tight layer first so it paints
	 * nearest the glyph, matching the SVG paint order.
	 *
	 * THE VALUES MOVED TO tokens.css AND THE NAME STAYED. The same stack now dresses the
	 * notices, the cart tables and every field (assets/css/surfaces.css), so one file has
	 * to own it — and that is the file that owns colour. This alias keeps the derivation
	 * recorded next to the mapping that produced it.
	 */
	--aethyrdancer-dropdown-fx: var(--ad-glow);
}

/*
 * THE CLOSED CONTROL — the only part of a native select that CSS reliably paints.
 *
 * Amarante at 20/1.5 is the quiet pair's setting, so these read as the same family as the
 * result count beside them without pretending to be the SVG treatment.
 */
.woocommerce-ordering .orderby,
.single-product form.cart .variations select {
	font-family: 'Amarante', serif;
	font-size: 20px;
	letter-spacing: 1.5px;
	color: var(--aethyrdancer-dropdown-fill);
}

/*
 * The size picker only. Ground, border and radius are lifted from the quantity input in
 * add-to-cart.css deliberately: the two sit side by side in the same form, and a select
 * that does not match the stepper beside it reads as a different kind of thing.
 */
.single-product form.cart .variations select {
	background-color: var(--ad-surface);
	border: 1px solid var(--ad-border);
	border-radius: 2px;

	/* Same clipping as the sort control: Astra sizes for a smaller face than 20px. */
	height: auto;
	padding: 0.4em 0.5em;
	line-height: 1.5;
	text-shadow: var(--aethyrdancer-dropdown-fx);
}

/*
 * THE OPEN LIST TAKES NEITHER THE GLOW NOR THE TRANSLUCENT FILL.
 *
 * Option rows are drawn by the browser's own popup, and `text-shadow` never paints there
 * on any platform — so the glow that carries the closed control simply is not available
 * to them. A fill at 72% was set to sit under that glow; without it, on the dark popup
 * `color-scheme: dark` in tokens.css now produces, it is just weaker text. The rows get
 * an opaque fill and an explicit ground instead. This is where the treatment stops.
 *
 * The face may or may not survive here (Windows and Linux honour it, macOS draws its own
 * list); the colours are what matter and those hold everywhere.
 */
.woocommerce-ordering .orderby option,
.single-product form.cart .variations select option {
	background-color: var(--ad-ground-200);
	color: var(--ad-text-strong);
	text-shadow: none;
}

.woocommerce-ordering select {
	max-width: 100%;
	/* Astra sizes the control for its own smaller face; at 20px the descenders clip. */
	height: auto;
	padding-top: 0.4em;
	padding-bottom: 0.4em;
	line-height: 1.5;
}

/* ---------------------------------------------------------------
 * Archive card
 * --------------------------------------------------------------- */

/*
 * Price up, and deliberately untreated — it must stay unambiguous.
 *
 * Needs the `.woocommerce` prefix and the Astra wrapper to outrank the parent theme's own
 * archive-price rule; without them this silently lost the cascade and stayed at 14.4px.
 */
.woocommerce ul.products li.product .astra-shop-summary-wrap .price,
.woocommerce ul.products li.product .astra-shop-summary-wrap .price .woocommerce-Price-amount {
	font-size: 22px;
	text-shadow: none;
	letter-spacing: normal;
}

/*
 * Title overlaid on the top of the thumbnail.
 *
 * Positioned rather than re-hooked: Astra builds the card from its own structure array,
 * and lifting the title out of that would mean re-implementing the card. Absolute
 * positioning takes it out of flow, so the summary block below closes up on its own with
 * no leftover gap.
 */
ul.products li.product {
	position: relative;
}

/*
 * Title sits at the FOOT of the picture, its baseline just above the frame's bottom
 * border.
 *
 * The offset is a percentage padding, because percentage padding resolves against the
 * containing block's WIDTH — and the thumbnail's height is a fixed 133.33% of its width.
 * A top offset in percent would resolve against height and be circular; a pixel offset
 * would break the moment the grid changes column count. This tracks the card at every
 * breakpoint with no JavaScript.
 */
/*
 * The `.woocommerce` prefix and the anchor class are load-bearing: Astra zeroes the loop
 * title's padding with a rule that outranks a bare three-class selector, and without them
 * this silently computed to 0 and the title stayed at the top of the picture.
 */
.woocommerce ul.products li.product .ast-loop-product__link .woocommerce-loop-product__title,
ul.products li.product .woocommerce-loop-product__title {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	z-index: 2;
	margin: 0;
	padding: calc(133.333% - 3.1rem) 0.9rem 0;
	pointer-events: none; /* the whole card is already a link; do not eat the click */
	text-align: center;
}

ul.products li.product .woocommerce-loop-product__title .aethyrdancer-lettering {
	display: block;
}

/*
 * The card art is dark at the top on some pieces and bright on others, so the title gets
 * a short scrim of its own. Local, feathered, and it covers roughly the top fifth of the
 * card rather than washing the whole image — the same argument as the hero scrim.
 */
ul.products li.product .astra-shop-thumbnail-wrap {
	position: relative;
}

/* The scrim follows the title to the bottom of the frame. */
ul.products li.product .astra-shop-thumbnail-wrap::before {
	content: '';
	position: absolute;
	bottom: 0;
	left: 0;
	right: 0;
	height: 30%;
	z-index: 1;
	pointer-events: none;
	border-radius: 0 0 7px 7px;
	background: linear-gradient(0deg, rgb(3 3 8 / 72%) 0%, rgb(3 3 8 / 0%) 100%);
}

/*
 * Price pulled up so its top edge just clears the frame's drop shadow, which is
 * 0 8px 22px — so roughly 8px of offset before the blur fades out.
 */
.woocommerce ul.products li.product .astra-shop-summary-wrap {
	margin-top: 0;
	padding-top: 0;
}

.woocommerce ul.products li.product .astra-shop-summary-wrap .price {
	display: block;
	margin-top: -19px;
}

/* -------------------------------------------------------------------------
 * Shop archive heading
 *
 * The heading text is swapped in inc/shop-chrome.php; this hides it visually while
 * leaving it in the document.
 *
 * IT USES THE screen-reader-text RECIPE, NOT `opacity: 0`, AND THE DIFFERENCE MATTERS.
 *
 * Google's spam policies name `opacity: 0` explicitly as an example of hidden text,
 * alongside white-on-white and off-screen positioning. Absolute/1px/clipped is the
 * pattern WordPress itself ships, the one assistive technology expects, and the one
 * already in this theme — the lettering system emits a `.screen-reader-text` span beside
 * every SVG. It also does not leave an invisible box sitting in the layout, which
 * `opacity: 0` does.
 *
 * What actually keeps this on the right side of the line is not the technique but the
 * text: the heading has to describe what is on the page. Hidden or visible, a heading
 * chosen to rank rather than to describe is precisely the case the policy is aimed at —
 * so if the wording ever stops matching the catalogue, this rule is the thing to delete.
 * ---------------------------------------------------------------------- */

.woocommerce-shop .woocommerce-products-header__title {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* -------------------------------------------------------------------------
 * Phones: one product across, not two.
 *
 * THE FLOOR WAS ALREADY WRITTEN DOWN, IN collections-index.css, AND IT IS 220px:
 * "what keeps a 3:4 card legible — below it the cutout stops reading as a garment". A
 * collection tile IS this card, so the same number applies here, and Astra's two columns
 * at 375px give it 158.
 *
 * The cost is not only the artwork. The title is lettering, and lettering holds its
 * measured size until the container forces it down — so at 158px a name like "Blessed of
 * Chaos Combat Boots" rendered in a box 131 by 14, about seven pixels of cap height, while
 * the same card on a desktop archive renders it at nearly four times that. It was the
 * smallest type on the site and it was on the one element a shopper has to read to know
 * what they are looking at.
 *
 * 520px is where two columns stop clearing the floor: 2 x 220 plus Astra's 20px gutter and
 * the container's own padding lands just under it. Above that the two-column grid is
 * unchanged.
 *
 * The page gets longer, which is the honest trade and the same one the collections index
 * already makes at this width. A phone showing one garment at a time is also the most
 * product-focal arrangement there is, which is what docs/design-direction.md asks for.
 * ---------------------------------------------------------------------- */

/*
 * THE SELECTOR IS LONG BECAUSE ASTRA'S IS.
 *
 * Astra prints its column counts as inline CSS in the head under
 * `.ast-container .woocommerce ul.products:not(.elementor-grid)` — four classes and an
 * element. A tidy `.woocommerce ul.products` here is three and loses, silently: the rule
 * applies, the cascade discards it, and the grid stays at two columns with nothing to say
 * why. The body class buys the specificity rather than `!important`, which would also have
 * to be answered by anything that legitimately wants a different count later.
 */
@media (max-width: 520px) {
	body.woocommerce .ast-container ul.products:not(.elementor-grid),
	body.woocommerce-page .ast-container ul.products:not(.elementor-grid) {
		grid-template-columns: minmax(0, 1fr);
	}

	/*
	 * A cap, so the card does not become a full-bleed poster on a large phone. 24rem is
	 * about 350px, which is a 375px viewport less its gutters — so on the narrowest common
	 * screen this changes nothing, and on a 430px one the card stops growing rather than
	 * pushing its own title past the size the rest of the archive uses.
	 */
	body.woocommerce .ast-container ul.products li.product,
	body.woocommerce-page .ast-container ul.products li.product {
		max-width: 24rem;
		margin-left: auto;
		margin-right: auto;
		width: 100%;
	}
}

/* =========================================================================
 * THE LEGIBILITY PASS (operator, 2026-09-17)
 *
 * The quiet treatment was on four selectors and visibly on one, the short description.
 * This extends it to the rest of the running text and headings the operator named, after
 * an audit of every text element on the front page, the shop archive, a product page and
 * an information page.
 *
 * DELIBERATELY NOT INCLUDED, each for its own reason:
 *   breadcrumbs, and the footer          - the operator excluded both
 *   prices                               - standing decision, see --ad-glow in tokens.css
 *   cart and checkout                    - the no-effects rule; surfaces.css sets none
 *   native <option> and select2 rows      - text-shadow never paints in a browser popup
 *   size-guide data cells (td)           - the operator named row and column headers only,
 *                                          and a glow behind every number is noise
 *   related-product card titles          - these want the `card` LETTERING, not this, so
 *                                          they are a separate change
 *
 * THE FILL TRAVELS WITH THE SHADOWS, except on the size-guide headers. See the note on
 * `--ad-quiet-fill` in tokens.css for why the translucent fill is what makes the glow
 * visible at all, and the header rule below for why that one place keeps opaque text.
 *
 * `body` LEADS SEVERAL OF THESE because Astra styles the same elements from its own
 * stylesheet at a comparable weight, and this file loads before surfaces.css rather than
 * last. Where a rule already lives in surfaces.css (the tabs, the delivery estimate) the
 * declaration was added there instead of being restated here.
 * ---------------------------------------------------------------------- */

/* Shop archive: the page title, at the large displacement. */
body .woocommerce-products-header__title {
	color: var(--ad-quiet-fill);
	text-shadow: var(--ad-quiet-fx-lg);
}

/*
 * Shop archive: the agentic-discovery block. Intro, the group toggles, their headings and
 * their copy. The product links inside it are left to the link colour and take the
 * treatment by inheritance from the list item, so a hover still changes only colour.
 */
body .aethyrdancer-discovery {
	color: var(--ad-quiet-fill);
	text-shadow: var(--ad-quiet-fx);
}

body .aethyrdancer-discovery :is(p, li, summary) {
	color: inherit;
	text-shadow: inherit;
}

body .aethyrdancer-discovery h3 {
	color: var(--ad-quiet-fill);
	text-shadow: var(--ad-quiet-fx);
}

/* Collection archive: the term description under the lettered collection name. */
body .aethyrdancer-collection-head__lede,
body .aethyrdancer-collection-head__lede p {
	color: var(--ad-quiet-fill);
	text-shadow: var(--ad-quiet-fx);
}

/*
 * Front page: the descriptor line under the lockup - the landing page's tertiary hero.
 *
 * NOT HERE. discovery.css owns it, sets `color` on it at two classes, and is enqueued after
 * this file, so a rule here could not win the fill however it was written. It also wants a
 * thinner fill and a softer, half-strength drop than the shared tokens carry. Both live in
 * discovery.css next to the element's own layout; see the note there.
 */

/* Product page: the "Related products" and "You may also like" headings. */
.woocommerce div.product .related > h2,
.woocommerce div.product .up-sells > h2 {
	color: var(--ad-quiet-fill);
	text-shadow: var(--ad-quiet-fx-lg);
}

/* Product page: the long description, in the Description tab panel. */
body.aethyrdancer-typeface .woocommerce-Tabs-panel--description,
body.aethyrdancer-typeface .woocommerce-Tabs-panel--description :is(p, li, h2, h3, h4) {
	color: var(--ad-quiet-fill);
	text-shadow: var(--ad-quiet-fx);
}

/*
 * Product page: the size-guide toggle, and the chart's headers.
 *
 * THE HEADERS KEEP OPAQUE TEXT, and that is the one exception in this pass. CLAUDE.md
 * names the size chart as the copy that prevents returns, and the translucent fill buys
 * the glow's visibility with contrast. At 12.8px in a table that trade is the wrong way
 * round, so the headers take the small displacement and the full-strength fill. The
 * operator asked for more tracking here too, which is what separates a header row from
 * the numbers under it once both are the same weight - this face has no bold.
 */
body .aethyrdancer-size-guide > summary {
	color: var(--ad-quiet-fill);
	text-shadow: var(--ad-quiet-fx);
}

body .aethyrdancer-size-guide th {
	color: var(--ad-text-strong);
	text-shadow: var(--ad-quiet-fx-sm);
	letter-spacing: 0.08em;
}

/*
 * Product page: the "Size" label above the picker, at 24px.
 *
 * It was 14px - smaller than the body copy - while labelling the highest-stakes control
 * on the page. The size it now takes is the operator's.
 *
 * `.single-product` IS COMPOUNDED ONTO `body`, NOT A DESCENDANT OF IT. It is a body class,
 * so `body.aethyrdancer-typeface .single-product` asks for a second element inside the body
 * carrying it, and matches nothing. Verified against the live DOM rather than assumed.
 */
body.aethyrdancer-typeface.single-product form.cart .variations label {
	font-size: 24px;
	color: var(--ad-quiet-fill);
	text-shadow: var(--ad-quiet-fx);
}
