/*
 * Das Kachel-Raster und die Grundform der Kacheln.
 *
 * Gemeinsam.
 * Die Zahl im Namen ist die Ladereihenfolge — bei CSS zählt sie.
 */

/*
 * Kachel-Raster. Spalten, Spaltenabstand und Höhe setzt die Section als
 * Inline-CSS (SectionGap, SectionHeight); der Wert hier greift nur, solange
 * nichts gesetzt ist.
 */
.spo-grid {
    display: grid;
    /*
     * Der Abstand kommt als Custom Property von der Reihe (ColumnsGap) — als
     * `gap` im Inline-CSS liesse er sich auf dem Telefon nicht begrenzen. Der
     * Rückfallwert ist der Kachelabstand des Designs.
     */
    gap: var(--spo-row-gap, 10px);
    /*
     * Die Höhe kommt als Custom Property von der Reihe (ColumnsHeight) und wird
     * hier angewendet, damit das Telefon sie gegen den zweiten Wert des Designs
     * tauschen kann (90-responsive.css). Als `height` im Inline-CSS wäre sie
     * unantastbar.
     *
     * Schreibt die Reihe keine — "Form des Bausteins", die Vorgabe —, ist die
     * Angabe zur Rechenzeit ungültig und fällt weg: dann sagt der Baustein, wie
     * hoch die Zelle wird (sein `aspect-ratio`), und die Höhe folgt der
     * Spaltenbreite. Genau das bedeutet diese Wahl.
     */
    height: var(--spo-row-height);
    margin-top: 10px;
    animation: spoTilesIn .46s cubic-bezier(.22, 1, .36, 1);
}

/*
 * Die Zelle gibt die Höhe, der Baustein füllt sie aus.
 *
 * Bis hierher stand hier `end`: jeder Baustein war so hoch, wie seine eigene
 * Form es sagte, und die Reihe richtete die kürzeren an ihrer Unterkante aus.
 * In einer Reihe aus gleich breiten Spalten fiel das nicht auf — gleiche Breite
 * und gleiches Verhältnis heißt gleiche Höhe, und die Unterkanten lagen ohnehin
 * auf einer Linie.
 *
 * In der Erlebnis-Reihe des Designs fällt es auf. Sie ist 1:1:2 geteilt, und
 * eine Kachel über zwei Spalten wurde mit `aspect-ratio: 1` doppelt so hoch wie
 * ihre Nachbarn: die Reihe stand in doppelter Höhe da, die beiden Quadrate
 * klebten an ihrem Boden, und darüber blieb eine leere Fläche.
 *
 * Jetzt ist die Höhe eine Angelegenheit der Reihe: `stretch` gibt jeder Zelle
 * die Höhe der Reihe, und der Baustein darin nimmt sie an (`height: 100%`
 * weiter unten). Wie hoch die Reihe selbst wird, sagt entweder sie selbst
 * (ColumnsHeight, eine Stufe in Pixeln) oder der Baustein, der eine Form
 * mitbringt — das Quadrat der Kachel. Eine Kachel über zwei Spalten steht damit
 * nur in einer Reihe mit Höhenvorgabe auf einer Linie mit ihren Nachbarn; ohne
 * Vorgabe ist sie so hoch wie breit und zieht die Reihe mit.
 *
 * Ausgerichtet wird damit nichts mehr, weil alle Zellen gleich hoch sind. Der
 * Boden, an dem das Menü klebt, bleibt der der Ebene (.spo-sheet:
 * align-items: flex-end) — das ist eine Frage des Sheets und nicht der Reihe.
 */
.spo-grid {
    align-items: stretch;
}

/*
 * Gibt die Reihe eine Höhe vor, gilt sie — und nicht die Form des Bausteins.
 *
 * Die Höhe am Raster (`height`, oben) stellt den Kasten auf ihr Maß. Die Zeile
 * darin ist damit nicht festgelegt: eine Rasterzeile ohne Angabe ist so hoch, wie
 * ihr Inhalt es verlangt, und eine Kachel mit `aspect-ratio: 1` verlangt ihre
 * Breite. In einer breiten Reihe war die Zelle deshalb höher als die Reihe und
 * lief über sie hinaus — in die Reihe darunter, sichtbar als übereinander
 * liegende Kacheln. Mit dem Maß der Reihe hatte das nichts mehr zu tun.
 *
 * `minmax(0, 1fr)` dreht das um: die 0 als Untergrenze heißt, dass der Inhalt
 * nicht mehr gegen die Vorgabe zählt, und das `1fr` füllt die Höhe des Kastens
 * aus. Damit ist die Reihe das Maß und die Form tritt zurück — genau das, was die
 * Wahl bedeutet. Der Baustein füllt seine Zelle ohnehin (`height: 100%`).
 *
 * Nur mit Vorgabe, deshalb an der Klasse: ohne sie hat der Kasten keine Höhe, die
 * ein `1fr` verteilen könnte.
 */
.spo-grid.spo-columns--height {
    grid-auto-rows: minmax(0, 1fr);
}

/*
 * "Nach Inhalt": die Zelle ist so hoch wie ihr Text, auch wenn der Baustein eine
 * Form mitbringt. Das ist die Wahl für eine Reihe, in der etwas Langes steht.
 *
 * Ohne diese Regel wäre "nach Inhalt" wieder "nach Breite": die Reihe schreibt
 * keine Höhe, und eine Kachel mit `aspect-ratio: 1` ist dann ein Quadrat.
 *
 * Die Bausteine stehen einzeln im Selektor, damit die Regel stärker ist als die
 * Form der Variante (.spo-button--blue und die anderen in 65-button.css): eine
 * Klasse mehr, und die Reihenfolge der Dateien spielt keine Rolle mehr.
 */
.spo-columns--height-content > .spo-tile,
.spo-columns--height-content > .spo-button,
.spo-columns--height-content > .spo-box,
.spo-columns--height-content > .spo-notice {
    aspect-ratio: auto;
}

/*
 * Der Abstand trennt Reihen voneinander. Steckt ein Stapel in der Spalte einer
 * Reihe, hat dessen erste Reihe ihn nicht – sonst stünde sie 10px tiefer als
 * die Höhe, die die äußere Reihe vorgibt. Mit Überschrift greift weiterhin der
 * Abstand darunter, die Regel gilt nur für das erste Kind.
 *
 * Der Stapel zwischen beiden ist für diesen Selektor unsichtbar: .spo-columns
 * bleibt Nachfahre von .spo-grid, auch wenn ein .spo-group dazwischen steht.
 */
.spo-grid .spo-columns > .spo-grid:first-child {
    margin-top: 0;
}

/*
 * Die Zelle gibt Breite und Höhe vor, der Baustein füllt sie aus – sonst säße er
 * in seiner eigenen Größe in einer zu großen Spalte.
 *
 * `min-width: 0` ist die zweite Hälfte der gleichen Aufteilung. Die Spalten
 * halten ihr Verhältnis über `minmax(0, 1fr)` (ColumnsPresenter), aber ein
 * Element in einer Spalte hat als Rasterzelle selbst eine Untergrenze: die
 * Breite seines Inhalts. Ohne diese Zeile stünde die Spalte auf ihrer Hälfte und
 * das Element ragte darüber hinaus. Mit ihr bricht der Inhalt um.
 *
 * Alle drei mit `!important`, und das ist hier keine Bequemlichkeit, sondern
 * dieselbe Sperre wie bei der Schrift (10-overlay.css) und beim Zeiger-Zustand
 * (65-button.css): das Menü liegt im Stylesheet einer Website, und dort redet
 * ständig jemand mit. `.menu a`, `nav button:hover`, `.teaser .btn` — jede
 * dieser Regeln ist spezifischer als eine einzelne Klasse von uns, und eine
 * davon mit `height` oder `min-width` darin nimmt dem Baustein die Zelle,
 * während die Reihe daneben weiter mit ihr rechnet. Genau die Wirkung war in der
 * Zielumgebung schon zweimal zu sehen, an der Schrift und am Fokus-Rahmen.
 *
 * Erzwungen wird bei der Breite die 0 und nicht die 100 %. Beides klingt nach
 * "füll die Zelle", aber `min-width: 100%` heißt "werde nie schmaler als deine
 * Zelle" — und weil die Untergrenze einer Rasterzelle in die Aufteilung
 * eingeht, zieht ein langes Wort damit seine Spalte auf. Eine Reihe 1:1:2 wäre
 * dann keine 1:1:2 mehr. Die Breite kommt aus der Zelle, und dass der Baustein
 * sie ausfüllt, sagt `width` — die Untergrenze hat damit nichts zu tun.
 */
.spo-tile,
.spo-button,
.spo-box,
.spo-notice {
    width: 100% !important;
    min-width: 0 !important;
    /*
     * Und die Höhe der Zelle, die `stretch` ihm gegeben hat. Im Frontend ist der
     * Baustein selbst die Zelle und die Zeile damit ohne Wirkung; auf der Bühne
     * des Editors stehen zwei Hüllen dazwischen (die Spalte und ihr Inhalt,
     * editor/99-chrome.css), und ohne sie stünde der Baustein dort in seiner
     * Inhaltshöhe in einer Zelle, die höher ist — die Bühne zeigte etwas
     * anderes als das Frontend.
     *
     * Die Form des Bausteins ist damit nicht weg, sie wechselt die Rolle: sie
     * sagt nicht mehr, wie hoch der Baustein wird, sondern wie hoch die Reihe
     * wird. Beim Ausmessen der Reihe steuert eine Kachel mit `aspect-ratio: 1`
     * ihre Breite als Höhe bei; steht die Höhe der Reihe fest, gilt für jede
     * Zelle diese Höhe — eine feste Höhe geht dem Seitenverhältnis vor, und die
     * Reihe ist damit die stärkere Angabe von beiden.
     *
     * Eine Unter- oder Obergrenze bleibt trotz `!important` möglich:
     * `min-height` und `max-height` gehen einer Höhe vor, auch einer erzwungenen.
     * Der Störer nutzt das schon (min-height: 123px, 64-box.css), und eine Reihe,
     * die ihren Zellen eine Spanne vorschreiben soll, käme an derselben Stelle
     * an — ohne dass diese Zeile ihr im Weg stünde.
     */
    height: 100% !important;
}

/*
 * Eine Reihe, die umbrechen darf (ColumnsElement::wraps).
 *
 * Flex statt Grid: ein Raster mit festen Spalten bricht nicht um — es läuft
 * über. Nur Flex legt seine Kinder in eine zweite Zeile, sobald der Platz für
 * alle in einer nicht mehr reicht. Die Schwelle ist die Mindestbreite einer
 * Spalte (ColumnMinWidth); sie kommt als Custom Property von der Reihe, weil
 * kein @media sie tragen könnte — gemessen wird die Reihe und nicht das
 * Fenster, und eine Reihe in der Spalte einer anderen ist schmaler als eine,
 * die die ganze Fläche hat.
 */
.spo-grid.spo-grid--wrap {
    display: flex;
    flex-wrap: wrap;
}

/*
 * `flex-basis: 0` und nicht die Mindestbreite als Basis: die Basis wird vor den
 * Gewichten verteilt, und eine Reihe "schmal und breit" stünde damit fast
 * gleich breit da. Mit Basis 0 verteilen allein die Gewichte — wie 1fr 2fr im
 * Raster —, und die Mindestbreite ist nur die Grenze, an der umgebrochen wird.
 *
 * `min(100%, …)` ist die Grenze der Grenze: die Mindestbreite gilt nur, solange
 * die Reihe sie hergibt. Ohne die Klammer schöbe ein grosser Wert die Zelle über
 * den Rand — 520px in einer Reihe von 328px (Telefon mit 360px Fenster) hiessen
 * eine 520px breite Kachel und eine Seite, die seitlich rollt. So bleibt auf dem
 * Telefon die Zelle so breit wie die Reihe und jede steht auf ihrer eigenen
 * Zeile; auf dem Schreibtisch ändert sie nichts, dort ist der Platz ohnehin da.
 *
 * Der Rückfallwert ist die Vorgabe aus ColumnMinWidth (Mittel); er greift nur,
 * wenn am Raster kein Inline-CSS steht.
 */
.spo-grid.spo-grid--wrap > * {
    flex: 1 1 0;
    min-width: min(100%, var(--spo-column-min, 160px));
    /*
     * Und die Höhe der Reihe als Untergrenze *einer Zelle*, nicht der Reihe: bricht
     * sie in zwei Zeilen, braucht sie das Doppelte, und ein `height` an der Reihe
     * schnitte die zweite ab (ColumnsPresenter schreibt dafür
     * `--spo-row-min-height`). Ohne Vorgabe fällt die Angabe weg.
     */
    min-height: var(--spo-row-min-height);
}

/*
 * Die Gewichte kommen einzeln von der Reihe
 * (ColumnsPresenter::weightProperties) — eine Regel je möglicher Spalte, und
 * mehr als vier hat eine Reihe nicht (ColumnsElement::MAX_COLUMNS). Im Frontend
 * gibt es keine Spalte, an die das Gewicht geschrieben werden könnte: dort ist
 * der Baustein selbst die Zelle.
 */
.spo-grid.spo-grid--wrap > :nth-child(1) {
    flex-grow: var(--spo-column-weight-1, 1);
}

.spo-grid.spo-grid--wrap > :nth-child(2) {
    flex-grow: var(--spo-column-weight-2, 1);
}

.spo-grid.spo-grid--wrap > :nth-child(3) {
    flex-grow: var(--spo-column-weight-3, 1);
}

.spo-grid.spo-grid--wrap > :nth-child(4) {
    flex-grow: var(--spo-column-weight-4, 1);
}

/*
 * Innenabstand, Grund, Schatten und Schrift stehen als Custom Properties da,
 * nicht als Wert: die Sperre am Ende dieser Datei holt sie im Zeiger- und
 * Fokus-Zustand zurück und muss sie dafür nicht ein zweites Mal kennen.
 */
.spo-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    aspect-ratio: 1;
    border-radius: 8px;
    overflow: hidden;
    --spo-tile-padding: 8px;
    --spo-tile-bg: var(--spo-tile-gradient);
    --spo-tile-fg: #fff;
    --spo-tile-shadow: 0 6px 16px rgba(45, 32, 10, .18);
    padding: var(--spo-tile-padding);
    background: var(--spo-tile-bg);
    box-shadow: var(--spo-tile-shadow);
    color: var(--spo-tile-fg);
    text-align: center;
    /*
     * Design: 14px auf dem Schreibtisch, 12px auf dem Telefon. Der Weg dazwischen
     * läuft mit der Fensterbreite (--spo-text-tile, tokens.css) und nicht über
     * einen Breakpoint: die Kachel wird stetig schmaler, ihre Aufschrift soll es
     * auch werden.
     */
    font-size: var(--spo-text-tile);
    /* Design: die Kachelbeschriftung steht auf 500, nicht auf dem geerbten 400 */
    font-weight: 500;
    cursor: pointer;
}

/*
 * Die breite Kachel behält ihre 14px auch dort, wo die quadratische heruntergeht
 * — in beiden Vorlagen steht sie auf 14px, sie hat den Platz. Auf dem
 * Schreibtisch sind beide gleich groß, und diese Zeile ist dann wirkungslos.
 */
.spo-tile--wide {
    aspect-ratio: auto;
    font-size: calc(14px - var(--spo-text-shrink));
}

/*
 * Design: die Beschriftung der CTA-Fläche steht auf 22px/400 – groß und leicht.
 *
 * Die Schriftfarbe ist die einzige Abweichung vom Export: dort steht Weiß, und
 * Weiß auf dem Orange des Designs kommt auf 2,1:1 — lesbar für den, der es
 * ohnehin schon weiß. Dunkelblau auf Orange sind 5,4:1, und es ist dasselbe
 * Paar, das das Design für den orangen Button und den CTA der Aktionsleiste
 * schon verwendet.
 */
.spo-tile--cta {
    aspect-ratio: 2.08;
    --spo-tile-bg: var(--spo-orange);
    --spo-tile-fg: var(--spo-blue-dark);
    /* 22px auf dem Schreibtisch, 18px auf dem Telefon (tokens.css) */
    font-size: var(--spo-text-cta);
    font-weight: 400;
}

/*
 * Eine Fläche, die etwas tut, ist im Frontend ein Knopf oder ein Link
 * (MenuElements/CallToAction, /Dynamic/Tile). Beide bringen ihre eigene
 * Schrift, ihren Rahmen und – der Link – eine Unterstreichung mit; die Fläche
 * soll aussehen wie die Fläche daneben, die nur ein <div> ist.
 *
 * Zurückgenommen wird nur, was die Klassen darüber nicht ohnehin setzen:
 * Schriftgröße, Gewicht und Ausrichtung stehen dort, und ein `font: inherit`
 * hier hätte sie mit seiner höheren Spezifität allesamt überschrieben — die
 * CTA-Fläche stünde wieder auf 12px.
 */
button.spo-tile,
a.spo-tile {
    border: 0;
    font-family: inherit;
    text-decoration: none;
}

.spo-tile-icon {
    display: flex;
    opacity: .95;
}

.spo-tile-icon img {
    width: 26px;
    height: 26px;
    display: block;
}

/*
 * Zeiger und Fokus ändern die Kachel nicht — auch dann nicht, wenn die Website
 * es sagt. Dieselbe Sperre wie bei Buttons (65-button.css), Zeilen
 * (63-accordion.css) und Leiste (30-actionbar.css), und aus demselben Anlass:
 * in der Zielumgebung steht
 *
 *     a:focus { outline: none; padding: 0; border: 2px solid #003C6E;
 *               white-space: nowrap; }
 *
 * und im Frontend ist eine Kachel mit Ziel ein <a>.
 *
 * Zwei Regeln, weil sie zwei verschiedene Fragen beantworten: das Aussehen
 * nimmt `:focus-visible` aus (der Ring ist ein Schatten und gehört ihm), die
 * Geometrie nicht (Innenabstand und Ring stören sich nicht).
 */
.spo-tile:hover:not(:focus-visible),
.spo-tile:focus:not(:focus-visible) {
    background: var(--spo-tile-bg) !important;
    color: var(--spo-tile-fg) !important;
    box-shadow: var(--spo-tile-shadow) !important;
    opacity: var(--spo-tile-opacity, 1) !important;
    text-decoration: none !important;
    transform: none !important;
    filter: none !important;
}

.spo-tile:hover,
.spo-tile:focus {
    padding: var(--spo-tile-padding) !important;
    border: var(--spo-tile-border, 0) !important;
    white-space: normal !important;
}
