/*
 * sections.css — the two display modes and the elements that change with them.
 *
 * The legacy site knows exactly two display worlds (see the plan, "Die zentrale Beobachtung:
 * zwei Sektions-Modi"). Everything else follows from that, which is why they are modelled here
 * as two classes rather than as a pile of individual rules.
 *
 * Responsibility against the Divi global presets (E1): the presets carry Divi's own options —
 * background, type, border, width. They are derived from tokens.css by
 * bin/setup-global-presets.sh so that every value is maintained in one place. They deliberately
 * set NO CSS class: Divi 5 does not read classes out of module presets at all, only a group
 * preset can do that (reasoning in bin/lib/global-presets.php).
 *
 * The classes here are therefore not the route by which page content gets its look, but the
 * route for everything that does not come from the builder: header, footer, archive and post
 * template (steps 6 and 8-11) are theme builder templates with their own HTML. There is no
 * Divi module there that could carry a preset — without these classes they would have no mode.
 *
 * Two routes to the same end, and both are needed:
 *
 *   1. Through the section — `.wi-section--dark p` catches everything inside it.
 *   2. Through the element itself — `.wi-text--dark`, `.wi-button--dark`.
 *
 * That is why every mode rule below carries both selectors. The values are the same as in the
 * presets because both come from tokens.css; a module can carry both without contradiction.
 */

/*
 * The section itself gets **no** width limit — only its content.
 *
 * Up to work step 12 this said `max-width: var(--wi-width-max)`, and that was wrong: the
 * section carries the background colour, and a background belongs across the full window
 * width. Below 1800px it went unnoticed because the two coincided. It surfaced during the
 * visual comparison at 1920px — the grey ground of the news list ended 45px short of either
 * edge and left two white strips that do not exist in the legacy site.
 *
 * The legacy site separates them the same way: `body.sub .content { background-color: #e2e2e2 }`
 * has no limit, `section .section-container { max-width: 1800px }` has one. Divi does it the
 * same way — the section is full width, the row inside it is bounded.
 *
 * What bounds the content here is `.wi-text-column` (Divi's row share, capped at 1800px) or
 * `.wi-container` (1800px, in base.css), depending on the template.
 */
.wi-section {
  position: relative;
}

/* The text column inside a section. Divi ships its own width for rows (80% of the window,
 * 1080px at most by default); the presets lift the cap to the section width (NA9 — until then
 * to the legacy 1170px), and this class holds the same geometry for rows outside the builder. */
.wi-row {
  width: var(--wi-width-text-ratio);
  max-width: var(--wi-width-max);
  margin-inline: auto;
}

/* ------------------------------------------------------------------ *
 * Dark — full-screen section with image
 * ------------------------------------------------------------------ */

.wi-section--dark {
  /* Base colour before the image is there. The legacy site pins it on .section so the section
   * never flashes white while the background image loads. */
  background-color: var(--wi-color-ink);
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  color: var(--wi-color-on-dark);
}

/* The overlay sits between image and text. It is the reason white type stays legible on
 * arbitrary nature photographs — without it the contrast depends on the motif.
 * The opacity is a token in tokens.css because it gets nudged during visual comparison. */
.wi-section--dark::before {
  content: '';
  position: absolute;
  inset: 0;
  background-color: var(--wi-color-ink);
  opacity: var(--wi-overlay-opacity);
  pointer-events: none;
}

/* The content has to sit above the overlay, otherwise the overlay covers it too. */
.wi-section--dark > * {
  position: relative;
  z-index: 1;
}

/* Context-free variant: a text module that carries dark mode itself. No overlay and no
 * background — those live on the section, not on the text. */
.wi-text--dark {
  color: var(--wi-color-on-dark);
}

.wi-section--dark h1,
.wi-section--dark h2,
.wi-section--dark h3,
.wi-section--dark p,
.wi-section--dark li,
.wi-text--dark h1,
.wi-text--dark h2,
.wi-text--dark h3,
.wi-text--dark p,
.wi-text--dark li {
  color: var(--wi-color-on-dark);
}

/* Until 2026-08-27 there was a separate H2 variant for dark mode here: 36px, uppercase, 60px
 * spacing. All three values are refuted on the rendered legacy site — it distinguishes the
 * modes for headings by colour alone, and that colour is in the rule above. Size, line height
 * and spacing now come from base.css (E11 in
 * AI/plans/done/sektions-bibliothek-divi.md). */

.wi-section--dark p,
.wi-text--dark p {
  font-size: var(--wi-font-size-body);
  font-weight: var(--wi-font-weight-light);
  line-height: var(--wi-line-height-body);
  margin-bottom: var(--wi-space-paragraph);
}

.wi-section--dark a,
.wi-text--dark a {
  color: var(--wi-color-accent);
  font-size: var(--wi-font-size-body);
}

/* ------------------------------------------------------------------ *
 * Light — content area
 * ------------------------------------------------------------------ */

.wi-section--light {
  background-color: var(--wi-color-surface);
  color: var(--wi-color-ink);
}

/* The news area is the only light section with an offset ground. */
.wi-section--light.wi-section--muted {
  background-color: var(--wi-color-surface-muted);
}

.wi-text--light {
  color: var(--wi-color-ink);
}

/* As in dark mode, only the colour is left: size, line height, weight and spacing live in
 * base.css on the type selector and apply in both modes. Post, list and error page set their
 * own values and carry two classes in the selector for it; they are unaffected. */
.wi-section--light h1,
.wi-section--light h2,
.wi-section--light h3,
.wi-text--light h1,
.wi-text--light h2,
.wi-text--light h3 {
  color: var(--wi-color-ink);
}

.wi-section--light p,
.wi-section--light li,
.wi-text--light p,
.wi-text--light li {
  font-size: var(--wi-font-size-body);
  color: var(--wi-color-ink);
}

/* ------------------------------------------------------------------ *
 * Elements that occur in both modes
 * ------------------------------------------------------------------ */

/* Buttons: outline instead of fill, no rounding, uppercase. Hover inverts. */
.wi-button {
  display: inline-block;
  font-family: var(--wi-font-sans), sans-serif;
  font-size: var(--wi-font-size-body);
  font-weight: var(--wi-font-weight-semibold);
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.5em 1.5em;
  color: var(--wi-color-ink);
  background-color: transparent;
  border: var(--wi-border-width-button) solid var(--wi-color-ink);
  border-radius: var(--wi-radius);
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.wi-button:hover,
.wi-button:focus {
  color: var(--wi-color-surface);
  background-color: var(--wi-color-ink);
  text-decoration: none;
}

/* In dark mode the base colour inverts, the logic stays the same.
 * `.wi-button--dark` is the context-free variant for the theme builder templates. */
.wi-section--dark .wi-button,
.wi-button--dark {
  color: var(--wi-color-on-dark);
  border-color: var(--wi-color-on-dark);
}

.wi-section--dark .wi-button:hover,
.wi-section--dark .wi-button:focus,
.wi-button--dark:hover,
.wi-button--dark:focus {
  color: var(--wi-color-ink);
  background-color: var(--wi-color-on-dark);
}

/* Light mode matches the base form. The class exists all the same so that both modes are
 * selectable as a preset in the builder, and so a light-mode button still looks right when it
 * stands inside a dark section — on a light card in it, say. */
.wi-button--light {
  color: var(--wi-color-ink);
  border-color: var(--wi-color-ink);
}

.wi-button--light:hover,
.wi-button--light:focus {
  color: var(--wi-color-surface);
  background-color: var(--wi-color-ink);
}

/*
 * Category label of the news: white on the accent colour. Used by both the post and the
 * archive template, which is why it lives here and not in either of them.
 *
 * Re-measured in work step 9 and corrected in the process: the typeface is **not** Open Sans
 * Condensed. The legacy site sets the condensed face only in the map's filter panel
 * (`#filter_part span.label`); the news label inherits the Poppins of body copy. The line
 * "Open Sans Condensed — Filterpanel der Karte, Labels" in the design specification means
 * those labels, not this one. Uppercase is not set here either — that belongs to the label of
 * the list view, which is a variant of its own (work step 10).
 *
 * Measured: 16px/18px, white on `#f28c00`, no rounding, padding 2px vertically and 0.6em
 * horizontally (the Bootstrap default value, which the legacy site leaves alone).
 */
.wi-label {
  display: inline-block;
  font-family: var(--wi-font-sans), sans-serif;
  font-size: var(--wi-post-meta-size);
  line-height: var(--wi-post-meta-line-height);
  font-weight: var(--wi-font-weight-bold);
  white-space: nowrap;
  padding: 2px 0.6em;
  color: var(--wi-color-on-dark);
  background-color: var(--wi-color-accent);
  border-radius: var(--wi-radius);
}

/*
 * The header strip — image across the full width, at the top of the document.
 *
 * It lives here and not in post.css because three page types carry it: the post (step 9), the
 * archive (step 10) and the 404 page (step 11). In the legacy site it is `.sub-section` and
 * therefore the same element with the same graphic on every subpage.
 *
 * Fixed height, image cropped. The legacy site does it with `background-size: cover`; here it
 * is an <img>, because a background image can carry neither alternative text nor `srcset` — and
 * sending 179 press photographs at full resolution to a phone would be the most expensive route
 * to the same picture.
 *
 * Together with `.wi-bleed-top` it starts at the top edge of the document, with the fixed
 * header above it. That is how the legacy site does it — and only that way does the fading
 * gradient in `header_bcg.png` make any sense.
 *
 * **Both classes in the selector, and here exceptionally not because of Divi.** Since work
 * package 2 `wi-hero` means two things: this header strip of the three theme builder templates
 * and the hero section S1 of the library (E23). With `.wi-hero` alone the rules below hit both
 * — harmless for the height, because Divi's `min-height: 100vh` beats the 600px, but
 * `.wi-hero img` would have pulled every image in a hero section to 100% x 100% and cropped it.
 * An image module in the hero is possible editorially at any time; it would only have shown up
 * there. The header strip carries `wi-hero wi-bleed-top` in all three templates, S1 carries
 * only `wi-hero` — the second class separates them without touching the markup. Found while
 * building the showcase page (T11).
 */
.wi-hero.wi-bleed-top {
  height: var(--wi-hero-height);
  overflow: hidden;
  background-color: var(--wi-color-ink);
}

.wi-hero.wi-bleed-top img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The legacy site crops its header graphic centred. With a press photograph the centre is
   * the better compromise than the top edge: motifs sit there more often. */
  object-position: center;
}

@media only screen and (max-width: 1366px) {
  .wi-hero.wi-bleed-top {
    height: var(--wi-hero-height-medium);
  }
}

@media only screen and (max-width: 991px) {
  .wi-hero.wi-bleed-top {
    height: var(--wi-hero-height-narrow);
  }

}

/*
 * Full-bleed up underneath the header.
 *
 * The legacy site sets no page offset: the header is `position: fixed; top: 0`, and the image
 * strip of every subpage (`.sub-section`) starts at y = 0 — the bar lies above it. That is
 * exactly what its graphic, a downwards fading gradient, is for; on a pushed-down area the
 * gradient would make no sense.
 *
 * The offset is here all the same, because a page without an image strip can arise in
 * WordPress at any time (header.css). This class takes it back for the first element of a page
 * — by exactly the height of the header, so the strip measures the same 600px as in the legacy
 * site and not 600 plus 120.
 *
 * Belongs here and not in post.css: the archive (step 10) and the 404 page (step 11) begin
 * with the same strip in the legacy site.
 */
.wi-bleed-top {
  margin-top: calc(-1 * var(--wi-header-height));
}

/*
 * The same for the two HEADER TEMPLATES of the library — S1 `hero-fullscreen` and
 * S2 `page-header-image` (work package 2, E25). Only by a different route, see below.
 *
 * Measured on the rendered legacy site: its hero begins at `y = 0` and measures a full 1080px
 * at a window height of 1080px; the image strip of every subpage likewise begins at `y = 0` and
 * measures 600px. The header is `position: fixed`, its ground transparent, and its graphic a
 * downwards fading gradient — it lies ABOVE the image. Without this rule both templates stood
 * 120px lower, with a second image strip above them: the header's gradient on empty space. Two
 * images stacked where the legacy site has one.
 *
 * **Not the negative margin from `.wi-bleed-top` but the removed page offset** — and that is
 * measured, not a preference: a negative top margin on the FIRST child that carries
 * `display: flex` collapses its width to **0** in Chrome. The section then stood as a 0px wide
 * stroke at the right edge with the panel next to it. Reproduced on the rendered front end:
 * with `display: block` the width stays at 1920, on a later section as well, and `-1px` is
 * already enough. Divi's sections are `.et_flex_section` and therefore flex containers
 * throughout — that route is out for them.
 *
 * The page offset belongs to exactly this question anyway: `#page-container` gets it in
 * header.css so that a page WITHOUT a header image does not start underneath the fixed bar.
 * Where a header template stands it is superfluous — the legacy site keeps its `body` at
 * `padding-top: 0`.
 *
 * **Only as the first element.** If a header template stands in the middle of the page —
 * possible editorially at any time — the offset would remain correct.
 *
 * `.et_pb_section` is in the selector so that `:has()` does not respond to the header strip of
 * the theme builder templates: that carries the same class `wi-hero` (E24) but is a `div` and
 * not a section element.
 *
 * The four selectors repeat those from header.css because that rule stands against Divi with
 * `!important` below 980px. Against `!important` only `!important` helps — plus a specificity
 * that at least draws level.
 */
body:has(.et_builder_inner_content > .et_pb_section.wi-hero:first-child) #page-container,
body:has(.et_builder_inner_content > .et_pb_section.wi-page-header:first-child) #page-container,
body:has(.et_builder_inner_content > .et_pb_section.wi-hero:first-child) > .wi-page,
body:has(.et_builder_inner_content > .et_pb_section.wi-page-header:first-child) > .wi-page {
  padding-top: 0 !important;
}

/*
 * The height of S2 `page-header-image` — from the theme, like the header strip of the posts
 * (N5, decided 2026-09-25).
 *
 * The library unit carries 600 / 400 / 300px as Divi `minHeight`, and Divi can only stagger
 * that at its own breakpoints, 980 and 767px. The legacy site switches at 1366 and 991px, and so
 * does `.wi-hero.wi-bleed-top` above. Measured on 2026-09-14 (import plan, finding 7): 600px at
 * 1366, 1280 and 991px where the legacy site has 400, 400 and 300, and 400px at 768px where it
 * has 300 — and "Downloads" stood 200px taller than "News & events" at the same width.
 *
 * Same tokens, same breakpoints as the header strip, so both can no longer drift apart. The
 * builder values stay in the unit: Divi writes them onto `.et_pb_section_N`, one class, without
 * `!important` — two classes here win over them without touching a single page, and the
 * imported pages need no rewrite. The price: changing the height of this unit in the builder
 * shows no effect; the height belongs to the theme.
 */
.et_pb_section.wi-page-header {
  min-height: var(--wi-hero-height);
}

@media only screen and (max-width: 1366px) {
  .et_pb_section.wi-page-header {
    min-height: var(--wi-hero-height-medium);
  }
}

@media only screen and (max-width: 991px) {
  .et_pb_section.wi-page-header {
    min-height: var(--wi-hero-height-narrow);
  }
}

/*
 * Spacing between stacked units (work package 2, E26).
 *
 * The legacy site knows spacing only where TEXT precedes: a heading brings 50px with it, a
 * paragraph 22px (E22). After an image, a grid or a tab group it measures **0** — and that is
 * exactly where two units stick together as soon as an editor stacks them. The library
 * deliberately deviates here; the deviation has to be named before acceptance.
 *
 * **The spacing sits at the TOP of the following unit and not at the bottom of the preceding
 * one.** That way a single unit gets nothing — no margin below the last element of a section,
 * no spacing nobody ordered. Only the second stacked unit brings it along.
 *
 * **It is triggered only by units without a bottom margin of their own.** Otherwise two sources
 * would add up and the spacing below a heading would stand at 50 + 22 = 72px. That very case
 * added three sources in E22 and produced 130px; the selector therefore names the triggering
 * units one by one instead of saying "everything but the first".
 *
 * **A ROW has no bottom margin of its own — the unit inside it has one** (F6 of the frontend
 * defect list). Naming `.et_pb_row` on its own therefore broke the sentence above: a row
 * holding a heading looked to the selector like a row holding an image, and below every such
 * heading stood 50 + 22 = 72px where the legacy site holds 50. Measured on the instance on
 * 2026-09-07 over all 227 published pages and posts: of 91 unit transitions **36 carried two
 * sources**, 34 of them a single-column row with a heading (M1, M2) followed by a further row,
 * on 12 pages. A row is therefore only a trigger while it ends in a unit that brings no
 * spacing along.
 *
 * **ONE such column is enough to keep the spacing, and all of them are needed to drop it.** A
 * row of two columns has one bottom edge, and which column draws it depends on the text — the
 * taller one draws it, and no selector can tell which that is. Were one text column enough to
 * disarm the rule, a row of image and text would lose its spacing whenever the image column is
 * the taller one: two units would stick together, which is the case this rule exists for. The
 * other way round the price is 22px too much below a text column that does not draw the edge —
 * visible, but not a defect that runs content together. On today's site the choice decides
 * nothing: of 296 rows, 193 mix a text column with another one (mostly copy next to a gallery),
 * and not one of them is followed by a further unit — they all close their section. It is a
 * decision for the editorial case, not for a measured one.
 *
 * An empty column carries no `:last-child` and therefore decides nothing. That is right: it
 * ends in no unit and draws no bottom edge either.
 *
 * **Only in page content** (`.et-l--post`). The theme builder templates from work package 1 run
 * under `.et-l--body`, `.et-l--header` and `.et-l--footer` — their rows stand there as they
 * were measured and are not to be shifted by this rule.
 *
 * The value is the legacy paragraph spacing and not a new number: the same step at 1600px, so
 * that a page has ONE rhythm and not two.
 *
 * **Why two rules and not one — and why the second carries more classes.**
 *
 *   1. For modules the weakest variant suffices. `:where()` does not count towards specificity,
 *      so the rule stands at a single class. Divi writes a module spacing set in the builder as
 *      `.et_pb_image_0{margin-top:…}` — the same specificity, but later in the document (E23).
 *      So whoever gives a unit a spacing in the builder still gets it; the rule only bites
 *      where nobody has set anything.
 *
 *   2. For ROWS it does not suffice. Divi gives its nested flex row an explicit
 *      `.et_flex_row .et_pb_row_nested.et_flex_row{margin:0}` — three classes, later in the
 *      document. With the weak variant the spacing between two 50/50 rows stayed at 0 although
 *      the rule was in the stylesheet and the selector matched; measured on the rendered box,
 *      nothing reported it. The second rule therefore names the parent node as well and comes
 *      to four classes. The price is on the table: it overrides a ROW spacing set in the
 *      builder. Divi's own rule does that anyway.
 */
.et-l--post :where(.et_pb_image, .et_pb_button_module_wrapper, .et_pb_code, .et_pb_tabs,
                   .et_pb_row:has(> .et_pb_column > :last-child:not(:is(.et_pb_text, .et_pb_heading)))) + :where(.et_pb_module, .et_pb_text) {
  margin-top: var(--wi-space-paragraph);
}

.et-l--post .et_flex_column > :where(.et_pb_image, .et_pb_button_module_wrapper, .et_pb_code, .et_pb_tabs,
                                     .et_pb_row:has(> .et_pb_column > :last-child:not(:is(.et_pb_text, .et_pb_heading)))) + .et_pb_row.et_flex_row,
.et-l--post .et_flex_section > :where(.et_pb_image, .et_pb_button_module_wrapper, .et_pb_code, .et_pb_tabs,
                                      .et_pb_row:has(> .et_pb_column > :last-child:not(:is(.et_pb_text, .et_pb_heading)))) + .et_pb_row.et_flex_row {
  margin-top: var(--wi-space-paragraph);
}

@media only screen and (max-width: 1600px) {
  .et-l--post :where(.et_pb_image, .et_pb_button_module_wrapper, .et_pb_code, .et_pb_tabs,
                     .et_pb_row:has(> .et_pb_column > :last-child:not(:is(.et_pb_text, .et_pb_heading)))) + :where(.et_pb_module, .et_pb_text) {
    margin-top: var(--wi-space-paragraph-narrow);
  }

  .et-l--post .et_flex_column > :where(.et_pb_image, .et_pb_button_module_wrapper, .et_pb_code, .et_pb_tabs,
                                       .et_pb_row:has(> .et_pb_column > :last-child:not(:is(.et_pb_text, .et_pb_heading)))) + .et_pb_row.et_flex_row,
  .et-l--post .et_flex_section > :where(.et_pb_image, .et_pb_button_module_wrapper, .et_pb_code, .et_pb_tabs,
                                        .et_pb_row:has(> .et_pb_column > :last-child:not(:is(.et_pb_text, .et_pb_heading)))) + .et_pb_row.et_flex_row {
    margin-top: var(--wi-space-paragraph-narrow);
  }
}

/* Vertical column divider, 1px x 130px. */
.wi-rule {
  width: 1px;
  height: var(--wi-rule-height);
  background-color: var(--wi-color-rule);
  border: 0;
  margin: 0;
}

/* ------------------------------------------------------------------ *
 * Interface to Divi's presets
 * ------------------------------------------------------------------ */

/*
 * Until 2026-08-27 two rules stood here that set the spacing below headings inside a Divi text
 * module — one each for dark and light mode, hooked onto Divi's preset class scheme
 * `preset--module--<module>--<preset-id>`. They were necessary because Divi knows no spacing
 * option for headings in the text module and base.css only set the font size back then.
 *
 * Both are gone. base.css now carries the spacing on the bare type selector, and that applies
 * inside a Divi module just as well — verified on the rendered source. This section is
 * therefore empty, and that is the better news: every rule here was a coupling to Divi
 * internals.
 *
 * It stays as a heading so that the next rule of this kind does not end up somewhere between
 * the mode classes.
 */

/*
 * The section's inherited colour — and it has become the next rule of that kind (work package
 * 2, T6).
 *
 * As a preset, `wi-section-dark` sets only the BACKGROUND. In the builder every module brings
 * the text colour along through its own preset, and for Divi modules that is enough:
 * `wi-text-dark` and `wi-heading-dark` set it explicitly.
 *
 * It stopped being enough once a unit put its OWN markup into a Divi section. M10 is a code
 * module with the markup from template-parts/download-list.php; whatever is not explicitly
 * coloured in it inherits — and up to here it inherited `--wi-color-ink` from `body`. That is
 * exactly the background colour of the dark section: the line with file type and size stood in
 * `#707070` on `#707070` and was invisible. Measured with bin/check-download-list.sh; it only
 * surfaced because the check compared the colour with the section colour and the two were
 * equal.
 *
 * Two classes would be too few here and are not needed: the rule sets an inherited colour,
 * which any explicit setting on a module beats anyway. Divi modules therefore stay untouched —
 * affected is only what would otherwise have no colour at all.
 *
 * Why here and not in the preset itself: Divi 5 reads no CSS classes out of module presets, and
 * a `color` on the section preset would apply to Divi's own section node. This file is the
 * documented place for "what is to apply to both worlds" — once on the mode selector for own
 * markup, once on the preset selector for builder content.
 */
.preset--module--divi-section--wi-section-dark {
  color: var(--wi-color-on-dark);
}

.preset--module--divi-section--wi-section-light {
  color: var(--wi-color-ink);
}

/*
 * The colours of the mode, read by the module presets (AI/plans/done/farbe-folgt-sektion.md).
 *
 * Text, heading and button presets take their colours from `--wi-mode-fg` (text) and
 * `--wi-mode-bg` (the section's ground, which the button needs for its hover). The section sets
 * both, so a module follows the section it stands in, whichever of its two presets it carries —
 * editors no longer switch a module from "Dark" to "Light". Outside these sections the variables
 * are unset and every preset falls back to the colour it always had (bin/lib/global-presets.php,
 * wildisland_mode_color()).
 *
 * Palette references and not the theme tokens: they are what the presets carried before, so the
 * rendered colour is the same value by construction.
 *
 * A section without a preset in the page content counts as light (E3 of the plan). That is the
 * white section Divi starts every new page with; before this, a library unit placed there showed
 * white text on white. The page header and the hero have no preset either but stand on a photo
 * and stay dark. Theme Builder layouts lie outside `.et-l--post` and are not touched.
 */
.preset--module--divi-section--wi-section-dark,
.et-l--post .preset--module--divi-section--default.wi-page-header,
.et-l--post .preset--module--divi-section--default.wi-hero {
  --wi-mode-fg: var(--gcid-wi-surface);
  --wi-mode-bg: var(--gcid-wi-ink);
}

.preset--module--divi-section--wi-section-light,
.et-l--post .preset--module--divi-section--default {
  --wi-mode-fg: var(--gcid-wi-ink);
  --wi-mode-bg: var(--gcid-wi-surface);
}

/*
 * S1 — the hero of the front page: the coloured panel and the title inside it.
 *
 * Both stand here and not in a preset, and both for the same reason: the legacy steps lie at
 * **1300px and 600px**, Divi's breakpoints at 980 and 767. A module preset can only do Divi's
 * steps — it could carry the values but not the boundaries at which they change. The same
 * pattern as with M8, M10 and M11 (E7): the shell comes from the library, the rule set from the
 * repository.
 *
 * All values measured on the rendered legacy site, `scripts/measure-bestand.sh <width> hero`
 * (2026-08-27). The breakpoints were determined by narrowing down and not adopted: 1301px shows
 * 30px, 1300px shows 25px; 601px shows 25px, 600px shows 22px.
 *
 * In the legacy site the panel hangs on the content element itself (`div.frame`), not on the
 * section — that carries the photo, bare since NA1 (2026-10-06). This separation is the core
 * of E23: a probe that asks the section finds grey and reports that there is no panel.
 *
 * `.et_pb_row` is in the selector for the same reason as `.et_pb_heading_container` with the
 * title below: the section preset carries
 * `.preset--module--divi-section--wi-section-dark > .et_pb_row { max-width: 1800px }` and thus
 * the same two classes. With equal specificity order decides, and Divi's
 * `et-critical-inline-css` sits in the document after every child stylesheet. With two classes
 * the panel therefore stayed 1800px wide — measured, not assumed.
 */
.wi-hero .et_pb_row.wi-hero__panel {
  background-color: var(--wi-color-hero-panel);
  padding: var(--wi-hero-panel-padding);
  max-width: var(--wi-hero-panel-width);
}

/*
 * The hero as a band and no longer a screen (NA2 of AI/plans/done/nacharbeiten.md, decided at
 * the acceptance walk of 2026-10-06). Until then the section followed the legacy site — window
 * high above 1200px, 70% of it below (F7) — and the panel was pinned absolutely at legacy
 * coordinates (F1). On load the news row lay entirely below the fold.
 *
 * What the client asked for: smaller than a screen, but taller than the header strip of the
 * subpages, so that the panel with the numbers fits inside, and the start of the news row
 * visible on load. That gives the height three bounds, one rule:
 *
 *   floor     the header strip of the subpages plus 40px (640 / 440 / 340px at its three
 *             steps), so the front page never looks like a subpage
 *   wish      the window minus `--wi-front-hero-reveal`: the space the news heading and the
 *             first strip of the cards need below the fold line
 *   cap       760px, so a tall window does not turn the band back into a screen
 *
 *   1920x1080 -> 760   1920x900 -> 660   1366x768 -> 543 (the panel)   375x667 -> 535 (the panel)
 *
 * The panel itself is the fourth bound and the one that wins on small windows: it stands IN THE
 * FLOW since NA2, so the section grows with it. Pinned absolutely, a longer heading or a sixth
 * fact would have run out of the photo; in the flow it pushes the band down instead.
 *
 * Two classes in the selector for the reason F7 found: Divi writes S1's height as
 * `.et_pb_section_0 { min-height: 100vh }` — one class — and `et-critical-inline-css` sits in
 * the document after every child stylesheet. `.et_pb_section` also keeps the rule off the header
 * strip of the theme builder templates, which carries `wi-hero` on a `div` (E24).
 *
 * The padding stays the preset's (40px, 30px from 980px down; NA7). It is what
 * bin/check-hero.sh reads to know Divi's deferred stylesheet has landed, and the preset wins
 * over two classes here anyway: same specificity, later in the document. The fixed header is
 * cleared by the panel's top margin instead (below).
 */
.et_pb_section.wi-hero {
  min-height: clamp(
    var(--wi-front-hero-height-min),
    calc(100vh - var(--wi-front-hero-reveal)),
    var(--wi-front-hero-height-max)
  );
  justify-content: center;
}

@media only screen and (max-width: 1366px) {
  .et_pb_section.wi-hero {
    --wi-front-hero-height-min: calc(var(--wi-hero-height-medium) + var(--wi-front-hero-lift));
  }
}

@media only screen and (max-width: 991px) {
  .et_pb_section.wi-hero {
    --wi-front-hero-height-min: calc(var(--wi-hero-height-narrow) + var(--wi-front-hero-lift));
  }
}

/*
 * The panel: centred in the band at every width, and plastic (NA2). The shadow is the one of
 * the orange box at the top right of the project map (`Karte_Danubeparks.jpg`): cast down and to
 * the side, soft at the edge. The small radius is the "may look more modern" of the same
 * decision. A shadow on a translucent box stays outside it — `box-shadow` is clipped to the
 * border box — so the photo still shows through the panel.
 *
 * Above 1300px the panel is 100% wide and capped at `--wi-hero-panel-width` (790px). Below, the
 * WIDTH keeps the legacy staircase of F9, measured 2026-09-07 across nineteen widths — only the
 * place changed, not the size:
 *
 *   1300-901px   100% minus 180px per side, capped at 600 | 940 at 1300, 600 at 960, 541 at 901
 *   900-501px    85%, capped at 600                       | 765 at 900, 510 at 600, 426 at 501
 *   from 500px   89%                                      | 445 at 500, 334 at 375
 *
 * Twice the panel gets WIDER as the window gets narrower (900 and 500px). That is the legacy
 * column's and is kept with it. The width has to be stated because the section centres its rows
 * (`align-items: center`): a row without one would shrink to its heading.
 *
 * The top margin is the height of the fixed header: the hero begins at `y = 0` underneath it
 * (see the page offset rule above), and the section centres the panel together with its margin.
 * What is centred is therefore the panel in the photo BELOW the header, with the preset padding
 * above and below as the smallest gap.
 */
.wi-hero .et_pb_row.wi-hero__panel {
  width: 100%;
  margin-top: var(--wi-header-height);
  margin-bottom: 0;
  border-radius: var(--wi-hero-panel-radius);
  box-shadow: var(--wi-hero-panel-shadow);
}

@media only screen and (max-width: 1300px) {
  .wi-hero .et_pb_row.wi-hero__panel {
    width: calc(100% - var(--wi-hero-column-inset) * 2);
  }
}

@media only screen and (max-width: 900px) {
  .wi-hero .et_pb_row.wi-hero__panel {
    width: var(--wi-hero-panel-width-ratio);
  }
}

@media only screen and (max-width: 500px) {
  .wi-hero .et_pb_row.wi-hero__panel {
    width: var(--wi-hero-panel-width-ratio-narrow);
  }
}

/*
 * Every link in the hero panel is a button — outline, uppercase, bottom right in the corner.
 * The legacy site does the same and ties it to nothing in the markup: its rule reads
 * `#section0 .csc-frame-default a` and hits every link in this one panel. The element itself is
 * a bare `<a href="…">Learn more</a>` without a class (F3 of the frontend defect list, measured
 * 2026-09-04).
 *
 * That is why the rule stands here and not on unit M7 `button`: there is no marker by which an
 * importer or an editor could designate the button. Whoever puts a link into the panel gets it
 * — exactly as in the legacy site.
 *
 * The colour is not cosmetics here but the reason the finding was urgent: without this rule the
 * link inherits `--wi-color-accent` from dark mode (the `.wi-section--dark a` rule above) and
 * therefore stands orange on the orange panel — roughly 1.4:1 and effectively unreadable. White
 * on the same surface comes to about 3.5:1.
 *
 * THREE classes in the selector, for the same reason as with the panel above: Divi's
 * `et-critical-inline-css` sits in the document after every child stylesheet, and the text
 * module's preset rule likewise carries two classes plus a type. With equal specificity order
 * decides, and order is against the child theme.
 */
.wi-hero .et_pb_row.wi-hero__panel a {
  display: inline-block;
  float: right;
  padding: var(--wi-hero-button-padding);
  border: var(--wi-hero-button-border) solid var(--wi-color-on-dark);
  color: var(--wi-color-on-dark);
  font-size: var(--wi-hero-button-size);
  font-weight: var(--wi-hero-button-weight);
  text-transform: uppercase;
  text-decoration: none;
}

/*
 * The way out of the rule above: a link in the panel that is meant to stay a link.
 *
 * The rule above deliberately catches every link, because that is what the legacy site does and
 * because the panel is a stage with one call to action, not a text area. But a Divi text module
 * in the panel can hold running copy, and running copy can carry a link — the legacy paragraph
 * "Project co-funded by the LIFE Programme of EU" is exactly the kind of sentence that invites
 * one. Without a way out, an editor would get a second floating button and could not switch it
 * off.
 *
 * Opt-out and not opt-in, and that is the load-bearing decision: the common case stays
 * automatic, and the exception is the one that has to be named. The other way round an editor
 * would have to type a class into the module's code view to get the button at all — and if they
 * forgot, the button would silently be missing. A visible wrong button beats an invisible
 * missing one. On top of that the link comes out of the importer as raw legacy HTML
 * (tools/inhalts-importer/import.php), so a hand-set class would not survive the next run.
 *
 * The appearance is derived and not measured — the legacy site has no running-copy link in this
 * panel, so there is no target value. Two things fix it: the surface tolerates no orange (the
 * accent on the panel measures roughly 1.4:1, which is the finding this whole rule set came
 * from), and once the colour no longer marks the link, the underline has to.
 *
 * FOUR classes, one more than the rule above, so this one wins wherever both match.
 */
.wi-hero .et_pb_row.wi-hero__panel a.wi-link {
  display: inline;
  float: none;
  padding: 0;
  border: 0;
  color: var(--wi-color-on-dark);
  font-size: inherit;
  font-weight: inherit;
  text-transform: none;
  text-decoration: underline;
}

/*
 * The title. The selector carries THREE classes and not two, and that is measured rather than
 * precautionary: Divi's rule reads
 * `.preset--module--divi-heading--wi-heading-dark .et_pb_heading_container h1` and thus
 * likewise carries two classes plus a type. With equal specificity order decides — and Divi's
 * `et-critical-inline-css` sits in the document AFTER every child stylesheet. With two classes
 * this rule therefore lost; the title stood at 35px/600 instead of 30px/300.
 *
 * `.et_pb_heading_container` is no arbitrary addition but exactly the node Divi goes through as
 * well. The class itself sits on the module shell — the heading lies one level below it.
 *
 * The margin below the title: 20px, likewise measured. It replaces the 50px that base.css gives
 * every H1 — inside the hero the title sits closer above its content.
 */
.wi-hero .wi-hero__title .et_pb_heading_container h1 {
  font-size: var(--wi-font-size-hero);
  line-height: var(--wi-line-height-hero);
  font-weight: var(--wi-font-weight-light);
  margin-bottom: var(--wi-space-heading-narrow);
}

@media only screen and (max-width: 1300px) {
  .wi-hero .et_pb_row.wi-hero__panel {
    max-width: var(--wi-hero-panel-width-medium);
  }

  .wi-hero .wi-hero__title .et_pb_heading_container h1 {
    font-size: var(--wi-font-size-hero-medium);
    line-height: var(--wi-line-height-hero-medium);
  }
}

@media only screen and (max-width: 600px) {
  .wi-hero .et_pb_row.wi-hero__panel {
    padding: var(--wi-hero-panel-padding-narrow);
  }

  .wi-hero .wi-hero__title .et_pb_heading_container h1 {
    font-size: var(--wi-font-size-hero-narrow);
    line-height: var(--wi-line-height-hero-narrow);
  }
}

/* ==========================================================================
 * Headings inside Divi modules — one size per level
 * ========================================================================== */

/*
 * Divi builds ONE rule for h1 to h6 out of a heading preset:
 * `.preset--module--divi-heading--wi-heading-dark .et_pb_heading_container h1, … h6 { … }`.
 * The level sits on the module, the preset cannot reach it. Everything a heading module renders
 * therefore arrived at the same size — measured on 2026-09-24: the H1 and the H2 of a page were
 * both 35px/600, and an H3 module on /wildislands/background/ was 35px as well where the legacy
 * site has 24px.
 *
 * The legacy site keeps H1 and H2 at 35px too and separates them by WEIGHT alone (600 against
 * 500). A preset cannot carry a weight per level either, so both became 600 and the last visible
 * difference went. On instruction the H1 now departs from the legacy site and grows instead; H2
 * and H3 keep their measured values. The H3 case is not a departure but a correction.
 *
 * THREE classes, and that is measured rather than precautionary — the same finding the hero title
 * rests on further up: Divi's rule carries two classes plus a type, and Divi's
 * `et-critical-inline-css` sits in the document AFTER every child stylesheet. At equal
 * specificity Divi would win.
 *
 * `.et_pb_heading_container` and `.et_pb_text_inner` are no arbitrary additions but exactly the
 * nodes Divi itself goes through.
 */
.et_pb_heading.et_pb_module:not(.wi-hero__title) .et_pb_heading_container h1,
.et_pb_text.et_pb_module .et_pb_text_inner h1 {
  font-size: var(--wi-font-size-h1);
  line-height: var(--wi-line-height-h1);
}

.et_pb_heading.et_pb_module:not(.wi-hero__title) .et_pb_heading_container h2,
.et_pb_text.et_pb_module .et_pb_text_inner h2 {
  font-size: var(--wi-font-size-h2);
  line-height: var(--wi-line-height-heading);
}

.et_pb_heading.et_pb_module:not(.wi-hero__title) .et_pb_heading_container h3,
.et_pb_text.et_pb_module .et_pb_text_inner h3 {
  font-size: var(--wi-font-size-h3);
  line-height: var(--wi-line-height-h3);
}

/*
 * The hero title is excluded by hand, and it has to be. Its rule further up carries three classes
 * plus a type as well — `.wi-hero .wi-hero__title .et_pb_heading_container h1` — so specificity is
 * EQUAL, and this block stands later in the file. Without `:not()` the hero title would have been
 * pulled from its own 30px scale onto the 44px of the page H1, and the check for it would have
 * gone red on a stylesheet that had just been written to fix something else.
 */

@media only screen and (max-width: 991px) {
  .et_pb_heading.et_pb_module:not(.wi-hero__title) .et_pb_heading_container h1,
  .et_pb_text.et_pb_module .et_pb_text_inner h1 {
    font-size: var(--wi-font-size-h1-narrow);
    line-height: var(--wi-line-height-h1-narrow);
  }

  .et_pb_heading.et_pb_module:not(.wi-hero__title) .et_pb_heading_container h2,
  .et_pb_text.et_pb_module .et_pb_text_inner h2 {
    font-size: var(--wi-font-size-heading-narrow);
    line-height: var(--wi-line-height-heading-narrow);
  }
}

/* The H3 steps back one boundary later than H1 and H2 — 700px, as the legacy site staggers it. */
@media only screen and (max-width: 700px) {
  .et_pb_heading.et_pb_module:not(.wi-hero__title) .et_pb_heading_container h3,
  .et_pb_text.et_pb_module .et_pb_text_inner h3 {
    font-size: var(--wi-font-size-h3-narrow);
    line-height: var(--wi-line-height-h3-narrow);
  }
}
