/* ---------------------------------------------------------------------------
 * pa-kundengalerie.css - der Weg des Kunden.
 *
 * Codeeingabe -> Galerie -> Einzelbild -> Warenkorb -> Bestellung ->
 * Kundenkonto mit Bestellungen und Downloads.
 * --------------------------------------------------------------------------- */

/* ===========================================================================
 * 1. Codeeingabe
 *
 * Vorher: fuenf Elemente, jedes einzeln per `position: relative; top: 100px;
 * left: 45px` an seinen Platz geschoben, das Eingabefeld mit `width: 285px`
 * fest, und unter 500 px eine zweite Variante mit `position: absolute` plus
 * `visibility: hidden` fuer das Begruessungsbild. Nichts davon floss mit der
 * Fensterbreite.
 *
 * Jetzt: eine zentrierte Karte, die von 320 px bis zum Breitbild dieselbe
 * Ordnung behaelt.
 * ======================================================================== */

/* Die Codeeingabe soll ohne Scrollen ins Bild passen - samt Fusszeile.
 *
 * Der Inhaltsbereich bekommt die restliche Fensterhoehe ohnehin (body ist
 * eine Flexspalte, .pa-shell hat flex: 1). Hier wird der Inhalt darin
 * mittig gesetzt und die zusaetzliche Hoehe herausgenommen, die vorher aus
 * grosszuegigen Innenabstaenden kam.
 *
 * `:has()` statt einer eigenen Klasse an der Seite, weil das Markup der
 * Startseite (HomePage.html) drei Panels nebeneinander haelt und nicht weiss,
 * welches davon gerade sichtbar ist. */
.pa-shell:has(.pa-code) {
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding-block: var(--pa-space-4);
}

/* Eine mittige Spalte: Ueberschrift, ein Satz, Eingabefeld.
 *
 * Vorher zwei Spalten mit einer Strichfigur links. Die ist raus - sie
 * erklaerte nichts, was der Satz darueber nicht sagt, und nahm auf einem
 * niedrigen Notebookfenster so viel Hoehe, dass die Fusszeile aus dem Bild
 * rutschte. */
.pa-code {
	width: 100%;
	max-width: 480px;
	margin-inline: auto;
	text-align: center;
}

.pa-code__intro {
	margin-bottom: var(--pa-space-5);
}

.pa-code__intro h1 {
	font-size: clamp(1.5rem, 2.2vw + 0.6rem, 2.25rem);
	letter-spacing: -0.02em;
	margin-bottom: var(--pa-space-3);
}

.pa-code__intro p {
	margin: 0;
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-base);
	text-wrap: pretty;
}

.pa-code__card {
	padding: var(--pa-space-5);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius-lg);
	background: var(--pa-surface);
	box-shadow: var(--pa-shadow);
	text-align: left;
}

/* --- Die Strichfigur neben der Codeeingabe -------------------------------
 *
 * Sie haelt das Eingabefeld auf Handhoehe. Damit das in jedem Fenster
 * stimmt, haengt sie am FELD und nicht am Seitenrand:
 *
 *   top: 50%              -> Oberkante der Figur auf die Mitte des Feldes
 *   translateY(-27.9%)    -> um 27,9 % der EIGENEN Hoehe nach oben
 *
 * 27,9 % ist nachgemessen, nicht geschaetzt: im Bild (174x376) liegt die
 * erhobene Hand in der rechtesten Spalte zwischen y=86 und y=124, Mitte
 * also y=105 - das sind 27,9 % von 376. Nach der Verschiebung sitzt genau
 * dieser Punkt auf der Mitte des Eingabefeldes.
 *
 * `position: absolute` ist wichtig: die Figur ist 376 px hoch und wuerde im
 * Textfluss die Seite hoeher machen als das Fenster - die Codeeingabe soll
 * aber ohne Scrollen hineinpassen.
 * ---------------------------------------------------------------------- */

.pa-code__figur {
	display: none;
}

@media (min-width: 992px) {
	/* Die Gruppe aus Figur und Karte optisch mittig stellen.
	 *
	 * Die Karte allein war zentriert, die Figur hing links daneben - damit
	 * stand das Ganze sichtbar links aus der Mitte. Der Versatz betraegt die
	 * halbe Breite des Platzes, den die Figur einnimmt.
	 *
	 * `position: relative` und nicht `transform`: eine Transformation macht
	 * das Element zum Bezugsrahmen fuer `position: fixed` - genau daran waren
	 * Dialoge in einer klebenden Spalte schon einmal haengen geblieben. */
	.pa-code {
		position: relative;
		left: calc((174px + var(--pa-space-6)) / 2);
	}

	.pa-code__inputwrap {
		position: relative;
	}

	.pa-code__figur {
		display: block;
		position: absolute;
		/* Links neben der Karte: 100 % ist die linke Kante des Feldes, dazu
		 * der Innenabstand der Karte und ein Abstand zur Figur. */
		right: calc(100% + var(--pa-space-5) + var(--pa-space-6));
		/* Die Hoehe bezieht sich auf die Mitte des Eingabefeldes, weil die
		 * Huelle genau um das Feld liegt. */
		top: 50%;
		/* Bei niedrigen Fenstern mitschrumpfen, sonst verschwinden die Beine
		 * hinter der Fusszeile. Das Seitenverhaeltnis bleibt, und weil die
		 * Verschiebung in PROZENT der eigenen Hoehe rechnet, sitzt die Hand
		 * auch dann genau auf der Feldmitte. */
		height: min(376px, 44vh);
		aspect-ratio: 174 / 376;
		width: auto;
		transform: translateY(-27.9%);
		background: url(boxHolder.png) no-repeat center / contain;
		/* Sie ist Zierde - sie soll keine Klicks abfangen. */
		pointer-events: none;
	}
}

.pa-code__label {
	display: block;
	margin-bottom: var(--pa-space-2);
	color: var(--pa-navy);
	font-size: var(--pa-text-sm);
	font-weight: 600;
}

/* Das Eingabefeld ist das Herz der Startseite - es darf gross sein. Die
 * Sperrung und die Tabellenziffern machen die Gruppen des Codes
 * (XXXX-XXXX-XXXX) auf einen Blick unterscheidbar; `text-transform`
 * nimmt dem Kunden die Frage nach Gross- und Kleinschreibung ab. */
.pa-code__input {
	width: 100%;
	padding: var(--pa-space-3) var(--pa-space-4);
	border: 2px solid var(--pa-border-strong);
	border-radius: var(--pa-radius);
	background: var(--pa-surface);
	color: var(--pa-navy);
	font-family: var(--pa-font-mono);
	font-size: clamp(1.25rem, 4vw, 1.6rem);
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.06em;
	text-align: center;
	text-transform: uppercase;
	transition: border-color var(--pa-duration) var(--pa-ease),
	            box-shadow var(--pa-duration) var(--pa-ease);
}

.pa-code__input::placeholder {
	color: var(--pa-ink-muted);
	letter-spacing: 0.06em;
	text-transform: none;
	opacity: 0.7;
}

.pa-code__input:focus {
	outline: none;
	border-color: var(--pa-primary);
	box-shadow: 0 0 0 4px rgba(98, 196, 13, 0.22);
}

.pa-code__submit {
	width: 100%;
	margin-top: var(--pa-space-4);
	padding-block: var(--pa-space-3);
	font-size: var(--pa-text-lg);
}

.pa-code__foot {
	margin-top: var(--pa-space-4);
	padding-top: var(--pa-space-3);
	border-top: 1px solid var(--pa-border);
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
	text-align: center;
}

/* ===========================================================================
 * 2. Galerieraster
 *
 * Vorher: `col-md-3 col-sm-3 col-xs-4` plus jQuery Isotope, das die Kacheln
 * nach `imagesLoaded` per JavaScript absolut positionierte - daher das
 * Nachrucken beim Laden. Isotope ist raus; CSS Grid steht vor dem ersten
 * Bild.
 *
 * ZUR DARSTELLUNG DER FOTOS
 *
 * Die Kacheln fuellen sich vollflaechig (`cover`) und tragen keinen eigenen
 * Rahmen. Der erste Entwurf hatte weisse Kaertchen mit Rand, Innenabstand
 * und `contain` - das war nachvollziehbar (nichts wird abgeschnitten), sah
 * aber aus wie eine Tabelle mit Bildern darin: jedes Foto sass in einem
 * Kasten mit grauen Streifen ueber und unter sich.
 *
 * Beschneiden ist vertretbar, weil das ganze Bild einen Klick entfernt in
 * der Grossansicht steht. Der Bildausschnitt sitzt bei 40 Prozent Hoehe und
 * nicht mittig: auf Portraits und Gruppenbildern sind die Gesichter im
 * oberen Drittel, ein mittiger Ausschnitt schneidet Koepfe an.
 * ======================================================================== */

.pa-gallery {
	--pa-tile: 220px;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(var(--pa-tile), 1fr));
	/* Enge Fugen: die Fotos sollen als Flaeche wirken, nicht als Liste. */
	gap: var(--pa-space-2);
	margin: 0 0 var(--pa-space-5);
	padding: 0;
	list-style: none;
}

@media (max-width: 767.98px) {
	.pa-gallery {
		--pa-tile: 150px;
		gap: var(--pa-space-1);
	}
}

@media (max-width: 400px) {
	/* Zwei Spalten auf dem schmalsten Telefon - drei waeren rund 100 px
	 * pro Bild und damit zum Aussuchen unbrauchbar. */
	.pa-gallery {
		--pa-tile: 130px;
	}
}

.pa-tile {
	position: relative;
	display: block;
	overflow: hidden;
	border-radius: var(--pa-radius-sm);
	/* Heller Platzhalter, nicht dunkel: solange ein Bild noch laedt - oder
	 * wenn es einmal fehlt - sieht eine hellgraue Flaeche nach "kommt noch"
	 * aus, eine dunkle nach Loch im Raster. */
	background: var(--pa-surface-sunken);
	cursor: pointer;
}

/* --- Bildverwaltung: Auswahlmodus im Raster ------------------------------
 *
 * Der Fotograf der Galerie und der eingetragene Bildverwalter koennen Bilder
 * entfernen. Vorher ging das nur Bild fuer Bild ueber die Einzelbildseite;
 * hier markiert ein Klick die Kachel, und die Leiste darueber entfernt die
 * ganze Auswahl.
 * ---------------------------------------------------------------------- */

.pa-manage {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--pa-space-3);
	margin-bottom: var(--pa-space-4);
	padding: var(--pa-space-3) var(--pa-space-4);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius-sm);
	background: var(--pa-surface-sunken);
}

.pa-manage__optionen {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--pa-space-3);
}

.pa-manage__anzahl {
	font-weight: 600;
	color: var(--pa-navy);
	font-variant-numeric: tabular-nums;
}

.pa-manage__link {
	color: var(--pa-link);
	font-size: var(--pa-text-sm);
	cursor: pointer;
}

.pa-manage__seitengroesse {
	display: flex;
	align-items: center;
	gap: var(--pa-space-2);
	color: var(--pa-text-muted);
	font-size: var(--pa-text-sm);
}

.pa-manage__seitengroesse .pa-manage__link {
	padding-inline: var(--pa-space-2);
	border-radius: var(--pa-radius-sm);
}

.pa-manage__seitengroesse .pa-manage__link.is-active {
	background: var(--pa-navy);
	color: #fff;
	font-weight: 600;
	text-decoration: none;
}

/* Der Auswahlhaken sitzt auf der Kachel und ist nur im Verwaltungsmodus
 * sichtbar. Ausserhalb des Modus soll die Galerie unveraendert aussehen. */
.pa-tile__wahl {
	position: absolute;
	top: var(--pa-space-2);
	left: var(--pa-space-2);
	z-index: 2;
	display: none;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	border: 2px solid #fff;
	border-radius: var(--pa-radius-sm);
	background: rgba(15, 23, 32, 0.35);
	color: transparent;
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
}

.pa-gallery--verwalten .pa-tile__wahl {
	display: flex;
}

/* Gewaehlte Kachel: Haken sichtbar, Bild leicht zurueckgenommen - damit die
 * Auswahl auch bei vielen Kacheln auf einen Blick erkennbar ist. */
.pa-gallery--verwalten .pa-tile.is-gewaehlt .pa-tile__wahl {
	background: var(--pa-primary);
	border-color: #fff;
	color: #fff;
}

.pa-gallery--verwalten .pa-tile.is-gewaehlt .pa-tile__frame {
	outline: 3px solid var(--pa-primary);
	outline-offset: -3px;
}

.pa-gallery--verwalten .pa-tile.is-gewaehlt .pa-tile__frame img {
	opacity: 0.75;
}

/* Im Verwaltungsmodus fuehrt der Klick nicht zur Grossansicht - die Lupe
 * waere dort eine falsche Ansage. */
.pa-gallery--verwalten .pa-tile__zoom {
	display: none;
}

/* --- Bildverwaltung in der Grossansicht --------------------------------- */

.pa-viewer__verwaltung {
	flex: none;
	display: flex;
	justify-content: flex-end;
	padding: var(--pa-space-2) var(--pa-space-5);
	border-top: 1px solid var(--pa-border);
}

.pa-tile__frame {
	/* display: block ist Pflicht, nicht Kosmetik: der Rahmen ist ein <span>
	 * in einem <a>, und auf einem Inline-Element wirkt `aspect-ratio` nicht.
	 * Ohne die Zeile hat der Kasten die Hoehe 0 und das Raster besteht aus
	 * duennen Strichen. */
	display: block;
	position: relative;
	/* 3:2, und das ist nachgemessen.
	 *
	 * Die Kacheln zeigen das Bild VOLLSTAENDIG (object-fit: contain, siehe
	 * unten); damit entscheidet die Kastenform, wie viel Flaeche ein Motiv
	 * bekommt und wie viel leer bleibt. Erhoben an 72 Bildern aus vier
	 * Kundengalerien: 58 liegend (3:2 und 16:9), 14 stehend (2:3), kein
	 * einziges quadratisches. Im Mittel genutzte Kastenflaeche:
	 *
	 *     3:2  88 %      4:3  81 %      5:4  77 %      1:1  66 %
	 *
	 * 3:2 ist zugleich das Format, in dem die Kameras liefern - die
	 * Mehrheit der Bilder fuellt den Kasten damit fast genau aus, und die
	 * stehenden bleiben trotzdem vollstaendig zu sehen. */
	aspect-ratio: 3 / 2;
	/* Der Grund hinter dem Bild. Wo das Motiv den Kasten nicht ausfuellt,
	 * soll die freie Flaeche wie ein Passepartout wirken und nicht wie ein
	 * Ladefehler. */
	background: var(--pa-surface-sunken);
	overflow: hidden;
}

/* Die Huelle, die das FotoAnzeigePanel um das Bild legt, muss die Flaeche
 * vollstaendig einnehmen. */
.pa-tile__frame > * {
	display: block;
	position: absolute;
	inset: 0;
}

.pa-tile__frame img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	/* VOLLSTAENDIG statt beschnitten.
	 *
	 * Vorher stand hier `cover` mit `object-position: center 40%` - das
	 * fuellte den Kasten lueckenlos und schnitt dafuer ab, was nicht
	 * hineinpasste. Bei einem Fotostreifen war anschliessend nicht mehr zu
	 * erkennen, DASS es einer ist: zu sehen war ein beliebiger Ausschnitt
	 * daraus. Wer in einer Galerie sucht, muss aber das Bildformat
	 * erkennen. Also `contain`: das Seitenverhaeltnis bleibt, das ganze
	 * Motiv ist zu sehen, und die freie Flaeche traegt den Grund des
	 * Rahmens. */
	object-fit: contain;
	transition: transform var(--pa-duration-slow) var(--pa-ease),
	            filter var(--pa-duration) var(--pa-ease);
}

/* Beim Zeigen rueckt das Bild leicht heran. Kein Rahmenwechsel, kein
 * Anheben der Kachel - in einem engen Raster wirkt beides unruhig. */
.pa-tile:hover .pa-tile__frame img,
.pa-tile:focus-visible .pa-tile__frame img {
	transform: scale(1.04);
}

/* Eine Lupe erscheint beim Zeigen: sie sagt, dass ein Klick das Bild gross
 * macht. Der Farbverlauf darunter haelt sie auf jedem Motiv lesbar. */
.pa-tile::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background:
		linear-gradient(to top, rgba(15, 23, 32, 0.45), rgba(15, 23, 32, 0) 45%);
	opacity: 0;
	transition: opacity var(--pa-duration) var(--pa-ease);
	pointer-events: none;
}

.pa-tile:hover::after,
.pa-tile:focus-visible::after {
	opacity: 1;
}

.pa-tile__zoom {
	position: absolute;
	right: var(--pa-space-2);
	bottom: var(--pa-space-2);
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: var(--pa-radius-pill);
	background: rgba(255, 255, 255, 0.92);
	color: var(--pa-navy);
	opacity: 0;
	transform: translateY(4px);
	transition: opacity var(--pa-duration) var(--pa-ease),
	            transform var(--pa-duration) var(--pa-ease);
	pointer-events: none;
}

.pa-tile:hover .pa-tile__zoom,
.pa-tile:focus-visible .pa-tile__zoom {
	opacity: 1;
	transform: translateY(0);
}

/* Auf Touchgeraeten gibt es kein "Zeigen" - dort steht die Lupe dauerhaft,
 * aber dezent. */
@media (hover: none) {
	.pa-tile__zoom {
		opacity: 0.85;
		transform: none;
	}
}

.pa-tile__caption {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 1;
	display: block;
	padding: var(--pa-space-4) var(--pa-space-3) var(--pa-space-2);
	background: linear-gradient(to top, rgba(15, 23, 32, 0.85), rgba(15, 23, 32, 0));
	color: #fff;
	font-size: var(--pa-text-sm);
	font-weight: 600;
	text-align: center;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Unterordner (Klassen, Kinder, Gruppen): groessere Kacheln, weil hier eine
 * Beschriftung dazugehoert. */
.pa-folders {
	--pa-tile: 240px;
	gap: var(--pa-space-3);
}

.pa-folders .pa-tile__frame img {
	object-position: center 35%;
}

/* ===========================================================================
 * 3. Ordnerauswahl ueber der Galerie
 *
 * Bei Schul- und Kindergartenfotografie stehen hier die Klassen bzw. die
 * Namen der Kinder. Vorher: eine nackte Auswahlliste zwischen zwei leeren
 * Bootstrap-Spalten, die nur ein &nbsp; enthielten, um sie in die Mitte zu
 * druecken - ohne Beschriftung, ohne Rahmen, ohne Hinweis darauf, was sie
 * auswaehlt.
 * ======================================================================== */

.pa-folder-select {
	margin-bottom: var(--pa-space-4);
}

.pa-folder-select__form {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--pa-space-3);
	width: fit-content;
	max-width: 100%;
	margin-inline: auto;
	padding: var(--pa-space-2) var(--pa-space-3);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius-pill);
	background: var(--pa-surface);
	box-shadow: var(--pa-shadow-sm);
}

.pa-folder-select__label {
	display: inline-flex;
	align-items: center;
	gap: var(--pa-space-2);
	margin: 0;
	padding-left: var(--pa-space-2);
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
	font-weight: 600;
	white-space: nowrap;
}

.pa-folder-select__input {
	flex: 1 1 200px;
	min-width: 0;
	max-width: 380px;
	border-color: transparent;
	background-color: var(--pa-surface-sunken);
	border-radius: var(--pa-radius-pill);
	color: var(--pa-navy);
	font-weight: 600;
}

.pa-folder-select__input:focus {
	background-color: var(--pa-surface);
}

@media (max-width: 575.98px) {
	/* Auf dem Telefon die volle Breite: eine mittige Pille mit langen
	 * Kindernamen darin wird sonst breiter als das Fenster. */
	.pa-folder-select__form {
		width: 100%;
		border-radius: var(--pa-radius);
	}

	.pa-folder-select__input {
		flex: 1 1 100%;
		max-width: none;
	}
}

/* ===========================================================================
 * 4. Einzelbild
 * ======================================================================== */

.pa-photo {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
	align-items: start;
	gap: var(--pa-space-6);
}

@media (max-width: 991.98px) {
	.pa-photo {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--pa-space-5);
	}
}

/* Das Grid-Kind braucht min-width: 0, sonst sprengt ein breites Bild oder
 * eine breite Tabelle darin die Spalte und die Seite scrollt waagerecht. */
.pa-photo__main {
	min-width: 0;
}

.pa-photo__stage {
	position: relative;
	overflow: hidden;
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius-lg);
	background: var(--pa-surface);
	box-shadow: var(--pa-shadow-sm);
}

/* Das Motiv bekommt reichlich Raum, wird aber nie so hoch, dass die
 * Artikelauswahl daneben aus dem Bild rutscht. */
.pa-photo__stage img {
	display: block;
	width: 100%;
	max-height: min(72vh, 780px);
	object-fit: contain;
	margin-inline: auto;
	background: var(--pa-surface-sunken);
}

.pa-photo__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: center;
	gap: var(--pa-space-1) var(--pa-space-3);
	padding: var(--pa-space-3) var(--pa-space-4);
	border-top: 1px solid var(--pa-border);
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
}

/* Ohne Inhalt kein Streifen.
 *
 * Zeigt der Fotograf keine Bildnummern an und hat kein oeffentliches Profil,
 * blieben Innenabstand und Trennlinie als leere Zeile unter dem Bild stehen.
 * `:empty` greift hier nicht - der Kasten enthaelt Leerraum aus dem Markup,
 * nur keine Elemente. Ohne `:has()` bleibt es beim leeren Streifen. */
.pa-photo__meta:not(:has(*)) {
	display: none;
}

.pa-photo__id {
	font-variant-numeric: tabular-nums;
	font-weight: 600;
	color: var(--pa-navy);
}

/* Sammelbestellungshinweis: Symbol links, Text und Anschrift daneben.
 * Die Anschrift steht in einem <address> - das kommt vom Browser kursiv und
 * mit Abstand nach unten, beides hier unerwuenscht. */
.pa-sammelbestellung {
	display: flex;
	gap: var(--pa-space-3);
}

.pa-sammelbestellung address {
	margin: var(--pa-space-1) 0 0;
	font-style: normal;
}

/* Blaettern zwischen den Bildern: gross genug fuer den Daumen und immer
 * an derselben Stelle. */
.pa-photo__nav {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--pa-space-3);
	margin-bottom: var(--pa-space-4);
}

/* Die Artikelspalte klebt ABSICHTLICH NICHT.
 *
 * Ein erster Entwurf hatte hier `position: sticky`, damit die Artikelliste
 * beim Scrollen stehen bleibt. Das hat den Bildzuschnitt unbenutzbar
 * gemacht: sticky bildet einen eigenen Stapelkontext, und die Modals der
 * Artikelauswahl (Bildzuschnitt, Produktsatzkonfiguration) liegen darin.
 * Der Abdunkler, den Bootstrap an den body haengt, lag damit UEBER dem
 * Dialog - die Knoepfe "Abbrechen" und "Ausschnitt waehlen" waren nicht
 * anklickbar, und damit liess sich fuer jedes Produkt mit abweichendem
 * Seitenverhaeltnis nichts mehr in den Warenkorb legen.
 *
 * Die Modals stattdessen an den body zu verschieben waere die andere
 * Loesung - aber Wicket rendert ihre Elternkomponente per AJAX neu und
 * wuerde das Element erneut anlegen, mit derselben Kennung an zwei Stellen.
 * Die Artikelliste ist ohnehin lang; nicht zu kleben kostet hier wenig. */
.pa-photo__sidebar {
	position: static;
}

/* Kurze Rueckmeldung nach dem Hinzufuegen in den Warenkorb. Vorher lag die
 * per `position: absolute; top: 0` fest 300 px breit ueber dem Seitenkopf. */
.pa-flash {
	position: fixed;
	left: 50%;
	top: calc(var(--pa-header-height) + var(--pa-space-3));
	z-index: calc(var(--pa-z-header) + 1);
	transform: translateX(-50%);
	width: min(420px, calc(100vw - 2 * var(--pa-space-4)));
	box-shadow: var(--pa-shadow-lg);
}

/* ===========================================================================
 * 5. Artikelauswahl
 * ======================================================================== */

.pa-articles .card + .card {
	margin-top: var(--pa-space-3);
}

.pa-article {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: center;
	gap: var(--pa-space-3);
	padding: var(--pa-space-4) 0;
	border-bottom: 1px solid var(--pa-border);
}

.pa-article:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

.pa-article__name {
	display: block;
	color: var(--pa-navy);
	font-weight: 600;
}

.pa-article__price {
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
	font-variant-numeric: tabular-nums;
}

.pa-article__tiers {
	margin-top: var(--pa-space-2);
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
}

.pa-article__tiers-title {
	display: block;
}

/* Staffelpreise als kleine Marken. Vorher standen sie untereinander, jeweils
 * mit einem <br/> abgeschlossen - bei fuenf Staffeln machte das die
 * Artikelzeile hoeher als das Motiv daneben. */
.pa-article__tier {
	display: inline-block;
	margin: var(--pa-space-1) var(--pa-space-1) 0 0;
	padding: 0.1em 0.55em;
	border-radius: var(--pa-radius-sm);
	background: var(--pa-surface-sunken);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

@media (max-width: 400px) {
	.pa-article {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Mengenwahl: minus, Zahl, plus. Die Trefferflaechen sind 44 px, damit sie
 * auf dem Telefon zu bedienen sind. */
.pa-qty {
	display: inline-flex;
	align-items: stretch;
	border: 1px solid var(--pa-border-strong);
	border-radius: var(--pa-radius-sm);
	overflow: hidden;
	background: var(--pa-surface);
}

.pa-qty button {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	min-height: 44px;
	padding: 0;
	border: 0;
	background: var(--pa-surface-sunken);
	color: var(--pa-navy);
	cursor: pointer;
	transition: background-color var(--pa-duration) var(--pa-ease);
}

.pa-qty button:hover {
	background: var(--pa-border);
}

.pa-qty input {
	width: 56px;
	min-height: 44px;
	border: 0;
	border-inline: 1px solid var(--pa-border-strong);
	background: var(--pa-surface);
	color: var(--pa-navy);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	text-align: center;
}

.pa-qty input:focus {
	outline: none;
	background: var(--pa-accent-soft);
}

/* ===========================================================================
 * 6. Warenkorb
 * ======================================================================== */

.pa-cart-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 340px);
	align-items: start;
	gap: var(--pa-space-6);
}

@media (max-width: 991.98px) {
	.pa-cart-layout {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--pa-space-5);
	}
}

/* Hier ist sticky unbedenklich, weil in dieser Spalte KEIN Modal steckt.
 * Wer eines hinzufuegt, muss das Kleben entfernen - siehe die Begruendung
 * bei .pa-photo__sidebar. */
.pa-cart-summary {
	position: sticky;
	top: calc(var(--pa-header-height) + var(--pa-space-4));
	padding: var(--pa-space-5);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius);
	background: var(--pa-surface);
	box-shadow: var(--pa-shadow-sm);
}

@media (max-width: 991.98px) {
	.pa-cart-summary {
		position: static;
	}
}

.pa-cart-summary__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--pa-space-3);
	padding-block: var(--pa-space-2);
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
}

.pa-cart-summary__row--total {
	margin-top: var(--pa-space-2);
	padding-top: var(--pa-space-3);
	border-top: 2px solid var(--pa-border);
	color: var(--pa-navy);
	font-size: var(--pa-text-lg);
	font-weight: 700;
}

.pa-cart-summary__row .pa-num {
	color: var(--pa-navy);
	font-weight: 600;
}

.pa-cart-summary__cta {
	width: 100%;
	margin-bottom: var(--pa-space-4);
	padding-block: var(--pa-space-3);
	font-size: var(--pa-text-base);
}

.pa-coupon {
	display: flex;
	gap: var(--pa-space-2);
	margin-top: var(--pa-space-4);
	padding-top: var(--pa-space-4);
	border-top: 1px solid var(--pa-border);
}

.pa-coupon input {
	flex: 1 1 auto;
	min-width: 0;
}

/* --- Positionen im Warenkorb ---------------------------------------------
 *
 * Vorher eine Tabelle mit festen Prozentbreiten, die auf dem Telefon
 * gequetscht wurde. Jetzt ein Raster mit benannten Feldern: unter 640 px
 * wechselt die ANORDNUNG, statt dass die Spalten schmaler werden.
 * ---------------------------------------------------------------------- */

.pa-cart-items {
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius);
	background: var(--pa-surface);
	box-shadow: var(--pa-shadow-sm);
	overflow: hidden;
}

.pa-cart-item {
	display: grid;
	grid-template-columns: 88px minmax(0, 1fr) auto auto auto;
	grid-template-areas:
		"thumb body  qty   price remove"
		"thumb extra extra extra extra";
	align-items: center;
	gap: var(--pa-space-2) var(--pa-space-4);
	padding: var(--pa-space-4);
	border-bottom: 1px solid var(--pa-border);
}

.pa-cart-item:last-child {
	border-bottom: 0;
}

.pa-cart-item__thumb   { grid-area: thumb; align-self: start; }
.pa-cart-item__body    { grid-area: body; min-width: 0; }
.pa-cart-item__extra   { grid-area: extra; min-width: 0; }
.pa-cart-item__qty     { grid-area: qty; }
.pa-cart-item__price   { grid-area: price; }
.pa-cart-item__remove-cell { grid-area: remove; display: flex; }

.pa-cart-item__thumb {
	display: block;
	overflow: hidden;
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius-sm);
	background: var(--pa-surface-sunken);
}

.pa-cart-item__thumb img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: contain;
}

.pa-cart-item__title {
	margin: 0 0 var(--pa-space-1);
	font-size: var(--pa-text-base);
	font-weight: 600;
	color: var(--pa-navy);
}

.pa-cart-item__detail {
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
}

/* Leer, solange die Position kein Produktsatz und kein Ausweis ist - dann
 * soll das Feld auch keinen Abstand erzeugen. */
.pa-cart-item__extra:empty {
	display: none;
}

.pa-cart-item__remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: var(--pa-radius-sm);
	color: var(--pa-ink-muted);
	transition: background-color var(--pa-duration) var(--pa-ease),
	            color var(--pa-duration) var(--pa-ease);
}

.pa-cart-item__remove:hover {
	background: var(--pa-danger-bg);
	color: var(--pa-danger);
	text-decoration: none;
}

@media (max-width: 639.98px) {
	.pa-cart-item {
		grid-template-columns: 72px minmax(0, 1fr) auto;
		grid-template-areas:
			"thumb body  remove"
			"extra extra extra"
			"qty   price price";
		gap: var(--pa-space-3);
		padding: var(--pa-space-3);
	}

	.pa-cart-item__price {
		text-align: right;
		align-self: center;
	}
}

/* Summe unter der Liste. */
.pa-cart-total {
	display: flex;
	align-items: baseline;
	justify-content: flex-end;
	gap: var(--pa-space-3);
	margin-top: var(--pa-space-4);
	padding: var(--pa-space-4);
	border-radius: var(--pa-radius);
	background: var(--pa-surface-sunken);
	color: var(--pa-navy);
	font-size: var(--pa-text-lg);
	font-weight: 700;
}

/* Kopf der Warenkorbseite: Ueberschrift und Rueckweg zur Galerie. */
.pa-cart-header {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--pa-space-3);
	margin-bottom: var(--pa-space-5);
}

.pa-cart-header .pa-page-title {
	display: flex;
	align-items: center;
	gap: var(--pa-space-3);
	margin-bottom: 0;
}

/* Der Balken unter der Ueberschrift stoert, wenn rechts daneben ein Knopf
 * steht - er zoege eine Linie ins Nichts. */
.pa-cart-header .pa-page-title::after {
	display: none;
}

.pa-cart-layout__main {
	min-width: 0;
}

.pa-cart-actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--pa-space-3);
	margin-top: var(--pa-space-4);
}

/* Kostenloser Versand ist eine gute Nachricht - sie darf als solche
 * aussehen und nicht wie ein Betrag. */
.pa-free-shipping {
	color: var(--pa-success);
	font-weight: 600;
}

.pa-minicart__meta {
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
	font-variant-numeric: tabular-nums;
}

/* --- Warenkorbauszug in der Kopfleiste ----------------------------------- */

.pa-minicart {
	margin: 0;
	padding: 0;
	list-style: none;
}

.pa-minicart__item {
	display: grid;
	grid-template-columns: 48px minmax(0, 1fr) auto;
	align-items: center;
	gap: var(--pa-space-3);
	padding: var(--pa-space-3) var(--pa-space-4);
	border-bottom: 1px solid var(--pa-border);
}

.pa-minicart__item img {
	display: block;
	width: 48px;
	aspect-ratio: 1 / 1;
	object-fit: contain;
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius-sm);
	background: var(--pa-surface-sunken);
}

.pa-minicart__title {
	margin: 0;
	font-size: var(--pa-text-sm);
	font-weight: 600;
	color: var(--pa-navy);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.pa-minicart__foot {
	padding: var(--pa-space-4);
	background: var(--pa-surface-sunken);
	border-top: 1px solid var(--pa-border);
}

.pa-minicart__total {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	margin-bottom: var(--pa-space-3);
	color: var(--pa-navy);
	font-weight: 700;
}

.pa-minicart__empty {
	padding: var(--pa-space-5) var(--pa-space-4);
	color: var(--pa-ink-soft);
	text-align: center;
}

/* ===========================================================================
 * 7. Bestellabschluss
 * ======================================================================== */

.pa-checkout {
	/* Der Bestellabschluss nimmt die Breite des Inhaltsbereichs.
	 *
	 * Vorher stand hier `max-width: 860px`: gedacht als Lesebreite fuer ein
	 * Formular, tatsaechlich sass der ganze Abschluss damit als schmale
	 * Saeule mitten auf einem 1600 px breiten Fenster - Adressen,
	 * Warenkorbzusammenfassung und Bestaetigung gequetscht, links und rechts
	 * je 354 px leer.
	 *
	 * Die Lesebreite gehoert nicht an die Seite, sondern an die einzelnen
	 * Bloecke: die Adressformulare sind unten begrenzt, damit dort keine
	 * 700 px breiten Eingabefelder stehen. */
	margin-inline: auto;
}

.pa-checkout .card + .card {
	margin-top: var(--pa-space-4);
}

/* Zwei Spalten auf breiten Fenstern: links die Eingaben, rechts die
 * Bestellschiene (Zusammenfassung und Abschluss).
 *
 * KEIN `position: sticky` an der Schiene, obwohl es hier naheliegt: darin
 * steckt der AGB-Dialog. Ein klebender Kasten bildet einen eigenen
 * Stapelkontext, und ein Modal darin landet unter dem Abdunkler und ist
 * nicht mehr bedienbar - genau der Fehler, der beim Bildzuschnitt in der
 * Seitenspalte des Einzelbildes schon einmal auftrat. */
@media (min-width: 1200px) {
	.pa-checkout > form {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(360px, 460px);
		gap: var(--pa-space-5);
		align-items: start;
	}

	.pa-checkout__meldungen {
		grid-column: 1 / -1;
	}

	.pa-checkout__eingaben > * + * {
		margin-top: var(--pa-space-4);
	}
}

/* Unterhalb von 1200 px stehen die Bloecke untereinander; die Abstaende
 * kommen dann aus der Kartenregel oben, die Huellen brauchen ihre eigenen. */
.pa-checkout__eingaben + .pa-checkout__schiene {
	margin-top: var(--pa-space-4);
}

/* Adressen nebeneinander, auf dem Telefon untereinander.
 *
 * Die Spalten wachsen nicht ins Unendliche: ein Adressformular ist ab etwa
 * 520 px nicht mehr besser lesbar, nur breiter. */
.pa-address-pair {
	display: grid;
	/* 480 und nicht 520: die linke Spalte des Abschlusses ist rund 1030 px
	 * breit, und zwei 520er Spalten plus Abstand brauchen 1064 - es passte
	 * damit nur eine, und die Wahl der Lieferadresse rutschte unter das
	 * Formular. */
	grid-template-columns: repeat(auto-fit, minmax(260px, 480px));
	gap: var(--pa-space-5);
}

/* Ueberschrift eines Adressblocks (Rechnungs- bzw. Lieferadresse) und das
 * Auswahlfeld darunter - siehe AddressChoosingPanel.html. */
.pa-address-head {
	margin-bottom: var(--pa-space-2);
	color: var(--pa-navy);
	font-size: var(--pa-text-base);
}

.pa-address-choose {
	margin-bottom: var(--pa-space-4);
}

/* Ohne bestehende Adressen ist das Auswahlfeld unsichtbar; dann darf der
 * Abstand nicht stehen bleiben. */
.pa-address-choose:empty {
	margin-bottom: 0;
}

.pa-address {
	padding: var(--pa-space-4);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius-sm);
	background: var(--pa-surface-sunken);
}

.pa-address address {
	margin: 0;
	font-style: normal;
	line-height: 1.6;
}

/* Zahlungsart: die Auswahl als anklickbare Flaechen, nicht als winziger
 * Radioknopf mit Text daneben. */
.pa-payment-options {
	display: grid;
	gap: var(--pa-space-3);
}

.pa-payment-option {
	display: flex;
	align-items: flex-start;
	gap: var(--pa-space-3);
	padding: var(--pa-space-4);
	border: 1px solid var(--pa-border-strong);
	border-radius: var(--pa-radius-sm);
	background: var(--pa-surface);
	cursor: pointer;
	transition: border-color var(--pa-duration) var(--pa-ease),
	            background-color var(--pa-duration) var(--pa-ease);
}

.pa-payment-option:hover {
	border-color: var(--pa-primary);
	background: var(--pa-accent-soft);
}

.pa-payment-option input {
	margin-top: 0.2em;
	flex: none;
}

.pa-payment-option:has(input:checked) {
	border-color: var(--pa-primary);
	border-width: 2px;
	background: var(--pa-accent-soft);
}

/* Zustimmungen. Die Trefferflaeche ist die ganze Zeile, nicht nur das
 * 13 px kleine Kaestchen. */
.pa-consent {
	display: flex;
	align-items: flex-start;
	gap: var(--pa-space-3);
	padding: var(--pa-space-3);
	border-radius: var(--pa-radius-sm);
	cursor: pointer;
}

.pa-consent:hover {
	background: var(--pa-surface-sunken);
}

.pa-consent input {
	flex: none;
	width: 1.15em;
	height: 1.15em;
	margin-top: 0.2em;
}

.pa-checkout__submit {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	gap: var(--pa-space-3);
	margin-top: var(--pa-space-4);
}

@media (max-width: 575.98px) {
	.pa-checkout__submit .btn {
		width: 100%;
	}
}

/* ===========================================================================
 * 8. Kundenkonto: Bestellungen, Downloads, Galerielisten
 *
 * Diese Ansichten waren Tabellen mit festen Pixel- und Prozentbreiten. Auf
 * dem Telefon wurden sie gequetscht - `table-responsive` stand am <table>
 * statt am Rahmen darum und hatte deshalb keine Wirkung.
 *
 * Unter 640 px wird jede Zeile zu einer Karte. Die Spaltenbeschriftung
 * kommt aus `data-label` im Markup, damit ohne Kopfzeile klar bleibt, was
 * ein Wert bedeutet.
 * ======================================================================== */

.pa-datatable {
	width: 100%;
	margin: 0;
	border-collapse: collapse;
}

.pa-datatable th,
.pa-datatable td {
	padding: var(--pa-space-3) var(--pa-space-4);
	text-align: left;
	vertical-align: middle;
	border-bottom: 1px solid var(--pa-border);
}

.pa-datatable thead th {
	background: var(--pa-surface-sunken);
	color: var(--pa-navy);
	font-size: var(--pa-text-sm);
	font-weight: 600;
	white-space: nowrap;
}

.pa-datatable tbody tr:hover {
	background: var(--pa-surface-sunken);
}

.pa-datatable tbody tr:last-child td {
	border-bottom: 0;
}

@media (max-width: 639.98px) {
	.pa-datatable thead {
		display: none;
	}

	.pa-datatable,
	.pa-datatable tbody,
	.pa-datatable tr,
	.pa-datatable td {
		display: block;
		width: 100%;
	}

	.pa-datatable tr {
		margin-bottom: var(--pa-space-3);
		border: 1px solid var(--pa-border);
		border-radius: var(--pa-radius);
		background: var(--pa-surface);
		box-shadow: var(--pa-shadow-sm);
		overflow: hidden;
	}

	.pa-datatable tbody tr:hover {
		background: var(--pa-surface);
	}

	.pa-datatable td {
		display: flex;
		align-items: baseline;
		justify-content: space-between;
		gap: var(--pa-space-4);
		padding: var(--pa-space-3) var(--pa-space-4);
		text-align: right;
	}

	.pa-datatable td::before {
		content: attr(data-label);
		flex: none;
		color: var(--pa-ink-soft);
		font-size: var(--pa-text-sm);
		font-weight: 600;
		text-align: left;
	}

	/* Zellen ohne Beschriftung (Vorschaubild, Aktionsknopf) nehmen die
	 * ganze Breite und werden nicht als Wertpaar dargestellt. */
	.pa-datatable td[data-label=""],
	.pa-datatable td:not([data-label]) {
		justify-content: center;
		text-align: center;
	}

	.pa-datatable td[data-label=""]::before,
	.pa-datatable td:not([data-label])::before {
		content: none;
	}
}

/* Statusmarkierung einer Bestellung. */
.pa-status {
	display: inline-flex;
	align-items: center;
	gap: var(--pa-space-2);
	padding: 0.2em 0.7em;
	border-radius: var(--pa-radius-pill);
	background: var(--pa-surface-sunken);
	border: 1px solid var(--pa-border);
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
	font-weight: 600;
	white-space: nowrap;
}

/* --- Galerielisten (oeffentliche Liste, besuchte Galerien) --------------- */

.pa-gallerylist {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
	gap: var(--pa-space-4);
	margin: 0;
	padding: 0;
	list-style: none;
}

.pa-gallerycard {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius);
	background: var(--pa-surface);
	box-shadow: var(--pa-shadow-sm);
	transition: transform var(--pa-duration) var(--pa-ease),
	            box-shadow var(--pa-duration) var(--pa-ease),
	            border-color var(--pa-duration) var(--pa-ease);
}

.pa-gallerycard:hover {
	transform: translateY(-2px);
	border-color: var(--pa-accent);
	box-shadow: var(--pa-shadow);
}

.pa-gallerycard__preview {
	display: block;
	aspect-ratio: 4 / 3;
	background: var(--pa-surface-sunken);
}

.pa-gallerycard__preview img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.pa-gallerycard__body {
	padding: var(--pa-space-4);
}

.pa-gallerycard__title {
	margin: 0 0 var(--pa-space-1);
	font-size: var(--pa-text-base);
	font-weight: 600;
	color: var(--pa-navy);
}

.pa-gallerycard__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--pa-space-1) var(--pa-space-3);
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
}

.pa-gallerycard__code {
	font-family: var(--pa-font-mono);
	font-weight: 600;
	letter-spacing: 0.04em;
}

/* --- Downloads ---------------------------------------------------------- */

.pa-download-link {
	display: inline-flex;
	align-items: center;
	gap: var(--pa-space-2);
	padding: var(--pa-space-2) var(--pa-space-3);
	border: 1px solid var(--pa-border-strong);
	border-radius: var(--pa-radius-sm);
	color: var(--pa-navy);
	font-weight: 600;
	font-size: var(--pa-text-sm);
}

.pa-download-link:hover {
	border-color: var(--pa-primary);
	background: var(--pa-accent-soft);
	color: var(--pa-navy);
	text-decoration: none;
}

/* ===========================================================================
 * 9. Leere Zustaende
 * ======================================================================== */

.pa-empty {
	padding: var(--pa-space-7) var(--pa-space-5);
	border: 1px dashed var(--pa-border-strong);
	border-radius: var(--pa-radius);
	background: var(--pa-surface);
	color: var(--pa-ink-soft);
	text-align: center;
}

.pa-empty h3 {
	margin-bottom: var(--pa-space-2);
}

/* ===========================================================================
 * 10. Anmelden, Registrieren, Passwort vergessen
 *
 * Uebernommen aus ownstyle.css und auf die Tokens umgestellt. Die drei
 * Seiten teilen sich eine Karte in halber Spaltenbreite. Der Login war
 * einmal ein grauer btn-default zwischen zwei nackten Textlinks und damit
 * optisch schwaecher als die Nebenwege; die Primaeraktion traegt seither die
 * volle Breite und die Nebenwege ordnen sich unter. Das bleibt so.
 * ======================================================================== */

.auth-card {
	padding: var(--pa-space-5) var(--pa-space-5) var(--pa-space-4);
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius);
	background: var(--pa-surface);
	box-shadow: var(--pa-shadow-sm);
	margin-bottom: var(--pa-space-5);
}

.auth-intro {
	color: var(--pa-ink-soft);
	margin-bottom: var(--pa-space-5);
}

.auth-card .form-label,
.auth-card .col-form-label {
	color: var(--pa-navy);
	font-weight: 600;
}

.auth-submit {
	width: 100%;
	margin-top: var(--pa-space-4);
	padding-block: var(--pa-space-3);
	font-weight: 600;
}

.auth-links {
	text-align: center;
	margin-top: var(--pa-space-4);
	padding-top: var(--pa-space-4);
	border-top: 1px solid var(--pa-border);
}

.auth-links a {
	color: var(--pa-link);
	cursor: pointer;
}

/* Der Nebenweg neben der Karte: sichtbar, aber erkennbar nachrangig. */
.auth-hint {
	padding: var(--pa-space-4) var(--pa-space-5);
	border: 1px dashed var(--pa-border-strong);
	border-radius: var(--pa-radius);
	background: var(--pa-surface-sunken);
	text-align: center;
	margin-bottom: var(--pa-space-5);
}

.auth-hint h4 {
	margin-top: 0;
	color: var(--pa-navy);
}

.auth-hint p {
	color: var(--pa-ink-soft);
	margin-bottom: 0;
}

/* Platz reservieren, damit das nachgeladene Turnstile-Widget die Maske nicht
   springen laesst. */
.turnstile-area {
	min-height: 70px;
}

/* --- Ergaenzungen zu den Galeriekarten ---------------------------------- */

/* Die Karte ist ein <a>; die Textbloecke darin sind deshalb Spans und
 * brauchen ausdrueckliches display. */
.pa-gallerycard__body,
.pa-gallerycard__preview,
.pa-gallerycard__title {
	display: block;
}

.pa-gallerycard {
	color: inherit;
	text-decoration: none;
}

.pa-gallerycard:hover {
	color: inherit;
	text-decoration: none;
}

/* Schloss an einer passwortgeschuetzten Galerie. Bisher merkte man den
 * Schutz erst, wenn sich nach dem Klick eine Passwortabfrage oeffnete. */
.pa-gallerycard__lock {
	display: inline-flex;
	align-items: center;
	gap: var(--pa-space-1);
	padding: 0.05em 0.5em;
	border-radius: var(--pa-radius-pill);
	background: var(--pa-warning-bg);
	color: var(--pa-warning);
	font-size: var(--pa-text-xs);
	font-weight: 600;
}

/* Der Galeriecode unter der Karte - bewusst ausserhalb des Kartenlinks,
 * weil er ein eigenes Ziel hat (Einstieg ueber den Code). */
.pa-gallerycard__code-row {
	margin-top: var(--pa-space-2);
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
	text-align: center;
}

.pa-gallerylist > li {
	display: flex;
	flex-direction: column;
}

.pa-gallerylist > li > .pa-gallerycard {
	flex: 1 1 auto;
}

/* --- Bestellpositionen: Zusatzfelder --------------------------------------
 * Dasselbe Raster wie der Warenkorb, aber die Bildzelle traegt zusaetzlich
 * die Bearbeitungsknoepfe fuer Admin und Labor.
 * ---------------------------------------------------------------------- */

.pa-cart-item__thumb-cell {
	grid-area: thumb;
	align-self: start;
	display: flex;
	flex-direction: column;
	gap: var(--pa-space-2);
}

.pa-pos-actions {
	display: flex;
	flex-direction: column;
	gap: var(--pa-space-2);
}

/* Leer im Kundenblick - dann soll auch kein Abstand entstehen. */
.pa-pos-actions:empty {
	display: none;
}

.pa-pos-actions .btn {
	font-size: var(--pa-text-xs);
	white-space: nowrap;
	width: 100%;
}

/* Menge als Faktor - das Malzeichen etwas leiser als die Zahl. */
.pa-cart-item__mal {
	color: var(--pa-text-muted);
	font-weight: 400;
}

/* Wo Knoepfe stehen, braucht die erste Spalte mehr als die 88 px fuer das
 * Vorschaubild.
 *
 * Im Kundenblick gibt es diese Knoepfe nicht - dort bleibt die Spalte
 * schmal. Admin und Labor sehen "Bildzuschnitt aendern", "Bild defekt
 * melden" und "Download defekt": in 88 px brach jeder dieser Texte
 * zweizeilig um und die Knoepfe waren kaum als solche zu erkennen. */
/* Der Selektor greift die LISTE, nicht die einzelne Zeile - und deshalb
 * gilt die Breite fuer alle Zeilen darin.
 *
 * Jede Zeile ist ihr eigenes Raster. Haette nur die Zeile mit Knoepfen die
 * breite erste Spalte, stuenden Bezeichnungen, Mengen und Preise der
 * uebrigen Zeilen woanders - genau das war bei der Versandkostenposition zu
 * sehen, die weder Bild noch Knoepfe hat: ihre Angaben standen aus der
 * Flucht der Bildpositionen heraus. */
.pa-cart-items:has(.pa-pos-actions .btn) .pa-cart-item {
	grid-template-columns: 170px minmax(0, 1fr) auto auto auto;
}

@media (max-width: 767.98px) {
	.pa-cart-items:has(.pa-pos-actions .btn) .pa-cart-item {
		grid-template-columns: 150px minmax(0, 1fr) auto;
	}
}

/* Felder eines Schuelerausweises bzw. einer Kundenkarte.
 *
 * Je Feld eine Zeile aus Bezeichnung und Wert. Bewusst flex und nicht
 * `subgrid`: subgrid koennten aeltere Browser nicht, und die Felder wuerden
 * dort untereinander statt nebeneinander stehen. */
.pa-pos-config {
	margin: var(--pa-space-2) 0 0;
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
}

.pa-pos-config > div {
	display: flex;
	flex-wrap: wrap;
	gap: 0 var(--pa-space-2);
}

.pa-pos-config dt {
	font-weight: 600;
	color: var(--pa-navy);
}

.pa-pos-config dt::after {
	content: ":";
}

.pa-pos-config dd {
	margin: 0;
}

/* ===========================================================================
 * 11. Grossansicht mit Artikelauswahl
 *
 * Kommt vom Server (GrossansichtPanel) und legt sich ueber die Galerie:
 * links das Motiv, rechts dieselbe Artikelauswahl wie auf der
 * Einzelbildseite. Bestellt wird ohne Seitenwechsel.
 *
 * Die Ueberlagerung ist ABSICHTLICH kein Bootstrap-Modal: aus der
 * Artikelauswahl heraus oeffnen sich weitere Dialoge (Bildzuschnitt,
 * Produktsatzkonfiguration), und Bootstrap unterstuetzt keine Modals
 * uebereinander. Als eigene Ebene mit z-index UNTER Bootstraps
 * Modalebene liegen jene Dialoge korrekt darueber.
 * ======================================================================== */

/* Solange die Grossansicht offen ist, scrollt die Seite dahinter nicht. */
.pa-viewer-offen,
.pa-viewer-offen body {
	overflow: hidden;
}

.pa-viewer {
	position: fixed;
	inset: 0;
	/* Ueber der klebenden Kopfleiste (1030), aber UNTER Bootstraps
	 * Modalhintergrund (1050) - siehe Abschnittskommentar. */
	z-index: 1040;
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(320px, 400px);
	background: rgba(12, 18, 24, 0.96);
	animation: pa-viewer-auf var(--pa-duration-slow) var(--pa-ease);
}

@keyframes pa-viewer-auf {
	from { opacity: 0; }
	to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
	.pa-viewer {
		animation: none;
	}
}

/* --- Motiv -------------------------------------------------------------- */

.pa-viewer__bild {
	display: flex;
	align-items: center;
	justify-content: center;
	/* Nimmt die Hoehe, die die Angaben darunter uebrig lassen. */
	flex: 1 1 auto;
	min-width: 0;
	min-height: 0;
	padding: var(--pa-space-6) var(--pa-space-6) var(--pa-space-4);
	overflow: hidden;
}

.pa-viewer__bild img {
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;
	border-radius: var(--pa-radius);
	box-shadow: 0 12px 48px rgba(0, 0, 0, 0.5);
}

/* --- Seitenspalte mit Blaettern und Artikeln ---------------------------- */

.pa-viewer__seite {
	display: flex;
	flex-direction: column;
	min-height: 0;
	background: var(--pa-surface);
	box-shadow: -8px 0 32px rgba(0, 0, 0, 0.3);
}

.pa-viewer__blaettern {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--pa-space-3);
	flex: none;
	padding: var(--pa-space-3) var(--pa-space-5);
	border-bottom: 1px solid var(--pa-border);
	background: var(--pa-surface-sunken);
}

.pa-viewer__nav {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border: 1px solid var(--pa-border);
	border-radius: var(--pa-radius-pill);
	background: var(--pa-surface);
	color: var(--pa-navy);
	cursor: pointer;
}

.pa-viewer__nav:hover {
	border-color: var(--pa-accent);
	background: var(--pa-accent-soft);
	color: var(--pa-navy);
	text-decoration: none;
}

.pa-viewer__zaehler {
	min-width: 6ch;
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
	font-variant-numeric: tabular-nums;
	text-align: center;
}

/* --- Hinweise in der Seitenspalte --------------------------------------- */

.pa-viewer__hinweise {
	flex: none;
	padding: var(--pa-space-4) var(--pa-space-5) 0;
}

.pa-viewer__hinweise .alert {
	margin-bottom: var(--pa-space-3);
	font-size: var(--pa-text-sm);
}

/* Ist kein Hinweis zu zeigen, rendert Wicket die Panels gar nicht - dann
 * soll auch der Innenabstand weg sein. Ohne `:has()` bleibt eine Luecke. */
.pa-viewer__hinweise:not(:has(*)) {
	display: none;
}

/* --- Angaben zum Motiv, unter dem Bild ---------------------------------- */

/* Sie stehen unter dem Motiv und nicht in der Seitenspalte - dort lasen sie
 * sich neben Artikelauswahl und Warenkorb wie eine Bestellangabe.
 *
 * Auf der dunklen Flaeche sind sie bewusst leise: keine Trennlinie, kein
 * Kasten, gedaempftes Weiss. Lesbar bleibt es trotzdem - nachgerechnet mit
 * der WCAG-Formel gegen die Flaeche der Grossansicht (rgb 12,18,24):
 * Bildnummer (Weiss mit 0,82) 12,7:1, Dateiname (0,62) 7,6:1, der
 * Profillink (0,72) 10,0:1. Die Schwelle fuer kleinen Text ist 4,5:1. */
.pa-viewer__buehne {
	display: flex;
	flex-direction: column;
	min-width: 0;
	min-height: 0;
}

.pa-viewer__meta {
	flex: none;
	padding: 0 var(--pa-space-6) var(--pa-space-5);
}

.pa-viewer__meta .pa-photo__meta {
	justify-content: center;
	gap: var(--pa-space-1) var(--pa-space-4);
	padding: 0;
	border-top: 0;
	color: rgba(255, 255, 255, 0.62);
	font-size: var(--pa-text-xs);
}

.pa-viewer__meta .pa-photo__id {
	color: rgba(255, 255, 255, 0.82);
	font-weight: 500;
}

/* Der Urhebervermerk verlinkt das Fotografenprofil - auf dunklem Grund
 * braucht der Link eine eigene Farbe, die Standardlinkfarbe ist dort zu
 * dunkel. */
.pa-viewer__meta a {
	color: rgba(255, 255, 255, 0.72);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.pa-viewer__meta a:hover {
	color: #fff;
}

/* Der Hinweis auf ein unbearbeitetes Bild bleibt ein Hinweiskasten - er ist
 * eine Aussage zum Bild und keine Beschriftung -, nur schmaler. */
.pa-viewer__meta .alert {
	max-width: 42rem;
	margin: var(--pa-space-3) auto 0;
	padding: var(--pa-space-2) var(--pa-space-3);
	font-size: var(--pa-text-sm);
	text-align: center;
}

/* Die Artikelauswahl scrollt fuer sich - bei zwanzig Artikeln soll nicht
 * die ganze Ueberlagerung wandern. */
.pa-viewer__artikel {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: var(--pa-space-4) var(--pa-space-5) var(--pa-space-6);
}

/* Innerhalb der Grossansicht braucht die Artikelauswahl keine eigenen
 * Kartenrahmen - die Spalte ist schon der Rahmen. */
.pa-viewer__artikel .card {
	border-left: 0;
	border-right: 0;
	border-radius: 0;
	box-shadow: none;
}

.pa-viewer__artikel .card + .card {
	margin-top: 0;
	border-top: 0;
}

/* --- Schliessen --------------------------------------------------------- */

.pa-viewer__zu {
	position: absolute;
	top: calc(var(--pa-space-4) + env(safe-area-inset-top));
	left: var(--pa-space-4);
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	border: 0;
	border-radius: var(--pa-radius-pill);
	background: rgba(255, 255, 255, 0.16);
	color: #fff;
	font-size: 1.25rem;
	cursor: pointer;
	transition: background-color var(--pa-duration) var(--pa-ease);
}

.pa-viewer__zu:hover {
	background: rgba(255, 255, 255, 0.3);
}

.pa-viewer :focus-visible {
	outline: 3px solid var(--pa-accent);
	outline-offset: 3px;
}

/* --- Unter 992 px: untereinander ---------------------------------------
 * Motiv oben mit begrenzter Hoehe, Artikelauswahl darunter scrollend. Wer
 * auf dem Telefon bestellt, soll das Motiv sehen UND an die Artikel
 * kommen, ohne zwischen zwei Bildschirmen zu wechseln.
 * ---------------------------------------------------------------------- */

@media (max-width: 991.98px) {
	.pa-viewer {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: minmax(0, 42vh) minmax(0, 1fr);
	}

	.pa-viewer__bild {
		padding: var(--pa-space-6) var(--pa-space-3) var(--pa-space-2);
	}

	/* Die Angaben ruecken mit dem Bild zusammen - oben teilen sich Motiv und
	 * Beschriftung 42vh. */
	.pa-viewer__meta {
		padding: 0 var(--pa-space-3) var(--pa-space-3);
	}

	.pa-viewer__seite {
		box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.3);
		border-top-left-radius: var(--pa-radius-lg);
		border-top-right-radius: var(--pa-radius-lg);
	}

	.pa-viewer__artikel {
		padding-inline: var(--pa-space-3);
	}

	.pa-viewer__zu {
		top: var(--pa-space-2);
		left: var(--pa-space-2);
		width: 44px;
		height: 44px;
	}
}

/* --- Dialoge innerhalb der Grossansicht --------------------------------
 *
 * Bildzuschnitt und Produktsatzkonfiguration oeffnen sich AUS der
 * Artikelauswahl heraus, liegen also innerhalb der Grossansicht. Bootstraps
 * Abdunkler haengt am body und damit ausserhalb - er lag ueber dem Dialog
 * und machte ihn unbedienbar.
 *
 * Diese Dialoge bekommen deshalb keinen Abdunkler von Bootstrap
 * (backdrop: false, siehe PaModal) und tragen ihn hier selbst. Er liegt
 * damit im selben Stapelkontext und richtig.
 * ---------------------------------------------------------------------- */

/* Die Abdunklung sitzt an der Grossansicht, nicht am Dialog.
 *
 * Am Dialog selbst (position: fixed, inset: 0) deckte sie die Artikelspalte
 * nicht mit ab - die stand hell daneben und sah bedienbar aus, obwohl der
 * Dialog auf eine Antwort wartete. Als Flaeche der Grossansicht liegt sie
 * ueber allem, was zu ihr gehoert.
 *
 * pointer-events bleibt aktiv: Klicks daneben sollen ins Leere gehen und
 * nicht die Artikelliste treffen. Geschlossen wird ueber die Knoepfe oder
 * Escape. */
.pa-viewer:has(.modal.show)::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1054;
	background: rgba(12, 18, 24, 0.72);
}

/* Ohne :has() bleibt die Abdunklung am Dialog - dann ist die Artikelspalte
 * daneben nicht abgedunkelt, der Dialog aber bedienbar. */
@supports not selector(:has(*)) {
	.modal.pa-modal--eigener-hintergrund {
		background: rgba(12, 18, 24, 0.72);
	}
}

/* In der Grossansicht ist der Platz knapper als auf einer ganzen Seite -
 * der Zuschnittsdialog darf die Hoehe nutzen. */
.pa-viewer .modal-dialog {
	max-height: calc(100vh - 2 * var(--pa-space-5));
}

/* --- Fussleiste der Artikelspalte --------------------------------------
 *
 * Ohne sie fehlte nach dem Hinzufuegen jede Rueckmeldung: die Kopfleiste mit
 * dem Warenkorb liegt hinter der Grossansicht und ist abgedunkelt. Hier
 * stehen Summe und der Weg zur Bestellung.
 * ---------------------------------------------------------------------- */

.pa-viewer__fuss {
	flex: none;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--pa-space-3);
	padding: var(--pa-space-3) var(--pa-space-5)
	         calc(var(--pa-space-3) + env(safe-area-inset-bottom));
	border-top: 1px solid var(--pa-border);
	background: var(--pa-surface-sunken);
}

.pa-viewer__summe {
	display: flex;
	align-items: baseline;
	gap: var(--pa-space-2);
	margin-right: auto;
	color: var(--pa-ink-soft);
	font-size: var(--pa-text-sm);
}

.pa-viewer__fuss .btn {
	flex: 0 1 auto;
}

@media (max-width: 991.98px) {
	.pa-viewer__fuss {
		padding-inline: var(--pa-space-3);
	}

	/* Auf dem Telefon der Knopf ueber die ganze Breite - er ist die
	 * Handlung. */
	.pa-viewer__fuss .btn {
		flex: 1 1 100%;
		order: 1;
	}
}
