/* =============================================================================
 * atomicplan/publication-list — Block-CSS
 *
 * Gescoped auf `.frame-type-atomicplan_publicationlist`. KEIN Sektions-
 * Hintergrund, KEIN Sektions-Padding, KEINE Container-Breite (Frame-System).
 * Farben ueber Bootstrap-Tokens (Frame-Invert-Logik), keine Heading-Typografie.
 * ========================================================================== */

.frame-type-atomicplan_publicationlist {

  --pl-publist-gap: 1.5rem;
  --pl-publist-line: color-mix(in srgb, var(--bs-body-color, #333) 16%, transparent);
  --pl-publist-muted: color-mix(in srgb, var(--bs-body-color, #333) 68%, transparent);
  --pl-publist-accent: var(--bs-primary, #0d6efd);
  --pl-publist-tag-bg: color-mix(in srgb, var(--bs-body-color, #333) 8%, transparent);
  --pl-publist-cover-bg: color-mix(in srgb, var(--bs-body-color, #333) 6%, transparent);
  /* Gefuellte Flaechen (aktiver Chip, aktuelle Blaetter-Seite) tragen KLEINEN
     Text auf Farbe — dafuer reicht ein Marken-Ton oft nicht (AA verlangt 4,5:1).
     Deshalb ein EIGENER Token, den das Theme auf seine dunklere Variante setzt,
     statt `--pl-publist-accent` mitzubenutzen. */
  --pl-publist-accent-strong: var(--pl-publist-accent);
  --pl-publist-on-accent: var(--bs-white, #fff);

  /* Chip-Form. Voreinstellung 0 = bisheriges (eckiges) Verhalten — bestehende
     Elemente auf anderen Installationen duerfen sich durch ein Paket-Update
     nicht veraendern. Themes mit runder Formensprache setzen die Variable auf
     ihren Pill-Radius; das Innenpolster waechst dann mit, sonst kleben die
     Beschriftungen an der Rundung. */
  --pl-publist-chip-radius: 0;
  --pl-publist-chip-padding: 0.4rem 0.8rem;

  /* Variante `cover`: Seitenverhaeltnis und Einpassung der Cover-Kachel.
     Voreinstellung 3:4 (Hochformat, das uebliche Buchformat) und `contain`,
     damit ein Cover NIE angeschnitten wird — bei einem Buchtitel faellt sonst
     die Kopf- oder Fusszeile weg. */
  --pl-publist-cover-ratio: 3 / 4;
  --pl-publist-cover-fit: contain;

  /* Abstand zum Listenanfang, wenn HTMX nach dem Tausch dorthin scrollt
     (`show:#…:top`). Das Theme setzt hier die Hoehe seines fixierten Headers —
     ohne den Versatz verschwindet die erste Kartenreihe darunter. */
  .pl-publist { scroll-margin-top: var(--pl-publist-scroll-offset, 1rem); }

  .pl-publist__intro {
    /* Reine Text-Zeilenlaenge — KEIN Sektions-Container. */
    max-width: 60rem;
    margin-block: 0 var(--pl-publist-gap);
  }
  .pl-publist__intro > *:last-child { margin-bottom: 0; }

  /* ---- Filterleiste ------------------------------------------------------ */
  .pl-publist__filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 1rem;
    margin-bottom: var(--pl-publist-gap);
  }
  .pl-publist__filters[hidden] { display: none; }

  .pl-publist__filter { display: flex; flex-direction: column; gap: 0.25rem; }
  .pl-publist__filter-label {
    font-size: 0.75rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--pl-publist-muted);
  }
  .pl-publist__filter select {
    padding: 0.45rem 0.6rem;
    border: 1px solid var(--pl-publist-line);
    background: var(--bs-body-bg, #fff);
    /* Das Options-Panel malt das Betriebssystem hell — Optionsfarbe deshalb NICHT
       aus einem Token beziehen, das ein Invert-Frame umdreht. */
    color: #222;
  }
  .pl-publist__filter select option { color: #222; background: #fff; }

  .pl-publist__empty {
    flex: 1 1 100%;
    margin: 0;
    color: var(--pl-publist-muted);
  }
  .pl-publist__empty[hidden] { display: none; }

  /* ---- Trefferzahl (zugleich Live-Region) -------------------------------- */
  .pl-publist__count {
    margin: 0 0 0.6rem;
    font-size: 0.9rem;
    color: var(--pl-publist-muted);
  }

  /* ---- Chips ------------------------------------------------------------
     Echte <button>-Elemente: fokussierbar, tastaturbedienbar, mit
     aria-pressed. `font: inherit` ist Pflicht — Browser geben Buttons sonst
     ihre eigene Systemschrift. */
  .pl-publist__filter--chips { flex: 1 1 100%; }
  .pl-publist__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.35rem;
  }
  .pl-publist__chip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    padding: var(--pl-publist-chip-padding);
    border-radius: var(--pl-publist-chip-radius);
    border: 1px solid var(--pl-publist-line);
    background: var(--pl-publist-tag-bg);
    color: inherit;
    font: inherit;
    font-size: 0.9rem;
    line-height: 1.25;
    cursor: pointer;
  }
  .pl-publist__chip:hover { border-color: var(--pl-publist-accent); }
  /* Sichtbarer Fokus ist bei Chips nicht verhandelbar: sie sind die einzige
     Bedienung der Facette. */
  .pl-publist__chip:focus-visible {
    outline: 2px solid var(--pl-publist-accent);
    outline-offset: 2px;
  }
  .pl-publist__chip.is-active {
    background: var(--pl-publist-accent-strong);
    border-color: var(--pl-publist-accent-strong);
    color: var(--pl-publist-on-accent);
  }
  /* Die Trefferzahl ist INFORMATION, keine Dekoration — deshalb kein `opacity`,
     das den Kontrast still unter AA druecken wuerde. Unterschieden wird sie von
     der Beschriftung durch die Klammern, nicht durch Blaesse. */
  .pl-publist__chip-count { font-variant-numeric: tabular-nums; }
  .pl-publist__chip-count::before { content: '('; }
  .pl-publist__chip-count::after { content: ')'; }

  .pl-publist__submit,
  .pl-publist__reset {
    align-self: flex-end;
    padding: 0.45rem 0.9rem;
    border: 1px solid var(--pl-publist-line);
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: 0.9rem;
    cursor: pointer;
    text-decoration: none;
  }

  /* ---- Blaettern --------------------------------------------------------- */
  .pl-publist__pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    margin-top: var(--pl-publist-gap);
  }
  .pl-publist__pages {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .pl-publist__page,
  .pl-publist__pagestep {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.4rem;
    padding: 0.4rem 0.7rem;
    border: 1px solid var(--pl-publist-line);
    color: inherit;
    font-size: 0.9rem;
    text-decoration: none;
  }
  .pl-publist__page:hover,
  .pl-publist__pagestep:hover { border-color: var(--pl-publist-accent); }
  .pl-publist__page.is-current {
    background: var(--pl-publist-accent-strong);
    border-color: var(--pl-publist-accent-strong);
    color: var(--pl-publist-on-accent);
  }
  .pl-publist__pagegap { padding: 0 0.2rem; color: var(--pl-publist-muted); }

  /* HTMX-Ladeanzeige: waehrend der Anfrage wird die Liste blass. Der
     Indikator haengt an `.htmx-request`, das HTMX selbst setzt. */
  .pl-publist.htmx-request .pl-publist__items { opacity: 0.5; transition: opacity 0.15s linear; }

  /* ---- Liste ------------------------------------------------------------- */
  .pl-publist__items {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--pl-publist-gap);
  }
  .pl-publist__item[hidden] { display: none; }

  .pl-publist__cover {
    background: var(--pl-publist-cover-bg);
    overflow: hidden;
  }
  .pl-publist__cover-img {
    display: block;
    width: 100%;
    height: auto;
  }

  .pl-publist__body { min-width: 0; }

  .pl-publist__meta {
    margin: 0 0 0.25rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    font-size: 0.78rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--pl-publist-muted);
  }
  .pl-publist__year { font-weight: 700; color: var(--pl-publist-accent); }

  .pl-publist__title { margin: 0 0 0.25rem; }
  .pl-publist__title-link { color: inherit; text-decoration: none; }
  .pl-publist__title-link:hover { color: var(--pl-publist-accent); text-decoration: underline; }

  .pl-publist__subtitle { margin: 0 0 0.35rem; color: var(--pl-publist-muted); }
  .pl-publist__authors { margin: 0; font-size: 0.9rem; }
  .pl-publist__source { margin: 0; font-size: 0.9rem; color: var(--pl-publist-muted); }

  .pl-publist__quote {
    margin: 0.6rem 0 0;
    /* Reine Text-Zeilenlaenge innerhalb der Karte. */
    max-width: 46rem;
  }

  .pl-publist__tags {
    list-style: none;
    margin: 0.6rem 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
  }
  .pl-publist__tag {
    padding: 0.15rem 0.5rem;
    font-size: 0.75rem;
    background: var(--pl-publist-tag-bg);
  }

  /* ---- Aktionen ---------------------------------------------------------
     `__actions` ist ein DIREKTES Kind von `__item` (nicht Teil von `__body`) —
     nur so kann die Variante `compact` sie neben das Cover in die erste Zeile
     stellen. In `cards`/`rows` steht sie unveraendert am Ende der Karte. */
  .pl-publist__actions {
    margin: 0.8rem 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1rem;
  }
  .pl-publist__action {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--pl-publist-accent);
    text-decoration: none;
  }
  .pl-publist__action:hover { text-decoration: underline; }
  .pl-publist__download::before { content: '\2193'; }
  .pl-publist__action--online::before { content: '\2197'; }
  .pl-publist__download-size { font-weight: 400; color: var(--pl-publist-muted); }

  /* ---- Variante: cards (Cover oben, ab md links) -------------------------
     Direkte Rasterkinder eines Items sind: __cover (optional), __meta, __body.
     Ohne Cover genuegt der natuerliche Fluss (eine Spalte); mit Cover bekommt
     das Bild die linke Spalte ueber beide Zeilen. */
  .pl-publist.-cards .pl-publist__item {
    display: grid;
    gap: 0.5rem;
    /* Karten-Innenpolster ist Komponenten-CSS (echte Karte). */
    padding: 1.25rem;
    border: 1px solid var(--pl-publist-line);
    align-content: start;
  }
  @media (min-width: 768px) {
    .pl-publist.-cards .pl-publist__items { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .pl-publist.-cards .pl-publist__item:has(.pl-publist__cover) {
      grid-template-columns: minmax(0, 7.5rem) minmax(0, 1fr);
      column-gap: 1rem;
      align-items: start;
    }
    .pl-publist.-cards .pl-publist__item > .pl-publist__cover { grid-row: 1 / span 2; grid-column: 1; }
    .pl-publist.-cards .pl-publist__item:has(.pl-publist__cover) > .pl-publist__meta,
    .pl-publist.-cards .pl-publist__item:has(.pl-publist__cover) > .pl-publist__body,
    .pl-publist.-cards .pl-publist__item:has(.pl-publist__cover) > .pl-publist__actions { grid-column: 2; }
  }

  /* ---- Variante: cover (Cover ueber die volle Kartenbreite) --------------
     Wie `cards`, aber das Cover steht randlos ueber der GANZEN Kartenbreite
     statt in einer Bildspalte oder mit Innenpolster. Darunter Metazeile, Titel,
     Angaben und die Aktionszeile.

     Warum eine eigene Variante und keine Aenderung an `cards`: das Paket laeuft
     auf mehreren Installationen. `cards` bleibt unveraendert, wer die neue
     Darstellung will, waehlt sie im Feld „Darstellung".

     Das Innenpolster sitzt an den TEXT-Kindern, nicht an der Karte — nur so
     laeuft das Bild bis an die Kartenkante. Karten sind Komponenten, ihr
     Innenpolster ist Komponenten-CSS (kein Sektions-Padding). */
  .pl-publist.-cover .pl-publist__item {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    border: 1px solid var(--pl-publist-line);
    align-content: start;
    padding: 0 0 1.25rem;
  }
  .pl-publist.-cover .pl-publist__cover {
    /* `width: 100%` ist NICHT redundant: ohne definite Breite schrumpft ein
       Kasten mit `aspect-ratio` bei gesetzter `max-height` auch seine BREITE,
       um das Verhaeltnis zu halten — die Kachel sass dann als 150x200-Block
       links in einer 390 px breiten Karte (gemessen 28.08.2026). Mit definiter
       Breite gewinnt `max-height`, die Kachel bleibt kartenbreit und das
       Verhaeltnis tritt zurueck. */
    width: 100%;
    aspect-ratio: var(--pl-publist-cover-ratio);
    /* Obergrenze der Kachelhoehe. Default `none` = bisheriges Verhalten (die
       Hoehe folgt allein dem Seitenverhaeltnis). Mit gesetztem Wert deckelt die
       Kachel ihre Hoehe; das Cover bleibt durch `object-fit: contain`
       vollstaendig sichtbar, wird nur kleiner und steht mittig. */
    max-height: var(--pl-publist-cover-max-height, none);
    background: var(--pl-publist-cover-bg);
  }
  /* Platzhalter-Kachel ohne Bilddatei: gleiche Flaeche, Publikationsart als
     zurueckhaltendes Label. Haelt das Raster auf gleicher Hoehe. */
  .pl-publist.-cover .pl-publist__cover.-empty {
    display: grid;
    place-items: center;
    padding: 1rem;
  }
  .pl-publist.-cover .pl-publist__cover-fallback {
    font-size: var(--pl-publist-cover-fallback-size, .75rem);
    letter-spacing: .14em;
    text-transform: uppercase;
    text-align: center;
    color: var(--pl-publist-muted);
  }
  .pl-publist.-cover .pl-publist__cover-img {
    width: 100%;
    height: 100%;
    object-fit: var(--pl-publist-cover-fit);
  }
  .pl-publist.-cover .pl-publist__meta { padding: 1.1rem 1.1rem 0.25rem; }
  .pl-publist.-cover .pl-publist__body { padding: 0 1.1rem; }
  .pl-publist.-cover .pl-publist__actions { padding: 0 1.1rem; }

  @media (min-width: 576px) {
    .pl-publist.-cover .pl-publist__items { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  @media (min-width: 992px) {
    .pl-publist.-cover .pl-publist__items { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }
  @media (min-width: 1400px) {
    .pl-publist.-cover .pl-publist__items { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  }

  /* ---- Variante: portrait (Hochformat-Cover links, Angaben rechts) ------
     Buecher sind fast immer hochformatig. Das Cover steht deshalb in einem
     HOCHFORMATIGEN Kasten (Seitenverhaeltnis `--pl-publist-cover-ratio`,
     Voreinstellung 3:4) am linken Kartenrand — randlos, ohne Innenpolster —
     und rechts daneben Metazeile, Titel, Angaben und Aktionen. Das Format
     darf von den uebrigen (querformatigen) Kacheln einer Site abweichen.

     Raster: eine Karte je Zeile, ab md zwei. INNERHALB der Karte bleibt das
     Cover in jeder Breite links (die Vorgabe „Beschreibung rechts" gilt auch
     mobil); die Kastenbreite ist ein Slot und skaliert per clamp() mit der
     Karte.

     Ein fehlendes Cover rendert das Template als Platzhalter-Kachel (wie in
     `cover`), sonst rutscht der Text an den Kartenrand und die Karten sehen
     unterschiedlich aus.

     Die Zeilen sind explizit: Cover ueber alle drei Zeilen, die dritte Zeile
     ist elastisch (`1fr`). Sonst verteilt das Raster die Hoehe eines hohen
     Covers gleichmaessig auf Meta/Body/Aktionen und reisst Luecken zwischen
     die Textbloecke.

     Das Innenpolster sitzt an den TEXT-Kindern, nicht an der Karte — nur so
     laeuft das Cover bis an die Kartenkante. Karten sind Komponenten, ihr
     Innenpolster ist Komponenten-CSS (kein Sektions-Padding). */
  --pl-publist-portrait-cover-width: clamp(7rem, 38%, 16rem);
  --pl-publist-portrait-gap: 1.25rem;
  --pl-publist-portrait-padding: 1.1rem;

  .pl-publist.-portrait .pl-publist__item {
    display: grid;
    grid-template-columns: var(--pl-publist-portrait-cover-width) minmax(0, 1fr);
    grid-template-rows: auto auto minmax(0, 1fr);
    column-gap: var(--pl-publist-portrait-gap);
    row-gap: 0.35rem;
    align-items: start;
    border: 1px solid var(--pl-publist-line);
    padding: 0;
  }
  .pl-publist.-portrait .pl-publist__cover {
    grid-column: 1;
    grid-row: 1 / span 3;
    width: 100%;
    aspect-ratio: var(--pl-publist-cover-ratio);
    background: var(--pl-publist-cover-bg);
  }
  .pl-publist.-portrait .pl-publist__cover.-empty {
    display: grid;
    place-items: center;
    padding: 1rem;
  }
  .pl-publist.-portrait .pl-publist__cover-fallback {
    font-size: var(--pl-publist-cover-fallback-size, .75rem);
    letter-spacing: .14em;
    text-transform: uppercase;
    text-align: center;
    color: var(--pl-publist-muted);
  }
  .pl-publist.-portrait .pl-publist__cover-img {
    width: 100%;
    height: 100%;
    object-fit: var(--pl-publist-cover-fit);
  }
  .pl-publist.-portrait .pl-publist__meta {
    grid-column: 2;
    grid-row: 1;
    padding: var(--pl-publist-portrait-padding) var(--pl-publist-portrait-padding) 0 0;
  }
  .pl-publist.-portrait .pl-publist__body {
    grid-column: 2;
    grid-row: 2;
    padding-right: var(--pl-publist-portrait-padding);
  }
  .pl-publist.-portrait .pl-publist__actions {
    grid-column: 2;
    grid-row: 3;
    padding-right: var(--pl-publist-portrait-padding);
  }
  /* Unterer Abstand am LETZTEN Textkind (Body oder Aktionen) — nicht an der
     Karte, sonst stuende das Cover nicht mehr buendig an der Unterkante. */
  .pl-publist.-portrait .pl-publist__item > :last-child:not(.pl-publist__cover) {
    padding-bottom: var(--pl-publist-portrait-padding);
  }

  @media (min-width: 768px) {
    .pl-publist.-portrait .pl-publist__items { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  /* ---- Variante: compact (Kundenvorlage) ---------------------------------
     Kleines Cover links oben, Aktionen rechts daneben, darunter Metazeile und
     Titel + Kurztext. Ziel ist eine KURZE Karte: die Handlung („ansehen",
     „herunterladen") steht oben statt am Ende einer langen Karte, dadurch wird
     die Seite deutlich kuerzer als in der Variante `cards`.

     Die Platzierung ist explizit (grid-row/grid-column) statt ueber
     `grid-template-areas`: Cover und Aktionen sind BEIDE optional, und mit
     Areas muesste jede Kombination eine eigene Vorlage bekommen. */
  .pl-publist.-compact .pl-publist__item {
    display: grid;
    grid-template-columns: minmax(0, 6.25rem) minmax(0, 1fr);
    column-gap: 1rem;
    row-gap: 0.4rem;
    padding: 1.1rem;
    border: 1px solid var(--pl-publist-line);
    align-content: start;
  }
  .pl-publist.-compact .pl-publist__cover {
    grid-column: 1;
    grid-row: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 10 / 7;
    background: var(--pl-publist-cover-bg);
  }
  .pl-publist.-compact .pl-publist__cover-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
  }
  .pl-publist.-compact .pl-publist__actions {
    grid-column: 2;
    grid-row: 1;
    margin: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.3rem;
  }
  /* Ohne Cover nimmt die Aktionszeile die volle Breite. */
  .pl-publist.-compact .pl-publist__item:not(:has(.pl-publist__cover)) > .pl-publist__actions { grid-column: 1 / -1; }
  .pl-publist.-compact .pl-publist__meta { grid-column: 1 / -1; grid-row: 2; margin-bottom: 0; }
  .pl-publist.-compact .pl-publist__body { grid-column: 1 / -1; grid-row: 3; }
  /* KEINE Heading-Typografie im Block-CSS: Groesse, Gewicht und Versalien des
     Kartentitels (<h3>) kommen aus den Settings-Slots h3-* und werden vom Theme
     ueber die CSS-Variablen `--bs-h3-*` verfeinert. */

  @media (min-width: 768px) {
    .pl-publist.-compact .pl-publist__items { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  @media (min-width: 992px) {
    .pl-publist.-compact .pl-publist__items { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }

  /* ---- Variante: rows (Jahr | Titel + Angaben, Hairline) ----------------- */
  .pl-publist.-rows .pl-publist__items { gap: 0; }
  .pl-publist.-rows .pl-publist__item {
    display: grid;
    gap: 0.25rem 1.5rem;
    padding-block: 1rem;
    border-top: 1px solid var(--pl-publist-line);
    align-content: start;
  }
  .pl-publist.-rows .pl-publist__item:last-child { border-bottom: 1px solid var(--pl-publist-line); }
  /* In der Zeilenvariante traegt die Meta-Spalte das Jahr — das Cover entfaellt. */
  .pl-publist.-rows .pl-publist__cover { display: none; }
  @media (min-width: 768px) {
    .pl-publist.-rows .pl-publist__item {
      grid-template-columns: minmax(0, 7rem) minmax(0, 1fr);
    }
    .pl-publist.-rows .pl-publist__meta { flex-direction: column; gap: 0.15rem; }
    /* Die Aktionszeile gehoert in die Textspalte, nicht unter die Jahres-Spalte. */
    .pl-publist.-rows .pl-publist__actions { grid-column: 2; }
  }
}
