/* ============================================================
   Phi EC · Design-Tokens "Achse"
   Quelle: 02-corporate-design/CD.md · DESIGN.md (Novamira-Slug: achse)

   Wird nach /wp-content/phiec-cd/tokens.css kopiert und dort von
   wp-content/novamira-sandbox/phiec-cd.php eingebunden. Die Datei
   laedt als letzte Stildatei der Seite, nach Hello Elementor, nach
   Elementor und nach dem Kit. Gleiche Spezifitaet gewinnt deshalb
   hier. Das ist die einzige Stelle, an der das CD durchgesetzt wird.

   Aufbau:
     0  Schriften
     1  Tokens
     2  Bruecke zu Elementor und Hello Elementor
     3  Typografie
     4  Rhythmus, Raster, Flaechen
     5  Schaltflaechen
     6  Kopf- und Fusszeile
     7  Komponenten
     8  Bildflaechen und Signaturbewegungen
     9  Zustaende, Details, Bewegung
    10  Druck

   Bestehende Klassennamen bleiben unveraendert, weil die
   Seitenvorlagen sie benutzen. Neues kommt dazu, nichts faellt weg.
   ============================================================ */


/* ============================================================
   0 · Schriften
   ------------------------------------------------------------
   fonts.css im selben Ordner verweist auf http://, die Seite laeuft
   auf https. Browser behandeln Schriften als blockierbaren
   Mixed Content und laden sie dann gar nicht. Ergebnis bisher:
   Systemschrift statt Archivo und Public Sans, und damit ein
   Auftritt, der nichts vom CD zeigt.

   Dieselben Dateien stehen hier noch einmal mit relativem Pfad.
   Relativ heisst gleiches Protokoll, gleiche Domain, kein Request
   an Dritte. Diese Deklaration steht nach fonts.css und gewinnt.

   Saubere Loesung: in fonts.css http://www.phiec.de/wp-content/
   phiec-cd/ durch /wp-content/phiec-cd/ ersetzen. Dann kann dieser
   Block hier ersatzlos weg.
   ============================================================ */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("fonts/archivo-latin-b9202932.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("fonts/archivo-latin-ext-c422bfcf.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Public Sans';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/public-sans-latin-e769ef35.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Public Sans';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/public-sans-latin-ext-98f94fdc.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* ============================================================
   1 · Tokens
   ============================================================ */

:root {
  /* --- Grund und Ink --- */
  --phi-bg:            #F4F3EF;   /* Knochen, Seitengrund */
  --phi-surface:       #FFFFFF;   /* Flächen, Karten, Tabellen */
  --phi-ink:           #16191A;   /* Graphit, Fließtext, dunkler Grund */

  /* --- Neutraltonleiter, zum Knochengrund gestimmt --- */
  --phi-n-0:           #FFFFFF;
  --phi-n-50:          #F4F3EF;
  --phi-n-100:         #EAE8E1;   /* Bänder, Tabellenkopf */
  --phi-n-200:         #DAD8CF;   /* Haarlinien, Rahmen */
  --phi-n-300:         #BCB9AE;   /* deaktiviert, Platzhalter */
  --phi-n-400:         #8D8A80;   /* Sekundärtext, erst ab 18px */
  --phi-n-500:         #615F57;   /* Labels, Bildunterschriften */
  --phi-n-600:         #3C3E3B;
  --phi-n-900:         #16191A;

  /* Haarlinie auf dunklem Grund. Kein eigener Farbwert, sondern der
     Knochengrund mit 16 Prozent Deckkraft. So bleibt die Palette
     geschlossen, und die Linie stimmt automatisch, egal auf welchem
     dunklen Ton sie liegt. */
  --phi-ink-line:      rgba(244, 243, 239, .16);

  /* --- Engineering --- */
  --phi-eng:           #0F5B5B;
  --phi-eng-dark:      #0A4140;
  --phi-eng-tint:      #E4EEED;

  /* --- Transport --- */
  --phi-trp:           #C1121F;
  --phi-trp-dark:      #8E1017;
  --phi-trp-tint:      #F9E8E9;

  /* --- Status, nur Formulare und Systemmeldungen --- */
  --phi-success:       #1E6E42;
  --phi-warning:       #9A6400;
  --phi-danger:        #A31621;

  /* --- Aktiver Akzent. Wird je Seitenbaum umgesetzt. --- */
  --phi-accent:        var(--phi-eng);
  --phi-accent-dark:   var(--phi-eng-dark);
  --phi-accent-tint:   var(--phi-eng-tint);

  /* --- Schrift --- */
  --phi-font-display:  "Archivo", "Archivo Expanded", system-ui, sans-serif;
  --phi-font-body:     "Public Sans", system-ui, sans-serif;

  /* Archivo liegt als variable Schrift vor, Breitenachse 62 bis 125.
     Display läuft in der breiten Fassung, Zwischenüberschriften in
     der normalen. Das ist die "Expanded"-Vorgabe aus dem CD, aber
     als Achsenwert statt als zweite Schriftdatei. */
  --phi-wdth-display:  118%;
  --phi-wdth-normal:   100%;

  /* --- Abstände, 4px-Basis --- */
  --phi-s-1:  4px;
  --phi-s-2:  8px;
  --phi-s-3:  12px;
  --phi-s-4:  16px;
  --phi-s-6:  24px;
  --phi-s-8:  32px;
  --phi-s-12: 48px;
  --phi-s-16: 64px;
  --phi-s-24: 96px;
  --phi-s-32: 128px;
  --phi-s-40: 160px;

  /* --- Form --- */
  --phi-radius:        2px;
  --phi-line:          1px solid var(--phi-n-200);
  --phi-shadow:        0 1px 2px rgba(22, 25, 26, .08);

  /* --- Raster --- */
  --phi-content-max:   1280px;
  --phi-measure:       68ch;
  --phi-gutter:        24px;

  /* Seitenrand. Wird für die Randabfaller gebraucht, deshalb steht
     er als Token und nicht nur als Padding in .phi-wrap. */
  --phi-wrap-pad:      20px;

  /* --- Bewegung. Regler steht auf 0.25. --- */
  --phi-t-state:       120ms;   /* Zustandswechsel an Bedienelementen */
  --phi-t-reveal:      240ms;   /* Einblenden beim Scrollen */
  --phi-ease:          cubic-bezier(.2, 0, 0, 1);

  /* --- Rhythmus. Ein Abschnitt setzt diese beiden Werte, die
         Rhythmusmaschine in Abschnitt 4 liest sie aus. --- */
  --phi-rhythm-top:    var(--phi-s-12);
  --phi-rhythm-bottom: var(--phi-s-12);
}

@media (min-width: 700px)  { :root { --phi-wrap-pad: 40px; } }
@media (min-width: 1100px) { :root { --phi-wrap-pad: 64px; } }

/* Seitenbaum-Umschaltung. Klasse auf <body> setzen. */
body.phi-engineering {
  --phi-accent:      var(--phi-eng);
  --phi-accent-dark: var(--phi-eng-dark);
  --phi-accent-tint: var(--phi-eng-tint);
}
body.phi-transport {
  --phi-accent:      var(--phi-trp);
  --phi-accent-dark: var(--phi-trp-dark);
  --phi-accent-tint: var(--phi-trp-tint);
}

/* Spartenumschaltung auf Abschnittsebene. Das CD gibt je
   Geschäftsbereich genau eine Signalfarbe vor. Statt jede
   Komponente doppelt zu bauen, schaltet eine Klasse den Akzent um
   und alles darunter erbt ihn. So bleibt die Regel "eine
   Akzentfarbe pro Seite" wahr, ohne zweiten Satz Bausteine.
   Die Dachseite bleibt neutral und zeigt die Sparten nur als
   2px-Oberkante an den beiden Türen. */
.phi-scope-transport {
  --phi-accent:      var(--phi-trp);
  --phi-accent-dark: var(--phi-trp-dark);
  --phi-accent-tint: var(--phi-trp-tint);
}
.phi-scope-engineering {
  --phi-accent:      var(--phi-eng);
  --phi-accent-dark: var(--phi-eng-dark);
  --phi-accent-tint: var(--phi-eng-tint);
}

/* Und dieselbe Umschaltung noch einmal fuer das ganze Dokument.
   ------------------------------------------------------------
   Die beiden Klassen daruber wirken nur innerhalb ihres eigenen
   Containers. Damit deckten sie auf einer Transportseite genau den
   ersten Abschnitt ab: Kopfzeile, Fusszeile und jeder weitere
   Abschnitt behielten den Vorgabeakzent Tiefteal. Gemessen auf
   /transport/: Wortmarke, Sprunglink und die Kontakt-Schaltflaeche
   in der Kopfzeile standen in #0F5B5B, waehrend der Seiteninhalt in
   Verkehrsrot lief. Der Inspektor meldete das als A7.1 "beide
   Spartenfarben auf einer Seite", auf allen vier Transportseiten,
   und er hatte recht.

   Das aktive Design sieht dafuer eine Klasse am Seitenrumpf vor.
   Die setzt WordPress hier aber nicht, und ein PHP-Eingriff waere
   dafuer zu viel: Seiten-IDs wechseln bei jedem rebuild.php, taugen
   also nicht als Anker.

   :has() loest das ohne PHP. Traegt irgendein Element im Dokument
   die Spartenklasse, faellt der Akzent fuer das ganze Dokument um,
   Kopf- und Fusszeile eingeschlossen. Die Dachseite traegt keine
   der beiden Klassen und bleibt neutral. */
html:has(.phi-scope-transport) {
  --phi-accent:      var(--phi-trp);
  --phi-accent-dark: var(--phi-trp-dark);
  --phi-accent-tint: var(--phi-trp-tint);
}
html:has(.phi-scope-engineering) {
  --phi-accent:      var(--phi-eng);
  --phi-accent-dark: var(--phi-eng-dark);
  --phi-accent-tint: var(--phi-eng-tint);
}


/* ============================================================
   2 · Brücke zu Elementor und Hello Elementor
   ------------------------------------------------------------
   Ohne diesen Abschnitt greifen die CD-Klassen nur halb. Er
   entschärft drei Voreinstellungen, die gegen das CD arbeiten.
   ============================================================ */

/* 2.1 Elementor hängt die CSS-Klasse eines Widgets an den
   Widgetrahmen, nicht an das Element darin. Eine Überschrift
   behält deshalb die Kit-Größe (4rem), egal welche Klasse
   am Rahmen steht. Hier erbt sie wieder von ihrem Rahmen,
   damit .phi-display-xl und .phi-display-l wirken. */
.phi-display-xl .elementor-heading-title,
.phi-display-l  .elementor-heading-title,
.phi-lead       .elementor-heading-title {
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  margin: 0;
}

/* Überschriften-Widgets ohne CD-Klasse laufen sonst ebenfalls auf
   4rem. Sie bekommen hier die Stufe, die zu ihrem Tag gehört. */
.elementor-widget-heading h2.elementor-heading-title {
  font-size: clamp(1.75rem, 3vw, 2.75rem);
  line-height: 1.08;
  letter-spacing: -.01em;
  font-weight: 700;
  font-stretch: var(--phi-wdth-normal);
}
.elementor-widget-heading h3.elementor-heading-title {
  font-size: 1.375rem;
  line-height: 1.2;
  letter-spacing: -.005em;
  font-weight: 700;
  font-stretch: var(--phi-wdth-normal);
}

/* 2.2 Hello Elementor setzt Bildunterschriften kursiv und in
   Grau. Das CD setzt sie aufrecht in n-500. */
figcaption,
.wp-caption-text {
  font-style: normal;
  color: var(--phi-n-500);
}

/* 2.3 Elementor-Container tragen von Haus aus keinen Seitenrand.
   Wo .phi-wrap fehlt, klebt der Text sonst am Displayrand. Die
   Regel greift nur auf der obersten Ebene einer Seite, damit
   verschachtelte Container nicht doppelt einrücken, und nicht in
   Kopf- und Fußzeile, die ihr eigenes Innenmaß haben. */
[data-elementor-type="wp-page"] > .e-con.e-parent:not(.phi-wrap):not(:has(.phi-wrap)) {
  padding-inline: var(--phi-wrap-pad);
}


/* ============================================================
   3 · Typografie
   ------------------------------------------------------------
   Grundsatz aus dem CD: Display steht eng, Fließtext läuft weit.
   Die Laufweite ist an den Schriftgrad gekoppelt, nicht frei
   gewählt: je größer der Grad, desto negativer die Laufweite.
   ============================================================ */

body {
  background: var(--phi-bg);
  color: var(--phi-ink);
  font-family: var(--phi-font-body);
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Deutsche Komposita sind lang. Ohne diese beiden Zeilen sprengt
     "Simulationsautomatisierung" jede schmale Spalte. */
  text-rendering: optimizeLegibility;
  font-kerning: normal;
}

.phi-display-xl,
.phi-display-l,
h1, h2, h3 {
  font-family: var(--phi-font-display);
  font-weight: 800;
  color: var(--phi-ink);
  text-wrap: balance;
  /* Kein Wortbruch in Überschriften. `break-word` trennt mitten im Wort,
     sobald ein Wort breiter ist als seine Spalte, und macht aus
     "Engineering." ein "Engineerin g.". Das CD löst den Fall anders:
     Eine Überschrift, die nicht in zwei Zeilen passt, ist ein
     Schriftgradfehler, kein Umbruchproblem. Also lieber der Größe
     nachhelfen als das Wort zerschneiden. */
  overflow-wrap: normal;
  word-break: normal;
  hyphens: manual;
}

.phi-display-xl {
  /* 8vw waren zu viel: bei 1440px ergibt das 115px, und eine Zeile wie
     "Engineering. Transport." braucht dann rund 1650px. Sie passte in
     keine Spalte und brach mitten im Wort. Der Deckel liegt jetzt so,
     dass die längste Zeile über die volle Inhaltsbreite in eine Zeile
     geht. Wer die Headline schmaler stellt, muss die Größe mitnehmen. */
  font-size: clamp(2rem, 4.8vw, 4.25rem);
  line-height: 1;
  letter-spacing: -.02em;
  text-transform: uppercase;
  font-stretch: var(--phi-wdth-display);
  /* Versalien haben keine Unterlängen. Der Zeilenabstand darf
     deshalb unter 1 gehen, sobald die Schrift groß genug ist,
     dass die enge Führung als Absicht gelesen wird. Auf kleinen
     Displays bleibt er bei 1, sonst kleben zwei Zeilen. */
  margin-block: 0 var(--phi-s-6);
}
@media (min-width: 900px) {
  .phi-display-xl { line-height: .94; letter-spacing: -.024em; }
}

.phi-display-l, h1 {
  font-size: clamp(2.25rem, 5vw, 4rem);
  line-height: 1.02;
  letter-spacing: -.015em;
  font-stretch: var(--phi-wdth-display);
  margin-block: 0 var(--phi-s-4);
}
@media (min-width: 900px) {
  .phi-display-l, h1 { line-height: .98; letter-spacing: -.018em; }
}

h2 {
  font-size: clamp(1.75rem, 3vw, 2.75rem);
  line-height: 1.08;
  letter-spacing: -.01em;
  font-weight: 700;
  font-stretch: var(--phi-wdth-normal);
}

h3 {
  font-size: 1.375rem;
  line-height: 1.2;
  letter-spacing: -.005em;
  font-weight: 700;
  font-stretch: var(--phi-wdth-normal);
}

/* Die Übergänge zwischen den Stufen. Zwei Überschriften direkt
   hintereinander sind ein Sprung, kein Absatz: der Abstand wird
   halbiert, sonst zerfällt die Gruppe. */
h2 + h3, h3 + h4, .phi-display-l + h2 { margin-top: var(--phi-s-3); }

.phi-lead,
.phi-lead p {
  font-size: 1.25rem;
  line-height: 1.55;
  max-width: var(--phi-measure);
  color: var(--phi-n-600);
  text-wrap: pretty;
}
/* Auf 390px traegt der Vorspann bei 20px nur 27 Zeichen je Zeile, und
   unter 28 wird Lesen zum Stolpern (M4.1, Baymard nennt 30 bis 50 als
   Zielbereich fuer Mobil). Gemessen, nicht geschaetzt: 350px nutzbare
   Breite geteilt durch die mittlere Zeichenbreite. Bei 18px sind es
   rund 30 Zeichen. Die CD-Stufe "Lead" bleibt am Schreibtisch
   unveraendert, sie wird nur auf dem Telefon eine Stufe kleiner. */
@media (max-width: 480px) {
  .phi-lead,
  .phi-lead p { font-size: 1.125rem; }
}
/* Der Vorspann steht direkt unter der Headline und gehört zu ihr.
   Deshalb rückt er heran statt den vollen Widgetabstand zu nehmen. */
.phi-display-xl + .phi-lead,
.phi-display-l  + .phi-lead { margin-top: calc(-1 * var(--phi-s-2)); }

p, li {
  max-width: var(--phi-measure);
  text-wrap: pretty;
}

.phi-small, .phi-small p { font-size: .875rem; line-height: 1.5; }

.phi-label,
.phi-label p {
  font-family: var(--phi-font-body);
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--phi-n-500);
  max-width: none;
}
/* Ein Versallabel gehört zu dem, was darunter steht. */
.phi-label + * { margin-top: var(--phi-s-3); }

/* Zahlen tabellarisch: Preise, km, kWh, Aktenzeichen */
table, .phi-num, .phi-proof__value, .phi-facts__row dd, time {
  font-variant-numeric: tabular-nums;
}

/* Textauszeichnung. Fett bleibt in der Familie, keine zweite
   Schrift, keine Farbe außer Ink. */
strong, b { font-weight: 700; color: inherit; }

/* Markierung in der Markenfarbe. Ein Detail, das kostenlos ist
   und trotzdem auffällt. */
::selection { background: var(--phi-accent); color: #FFFFFF; }


/* ============================================================
   4 · Rhythmus, Raster, Flächen
   ------------------------------------------------------------
   Bisher trug fast jeder Abschnitt oben und unten dasselbe Maß.
   Gleichmaß liest sich als Aufzählung, nicht als Komposition.

   Die Rhythmusmaschine: jeder Abschnitt der obersten Ebene liest
   zwei Variablen aus. Die Abschnittsklassen setzen sie, und
   Nachbarschaftsregeln korrigieren sie. Der Abstand zwischen zwei
   Abschnitten ist die Summe aus dem unteren Maß des einen und dem
   oberen des anderen. Zielmaß aus dem CD: 96px mobil, 128px
   Desktop, also zweimal 48 beziehungsweise zweimal 64.
   ============================================================ */

[data-elementor-type="wp-page"] > .e-con.e-parent,
.phi-section {
  padding-block: var(--phi-rhythm-top) var(--phi-rhythm-bottom);
}

@media (min-width: 900px) {
  :root {
    --phi-rhythm-top:    var(--phi-s-16);
    --phi-rhythm-bottom: var(--phi-s-16);
  }
}

/* Der Normalfall. */
.phi-section {
  --phi-rhythm-top:    var(--phi-s-12);
  --phi-rhythm-bottom: var(--phi-s-12);
}
@media (min-width: 900px) {
  .phi-section {
    --phi-rhythm-top:    var(--phi-s-16);
    --phi-rhythm-bottom: var(--phi-s-16);
  }
}

/* Enger Abschnitt: gehört zum vorigen, wird nur abgesetzt. */
.phi-section--tight {
  --phi-rhythm-top:    var(--phi-s-8);
  --phi-rhythm-bottom: var(--phi-s-8);
}

/* Weiter Abschnitt: trägt eine große Aussage und braucht Luft. */
.phi-section--airy {
  --phi-rhythm-top:    var(--phi-s-16);
  --phi-rhythm-bottom: var(--phi-s-16);
}
@media (min-width: 900px) {
  .phi-section--airy {
    --phi-rhythm-top:    var(--phi-s-24);
    --phi-rhythm-bottom: var(--phi-s-24);
  }
}

/* Der Hero sitzt unter einer klebenden Kopfzeile. Ein großes Maß
   oben verschenkt den ersten Bildschirm, den das CD ausdrücklich
   für Headline, Vorspann und Schaltfläche reserviert. Unten darf
   er dafür großzügig sein. */
.phi-hero {
  --phi-rhythm-top:    var(--phi-s-8);
  --phi-rhythm-bottom: var(--phi-s-12);
}
@media (min-width: 900px) {
  .phi-hero {
    --phi-rhythm-top:    var(--phi-s-12);
    --phi-rhythm-bottom: var(--phi-s-16);
  }
}

/* Die Nachweisleiste ist ein Band, kein Abschnitt. Sie trennt
   über ihre Fläche, nicht über Weißraum. */
.phi-proof {
  --phi-rhythm-top:    var(--phi-s-8);
  --phi-rhythm-bottom: var(--phi-s-8);
}

/* Die dunkle Fläche ist die lauteste Stelle der Seite. Sie
   bekommt das größte Maß, damit sie als Zäsur wirkt. */
.phi-dark {
  --phi-rhythm-top:    var(--phi-s-16);
  --phi-rhythm-bottom: var(--phi-s-16);
}
@media (min-width: 900px) {
  .phi-dark {
    --phi-rhythm-top:    var(--phi-s-24);
    --phi-rhythm-bottom: var(--phi-s-24);
  }
}

/* Nachbarschaften. Hier entsteht der eigentliche Wechsel.
   Ein Band bringt seine eigene Trennung mit, der Abschnitt
   danach muss den Abstand nicht noch einmal zahlen. */
.phi-proof + .phi-section,
.phi-band  + .phi-section {
  --phi-rhythm-top: var(--phi-s-12);
}
/* Nach einer dunklen Fläche braucht das Auge mehr, nicht weniger. */
.phi-dark + .phi-section {
  --phi-rhythm-top: var(--phi-s-24);
}
/* Der erste Abschnitt einer Unterseite schließt an den Seitenkopf
   an und rückt heran. */
.phi-pagehead + .phi-section {
  --phi-rhythm-top: var(--phi-s-12);
}

.phi-wrap {
  max-width: var(--phi-content-max);
  margin-inline: auto;
  padding-inline: var(--phi-wrap-pad);
  box-sizing: border-box;
}

.phi-dark {
  background: var(--phi-ink);
  color: var(--phi-bg);
}
.phi-dark h1, .phi-dark h2, .phi-dark h3 { color: var(--phi-bg); }
.phi-dark .phi-lead, .phi-dark .phi-lead p { color: var(--phi-n-300); }
.phi-dark .phi-label { color: var(--phi-n-400); }
.phi-dark a { color: var(--phi-bg); text-decoration-color: var(--phi-n-400); }
.phi-dark hr, .phi-dark .phi-rule { border-top-color: var(--phi-ink-line); }

.phi-band { background: var(--phi-n-100); }
.phi-rule { border: 0; border-top: var(--phi-line); margin: 0; }
hr { border: 0; border-top: var(--phi-line); }

/* Karten nur bei echter Hierarchie. Sonst Haarlinie oder Weißraum. */
.phi-card {
  background: var(--phi-surface);
  border: var(--phi-line);
  border-radius: var(--phi-radius);
  padding: var(--phi-s-8);
}

/* Asymmetrischer Zweispalter. Kippt unter 900px untereinander.
   Der Zwischenraum wächst mit der Bildschirmbreite, damit die
   beiden Spalten auf großen Schirmen nicht zusammenlaufen. */
.phi-split {
  display: flex;
  gap: clamp(var(--phi-s-8), 5vw, var(--phi-s-24));
  align-items: flex-start;
}
.phi-split > :first-child { flex: 0 1 62%; }
.phi-split > :last-child  { flex: 0 1 38%; }
.phi-split--flip > :first-child { flex: 0 1 38%; }
.phi-split--flip > :last-child  { flex: 0 1 62%; }
/* Der Zweispalter bricht im GANZEN Tabletband um, nicht erst bei
   900px. Anweisung des Nutzers vom 2026-08-23, und sie deckt sich
   mit der Messung: Auf dem iPad blieb fuer die Nebenspalte eine
   Restbreite, in der weder die Faktenliste noch der Fliesstext
   daneben vernuenftig standen. Das Zwischenband ist genau die
   Breite, in der das Schreibtischlayout schon greift und der Platz
   nicht reicht (Pruefliste, Abschnitt T).

   Auf dem Tablet gilt deshalb dasselbe wie auf dem Telefon: eine
   Spalte, und die Nebenspalte wandert unter den Text. 1199px ist
   die Obergrenze des Tabletbands aus der Pruefliste. */
@media (max-width: 1199px) {
  /* display:block muss BEIDE Ebenen treffen. Bei einem "boxed"
     Container legt Elementor die Flex-Reihe nicht auf das Element
     mit unserer Klasse, sondern auf das innere .e-con-inner. Ein
     display:block nur aussen laesst die Reihe bestehen: Die Kinder
     bekommen zwar width:100%, schrumpfen als Flex-Elemente aber
     wieder auf die halbe Breite. Gemessen auf /kontakt/ am iPad:
     Spalte 350px statt 720px, und darin eine 224px-Labelspur, die
     dem Wert 90px uebrig liess.

     Und wie ueberall bei Elementor braucht es !important, weil die
     eigene Regel dieselbe Spezifitaet hat und frueher steht. */
  .phi-split,
  .phi-split > .e-con-inner {
    display: block !important;
  }
  .phi-split > * + *,
  .phi-split > .e-con-inner > * + * { margin-top: var(--phi-s-12); }

  /* Der Umbruch allein reicht nicht. Elementor schreibt die
     Spaltenbreite als eigene Regel auf das Kind ("width: 38%"), und
     die überlebt das display:block am Elternteil ungerührt. Die
     Spalte bleibt dann 38 Prozent breit, obwohl sie untereinander
     steht, und ihr Inhalt läuft seitlich heraus.

     Gemessener Fall: Auf dem iPad stand die Faktenliste von
     /kontakt/ in einer 246px-Spalte mit einer 224px breiten
     Labelspalte darin. Der Wert daneben bekam 105px, die Anschrift
     brauchte 159px, und die Seite weitete den Viewport von 820 auf
     913px auf (Befund A5.1).

     Dasselbe Muster wie beim Hero: gegen Elementors eigene
     Spezifität hilft nur !important. */
  .phi-split > *,
  .phi-split > .e-con-inner > * {
    width: 100% !important;
    max-width: 100% !important;
    flex-basis: auto !important;
  }
}

/* Seitenkopf einer Unterseite. Kein zweiter Hero. */
.phi-pagehead { border-bottom: var(--phi-line); }
.phi-pagehead h1 { max-width: 18ch; }
.phi-pagehead p  { max-width: 60ch; }


/* ============================================================
   5 · Schaltflächen
   ------------------------------------------------------------
   Eine Beschriftung pro Absicht: Engineering "Projekt besprechen",
   Transport "Angebot anfordern", allgemein "Kontakt".

   Wichtig: Elementor hängt .phi-btn an den Widgetrahmen, der
   eigentliche Link darin ist .elementor-button und trägt die
   Kit-Voreinstellung. Ohne die Regel in 5.1 stünde weiße Schrift
   auf Knochengrund in einem tiefteal Kasten, also unlesbar.
   ============================================================ */

/* 5.1 Der Widgetrahmen wird durchlässig, die Fläche wandert auf
   den Link. Höhere Spezifität als .phi-btn--primary, damit die
   Farbe nicht am Rahmen hängen bleibt. */
.elementor-widget-button.phi-btn {
  display: inline-flex;
  padding: 0;
  border: 0;
  background: none;
}

.phi-btn,
.phi-btn .elementor-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--phi-s-2);
  padding: var(--phi-s-4) 28px;
  border-radius: var(--phi-radius);
  font-family: var(--phi-font-body);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1;
  letter-spacing: 0;
  text-transform: none;
  text-decoration: none;
  border: 1.5px solid transparent;
  cursor: pointer;
  /* Nur transform und Farbe, nichts anderes. Elementor setzt hier
     sonst "all .3s", das animiert auch Maße. */
  transition: background-color var(--phi-t-state) var(--phi-ease),
              color            var(--phi-t-state) var(--phi-ease),
              border-color     var(--phi-t-state) var(--phi-ease),
              transform        var(--phi-t-state) var(--phi-ease);
}

.phi-btn--primary,
.phi-btn--primary .elementor-button {
  background: var(--phi-accent);
  color: #FFFFFF;
  border-color: var(--phi-accent);
}
.phi-btn--primary:hover,
.phi-btn--primary .elementor-button:hover,
.phi-btn--primary .elementor-button:focus {
  background: var(--phi-accent-dark);
  border-color: var(--phi-accent-dark);
  color: #FFFFFF;
}
/* Beim Drücken 1px nach unten. Das ist der ganze Effekt. */
.phi-btn--primary:active,
.phi-btn--primary .elementor-button:active { transform: translateY(1px); }

.phi-btn--secondary,
.phi-btn--secondary .elementor-button {
  background: transparent;
  color: var(--phi-accent);
  border-color: var(--phi-accent);
}
.phi-btn--secondary:hover,
.phi-btn--secondary .elementor-button:hover,
.phi-btn--secondary .elementor-button:focus {
  background: var(--phi-accent-tint);
  color: var(--phi-accent-dark);
  border-color: var(--phi-accent-dark);
}
.phi-btn--secondary:active,
.phi-btn--secondary .elementor-button:active { transform: translateY(1px); }

.phi-btn--tertiary,
.phi-btn--tertiary .elementor-button {
  padding: 0;
  background: none;
  color: var(--phi-accent);
  border: 0;
  border-bottom: 2px solid var(--phi-accent);
  border-radius: 0;
}
.phi-btn--tertiary:hover,
.phi-btn--tertiary .elementor-button:hover {
  color: var(--phi-accent-dark);
  border-bottom-color: var(--phi-accent-dark);
}

/* Auf dunklem Grund kehrt sich die primäre Fläche um. */
.phi-dark .phi-btn--primary,
.phi-dark .phi-btn--primary .elementor-button,
.phi-footer .phi-btn--primary,
.phi-footer .phi-btn--primary .elementor-button {
  background: var(--phi-bg);
  color: var(--phi-ink);
  border-color: var(--phi-bg);
}
.phi-dark .phi-btn--primary .elementor-button:hover,
.phi-footer .phi-btn--primary .elementor-button:hover {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: var(--phi-ink);
}
.phi-dark .phi-btn--secondary,
.phi-dark .phi-btn--secondary .elementor-button {
  color: var(--phi-bg);
  border-color: var(--phi-n-400);
  background: transparent;
}
.phi-dark .phi-btn--secondary .elementor-button:hover {
  border-color: var(--phi-bg);
  background: rgba(244, 243, 239, .08);
  color: #FFFFFF;
}

/* Absendeknöpfe von Fluent Forms folgen derselben Regel, sonst
   steht mitten im Formular ein fremder Knopf. */
.ff-btn-submit,
.frm-fluent-form .ff-btn-submit {
  background: var(--phi-accent);
  color: #FFFFFF;
  border: 1.5px solid var(--phi-accent);
  border-radius: var(--phi-radius);
  padding: var(--phi-s-4) 28px;
  font-family: var(--phi-font-body);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1;
  box-shadow: none;
  transition: background-color var(--phi-t-state) var(--phi-ease);
}
.ff-btn-submit:hover { background: var(--phi-accent-dark); }


/* ============================================================
   6 · Kopf- und Fußzeile
   Gebaut mit Ultimate Addons for Elementor, weil der Theme Builder
   zu Elementor Pro gehört.
   ============================================================ */

.phi-header {
  border-bottom: var(--phi-line);
  background: var(--phi-bg);
  position: sticky;
  top: 0;
  z-index: 50;
}
.phi-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--phi-s-8);
  min-height: 72px;
  max-width: var(--phi-content-max);
  margin-inline: auto;
  padding-inline: var(--phi-wrap-pad);
  box-sizing: border-box;
}

/* Die Kopfzeile trägt eine Haarlinie erst, wenn gescrollt wurde.
   Ohne Skript nicht machbar, deshalb steht sie immer. Sie ist
   1px und stört nicht. */

/* Wortmarke. Kein Rechtsformzusatz, so will es das CD.
   Zeile 2 steht im CD auf 22 Prozent von Zeile 1 und mit deutlich
   mehr Laufweite. Hier einzeilig gesetzt, deshalb übernimmt der
   Größensprung diese Aufgabe. */
.phi-brand {
  font-family: var(--phi-font-display);
  font-weight: 800;
  font-size: 1.0625rem;
  font-stretch: var(--phi-wdth-display);
  letter-spacing: -.005em;
  text-transform: uppercase;
  color: var(--phi-ink);
  text-decoration: none;
  white-space: nowrap;
  display: inline-flex;
  align-items: baseline;
  gap: .5em;
}
.phi-brand span {
  font-family: var(--phi-font-body);
  font-weight: 600;
  font-size: .5em;
  font-stretch: normal;
  letter-spacing: .14em;
  color: var(--phi-n-500);
}
@media (max-width: 560px) {
  /* Unter 560px passt der Zusatz nicht mehr in eine Zeile.
     Dann trägt die Bildmarke allein, so wie im CD vorgesehen. */
  .phi-brand span { display: none; }
}

/* Navigation bleibt einzeilig. Der aktive Punkt trägt eine
   2px-Unterkante in der Spartenfarbe, sie wächst von links.
   Die Kante liegt als ::after auf, damit beim Wechsel nichts
   springt und nur transform animiert wird. */
.phi-nav { display: flex; align-items: center; gap: var(--phi-s-6); }
.phi-nav a {
  position: relative;
  font-size: .9375rem;
  color: var(--phi-n-600);
  text-decoration: none;
  padding-block: var(--phi-s-2);
  border-bottom: 2px solid transparent;
  transition: color var(--phi-t-state) var(--phi-ease);
}
.phi-nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 2px;
  background: var(--phi-accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--phi-t-state) var(--phi-ease);
}
.phi-nav a:hover,
.phi-nav a[aria-current="page"],
.phi-nav li.current-menu-item > a,
.phi-nav li.current-menu-ancestor > a {
  color: var(--phi-ink);
}
.phi-nav a:hover::after,
.phi-nav a[aria-current="page"]::after,
.phi-nav li.current-menu-item > a::after,
.phi-nav li.current-menu-ancestor > a::after {
  transform: scaleX(1);
}
.phi-nav .phi-btn { border-bottom: 0; }
/* Ohne das erbt die Schaltflaeche die Navigationsfarbe und steht dunkel
   auf dunklem Grund. Gemessen waren rund 1,1 zu 1. */
.phi-nav a.phi-btn--primary,
.phi-nav a.phi-btn--primary:hover {
  color: #FFFFFF;
  background: var(--phi-accent);
  padding: var(--phi-s-3) var(--phi-s-6);
}
.phi-nav a.phi-btn--primary:hover { background: var(--phi-accent-dark); }
.phi-nav .phi-btn::after { display: none; }

@media (max-width: 780px) {
  .phi-header__inner { flex-wrap: wrap; min-height: 0; padding-block: var(--phi-s-3); }
  .phi-nav { width: 100%; gap: var(--phi-s-4); flex-wrap: wrap; font-size: .875rem; }
}

/* --- Fußzeile --- */
.phi-footer {
  background: var(--phi-ink);
  color: var(--phi-n-300);
  border-top: var(--phi-line);
}
.phi-footer a {
  color: var(--phi-bg);
  text-underline-offset: .2em;
  text-decoration-color: var(--phi-ink-line);
  transition: text-decoration-color var(--phi-t-state) var(--phi-ease);
}
.phi-footer a:hover { text-decoration-color: var(--phi-n-400); }
.phi-footer h2, .phi-footer h3 { color: var(--phi-bg); }
.phi-footer__cols {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: var(--phi-s-12);
}
@media (max-width: 860px) {
  .phi-footer__cols { grid-template-columns: 1fr; gap: var(--phi-s-8); }
}
.phi-footer__label {
  font-size: .75rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--phi-n-400);
  margin-bottom: var(--phi-s-3);
}
.phi-footer__list { list-style: none; padding: 0; margin: 0; }
.phi-footer__list li + li { margin-top: var(--phi-s-2); }
.phi-footer__bar {
  border-top: 1px solid var(--phi-ink-line);
  margin-top: var(--phi-s-12);
  padding-top: var(--phi-s-6);
  /* 14px und nicht 13px. Die Untergrenze aus A3.4 gilt auch fuer die
     Rechtszeile: Sie traegt die Verkehrsleiter-Angabe, also genau die
     Art Nachweis, die das CD sichtbar haben will. Kleiner setzen
     heisst, ihn zu verstecken. Entspricht der Stufe "Small". */
  font-size: .875rem;
  color: var(--phi-n-400);
}


/* ============================================================
   7 · Komponenten
   ============================================================ */

/* --- Nachweisleiste. Das zentrale Vertrauenselement.
       Steht unter dem Hero, nie darin. --- */

.phi-proof {
  background: var(--phi-n-100);
  border-top: var(--phi-line);
  border-bottom: var(--phi-line);
}

.phi-proof__inner {
  max-width: var(--phi-content-max);
  margin-inline: auto;
  padding-inline: var(--phi-wrap-pad);
  box-sizing: border-box;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--phi-s-8);
}

/* Jeder Eintrag bekommt eine 2px-Oberkante. Das ist die
   Registermarke aus dem technischen Zeichnen: sie ordnet die
   Einträge in eine Reihe, ohne senkrechte Linien zu ziehen,
   die das CD für Tabellen ausschließt. */
.phi-proof__item {
  border-top: 2px solid var(--phi-n-300);
  padding-top: var(--phi-s-3);
}

.phi-proof__label {
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--phi-n-500);
  margin: 0 0 var(--phi-s-1);
}

.phi-proof__value {
  font-size: 1rem;
  line-height: 1.45;
  color: var(--phi-ink);
  margin: 0;
  max-width: 34ch;
}

/* --- Zwei Türen auf der Dachseite. Keine Karten, nur Oberkanten.
       Die beiden Geschäftsbereiche stehen groß, ein dritter
       Verweis daneben klein. So entsteht Größenkontrast statt
       drei gleicher Kacheln. --- */
.phi-door {
  border-top: 2px solid var(--phi-n-300);
  padding-top: var(--phi-s-6);
}
.phi-door--eng { border-top-color: var(--phi-eng); }
.phi-door--trp { border-top-color: var(--phi-trp); }
.phi-door h2 { margin-bottom: var(--phi-s-3); }
.phi-door--eng h2,
.phi-door--trp h2 {
  font-size: clamp(2rem, 4.2vw, 3.25rem);
  line-height: 1.02;
  letter-spacing: -.015em;
  font-weight: 800;
  font-stretch: var(--phi-wdth-display);
}
/* Die neutrale Tür ist der Nebenweg und wird auch so gesetzt. */
.phi-door:not(.phi-door--eng):not(.phi-door--trp) h2 {
  font-size: 1.375rem;
  line-height: 1.2;
  font-weight: 700;
  font-stretch: var(--phi-wdth-normal);
}
.phi-door:not(.phi-door--eng):not(.phi-door--trp) p { font-size: .9375rem; }

/* Der ganze Türblock ist anklickbar wirkend, aber nur der Link
   ist es. Der Verweis am Fuß wird deshalb zum sichtbaren Ziel. */
.phi-door p:last-child a {
  font-weight: 600;
  color: var(--phi-accent);
  text-decoration: none;
  border-bottom: 2px solid var(--phi-accent);
  padding-bottom: 1px;
}
.phi-door--eng p:last-child a { color: var(--phi-eng); border-bottom-color: var(--phi-eng); }
.phi-door--trp p:last-child a { color: var(--phi-trp); border-bottom-color: var(--phi-trp); }

/* --- Partnerhinweis. Deutlich als fremdes Angebot erkennbar. --- */
.phi-partner {
  border: var(--phi-line);
  border-left: 3px solid var(--phi-n-400);
  padding: var(--phi-s-6);
  background: var(--phi-surface);
}
.phi-partner h3 { margin: 0 0 var(--phi-s-3); }
.phi-partner p:last-child { margin-bottom: 0; }
.phi-partner a { color: var(--phi-n-600); text-underline-offset: .2em; }
.phi-partner a:hover { color: var(--phi-ink); }

/* --- Tabellen --- */
.phi-table { width: 100%; border-collapse: collapse; }
.phi-table th {
  background: var(--phi-n-100);
  text-align: left;
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--phi-n-500);
  padding: var(--phi-s-3) var(--phi-s-4);
}
.phi-table td {
  padding: var(--phi-s-3) var(--phi-s-4);
  border-top: var(--phi-line);
}
.phi-table td.phi-num,
.phi-table th.phi-num { text-align: right; }
/* Zebrastreifen erst ab acht Zeilen, so steht es im CD. Die
   Bedingung lässt sich in CSS genau so formulieren: nur wenn eine
   achte Zeile existiert, wird gestreift. */
.phi-table tbody:has(tr:nth-child(8)) tr:nth-child(even) {
  background: var(--phi-n-50);
}
.phi-table tbody tr:hover { background: var(--phi-n-100); }

/* --- Formulare --- */
.phi-field { margin-bottom: var(--phi-s-6); }
.phi-field label {
  display: block;
  font-size: .875rem;
  font-weight: 600;
  margin-bottom: var(--phi-s-2);
  color: var(--phi-n-600);
}
.phi-field input,
.phi-field textarea,
.phi-field select,
.ff-el-form-control {
  width: 100%;
  background: var(--phi-surface);
  border: 1px solid var(--phi-n-300);
  border-radius: var(--phi-radius);
  padding: var(--phi-s-3) 14px;
  font-family: var(--phi-font-body);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--phi-ink);
  transition: border-color var(--phi-t-state) var(--phi-ease);
}
.phi-field input::placeholder,
.ff-el-form-control::placeholder { color: var(--phi-n-300); }
.phi-field input:focus,
.phi-field textarea:focus,
.ff-el-form-control:focus { border-color: var(--phi-accent); }
.phi-field--error input { border-color: var(--phi-danger); }
.phi-field__error {
  display: block;
  margin-top: var(--phi-s-2);
  font-size: .875rem;
  color: var(--phi-danger);
}

/* --- Einwilligungsplatzhalter für eingebettete Inhalte --- */
.phi-embed-placeholder {
  background: var(--phi-n-100);
  border: var(--phi-line);
  border-radius: var(--phi-radius);
  padding: var(--phi-s-12) var(--phi-s-8);
  text-align: left;
}
.phi-embed-placeholder p { margin-bottom: var(--phi-s-6); }

/* Steht ein Platzhalter neben einer laengeren Spalte, klafft darunter
   ein Loch (Pruefliste B5). Auf /kontakt/ war die Faktenliste rund
   460px hoch und der Formularplatz daneben 170px: dazwischen 290px
   Nichts, das kein Befund meldet und das jeder sieht.

   Der Platzhalter zieht sich deshalb auf die Hoehe seiner Nachbarin.
   Er ist ohnehin eine angekuendigte Flaeche und keine Aussage, also
   darf er die Flaeche auch fuellen. Sobald das echte Formular drin
   steht, traegt die Spalte sich selbst und die Regel greift nicht
   mehr, weil es dann keinen Platzhalter mehr gibt.

   :has() waehlt nur die Splits aus, die das wirklich betrifft. Alle
   anderen behalten ihr align-items: flex-start. */
.phi-split:has(.phi-embed-placeholder) { align-items: stretch; }
.phi-split:has(.phi-embed-placeholder) > *,
.phi-split:has(.phi-embed-placeholder) > * > *,
.phi-split:has(.phi-embed-placeholder) .elementor-widget-text-editor,
.phi-split:has(.phi-embed-placeholder) .elementor-widget-container {
  height: 100%;
}
.phi-embed-placeholder {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
@media (max-width: 1199px) {
  /* Untereinander gibt es nichts mehr auszugleichen. */
  .phi-split:has(.phi-embed-placeholder) > *,
  .phi-split:has(.phi-embed-placeholder) > * > *,
  .phi-split:has(.phi-embed-placeholder) .elementor-widget-text-editor,
  .phi-split:has(.phi-embed-placeholder) .elementor-widget-container,
  .phi-embed-placeholder { height: auto; }
}

/* --- Einwilligungsbanner. Schmale Leiste, kein Overlay. --- */
.phi-consent {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 9999;
  background: var(--phi-ink);
  color: var(--phi-bg);
  border-top: 2px solid var(--phi-accent);
  padding: var(--phi-s-4) var(--phi-gutter);
  max-height: 96px;
}
.phi-consent__inner {
  max-width: var(--phi-content-max);
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: var(--phi-s-6);
  flex-wrap: wrap;
}
.phi-consent p { font-size: .875rem; margin: 0; max-width: 60ch; }
/* Ablehnen muss genauso leicht sein wie Annehmen. */
.phi-consent .phi-btn { padding: var(--phi-s-3) var(--phi-s-6); font-size: .875rem; }

/* --- Fließtext, Artikel, Projektbericht --- */
.phi-prose {
  max-width: 68ch;
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--phi-ink);
  /* Deutsche Komposita werden in schmalen Spalten getrennt.
     Ohne das reißen Wörter wie "Simulationsautomatisierung"
     Löcher in den Flattersatz. */
  hyphens: auto;
  -webkit-hyphens: auto;
  hyphenate-limit-chars: 8 4 4;
}
.phi-prose > * + * { margin-top: var(--phi-s-6); }
.phi-prose h2 {
  font-family: var(--phi-font-display);
  font-weight: 700;
  font-size: 1.75rem;
  line-height: 1.1;
  letter-spacing: -.01em;
  margin-top: var(--phi-s-16);
  hyphens: manual;
}
.phi-prose h3 {
  font-family: var(--phi-font-display);
  font-weight: 700;
  font-size: 1.25rem;
  line-height: 1.15;
  margin-top: var(--phi-s-12);
  hyphens: manual;
}
/* Eine Zwischenüberschrift direkt nach einer anderen gehört dazu. */
.phi-prose h2 + h3 { margin-top: var(--phi-s-4); }
.phi-prose ul, .phi-prose ol { padding-left: 1.25em; }
.phi-prose li + li { margin-top: var(--phi-s-2); }
.phi-prose li::marker { color: var(--phi-n-400); }
.phi-prose a {
  color: var(--phi-accent);
  text-underline-offset: .2em;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--phi-n-300);
  transition: text-decoration-color var(--phi-t-state) var(--phi-ease),
              color var(--phi-t-state) var(--phi-ease);
}
.phi-prose a:hover {
  color: var(--phi-accent-dark);
  text-decoration-color: var(--phi-accent);
  text-decoration-thickness: 2px;
}

/* --- Kopfzeile eines Artikels: Datum, Sparte, Lesedauer --- */
.phi-meta {
  font-size: .8125rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--phi-n-500);
  border-top: var(--phi-line);
  border-bottom: var(--phi-line);
  padding-block: var(--phi-s-3);
}

/* --- Zitat. Haarlinie statt Anführungsgrafik. --- */
.phi-quote {
  border-left: 2px solid var(--phi-accent);
  padding-left: var(--phi-s-6);
  margin-left: 0;
  font-family: var(--phi-font-display);
  font-weight: 600;
  font-size: 1.375rem;
  line-height: 1.25;
  letter-spacing: -.005em;
  hyphens: manual;
}
.phi-quote cite {
  display: block;
  margin-top: var(--phi-s-4);
  font-family: var(--phi-font-body);
  font-weight: 400;
  font-size: .875rem;
  font-style: normal;
  color: var(--phi-n-500);
}

/* --- Bild mit Unterschrift. Unterschrift steht darunter, nie
       darüber, und nie im Bild. --- */
.phi-figure { margin: 0; }
.phi-figure img { display: block; width: 100%; border-radius: var(--phi-radius); }
.phi-figure figcaption {
  margin-top: var(--phi-s-3);
  font-size: .875rem;
  line-height: 1.5;
  font-style: normal;
  color: var(--phi-n-500);
  max-width: 60ch;
  /* Die Unterschrift hängt optisch am linken Bildrand und bekommt
     eine kurze Haarlinie als Ankerpunkt. */
  border-top: var(--phi-line);
  padding-top: var(--phi-s-2);
}

/* --- Eckdaten eines Projektberichts. Haarlinien, keine Karten. --- */
.phi-facts { border-top: var(--phi-line); }
.phi-facts__row {
  display: grid;
  /* Beide Spuren dürfen schrumpfen. Ein festes 14rem für das Label
     hielt die Spur auch dann auf 224px, wenn die ganze Zeile nur
     246px breit war, und drückte den Wert daneben aus der Seite
     heraus. minmax(0, …) ist hier kein Zierrat: Eine Grid-Spur hat
     von Haus aus min-width:auto und schrumpft sonst nie unter ihren
     Inhalt. */
  grid-template-columns: minmax(0, 14rem) minmax(0, 1fr);
  gap: var(--phi-s-4);
  padding-block: var(--phi-s-4);
  border-bottom: var(--phi-line);
}
/* Anschriften enthalten lange, unteilbare Woerter ("Rotenwaldstrasse").
   Sie brechen lieber im Wort als aus der Spalte heraus.

   break-word und NICHT anywhere. Der Unterschied ist hier der ganze
   Punkt: "anywhere" zaehlt beim Berechnen der minimalen inhaltlichen
   Breite mit, die min-content-Breite faellt damit auf ein einzelnes
   Zeichen, und eine Grid-Spur mit minmax(0, 1fr) darf dann auf
   wenige Pixel zusammenfallen. Genau das ist passiert: Auf dem iPad
   war das dd sechs Pixel breit und "info@phiec.de" stand als 336px
   hohe Buchstabensaeule. "break-word" bricht im Notfall genauso,
   laesst die min-content-Breite aber beim laengsten Wort. */
.phi-facts__row dd { overflow-wrap: break-word; }
.phi-facts__row dt {
  font-size: .8125rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--phi-n-500);
  /* Das Label sitzt auf der Grundlinie des Werts daneben, nicht
     darüber. Der kleinere Grad braucht dafür etwas Vorschub. */
  padding-top: .18em;
}
.phi-facts__row dd { margin: 0; max-width: 60ch; }
.phi-facts__row:hover { background: var(--phi-n-50); }
@media (max-width: 700px) {
  .phi-facts__row { grid-template-columns: 1fr; gap: var(--phi-s-1); }
  .phi-facts__row dt { padding-top: 0; }
}


/* ============================================================
   8 · Bildflächen und Signaturbewegungen
   ------------------------------------------------------------
   variance steht auf 0.65. Bilder dürfen den Rahmen brechen,
   Größenkontrast ist erwünscht, Ebenen dürfen sich überlagern.
   Bis echte Fotos vorliegen, macht der Platzhalter das mit.
   ============================================================ */

/* --- Der Platzhalter ist keine leere Fläche und kein Streifen-
       muster, sondern die Konstruktion der Marke selbst: ein Ring
       und eine Achse, die durch ihn läuft und aus dem Bild
       herausläuft, auf einem technischen Raster.

       Alles ist aus Farbstopps gebaut, nicht aus Verläufen: die
       Kanten sind hart, die Übergangszone ist 1px breit und dient
       nur der Kantenglättung. Keine Datei, kein Fremdrequest.

       Die Maße stammen aus logo/phi-mark-square.svg:
       Ring außen 36, Strich 8, also Verhältnis 1 zu 4,5.
       Innenradius ist folglich 5/9 des Außenradius. --- */
.phi-media {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: var(--phi-radius);
  border: var(--phi-line);
  overflow: hidden;

  --phi-mark-r:  clamp(30px, 8vw, 64px);            /* Außenradius */
  --phi-mark-ri: calc(var(--phi-mark-r) * .5556);   /* Innenradius */
  --phi-axis:    calc(var(--phi-mark-r) * .4444);   /* Strichstärke */
  --phi-mark-x:  66%;                               /* Ringmitte, außermittig */

  background-color: var(--phi-n-100);
  background-image:
    /* 1 · Ring */
    radial-gradient(circle at var(--phi-mark-x) 50%,
      transparent 0 calc(var(--phi-mark-ri) - .5px),
      var(--phi-n-300)  calc(var(--phi-mark-ri) + .5px) calc(var(--phi-mark-r) - .5px),
      transparent calc(var(--phi-mark-r) + .5px) 100%),
    /* 2 · Achse, läuft über die ganze Breite aus dem Bild heraus */
    linear-gradient(to bottom,
      transparent calc(50% - var(--phi-axis) / 2 - .5px),
      var(--phi-n-300) calc(50% - var(--phi-axis) / 2 + .5px),
      var(--phi-n-300) calc(50% + var(--phi-axis) / 2 - .5px),
      transparent calc(50% + var(--phi-axis) / 2 + .5px)),
    /* 3 · technisches Raster, senkrecht */
    repeating-linear-gradient(90deg,
      var(--phi-n-200) 0 1px, transparent 1px 24px),
    /* 4 · technisches Raster, waagerecht */
    repeating-linear-gradient(0deg,
      var(--phi-n-200) 0 1px, transparent 1px 24px);
}
.phi-media--tall { aspect-ratio: 3 / 4; --phi-mark-x: 50%; }
.phi-media--wide { aspect-ratio: 16 / 9; --phi-mark-x: 72%; }

/* Der Hinweis, was hier später steht. n-500 statt n-400, weil
   n-400 auf dem Bandton nur etwa 2,8 zu 1 erreicht und damit
   unter der Grenze liegt. */
.phi-media::after {
  content: attr(data-hint);
  position: absolute;
  left: var(--phi-s-4);
  bottom: var(--phi-s-3);
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--phi-n-500);
  background: var(--phi-n-100);
  padding-right: var(--phi-s-2);
}

/* --- Randabfallend. Bricht aus der Inhaltsbreite in den Viewport.
       Gilt für ein Element, das die volle Breite von .phi-wrap
       einnimmt. --- */
.phi-bleed {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  max-width: none;
  border-radius: 0;
}

/* --- Einseitiger Randabfall. Anders als .phi-bleed rechnet diese
       Formel nicht mit der eigenen Breite, sondern mit dem Abstand
       vom Rasterrand zum Viewportrand. Sie gilt deshalb auch für
       eine schmale Spalte in einem Zweispalter. --- */
.phi-bleed--right {
  margin-right: calc(-1 * (50vw - min(50vw, var(--phi-content-max) / 2) + var(--phi-wrap-pad)));
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: 0;
}
.phi-bleed--left {
  margin-left: calc(-1 * (50vw - min(50vw, var(--phi-content-max) / 2) + var(--phi-wrap-pad)));
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  border-left: 0;
}
@media (max-width: 900px) {
  /* Auf schmalen Displays gibt es keinen Rand zum Ausbrechen. */
  .phi-bleed--right, .phi-bleed--left { margin-inline: 0; }
}

/* --- Überlappung. Ein Element schiebt sich über die Grenze des
       nächsten Abschnitts. Das negative Maß verkürzt die Zeile,
       in der es steht, das Element selbst bleibt stehen. --- */
.phi-overlap { position: relative; z-index: 1; margin-bottom: calc(-1 * var(--phi-s-16)); }
@media (max-width: 900px) { .phi-overlap { margin-bottom: 0; } }

/* --- Der Hero. Hier passieren die Signaturbewegungen. --- */

/* Die Headline wird zusätzlich von der Fensterhöhe begrenzt.
   Das CD verlangt, dass Headline, Vorspann und Schaltfläche ohne
   Scrollen sichtbar sind. Auf einem flachen Notebookdisplay
   erledigt 8vw das nicht, 13vh schon. */
.phi-hero .phi-display-xl,
.phi-hero .phi-display-xl .elementor-heading-title {
  /* Gemessen am 2026-08-23: bei 8vw braucht die Zeile
     "Engineering. Transport." rund 1400px, verfuegbar sind 1152px.
     Sie brach deshalb in vier statt zwei Zeilen. 5,4vw laesst beide
     Zeilen in die Inhaltsbreite. Wer die Headline kuerzt, darf wieder
     hochgehen, aber dann bitte nachmessen. */
  font-size: clamp(2.25rem, min(5.4vw, 10vh), 4.875rem);
}

.phi-hero .phi-split { align-items: center; }

/* Die Textspalte des Heros. Höchstens vier Textelemente, so steht
   es im CD, und der Vorspann bleibt deutlich schmaler als die
   Headline, damit der Größenkontrast trägt. */
.phi-hero__text { align-self: start; }
.phi-hero__text .phi-lead,
.phi-hero__text .phi-lead p { max-width: 46ch; }

/* Primäre und sekundäre Schaltfläche stehen nebeneinander und
   brechen erst um, wenn sie müssen. */
.phi-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--phi-s-4);
  margin-top: var(--phi-s-8);
}

@media (min-width: 900px) {
  /* Die Bildfläche im Hero läuft nach rechts aus dem Raster heraus
     und schiebt sich unten über die Nachweisleiste. Genau das
     meint variance 0.65: kein zweiter gerahmter Kasten neben dem
     Text, sondern eine Ebene, die weitergeht. */
  .phi-hero .phi-media {
    aspect-ratio: auto;
    /* Vorher 52vh, das ergab neben zwei Zeilen Vorspann eine
       Flaeche von 620px und darunter ein Loch. */
    min-height: clamp(280px, 34vh, 420px);
    margin-right: calc(-1 * (50vw - min(50vw, var(--phi-content-max) / 2) + var(--phi-wrap-pad)));
    margin-bottom: calc(-1 * var(--phi-s-16));
    border-right: 0;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    position: relative;
    z-index: 1;
  }
  /* Die Textspalte sitzt mittig zur Bildfläche. Solange die Headline
     noch in der Spalte stand, war oben richtig. Seit sie über die
     volle Breite läuft, stehen dort nur noch Vorspann und
     Schaltflächen, und die ließen darunter ein Loch. */
  .phi-hero .phi-split > :first-child { align-self: center; }
}

/* Größenkontrast im Fließtext: eine belegte Zahl oder ein
   Kurzwort darf sehr groß stehen, direkt in der Zeile.
   Nur für tatsächlich belegte Angaben verwenden. */
.phi-figure-large {
  font-family: var(--phi-font-display);
  font-weight: 800;
  font-stretch: var(--phi-wdth-display);
  font-size: clamp(3rem, 9vw, 7rem);
  line-height: .86;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  display: block;
  color: var(--phi-ink);
}
.phi-figure-large + * { margin-top: var(--phi-s-2); }


/* ============================================================
   9 · Zustände, Details, Bewegung
   ============================================================ */

/* Fokus ist immer sichtbar. Auf dunklem Grund wechselt der Ring
   auf Knochen, weil Tiefteal auf Graphit zu wenig Kontrast hat. */
.phi-btn:focus-visible,
.phi-btn .elementor-button:focus-visible,
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--phi-accent);
  outline-offset: 2px;
  border-radius: var(--phi-radius);
}
.phi-dark :focus-visible,
.phi-footer :focus-visible,
.phi-consent :focus-visible {
  outline-color: var(--phi-bg);
}

/* Der Sprunglink von Ultimate Addons erbt sonst dessen Blau. */
.hfe-skip-link:focus {
  background: var(--phi-ink);
  color: var(--phi-bg);
  outline: 2px solid var(--phi-accent);
  border-radius: 0 0 var(--phi-radius) 0;
  text-decoration: none;
  font-family: var(--phi-font-body);
  font-weight: 600;
}

/* Deaktiviert. Kein Grau in Watte, sondern eine klare Aussage. */
[disabled], .is-disabled {
  color: var(--phi-n-300);
  border-color: var(--phi-n-200);
  cursor: not-allowed;
}

/* Ladezustand: Skelettfläche in der Form des Ergebnisses,
   kein Spinner. Statisch, weil motion auf 0.25 steht. */
.phi-skeleton {
  background: var(--phi-n-100);
  border-radius: var(--phi-radius);
  min-height: 1em;
}

/* Einblenden beim Scrollen. Deckkraft plus 8px Versatz, 240ms.
   Läuft ohne Skript, sobald der Browser Scroll-Zeitleisten kennt;
   kennt er sie nicht, ist der Inhalt einfach sichtbar. */
.phi-reveal {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--phi-t-reveal) var(--phi-ease),
              transform var(--phi-t-reveal) var(--phi-ease);
}
.phi-reveal.is-visible { opacity: 1; transform: none; }

@supports (animation-timeline: view()) {
  .phi-reveal {
    opacity: 1;
    transform: none;
    animation: phi-fade-in linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 40%;
  }
}
@keyframes phi-fade-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .phi-reveal { opacity: 1; transform: none; animation: none; }
}

/* Fällt das Skript aus, bleibt der Inhalt sichtbar. */
.no-js .phi-reveal { opacity: 1; transform: none; }

/* Die klebende Kopfzeile darf einen Sprungziel-Anker nicht
   verdecken (WCAG 2.4.11, Befund A6.9).

   :target allein reicht dafür nicht. Es greift nur bei einem Anker im
   Adressfeld, nicht wenn die Tastatur den Fokus auf ein Element weiter
   unten setzt und der Browser dorthin scrollt. Genau das ist der Fall,
   den 2.4.11 meint. Deshalb zusätzlich scroll-padding-top am
   Wurzelelement: es gilt für jedes Scrollen im Dokument, egal wer es
   ausgelöst hat.

   Die Höhe ist gemessen, nicht geschätzt: 89px mobil, 77px auf dem
   iPad, 93px am Schreibtisch. Ein fester Wert passt an keiner Stelle,
   also führt eine Variable die Höhe je Band, und beide Regeln speisen
   sich daraus. Die acht Pixel obendrauf sind Luft, damit das Ziel
   nicht auf Kante an der Haarlinie klebt. */
:root { --phi-kopf: 96px; }
@media (min-width: 780px) and (max-width: 1199px) { :root { --phi-kopf: 80px; } }

html { scroll-padding-top: calc(var(--phi-kopf) + var(--phi-s-2)); }
:target { scroll-margin-top: calc(var(--phi-kopf) + var(--phi-s-2)); }


/* ============================================================
   10 · Druck
   ------------------------------------------------------------
   Das CD nennt dokumentenfähige Gestaltung ausdrücklich. Eine
   ausgedruckte Seite ist ein Beleg, der beim Kunden im Vorgang
   landet, und soll dort nicht wie ein Bildschirmfoto aussehen.
   ============================================================ */

@media print {
  /* Graphit statt reinem Schwarz, auch auf Papier. Das CD schliesst
     #000000 aus, und im Druck liegt Graphit ohnehin naeher an dem,
     was eine Vierfarbmaschine als Schwarz ausgibt. */
  body { background: #FFFFFF; color: var(--phi-ink); font-size: 11pt; }
  .phi-header, .phi-consent, .phi-nav, .phi-media { display: none; }
  .phi-footer { background: none; color: var(--phi-ink); border-top: 1pt solid var(--phi-n-300); }
  .phi-footer a, .phi-dark, .phi-dark h1, .phi-dark h2, .phi-dark h3 { color: var(--phi-ink); }
  .phi-dark { background: none; }
  .phi-section, .phi-hero, [data-elementor-type="wp-page"] > .e-con.e-parent {
    padding-block: 12pt;
  }
  /* Ein Verweis ohne Ziel ist auf Papier wertlos. */
  .phi-prose a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
  h1, h2, h3 { break-after: avoid; }
  .phi-facts__row, .phi-proof__item, figure { break-inside: avoid; }
}

/* ============================================================
   Klappmenü
   ------------------------------------------------------------
   Ergaenzt 2026-08-23, nachdem der erste Mobilabzug zeigte, dass
   die Navigation in drei Zeilen brach und rund ein Fuenftel der
   Bildschirmhoehe frass.

   Das Klappmenue ist ein etabliertes Muster und ausdruecklich
   gewollt. Die Forschung mahnt zurecht, dass versteckte Punkte
   seltener gefunden werden, deshalb der Hybridweg: Die Schaltflaeche
   traegt neben dem Strichsymbol das Wort "Menue", und der Zustand
   steht in aria-expanded, damit Vorlesewerkzeuge ihn ansagen.
   ============================================================ */

.phi-burger {
  display: none;                     /* am Desktop nicht vorhanden */
  align-items: center;
  gap: var(--phi-s-2);
  background: transparent;
  border: 1px solid var(--phi-n-200);
  border-radius: var(--phi-radius);
  color: var(--phi-ink);
  font-family: var(--phi-font-body);
  font-size: .875rem;
  font-weight: 600;
  /* 44px Zielgroesse nach WCAG 2.5.8. */
  min-height: 44px;
  padding-inline: var(--phi-s-3);
  cursor: pointer;
}

/* Das Strichsymbol. Drei Linien aus einem Element, damit im Markup
   kein leerer Kasten mehr steht als noetig. */
.phi-burger__strich,
.phi-burger__strich::before,
.phi-burger__strich::after {
  display: block;
  width: 18px;
  height: 2px;
  background: currentColor;
  transition: transform var(--phi-t-state) var(--phi-ease),
              opacity var(--phi-t-state) var(--phi-ease);
}
.phi-burger__strich { position: relative; }
.phi-burger__strich::before,
.phi-burger__strich::after {
  content: "";
  position: absolute;
  left: 0;
}
.phi-burger__strich::before { top: -6px; }
.phi-burger__strich::after  { top:  6px; }

/* Im geoeffneten Zustand wird aus den drei Strichen ein Kreuz.
   Animiert werden nur transform und opacity, so will es das CD. */
.phi-burger[aria-expanded="true"] .phi-burger__strich {
  background: transparent;
}
.phi-burger[aria-expanded="true"] .phi-burger__strich::before {
  transform: translateY(6px) rotate(45deg);
}
.phi-burger[aria-expanded="true"] .phi-burger__strich::after {
  transform: translateY(-6px) rotate(-45deg);
}

@media (prefers-reduced-motion: reduce) {
  .phi-burger__strich,
  .phi-burger__strich::before,
  .phi-burger__strich::after { transition: none; }
}

@media (max-width: 860px) {
  .phi-burger { display: inline-flex; }

  .phi-header__inner {
    flex-wrap: wrap;
    min-height: 56px;
    gap: var(--phi-s-4);
  }

  /* Die Navigation liegt eingeklappt hinter der Schaltflaeche.
     display:none nimmt sie auch aus der Tabreihenfolge, das ist
     hier richtig: was nicht sichtbar ist, soll auch nicht
     angesprungen werden. */
  .phi-nav {
    display: none;
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding-block: var(--phi-s-2) var(--phi-s-4);
  }
  .phi-header__inner:has(.phi-burger[aria-expanded="true"]) .phi-nav {
    display: flex;
  }

  /* Jeder Punkt ist eine eigene Zeile mit 44px Zielgroesse. */
  .phi-nav a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding-block: var(--phi-s-2);
    border-bottom: 1px solid var(--phi-n-200);
  }
  .phi-nav a:last-child { border-bottom: 0; }

  /* Die Kontaktschaltflaeche bleibt eine Schaltflaeche, keine Zeile. */
  .phi-nav a.phi-btn--primary {
    justify-content: center;
    margin-top: var(--phi-s-3);
    border-bottom: 0;
  }
}

/* Sichtbarer Fokus, auch auf der Schaltflaeche. */
.phi-burger:focus-visible {
  outline: 2px solid var(--phi-accent);
  outline-offset: 2px;
}

/* ============================================================
   Hero auf Mobil
   ------------------------------------------------------------
   Der erste Mobilabzug zeigte die Bildflaeche als 90-Pixel-Streifen,
   der von der Nachweisleiste ueberlappt wurde. Ursache: die Flaeche
   erbte das Hochformat 3:4 aus phi-media--tall, und der Elternteil
   begrenzte ihre Hoehe.

   Auf schmalen Displays ist Hochformat ohnehin falsch: es schiebt
   alles Weitere unter die Falz. Breitformat und eine feste Mindesthoehe
   loesen beides.
   ============================================================ */

@media (max-width: 899px) {
  /* Elementor setzt seinen Containern display:flex mit eigener
     Spezifitaet. Ohne !important bleibt der Zweispalter auch auf
     390px ein Zweispalter, und weil er zugleich align-items:center
     traegt, steht die Bildflaeche oben und unten aus ihrem Container
     heraus. Der folgende Abschnitt ueberdeckt sie dann, sichtbar
     blieb ein 90-Pixel-Streifen. Genau das zeigte der Abzug mit
     eingefaerbten Containergrenzen. */
  .phi-hero .phi-split {
    display: block !important;
    align-items: flex-start !important;
  }
  .phi-hero .phi-split > * + * {
    margin-top: var(--phi-s-8);
  }
  /* Breite und Hoehe zuruecksetzen. Die Prozentwerte stammen vom
     Zweispalter, und die Elementor-Container bringen eigene
     Hoehenangaben mit. Blieben die stehen, ragte die Bildflaeche aus
     ihrem Container heraus und wurde vom naechsten Abschnitt
     ueberdeckt: sichtbar blieb ein 90-Pixel-Streifen. */
  /* Nur die Breite zuruecksetzen. Ein zusaetzliches
     height:auto mit min-height:0 laesst den Container um die
     Bildflaeche kollabieren: die Flaeche behaelt ihr Seitenverhaeltnis,
     ihr Elternteil zaehlt die Hoehe aber nicht mehr mit, und der
     folgende Abschnitt schiebt sich darueber. Genau dieser Fehler hat
     hier mehrere Runden gekostet, deshalb steht er hier. */
  /* Nicht nur der Split, auch seine beiden Spalten sind
     Elementor-Flex-Container. Bleibt die Bildspalte flex, staucht sie
     ihr Kind auf die Zeilenhoehe, und die Bildflaeche waechst mit
     ihrem Seitenverhaeltnis darueber hinaus: die Spalte zaehlt sie
     nicht mit, der folgende Abschnitt schiebt sich darueber. Sichtbar
     blieb ein 35-Pixel-Streifen.

     Blockfluss loest das, weil dort die Hoehe des Kindes zur Hoehe des
     Elternteils gehoert. */
  .phi-hero .phi-split > * {
    width: auto !important;
    display: block !important;
  }
  /* Breite fuehrt, Hoehe folgt aus dem Verhaeltnis. Umgekehrt
     erzwingt min-height zusammen mit aspect-ratio eine Breite, die
     ueber den Bildschirmrand hinauslaeuft: 200px mal 16/9 sind 355px,
     und mit dem Seitenrand passt das auf 390px nicht mehr. */
  .phi-hero .phi-media,
  .phi-hero .phi-media--tall {
    aspect-ratio: 16 / 9;
    min-height: 0;
    width: 100%;
    max-width: 100%;
  }

  /* Ein Raster, nicht drei. Headline, Vorspann, Schaltflaechen und
     Bildflaeche standen auf drei verschiedenen Einzuegen, weil die
     Elementor-Container ihr eigenes Innenmass mitbringen. */
  .phi-hero .phi-split > *,
  .phi-hero .phi-split > * > *,
  .phi-hero .phi-lead,
  .phi-hero .phi-hero__actions {
    padding-inline: 0;
    margin-inline: 0;
    max-width: 100%;
  }
}

/* ============================================================
   Aufmacherbild im Beitrag
   ------------------------------------------------------------
   Ein Aufmacher soll den Beitrag ankuendigen, nicht den ersten
   Bildschirm fuellen. Ohne Begrenzung nimmt ein Querformat bei
   1280px Inhaltsbreite gut 800px Hoehe ein, und der Text beginnt
   erst nach dem zweiten Scrollen.
   ============================================================ */

/* Elementor setzt seinen Bildern eigene Regeln mit hoeherer
   Spezifitaet. Ohne den Widgetrahmen im Selektor greift die Begrenzung
   nicht, und der Aufmacher fuellt den ersten Bildschirm. */
.elementor-widget-text-editor .phi-figure img,
.phi-figure img {
  max-height: 52vh !important;
  width: 100%;
  object-fit: cover;
  display: block;
}
@media (max-width: 780px) {
  .elementor-widget-text-editor .phi-figure img,
  .phi-figure img { max-height: 34vh !important; }
}

/* Artikelueberschriften stehen eine Stufe kleiner als eine
   Seitenueberschrift. Ein Beitragstitel ist laenger als ein Claim und
   braucht sonst vier Zeilen. */
.phi-pagehead .phi-display-l,
.phi-pagehead .phi-display-l .elementor-heading-title {
  font-size: clamp(1.875rem, 3.6vw, 3.25rem);
}

/* Die Unterschrift traegt Urheber, Lizenz und Quellenverweis. Das ist
   Pflicht aus der Lizenz, keine Zierde, und sie darf deshalb leise
   stehen, aber nicht verschwinden. */
.phi-figure figcaption a {
  color: var(--phi-n-500);
  text-underline-offset: .2em;
}
.phi-figure figcaption a:hover { color: var(--phi-accent); }

/* ============================================================
   Blog: Filter, Marken, Rueckweg
   ------------------------------------------------------------
   Ergaenzt 2026-08-23. Der Filter arbeitet mit Mehrfachauswahl und
   ODER-Verknuepfung: wer zwei Themen waehlt, sieht beide. Eine
   UND-Verknuepfung waere bei wenigen Beitraegen meist leer.
   ============================================================ */

.phi-filter { margin-bottom: var(--phi-s-12); }

.phi-filter__titel {
  font-size: .75rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--phi-n-500);
  margin: 0 0 var(--phi-s-3);
}

.phi-filter__knoepfe {
  display: flex;
  flex-wrap: wrap;
  gap: var(--phi-s-2);
}

.phi-filter__knopf {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  /* 44px Zielgroesse nach WCAG 2.5.8, auch am Schreibtisch bequem. */
  min-height: 44px;
  padding-inline: var(--phi-s-4);
  background: transparent;
  border: 1px solid var(--phi-n-200);
  border-radius: var(--phi-radius);
  font-family: var(--phi-font-body);
  font-size: .875rem;
  font-weight: 600;
  color: var(--phi-n-600);
  cursor: pointer;
  transition: border-color var(--phi-t-state) var(--phi-ease),
              color var(--phi-t-state) var(--phi-ease);
}
.phi-filter__knopf:hover { border-color: var(--phi-n-400); color: var(--phi-ink); }

/* Der gewaehlte Zustand steht nicht nur in der Farbe. Wer Farben nicht
   unterscheidet, erkennt ihn am Rahmen und an der Fettung. */
.phi-filter__knopf.is-aktiv {
  border-color: var(--phi-accent);
  border-width: 2px;
  color: var(--phi-accent);
  background: var(--phi-accent-tint);
}

.phi-filter__knopf:focus-visible {
  outline: 2px solid var(--phi-accent);
  outline-offset: 2px;
}

.phi-filter__zahl {
  font-size: .75rem;
  font-weight: 400;
  color: var(--phi-n-400);
}
.phi-filter__knopf.is-aktiv .phi-filter__zahl { color: inherit; }

.phi-filter__stand {
  margin: var(--phi-s-3) 0 0;
  font-size: .8125rem;
  color: var(--phi-n-500);
  min-height: 1.2em;      /* haelt den Platz, damit nichts springt */
}

/* --- Marken am Beitrag --- */
.phi-marken { margin: var(--phi-s-3) 0 0; display: flex; flex-wrap: wrap; gap: var(--phi-s-2); }
.phi-marke {
  display: inline-block;
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--phi-n-500);
  background: var(--phi-n-100);
  border-radius: var(--phi-radius);
  padding: .25em .6em;
  text-decoration: none;
}
a.phi-marke:hover { color: var(--phi-accent); background: var(--phi-accent-tint); }
.phi-marken--gross { margin-top: var(--phi-s-4); }

/* --- Beitragszeile --- */
.phi-beitrag h3 { margin: 0 0 var(--phi-s-2); font-size: 1.25rem; }
.phi-beitrag h3 a { color: var(--phi-ink); text-decoration: none; }
.phi-beitrag h3 a:hover { color: var(--phi-accent); text-decoration: underline; }
.phi-beitrag p { margin: 0; }
.phi-beitrag[hidden] { display: none; }

/* --- Rueckweg --- */
.phi-zurueck { margin: 0 0 var(--phi-s-4); font-size: .875rem; }
.phi-zurueck a {
  color: var(--phi-n-500);
  text-decoration: none;
}
.phi-zurueck a::before { content: "\2190\00a0"; }   /* Pfeil nach links */
.phi-zurueck a:hover { color: var(--phi-accent); text-decoration: underline; }

@media (max-width: 780px) {
  .phi-filter__knopf { font-size: .8125rem; padding-inline: var(--phi-s-3); }
}

/* ============================================================
   Unsichtbarer Text, behoben
   ------------------------------------------------------------
   Der Inspektor hat auf der Startseite Kontrast 1 zu 1 gemeldet, und
   der Bildschirmabzug hat es bestaetigt: die Ueberschrift im dunklen
   Abschnitt und die Anschrift in der Fusszeile standen Graphit auf
   Graphit, also unsichtbar.

   Ursache: Elementor faerbt Ueberschriften und Fliesstext ueber den
   Kit ein, und zwar an `.elementor-heading-title` und am Widgetrahmen.
   Die Regeln weiter oben treffen nur `h2` und `p` und verlieren
   deshalb. Hier stehen sie mit dem Rahmen im Selektor.
   ============================================================ */

.phi-dark h1, .phi-dark h2, .phi-dark h3,
.phi-dark .elementor-heading-title,
.phi-dark .elementor-widget-heading .elementor-heading-title,
.phi-dark .elementor-widget-text-editor,
.phi-dark .elementor-widget-text-editor p {
  color: var(--phi-bg);
}
.phi-dark .phi-lead,
.phi-dark .phi-lead p,
.phi-dark .elementor-widget-text-editor.phi-lead p {
  color: var(--phi-n-300);
}

.phi-footer,
.phi-footer p,
.phi-footer li,
.phi-footer .elementor-widget-text-editor,
.phi-footer .elementor-widget-text-editor p,
.phi-footer .elementor-widget-text-editor li {
  color: var(--phi-n-300);
}
.phi-footer .phi-footer__label { color: var(--phi-n-400); }
.phi-footer a,
.phi-footer .elementor-widget-text-editor a { color: var(--phi-bg); }

/* ============================================================
   Code im Fliesstext
   ------------------------------------------------------------
   Fachbeitraege zeigen Befehle und Pfade. Ohne eigene Gestaltung
   laufen sie im Fliesstext mit und sind nicht als Code erkennbar.

   Schriftwahl: die Systemschrift fuer Festbreite. Das CD nennt keine
   Monospace, und eine vierte Schriftdatei nachzuladen waere fuer ein
   paar Codezeilen unverhaeltnismaessig.
   ============================================================ */

:root {
  --phi-font-mono: ui-monospace, "SFMono-Regular", "Menlo", "Consolas",
                   "Liberation Mono", monospace;
}

/* --- Code in einer Zeile --- */
.phi-prose code,
.phi-prose kbd {
  font-family: var(--phi-font-mono);
  font-size: .875em;
  background: var(--phi-n-100);
  border: 1px solid var(--phi-n-200);
  border-radius: var(--phi-radius);
  padding: .1em .35em;
  /* Ein langer Pfad soll umbrechen duerfen, sonst sprengt er die
     Textspalte. Im Fliesstext ist das die einzige Stelle, an der ein
     Umbruch mitten im Wort richtig ist. */
  overflow-wrap: break-word;
  word-break: break-all;
}

/* --- Codeblock --- */
.phi-prose pre {
  font-family: var(--phi-font-mono);
  font-size: .8125rem;
  line-height: 1.55;
  background: var(--phi-ink);
  color: var(--phi-bg);
  border-radius: var(--phi-radius);
  padding: var(--phi-s-4) var(--phi-s-6);
  margin-block: var(--phi-s-6);
  /* Waagerecht scrollen statt die Seite sprengen. Das verlangt auch
     die Pruefliste, Regel M8.1. */
  overflow-x: auto;
  /* Der Block darf breiter sein als die Textspalte, sonst wird jede
     Befehlszeile umgebrochen. */
  max-width: 100%;
  -webkit-overflow-scrolling: touch;
}

.phi-prose pre code {
  /* Im Block traegt der Rahmen des <pre> die Flaeche, das <code>
     darin bleibt nackt. */
  font-family: inherit;
  font-size: inherit;
  background: none;
  border: 0;
  padding: 0;
  color: inherit;
  white-space: pre;
  word-break: normal;
  overflow-wrap: normal;
}

/* Der Scrollbalken soll sichtbar sein, sonst weiss niemand, dass es
   rechts weitergeht. */
.phi-prose pre::-webkit-scrollbar { height: 8px; }
.phi-prose pre::-webkit-scrollbar-thumb {
  background: var(--phi-n-600);
  border-radius: var(--phi-radius);
}

/* Eine Beschriftung ueber dem Block, etwa der Dateiname. */
.phi-codetitel {
  font-family: var(--phi-font-mono);
  font-size: .75rem;
  letter-spacing: .04em;
  color: var(--phi-n-500);
  background: var(--phi-n-100);
  border: 1px solid var(--phi-n-200);
  border-bottom: 0;
  border-radius: var(--phi-radius) var(--phi-radius) 0 0;
  padding: var(--phi-s-2) var(--phi-s-4);
  margin-block: var(--phi-s-6) 0;
  display: inline-block;
}
.phi-codetitel + pre {
  margin-top: 0;
  border-top-left-radius: 0;
}

@media (max-width: 780px) {
  .phi-prose pre {
    font-size: .75rem;
    padding: var(--phi-s-3) var(--phi-s-4);
  }
}

/* Im Druck bricht der Block um, statt abgeschnitten zu werden. */
@media print {
  .phi-prose pre {
    background: none;
    /* Auch im Druck bleibt die Palette geschlossen: Graphit statt
       reinem Schwarz, Haarlinie in n-300 statt einem fremden Grau. */
    color: var(--phi-ink);
    border: 1px solid var(--phi-n-300);
    white-space: pre-wrap;
    overflow-x: visible;
  }
}

/* Bild im Fliesstext. Kleiner als der Aufmacher, damit der Unterschied
   zwischen "das ist der Beitrag" und "das begleitet diesen Abschnitt"
   sichtbar bleibt. */
.phi-figure--im-text {
  margin-block: var(--phi-s-8);
}
.elementor-widget-text-editor .phi-figure--im-text img,
.phi-figure--im-text img {
  max-height: 34vh !important;
}
@media (max-width: 780px) {
  .elementor-widget-text-editor .phi-figure--im-text img,
  .phi-figure--im-text img { max-height: 26vh !important; }
}


/* ============================================================
   13 · Fremdwidget Terminbuchung (FluentBooking)
   ------------------------------------------------------------
   Das Buchungswidget bringt eine vollständige eigene Gestaltung
   mit: eigene Palette, eigene Radien, eigene Zielgrößen. Auf
   /kontakt/ stand es dadurch als Fremdkörper mitten im CD, und
   der Inspektor meldete es dreifach: A7.2 (vier Farben außerhalb
   der Palette), A6.5 (Schaltflächen unter 44px), A7.5 (Radius 4
   und 8 statt 2), A6.3 (zwei Fokusregeln ohne Ersatz).

   Das Plugin wird dafür nicht angefasst. Es führt seine Farben
   sauber über CSS-Variablen, und die werden hier umgebogen. Das
   ist die kleinstmögliche Fläche: Wird das Plugin aktualisiert,
   bleiben die Variablennamen, und die Umfärbung hält.

   Die Werte sind gemessen, nicht geraten. Abgelesen mit
   getComputedStyle am ausgelieferten Widget am 2026-08-23:
     --fcal_primary_color        #386bb8  → Tiefteal
     --fcal_dark                 #1B2533  → Graphit
     --fcal_gray                 #6b7280  → n-500
     --fcal_enable_day_bg        #e5e7eb  → n-100
     --fcal_slot_border          #D6DAE1  → n-200
     --fcal_thBG                 #f5f6f7  → n-100
     --fcal_body_bg              #f3f4f6  → Knochen
     --fcal_date_disabled_color  #6b7280  → n-300
     --fcal_date_radius          4px      → 2px
     --fcal_avatar_radius        8px      → 2px

   Gesetzt wird auf .phi-booking .fcal_cal_wrap und nicht auf
   .phi-booking allein. Grund: Das Plugin deklariert dieselben
   Variablen auf .fcal-light-mode, und diese Klasse sitzt auf dem
   Wrap-Element selbst. Eine Deklaration am Elternteil verliert
   deshalb gegen sie. Zwei Klassen schlagen eine.
   ============================================================ */

.phi-booking .fcal_cal_wrap,
.phi-booking .fcal_cal_wrap.fcal-light-mode {
  --fcal_primary_color:       var(--phi-accent);
  --fcal_primaryColor:        var(--phi-accent);
  --fcal_dark:                var(--phi-ink);
  --fcal_gray:                var(--phi-n-500);
  --fcal_whiteColor:          var(--phi-surface);
  --fcal_cal_bg:              var(--phi-surface);
  --fcal_input_bg:            var(--phi-surface);
  --fcal_body_bg:             var(--phi-bg);
  --fcal_slot_border:         var(--phi-n-200);
  --fcal_thBG:                var(--phi-n-100);
  --fcal_enable_day_bg:       var(--phi-n-100);
  --fcal_date_disabled_bg:    transparent;
  /* n-500 und nicht n-300. Das Widget benutzt diese Variable nicht nur
     für abgelaufene Tage, sondern auch für die Jahreszahl neben dem
     Monatsnamen, und die ist ganz normaler Text. Auf n-300 gestellt kam
     sie auf 1,96:1 und fiel als A3.1 durch. n-500 trägt 6,3:1.
     Die wirklich abgeschalteten Tage bekommen ihr helleres Grau weiter
     unten, gezielt und nur sie. */
  --fcal_date_disabled_color: var(--phi-n-500);
  --fcal_date_radius:         var(--phi-radius);
  --fcal_avatar_radius:       var(--phi-radius);
  --fcal_scroll_bar_bg:       var(--phi-n-300);
}

/* Das Widget setzt seine Schrift nicht selbst, es erbt. Damit es
   nicht doch in der Systemschrift landet, wenn Elementor
   dazwischenfunkt, wird die Hausschrift hier festgeschrieben. */
.phi-booking .fcal_cal_wrap { font-family: var(--phi-font-body); }

/* Ein Radius, überall derselbe (CD 5, Befund A7.5). Das Widget
   mischt 4px, 6px und 8px. */
.phi-booking .fcal_cal_wrap :is(button, input, select, textarea,
  .fcal_slot_item, .fcal_date_item, .day, .fcal_author_avatar, img) {
  border-radius: var(--phi-radius);
}

/* Zielgrößen (Befund A6.5). Gemessen waren
   button.fcal_btn_disabled und button.fcal_nav_active mit 32x30,
   die Tageszellen mit 33x33 und die Eingabefelder mit 36 Höhe.
   WCAG 2.5.5 und Apple nennen 44, Android 48.

   min-height statt height, damit nichts abgeschnitten wird, und
   inline-flex mit Zentrierung, weil eine bloße Mindesthöhe die
   Beschriftung sonst oben kleben lässt. */
.phi-booking .fcal_cal_wrap :is(button, .day, .fcal_nav_active,
  .fcal_btn_disabled) {
  min-width: 44px;
  min-height: 44px;
}
.phi-booking .fcal_cal_wrap :is(button, .day) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.phi-booking .fcal_cal_wrap :is(input, select, textarea) {
  min-height: 44px;
}

/* Fokusring (Befund A6.3). Svelte hängt seine Selektoren dreifach
   an sich selbst, "input.svelte-82qwg8.svelte-82qwg8.svelte-82qwg8",
   und kommt damit auf eine Spezifität, gegen die eine normale Regel
   nicht ankommt. Dagegen hilft nur !important.

   Der Hash im Klassennamen ändert sich bei jedem Plugin-Update,
   deshalb steht er hier bewusst NICHT im Selektor. */
.phi-booking .fcal_cal_wrap :is(a, button, input, select, textarea,
  [tabindex]):focus-visible {
  outline: 2px solid var(--phi-accent) !important;
  outline-offset: 2px !important;
}

/* Bilder ohne Maße erzeugen Layoutsprünge (Befund L1.4). Das
   Widget liefert das Autorenbild und physical_location.svg ohne
   width und height aus. */
.phi-booking .fcal_cal_wrap :is(img, svg) {
  max-width: 100%;
  height: auto;
}
.phi-booking .fcal_cal_wrap .fcal_author_avatar img {
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

/* Kein Schatten, keine Verläufe. Das CD trennt mit Haarlinien. */
.phi-booking .fcal_cal_wrap :is(.fcal_calendar_inner, .fcal_side,
  .fcal_slot_item, .fcal_holder) {
  box-shadow: none;
}
.phi-booking .fcal_cal_wrap .fcal_calendar_inner {
  border: var(--phi-line);
}

/* Die Überschrift des Widgets ist ein h1 (siehe Befund A1.3). Die
   Ebene lässt sich nur über den Plugin-Filter ändern, das Aussehen
   dagegen hier: Sie tritt optisch hinter die eigene Abschnitts-
   überschrift zurück und nimmt deren Rolle nicht ein. */
.phi-booking .fcal_cal_wrap .fcal_slot_heading {
  font-family: var(--phi-font-display);
  font-size: 1.375rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--phi-ink);
}

/* Abgeschaltete Tage und abgeschaltete Blätterpfeile dürfen blass
   sein: WCAG 1.4.3 nimmt Text, der zu einem inaktiven Bedienelement
   gehört, ausdrücklich von der Kontrastforderung aus. Wichtig ist,
   dass man ihnen ansieht, dass sie nicht gehen.

   Gesetzt wird hier gezielt und nicht über die Variable, weil das
   Widget dieselbe Variable auch für die Jahreszahl benutzt, und die
   ist normaler Text (siehe oben). */
.phi-booking .fcal_cal_wrap :is(.day-disabled, .fcal_btn_disabled) {
  /* !important ist hier nicht Bequemlichkeit, sondern gemessen
     notwendig. Das Plugin faerbt die Blaetterknoepfe ueber
     ".fcal_calendar_inner .fcal_date_wrapper .calendar-header
     .calendar_nav button", also mit Spezifitaet 0,4,1. Diese Regel
     kommt auf 0,3,0 und verliert ohne !important, obwohl sie das
     Element direkt trifft. Ohne sie blieb #6B7280 stehen und wurde
     als A7.2 gemeldet. */
  color: var(--phi-n-300) !important;
}
/* Das Plugin färbt die Pfeil-SVG in den Blätterknöpfen fest in
   #6B7280 ein, an der Variablen vorbei. Gemessen als A7.2. */
.phi-booking .fcal_cal_wrap :is(.fcal_btn_disabled, .fcal_nav_active) :is(svg, path) {
  color: currentColor;
  fill: currentColor;
  stroke: currentColor;
}
.phi-booking .fcal_cal_wrap .fcal_nav_active {
  /* Gleiche Falle wie eine Regel weiter oben: das Plugin gewinnt
     mit 0,4,1. Ohne !important blieb #6B7280 stehen (A7.2). */
  color: var(--phi-ink) !important;
}

/* Das Autorenbild kommt ohne src. Der Gravatar-Request nach
   secure.gravatar.com ist abgestellt, das <img> selbst liefert das
   Plugin trotzdem weiter aus, und der Browser malt dort ein
   kaputtes Bildsymbol samt Alternativtext über vier Zeilen. Auf dem
   Bildschirmabzug war das der auffälligste Fehler der ganzen Seite,
   und kein einziger Befund hat ihn gemeldet.

   Weg damit, bis es ein echtes Foto gibt. Das CD verbietet
   Platzhalterbilder aus fremder Quelle ohnehin. */
.phi-booking .fcal_cal_wrap .fcal_author_avatar:has(img:not([src])) { display: none; }
.phi-booking .fcal_cal_wrap img:not([src]) { display: none; }

/* Bilder ohne width und height erzeugen Layoutsprünge (L1.4). Beide
   Bilder in diesem Widget sind quadratisch: das Autorenbild mit 80px
   und das Ortssymbol mit 16px. */
.phi-booking .fcal_cal_wrap img:not([width]) { aspect-ratio: 1 / 1; }


/* ============================================================
   14 · Elementors Kit-Linkfarbe an den Akzent binden
   ------------------------------------------------------------
   Elementor schreibt die globale Linkfarbe als ".elementor-kit-9 a"
   in eine eigene Datei, mit dem Hexwert der Kit-Systemfarbe
   "accent" fest eingebrannt. Das ist Spezifitaet 0,2,0 und schlaegt
   damit jede Ein-Klassen-Regel in dieser Datei.

   Die Folge war messbar: Auf allen vier Transportseiten stand die
   Wortmarke, der Sprunglink und die Kontakt-Schaltflaeche der
   Kopfzeile in Tiefteal, waehrend der Seiteninhalt in Verkehrsrot
   lief. Der Inspektor meldete A7.1 "beide Spartenfarben auf einer
   Seite". Die Spartenumschaltung weiter oben half nicht, weil sie
   nur die CSS-Variable umstellt und diese Regel die Variable gar
   nicht benutzt.

   Hier wird sie darauf verpflichtet. Der Kit-Selektor traegt die
   Post-ID des Kits, die bei einem Neuaufbau wechseln kann, deshalb
   steht hier das Praefix statt der Nummer. Das vorangestellte "html"
   hebt die Spezifitaet auf 0,2,1, damit die Regel unabhaengig von
   der Ladereihenfolge gewinnt.
   ============================================================ */

html [class*="elementor-kit-"] a { color: var(--phi-accent); }

/* Die Wortmarke ist davon ausgenommen. Das CD fuehrt als
   Standardfassung auf hellem Grund Graphit, nicht die Spartenfarbe
   (CD 5, Farbfassung 1). Damit traegt die Kopfzeile ueberhaupt
   keine Akzentfarbe mehr ausser der Kontakt-Schaltflaeche, und die
   folgt jetzt der Sparte. */
html [class*="elementor-kit-"] a.phi-brand,
a.phi-brand { color: var(--phi-ink); }
html [class*="elementor-kit-"] a.phi-brand span { color: var(--phi-n-500); }

/* Der Sprunglink liegt im Fokus auf Graphit. Die Kit-Regel faerbte
   seinen Text in die Akzentfarbe, also dunkel auf dunkel. Sichtbar
   wird er nur bei Tastaturbedienung, gemeldet hat es niemand, und
   genau deshalb steht es hier. */
/* Nur im Fokus. Ungefokussiert liegt der Sprunglink ausserhalb des
   Bildes auf dem Knochengrund, und Knochen auf Knochen ist 1:1. Die
   erste Fassung dieser Regel galt fuer beide Zustaende und hat genau
   das ausgeloest (A3.1, neu im Lauf danach). */
html [class*="elementor-kit-"] a.hfe-skip-link { color: var(--phi-ink); }
html [class*="elementor-kit-"] a.hfe-skip-link:focus { color: var(--phi-bg); }

/* Verweise in der Fusszeile stehen auf Graphitgrund. Dort traegt die
   Akzentfarbe zu wenig Kontrast, sie laufen in Knochen. */
html [class*="elementor-kit-"] .phi-footer a { color: var(--phi-bg); }
html [class*="elementor-kit-"] .phi-dark a { color: var(--phi-bg); }

/* ------------------------------------------------------------
   Elementors Globalfarben an die Palette binden
   ------------------------------------------------------------
   Elementor legt seine Systemfarben als CSS-Variablen auf den
   Rumpf (".elementor-kit-9" sitzt auf <body>) und benutzt sie in
   der je Seite erzeugten Datei, etwa

     .elementor-widget-heading .elementor-heading-title {
       color: var(--e-global-color-primary);
     }

   Das ist Spezifitaet 0,2,0 und schlaegt die Ueberschriftenregel in
   dieser Datei. Gemessen auf /transport/: "Staedte und Umkreis"
   stand in Tiefteal auf einer Transportseite, weil beide Kit-Farben
   "primary" und "accent" auf #0F5B5B stehen. Zusammen mit dem
   Verkehrsrot des Inhalts ergab das A7.1.

   Statt jede erzeugte Regel einzeln zu ueberschreiben, werden die
   Variablen selbst umgebogen. Damit folgt alles, was Elementor je
   aus ihnen faerbt, automatisch dem CD:

     primary    Ueberschriften   → Graphit (CD 4: Headlines sind Ink)
     secondary  Nebentext        → n-500
     text       Fliesstext       → Graphit
     accent     Akzent           → die Spartenfarbe

   "html body[class*=...]" kommt auf 0,1,2 und gewinnt gegen die
   0,1,0 der Kit-Datei, unabhaengig von der Ladereihenfolge. Die
   Post-ID steht bewusst nicht drin, sie wechselt beim Neuaufbau.
   ------------------------------------------------------------ */
html body[class*="elementor-kit-"] {
  --e-global-color-primary:   var(--phi-ink);
  --e-global-color-secondary: var(--phi-n-500);
  --e-global-color-text:      var(--phi-ink);
  --e-global-color-accent:    var(--phi-accent);
}

/* ------------------------------------------------------------
   Schaltflaechen: der Widgetrahmen ist keine Schaltflaeche
   ------------------------------------------------------------
   Die Klassen phi-btn--primary und --secondary muessen zwei Faelle
   treffen: In der Kopfzeile sitzt phi-btn direkt auf einem <a>, in
   den Vorlagen auf dem Elementor-Widgetrahmen, der den Link
   umschliesst. Die Farbregeln zielen deshalb auf beides.

   Genau das faellt einem im dunklen Abschnitt auf die Fuesse. Die
   Regel ".phi-dark .phi-btn--primary" (0,2,0) faerbt auch den
   Rahmen, und der ist so breit wie der Abschnitt. Gemessen auf
   /transport/: Die Schaltflaeche "Angebot anfordern" war 201px
   breit, der knochenfarbene Balken darunter 1152px. Auf dem
   Bildschirmabzug sah es aus wie eine Schaltflaeche ueber die volle
   Inhaltsbreite. Gemeldet hat das kein Befund, weil die
   Schaltflaeche selbst ja stimmt.

   Der Rahmen wird hier wieder durchlaessig gemacht, nach allen
   Farbregeln und mit vorangestelltem html, damit weder
   Reihenfolge noch Spezifitaet daran etwas aendern. align-self
   haelt ihn ausserdem davon ab, sich im Flex-Container auf die
   volle Breite zu ziehen.
   ------------------------------------------------------------ */
html .elementor-widget.phi-btn {
  background: none;
  border: 0;
  padding: 0;
  align-self: flex-start;
  width: auto;
  max-width: 100%;
}
/* Zentriert ausgerichtete Abschnitte behalten ihre Ausrichtung. */
html .phi-center .elementor-widget.phi-btn { align-self: center; }

/* ------------------------------------------------------------
   Tabellen: eigener Scrollbereich statt Buchstabensaeulen
   ------------------------------------------------------------
   Pruefliste M8.1. Eine Tabelle mit vier Spalten hat auf 820px
   rund 170px je Spalte, und ein Wort wie
   "Simulationsautomatisierung" braucht mehr. Ohne eigene
   Scrollflaeche passiert eines von zwei Dingen: Die Tabelle
   schiebt die ganze Seite seitwaerts (A5.1), oder sie quetscht
   sich zusammen und bricht die Woerter auf (A4.7). Beides ist
   gemeldet worden.

   Die Loesung ist nicht enger setzen, sondern die Tabelle ihre
   natuerliche Breite behalten zu lassen und ihr einen eigenen
   Scrollbereich zu geben. Der Rest der Seite bleibt davon
   unberuehrt.

   Damit das ohne zusaetzliches Markup geht, wird die Tabelle
   selbst zum Scrollbereich: display:block plus overflow-x. Das
   kostet die Tabellensemantik nicht, die Rollen bleiben ueber die
   Elemente erhalten.
   ------------------------------------------------------------ */
.phi-prose table,
.phi-prose .phi-table,
.elementor-widget-text-editor table {
  display: block;
  overflow-x: auto;
  max-width: 100%;
  /* Erst ab dieser Breite lohnt Scrollen. Darunter passt sie. */
  min-width: 0;
  /* Damit die Spalten nicht unter ihren Inhalt gequetscht werden. */
  white-space: normal;
  -webkit-overflow-scrolling: touch;
}
.phi-prose table > :is(thead, tbody, tfoot),
.elementor-widget-text-editor table > :is(thead, tbody, tfoot) {
  display: table;
  width: 100%;
  min-width: max-content;
}
/* Eine Zelle bricht nicht mitten im Wort. Sie darf lieber breiter
   werden, der Scrollbereich faengt das auf. */
.phi-prose :is(td, th),
.elementor-widget-text-editor :is(td, th) {
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}

/* Der Scrollbereich braucht einen Fokus, damit er auch mit der
   Tastatur erreichbar ist (WCAG 2.1.1). tabindex kann CSS nicht
   setzen, deshalb wenigstens ein sichtbarer Rand, der zeigt, dass
   hier etwas weitergeht. */
.phi-prose table { border-inline: 1px solid transparent; }
.phi-prose table:hover { border-inline-color: var(--phi-n-200); }

/* ------------------------------------------------------------
   Die Tuerenreihe der Startseite
   ------------------------------------------------------------
   Drei Tueren nebeneinander, 42/42/16 Prozent. Am Schreibtisch ist
   das richtig und ausdruecklich kein Verstoss gegen "nie drei
   gleiche Kacheln": Die dritte ist bewusst schmaler, das ist ein
   Bento mit Rhythmus und keine Kachelreihe.

   Auf dem Tablet traegt dieselbe Aufteilung nicht mehr. Gemessen
   auf 820px: 253, 253 und 98 Pixel. In der 98px-Spalte brach
   "Projektberichte." mitten im Wort (A4.7). Sechzehn Prozent von
   720 sind keine Spalte, sondern ein Streifen.

   Deshalb gilt hier dasselbe wie fuer den Zweispalter: Im
   Tabletband stehen die Tueren untereinander.
   ------------------------------------------------------------ */
@media (max-width: 1199px) {
  .phi-doors,
  .phi-doors > .e-con-inner {
    display: block !important;
  }
  .phi-doors > *,
  .phi-doors > .e-con-inner > * {
    width: 100% !important;
    max-width: 100% !important;
  }
  .phi-doors > * + *,
  .phi-doors > .e-con-inner > * + * { margin-top: var(--phi-s-8); }
}

/* ------------------------------------------------------------
   Hohe Bildflaeche neben kurzem Text
   ------------------------------------------------------------
   Pruefliste B5: "Entsteht ein Loch, wo eine Spalte kuerzer ist als
   ihre Nachbarin?" Auf der Startseite steht im Abschnitt "Zwei
   Gewerke, eine Verantwortung" eine hochformatige Bildflaeche von
   rund 350px neben einem Textblock von rund 130px. Beide oben
   ausgerichtet, also klafft unten rechts ein Loch von gut 200px.

   Kein Befund meldet das, es ist reine Komposition. Die Loesung ist
   nicht, den Text zu strecken, sondern ihn an der Bildflaeche
   auszurichten: Dann liegt der Weissraum ober- und unterhalb und
   liest sich als Absicht statt als Rest.

   Nur dort, wo wirklich eine Bildflaeche im Spiel ist. Splits aus
   zwei Textspalten bleiben oben ausgerichtet, dort ist die
   gemeinsame Oberkante die Ordnung.
   ------------------------------------------------------------ */
@media (min-width: 1200px) {
  .phi-split:has(.phi-media) { align-items: center; }
}

/* Kleintext auf dem Telefon
   ------------------------------------------------------------
   Die CD-Stufe "Small" steht bei 0,875rem, also 14px. Das ist eine
   Schreibtischskala. Auf dem Telefon ist 16px die Untergrenze fuer
   alles, was gelesen werden soll (M3.1), und die Anschrift im
   Kontaktblock ist genau das: Sie wird gelesen, abgetippt und
   angerufen. Gemeldet auf /engineering/ mit 14px.

   Versallabels und die Rechtszeile in der Fusszeile bleiben klein,
   die sind kein Fliesstext und ausdruecklich ausgenommen. */
@media (max-width: 780px) {
  .phi-small,
  p.phi-small { font-size: 1rem; }
}

/* Das Buchungswidget setzt seine Ortszeile auf 14px. */
@media (max-width: 780px) {
  .phi-booking .fcal_cal_wrap :is(.fcal_loc_text, .fcal_duration_text) {
    font-size: 1rem;
  }
}
