/*
 * Styling that knows what a fragrance is.
 *
 * Everything in oview-bricks is deliberately ignorant of any dataset: cards.css
 * has a `.oview-card__marker` slot and no idea that this one holds three values
 * or what they are called. That knowledge belongs here, with the plugin that
 * declares the column, for the same reason the filter spec does.
 *
 * The test for whether a rule belongs in this file: does it name a value from
 * this dataset? `[data-marker="unisex"]` does. Move it here.
 */

/* --- the card's gender wash ---------------------------------------------- */

/*
 * A glow rising from the bottom edge, brightest under the middle of the card.
 *
 * ⚠️ Radial, not linear, and that is the whole difference. A linear gradient
 * lays the same amount of colour in the bottom corners as under the centre, so
 * it reads as a painted band with a hard left and right edge. A radial one
 * anchored to the bottom edge falls off in every direction at once, which is
 * what makes it look like light instead of paint.
 *
 * `130% 34% at 50% 100%` - wider than the card, so the falloff happens outside
 * the corners rather than inside them; a third of its height; centred on the
 * bottom edge.
 *
 * ⚠️ The height is deliberately close to the 10% the linear version had been
 * tuned down to. Changing the SHAPE is not a licence to put the intensity back:
 * a radial reaching 55% up the card was more colour than the linear band it
 * replaced, which was the thing that had already been rejected twice.
 *
 * A background-image on the card rather than a pseudo-element, so it layers
 * over the card's own background-color and under every child without touching
 * the stacking context, which already holds the stretched title link.
 *
 * It is never the only signal: the icon beside the year carries a shape and
 * that icon's text carries the word. Colour alone would fail WCAG 1.4.1 and is
 * invisible to roughly one man in twelve.
 *
 * Each rule also sets --card-accent, the hairline cards.css draws along the
 * bottom edge. Same value as the hover border, so a card states its gender in
 * one colour three ways - the glow, the line and the mark - and adds no token
 * to do it.
 */
.oview-card[data-marker="female"] {
	background-image: radial-gradient(130% 34% at 50% 100%, var(--color-gender-female), transparent 70%);
	--card-accent: var(--color-gender-female-ink);
}

.oview-card[data-marker="male"] {
	background-image: radial-gradient(130% 34% at 50% 100%, var(--color-gender-male), transparent 70%);
	--card-accent: var(--color-gender-male-ink);
}

.oview-card[data-marker="unisex"] {
	background-image: radial-gradient(130% 34% at 50% 100%, var(--color-gender-unisex), transparent 70%);
	--card-accent: var(--color-gender-unisex-ink);
}

/*
 * And the hover border picks up the same value.
 *
 * No new tokens: it is the -ink already used for this value's checkbox and its
 * icon, so a hovered card, its own mark and its row in the facet are visibly
 * one thing. A card with no gender keeps --color-border-strong from cards.css,
 * which is what these override.
 *
 * A border is a non-text UI component under WCAG 1.4.11 and all three inks
 * clear its 3:1 - the weakest is unisex at 3.43:1 on white.
 */
.oview-card[data-marker="female"]:hover,
.oview-card[data-marker="female"]:focus-within {
	border-color: var(--color-gender-female-ink);
}

.oview-card[data-marker="male"]:hover,
.oview-card[data-marker="male"]:focus-within {
	border-color: var(--color-gender-male-ink);
}

.oview-card[data-marker="unisex"]:hover,
.oview-card[data-marker="unisex"]:focus-within {
	border-color: var(--color-gender-unisex-ink);
}

/*
 * ⚠️ No wash in the list view.
 *
 * The gradient is tuned to a 167px card: 34% of its height, fading out to the
 * corners. Stretched across a 900px row the same rule paints a pink band under
 * every line of the list, which is a different thing entirely - it stopped
 * being a hint the moment the box changed shape.
 *
 * The row keeps the colour: cards.css turns the accent hairline into a bar
 * down the leading edge, and the mark beside the year is unchanged.
 *
 * The selector needs `[data-marker]` to outweigh the three rules above. A rule
 * in cards.css could not do this at all - it loads first, and at equal
 * specificity the later file wins.
 */
.ov-view-list .oview-card[data-marker] {
	background-image: none;
}

/* --- the card's gender icon ---------------------------------------------- */

/*
 * The icon BOX, not just the icon.
 *
 * ⚠️ These four properties were in cards.css, on `.oview-card__marker` itself,
 * where they silently declared that every dataset's marker is an icon. They
 * are not: they are the shape a gender mark takes, and `text-indent` is what
 * hides the word "female" once the icon is drawn over it. Keyed on the three
 * values so a marker holding a note group or an accord family is unaffected.
 *
 * The test from the top of this file applies exactly: does the rule name a
 * value from this dataset? Now it does, and now it is in the right file.
 */
.oview-card__marker[data-marker="female"],
.oview-card__marker[data-marker="male"],
.oview-card__marker[data-marker="unisex"] {
	width: 1.6rem;
	height: 1.6rem;
	max-width: none;
	overflow: hidden;
	text-indent: -100em;
	/*
	 * ⚠️ TEXT-INDENT ONLY INDENTS THE FIRST LINE, AND THIS ELEMENT CAN WRAP.
	 *
	 * `.oview-card__marker` carries `overflow-wrap: break-word`, so "female" in
	 * a 16px box is free to break - and a second line is NOT indented. It would
	 * render at x=0, inside the box, in full view: the exact failure
	 * check-controls.js exists for, "unisex" leaving "sex" on every card.
	 *
	 * Defensive, not a fix for an observed break. Nothing was wrapping when
	 * this was added. But hiding text by moving it is only safe while the text
	 * cannot be re-laid-out behind you, and the type scale is fluid now: the
	 * size at any given width is a computed fraction rather than a number
	 * somebody chose. `nowrap` removes the choice.
	 */
	white-space: nowrap;
}

/*
 * A mask, not an <img> and not a background-image.
 *
 * A mask takes its colour from `background`, so one file serves all three
 * states and the icon can be tinted to match its value. As a background-image
 * the colour would be baked into the file and each gender would need its own
 * copy for every colour it is ever drawn in.
 *
 * The files are the ones in svgs/, copied here so the plugin carries its own
 * assets rather than reaching outside itself for them.
 */
.oview-card__marker[data-marker="female"]::before,
.oview-card__marker[data-marker="male"]::before,
.oview-card__marker[data-marker="unisex"]::before {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--color-text-muted);
	mask-repeat: no-repeat;
	mask-position: center;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	-webkit-mask-position: center;
	-webkit-mask-size: contain;
}

.oview-card__marker[data-marker="female"]::before {
	background: var(--color-gender-female-ink);
	mask-image: url("icons/gender-female.svg");
	-webkit-mask-image: url("icons/gender-female.svg");
}

.oview-card__marker[data-marker="male"]::before {
	background: var(--color-gender-male-ink);
	mask-image: url("icons/gender-male.svg");
	-webkit-mask-image: url("icons/gender-male.svg");
}

.oview-card__marker[data-marker="unisex"]::before {
	background: var(--color-gender-unisex-ink);
	mask-image: url("icons/gender-unisex.svg");
	-webkit-mask-image: url("icons/gender-unisex.svg");
}

/* --- the gender facet ----------------------------------------------------- */

/*
 * The one facet whose options are colour-coded, because gender is the filter
 * people reach for first and three values are few enough to learn at a glance.
 *
 * Scoped by BOTH the facet and the value. `[data-oview-facet="gender"]` is what
 * stops this leaking into any other facet that happens to have an option called
 * "male", and it is why the facet element puts its key in the DOM.
 *
 * The checkbox uses -ink and the label uses -on, which are different colours on
 * purpose. A checkbox is a non-text UI component and clears WCAG 1.4.11 at 3:1;
 * a label is text and needs 4.5:1, which -ink does not reach at these hues -
 * unisex ink is 3.43:1 on white. One hue cannot do both jobs.
 */
[data-oview-facet="gender"] .oview-facet__option--on[data-value="female"] .oview-facet__check {
	background: var(--color-gender-female-ink);
	border-color: var(--color-gender-female-ink);
}

[data-oview-facet="gender"] .oview-facet__option--on[data-value="male"] .oview-facet__check {
	background: var(--color-gender-male-ink);
	border-color: var(--color-gender-male-ink);
}

[data-oview-facet="gender"] .oview-facet__option--on[data-value="unisex"] .oview-facet__check {
	background: var(--color-gender-unisex-ink);
	border-color: var(--color-gender-unisex-ink);
}

/*
 * ⚠️ AND THE ICON WHERE THERE IS ONE, because the box it replaced carried the
 * state. The option now draws a gender symbol instead of a tick, so with only
 * the rules above a chosen row said so with its label colour and nothing else.
 *
 * `-ink` and not `-on`: an icon is a non-text UI component, so it clears
 * WCAG 1.4.11 at 3:1 like the checkbox did. The label beside it still needs the
 * darker `-on`, which is the paragraph above.
 */
[data-oview-facet="gender"] .oview-facet__option--on[data-value="female"] .oview-facet__icon--option {
	color: var(--color-gender-female-ink);
}

[data-oview-facet="gender"] .oview-facet__option--on[data-value="male"] .oview-facet__icon--option {
	color: var(--color-gender-male-ink);
}

[data-oview-facet="gender"] .oview-facet__option--on[data-value="unisex"] .oview-facet__icon--option {
	color: var(--color-gender-unisex-ink);
}

[data-oview-facet="gender"] .oview-facet__option--on[data-value="female"] .oview-facet__name {
	color: var(--color-gender-female-on);
}

[data-oview-facet="gender"] .oview-facet__option--on[data-value="male"] .oview-facet__name {
	color: var(--color-gender-male-on);
}

[data-oview-facet="gender"] .oview-facet__option--on[data-value="unisex"] .oview-facet__name {
	color: var(--color-gender-unisex-on);
}

/* The count follows its row: tint behind, the same darker text on top. */
[data-oview-facet="gender"] .oview-facet__option--on[data-value="female"] .oview-facet__count {
	background: var(--color-gender-female);
	color: var(--color-gender-female-on);
}

[data-oview-facet="gender"] .oview-facet__option--on[data-value="male"] .oview-facet__count {
	background: var(--color-gender-male);
	color: var(--color-gender-male-on);
}

[data-oview-facet="gender"] .oview-facet__option--on[data-value="unisex"] .oview-facet__count {
	background: var(--color-gender-unisex);
	color: var(--color-gender-unisex-on);
}

/* --- the card's rating ---------------------------------------------------- */

/*
 * The star belongs to this dataset, not to the card.
 *
 * ov_card() emits a class per fact POSITION, so this rule says "our second
 * fact is a score" - a thing only the fragrance plugin knows. A dataset whose
 * second fact is a weight class simply never writes it.
 *
 * ⚠️ ::after, not ::before. The separator in cards.css already owns ::before
 * on every fact, and an element has one of each: a star written to ::before was
 * silently replaced by the dot, which read as the star rule not applying.
 *
 * Drawn by CSS so the element stays genuinely empty when there is no rating and
 * :empty removes it - otherwise every unrated fragrance shows a lonely star.
 */
.oview-card__fact--1::after {
	content: "\00a0\2605";
	color: var(--color-warning);
}

/*
 * ⚠️ THE SCORE READS AS THE SCORE, not as a number with a star after it.
 *
 * The star was warning-orange and the digits were body text, which is the
 * colouring of a caption with a decoration on it. On a card whose whole job is
 * "is this one any good", the figure is the thing being looked at.
 */
.oview-card__fact--1 {
	color: var(--color-warning-ink);
	font-weight: 600;
}

/*
 * The year is the quiet one, and it is a number: mono, so a column of cards
 * lines its years up rather than kerning each one differently.
 */
.oview-card__fact--0 {
	font-family: var(--font-mono);
	color: var(--color-text-muted);
}

/*
 * ⚠️ A BOTTLE IS TALLER THAN IT IS WIDE, AND THE SHARED CARD IS NOT.
 *
 * A promoted frame gives `.oview-card__media` a fixed `height: 10.4rem`, which
 * is right for the wordmark it was drawn for: a brand logo is a wide, short
 * thing. A bottle in that box is a 218px-wide letterbox with a 40px bottle in
 * the middle of it.
 *
 * Square, and stated HERE, because the shape of the picture is a fact about
 * this dataset - the same argument the gender wash above makes. This stylesheet
 * loads after the frames, which is what makes one line enough.
 *
 * ⚠️ SCOPED TO THE GRID THAT ASKED FOR IT, AND TWO NARROWER SCOPES FAILED FIRST.
 *
 * This file is enqueued on every page, so an unscoped rule about a shared class
 * leaks the way a promoted frame does, and the card appears in five templates
 * with five different shapes.
 *
 * `[data-marker]` was the first attempt, on the reading that only a fragrance
 * card declares one. Wrong: `ov_card()` writes whatever is in the marker slot,
 * and the BRAND card's marker is its country flag - so the rule reached the
 * brands archive, took the height off a 257px logo box and pushed the card's own
 * body past the viewport. The three gender VALUES were the second, and they are
 * correct about which card it is and say nothing about which LAYOUT: the same
 * fragrance card is a compact row on a brand, note and accord page, where a
 * square media is the full column width and the body goes beside it.
 *
 * `.oview-card-grid--dense` is the fragrance archive's own grid, declared by
 * that template and nothing else. A rule about how tall a picture is in a
 * four-column grid belongs to the grid, not to the dataset's whole card.
 * `check-mobile.js` said so twice, on four pages and then on three.
 */
.oview-card-grid--dense .oview-card__media {
	height: auto;
	aspect-ratio: 1 / 1;
}

/* --- the note and accord archives ---------------------------------------- */

/*
 * "49,571" is a number; "49,571 fragrances" is a quantity.
 *
 * Same trick as the star above and for the same two reasons: the word is a
 * fact about THIS dataset's first fact, and drawing it in CSS keeps the
 * element genuinely empty so `:empty` can remove it when the count is missing.
 * A literal word in the template would defeat that and leave a stray separator.
 *
 * Scoped by the archive's own body class rather than by `--0`, because the
 * browse page's first fact is a year and would otherwise read "1998 fragrances".
 */
.post-type-archive-note .oview-card__fact--0::after,
.post-type-archive-accord .oview-card__fact--0::after,
.post-type-archive-brand .oview-card__fact--0::after {
	/*
	 * Six digits, not four. A CSS escape runs to six hex characters unless
	 * something stops it, so `\00a0fragrances` is read as codepoint 0x00A0F
	 * followed by "ragrances" - and the card rendered a Gurmukhi letter where
	 * the space should have been. The star rule above only escapes this
	 * because `\2605` is followed by a closing quote.
	 *
	 * The zero-padded form terminates itself. A trailing space terminates it
	 * too, but is then eaten as the terminator rather than printed, which is
	 * the other half of the same trap.
	 */
	content: "\0000a0fragrances";
	color: var(--color-text-muted);
}

/*
 * The accord archive's wash, from the row's own colour.
 *
 * Same radial as the gender wash and for the same reasons - anchored to the
 * bottom edge, wider than the card, about a third of its height, so it reads as
 * light rather than as paint. What differs is where the colour comes from:
 * gender has three values and three token pairs, accords have 92 hand-authored
 * hexes (D35), so the value arrives per card in `--card-accent` and this rule
 * derives the pale form from it instead of naming a second token.
 *
 * `color-mix` at 22% rather than a second column of pale hexes. 92 colours
 * would otherwise need 92 more, hand-tuned, and drift apart the first time one
 * of them is corrected.
 *
 * The accent hairline along the bottom edge needs no rule at all: cards.css
 * already draws it from the same property.
 */
.post-type-archive-accord .oview-card {
	background-image: radial-gradient(130% 34% at 50% 100%, color-mix(in srgb, var(--card-accent) 22%, transparent), transparent 70%);
}

/*
 * ⚠️ The hover border is NOT recoloured, and that is the one place this stops
 * copying the gender pattern.
 *
 * A border is a non-text UI component under WCAG 1.4.11 and owes 3:1. The three
 * gender inks clear it - the weakest is unisex at 3.43:1. The accord colours do
 * not: **46 of the 92 are below 3:1 on white**, white floral worst at 1.20:1,
 * and they are chosen to describe a smell rather than to be legible as a line.
 * So the border keeps --color-border-strong from cards.css.
 *
 * The wash above is exempt because it is decorative: the accord's name and its
 * family are both text on the card, so nothing is carried by colour alone
 * (WCAG 1.4.1).
 */

/*
 * ⚠️ No wash in the list view, same rule as gender and the same reason: a
 * gradient tuned to a 162px card paints a band across a 900px row.
 */
.ov-view-list .post-type-archive-accord .oview-card,
.post-type-archive-accord .ov-view-list .oview-card {
	background-image: none;
}

/*
 * Accord names are stored lowercase because that is how the source spells them,
 * and `name` is the key the import upserts on - so the fix is display, not data
 * (D30 for brands, the same rule here). `display_name` overrides it where we
 * have decided on our own spelling, and capitalize leaves that alone when it is
 * already capitalised.
 */
.post-type-archive-accord .oview-card__title,
.post-type-archive-accord .oview-card__parent {
	text-transform: capitalize;
}

/*
 * The flag needs room the icon markers do not.
 *
 * `.oview-card__marker` is a short label; a flag emoji at that size is a smudge.
 * It is the one marker on the site that is a picture rather than a word, so it
 * gets the size a picture needs and nothing else changes.
 *
 * ⚠️ A TOKEN, not a raw rem. The first version said `1.1rem` reasoning from a
 * 16px root - but the root here is **10px** and fluid (D39), so 1.1rem computed
 * to 11px and failed the 12px floor `check-mobile.js` enforces. Every size on
 * this site comes from the scale precisely so that arithmetic is never done in
 * a stylesheet.
 */
.post-type-archive-brand .oview-card__marker {
	/* ⚠️ Was `--text-m` to stop an emoji flag being a smudge. The flag is an
	 * image now and carries its own size, so this only has to stop the marker
	 * shrinking the line it sits on. */
	font-size: var(--text-s);
	line-height: 1;
}

/*
 * The brand page's meta line: a flag, a kind, a website link.
 *
 * ⚠️ The link needs a tap target, and inline text does not have one. At its
 * natural 22px it failed WCAG 2.2 SC 2.5.8's 24px floor - the card titles get
 * away with 21px only because the card's stretched anchor gives them the whole
 * card to hit, and a link on its own has no such help.
 */
.oview-brand-meta {
	font-size: var(--text-s);
}

.oview-brand-meta a {
	display: inline-flex;
	align-items: center;
	min-height: 24px;
}

