/*
  Content blocks and the 12-column block grid — Slice 9, ticket 26a.

  Own file by contract §6 ("Alles Block-CSS hierher, nicht in components.css"): four agents work on Slice 9
  in parallel, and components.css is the one stylesheet three of them append to.

  Parity target: docs/nachweise/altsystem/*.png. The old live system's content pages are a three-column
  raster of square-ish tiles with a 2 px dotted black border and centred text, interleaved with borderless
  photos that fill a whole cell, under a dotted section heading. Everything dotted here comes from the
  --border-motif token family (tokens.css, design-altsystem-paritaet.md §1) — no new `dotted` literals and
  no new hex values, so a future style change still happens in one place.

  Mobile-first, like every other stylesheet in this shop: one column below 768 px, the editorial
  columnSpan widths above it.
*/

/* --- The grid ------------------------------------------------------------ */
.block-grid {
  /* Umbraco's gridColumns, handed down as an inline custom property by
     Views/Partials/blockgrid/default.cshtml. The fallback keeps the grid sane if a data type is ever
     configured without it. */
  --block-grid-columns: 12;
}

.block-grid__items {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

.block-grid__item {
  /* Stretches the block inside its cell, which is what gives a row of tiles equal heights — the old
     system's rows line up because the tiles fill them, not because anyone set a fixed height. */
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.block-grid__item > * {
  flex: 1 1 auto;
}

@media (min-width: 768px) {
  .block-grid__items {
    grid-template-columns: repeat(var(--block-grid-columns), minmax(0, 1fr));
  }

  .block-grid__item {
    /* --block-column-span / --block-row-span come from the item's own inline style (items.cshtml). A
       12-column grid with columnSpan 4 is the three-column raster of the old system; 9 + 3 is the home
       page's wide/narrow split. */
    grid-column: span var(--block-column-span, 12);
    grid-row: span var(--block-row-span, 1);
  }
}

/* --- The dotted tile ----------------------------------------------------- */
.block-tile {
  --block-tile-min-height: 15rem;

  display: flex;
  flex-direction: column;
  /* Vertically centred, as in every tile of the old system: a two-line process step sits in the middle of
     its box, not at the top edge. */
  justify-content: center;
  gap: var(--space-3);
  min-height: var(--block-tile-min-height);
  padding: var(--space-5);
  border: var(--border-motif);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
}

.block-tile--center {
  text-align: center;
}

.block-tile--start {
  text-align: start;
}

/*
  showBorder: false — the legal-text case (Impressum/AGB/Datenschutz). A two-thousand-word text inside a
  dotted box reads as a defect, and the old system renders those pages as plain running text too. No
  min-height and top-aligned: long text has no reason to be vertically centred.
*/
.block-plain {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* --- Richtext bodies ----------------------------------------------------- */
/*
  Editors write these, so the shape of the markup is not ours to predict: paragraphs, lists, inline bold
  (the old system bolds *inside* sentences, which is why every body field is richtext), the occasional
  table. Only spacing and link colour are set here — headings and font sizes come from layout.css.
*/
.rich-text > * + * {
  margin-top: var(--space-3);
}

.rich-text ul,
.rich-text ol {
  padding-inline-start: var(--space-5);
}

.rich-text :last-child {
  margin-bottom: 0;
}

/* --- textCardBlock ------------------------------------------------------- */
.text-card__label {
  /* The big "1.", "2." of the old system's process steps. */
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  margin: 0;
}

.text-card__heading {
  font-size: var(--heading-size-tile);
  font-weight: var(--heading-weight);
  line-height: var(--line-height-tight);
  margin: 0;
}

.text-card__body {
  font-size: var(--font-size-base);
  color: var(--color-ink-soft);
}

/* A left-aligned, borderless legal text is a reading text, not a tile caption — full body size. */
.block-plain .text-card__body {
  font-size: var(--font-size-base);
}

/* --- claimBlock ---------------------------------------------------------- */
.claim__text {
  font-size: var(--font-size-xl);
  line-height: var(--line-height-tight);
}

.claim__text strong,
.claim__text b {
  /* "knusprige vielfalt in *höchster qualität* aus meisterhand": the bold run inside the sentence is the
     whole point of these tiles. */
  font-weight: var(--font-weight-bold);
}

@media (min-width: 768px) {
  .claim__text {
    font-size: var(--font-size-2xl);
  }
}

/* --- imageBlock ---------------------------------------------------------- */
.block-image {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0;
}

.block-image__img {
  display: block;
  width: 100%;
  /* Fills the cell next to the tiles of the same row (object-fit crops rather than distorts). The
     aspect-ratio is the mobile fallback, where a cell has no sibling to match. */
  flex: 1 1 auto;
  min-height: 15rem;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-md);
}

.block-image__caption {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  text-align: center;
}

/* --- teaserBlock --------------------------------------------------------- */
.teaser__image {
  display: block;
  width: 100%;
  max-height: 12rem;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

.teaser__title {
  font-size: var(--heading-size-tile);
  font-weight: var(--heading-weight);
  line-height: var(--line-height-tight);
  margin: 0;
}

.teaser__text {
  font-size: var(--font-size-base);
  color: var(--color-ink-soft);
}

.teaser__action {
  margin: 0;
}

/* --- ctaBlock ----------------------------------------------------------- */
.cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-5);
  border: var(--border-motif);
  border-radius: var(--radius-md);
  text-align: center;
}

/* The brand yellow is only ever a surface behind black text, never text on white (brand-notes.md). */
.cta--brand {
  background-color: var(--color-brand);
  color: var(--color-ink);
}

.cta--dark {
  background-color: var(--color-ink);
  color: var(--color-surface);
  /* A dotted black border on a black surface is invisible; the surface itself is the boundary here. */
  border-color: var(--color-ink);
}

.cta--muted {
  background-color: var(--color-surface-muted);
}

.cta--dark a {
  color: var(--color-surface);
}

.cta__text {
  font-size: var(--font-size-lg);
  line-height: var(--line-height-tight);
}

.cta__action {
  margin: 0;
}

/* --- mapBlock ----------------------------------------------------------- */
.map-block {
  /* The embed brings its own height; the tile must not add a second minimum on top of it. */
  min-height: 0;
  padding: var(--space-3);
  gap: var(--space-3);
}

.map-block__frame {
  display: block;
  width: 100%;
  border: 0;
  border-radius: var(--radius-sm);
}

.map-block__notice {
  font-size: var(--font-size-xs);
  color: var(--color-ink-muted);
}

/* --- deliveryAreaBlock -------------------------------------------------- */
.delivery-area__heading {
  font-size: var(--heading-size-tile);
  font-weight: var(--heading-weight);
  margin: 0;
}

.delivery-area__text {
  font-size: var(--font-size-base);
  color: var(--color-ink-soft);
}

/* --- recentOrdersBlock -------------------------------------------------- */
.recent-orders {
  /* A table needs its natural height, and two orders in one tile would otherwise be centred against a
     fixed minimum. */
  min-height: 0;
  gap: var(--space-5);
  justify-content: flex-start;
}

.recent-orders__heading {
  font-size: var(--heading-size-tile);
  font-weight: var(--heading-weight);
  margin: 0;
}

.recent-orders__order + .recent-orders__order {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: var(--border-motif);
}

.recent-orders__order-title {
  font-weight: var(--font-weight-semibold);
  margin: 0 0 var(--space-3);
}

.recent-orders__lines {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-sm);
}

.recent-orders__lines th,
.recent-orders__lines td {
  padding: var(--space-2) var(--space-1);
  text-align: start;
  border-bottom: var(--border-width) var(--border-style-motif) var(--color-border-strong);
}

.recent-orders__lines tfoot th,
.recent-orders__lines tfoot td {
  font-weight: var(--font-weight-bold);
  border-bottom: 0;
}

/* The repeat hint is the shared notice box (design review 14.10.2026, third round) between table and
   button. */
.recent-orders__order > .alert {
  margin: var(--space-3) 0;
}

.recent-orders__numeric {
  text-align: end;
  white-space: nowrap;
}


/* --- newProductsBlock --------------------------------------------------- */
/* Same spacing as .catalog-grid, so the cards here and on /produkte are the same size. */
/* Ticket 26g A (design review 30.10.2026, E2.4/A8): two columns on the phone like /produkte, with the
   same smaller mobile gaps, so a tile is the same size here and there. */
.new-products__grid {
  display: grid;
  gap: var(--space-5) var(--space-3);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 768px) {
  .new-products__grid {
    gap: var(--space-7) var(--space-4);
    /* Not a fixed count: this block can be placed at any columnSpan, so the number of products per row
       has to follow the width it actually got. auto-fill rather than auto-fit, and an 18rem minimum, so
       that full width gives the catalogue's three columns and two new products do not stretch to half
       the page each (design review 13.10.2026, second round). */
    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
  }
}

/* --- Page title of a content page --------------------------------------- */
/*
  The dotted heading of the design system (.section-heading in components.css) on an <h1>: same rule, same
  knockout, same tokens, same size. Until the third design review (14.10.2026) the label was also
  lighter (regular, after the old system's unbolded page titles) — reported as "Headline Styles sind nicht
  einheitlich (fett/nicht fett)" next to the bold section and tile headings, so every heading now shares
  --heading-weight; page title and section heading share --heading-size-section (the page title keeps the
  size it had), tile and card headings use --heading-size-tile.
*/
.section-heading--page {
  margin-bottom: var(--space-6);
}

/*
  Design review 13.10.2026: every page title (cart, checkout, account, product, ...) uses this heading, so
  long titles ("Registrierung entgegengenommen", product names) must wrap on a phone instead of pushing the
  label past the viewport — the label may shrink down to its longest word, the rules shrink to nothing.
*/
.section-heading--page .section-heading__label {
  flex-shrink: 1;
  min-width: 0;
  text-align: center;
  overflow-wrap: anywhere;
  font-size: var(--heading-size-section);
  font-weight: var(--heading-weight);
}

/* Left-aligned page title (product detail: the name sits in a column beside the photo). */
.section-heading--page.section-heading--start .section-heading__label {
  text-align: start;
}

/* --- Header banner (composition pageHeader) ----------------------------- */
/*
  Full-bleed, like the old system's 1920×300 banner on every subpage. A fixed height plus object-fit keeps
  the band the same on every page regardless of the picture's own proportions — a banner that changes height
  from page to page makes the header jump.
*/
.page-header {
  width: 100%;
  overflow: hidden;
  background-color: var(--color-surface-sunken);
}

.page-header__image {
  display: block;
  width: 100%;
  height: 8rem;
  object-fit: cover;
}

@media (min-width: 768px) {
  .page-header__image {
    height: 12rem;
  }
}

@media (min-width: 1200px) {
  .page-header__image {
    /* 1920 × 300 is the old system's own ratio; at full width that is roughly this. */
    height: 18.75rem;
  }
}

/* --- Ticket 26d: a widget block that renders nothing must not leave a hole ---------------------- */
/*
  The three widget blocks decide per visitor whether they render at all: the balance tile is hidden for
  anyone but an approved customer (G-16), the repeat-order box disappears without history (E7.1/A4), and
  "Neue Produkte" disappears when G-1 filters every picked product away (E7.1/A6). Their grid cell is
  written unconditionally by items.cshtml, though, so on the anonymous home page the whole first row —
  columnSpan 9 plus 3 — is a pair of empty wrappers, and the grid still puts its row gap around them.

  :empty cannot be used for this: Razor writes a newline and indentation inside every cell, which counts
  as content. :not(:has(*)) asks the question that actually matters — "no element children" — and leaves
  cells whose block did render untouched.

  Appended at the end of the file rather than edited into the grid section above (contract §6: this file
  belongs to A2/T26a; appending keeps the hunks of the parallel Slice-9 agents from overlapping).
*/
.block-grid__item:not(:has(*)) {
  display: none;
}

/* --- Die Guthaben-Kachel behält ihre eigene Höhe (Auftraggeber, 14.08.2026) --------------------- */
/*
  Zellen strecken ihren Inhalt (siehe .block-grid__item oben) — bei Textkacheln ist das gewollt, weil eine
  Reihe dadurch auf gleiche Höhe kommt, so wie das Raster des Altsystems aussieht. Neben der breiten
  Bestellwiederholung (columnSpan 9) zieht das die Guthaben-Kachel (columnSpan 3) aber auf deren volle
  Höhe, und aus der kleinen gelben Box wird eine große leere Fläche.

  Deshalb hier gezielt nur für diesen einen Block zurückgenommen: align-self hält die Zelle auf ihrer
  Inhaltshöhe, flex: 0 0 auto verhindert, dass die Kachel innerhalb der Zelle nachwächst. Auf Mobil ist
  das Raster einspaltig, dort ändert die Regel nichts.
*/
.block-grid__item[data-block="balanceBlock"] {
  align-self: start;
}

.block-grid__item[data-block="balanceBlock"] > * {
  flex: 0 0 auto;
}

/*
  Punkteband oben (Design-Review 13.10.2026): wie im Altsystem (_header.scss .dots-top) liegt
  punkte_oben.png auf dem Bild, an seiner Oberkante — nicht auf weißem Grund über dem Header. Darum
  sitzt es auf beiden Bannern: dem Headerbild der Unterseiten und dem Startseiten-Banner (components.css
  .home-hero). Ungespiegelt, volle Breite, linksbündig; rein dekorativ, daher Pseudoelement.
*/
.page-header,
.home-hero {
  position: relative;
}

.page-header::before,
.home-hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  z-index: 1;
  height: 25px;
  background: url("/assets/brand/punkte_oben.png") left top / auto 25px repeat-x;
  pointer-events: none;
}
