/*
 * The mini-basket drawer: flow, position and nothing else.
 *
 * WHY A FOURTH STYLESHEET
 *
 * Same rail as `buy.css` and for the same reason. `storefront.css` is enqueued
 * on every page of every shop; a drawer is on the pages whose header carries
 * the widget. This one is registered and never enqueued — Elementor pulls it in
 * through `MiniCartWidget::get_style_depends()`, so a shop that never places
 * the widget never downloads a byte of it.
 *
 * WHAT MAY STAND HERE (§ II.6.1): layout only. Every colour, font, radius and
 * shadow is a control on the widget pointing at the class below it (§ VI.7), so
 * the template owns the look and the plugin owns the flow.
 *
 * THE EXCEPTIONS, COUNTED — four, and each one is a mechanism rather than a
 * decision:
 *
 *   1. `position: fixed` and `z-index` on the panel and the scrim. This is what
 *      "Schublade von rechts" IS; without it the drawer is a box in the header.
 *      ⚠ An ancestor with `transform`, `filter`, `backdrop-filter`,
 *      `perspective` or `will-change` makes itself the containing block and the
 *      panel stops being flush with the window — Elementor's own motion effects
 *      set `transform` on a section. The layout guard (W1) measures the right
 *      edge at 1366 px, which is the only way this is ever noticed.
 *   2. `background: Canvas` on the panel. A `position: fixed` element with no
 *      background lets the page text through it, and the drawer is then
 *      unreadable rather than merely unstyled. `Canvas` is the browser's own
 *      surface colour — it follows the platform and the user's dark mode. It is
 *      the absence of a decision, and the control above it wins the moment it
 *      is touched (`{{WRAPPER}} .ostia-mini__panel` is (0,2,0) against (0,1,0)).
 *   3. `background: rgb(0 0 0 / .35)` on the scrim. The scrim has no other
 *      function: an invisible backdrop is a click target nobody can see, and
 *      "click outside closes" then reads as a page that eats clicks.
 *   4. `appearance: textfield` plus the two WebKit spin-button pseudos on the
 *      quantity field, identical to `buy.css` and for the identical reason —
 *      the −/+ buttons exist because the native arrows are 13 px on a desktop
 *      and untouchable on a phone; leaving them in gives the same control
 *      twice.
 *
 * Every selector is a class of ours, at most two deep (§ II.1.2 R4).
 */

/* ---- the trigger ------------------------------------------------------- */

.ostia-mini {
	display: inline-flex;
}

.ostia-mini__trigger {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	/* WCAG 2.5.5 (AAA). The header cart is the most-tapped control in a shop
	   and it is often nothing but a 16 px icon. */
	min-height: 44px;
}

.ostia-mini__icon {
	display: inline-flex;
	width: 1.5rem;
	height: 1.5rem;
	flex: none;
}

.ostia-mini__icon svg {
	width: 100%;
	height: 100%;
}

/*
 * VISUALLY GONE, NEVER GONE. An operator who clears the label wants an icon,
 * not an unnamed button: to a screen reader a control with no accessible name
 * is a control nobody can describe.
 */
.ostia-mini__label--hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* Every number in the drawer sits on tabular digits — the counter, the line
   sums and the subtotal (README: „Preisleiter, immer tabular-nums"). Numeric
   alignment is layout, not taste, the same line `storefront.css` draws. */
.ostia-mini__count,
.ostia-mini__sum,
.ostia-mini__total span:last-child {
	font-variant-numeric: tabular-nums;
}

.ostia-mini__count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* So 1 and 12 do not resize the header. */
	min-width: 1.5em;
}

/* ---- der Zähler als Blase, wenn der Auslöser nur ein Symbol ist --------- */
/*
 * Geometrie, sonst nichts: Fläche, Schriftfarbe, Radius und Polster der Blase
 * kommen aus den Reglern (`mini_count_*`), und die Kopfvorlage setzt sie.
 * Hier steht nur, wo sie sitzt und dass sie bei null verschwindet.
 *
 * Warum überhaupt: neben dem Warenkorbsymbol stand auf jeder Seite eine „0“
 * als Wort, während die Merkliste zwei Symbole weiter nichts zeigte — zwei
 * Zähler derselben Kopfzeile mit zwei Antworten auf dieselbe Frage. Der
 * Entwurf zeigt beide gleich.
 */
.ostia-mini--bare .ostia-mini__trigger {
	position: relative;
}

.ostia-mini--bare .ostia-mini__count {
	position: absolute;
	top: 4px;
	right: 2px;
	min-width: 16px;
	height: 16px;
}

/*
 * ⚠ JEDER AUSLÖSER, NICHT NUR DER IM KOPF. Diese Regel hing an
 *   `--bare`, also am Kopfsymbol; der freistehende Auslöser trug weiter eine
 *   „0" neben dem Wort „Warenkorb" — der Zustand, den ein Shop am häufigsten
 *   zeigt (Abnahme vom 2026-09-10). Die Zahl ist die Aussage „so viel liegt
 *   drin"; bei null ist die Aussage das Wort daneben.
 */
.ostia-mini__count[data-ostia-empty="true"] {
	display: none;
}

/* ---- the drawer -------------------------------------------------------- */

.ostia-mini__scrim {
	position: fixed;
	inset: 0;
	/* Exception 3. */
	background: rgb(0 0 0 / .35);
	z-index: 99998;
}

.ostia-mini__panel {
	position: fixed;
	inset-block: 0;
	inset-inline-end: 0;
	/*
	 * CLAMPED AGAINST THE WINDOW, WHICH IS WHY THE WIDTH IS A CUSTOM PROPERTY
	 * AND NOT A CONTROL WRITING `width`. A drawer wider than the viewport is a
	 * horizontal scrollbar on the whole document, and W1 forbids exactly that
	 * (`scrollWidth <= innerWidth`).
	 */
	width: min(var(--ostia-mini-width, 24rem), 100vw);
	max-width: 100vw;
	display: flex;
	flex-direction: column;
	/* Exception 2. */
	background: Canvas;
	color: inherit;
	z-index: 99999;
	/*
	 * ⚠ DER RAND LIEGT IN DEN DREI TEILEN, NICHT UM SIE HERUM — und das ist
	 * kein Geschmack, sondern die Bedingung für die zwei Trennlinien, die
	 * `Kopf.dc.html` zeichnet. Mit 1 rem Polster am Panel und 12 px Lücke
	 * dazwischen endet eine Linie unter der Kopfzeile 16 px vor beiden Kanten
	 * und schwebt 12 px über dem Inhalt, den sie abtrennen soll.
	 *
	 * Abstand ist Layout und darf hier stehen (§ II.6.1); was die Linie selbst
	 * angeht — Farbe, Stärke, Radius — steht an den Reglern `mini_head_*` und
	 * `mini_foot_*`.
	 */
	padding: 0;
	gap: 0;
}

/*
 * `display: flex` beats the `hidden` attribute, and a drawer that is closed and
 * still covering the page is the whole shop broken. Both, because the scrim is
 * a block and the panel a flex container.
 */
.ostia-mini__panel[hidden],
.ostia-mini__scrim[hidden] {
	display: none;
}

/* From the right, and only for people who did not ask for less motion. */
@media (prefers-reduced-motion: no-preference) {
	.ostia-mini__panel {
		animation: ostia-mini-in .18s ease-out;
	}
}

@keyframes ostia-mini-in {
	from { transform: translateX(100%); }
	to   { transform: translateX(0); }
}

.ostia-mini__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: .5rem;
	flex: none;
	padding: 20px 24px;
}

.ostia-mini__title {
	margin: 0;
}

/*
 * „3 Positionen" — pushed to the close button by its own auto margin, so the
 * head's `space-between` has nothing left to spread when it is there and
 * puts the close button on the edge when it is not. Off until a template's
 * responsive control switches it on (the phone's drawer, `MobilSchubladen`);
 * `hidden` — set by the island on an empty basket — must beat that control,
 * which writes at a higher specificity, hence the one `!important`.
 */
.ostia-mini__positions {
	display: none;
	margin-left: auto;
	white-space: nowrap;
}

.ostia-mini__positions[hidden] {
	display: none !important;
}

.ostia-mini__close {
	min-width: 44px;
	min-height: 44px;
	flex: none;
	line-height: 1;
}

/*
 * THE ONLY SCROLLING PART. The head stays and the foot stays; a drawer whose
 * "Zur Kasse" button scrolls away with the fifth row is the mistake sticky
 * summary columns make (§ VII.6.2 makes the same point with a max-height).
 */
/*
 * ⚠ OHNE EIGENES POLSTER, UND DAS IST EINE FOLGE DES AUFBAUS. Der Fuss wird
 * von `mini-cart.js` MIT IN DIESES ELEMENT gerendert (es ist das einzige, das
 * die Insel füllt) — ein Polster hier läge also auch um den Fuss, und seine
 * Trennlinie endete 24 px vor beiden Kanten statt an ihnen. Den Rand tragen
 * deshalb die Teile: Liste, Fuss, Leerzustand, Fehler, Skelett.
 */
.ostia-mini__body {
	flex: 1 1 auto;
	overflow-y: auto;
	min-height: 0;
}

/* ---- the rows ---------------------------------------------------------- */

.ostia-mini__lines {
	list-style: none;
	margin: 0;
	padding: 20px 24px;
	display: flex;
	flex-direction: column;
	gap: 20px;
}

/*
 * Two rows of three cells. The picture spans both, the title sits beside the
 * remove button, the stepper beside the line total. `minmax(0, 1fr)` on the
 * middle column rather than `1fr`: a grid item's minimum is its content, so a
 * long product name without it widens the column past the drawer and the panel
 * grows a scrollbar sideways.
 */
.ostia-mini__line {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	grid-template-areas:
		"media text   remove"
		"media stepper sum";
	/* 5 px between title and options, 14 between picture and text (Blatt
	   Kopf); the stepper 4 px under the options is the grid row's gap. */
	gap: 5px 14px;
	align-items: start;
}

.ostia-mini__media  { grid-area: media; display: block; }
.ostia-mini__text   { grid-area: text; min-width: 0; }
.ostia-mini__remove { grid-area: remove; min-width: 44px; min-height: 44px; line-height: 1; }
/* `justify-self: start`, or the grid stretches the stepper across the whole
   text column: measured 208 px wide with the − at the left edge and the + at
   the right. The sheet draws an 82 px box at the start and the sum at the end. */
.ostia-mini__stepper{ grid-area: stepper; align-self: center; justify-self: start; }
.ostia-mini__sum    { grid-area: sum; align-self: center; text-align: end; white-space: nowrap; }

/*
 * 3 : 4, the ratio all three reference shops use, with the width settable and
 * the height following it. 64 px is § VI.1.5's drawer size.
 */
.ostia-mini__image {
	display: block;
	width: 64px;
	height: auto;
	aspect-ratio: 3 / 4;
	max-width: 100%;
}

.ostia-mini__link {
	/* Two lines of a product name, then a clip — a drawer is a summary, and a
	   six-line title pushes the fifth row out of the panel. */
	display: -webkit-box;
	overflow: hidden;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
}

.ostia-mini__options {
	margin: 0;
}

.ostia-mini__flag {
	margin: .15rem 0 0;
}

.ostia-mini__stepper {
	display: flex;
	align-items: center;
	gap: .25rem;
}

.ostia-mini__step {
	min-width: 44px;
	min-height: 44px;
	line-height: 1;
}

.ostia-mini__qty {
	width: 3rem;
	min-height: 44px;
	/* The field must not grow with the stepper's box; its width is a control. */
	flex: none;
	text-align: center;
	/* Exception 4. */
	appearance: textfield;
	-moz-appearance: textfield;
}

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

/* ---- foot, and the states that are not a list -------------------------- */

.ostia-mini__more {
	margin: 0;
	padding: 0 24px 20px;
}

/* Im Fuss, direkt unter der Summe, auf die er sich bezieht. */
.ostia-mini__progress {
	margin: 0;
}

/*
 * DER FUSS SCROLLT NICHT, also klebt er am unteren Rand des Panels und trägt
 * seinen Rand selbst. `margin-top` stand hier, als er noch im scrollenden
 * Bereich lag; jetzt wäre er eine Lücke zwischen zwei Kanten.
 */
.ostia-mini__foot {
	display: flex;
	flex-direction: column;
	gap: .875rem;
	padding: 20px 24px;
}

.ostia-mini__total {
	display: flex;
	justify-content: space-between;
	/* Label and amount on one baseline — 15 px beside 24 px sit apart otherwise. */
	align-items: baseline;
	gap: 1rem;
	margin: 0;
}

.ostia-mini__button {
	display: block;
	text-align: center;
	min-height: 44px;
	/* So the label is centred in the 44 px the target size asks for. */
	padding: .6rem 1rem;
}

.ostia-mini__empty,
.ostia-mini__error {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: .75rem;
	padding: 20px 24px;
}

.ostia-mini__empty p,
.ostia-mini__error p {
	margin: 0;
}

.ostia-mini__empty-link,
.ostia-mini__retry {
	min-height: 44px;
}

/*
 * The shape of the contents, not a spinner. The bar height is the picture
 * height, so the rows do not move when the answer arrives.
 *
 * `currentColor` at low opacity rather than a grey: it is derived from whatever
 * the template set, so it is not a colour decision and it stays visible in a
 * dark theme.
 */
.ostia-mini__skeleton {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding: 20px 24px;
}

.ostia-mini__skeleton div {
	height: 85px;
	background: currentColor;
	opacity: .08;
}

/*
 * THE EDITOR PREVIEW, AND ONLY THERE. The widget draws the drawer open on the
 * canvas so the Style tab has something to act on; taking it out of the fixed
 * layer is what makes that possible.
 */
.ostia-mini--preview,
.ostia-mini--preview .ostia-mini__panel {
	position: static;
	display: block;
	width: auto;
	animation: none;
	z-index: auto;
}
