/*
 * The buy column: quantity field, breadcrumb, size chart, details table. Flow
 * and nothing else.
 *
 * WHY A THIRD STYLESHEET AND NOT `storefront.css`
 *
 * Because `storefront.css` is enqueued on every page of every shop
 * (`Storefront::registerStyle()` says why, and it is right), and none of these
 * three parts is on every page. This one travels on the rail `catalog.css`
 * already uses: registered, never enqueued, pulled in by `get_style_depends()`
 * of the widget that needs it. A shop whose product page has no size chart
 * never downloads its dialog rules.
 *
 * WHAT MAY STAND HERE (§ II.6.1): layout only. No colour, background, font,
 * radius or shadow — every one of those is a control on the widget pointing at
 * the class below it (§ V.9), so the template owns the look and the plugin
 * owns the flow.
 *
 * THE EXCEPTIONS, COUNTED — four, and every one of them undoes a browser
 * default rather than making a decision:
 *
 *   1. `padding-inline-start: 0` and `margin: 0` on the breadcrumb list.
 *      A UA stylesheet indents every `<ol>` by 40 px for the numbers it is
 *      not going to draw. Ground code `grid-flow`: without it the trail hangs
 *      in the air beside its own column.
 *   2. `appearance: textfield` plus the two WebKit spin-button pseudos.
 *      § V.3.3 builds the −/+ buttons precisely because the native arrows are
 *      13 px high on a desktop and untouchable on a phone; leaving them in
 *      beside the built ones gives the same control twice.
 *   3. `text-overflow: ellipsis` on the breadcrumb's last link under 768 px.
 *      Ground code `grid-flow`. § V.1.2 asks for the trail "einzeilig mit
 *      Ellipse" in as many words and the property list of § II.6.1 does not
 *      carry `text-overflow` — it carries `overflow`, `white-space` and
 *      `word-break`, none of which draws the three dots. Reported as a gap in
 *      that list rather than worked around: without it the alternative is a
 *      hard clip mid-word.
 *   4. `margin-inline-start: 0` on the details table's `<dd>`. Same shape as
 *      exception 1: a UA stylesheet indents every `<dd>` by 40 px, and a
 *      value column that starts 40 px in is not a column.
 *
 * Nothing here selects markup that is not ours. The size chart's table comes
 * out of the operator's page and is styled by their theme (§ II.1.2 R4).
 *
 * Every selector is a class of ours, at most two deep (§ II.1.2 R4).
 */

/* ---- the quantity field ------------------------------------------------ */

/*
 * A row, and the numbers stay on it. `flex-wrap` is deliberately absent: a
 * quantity field that wraps between the minus and the input is not a quantity
 * field any more, and at 44 px per button plus the input it fits inside the
 * 352 px § V.1.2 measured for the narrowest buy column.
 */
.ostia-qty {
	display: flex;
	align-items: center;
	gap: .5rem;
}

/*
 * WIDTH HERE RATHER THAN AS A CONTROL DEFAULT. § II.6.4 permits a default on
 * this one control by name — and a default is a declaration Elementor then
 * writes into the stylesheet of every shop whether anybody chose it or not.
 * The rule reaches the same place and leaves the page clean, and the control
 * still wins the moment it is touched (`{{WRAPPER}} .ostia-qty__input` is
 * (0,2,0) against this (0,1,0)).
 *
 * Without it the field is as wide as the theme's `input`, which on most themes
 * is the full column: a box for three digits taking the whole buy column.
 */
.ostia-qty__input {
	width: 4.5rem;
	min-height: 44px;
	appearance: textfield;
	-moz-appearance: textfield;
}

.ostia-qty__input::-webkit-outer-spin-button,
.ostia-qty__input::-webkit-inner-spin-button {
	appearance: none;
	-webkit-appearance: none;
}

/*
 * 44 px is the floor of WCAG 2.5.5 and the number § V.1.2 lays the buy column
 * out around. The control above it can only grow this, never shrink it.
 */
.ostia-qty__step {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	cursor: pointer;
}

/*
 * Still read aloud, just not drawn.
 *
 * ⚠ MIT `clip-path`, WIE ÜBERALL SONST — und der Satz, der hier stand
 * („`clip-path` ist nicht auf der erlaubten Liste"), war schlicht falsch:
 * sechs Regeln in `catalog.css`, `account.css`, `mini-cart.css` und
 * `storefront.css` benutzen genau dieses Rezept.
 *
 * Es ist nicht nur Einheitlichkeit. Ein Element mit `overflow: hidden` und
 * einem Pixel Kantenlänge steht trotzdem im Layout, und der Layoutwächter
 * sieht ein 1×1-Rechteck auf einem 48×48-Knopf: acht Befunde am 2026-09-09,
 * auf Produkt- und Präsentationsseite bei jeder Breite. `clip-path` macht das
 * Element für die Messung zu dem, was es für das Auge längst ist — nicht da.
 */
.ostia-qty__label--hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* The line that says why the number moved. It takes the whole row to itself. */
.ostia-qty__note {
	flex-basis: 100%;
}

/* Editor only — the widget prints it so the operator can find the field's id. */
.ostia-qty__hint {
	flex-basis: 100%;
	word-break: break-all;
}

/* ---- the breadcrumb ---------------------------------------------------- */

.ostia-breadcrumb__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .5rem;
	list-style: none;
	/* Exception 1 — see the header. */
	margin: 0;
	padding-inline-start: 0;
}

.ostia-breadcrumb__item {
	display: flex;
	align-items: center;
	gap: .5rem;
}

/*
 * ONE LINE WITH AN ELLIPSIS ON A PHONE (§ V.1.2, row "Brotkrume"). A trail
 * three categories deep is otherwise the first three lines of a product page,
 * above the picture.
 */
@media (max-width: 767px) {
	.ostia-breadcrumb__list {
		flex-wrap: nowrap;
		overflow-x: auto;
		white-space: nowrap;
	}

	.ostia-breadcrumb__current {
		overflow: hidden;
		text-overflow: ellipsis;
	}
}

/* ---- the details table ------------------------------------------------- */

/*
 * BEGRIFF LINKS, WERT RECHTS — UND DAS IST EIN RASTER, KEINE GESTALTUNG.
 *
 * Ohne diese vier Regeln stellt der Browser eine `<dl>` untereinander und
 * rückt jedes `<dd>` um 40 px ein: „Artikelnummer", darunter eingerückt
 * „P-010100", siebenmal. Das Blatt `Produkt.dc.html` zeichnet zwei Spalten mit
 * einer feinen Linie darunter, und zwei Spalten sind Anordnung.
 *
 * WAS HIER NICHT STEHT: die Linie selbst. Ihre Farbe und ihre Stärke sind zwei
 * Regler an `ostia-details` (`details_rule_color`, `details_rule_width`), und
 * die Startvorlage zeigt sie auf die Kit-Rolle „Ostia Linie". Ein fester Wert
 * hier wäre eine Farbe, die kein Shop ändern kann.
 *
 * `margin-inline-start: 0` ist die vierte gezählte Ausnahme des Kopfes: sie
 * nimmt dem `<dd>` die Einrückung des User-Agent-Stylesheets zurück und trifft
 * keine Entscheidung.
 */
/*
 * Die Rechtslinks unter „Lieferung und Rückgabe" — eine Zeile, keine Liste.
 *
 * Nur Achse, Umbruch und Abstand; Schrift und Farbe kommen aus den Reglern
 * `details_links_*` und `details_link_*`. Ohne diese Zeilen zeichnete das
 * Theme die `<ul>` mit Browserpunkten untereinander — gemessen am 2026-09-09
 * auf jeder Produktseite. Der Abstand ist eine Variable, weil `Canon::grid`
 * `gap` schreibt und der Rest hier nichts vorgeben soll.
 */
.ostia-details__links {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 6px 16px;
}

.ostia-details__link-item {
	margin: 0;
}

.ostia-details__pairs {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: baseline;
	margin: 0;
}

.ostia-details__term {
	grid-column: 1;
	padding: 13px 0;
}

.ostia-details__value {
	grid-column: 2;
	padding: 13px 0;
	text-align: end;
	/* Ausnahme 4 — siehe oben. */
	margin-inline-start: 0;
}

/* ---- the size chart ---------------------------------------------------- */

.ostia-size-chart__trigger {
	display: inline-flex;
	align-items: center;
	gap: .35rem;
}

.ostia-size-chart__icon {
	flex: none;
}

/*
 * The dialog sizes itself to the window and lets the table scroll inside it —
 * a size chart is wide by nature, and a page that scrolls sideways because of
 * one is the house rule this file must not break.
 */
.ostia-size-chart__panel {
	width: min(48rem, calc(100vw - 2rem));
	max-width: calc(100vw - 2rem);
	max-height: calc(100vh - 4rem);
	overflow: auto;
}

.ostia-size-chart__content {
	overflow-x: auto;
}

/* ---- the stock dot ----------------------------------------------------- */

/*
 * A dot is a shape and its colours are four controls (`ostia-stock-dot`). What
 * belongs here is that it does not stretch: in a flex row an 8 px span would
 * otherwise take the row's height and stop being round.
 */
.ostia-stock-dot {
	display: inline-block;
	flex: none;
}

/* ---- „Benachrichtigen, wenn da" ---------------------------------------- */

/*
 * A stacked form: label, field, button, one under the other and each as wide
 * as the column. Height, edge, radius and type are controls; the axis is here.
 *
 * The honeypot is the one element with no control, and it has a ground code:
 * it is never seen by anybody. Same recipe as every other visually-hidden
 * element in this tree (`clip-path`, not a 1 px box, so the layout guard does
 * not measure a rectangle where the eye sees nothing).
 */
.ostia-stock-notify {
	display: flex;
	flex-direction: column;
	align-items: stretch;
}

.ostia-stock-notify__input,
.ostia-stock-notify__button {
	width: 100%;
}

.ostia-stock-notify__trap {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
}

.ostia-stock-notify__said {
	margin: 0;
}

/* ---- the buy button ---------------------------------------------------- */

/*
 * Centred, and it fills the space the row gives it. Everything else — colour,
 * type, padding, radius, and the whole locked state — is a control on
 * `ostia-buy-button`, because a template has to be able to draw the sheet's
 * two appearances without touching a stylesheet.
 */
.ostia-buy {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	cursor: pointer;
}

/* ---- the word beside a variant label ----------------------------------- */

/*
 * „Größentabelle" sits at the RIGHT edge of the label it belongs to, which is
 * one declaration and the reason this rule exists: a legend is the `<legend>`
 * of somebody else's `<fieldset>`, and nothing outside the picker can reach
 * into it. `margin-inline-start: auto` is axis, not decoration; the colour and
 * the size are the two `variants_aside_*` controls.
 */
.ostia-variants__aside {
	margin-inline-start: auto;
}

/*
 * The label of a REAL choice carries three things — name, chosen value, aside
 * — so it is a row rather than a line of text. `<legend>` needs `display:
 * flex` spelled out: a legend is not a flex container by default in any
 * engine.
 *
 * ⚠ NICHT IN DER FESTSTEHENDEN ZEILE. Dort IST die Beschriftung nur das
 * Wort, und mit `width: 100%` schob sie den Wert in die nächste Zeile —
 * „Material" über „: polyester", gemessen am 2026-09-10 auf
 * `/variante/p-200-tuerkis/`.
 */
.ostia-variants__group:not(.ostia-variants__group--fixed) > .ostia-variants__legend {
	display: flex;
	align-items: baseline;
	width: 100%;
}

/*
 * An axis with one value: „Material: Polyester" on ONE line.
 *
 * ⚠ ZWEI KLASSEN IM SELEKTOR, UND ZWAR GEMESSEN. `storefront.css` gibt jeder
 * `.ostia-variants__group` ein `flex-direction: column` — richtig für eine
 * Gruppe aus Beschriftung und Wahlleiste, falsch für eine Zeile aus zwei
 * Wörtern. Beide Regeln haben eine Klasse, also entscheidet die Reihenfolge
 * der Dateien, und die entscheidet Elementor nach Abhängigkeiten: am
 * 2026-09-10 stand „Material" über „: polyester". Mit dem Elternteil im
 * Selektor gewinnt diese Regel überall.
 */
.ostia-variants .ostia-variants__group--fixed {
	display: flex;
	flex-direction: row;
	align-items: baseline;
	gap: .35rem;
	margin: 0;
}
