/* ==========================================================================
   Deliberate deviations from the reference build.

   Everything here is a considered change requested after review — NOT a fix
   for a porting error. Kept separate from site.css so that file stays a
   faithful copy of https://timo.31m.de/ki/ and can be re-ported wholesale if
   the agency ships an update; this file then reapplies our decisions on top.

   Each block records what changed and why.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Hero — requested 2026-08-10:
   wider text/button column, slightly smaller type, more air under the nav.

   Reference values at ≥1800px were: column 740px, h1 115px, sub 25px/600px,
   eyebrow 17px, and no top padding (content vertically centred in 100vh).
   -------------------------------------------------------------------------- */

.kiez-site .hero-content {
  max-width: 980px;          /* was 740px — wider measure for text and buttons */
}

.kiez-site .hero-sub {
  max-width: 760px;          /* was 600px — keeps the sub in proportion */
}

/* Horizontal position — requested 2026-08-10.

   `.hero` is a flex container and `.wrap` carries `margin: 0 auto`, so inside
   a flex context the wrap shrinks to its content and centres itself. That put
   the hero text ~26% in from the left, while every other section's `.wrap` is
   full width and starts at the page gutter. Forcing the hero wrap to full
   width left-aligns the content and lines the headline up with the sections
   below it. */
.kiez-site .hero > .wrap {
  width: 100%;
}

/* Vertical position. The hero is `align-items:center` inside `min-height:100vh`,
   so top padding shifts the whole block down. Enough to clear the fixed nav,
   but less than before so the block sits higher in the viewport. */
.kiez-site .hero {
  padding-top: 40px;
}

/* With the top bar above it (inc/chrome.php), the hero still fills the first
   screen exactly: --kiez-tb-h is the bar's height (site.js), 0 when hidden. */
.kiez-site.kiez-has-topbar .hero { min-height: calc(100vh - var(--kiez-tb-h, 0px)); }

.kiez-site .hero h1 {
  font-size: clamp(40px, 6vw, 72px);   /* was clamp(42px, 7vw, 80px) */
}

@media (min-width: 1800px) {
  .kiez-site .hero { padding-top: 56px; }
  .kiez-site .hero h1 { font-size: 96px; }   /* was 115px */
  .kiez-site .hero-sub { font-size: 22px; }  /* was 25px */
  .kiez-site .hero-eyebrow { font-size: 15px; } /* was 17px */
}

@media (max-width: 600px) {
  /* A smaller offset suffices on phones (the nav stays fixed here too). */
  .kiez-site .hero { padding-top: 56px; }
  .kiez-site .hero h1 { font-size: 34px; }
}

/* Still instead of the video under reduced motion (client 2026-10-12: "no
   video on another client"). site.css hides the video there, as wcg.htm does,
   which left a flat purple box. The still is the video's first frame
   (--hero-poster, set by kiez-hero-video.php), under the same overlay. */
@media (prefers-reduced-motion: reduce) {
  .kiez-site .hero { background-image: var(--hero-poster, none); background-size: cover; background-position: center; }
}

/* Buttons gain a little presence so they still read as substantial against
   the wider column now that the headline is smaller. */
.kiez-site .hero-actions .btn {
  padding: 15px 34px;
  font-size: 15px;
}

@media (max-width: 600px) {
  .kiez-site .hero-actions .btn { padding: 13px 24px; font-size: 14px; }
}

/* --------------------------------------------------------------------------
   Real forms in the reference shells.

   The reference build ships static mock forms. The live page uses Contact
   Form 7 ("Kontaktformular", 12355) and the Newsletter plugin, whose markup
   nests fields inside <p> and <span class="wpcf7-form-control-wrap">. These
   rules give that plugin output the reference's own field styling, so the
   sections look unchanged while actually submitting.
   -------------------------------------------------------------------------- */

/* Kontakt — CF7 ----------------------------------------------------------- */
.kiez-site .contact-form .wpcf7-form { display: flex; flex-direction: column; gap: 14px; }
.kiez-site .contact-form .wpcf7-form p { margin: 0; }
.kiez-site .contact-form .wpcf7-form-control-wrap { display: block; }

.kiez-site .contact-form input[type="text"],
.kiez-site .contact-form input[type="email"],
.kiez-site .contact-form input[type="tel"],
.kiez-site .contact-form input[type="url"],
.kiez-site .contact-form textarea {
  width: 100%;
  font-family: var(--body);
  font-size: 14px;
  padding: 13px 18px;
  border-radius: var(--r);
  border: 1.5px solid var(--violet-10);
  background: var(--white);
  color: var(--purple);
  outline: none;
  transition: border-color .25s;
}
.kiez-site .contact-form input:focus,
.kiez-site .contact-form textarea:focus { border-color: var(--violet); }
.kiez-site .contact-form textarea { min-height: 130px; resize: vertical; }

.kiez-site .contact-form input[type="submit"] {
  align-self: flex-start;
  font-family: var(--display);
  font-size: 14px;
  font-weight: 700;
  padding: 14px 30px;
  border-radius: var(--r);
  background: var(--orange);
  color: var(--white);
  border: none;
  cursor: pointer;
  transition: filter .2s, transform .2s;
}
.kiez-site .contact-form input[type="submit"]:hover { filter: brightness(1.08); transform: translateY(-1px); }

/* Validation + response messages, on the light contact surface. */
.kiez-site .contact-form .wpcf7-not-valid-tip { font-size: 13px; color: #B8431A; margin-top: 6px; }
.kiez-site .contact-form .wpcf7-response-output {
  margin: 8px 0 0; padding: 12px 16px; border-radius: var(--r);
  border-width: 1.5px; font-size: 14px; color: var(--purple);
}
.kiez-site .contact-form .wpcf7-spinner { margin: 0 0 0 10px; }

/* Newsletter — Newsletter plugin, on the dark band ------------------------- */
.kiez-site .nl-form .tnp-subscription,
.kiez-site .nl-form .tnp-subscription-minimal { margin: 0; max-width: none; }
.kiez-site .nl-form .tnp-subscription form,
.kiez-site .nl-form .tnp-subscription-minimal form { display: flex; gap: 10px; flex-wrap: wrap; text-align: left !important; }
/* The plugin's white-space:nowrap kept the minimal form 1148px wide at every
   screen size: button and consent text were cut off (audit 10-12). */
.kiez-site .nl-form .tnp-subscription-minimal form { white-space: normal; }
.kiez-site .nl-form .tnp-field { margin: 0; flex: 1; min-width: min(220px, 100%); }   /* min(): fits the 182px sidebar box at 320px (2026-10-12) */
.kiez-site .nl-form .tnp-subscription-minimal .tnp-email { flex: 1 1 220px; width: auto; }

/* Labels stay visible. This used to be `.tnp-field label { display: none }`,
   which hid the list checkboxes and the REQUIRED privacy checkbox too — a
   browser cannot prompt for a hidden required field, so the form could not be
   submitted at all (found 2026-10-05). The full form's email field has no
   placeholder (the plugin ignores one there), so its label is its only hint;
   the minimal form has no label and uses the placeholder instead. */
.kiez-site .nl-form .tnp-field-email label {
  display: block; margin-bottom: 6px;
  color: var(--text-on-dark-soft, #F2ECFF); font-size: 13px;
}
.kiez-site .nl-form .tnp-subscription form { align-items: flex-end; }

/* Email and button share the first row; list choice and consent follow. */
.kiez-site .nl-form .tnp-field-email  { order: 0; }
.kiez-site .nl-form .tnp-field-button { order: 1; flex: 0 0 auto; min-width: 0; }
.kiez-site .nl-form .tnp-lists        { order: 2; flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 4px 22px; }
.kiez-site .nl-form .tnp-lists .tnp-field { flex: 0 0 auto; min-width: 0; }
.kiez-site .nl-form .tnp-privacy-field { order: 3; }

.kiez-site .nl-form .tnp-field-checkbox label,
.kiez-site .nl-form .tnp-privacy-field label {
  display: flex; align-items: flex-start; gap: 8px; cursor: pointer;
  color: var(--text-on-dark-soft, #F2ECFF); font-size: 13px; line-height: 1.5;
}
/* site.css styles every `.nl-form input` as a text field; undo that here. */
.kiez-site .nl-form input[type="checkbox"] {
  flex: 0 0 auto; width: 16px; height: 16px; margin-top: 2px; padding: 0;
  border: 0; border-radius: 0; background: none; accent-color: var(--orange);
}
.kiez-site .nl-form .tnp-privacy-field a { text-decoration: underline; text-underline-offset: 2px; }

.kiez-site .nl-form input[type="text"],
.kiez-site .nl-form input[type="email"] {
  width: 100%;
  font-family: var(--body);
  font-size: 14px;
  padding: 13px 18px;
  border-radius: var(--r);
  border: 1.5px solid rgba(255, 255, 255, .15);
  background: rgba(255, 255, 255, .07);
  color: var(--white);
  outline: none;
  transition: border-color .2s;
}
.kiez-site .nl-form input::placeholder { color: #C9BBE0; opacity: 1; }
.kiez-site .nl-form input:focus { border-color: var(--orange); }

.kiez-site .nl-form input[type="submit"],
.kiez-site .nl-form .tnp-submit {
  font-family: var(--display);
  font-size: 13px;
  font-weight: 700;
  padding: 13px 26px;
  border-radius: var(--r);
  background: var(--orange);
  color: var(--white);
  border: none;
  cursor: pointer;
  white-space: nowrap;
  width: auto;
  transition: filter .2s, transform .2s;
}
.kiez-site .nl-form input[type="submit"]:hover { filter: brightness(1.1); transform: translateY(-1px); }

/* Consent checkbox / privacy line the plugin renders under the field. */
.kiez-site .nl-form .tnp-privacy-field,
.kiez-site .nl-form .tnp-privacy-field a { color: var(--text-on-dark-soft, #F2ECFF); font-size: 13px; }
.kiez-site .nl-form .tnp-privacy-field { flex-basis: 100%; }

/* --------------------------------------------------------------------------
   Page header (kiez-page-header).

   Not in the reference build — it only designed the full-height home hero — so
   this is composed from the design's own tokens and type scale. It is the sole
   structural difference between a section hub and an article page; everything
   below it is composed from the same elements as any other page.
   -------------------------------------------------------------------------- */

.kiez-site .page-header {
  background: var(--purple);
  padding: calc(90px + clamp(48px, 6vw, 88px)) 0 clamp(48px, 6vw, 80px);
  position: relative;
  overflow: hidden;
}

/* A page opening with this header supplies its own nav clearance, so the
   generic no-hero offset would double it up. */
.kiez-site.kiez-no-hero .confera-body-wrapper:has(.page-header) { padding-top: 0; }

/* #9110: a design page with neither hero nor purple band at the top
   (kiez_top_band() = plain) gets a solid nav from the first paint; reserve
   its height, or the first lines start underneath it. */
.kiez-site.kiez-top-plain .confera-body-wrapper { padding-top: 90px; }

.kiez-site .page-crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-family: var(--display);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-on-dark-soft, #F2ECFF);
  margin-bottom: 22px;
}
.kiez-site .page-crumbs a { color: inherit; opacity: .8; }
.kiez-site .page-crumbs a:hover,
.kiez-site .page-crumbs a:focus-visible { opacity: 1; color: var(--white); }  /* #8820: no orange on purple */
/* #8818: the breadcrumb is now a list, ends with the current page, and the
   top-level section is plain text (not a link). */
.kiez-site .page-crumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; list-style: none; margin: 0; padding: 0; }
.kiez-site .page-crumbs li { display: inline-flex; align-items: center; gap: 8px; }
.kiez-site .page-crumbs-sep { opacity: .5; }
.kiez-site .page-crumbs li > span:not(.page-crumbs-sep) { opacity: .8; }
.kiez-site .page-crumbs [aria-current="page"] { opacity: 1; color: var(--white); font-weight: 600; }

/* #8820 (2026-10-06): the purple variant of #8801 on every page header —
   eyebrow in the client's off-white instead of orange. */
.kiez-site .page-header .stl { color: var(--label-on-dark, #F4E8FF); margin-bottom: 10px; }

.kiez-site .page-title {
  font-family: var(--display);
  font-size: clamp(32px, 4.6vw, 60px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.03em;
  color: #fff;
  margin: 0;
  /* #9108: was 20ch (700px at 1440), which left most of the band empty and
     broke a 111-character event title into six lines. Balanced lines keep a
     long title from ending on a single orphaned word. */
  max-width: 34ch;
  text-wrap: balance;
  overflow-wrap: break-word;
}

/* #9108: titles over 60 characters (kiez_page_title_class()) and all post
   titles — news headlines run to 110 characters — use a smaller scale. */
.kiez-site .page-title--long,
.kiez-site .post-header .page-title { font-size: clamp(30px, 3.6vw, 48px); line-height: 1.08; }

/* #9120: band variants for single posts. Title in the content or hidden: a
   slim band with breadcrumb and eyebrow only (the nav still needs purple
   under it). Featured image behind the band: tinted to keep white text at
   7:1 or better. */
.kiez-site .page-header--title-content,
.kiez-site .page-header--title-none { padding-bottom: 36px; }
.kiez-site .page-header--title-content .stl,
.kiez-site .page-header--title-none .stl { margin-bottom: 0; }
.kiez-site .page-header--image {
  background: linear-gradient(rgba(60, 31, 102, .86), rgba(60, 31, 102, .86)), var(--kiez-header-img) center / cover no-repeat, var(--purple);
}
.kiez-site .screen-reader-text {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.kiez-site .page-intro {
  font-size: clamp(16px, 1.3vw, 19px);
  line-height: 1.6;
  color: var(--text-on-dark-soft, #F2ECFF);
  max-width: 68ch;
  margin: 20px 0 0;
}

@media (max-width: 767px) {
  .kiez-site .page-header { padding: calc(72px + 40px) 0 40px; }
  /* Long German compounds overflowed at 390px (#9108). Balanced lines are
     shorter, so on a phone they split more words; "pretty" only avoids an
     orphaned last word. */
  .kiez-site .page-title { max-width: none; hyphens: auto; text-wrap: pretty; }
  .kiez-site .page-title--long,
  .kiez-site .post-header .page-title { font-size: 26px; }
}

/* --------------------------------------------------------------------------
   Archive layer — blog, categories, single post, search, 404.

   The page SHELL is not in the agency reference (which designed the homepage
   and the component library, not an archive), so the two-column layout and the
   sidebar are composed from the design's tokens. The CARDS inside it are not
   invented: they are the agency's Blog-Vorschau (section 11), rendered by
   kiez_blog_card() in inc/cards.php — see the blog-card block further down.
   -------------------------------------------------------------------------- */

.kiez-site .archive-wrap { background: var(--white); padding: clamp(48px, 6vw, 88px) 0 clamp(64px, 8vw, 112px); }

.kiez-site .archive-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: clamp(32px, 4vw, 64px);
  align-items: start;
}

/* DEVIATION from the agency's .blog-grid (library.css), on two points:

   - minmax track 280px -> 320px. The agency's row runs the full page width;
     ours shares the row with a 320px sidebar, so a 280px track yielded four
     cramped columns and long German titles broke mid-word. 320px gives the
     three-up the agency actually drew.
   - min(320px, 100%) rather than a bare 320px, because below a ~370px viewport
     a fixed track overflows its content box. That used to be invisible behind
     `.kiez-site{overflow-x:hidden}`; a full-bleed featured image makes the
     clipping obvious.

   auto-FILL, deliberately, matching the agency. auto-fit collapses tracks that
   are empty across the whole grid, so a category archive with one post would
   stretch that single card across the full column with a 180px letterbox image
   strip. auto-fill keeps the tracks, so one result sits at one card's width. */
.kiez-site .archive-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
  gap: 24px;
}

.kiez-site .archive-empty { font-size: 16px; color: var(--purple); opacity: .75; }

/* Pagination -------------------------------------------------------------- */
.kiez-site .archive-pagination { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 40px; }
.kiez-site .archive-pagination .page-numbers {
  font-family: var(--display); font-size: 14px; font-weight: 600;
  padding: 10px 16px; border-radius: var(--r);
  border: 1.5px solid var(--violet-15); color: var(--purple);
  transition: background .2s, border-color .2s, color .2s;
}
.kiez-site .archive-pagination .page-numbers:hover { border-color: var(--violet); color: var(--violet); }
.kiez-site .archive-pagination .page-numbers.current { background: var(--violet); border-color: var(--violet); color: #fff; }

/* Single post ------------------------------------------------------------- */
/* #9119: image and text fill the column up to the sidebar; the old 72ch cap
   left 318px empty at 1440. "Lesebreite" is a per-post option (#9120).
   min-width: 0 lets a wide builder slider shrink instead of widening the
   grid track (a 14,000px carousel pushed the burger off a phone screen). */
.kiez-site .post-article,
.kiez-site .archive-main { max-width: none; min-width: 0; }
.kiez-site .post-article--reading { max-width: 75ch; }
/* Highlight Box text is a <div> now (audit 10-12): paragraphs keep the variant's colour and size. */
.kiez-site :is(.highlight-body-text, .highlight-body-text-2) p { margin: 0 0 .6em; }
.kiez-site :is(.highlight-body-text, .highlight-body-text-2) > :last-child { margin-bottom: 0; }
/* Without a sidebar the reading column sat at the left of an empty half (audit 10-12). */
.kiez-site .archive-layout--full .post-article--reading { margin-inline: auto; }
.kiez-site .archive-layout--full { grid-template-columns: minmax(0, 1fr); }
.kiez-site .post-meta { font-family: var(--display); font-size: 13px; font-weight: 700; color: var(--orange); margin-bottom: 22px; }
.kiez-site .post-figure { margin: 0 0 32px; border-radius: var(--r); overflow: hidden; }
/* #9117: the image kept its attribute height (428px) while max-width shrank
   its width, so every featured image was stretched (302×428 on a phone);
   Confera's img { height: auto } reset is dequeued on design pages. The
   format is a per-post option; the default matches the 1100×460 uploads. */
.kiez-site .post-figure img { display: block; width: 100%; height: auto; object-fit: cover; }
.kiez-site .post-figure--wide img { aspect-ratio: 1100 / 460; }
.kiez-site .post-figure--16-9 img { aspect-ratio: 16 / 9; }
.kiez-site .post-figure--3-2 img { aspect-ratio: 3 / 2; }
.kiez-site .post-figure--4-3 img { aspect-ratio: 4 / 3; }
.kiez-site .post-figure--natural img { aspect-ratio: auto; max-height: 720px; object-fit: contain; }
/* #9120: title above the image instead of in the band. */
.kiez-site .post-title {
  font-family: var(--display); font-size: clamp(28px, 3.4vw, 44px); font-weight: 800;
  line-height: 1.1; letter-spacing: -.02em; color: var(--purple);
  margin: 0 0 28px; overflow-wrap: break-word; text-wrap: balance;
}
.kiez-site .post-body { font-size: 17px; line-height: 1.75; color: var(--purple); }
.kiez-site .post-body > * + * { margin-top: 1.1em; }
.kiez-site .post-body h2 { font-family: var(--display); font-size: clamp(24px, 2.4vw, 32px); font-weight: 700; letter-spacing: -.02em; margin-top: 1.8em; }
.kiez-site .post-body h3 { font-family: var(--display); font-size: clamp(20px, 2vw, 25px); font-weight: 700; letter-spacing: -.015em; margin-top: 1.6em; }
/* h4–h6 fell back to the design reset and an h5 came out at 14px, smaller
   than the 17px text it heads (#9119, post 12635). */
.kiez-site .post-body :is(h4, h5, h6) { font-family: var(--display); font-size: 18px; font-weight: 700; letter-spacing: -.01em; margin-top: 1.5em; }
.kiez-site .post-body a:not(.wp-block-button__link) { color: var(--violet); text-decoration: underline; text-underline-offset: .2em; }
/* Block-editor buttons read violet-underlined on #32373C (2.2:1); give them
   the design's filled button instead. */
.kiez-site .post-body .wp-block-button__link {
  display: inline-block; padding: 14px 28px; border-radius: var(--r);
  background: var(--orange); color: #fff; text-decoration: none;
  font-family: var(--display); font-size: 15px; font-weight: 600;
}
.kiez-site .post-body .wp-block-button__link:hover { filter: brightness(1.1); }
.kiez-site .post-body img { border-radius: var(--r); }
.kiez-site .post-body img:not(.image-el) { height: auto; }
.kiez-site .post-body blockquote {
  margin: 1.6em 0; padding: 4px 0 4px 24px;
  border-left: 3px solid var(--orange);
  font-family: var(--display); font-size: 20px; font-weight: 700; line-height: 1.4; color: var(--violet);
}
.kiez-site .post-body ul, .kiez-site .post-body ol { padding-left: 1.3em; }
.kiez-site .post-body li { list-style: disc; margin-top: .4em; }
.kiez-site .post-body ol li { list-style: decimal; }

/* #9118: page-builder content of a post, in the article column. The page
   gutter (#8917) is for whole pages; inside the article the content lines
   up with the date and the image instead. Selectors carry an ID's weight
   (:not(#kiez-post)) so they outrank the #8917 rules they correct, while an
   editor's inline padding still wins. */
.kiez-site .post-builder { isolation: isolate; }   /* GoodLayers paints column backgrounds at z-index -2, under .archive-wrap's white */
.kiez-site .post-body + .post-builder { margin-top: 1.1em; }
.kiez-site .post-builder:not(#kiez-post) :is(.gdlr-core-pbf-wrapper-container, .gdlr-core-pbf-section-container) {
  max-width: none; margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0;
}
.kiez-site .post-builder:not(#kiez-post) .gdlr-core-pbf-wrapper-container > .gdlr-core-pbf-element { padding-left: 0; padding-right: 0; }
.kiez-site .post-builder:not(#kiez-post) > .gdlr-core-page-builder-body > :first-child { padding-top: 0; }
.kiez-site .post-builder:not(#kiez-post) > .gdlr-core-page-builder-body > :last-child { padding-bottom: 0; }
@media (min-width: 768px) {   /* below 768px GoodLayers zeroes column padding itself */
  .kiez-site .post-builder:not(#kiez-post) .gdlr-core-pbf-wrapper-container { margin-left: -10px; margin-right: -10px; }
  .kiez-site .post-builder:not(#kiez-post) .gdlr-core-pbf-wrapper-container > .gdlr-core-pbf-element { padding-left: 10px; padding-right: 10px; }
}
/* A full-width band dropped into a post stays in the article: breaking out
   ran it under the sidebar. A page header is dropped, the post has its own. */
.kiez-site .post-builder section:is(.hero, .about, .news, .events, .newsletter, .contact):not(#kiez-post) { width: auto; max-width: 100%; margin-left: 0; margin-right: 0; }
.kiez-site .post-builder section.page-header { display: none; }
/* Article typography for GoodLayers text boxes only — a blanket link rule
   would turn KI:EZ buttons into violet underlined text. */
.kiez-site .post-builder .gdlr-core-text-box-item-content { font-size: 17px; line-height: 1.75; color: var(--purple); }
.kiez-site .post-builder .gdlr-core-text-box-item-content > * + * { margin-top: 1.1em; }
.kiez-site .post-builder .gdlr-core-text-box-item-content a { color: var(--violet); text-decoration: underline; text-underline-offset: .2em; }
.kiez-site .post-builder .gdlr-core-text-box-item-content :is(ul, ol) { padding-left: 1.3em; }
.kiez-site .post-builder .gdlr-core-text-box-item-content li { list-style: disc; margin-top: .4em; }
.kiez-site .post-builder .gdlr-core-text-box-item-content ol li { list-style: decimal; }
/* Legacy GoodLayers gallery carousel in the old posts (12606): portrait and
   landscape photos side by side made the slides uneven, with white gaps.
   One height, cropped to fill, gaps and corners as in the design. */
.kiez-site .post-builder .gdlr-core-gallery-item .flexslider .slides > li { padding: 0 6px; }
.kiez-site .post-builder .gdlr-core-gallery-item .flexslider .slides img {
  width: 100%; height: clamp(180px, 22vw, 300px); object-fit: cover; border-radius: var(--r);
}

.kiez-site .post-nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 56px; }   /* minmax: a long word must not widen the track (320px) */
.kiez-site .post-nav a {
  display: block; padding: 20px 22px; border-radius: var(--r);
  border: 1.5px solid var(--violet-10);
  font-family: var(--display); font-weight: 700; color: var(--violet); line-height: 1.35;
  transition: border-color .25s, transform .25s;
}
.kiez-site .post-nav a:hover { border-color: var(--violet); transform: translateY(-2px); }
/* Only the label, not the brand span inside the title (2026-10-12: "KI:Expertisezentrum.nrw"
   showed as a small orange line since the titles go through kiez_brand_html). */
.kiez-site .post-nav a > span:not(.kiez-brand) { display: block; font-size: 12px; font-weight: 600; color: var(--orange); margin-bottom: 6px; }
.kiez-site .post-nav-next { text-align: right; }

/* Sidebar ----------------------------------------------------------------- */
.kiez-site .archive-side { display: flex; flex-direction: column; gap: 28px; position: sticky; top: 110px; }
.kiez-site .archive-side--tall { position: static; }   /* taller than the window (site.js, #9109) */
.kiez-site .side-block { border: 1.5px solid var(--violet-10); border-radius: var(--r); padding: 24px; }
.kiez-site .side-label {
  font-family: var(--display); font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .15em; color: var(--orange); margin-bottom: 16px;
}
.kiez-site .side-cats { display: flex; flex-direction: column; gap: 2px; }
.kiez-site .side-cats a {
  display: flex; justify-content: space-between; gap: 12px;
  font-family: var(--display); font-size: 15px; font-weight: 500; color: var(--purple);
  padding: 9px 10px; border-radius: 6px; transition: background .2s, color .2s;
}
.kiez-site .side-cats a:hover { background: var(--violet-06); color: var(--violet); }
.kiez-site .side-cats a.is-current { background: var(--violet); color: #fff; }
.kiez-site .side-cats span { opacity: .6; font-size: 13px; }

.kiez-site .side-list { display: flex; flex-direction: column; gap: 16px; }
.kiez-site .side-list a { display: block; font-family: var(--display); font-size: 15px; font-weight: 600; color: var(--violet); line-height: 1.35; }
.kiez-site .side-list a:hover { color: var(--orange); }
.kiez-site .side-list time { display: block; font-size: 12px; color: var(--text-on-light-soft, #5C447E); margin-top: 4px; }
.kiez-site .side-block .btn-ghost { margin-top: 18px; }

.kiez-site .side-block-cta { background: var(--purple); border-color: transparent; }
.kiez-site .side-block-cta p { font-size: 14px; line-height: 1.6; color: var(--text-on-dark-soft, #F2ECFF); margin: 0 0 16px; }
.kiez-site .side-block-cta .nl-form .tnp-subscription form { flex-direction: column; align-items: stretch; }
.kiez-site .side-block-cta .nl-form input[type="submit"] { width: 100%; }

/* Search + 404 ------------------------------------------------------------ */
.kiez-site .search-form { display: flex; gap: 10px; margin-bottom: 36px; flex-wrap: wrap; }
.kiez-site .search-form input[type="search"] {
  flex: 1; min-width: 220px;
  font-family: var(--body); font-size: 15px; padding: 14px 18px;
  border-radius: var(--r); border: 1.5px solid var(--violet-15);
  background: var(--white); color: var(--purple); outline: none;
}
.kiez-site .search-form input[type="search"]:focus { border-color: var(--violet); }
.kiez-site .notfound-links { display: flex; flex-wrap: wrap; gap: 10px; }

@media (max-width: 900px) {
  .kiez-site .archive-layout { grid-template-columns: minmax(0, 1fr); }   /* 1fr grew with a slider's min-content (#9118) */
  .kiez-site .archive-side { position: static; }
  .kiez-site .post-nav { grid-template-columns: minmax(0, 1fr); }
  .kiez-site .post-nav-next { text-align: left; }
}

/* --------------------------------------------------------------------------
   Atoms placed directly in builder columns.

   The design's cards were written as children of a grid (.bento, .logo-row,
   .mission-list). Composed in the builder they sit one-per-column instead, so
   they have to stand on their own and fill whatever column they are given.
   -------------------------------------------------------------------------- */

/* IMPORTANT: these must match only a card placed *directly* as an element —
   i.e. a standalone atom. Written as a descendant selector they also hit cards
   rendered inside a feed element's own track (.news-track > .news-card), which
   forced every news card to 100% width and collapsed the horizontal scroller
   to a single visible card. The child combinator keeps atoms and feeds apart. */

.kiez-site .gdlr-core-pbf-element > .bento-card,
.kiez-site .gdlr-core-pbf-element > .logo-pill { height: 100%; width: 100%; }

/* .bento-card is flex-column in the design; keep the link pinned to the
   bottom so cards of differing text length still line up. */
.kiez-site .gdlr-core-pbf-element > .bento-card { display: flex; flex-direction: column; }
.kiez-site .gdlr-core-pbf-element > .bento-card .btn-ghost { margin-top: auto; }

/* ...but `height: 100%` had nothing to fill: GoodLayers columns are floats
   of their own content height, so a card with a longer text still ended
   lower than its neighbours (Apps, 24px). The design's .bento grid stretched
   all three. A column row holding field cards becomes a wrapping flex row
   instead; stretched flex items have a definite height, so the 100% chain
   resolves down to the card. Column widths stay GoodLayers' own. */
.kiez-site .gdlr-core-pbf-wrapper-container:has(> .gdlr-core-pbf-column .bento-card) { display: flex; flex-wrap: wrap; }
.kiez-site .gdlr-core-pbf-wrapper-container:has(> .gdlr-core-pbf-column .bento-card)::before,
.kiez-site .gdlr-core-pbf-wrapper-container:has(> .gdlr-core-pbf-column .bento-card)::after { content: none; }   /* clearfix, would become flex items */
.kiez-site .gdlr-core-pbf-column:has(.bento-card) > .gdlr-core-pbf-column-content-margin,
.kiez-site .gdlr-core-pbf-column:has(.bento-card) .gdlr-core-pbf-column-content { height: 100%; }
/* The column content is a flex column whose card element takes the rest: a
   caption element above a card (Elemente page) used to become column-tall
   too and pushed the card one card-height down over the next row (#9105). */
.kiez-site .gdlr-core-pbf-column:has(.bento-card) .gdlr-core-pbf-column-content { display: flex; flex-direction: column; }
.kiez-site .gdlr-core-pbf-column:has(.bento-card) .gdlr-core-pbf-column-content > .gdlr-core-pbf-element:has(> .bento-card) { flex: 1 0 auto; }
/* Catalogue rows: the wrap margin on all but the last column made the first
   card 28px shorter side by side; a row gap spaces wrapped columns instead. */
.kiez-site .spec-demo-row .gdlr-core-pbf-wrapper-container:has(> .gdlr-core-pbf-column .bento-card) { row-gap: 28px; }
.kiez-site .spec-demo-row .gdlr-core-pbf-column:has(.bento-card) { margin-bottom: 0; }

/* Row-shaped atoms span the full column. `.news-card` is deliberately absent:
   kiez-card only ever emits it inside its own .news-track, never as a direct
   child of an element, so that arm never matched anything. */
.kiez-site .gdlr-core-pbf-element > .mission-item,
.kiez-site .gdlr-core-pbf-element > .ev { width: 100%; flex: none; }

/* Blog cards need no equivalent: .blog-card-light/-dark are flex containers and
   .blog-grid-2 is a grid, so all three are block-level and already fill the
   column at width:auto. .mission-item and .ev need the rule because the design
   sizes them as flex ITEMS of a row they no longer sit in. */

/* --------------------------------------------------------------------------
   Reveal stagger for atoms in a builder row.

   In the reference the cards of a grid carry .d1/.d2/.d3, which are just
   transition-delays, so a row fades in left-to-right instead of all at once.
   Those classes came from the card's index inside the monolithic grid element.
   Composed from atoms there is no index to read — but the builder column
   already encodes the position, so take the delay from that instead. Same
   values as .rv.d1/.d2/.d3 in site.css.

   The `> .rv` matters: it restricts this to an atom placed directly as an
   element. Without it, the cards inside a feed element's own track (e.g.
   .news-track > .news-card, which carry their own .d1/.d2/.d3) would all be
   flattened to their column's single delay and lose their internal stagger.

   Note the section head usually sits in the row's first (full-width) column,
   so the cards start at :nth-child(2) and the whole cascade is offset by one
   step against the reference. Only the spacing between siblings is visible —
   each element's delay starts when it crosses the observer threshold, not at
   a shared moment — so the offset does not read on screen. */

.kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-pbf-column:nth-child(2) .gdlr-core-pbf-element > .rv { transition-delay: .08s; }
.kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-pbf-column:nth-child(3) .gdlr-core-pbf-element > .rv { transition-delay: .16s; }
.kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-pbf-column:nth-child(4) .gdlr-core-pbf-element > .rv { transition-delay: .24s; }
.kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-pbf-column:nth-child(n+5) .gdlr-core-pbf-element > .rv { transition-delay: .32s; }

/* Consecutive builder elements should not lose the design's rhythm. */
.kiez-site .gdlr-core-pbf-column .stl + .sth,
.kiez-site .gdlr-core-pbf-element .stl + .sth { margin-top: 6px; }
.kiez-site .gdlr-core-pbf-element > .sth { margin-bottom: 0; }

/* Light variants, for the same atoms on the purple surfaces. */
.kiez-site .stl-light { color: var(--text-on-dark-soft, #F2ECFF); }
.kiez-site .sth-light { color: #fff; }

/* --------------------------------------------------------------------------
   Element library (kiez-spec) — the Elemente page.

   Mirrors the reference library page: a numbered spec header above each live
   element, so the catalogue documents itself and can never drift from what the
   builder actually renders.
   -------------------------------------------------------------------------- */

.kiez-site .spec {
  border-top: 2px solid var(--violet-15);
  padding-top: 22px;
  margin-bottom: 28px;
}
.kiez-site .spec-num {
  font-family: var(--display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--orange);
  margin-bottom: 10px;
}
.kiez-site .spec-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
}
.kiez-site .spec-name {
  font-family: var(--display);
  font-size: clamp(22px, 2.2vw, 30px);
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--violet);
  margin: 0;
}
.kiez-site .spec-slug {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  background: var(--violet-06);
  border: 1px solid var(--violet-15);
  color: var(--purple);
  padding: 3px 9px;
  border-radius: 5px;
}
.kiez-site .spec-desc {
  font-size: 16px;
  line-height: 1.6;
  color: var(--purple);
  max-width: 78ch;
  margin: 12px 0 0;
}
.kiez-site .spec-usage {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-on-light-soft, #5C447E);
  max-width: 78ch;
  margin: 8px 0 0;
}
.kiez-site .spec-usage strong { color: var(--violet); }

/* Dark demo surface on the Elemente page (the front page now uses the
   design's own .mission / .consortium classes instead). */
.kiez-site .kiez-block-dark { background: var(--purple); }

/* On dark demo surfaces the spec header inverts. */
.kiez-site .kiez-block-dark .spec { border-top-color: rgba(255, 255, 255, .22); }
.kiez-site .kiez-block-dark .spec-name { color: #fff; }
.kiez-site .kiez-block-dark .spec-desc { color: var(--text-on-dark-soft, #F2ECFF); }
.kiez-site .kiez-block-dark .spec-usage { color: var(--text-on-dark-soft, #F2ECFF); opacity: .85; }
.kiez-site .kiez-block-dark .spec-usage strong { color: #fff; }
.kiez-site .kiez-block-dark .spec-slug {
  background: rgba(255, 255, 255, .10);
  border-color: rgba(255, 255, 255, .22);
  color: #fff;
}

/* Demo surface so a white-on-white element is still visible. */
.kiez-site .spec-demo-row .spec-demo {
  border: 1.5px dashed var(--violet-15);
  border-radius: var(--kiez-r, 8px);
  padding: 28px;
  margin-bottom: 64px;
  background: var(--off-white);
}

/* --------------------------------------------------------------------------
   Section container for atom-built sections.

   The design's section padding and page gutter came from its own markup
   (`<section class="mission"><div class="wrap">`). Sections composed from
   atoms in the builder have neither, so their content ran edge to edge with no
   vertical rhythm. `.kiez-gutter` on the section wrapper restores both, using
   the same values as the design's own `.wrap`.

   Sections whose element already renders its own <section>/<div class="wrap">
   (hero, about, news feed, events feed, newsletter, contact, page header) must
   NOT carry this class, or the gutter doubles up.
   -------------------------------------------------------------------------- */

/* `.kiez-gutter` now only reproduces the design's `.wrap` container. Vertical
   padding, background and the label/title colours come from the design's own
   section classes (.fields, .mission, .consortium), which the wrapper carries —
   so the reference CSS applies directly instead of being reimplemented here. */

/* The heading row needs breathing space before the cards below it. */
.kiez-site .kiez-gutter .gdlr-core-pbf-column .sth { margin-bottom: 40px; }

/* --------------------------------------------------------------------------
   Column gutters in atom-built sections.

   The design spaced its cards with `.bento { gap: 20px }`. Composed from atoms
   the cards are separate builder columns, so the gap has to come from column
   padding instead — 10px each side. Two corrections are needed:

   1) The section container subtracts that 10px so the outer edges still align
      with the page gutter (24 / 48 / 20px).
   2) GoodLayers forces `padding: 0 30px !important` on columns below 767px
      (page-builder.css, .gdlr-core-pbf-wrapper-full-no-space). Ours must win,
      hence the matching !important — the only place we use it.
   -------------------------------------------------------------------------- */

/* Reproduces the design's `.wrap`: max-width var(--max) centred, then padding.
   The 10px column half-gap is subtracted from the padding so the outer edge
   lands in exactly the same place as the reference:
       24px (from max-width) + 14px (padding) + 10px (column) = 48px
   matching `.wrap { max-width: calc(100% - 48px); padding: 0 24px }`. */
.kiez-site .kiez-gutter .gdlr-core-pbf-wrapper-container {
  max-width: var(--max);
  margin-left: auto;
  margin-right: auto;
  padding: 0 14px;
}

@media (min-width: 1800px) {
  .kiez-site .kiez-gutter .gdlr-core-pbf-wrapper-container { padding: 0 38px; }
}
@media (max-width: 600px) {
  .kiez-site .kiez-gutter .gdlr-core-pbf-wrapper-container { padding: 0 10px; }
}

.kiez-site .kiez-gutter .gdlr-core-pbf-column-content-margin {
  padding-left: 10px !important;
  padding-right: 10px !important;
}

/* Vertical rhythm between stacked rows (mission rows, logo tiles wrapping).
   Only a heading row (section title) sits tight on what follows; the rule
   used to zero ANY first column, so stacked content columns touched on
   phones (13 of 24 pairs on /elemente/, #9101). */
.kiez-site .kiez-gutter .gdlr-core-pbf-column { margin-bottom: 20px; }
.kiez-site .kiez-gutter .gdlr-core-pbf-column:first-child:has(.sth) { margin-bottom: 0; }
/* Hand-built rows: GoodLayers stacks columns below 768px with no gap. */
@media (max-width: 767px) {
  .kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) .gdlr-core-pbf-column + .gdlr-core-pbf-column { margin-top: var(--kiez-space-col, 24px); }
}

/* KI:EZ Pullquote with attribution (#9101). */
.kiez-site .pullquote-figure { margin: 0; }
.kiez-site .pullquote-cite {
  display: block; margin-top: 14px; padding-left: 28px;   /* under the text, past the bar */
  font-size: 14px; line-height: 1.5; color: var(--text-on-light-soft, #5C447E);
}
.kiez-site .pullquote-cite strong { color: var(--purple); font-weight: 700; }

/* --------------------------------------------------------------------------
   Grid-container equivalents.

   The design wrapped its cards in .bento (grid, gap 20, margin-top 48),
   .logo-row (centred flex, max-width 1260) and .mission-list. Composed from
   atoms those roles fall to GDLR's column row, so the spacing they contributed
   is reproduced here on the section's own container.
   -------------------------------------------------------------------------- */

/* .bento { margin-top: 48px } — space between the heading row and the cards. */
.kiez-site .fields .gdlr-core-pbf-column.gdlr-core-column-20 { margin-top: 48px; }

/* .logo-row { justify-content: center; max-width: 1260px; margin: 0 auto } */
.kiez-site .consortium .gdlr-core-pbf-wrapper-container {
  max-width: 1260px;
  justify-content: center;
}
.kiez-site .consortium .gdlr-core-pbf-column.gdlr-core-column-15 { margin-top: 16px; }

@media (min-width: 1800px) {
  .kiez-site .consortium .gdlr-core-pbf-wrapper-container { max-width: 1400px; }
}

/* .mission-list { gap: 0 } — rows already sit flush; only the header spaces. */
.kiez-site .mission .gdlr-core-pbf-column { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   Library components — states the agency expressed as runtime bindings.

   The Bausteine page drove tab colour, the FAQ icon rotation and the audio
   progress width through its prototype runtime's inline `style="{{ … }}"`
   bindings, so library.css contains no CSS for those states. ui.js toggles
   real classes instead; these rules give those classes the same appearance.
   -------------------------------------------------------------------------- */

/* Tabs — active state (was `style="color:{{ tab.color }}"`). */
.kiez-site .tabs-tab-btn[aria-selected="true"],
.kiez-site .tabs-tab-btn-vertical[aria-selected="true"] {
  color: var(--violet);
  border-color: var(--orange);
  background: rgba(134, 53, 246, .06);
}
.kiez-site .tabs-tab-btn,
.kiez-site .tabs-tab-btn-vertical { color: var(--text-on-light-soft, #5C447E); }
.kiez-site .tabs-tab-btn:hover,
.kiez-site .tabs-tab-btn-vertical:hover { color: var(--violet); }

/* FAQ — icon rotation (was `style="transform:{{ item.iconTransform }}"`). */
.kiez-site .faq-toggle-icon { transition: transform .3s; }
.kiez-site .faq-block.kiez-open .faq-toggle-icon { transform: rotate(45deg); }

/* Masked icons — the library hardcodes one class per bundled icon; we pass the
   mask as a custom property so any uploaded SVG works. */
.kiez-site .kiez-icon-mask {
  display: block;
  width: 64px;
  height: 64px;
  background-color: var(--kiez-fi-color, var(--violet));
  mask-image: var(--kiez-fi-mask);
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-image: var(--kiez-fi-mask);
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
}
.kiez-site .icon-card-dark .kiez-icon-mask { background-color: var(--kiez-fi-color, var(--orange)); }   /* per-card colour on dark too (#8930) */

.kiez-site .icon-label,
.kiez-site .icon-label-dark {
  font-family: var(--display);
  font-size: 14px;
  font-weight: 700;
  text-align: center;
}
.kiez-site .icon-label { color: var(--purple); }
.kiez-site .icon-label-dark { color: #fff; }

/* --------------------------------------------------------------------------
   Elemente page rhythm.

   Each entry is a spec row followed by one or two demo rows. Those wrappers
   carry no inline padding (so the design's section classes can govern on real
   pages), which means GoodLayers' default `.gdlr-core-pbf-wrapper
   { padding: 60px 0 30px }` applied to all 73 — 90px between a heading and its
   own demo, and again before the next entry. These give the page one rhythm.
   Specificity (0,2,0) beats the plugin default (0,1,0).
   -------------------------------------------------------------------------- */

.kiez-site .kiez-spec-row  { padding: 64px 0 0; }
.kiez-site .spec-demo-row  { padding: 28px 0 64px; }

/* A light demo row followed by its dark counterpart is one demo, not two. */
.kiez-site .spec-demo-row + .spec-demo-row { padding-top: 0; }
.kiez-site .kiez-spec-row + .spec-demo-row { padding-top: 28px; }

/* The first entry sits directly under the page header. */
.kiez-site .kiez-spec-row:first-of-type { padding-top: 48px; }

/* Captions above each variant need a little air from the element below. */
.kiez-site .spec-demo-row .btn-demo-label,
.kiez-site .spec-demo-row .btn-demo-label-2 { margin-bottom: 14px; }

/* Variants sitting side by side in a row want vertical breathing room when
   they wrap onto a second line. */
.kiez-site .spec-demo-row .gdlr-core-pbf-column { margin-bottom: 28px; }
.kiez-site .spec-demo-row .gdlr-core-pbf-column:last-child { margin-bottom: 0; }

@media (max-width: 600px) {
  .kiez-site .kiez-spec-row { padding-top: 40px; }
  .kiez-site .spec-demo-row { padding: 20px 0 40px; }
}

/* --------------------------------------------------------------------------
   Single event — the facts block above the description.
   -------------------------------------------------------------------------- */

.kiez-site .event-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 20px;
  padding: 24px;
  margin-bottom: 32px;
  border: 1.5px solid var(--violet-10);
  border-radius: var(--r);
  background: var(--off-white);
}
.kiez-site .event-fact { font-size: 15px; line-height: 1.5; color: var(--purple); }
.kiez-site .event-fact-label {
  display: block;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--orange);
  margin-bottom: 6px;
}
.kiez-site .event-fact-sub { display: block; font-size: 13px; color: var(--text-on-light-soft, #5C447E); margin-top: 4px; }
.kiez-site .event-facts .btn-ghost { margin-top: 2px; }
/* #9106: category and tag chips under the facts, as pills like the page
   numbers; each opens the calendar filtered by that term. */
.kiez-site .event-terms { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: -12px 0 32px; padding: 0; }
.kiez-site .event-term {
  display: inline-block; padding: 7px 14px; border-radius: 999px;
  border: 1.5px solid var(--violet-15); color: var(--purple);
  font-family: var(--display); font-size: 13px; font-weight: 600;
  transition: border-color .2s, color .2s;
}
.kiez-site .event-term:hover,
.kiez-site .event-term:focus-visible { border-color: var(--violet); color: var(--violet); }

/* --------------------------------------------------------------------------
   Events archive — The Events Calendar's own views inside the design's page.

   TEC's list/month/day views are not rebuilt here: they carry live filtering,
   a datepicker and an iCal subscribe menu that would all have to be
   reimplemented, and they ship a self-contained stylesheet that already
   handles their layout and breakpoints. So these rules only make that
   stylesheet agree with the surrounding page — typeface, ink and accent — and
   stop it from applying a second page container inside ours.

   TEC's own selectors sit at (0,1,0)–(0,2,0); everything here is at least
   (0,3,0) via .kiez-site .kiez-events-archive, so nothing needs !important.

   Deliberate: no sidebar on this archive, unlike /blog/ and single posts.
   TEC's events bar (keyword search + view selector + top bar) is built for
   full width and becomes unusable in a two-thirds column.
   -------------------------------------------------------------------------- */

/* Typeface. The attribute selectors catch the BEM classes TEC sets a
   font-family on directly (.tribe-common-h5, .tribe-common-b2, …), which plain
   inheritance from .tribe-common would not reach. */
.kiez-site .kiez-events-archive .tribe-common,
.kiez-site .kiez-events-archive [class^="tribe-"],
.kiez-site .kiez-events-archive [class*=" tribe-"] {
  font-family: var(--body);
  color: var(--purple);
}

/* Headings and the date tag take the display face. */
.kiez-site .kiez-events-archive .tribe-events-calendar-list__event-title,
.kiez-site .kiez-events-archive .tribe-events-calendar-list__event-title-link,
.kiez-site .kiez-events-archive .tribe-events-calendar-list__month-separator-text,
.kiez-site .kiez-events-archive .tribe-events-calendar-list__event-date-tag-daynum,
.kiez-site .kiez-events-archive .tribe-events-calendar-list__event-date-tag-weekday,
.kiez-site .kiez-events-archive .tribe-events-calendar-list__event-venue-title,
.kiez-site .kiez-events-archive .tribe-events-header__content-title,
.kiez-site .kiez-events-archive .tribe-events-c-top-bar__today-button,
.kiez-site .kiez-events-archive .tribe-events-c-top-bar__nav-link,
.kiez-site .kiez-events-archive .tribe-events-c-view-selector__list-item-text,
.kiez-site .kiez-events-archive .tribe-events-c-subscribe-dropdown__button-text,
.kiez-site .kiez-events-archive .tribe-events-c-nav__prev,
.kiez-site .kiez-events-archive .tribe-events-c-nav__next,
.kiez-site .kiez-events-archive .tribe-events-c-nav__today {
  font-family: var(--display);
}

.kiez-site .kiez-events-archive .tribe-events-calendar-list__event-title-link {
  color: var(--purple);
  transition: color .2s;
}
.kiez-site .kiez-events-archive .tribe-events-calendar-list__event-title-link:hover,
.kiez-site .kiez-events-archive .tribe-events-calendar-list__event-title-link:focus-visible {
  color: var(--orange);
}

/* The day-number block is the one place the design's accent belongs. */
.kiez-site .kiez-events-archive .tribe-events-calendar-list__event-date-tag-daynum {
  color: var(--violet);
}

/* Month separators read as section labels. */
.kiez-site .kiez-events-archive .tribe-events-calendar-list__month-separator-text {
  color: var(--orange);
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* Links: violet, orange on interaction, matching the rest of the site. */
.kiez-site .kiez-events-archive .tribe-common-anchor-thin,
.kiez-site .kiez-events-archive .tribe-events-c-top-bar__nav-link,
.kiez-site .kiez-events-archive .tribe-events-c-nav__prev,
.kiez-site .kiez-events-archive .tribe-events-c-nav__next { color: var(--violet); }
.kiez-site .kiez-events-archive .tribe-common-anchor-thin:hover,
.kiez-site .kiez-events-archive .tribe-common-anchor-thin:focus-visible { color: var(--orange); }

/* Buttons keep TEC's geometry but take the brand face and accent. */
.kiez-site .kiez-events-archive .tribe-common-c-btn,
.kiez-site .kiez-events-archive .tribe-events-c-search__button,
.kiez-site .kiez-events-archive .tribe-events-c-subscribe-dropdown__button {
  font-family: var(--display);
}
/* #8821 (2026-10-06): the primary button is orange with white text, like
   every other primary button in the design (.btn-fill). It was violet with
   TEC's dark text — 2.4:1, too little contrast. */
.kiez-site .kiez-events-archive .tribe-events-c-search__button {
  background-color: var(--orange);
  border-color: var(--orange);
  color: var(--white);
}
.kiez-site .kiez-events-archive .tribe-events-c-search__button:hover,
.kiez-site .kiez-events-archive .tribe-events-c-search__button:focus-visible {
  background-color: var(--orange);
  border-color: var(--orange);
  color: var(--white);
  filter: brightness(1.1);
}
.kiez-site .kiez-events-archive .tribe-events-c-search__button:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }

/* The active view tab. */
.kiez-site .kiez-events-archive .tribe-events-c-view-selector__list-item--active
  .tribe-events-c-view-selector__list-item-text { color: var(--violet); }

/* One container, not two: ours already sets the max-width and gutters. */
.kiez-site .kiez-events-archive .tribe-common-l-container,
.kiez-site .kiez-events-archive .tribe-events-l-container {
  max-width: none;
  padding-left: 0;
  padding-right: 0;
}

/* --------------------------------------------------------------------------
   Blog card (agency section 11, "Blog-Vorschau") in real use.

   library.css carries the agency's rules verbatim and stays untouched. What
   follows is only what a live listing needs and a static specimen does not.
   The markup is in inc/cards.php, which documents the DOM deviations; these
   are the matching CSS ones.
   -------------------------------------------------------------------------- */

/* 1. Equal heights. The agency specimen has one-line excerpts, so .blog-block-2
      is a plain block. Real posts have variable excerpts, which left ragged
      cards and a floating "Lesen →". Same treatment already used on
      .bento-card above. `flex: none` keeps the image strip from being
      squashed once it becomes a flex item. */
.kiez-site .blog-card-light,
.kiez-site .blog-card-dark { display: flex; flex-direction: column; }
/* Client 2026-10-12 (blog teaser images full width): the strip keeps the
   featured-image format instead of library.css's fixed 180px (250px from
   1800px). With a fixed height its ratio swung from 1.6 to 2.4 with the
   column width and cut the sides off the 1100 × 460 images. At 1440px (430px
   card) this is the agency's 430 × 180 exactly. */
.kiez-site { --kiez-post-ratio: 1100 / 460; }
.kiez-site .blog-card-light > .blog-block,
.kiez-site .blog-card-dark > .blog-block { flex: none; height: auto; aspect-ratio: var(--kiez-post-ratio); }
.kiez-site .blog-card-light > .blog-block-2,
.kiez-site .blog-card-dark > .blog-block-2 { flex: 1; display: flex; flex-direction: column; }
.kiez-site .blog-card-light .card-link-arrow,
.kiez-site .blog-card-dark .card-link-arrow { margin-top: auto; }

/* 2. Whole-card click target. The link is on the title, so its accessible name
      is the title alone rather than the card's ~40 words; this overlay gives
      pointer users the full-card target back.

      TRADE-OFF, accepted: the overlay covers the card and takes the pointer, so
      the excerpt is no longer selectable by dragging across it. That is the
      cost of every full-card-overlay pattern — `pointer-events: none` would
      restore selection but also remove the click target the overlay exists for.
      A short accessible name is worth more here than selectable teaser text;
      the full text is one click away.

      Anything interactive added inside a card later must be raised above the
      overlay with `position: relative; z-index: 1`. */
.kiez-site .blog-card-light,
.kiez-site .blog-card-dark { position: relative; }
.kiez-site .blog-card-link::after { content: ''; position: absolute; inset: 0; }

/* 3. Keyboard focus follows the card's 8px radius rather than drawing a square
      ring around the title text inside a rounded card.

      :has(:focus-visible), not :focus-within — :focus-within also fires when
      the link is clicked with a mouse, which would flash the ring and the image
      zoom at every pointer user.

      The ring is violet on BOTH variants. `outline` paints outside the border
      box, so on the dark card it still lands on the white page behind it, not
      on the card's own #3C1F66 — gold there measures 1.62:1 against white and
      fails SC 1.4.11. Violet is 5.45:1 on white.

      Wrapped in @supports, and the link's own `outline: none` with it: an
      unsupported :has() would otherwise drop the card ring while the
      outline-removal still applied, leaving no focus indicator at all. Inside
      the guard the card takes the ring; outside it, the link keeps its own. */
@supports selector(:has(*)) {
  .kiez-site .blog-card-light:has(.blog-card-link:focus-visible),
  .kiez-site .blog-card-dark:has(.blog-card-link:focus-visible) {
    outline: 3px solid var(--violet);
    outline-offset: 2px;
  }
  .kiez-site .blog-card-link:focus-visible { outline: none; }
}

/* 4. Hover/focus zoom on the CARD, not just on the image. library.css keeps the
      agency's element-scoped `.blog-el:hover` — correct for a specimen whose
      card is not a link. Once the card is a link, container hover is the
      agency's own idiom (it is what wcg.htm specifies for .mission-item).

      The keyboard arm is a SEPARATE rule, not another entry in these selector
      lists: one unsupported :has() invalidates an entire list, which would take
      the pointer behaviour down with it. */
.kiez-site .blog-card-light:hover .blog-el,
.kiez-site .blog-card-dark:hover .blog-el { transform: scale(1.06); }

.kiez-site .blog-card-light:hover .card-link-arrow .arr,
.kiez-site .blog-card-dark:hover .card-link-arrow .arr { transform: translateX(4px); }
.kiez-site .card-link-arrow .arr { display: inline-block; transition: transform .2s; }

/* Keyboard equivalents of the two rules above. */
.kiez-site .blog-card-light:has(.blog-card-link:focus-visible) .blog-el,
.kiez-site .blog-card-dark:has(.blog-card-link:focus-visible) .blog-el { transform: scale(1.06); }
.kiez-site .blog-card-light:has(.blog-card-link:focus-visible) .card-link-arrow .arr,
.kiez-site .blog-card-dark:has(.blog-card-link:focus-visible) .card-link-arrow .arr { transform: translateX(4px); }

/* 5. The horizontal teaser's CTA is drawn as a <button> by the agency. A button
      cannot navigate, so inc/cards.php emits an <a>; these are the box
      properties the button UA stylesheet was supplying. */
.kiez-site a.blog-el-2 { line-height: 1.2; }

/* 6. The agency's .blog-grid is used for real by kiez-blog-feed, where the
      viewport can be narrower than its 280px minimum. Same min() guard as
      .archive-grid; library.css stays a verbatim port. */
.kiez-site .blog-grid { grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); }
/* The same guard for every other library grid (#9105): their fixed minimum
   (150–320px) ran 48–64px off a 320px phone and out of narrow builder columns.
   Breakpoints are unchanged wherever the box is wider than the minimum. */
.kiez-site :is(.columns-grid, .card-grid, .blog-grid-2, .cta-grid) { grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }
.kiez-site :is(.highlight-grid, .image-grid, .tabs-grid) { grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); }
.kiez-site :is(.form-grid, .chart-grid) { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.kiez-site .audio-grid { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
.kiez-site .columns-grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); }
.kiez-site :is(.colors-grid, .kiez-void) { grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)); }
.kiez-site .consortium-grid { grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); }

/* 7. ≥1800px parity. site.css scales the root to 144% at this breakpoint and
      gives .news-card five explicit overrides; library.css has no media queries
      at all, so blog cards would render ~30% under-scaled beside everything
      else. INTERPOLATED — these values are derived from the news-card ratios,
      not supplied by the agency. The -3 selectors cover the horizontal teaser,
      which has its own class for every node. */
@media (min-width: 1800px) {
  /* Image heights: none here, both strips follow the image format (see 1.). */
  .kiez-site .blog-block-2 { padding: 34px; }
  .kiez-site .blog-eyebrow,
  .kiez-site .blog-eyebrow-2 { font-size: 15px; }
  .kiez-site .blog-label,
  .kiez-site .blog-label-2 { font-size: 24px; }
  .kiez-site .blog-label-3 { font-size: 34px; }
  .kiez-site .blog-body-text,
  .kiez-site .blog-body-text-2 { font-size: 20px; }
  .kiez-site .blog-body-text-3 { font-size: 21px; }
  .kiez-site a.blog-el-2 { font-size: 17px; padding: 14px 32px; }
  .kiez-site .blog-card-light .card-link-arrow,
  .kiez-site .blog-card-dark .card-link-arrow { font-size: 17px; }
}

/* --------------------------------------------------------------------------
   Page gutter for builder content — #8917, revised 2026-10-06.

   Confera's options CSS gave `.gdlr-core-container` its width and padding and
   is dequeued on design pages, so builder content needs its own gutter.

   First version (2026-10-05) skipped every container that held a full-width
   band (hero, about, news, events, newsletter, contact, page header) so the
   band would not be boxed in. Browser-checked on "Elemente testen": in a
   MIXED container that left the ordinary elements next to the band (accordion,
   alerts, code …) without any side margin, flush at x=0 / x=1920.

   Now: every boxed container is boxed, always — and the bands break out of it
   to full viewport width themselves. Containers covered:
     - the implicit section GoodLayers puts around loose elements;
     - hand-built wrappers: "Boxed", "Custom Width", and "Full" with
       "Allow Item Padding" (GoodLayers' `.gdlr-core-pbf-wrapper-full`).
   "Full" WITHOUT item padding (`-full-no-space`) stays edge to edge — that is
   what the option means in GoodLayers. Block-template sections
   (`.kiez-gutter`) keep their own rules above.
   Editor-set padding is written inline by GoodLayers and still wins (#8948).
   -------------------------------------------------------------------------- */

/* Containers reproduce the design's .wrap. */
.kiez-site .gdlr-core-pbf-section-container.gdlr-core-container,
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) .gdlr-core-pbf-wrapper-container.gdlr-core-container {
  max-width: var(--max);
  margin-left: auto;
  margin-right: auto;
}
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) .gdlr-core-pbf-wrapper-container.gdlr-core-container-custom {
  margin-left: auto;
  margin-right: auto;   /* max-width comes inline from the wrapper option */
}

/* Loose elements: the full .wrap padding. */
.kiez-site .gdlr-core-pbf-section-container.gdlr-core-container { padding: 0 24px; }

/* Hand-built wrappers: 14px + a 10px half-gap on each column = 24px at the
   outer edge and 20px between columns, as in .kiez-gutter. */
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full).gdlr-core-pbf-wrapper-container { padding: 0 14px; }
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full).gdlr-core-pbf-wrapper-container .gdlr-core-pbf-column-content-margin {
  padding-left: 10px;
  padding-right: 10px;
}
/* An element dropped straight into a wrapper, without a column, gets the same
   half-gap a column would give it, so its edges line up with the rest. */
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full).gdlr-core-pbf-wrapper-container > .gdlr-core-pbf-element {
  padding-left: 10px;
  padding-right: 10px;
}

@media (min-width: 1800px) {
  .kiez-site .gdlr-core-pbf-section-container.gdlr-core-container { padding: 0 48px; }
  .kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full).gdlr-core-pbf-wrapper-container { padding: 0 38px; }
}
@media (max-width: 600px) {
  .kiez-site .gdlr-core-pbf-section-container.gdlr-core-container { padding: 0 20px; }
  .kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full).gdlr-core-pbf-wrapper-container { padding: 0 10px; }
}

/* Full-width bands break out of a boxed container to the viewport edges.
   Only in full-width columns or placed straight in the wrapper (a band in a
   half column stays in its column). The wrapper case was missed by the
   2026-10-06 rewrite and boxed the page header of "Was ist Inferenz?".
   100vw includes the scrollbar; the few px of overhang are clipped by
   `.kiez-site { overflow-x: hidden }`. */
.kiez-site .gdlr-core-pbf-section-container.gdlr-core-container > .gdlr-core-pbf-element section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header),
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full) .gdlr-core-column-60 .gdlr-core-pbf-element section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header),
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full).gdlr-core-pbf-wrapper-container > .gdlr-core-pbf-element section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header) {
  width: 100vw;
  max-width: none;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

/* A column holding a band in an edge-to-edge wrapper must not inset it: the
   page-builder blocks give columns 0 10px inline padding, which left 10px
   white strips beside the purple page header (#8820 "Rand links/rechts").
   !important because GoodLayers writes column padding inline. Below 1000px
   it repeats that padding as `#gdlr-core-column-N .gdlr-core-pbf-column-
   content-margin { … !important }`, and the ID outranked this rule, so the
   strips came back on tablets and phones; :not(#kiez-band-column) matches
   every column and only adds an ID's weight of specificity. */
.kiez-site .gdlr-core-pbf-wrapper-full-no-space .gdlr-core-pbf-column-content-margin:not(#kiez-band-column):has(> .gdlr-core-pbf-column-content > .gdlr-core-pbf-element section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header)) {
  padding-left: 0 !important;
  padding-right: 0 !important;
}

/* Vertical rhythm. `.kiez-site * { padding: 0 }` (site.css) also wiped
   GoodLayers' default wrapper padding.
   1) Containers without a band: var(--kiez-space-wrap) above and below (board
      2026-10-14: 64 / 56 / 48px, defined below). A band must sit flush
      (a page header directly under the nav), so mixed containers get their
      spacing from the element rules below instead. */
.kiez-site .gdlr-core-pbf-section:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))),
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):has(> .gdlr-core-pbf-wrapper-content > :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full)):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) {
  padding-top: var(--kiez-space-wrap, 48px);
  padding-bottom: var(--kiez-space-wrap, 48px);
}
.kiez-site .gdlr-core-pbf-section:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) + .gdlr-core-pbf-section:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))),
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) + .gdlr-core-pbf-wrapper:not(.kiez-gutter):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) {
  padding-top: 0;   /* collapse the doubled gap between two padded neighbours */
}

/* 2) Elements stacked in one container: 24px; an eyebrow (.stl) stays tight
      to the title after it. Two bands meet without a gap (designed sections). */
.kiez-site .gdlr-core-pbf-section-container > .gdlr-core-pbf-element:not(:has(> .stl, > .kiez-spacing > .stl)):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) + .gdlr-core-pbf-element:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))),
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-pbf-column-content, .gdlr-core-pbf-wrapper-container) > .gdlr-core-pbf-element:not(:has(> .stl, > .kiez-spacing > .stl)):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) + .gdlr-core-pbf-element:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) {
  margin-top: 24px;
}

/* 3) Where a band meets an ordinary element — and at the open ends of a
      mixed container — leave the section-sized gap the design uses. */
.kiez-site :is(.gdlr-core-pbf-section-container, .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-pbf-column-content, .gdlr-core-pbf-wrapper-container)) > .gdlr-core-pbf-element:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header)) + .gdlr-core-pbf-element:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))),
.kiez-site :is(.gdlr-core-pbf-section-container, .gdlr-core-pbf-wrapper:not(.kiez-gutter) :is(.gdlr-core-pbf-column-content, .gdlr-core-pbf-wrapper-container)) > .gdlr-core-pbf-element:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) + .gdlr-core-pbf-element:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header)) {
  margin-top: 48px;
}
.kiez-site .gdlr-core-pbf-section-container:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header)) > .gdlr-core-pbf-element:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))):first-child,
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header)) :is(.gdlr-core-pbf-column-content, .gdlr-core-pbf-wrapper-container) > .gdlr-core-pbf-element:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))):first-child {
  margin-top: 48px;
}
.kiez-site .gdlr-core-pbf-section-container:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header)) > .gdlr-core-pbf-element:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))):last-child,
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header)) :is(.gdlr-core-pbf-column-content, .gdlr-core-pbf-wrapper-container) > .gdlr-core-pbf-element:not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))):last-child {
  margin-bottom: 48px;
}

/* In-page anchors (#contact, #news …) landed underneath the fixed nav (#8805).
   Past the hero the nav is compact (50px); 72px leaves a little air. The
   scroll container is <html>, outside the .kiez-site body class, hence
   :has(). The nav is fixed on phones too (site.css), so they need the
   offset as well — it was 0 there and anchors landed under the bar (#9116). */
html:has(> body.kiez-site) { scroll-padding-top: 72px; }
@media (max-width: 600px) {
  html:has(> body.kiez-site) { scroll-padding-top: 58px; }
}

/* Alert-box icon (#8918) — replaces the 8px dot when an icon is chosen, in
   the dot's own colour per variant (library.css .alert-dot*). */
.kiez-site .alert-icon { flex-shrink: 0; font-size: 18px; line-height: 1; margin-top: 3px; width: 20px; text-align: center; }
.kiez-site .alert-icon--info    { color: #27B5FC; }
.kiez-site .alert-icon--success { color: #21D6CD; }
.kiez-site .alert-icon--warning { color: #F0C808; }
.kiez-site .alert-icon--error,
.kiez-site .alert-icon--dark    { color: #EC6329; }

/* Code-block copy button (#8947): was a <span>, now a real button. */
.kiez-site button.code-eyebrow { padding: 4px 0; border-radius: 4px; }
.kiez-site button.code-eyebrow:hover { filter: brightness(1.15); }
.kiez-site button.code-eyebrow:focus-visible { outline: 2px solid #EC6329; outline-offset: 3px; }

/* Image element (#8931): "whole image" display. The design's frame is a
   fixed 260px band with object-fit: cover; this variant lets the picture keep
   its own proportions. The fixed height itself is now an option too. */
.kiez-site .image-media-frame--natural { height: auto; }
.kiez-site .image-media-frame--natural .image-el { height: auto; }
.kiez-site .kiez-image > a { display: block; }
.kiez-site .kiez-image > a:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; border-radius: 8px; }

/* Icon cards (#8930): icon-font glyphs sized and coloured like the masked
   SVGs (64px box, violet on light, orange on dark, per-card colour wins). */
.kiez-site .kiez-icon-font {
  display: flex; align-items: center; justify-content: center;
  width: 64px; height: 64px; font-size: 52px; line-height: 1;
  color: var(--kiez-fi-color, var(--violet));
}
.kiez-site .icon-card-dark .kiez-icon-font { color: var(--kiez-fi-color, var(--orange)); }
/* KI:EZ design icons from the icon set (#8930) are drawn at 1em: the
   design's 64px. Cards with a label only sit centred, not at the top. */
.kiez-site .kiez-icon-font.kiez-ico { font-size: 64px; }
.kiez-site .icon-card-light { justify-content: center; }

/* News scroller (#8804/#8924). The reference hid the track's scrollbar and
   offered nothing else, so cards past the viewport were unreachable with a
   mouse. Now: prev/next arrows next to "Alle News" (ui.js), a slim visible
   scrollbar, and a focus ring because the track is keyboard-scrollable. */
.kiez-site .news-actions { display: flex; align-items: center; gap: 16px; }
.kiez-site .news-nav { display: flex; gap: 8px; }
.kiez-site .news-nav[hidden] { display: none; }
.kiez-site .news-nav-btn {
  width: 44px; height: 44px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--violet-25); color: var(--violet);
  font-size: 18px; line-height: 1;
  transition: border-color .2s, background .2s, opacity .2s;
}
.kiez-site .news-nav-btn:hover:not(:disabled) { border-color: var(--violet); background: var(--violet-06); }
.kiez-site .news-nav-btn:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; }
.kiez-site .news-nav-btn:disabled { opacity: .35; cursor: default; }

.kiez-site .news-track {
  scrollbar-width: thin;
  scrollbar-color: var(--violet-25) transparent;
  padding-bottom: 14px;
}
.kiez-site .news-track::-webkit-scrollbar { display: block; height: 6px; }
.kiez-site .news-track::-webkit-scrollbar-track { background: transparent; }
.kiez-site .news-track::-webkit-scrollbar-thumb { background: var(--violet-25); border-radius: 3px; }
.kiez-site .news-track:focus-visible { outline: 2px solid var(--violet); outline-offset: 4px; border-radius: var(--r); }

@media (min-width: 1800px) {
  .kiez-site .news-nav-btn { width: 52px; height: 52px; font-size: 20px; }
}

/* Blog grid (#8920): fixed column counts as an alternative to the default
   auto-fill. They step down on smaller screens so cards never get squeezed
   below a readable width. Pagination reuses .archive-pagination. */
.kiez-site .blog-grid.blog-grid--cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.kiez-site .blog-grid.blog-grid--cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.kiez-site .blog-grid.blog-grid--cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) {
  .kiez-site .blog-grid.blog-grid--cols-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 960px) {
  .kiez-site .blog-grid.blog-grid--cols-3,
  .kiez-site .blog-grid.blog-grid--cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  .kiez-site .blog-grid[class*="blog-grid--cols-"] { grid-template-columns: 1fr; }
}
.kiez-site .kiez-blog-feed + .archive-pagination { margin: -16px 0 40px; }
.kiez-site .kiez-blog-feed { scroll-margin-top: 90px; }

/* --------------------------------------------------------------------------
   Purple variant on dark surfaces — requested 2026-10 (#8801).

   On dark purple, eyebrows and labels drop the orange for the client's
   "Off-White" #F4E8FF (its own token: --off-white already means the light
   page background #FAFAFD), and numbers and active elements go white.
   Places named in the ticket: the header (hero + the nav while it floats
   over the hero), "Unsere Mission", the Handlungsfeld card on purple
   ("Kompetenz", i.e. any featured card) and "Konsortium".

   Deliberately unchanged: the orange primary button (a call to action, not
   an eyebrow/label/number), the orange parts of the wordmark (logo), and
   every orange on light surfaces. #F4E8FF on #3C1F66 is ~11:1, white ~13:1.
   -------------------------------------------------------------------------- */
.kiez-site { --label-on-dark: #F4E8FF; }

/* Header */
.kiez-site .hero-eyebrow { color: var(--label-on-dark); }
@media (min-width: 961px) {
  /* Only top-level items, and only while the nav is transparent over the
     hero; dropdown panels are white and keep their own colours. */
  .kiez-site .nav:not(.nav--solid) .nav-links > a.active,
  .kiez-site .nav:not(.nav--solid) .nav-links > a:hover,
  .kiez-site .nav:not(.nav--solid) .nav-item > .nav-top.active,
  .kiez-site .nav:not(.nav--solid) .nav-item > .nav-top:hover,
  .kiez-site .nav:not(.nav--solid) .nav-item:focus-within > .nav-top { color: var(--white); }
}

/* Unsere Mission */
.kiez-site .mission .stl { color: var(--label-on-dark); }
.kiez-site .mission-num {
  background: none;
  -webkit-text-fill-color: var(--white);
  color: var(--white);
}

/* Handlungsfeld card on purple */
.kiez-site .bento-card.featured .field-tag { color: var(--label-on-dark); }
.kiez-site .bento-card.featured .btn-ghost { color: var(--white); }
.kiez-site .bento-card.featured:hover .field-icon--kompetenz,
.kiez-site .bento-card.featured:hover .field-icon { --fi-color: var(--white); }

/* Konsortium */
.kiez-site .consortium .stl { color: var(--label-on-dark); }

/* --------------------------------------------------------------------------
   Personnel (#8938): Confera's personnel styles in the KI:EZ tokens.
   card    Confera "Card Style", the default: white card, 1.5px violet
           hairline, photo on top, hover lift + zoom inside the frame
   plain   "Column Style": no card
   feature "Card Style 2": white name box over the bottom of the photo
   rows    round photo left — the contact page
   compact 64px photos as a list — sidebars, narrow columns
   Purple is a solid purple card that works on any background, like the
   library's .blog-card-dark; the old "on dark purple" was white text only
   and vanished on white sections (#8938, client test page).
   Columns and the stacking of rows follow the element's own width
   (container queries), not the viewport: the element can sit in a narrow
   builder column, where the old ≤600px rule clipped the text at 800px.
   -------------------------------------------------------------------------- */
.kiez-site .kiez-people {
  --kp-cols: 3; --kp-gap: 24px; --kp-min: 220px;
  container: kiez-people / inline-size;
  width: 100%; display: grid; gap: var(--kp-gap);
}
.kiez-site .kiez-people--cols-2 { --kp-cols: 2; }
.kiez-site .kiez-people--cols-4 { --kp-cols: 4; }
.kiez-site .kiez-people--cols-5 { --kp-cols: 5; }
/* At most N columns, none narrower than --kp-min (then fewer columns). The
   .1px stops rounding from dropping a column that fits exactly. */
.kiez-site .kiez-people--card,
.kiez-site .kiez-people--plain,
.kiez-site .kiez-people--feature {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, max(var(--kp-min), (100% - (var(--kp-cols) - 1) * var(--kp-gap)) / var(--kp-cols) - .1px)), 1fr));
}
/* One column: one card, not a full-width poster. */
.kiez-site .kiez-people.kiez-people--cols-1 { grid-template-columns: minmax(0, 440px); }
.kiez-site .kiez-people--cols-1.kiez-people--center { justify-content: center; }

/* The scroll reveal (.rv: transform + transition) sits on the item, so it
   cannot cancel the card's hover lift; the card fills the item. */
.kiez-site .kiez-people-item { display: flex; min-width: 0; }
.kiez-site .kiez-person {
  container: kiez-card / inline-size;  /* narrow cards adapt (name box below) */
  flex: 1; min-width: 0; position: relative;
  display: flex; flex-direction: column;
  overflow-wrap: break-word;
}

/* Photo */
.kiez-site .kiez-person-photo {
  position: relative; overflow: hidden; background: var(--violet-06);
  display: flex; align-items: center; justify-content: center;
}
.kiez-site .kiez-person-img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 15%;  /* portraits: keep the head in frame */
  transition: transform .6s cubic-bezier(.22, 1, .36, 1), filter .4s;
}
.kiez-site .kiez-people--ratio-4-5 .kiez-person-photo { aspect-ratio: 4 / 5; }
.kiez-site .kiez-people--ratio-1-1 .kiez-person-photo { aspect-ratio: 1 / 1; }
.kiez-site .kiez-people--ratio-3-4 .kiez-person-photo { aspect-ratio: 3 / 4; }
.kiez-site .kiez-people--ratio-original .kiez-person-img { height: auto; }
.kiez-site .kiez-people--ratio-original .kiez-person-photo--none { aspect-ratio: 4 / 5; }
/* Round (client 2026-10-12): a circle above the name instead of a full-width
   photo, for square team photos. 176px, so 500px uploads stay sharp at 2x;
   inside the card's padding, centred or flush with the text. */
.kiez-site .kiez-people--ratio-round .kiez-person-photo,
.kiez-site .kiez-people--plain.kiez-people--ratio-round .kiez-person-photo {
  aspect-ratio: 1 / 1; width: min(176px, 70%); border-radius: 50%; margin: 28px auto 0; flex: 0 0 auto;
}
.kiez-site .kiez-people--card.kiez-people--ratio-round.kiez-people--left .kiez-person-photo { margin-left: 22px; }
.kiez-site .kiez-people--plain.kiez-people--ratio-round .kiez-person-photo { margin-top: 0; }
.kiez-site .kiez-people--plain.kiez-people--ratio-round.kiez-people--left .kiez-person-photo { margin-left: 2px; }
.kiez-site .kiez-people--ratio-round .kiez-person-img { object-position: 50% 30%; }
.kiez-site .kiez-people--ratio-round .kiez-person-initials { font-size: 44px; }
.kiez-site .kiez-person-initials {
  font-family: var(--display); font-weight: 800; font-size: 56px; line-height: 1;
  color: var(--violet); letter-spacing: -.02em;
}

/* Text: name in Funnel Display violet, role #776294 (5.3:1), institution as
   the orange .field-tag eyebrow (3.29:1, accepted as delivered). */
.kiez-site .kiez-person-body {
  container: kiez-person / inline-size;
  flex: 1; display: flex; flex-direction: column; gap: 4px;
  padding: 22px 22px 24px;
}
.kiez-site .kiez-people--center .kiez-person-body { align-items: center; text-align: center; }
/* Centred lines shrink to fit, and break-word does not narrow a long word's
   minimum width, so "HOCHSCHULREKTORENKONFERENZ" stuck out of the card and
   was clipped. Capped at the box width, the word wraps (#8938 review). */
.kiez-site .kiez-person-body > * { max-width: 100%; }
.kiez-site .kiez-person-inst {
  font-family: var(--display); font-size: 11px; font-weight: 600; line-height: 1.4;
  text-transform: uppercase; letter-spacing: .12em; color: var(--orange); margin-bottom: 2px;
}
.kiez-site .kiez-person-name {
  font-family: var(--display); font-size: 22px; font-weight: 700; line-height: 1.2;
  letter-spacing: -.02em; color: var(--violet); margin: 0;
}
.kiez-site .kiez-person-name a { color: inherit; text-decoration: none; transition: color .2s; }
.kiez-site .kiez-person-name a:hover { color: var(--orange); }
.kiez-site .kiez-person-role { font-size: 15px; line-height: 1.45; color: #776294; }
.kiez-site .kiez-person-text { font-size: 14px; line-height: 1.6; color: #776294; margin: 6px 0 0; }  /* not Confera's p margin */
.kiez-site .kiez-person a:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; border-radius: 2px; }

/* Contact, pushed to the bottom so the contact lines of a row of cards
   start at the same height. */
.kiez-site .kiez-person-foot { margin-top: auto; padding-top: 14px; align-self: stretch; }
.kiez-site .kiez-person-contact {
  list-style: none; margin: 0; padding: 14px 0 0; border-top: 1.5px solid var(--violet-10);
  display: flex; flex-direction: column; gap: 6px;
}
.kiez-site .kiez-people--center .kiez-person-contact { align-items: center; }
/* Centred lines shrink to fit: capped, a long address ("jennifer.schwarzenberg@…")
   wraps inside the card instead of running into its edge (#8938 review). */
.kiez-site .kiez-person-contact li { max-width: 100%; }
.kiez-site .kiez-person-contact a {
  display: inline-flex; align-items: baseline; gap: 8px; max-width: 100%;
  font-size: 14px; line-height: 1.5; color: var(--purple); text-decoration: none;
  transition: color .2s;
}
.kiez-site .kiez-person-contact a:hover { color: var(--violet); }
.kiez-site .kiez-person-contact i { flex-shrink: 0; width: 14px; text-align: center; color: var(--violet); }
.kiez-site .kiez-person-contact-text { min-width: 0; }
/* E-mail: the line breaks before the @ (<wbr>); the domain moves to the next
   line as one piece. An inline-block cannot be wider than the line, so only
   a line too narrow for the domain alone lets it break inside — no overflow. */
.kiez-site .kiez-person-mail-domain { display: inline-block; max-width: 100%; }
/* Centred, and in narrow cards: icon in the text flow, so a wrapped domain
   gets the whole line instead of the space beside the icon. An inline-block
   link keeps one clean focus ring around both lines. */
.kiez-site .kiez-people--center .kiez-person-contact a { display: inline-block; }
.kiez-site .kiez-people--center .kiez-person-contact i { margin-right: 6px; }
/* Responsive check 2026-10-12: long role words ("Veranstaltungsmanagement")
   broke off single letters in 186px cards at 320px. Hyphenate there only. */
@container kiez-person (max-width: 200px) {
  .kiez-site .kiez-person-role { hyphens: auto; hyphenate-limit-chars: 12 5 5; }
}
@container kiez-person (max-width: 200px) {
  .kiez-site .kiez-person-contact a { display: inline-block; }
  .kiez-site .kiez-person-contact i { margin-right: 6px; }
}

/* Card (default) and rows: white card with the violet hairline. */
.kiez-site .kiez-people--card .kiez-person,
.kiez-site .kiez-people--rows .kiez-person {
  background: var(--white); border: 1.5px solid var(--violet-10); border-radius: var(--r);
  overflow: hidden; transition: transform .35s, box-shadow .35s, border-color .3s;
}
.kiez-site .kiez-people--card:not(.kiez-people--hover-none) .kiez-person:is(:hover, :focus-within),
.kiez-site .kiez-people--rows:not(.kiez-people--hover-none) .kiez-person:is(:hover, :focus-within) {
  border-color: var(--violet-25); box-shadow: 0 16px 48px rgba(134, 53, 246, .08);
}

/* Plain: no card, rounded photo. */
.kiez-site .kiez-people--plain .kiez-person-photo { border-radius: var(--r); }
.kiez-site .kiez-people--plain .kiez-person-body { padding: 18px 2px 4px; }

/* Feature: white name box over the bottom of the photo. By default (touch
   screens, reduced motion) it shows everything; with a mouse, institution,
   role and contact appear on hover and on keyboard focus. */
.kiez-site .kiez-people--feature .kiez-person-photo { border-radius: var(--r); }
.kiez-site .kiez-people--feature .kiez-person-body {
  --kp-inset: 16px;
  position: relative; z-index: 1; margin: -48px var(--kp-inset) 0;
  padding: 18px 18px 20px; background: var(--white); border-radius: var(--r);
  box-shadow: 0 8px 32px rgba(60, 31, 102, .12);
}
.kiez-site .kiez-people--feature .kiez-person-foot { padding-top: 10px; }
.kiez-site .kiez-people--feature .kiez-person-contact { border-top: 0; padding-top: 0; }
/* Narrow card (a 1/3 column on a tablet): a wider box, so the e-mail domain
   still fits on one line. */
@container kiez-card (max-width: 260px) {
  .kiez-site .kiez-people--feature .kiez-person-body { --kp-inset: 8px; padding-left: 12px; padding-right: 12px; }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  /* The box is anchored to the bottom and grows upwards over the photo, so
     revealing the details does not move the grid. It stops just below the
     card top and scrolls beyond that: long names and roles in a narrow
     column or over a square photo pushed it into the card or the section
     title above (#8938 review). */
  .kiez-site .kiez-people--feature .kiez-person { padding-bottom: 30px; }
  .kiez-site .kiez-people--feature .kiez-person-body {
    position: absolute; left: var(--kp-inset); right: var(--kp-inset); bottom: 0; margin: 0;
    max-height: calc(100% - var(--kp-inset)); overflow: hidden auto; scrollbar-width: thin;
    scroll-padding-block: 8px;  /* a link scrolled into view keeps its whole focus ring */
  }
  /* Visually hidden rather than display:none — the links stay focusable, so
     keyboard focus (:focus-within) reveals them, screen readers read them,
     and a hidden part takes no room (no empty gap in the box). A card with
     nothing to focus (--static: no profile link, e-mail or phone) could not
     reveal them by keyboard, so it shows them all the time. */
  .kiez-site .kiez-people--feature .kiez-person:not(.kiez-person--static):not(:hover):not(:focus-within) :is(.kiez-person-inst, .kiez-person-role, .kiez-person-foot) {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .kiez-site .kiez-people--feature .kiez-person:not(.kiez-person--static):is(:hover, :focus-within) :is(.kiez-person-inst, .kiez-person-role, .kiez-person-foot) {
    animation: kiez-person-reveal .35s cubic-bezier(.22, 1, .36, 1) both;
  }
}
@keyframes kiez-person-reveal { from { opacity: 0; transform: translateY(6px); } }

/* Rows: round photo left, details right — the contact page. */
.kiez-site .kiez-people--rows { grid-template-columns: repeat(auto-fill, minmax(min(420px, 100%), 1fr)); }
.kiez-site .kiez-people--rows .kiez-person,
.kiez-site .kiez-people--compact .kiez-person { flex-direction: row; align-items: flex-start; }
.kiez-site .kiez-people--rows .kiez-person { gap: 22px; padding: 22px; }
.kiez-site .kiez-people--rows .kiez-person-photo,
.kiez-site .kiez-people--compact .kiez-person-photo { flex: 0 0 auto; width: 112px; aspect-ratio: 1 / 1; border-radius: 50%; }
.kiez-site .kiez-people--rows .kiez-person-body,
.kiez-site .kiez-people--compact .kiez-person-body { padding: 0; align-self: stretch; min-width: 0; }
.kiez-site .kiez-people--rows .kiez-person-initials { font-size: 36px; }
.kiez-site .kiez-people--rows .kiez-person-name { font-size: 20px; }
/* Narrow element (a 1/3 column on a tablet, phones): photo above the text. */
@container kiez-people (max-width: 380px) {
  .kiez-site .kiez-people--rows .kiez-person { flex-direction: column; gap: 16px; padding: 20px 18px; }
  .kiez-site .kiez-people--rows .kiez-person-photo { width: 96px; }
}

/* Compact: 64px photos as a list with hairlines. */
.kiez-site .kiez-people--compact { grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); column-gap: 32px; row-gap: 0; }
.kiez-site .kiez-people--compact .kiez-person { gap: 16px; padding: 16px 0; border-bottom: 1px solid var(--violet-10); }
.kiez-site .kiez-people--compact .kiez-person-photo { width: 64px; }
.kiez-site .kiez-people--compact .kiez-person-initials { font-size: 22px; }
.kiez-site .kiez-people--compact .kiez-person-body { gap: 2px; }
.kiez-site .kiez-people--compact .kiez-person-inst { font-size: 10px; margin-bottom: 0; }
.kiez-site .kiez-people--compact .kiez-person-name { font-size: 17px; letter-spacing: -.01em; }
.kiez-site .kiez-people--compact .kiez-person-role { font-size: 14px; }
.kiez-site .kiez-people--compact .kiez-person-foot { padding-top: 6px; }
.kiez-site .kiez-people--compact .kiez-person-contact { border-top: 0; padding-top: 0; gap: 2px; }
.kiez-site .kiez-people--compact .kiez-person-contact a { font-size: 13px; }
/* A 1/3 column on a tablet (~220px): beside a 64px photo the e-mail domain
   would have to break, so the photo goes above the text. */
@container kiez-people (max-width: 240px) {
  .kiez-site .kiez-people--compact .kiez-person { flex-direction: column; gap: 10px; }
}

/* Purple cards: their own purple background, readable on white and on
   purple sections (white 13.3:1, role #B9A9DD 6.2:1, labels #F4E8FF ~11:1). */
.kiez-site .kiez-people--purple.kiez-people--card .kiez-person,
.kiez-site .kiez-people--purple.kiez-people--rows .kiez-person { background: var(--purple); border-color: rgba(255, 255, 255, .14); }
.kiez-site .kiez-people--purple.kiez-people--card:not(.kiez-people--hover-none) .kiez-person:is(:hover, :focus-within),
.kiez-site .kiez-people--purple.kiez-people--rows:not(.kiez-people--hover-none) .kiez-person:is(:hover, :focus-within) {
  border-color: rgba(255, 255, 255, .4); box-shadow: 0 16px 48px rgba(60, 31, 102, .28);
}
.kiez-site .kiez-people--purple.kiez-people--feature .kiez-person-body { background: var(--purple); box-shadow: 0 8px 32px rgba(60, 31, 102, .3); }
.kiez-site .kiez-people--purple.kiez-people--compact { padding: 4px 22px; background: var(--purple); border-radius: var(--r); }
/* Plain has no cards, so purple is one panel, as for Compact (audit 10-07). */
.kiez-site .kiez-people--purple.kiez-people--plain { padding: 22px; background: var(--purple); border-radius: var(--r); }
.kiez-site .kiez-people--purple.kiez-people--compact .kiez-person { border-bottom-color: rgba(255, 255, 255, .14); }
.kiez-site .kiez-people--purple.kiez-people--compact .kiez-people-item:last-child .kiez-person { border-bottom: 0; }
.kiez-site .kiez-people--purple .kiez-person-photo { background: rgba(255, 255, 255, .08); }
/* The name box's photo sits on the section, not on a purple card: the 8%
   white alone left white initials on white (1:1). Same tone as on a card. */
.kiez-site .kiez-people--purple.kiez-people--feature .kiez-person-photo {
  background: linear-gradient(rgba(255, 255, 255, .08), rgba(255, 255, 255, .08)) var(--purple);
}
.kiez-site .kiez-people--purple .kiez-person-initials,
.kiez-site .kiez-people--purple .kiez-person-name,
.kiez-site .kiez-people--purple .kiez-person-contact a { color: var(--white); }
.kiez-site .kiez-people--purple .kiez-person-inst,
.kiez-site .kiez-people--purple .kiez-person-contact i { color: var(--label-on-dark, #F4E8FF); }
.kiez-site .kiez-people--purple .kiez-person-role,
.kiez-site .kiez-people--purple .kiez-person-text { color: #B9A9DD; }
.kiez-site .kiez-people--purple .kiez-person-contact { border-top-color: rgba(255, 255, 255, .14); }
/* No orange on purple (#8801): links lighten to the violet tint (5.9:1). */
.kiez-site .kiez-people--purple .kiez-person-name a:hover,
.kiez-site .kiez-people--purple .kiez-person-contact a:hover { color: #C39AFB; }
.kiez-site .kiez-people--purple .kiez-person a:focus-visible { outline-color: var(--white); }

/* Hover on the photo: zoom inside the frame (as the library's .image-el) or
   black and white until hover. Keyboard focus inside a card counts too. */
.kiez-site .kiez-people--hover-grayscale .kiez-person-img { filter: grayscale(1); }
.kiez-site .kiez-people--hover-grayscale .kiez-person:is(:hover, :focus-within) .kiez-person-img { filter: none; }
@media (hover: none) {
  .kiez-site .kiez-people--hover-grayscale .kiez-person-img { filter: none; }  /* no hover on touch: colour */
}
@media (prefers-reduced-motion: no-preference) {
  .kiez-site .kiez-people--card:not(.kiez-people--hover-none) .kiez-person:is(:hover, :focus-within) { transform: translateY(-4px); }
  .kiez-site .kiez-people--hover-zoom .kiez-person:is(:hover, :focus-within) .kiez-person-img { transform: scale(1.06); }
}

@media (min-width: 1800px) {
  .kiez-site .kiez-people { --kp-gap: 32px; --kp-min: 280px; }
  .kiez-site .kiez-people.kiez-people--cols-1 { grid-template-columns: minmax(0, 560px); }
  .kiez-site .kiez-person-inst { font-size: 13px; }
  .kiez-site .kiez-person-name { font-size: 24px; }
  .kiez-site .kiez-people--rows .kiez-person-name { font-size: 22px; }
  .kiez-site .kiez-person-role { font-size: 17px; }
  .kiez-site .kiez-person-text,
  .kiez-site .kiez-person-contact a { font-size: 16px; }
  .kiez-site .kiez-people--compact .kiez-person-inst { font-size: 12px; }
  .kiez-site .kiez-people--compact .kiez-person-name { font-size: 19px; }
  .kiez-site .kiez-people--compact .kiez-person-role,
  .kiez-site .kiez-people--compact .kiez-person-contact a { font-size: 15px; }
}

/* Text element (#8935). Inherits the article styles of .post-body; these are
   only the element's own variants. */
.kiez-site .kiez-text--reading { max-width: 70ch; }
.kiez-site .kiez-text--center { text-align: center; margin-left: auto; margin-right: auto; }
.kiez-site .kiez-text--center ul,
.kiez-site .kiez-text--center ol { display: inline-block; text-align: left; }
.kiez-site .kiez-text--intro { font-size: clamp(18px, 1.6vw, 21px); line-height: 1.6; }
.kiez-site .kiez-text--small { font-size: 14px; line-height: 1.6; color: #5C447E; }
.kiez-site .kiez-text > :first-child { margin-top: 0; }
/* On dark purple: white text, #8801 off-white for quotes, links underlined. */
.kiez-site .kiez-text--dark { color: var(--white); }
.kiez-site .kiez-text--dark h2,
.kiez-site .kiez-text--dark h3,
.kiez-site .kiez-text--dark h4 { color: var(--white); }
/* :not() matches .post-body's link rule (0,3,1), which won before: violet on purple, 2.44:1 (audit 10-12). */
.kiez-site .kiez-text--dark a:not(.wp-block-button__link) { color: var(--label-on-dark, #F4E8FF); }
.kiez-site .kiez-text--dark blockquote { color: var(--label-on-dark, #F4E8FF); border-left-color: var(--white); }
@media (min-width: 1800px) {
  .kiez-site .kiez-text--body { font-size: 20px; }
  .kiez-site .kiez-text--intro { font-size: 25px; }
  .kiez-site .kiez-text--small { font-size: 17px; }
}

/* --------------------------------------------------------------------------
   Gallery (#8932). Rounded 8px frames and hover zoom as on the single image
   element (library.css .image-media-frame / .image-el). Grid crops to a ratio
   (or keeps each image uncropped), masonry keeps proportions, slider reuses
   the news arrows. 2026-10-06, Confera's options in KIEZ tokens: 1-6
   columns, 1 or 2 per row on phones, gap normal/large/none, hover icon,
   whole-image fit for logos, a slim caption bar on touch, a dark surface,
   and a masonry that fills left to right (ui.js).
   -------------------------------------------------------------------------- */
.kiez-site .kiez-gallery { --kg-cols: 3; --kg-gap: 16px; }
.kiez-site .kiez-gallery--cols-1 { --kg-cols: 1; }
.kiez-site .kiez-gallery--cols-2 { --kg-cols: 2; }
.kiez-site .kiez-gallery--cols-4 { --kg-cols: 4; }
.kiez-site .kiez-gallery--cols-5 { --kg-cols: 5; }
.kiez-site .kiez-gallery--cols-6 { --kg-cols: 6; }
/* 0px, not 0: the slider's calc() subtracts the gaps from 100%. */
.kiez-site .kiez-gallery--gap-large { --kg-gap: 32px; }
.kiez-site .kiez-gallery--gap-none { --kg-gap: 0px; }

.kiez-site .kiez-gallery-item { margin: 0; break-inside: avoid; }
.kiez-site .kiez-gallery-item > a { display: block; }
.kiez-site .kiez-gallery-item > a:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; border-radius: 8px; }
.kiez-site .kiez-gallery-frame { display: block; position: relative; border-radius: 8px; overflow: hidden; background: var(--violet-06); }
.kiez-site .kiez-gallery-img {
  display: block; width: 100%; height: auto;
  transition: transform .6s cubic-bezier(.22, 1, .36, 1);
}
/* No zoom for visitors who asked for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .kiez-site .kiez-gallery:not(.kiez-gallery--hover-none) .kiez-gallery-item a:hover .kiez-gallery-img { transform: scale(1.06); }
}

/* Fixed ratio (grid + slider) */
.kiez-site .kiez-gallery--ratio-4-3  .kiez-gallery-frame { aspect-ratio: 4 / 3; }
.kiez-site .kiez-gallery--ratio-3-2  .kiez-gallery-frame { aspect-ratio: 3 / 2; }
.kiez-site .kiez-gallery--ratio-16-9 .kiez-gallery-frame { aspect-ratio: 16 / 9; }
.kiez-site .kiez-gallery--ratio-1-1  .kiez-gallery-frame { aspect-ratio: 1 / 1; }
.kiez-site .kiez-gallery--ratio-3-4  .kiez-gallery-frame { aspect-ratio: 3 / 4; }
/* Own proportions (masonry, ratio "original"): the item carries the image's
   ratio as --ar, so the frame keeps its height before the image loads. */
.kiez-site .kiez-gallery--masonry .kiez-gallery-frame,
.kiez-site .kiez-gallery--ratio-original .kiez-gallery-frame { aspect-ratio: var(--ar); }
.kiez-site [class*="kiez-gallery--ratio-"] .kiez-gallery-img,
.kiez-site .kiez-gallery--masonry .kiez-gallery-img { height: 100%; object-fit: cover; }
/* Whole image (logos): uncropped on a white tile with the card hairline. */
.kiez-site .kiez-gallery--fit-contain .kiez-gallery-frame { background: var(--white); box-shadow: inset 0 0 0 1.5px rgba(134, 53, 246, .12); }
.kiez-site .kiez-gallery--fit-contain .kiez-gallery-img { object-fit: contain; padding: 8%; }

.kiez-site .kiez-gallery--grid {
  display: grid; gap: var(--kg-gap);
  grid-template-columns: repeat(var(--kg-cols), minmax(0, 1fr));
}
/* Masonry without JS: CSS columns, filled top to bottom. ui.js turns it into
   a grid of 4px rows in which every item spans its own height plus the gap,
   so the images fill left to right like Confera's (Isotope) masonry. */
.kiez-site .kiez-gallery--masonry { columns: var(--kg-cols); column-gap: var(--kg-gap); }
.kiez-site .kiez-gallery--masonry .kiez-gallery-item { margin-bottom: var(--kg-gap); }
.kiez-site .kiez-gallery--masonry.kiez-gallery--masonry-grid {
  display: grid; grid-template-columns: repeat(var(--kg-cols), minmax(0, 1fr));
  grid-auto-rows: 4px; column-gap: var(--kg-gap); row-gap: 0; align-items: start;
}
.kiez-site .kiez-gallery--masonry-grid .kiez-gallery-item { margin-bottom: 0; }
/* ui.js sets the frame heights; without a set width, aspect-ratio would
   derive the width from that height and the frame would leave the column. */
.kiez-site .kiez-gallery--masonry-grid .kiez-gallery-frame { width: 100%; }

.kiez-site .kiez-gallery--slider {
  display: flex; gap: var(--kg-gap); overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: thin; scrollbar-color: var(--violet-25) transparent; padding-bottom: 12px;
}
.kiez-site .kiez-gallery--slider .kiez-gallery-item {
  flex: 0 0 calc((100% - (var(--kg-cols) - 1) * var(--kg-gap)) / var(--kg-cols));
  scroll-snap-align: start;
}
.kiez-site .kiez-gallery--slider:focus-visible { outline: 2px solid var(--violet); outline-offset: 4px; border-radius: 8px; }
.kiez-site .kiez-gallery-nav { justify-content: flex-end; margin-bottom: 14px; }

/* Gap "none" (Confera grid-no-space): the images touch, only the outer
   corners of the whole gallery stay rounded (the slider rounds its two ends).
   No room for an outline outside the tile, and one inside would be painted
   under the image, so the focus ring is a layer on top of the tile (a
   border, which forced-colors mode keeps). Every slider uses that ring too:
   its scroll box cut off the outer ring at the top and the first slide's
   left edge (#8932 review). */
.kiez-site .kiez-gallery--gap-none:not(.kiez-gallery--slider) { border-radius: var(--r); overflow: hidden; }
.kiez-site .kiez-gallery--gap-none .kiez-gallery-frame { border-radius: 0; }
.kiez-site .kiez-gallery--gap-none.kiez-gallery--slider .kiez-gallery-item:first-child .kiez-gallery-frame { border-radius: var(--r) 0 0 var(--r); }
.kiez-site .kiez-gallery--gap-none.kiez-gallery--slider .kiez-gallery-item:last-child .kiez-gallery-frame { border-radius: 0 var(--r) var(--r) 0; }
.kiez-site :is(.kiez-gallery--gap-none, .kiez-gallery--slider) .kiez-gallery-item > a { position: relative; }
.kiez-site :is(.kiez-gallery--gap-none, .kiez-gallery--slider) .kiez-gallery-item > a:focus-visible { outline: none; }
.kiez-site :is(.kiez-gallery--gap-none, .kiez-gallery--slider) .kiez-gallery-item > a:focus-visible::after {
  content: ''; position: absolute; inset: 0; z-index: 4; pointer-events: none;
  border: 2px solid var(--violet); box-shadow: inset 0 0 0 2px var(--white);
}
.kiez-site .kiez-gallery--slider:not(.kiez-gallery--gap-none) .kiez-gallery-item > a:focus-visible::after { border-radius: var(--r); }
.kiez-site .kiez-gallery--gap-none.kiez-gallery--slider .kiez-gallery-item:first-child > a:focus-visible::after { border-radius: var(--r) 0 0 var(--r); }
.kiez-site .kiez-gallery--gap-none.kiez-gallery--slider .kiez-gallery-item:last-child > a:focus-visible::after { border-radius: 0 var(--r) var(--r) 0; }
.kiez-site .kiez-gallery--gap-none figcaption.image-block { margin: 0; padding: 8px 10px 12px; }

/* Hover "zoom + icon" (Confera icon-hover) in KIEZ colours: purple veil and a
   white 52px disc with a violet magnifier, or an arrow on links. Keyboard
   focus shows it too. */
.kiez-site .kiez-gallery--hover-icon .kiez-gallery-link .kiez-gallery-frame::after {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: rgba(60, 31, 102, .45); opacity: 0; transition: opacity .3s;
}
.kiez-site .kiez-gallery--hover-icon .kiez-gallery-link .kiez-gallery-frame::before {
  content: ''; position: absolute; z-index: 3; left: 50%; top: 50%;
  width: 52px; height: 52px; margin: -26px 0 0 -26px; border-radius: 50%;
  background: var(--white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238635F6' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.3 15.3 20 20M10.5 7.8v5.4M7.8 10.5h5.4'/%3E%3C/svg%3E") center / 24px no-repeat;
  opacity: 0; transition: opacity .3s, transform .3s;
}
.kiez-site .kiez-gallery--hover-icon .kiez-gallery-link--url .kiez-gallery-frame::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238635F6' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
}
.kiez-site .kiez-gallery--hover-icon .kiez-gallery-link:is(:hover, :focus-visible) .kiez-gallery-frame::after,
.kiez-site .kiez-gallery--hover-icon .kiez-gallery-link:is(:hover, :focus-visible) .kiez-gallery-frame::before { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .kiez-site .kiez-gallery--hover-icon .kiez-gallery-link .kiez-gallery-frame::before { transform: scale(.8); }
  .kiez-site .kiez-gallery--hover-icon .kiez-gallery-link:is(:hover, :focus-visible) .kiez-gallery-frame::before { transform: none; }
}
/* With on-image captions the disc sits in the top right corner and shrinks
   with the tile (height queries, see Captions): centred, it covered the first
   caption line on tiles under ~190px (#8932 review). Tiles up to 60px have no
   room for both, there the veil alone marks the link. */
.kiez-site .kiez-gallery--hover-icon.kiez-gallery--overlay .kiez-gallery-link .kiez-gallery-frame::before {
  left: auto; top: 10px; right: 10px; margin: 0; width: 40px; height: 40px; background-size: 20px;
}
@container (max-height: 150px) {
  .kiez-site .kiez-gallery--hover-icon.kiez-gallery--overlay .kiez-gallery-link .kiez-gallery-frame::before { top: 8px; right: 8px; width: 32px; height: 32px; background-size: 16px; }
}
@container (max-height: 100px) {
  .kiez-site .kiez-gallery--hover-icon.kiez-gallery--overlay .kiez-gallery-link .kiez-gallery-frame::before { top: 6px; right: 6px; width: 28px; height: 28px; background-size: 14px; }
}
@container (max-height: 60px) {
  .kiez-site .kiez-gallery--hover-icon.kiez-gallery--overlay .kiez-gallery-link .kiez-gallery-frame::before { display: none; }
}

/* Captions. "Title and caption" puts the title on its own line. File-name
   titles have no spaces, so long words may break. On the image at most three
   lines, so a long caption cannot grow past the top of a small tile; the
   lightbox shows it in full. */
.kiez-site .kiez-gallery-item figcaption.image-block { margin-top: 8px; overflow-wrap: break-word; }
.kiez-site .kiez-gallery-overlay-text {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
  overflow: hidden; overflow-wrap: break-word;
}
.kiez-site .kiez-gallery-cap-title { display: block; font-weight: 700; }
.kiez-site figcaption .kiez-gallery-cap-title { color: var(--purple); }
.kiez-site .kiez-gallery-overlay {
  position: absolute; inset: auto 0 0 0; z-index: 2; max-height: 100%; overflow: hidden; padding: 18px 16px 14px;
  /* Starts at .55, not 0 (audit 10-07): over bright photo areas the first of
     three caption lines fell to 3.3:1. */
  background: linear-gradient(180deg, rgba(60, 31, 102, .55), rgba(60, 31, 102, .92));
  font-family: var(--display); font-size: 14px; font-weight: 600; color: #fff;
  opacity: 0; transform: translateY(6px); transition: opacity .3s, transform .3s;
}
.kiez-site .kiez-gallery-item:hover .kiez-gallery-overlay,
.kiez-site .kiez-gallery-item:focus-within .kiez-gallery-overlay { opacity: 1; transform: none; }
/* Logos sit on white, where the fading veil left white text on almost white
   (2.1:1): a solid bar instead (#8932 review). */
.kiez-site .kiez-gallery--fit-contain .kiez-gallery-overlay { background: rgba(60, 31, 102, .9); }
/* Height queries (the steps below, the hover icon above) need frames whose
   height comes from a ratio, never from the image. */
.kiez-site .kiez-gallery--overlay[class*="kiez-gallery--ratio-"]:not(.kiez-gallery--ratio-original) .kiez-gallery-frame,
.kiez-site .kiez-gallery--overlay .kiez-gallery-item[style*="--ar"] .kiez-gallery-frame { container-type: size; }
/* Mouse: three lines on tiles over 150px, two up to 150px and one in a slim
   bar up to 100px, so the tile never cuts a caption off mid-line (#8932
   review). The selectors carry .kiez-gallery to beat the logo bar above. */
@media (hover: hover) {
  .kiez-site .kiez-gallery--fit-contain .kiez-gallery-overlay { padding: 10px 12px; }
  @container (max-height: 150px) {
    .kiez-site .kiez-gallery .kiez-gallery-overlay-text { -webkit-line-clamp: 2; }
  }
  @container (max-height: 100px) {
    .kiez-site .kiez-gallery .kiez-gallery-overlay { padding: 5px 10px; background: rgba(60, 31, 102, .85); font-size: 12px; line-height: 1.35; }
    .kiez-site .kiez-gallery .kiez-gallery-overlay-text { -webkit-line-clamp: 1; }
    .kiez-site .kiez-gallery-overlay .kiez-gallery-cap-title { display: inline; }
  }
  @container (max-height: 60px) {
    .kiez-site .kiez-gallery .kiez-gallery-overlay { padding: 3px 8px; font-size: 11px; }
  }
}
/* Touch has no hover, so the caption is always on: a slim bar of at most two
   lines (one on short tiles) that never covers more than 35% of the image;
   the full text is in the lightbox. */
@media (hover: none) {
  .kiez-site .kiez-gallery-overlay {
    opacity: 1; transform: none; max-height: 35%; overflow: hidden; padding: 6px 10px;
    background: rgba(60, 31, 102, .85); font-size: 12px; line-height: 1.35;
  }
  .kiez-site .kiez-gallery-overlay-text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
  .kiez-site .kiez-gallery-overlay .kiez-gallery-cap-title { display: inline; }
  @container (max-height: 127px) {
    .kiez-site .kiez-gallery-overlay-text { -webkit-line-clamp: 1; }
  }
  @container (max-height: 80px) {
    .kiez-site .kiez-gallery-overlay { padding: 3px 8px; font-size: 11px; }
  }
}
/* The same bar everywhere when an image has no link (On click: Nothing):
   nothing to focus, so a hover-only caption would be mouse-only (#8932
   review). Kept after the mouse steps, which it replaces. */
.kiez-site .kiez-gallery--static .kiez-gallery-overlay {
  opacity: 1; transform: none; max-height: 35%; padding: 6px 10px;
  background: rgba(60, 31, 102, .85); font-size: 12px; line-height: 1.35;
}
.kiez-site .kiez-gallery--static .kiez-gallery-overlay-text { -webkit-line-clamp: 2; }
.kiez-site .kiez-gallery--static .kiez-gallery-overlay .kiez-gallery-cap-title { display: inline; }
@container (max-height: 127px) {
  .kiez-site .kiez-gallery--static .kiez-gallery-overlay-text { -webkit-line-clamp: 1; }
}
@container (max-height: 80px) {
  .kiez-site .kiez-gallery--static .kiez-gallery-overlay { padding: 3px 8px; font-size: 11px; }
}
/* Tiles under 60px (narrow columns on the desktop): 35% is less than one line. */
@container (max-height: 60px) {
  .kiez-site .kiez-gallery--static .kiez-gallery-overlay { max-height: 100%; }
}

/* Surface "On dark purple" (#8932 review: the title below the image was
   purple on purple, the caption 2.2:1, violet focus rings 2.4:1). */
.kiez-site .kiez-gallery--dark figcaption.image-block { color: var(--label-on-dark, #F4E8FF); }
.kiez-site .kiez-gallery--dark figcaption .kiez-gallery-cap-title { color: var(--white); }
.kiez-site .kiez-gallery--dark .kiez-gallery-item > a:focus-visible,
.kiez-site .kiez-gallery--dark.kiez-gallery--slider:focus-visible { outline-color: var(--white); }
.kiez-site .kiez-gallery--dark.kiez-gallery--slider { scrollbar-color: rgba(255, 255, 255, .4) transparent; }
.kiez-site .kiez-gallery-nav--dark .news-nav-btn { border-color: rgba(255, 255, 255, .4); color: var(--white); }
.kiez-site .kiez-gallery-nav--dark .news-nav-btn:hover:not(:disabled) { border-color: var(--white); background: rgba(255, 255, 255, .1); }
.kiez-site .kiez-gallery-nav--dark .news-nav-btn:focus-visible { outline-color: var(--white); }

@media (max-width: 960px) {
  .kiez-site .kiez-gallery--cols-4, .kiez-site .kiez-gallery--cols-5, .kiez-site .kiez-gallery--cols-6 { --kg-cols: 3; }
}
/* Phones: 1 or 2 per row as chosen by the editor (was forced to 2, i.e.
   146px tiles at 390px). */
@media (max-width: 600px) {
  .kiez-site .kiez-gallery { --kg-gap: 10px; }
  .kiez-site .kiez-gallery--gap-large { --kg-gap: 16px; }
  .kiez-site .kiez-gallery--gap-none { --kg-gap: 0px; }
  .kiez-site .kiez-gallery--m-cols-1 { --kg-cols: 1; }
  .kiez-site .kiez-gallery--m-cols-2 { --kg-cols: 2; }
}
/* site.css shortens every transition, but its * does not reach the icon's
   pseudo-elements (same selectors as above, so this later rule wins). */
@media (prefers-reduced-motion: reduce) {
  .kiez-site .kiez-gallery-img, .kiez-site .kiez-gallery-overlay,
  .kiez-site .kiez-gallery--hover-icon .kiez-gallery-link .kiez-gallery-frame::before,
  .kiez-site .kiez-gallery--hover-icon .kiez-gallery-link .kiez-gallery-frame::after { transition: none; }
}

/* Table (#8949). Design tokens: Funnel Display header in purple on a light
   violet tint, violet hairlines like .mission-divider, 8px outer radius. */
.kiez-site .kiez-table-wrap {
  overflow-x: auto; border: 1.5px solid rgba(134, 53, 246, .12); border-radius: 8px;
  scrollbar-width: thin; scrollbar-color: var(--violet-25) transparent;
}
.kiez-site .kiez-table-wrap:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; }
.kiez-site .kiez-table { width: 100%; border-collapse: collapse; font-size: 15px; line-height: 1.5; color: var(--purple); }
.kiez-site .kiez-table caption {
  caption-side: top; text-align: left; padding: 16px 20px 4px;
  font-family: var(--display); font-weight: 700; font-size: 17px; color: var(--violet);
}
.kiez-site .kiez-table th,
.kiez-site .kiez-table td { padding: 14px 20px; text-align: left; vertical-align: top; }
.kiez-site .kiez-table thead th {
  font-family: var(--display); font-size: 13px; font-weight: 700; letter-spacing: .02em;
  color: var(--purple); background: var(--violet-06); white-space: nowrap;
}
.kiez-site .kiez-table tbody th { font-family: var(--display); font-weight: 600; color: var(--violet); }
.kiez-site .kiez-table--lines tbody tr + tr > * { border-top: 1px solid rgba(134, 53, 246, .12); }
.kiez-site .kiez-table--lines thead + tbody tr:first-child > * { border-top: 1px solid rgba(134, 53, 246, .18); }
.kiez-site .kiez-table--striped tbody tr:nth-child(even) > * { background: rgba(134, 53, 246, .035); }
.kiez-site .kiez-table--compact th,
.kiez-site .kiez-table--compact td { padding: 8px 14px; font-size: 14px; }
.kiez-site .kiez-table a { color: var(--violet); text-decoration: underline; text-underline-offset: .2em; }
@media (min-width: 1800px) {
  .kiez-site .kiez-table { font-size: 18px; }
  .kiez-site .kiez-table thead th { font-size: 15px; }
}

/* --------------------------------------------------------------------------
   Roadmap (#8941) and Timeline (#8942). Violet line and dots; done = filled
   violet, current = orange ring (the design's accent), planned = hollow.
   Roadmap runs horizontally when it has room, vertically in a narrow box.
   -------------------------------------------------------------------------- */
.kiez-site .kiez-roadmap { --kr-line: rgba(134, 53, 246, .18); --kr-fill: var(--violet); container: kiez-roadmap / inline-size; }
.kiez-site .kiez-roadmap-list {
  list-style: none; margin: 0; padding: 0; position: relative;
  display: grid; grid-template-columns: repeat(var(--kr-count), minmax(0, 1fr)); gap: 0;
}  /* no gap: column centres must sit at exact 100%/(2n) steps for the line */
/* The line (behind the dots) and its filled part up to the current milestone. */
.kiez-site .kiez-roadmap-list::before,
.kiez-site .kiez-roadmap-list::after {
  content: ''; position: absolute; top: 9px; height: 3px; border-radius: 2px;
  left: calc(50% / var(--kr-count)); right: calc(50% / var(--kr-count));
}
.kiez-site .kiez-roadmap-list::before { background: var(--kr-line); }
.kiez-site .kiez-roadmap-list::after {
  background: var(--kr-fill);
  right: auto; width: calc((100% - 100% / var(--kr-count)) * var(--kr-progress));
}
.kiez-site .kiez-roadmap-item { position: relative; text-align: center; padding: 38px 12px 0; }
.kiez-site .kiez-roadmap-dot {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%); z-index: 1;
  width: 21px; height: 21px; border-radius: 50%;
  background: var(--white); border: 3px solid var(--kr-line);
}
.kiez-site .kiez-roadmap-item.is-done .kiez-roadmap-dot { background: var(--violet); border-color: var(--violet); }
.kiez-site .kiez-roadmap-item.is-current .kiez-roadmap-dot { border-color: var(--orange); box-shadow: 0 0 0 5px rgba(236, 99, 41, .18); }
.kiez-site .kiez-roadmap-label {
  font-family: var(--display); font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .12em; color: var(--orange); margin-bottom: 6px;
}
.kiez-site .kiez-roadmap-title { font-family: var(--display); font-size: 18px; font-weight: 700; color: var(--violet); line-height: 1.3; margin: 0 0 6px; }
/* Long compounds ("Hochschulverwaltungsrechenzentren") break instead of
   sticking out of a narrow column (#9105). */
.kiez-site :is(.kiez-roadmap-body, .kiez-timeline-body) { overflow-wrap: break-word; hyphens: auto; }
.kiez-site .kiez-roadmap-status {
  display: inline-block; font-family: var(--display); font-size: 11px; font-weight: 600;
  padding: 3px 10px; border-radius: 99px; margin-bottom: 10px;
  background: var(--violet-06); color: #5C447E;
}
.kiez-site .kiez-roadmap-item.is-done .kiez-roadmap-status { background: rgba(134, 53, 246, .12); color: var(--violet); }
.kiez-site .kiez-roadmap-item.is-current .kiez-roadmap-status { background: rgba(236, 99, 41, .12); color: #B8431A; }
.kiez-site .kiez-roadmap-text { font-size: 14px; line-height: 1.6; color: #776294; }
.kiez-site .kiez-roadmap-text > * + * { margin-top: .6em; }

/* Vertical: always with Layout "Always vertical"; with "Automatic" by the
   roadmap's own width, not the screen's (#9105): in a half column at 1024px
   four milestones were 114px wide each. Up to four need 700px, five or more
   960px. The three blocks repeat the same declarations because a container
   query cannot be combined with a class in one OR. */
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-list { grid-template-columns: minmax(0, 1fr); gap: 28px; }
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-list::before,
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-list::after { top: 10px; bottom: 10px; left: 9px; right: auto; width: 3px; height: auto; }
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-list::after { bottom: auto; height: calc((100% - 20px) * var(--kr-progress)); }
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-item { text-align: left; padding: 0 0 0 42px; }
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-dot { left: 0; transform: none; }
/* Stacked: one segment per milestone, from its dot to the next, coloured up to
   the reached one (audit 10-12). One line over the whole list ran 113px past
   the last dot, and its coloured share stopped between milestones. */
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-list::before,
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-list::after { display: none; }
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-item:not(:last-child)::before { content: ''; position: absolute; left: 9px; top: 10px; bottom: -38px; width: 3px; border-radius: 2px; background: var(--kr-line); }   /* -38px: 28px gap + 10px to the next dot's centre */
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-item:has(~ .is-done, ~ .is-current)::before { background: var(--kr-fill); }
@container kiez-roadmap (max-width: 699px) {
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-list { grid-template-columns: minmax(0, 1fr); gap: 28px; }   /* 1fr grew to the longest word: 74px past a phone screen */
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-list::before,
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-list::after { top: 10px; bottom: 10px; left: 9px; right: auto; width: 3px; height: auto; }
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-list::after { bottom: auto; height: calc((100% - 20px) * var(--kr-progress)); }
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-item { text-align: left; padding: 0 0 0 42px; }
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-dot { left: 0; transform: none; }
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-list::before,
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-list::after { display: none; }
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-item:not(:last-child)::before { content: ''; position: absolute; left: 9px; top: 10px; bottom: -38px; width: 3px; border-radius: 2px; background: var(--kr-line); }   /* -38px: 28px gap + 10px to the next dot's centre */
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-item:has(~ .is-done, ~ .is-current)::before { background: var(--kr-fill); }
}
@container kiez-roadmap (max-width: 959px) {
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-list { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-list::before,
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-list::after { top: 10px; bottom: 10px; left: 9px; right: auto; width: 3px; height: auto; }
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-list::after { bottom: auto; height: calc((100% - 20px) * var(--kr-progress)); }
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-item { text-align: left; padding: 0 0 0 42px; }
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-dot { left: 0; transform: none; }
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-list::before,
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-list::after { display: none; }
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-item:not(:last-child)::before { content: ''; position: absolute; left: 9px; top: 10px; bottom: -38px; width: 3px; border-radius: 2px; background: var(--kr-line); }   /* -38px: 28px gap + 10px to the next dot's centre */
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-item:has(~ .is-done, ~ .is-current)::before { background: var(--kr-fill); }
}
/* "Always horizontal" (client 2026-10-12): each milestone keeps at least
   220px, and the roadmap scrolls sideways when that is wider than its box. The
   next milestone peeking in at the edge shows that there is more. The list
   itself grows (min-width), so the line spans every milestone. Top padding
   keeps the current dot's halo inside the scroll box. */
.kiez-site .kiez-roadmap--horizontal {
  overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity; padding: 6px 0 12px;
}
.kiez-site .kiez-roadmap--horizontal .kiez-roadmap-list { min-width: calc(var(--kr-count) * 220px); }
.kiez-site .kiez-roadmap--horizontal .kiez-roadmap-item { scroll-snap-align: start; }
/* Inset: the fade mask below would hide an outline outside the box. */
.kiez-site .kiez-roadmap--horizontal:focus-visible { outline: 2px solid var(--violet); outline-offset: -2px; border-radius: 4px; }
.kiez-site .kiez-roadmap--horizontal.kiez-roadmap--dark:focus-visible { outline-color: var(--white); }
/* A fade at the right edge while there is more to scroll: three milestones
   can fill the box exactly (662px half column), then nothing peeks in. A
   scroll-driven animation is inactive without overflow, so wide roadmaps get
   no fade. Browsers without it keep the line running off the edge as the hint. */
@property --kr-fade { syntax: '<length>'; inherits: false; initial-value: 0px; }
@keyframes kiez-kr-fade { from { --kr-fade: 64px; } to { --kr-fade: 0px; } }
@supports (animation-timeline: scroll()) {
  .kiez-site .kiez-roadmap--horizontal {
    animation: kiez-kr-fade linear both; animation-timeline: scroll(self inline);
    -webkit-mask-image: linear-gradient(to left, transparent, #000 var(--kr-fade));
    mask-image: linear-gradient(to left, transparent, #000 var(--kr-fade));
  }
}

/* Timeline */
.kiez-site .kiez-timeline { list-style: none; margin: 0; padding: 0; position: relative; container: kiez-timeline / inline-size; }
.kiez-site .kiez-timeline-item {
  display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 0 40px; position: relative;
  padding-bottom: 36px;
}
.kiez-site .kiez-timeline-item::before { /* the line */
  content: ''; position: absolute; left: 180px; top: 8px; bottom: -8px; width: 2px; background: rgba(134, 53, 246, .18);
}
.kiez-site .kiez-timeline-item:last-child::before { bottom: auto; height: 0; }
.kiez-site .kiez-timeline-item::after { /* the dot */
  content: ''; position: absolute; left: 174px; top: 6px; width: 14px; height: 14px; border-radius: 50%;
  background: var(--white); border: 3px solid var(--violet);
}
.kiez-site .kiez-timeline-date {
  font-family: var(--display); font-size: 13px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .08em; color: var(--orange); text-align: right; padding-top: 3px;
}
.kiez-site .kiez-timeline-body { padding-left: 20px; }
.kiez-site .kiez-timeline-title { font-family: var(--display); font-size: 19px; font-weight: 700; color: var(--violet); line-height: 1.3; margin: 0 0 6px; }
.kiez-site .kiez-timeline-text { font-size: 15px; line-height: 1.65; color: #776294; }
.kiez-site .kiez-timeline-text > * + * { margin-top: .6em; }
/* Stacked by the timeline's own width (#9105): in a half column at 768px the
   text column next to the dates was 126px. */
@container kiez-timeline (max-width: 559px) {
  .kiez-site .kiez-timeline-item { grid-template-columns: minmax(0, 1fr); padding-left: 32px; }
  .kiez-site .kiez-timeline-item::before { left: 6px; }
  .kiez-site .kiez-timeline-item::after { left: 0; }
  .kiez-site .kiez-timeline-date { text-align: left; margin-bottom: 4px; }
  .kiez-site .kiez-timeline-body { padding-left: 0; }
}

/* On dark purple (#8801 colours). */
.kiez-site .kiez-roadmap--dark { --kr-line: rgba(255, 255, 255, .2); --kr-fill: var(--white); }
.kiez-site .kiez-roadmap--dark .kiez-roadmap-dot { background: var(--purple); }
.kiez-site .kiez-roadmap--dark .kiez-roadmap-item.is-done .kiez-roadmap-dot { background: var(--white); border-color: var(--white); }
.kiez-site .kiez-roadmap--dark .kiez-roadmap-item.is-current .kiez-roadmap-dot { border-color: var(--white); box-shadow: 0 0 0 5px rgba(255, 255, 255, .2); }
.kiez-site .kiez-roadmap--dark .kiez-roadmap-label,
.kiez-site .kiez-timeline--dark .kiez-timeline-date { color: var(--label-on-dark, #F4E8FF); }
.kiez-site .kiez-roadmap--dark .kiez-roadmap-title,
.kiez-site .kiez-timeline--dark .kiez-timeline-title { color: var(--white); }
.kiez-site .kiez-roadmap--dark .kiez-roadmap-text,
.kiez-site .kiez-timeline--dark .kiez-timeline-text { color: #C9BBE0; }
/* The light-surface pill colours (.is-done/.is-current) outranked a plain
   dark rule and left the pills at 2.2:1 on purple (#8941). */
.kiez-site .kiez-roadmap--dark .kiez-roadmap-item .kiez-roadmap-status { background: rgba(255, 255, 255, .12); color: var(--white); }
.kiez-site .kiez-roadmap--dark .kiez-roadmap-item.is-current .kiez-roadmap-status { background: var(--white); color: var(--purple); }
.kiez-site .kiez-timeline--dark .kiez-timeline-item::before { background: rgba(255, 255, 255, .2); }
.kiez-site .kiez-timeline--dark .kiez-timeline-item::after { background: var(--purple); border-color: var(--white); }

/* Item text now comes from a visual editor (#8941/#8942): lists, links and
   images as in articles — site.css resets ul and a to nothing. */
.kiez-site :is(.kiez-roadmap-text, .kiez-timeline-text) :is(ul, ol) { padding-left: 1.3em; }
/* Roadmap columns are centred on desktop: outside bullets hung at the
   column's left edge, far from their text. */
.kiez-site .kiez-roadmap-text :is(ul, ol) { padding-left: 0; }
.kiez-site :is(.kiez-roadmap-text, .kiez-timeline-text) li { list-style: disc; margin-top: .3em; }
.kiez-site .kiez-roadmap-text li { list-style-position: inside; }   /* after the li shorthand, which resets it */
.kiez-site :is(.kiez-roadmap-text, .kiez-timeline-text) ol li { list-style: decimal; }
.kiez-site :is(.kiez-roadmap-text, .kiez-timeline-text) a { color: var(--violet); text-decoration: underline; text-underline-offset: .2em; }
.kiez-site :is(.kiez-roadmap-text, .kiez-timeline-text) img { max-width: 100%; height: auto; border-radius: 6px; }
.kiez-site :is(.kiez-roadmap--dark, .kiez-timeline--dark) :is(.kiez-roadmap-text, .kiez-timeline-text) a { color: var(--white); }

/* Countdown (#8943). Numbers in Funnel Display 800 with the design's
   violet→orange gradient on light (like .ev-day), white on dark purple
   (#8801: numbers white). Tabular figures so the digits do not jitter. */
.kiez-site .kiez-countdown { text-align: center; }
.kiez-site .kiez-countdown--left { text-align: left; }
.kiez-site .kiez-countdown-head { margin-bottom: 28px; }
.kiez-site .kiez-countdown-units { display: inline-flex; flex-wrap: wrap; justify-content: center; gap: 16px; }
.kiez-site .kiez-countdown-units[hidden] { display: none; }
.kiez-site .kiez-cd-unit {
  min-width: 112px; padding: 22px 18px 18px; border-radius: 8px;
  background: var(--white); border: 1.5px solid rgba(134, 53, 246, .12);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
}
.kiez-site .kiez-cd-num {
  font-family: var(--display); font-weight: 800; font-size: clamp(36px, 5vw, 56px); line-height: 1;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
  background: linear-gradient(135deg, var(--violet), var(--orange));
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.kiez-site .kiez-cd-label {
  font-family: var(--display); font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .12em; color: #5C447E;
}
.kiez-site .kiez-countdown-done { font-family: var(--display); font-size: clamp(24px, 3vw, 34px); font-weight: 700; color: var(--violet); }
.kiez-site .kiez-countdown-date { margin-top: 18px; font-size: 14px; color: #776294; }
.kiez-site .kiez-countdown .btn { margin-top: 24px; }

.kiez-site .kiez-countdown--dark .kiez-cd-unit { background: rgba(255, 255, 255, .06); border-color: rgba(255, 255, 255, .14); }
.kiez-site .kiez-countdown--dark .kiez-cd-num { background: none; -webkit-text-fill-color: var(--white); color: var(--white); }
.kiez-site .kiez-countdown--dark .kiez-cd-label,
.kiez-site .kiez-countdown--dark .stl { color: var(--label-on-dark, #F4E8FF); }
.kiez-site .kiez-countdown--dark .sth,
.kiez-site .kiez-countdown--dark .kiez-countdown-done { color: var(--white); }
.kiez-site .kiez-countdown--dark .kiez-countdown-date { color: #C9BBE0; }
@media (max-width: 600px) {
  .kiez-site .kiez-countdown-units { gap: 10px; }
  .kiez-site .kiez-cd-unit { min-width: 72px; padding: 14px 10px 12px; }
}

/* Newsletter sign-up page (#8800 group, page = the Newsletter plugin's own
   page, 11471). Two columns: what the lists contain, and a purple card with
   the plugin's [newsletter] output — form, or its confirmation/unsubscribe
   messages — reusing the .nl-form styles of the newsletter band.
   Note: GoodLayers puts a column's custom class on .gdlr-core-pbf-column-
   content-margin, not on .gdlr-core-pbf-column (browser-checked). */
.kiez-site .kiez-nl-signup .gdlr-core-pbf-wrapper-container { display: flex; flex-wrap: wrap; align-items: flex-start; }
.kiez-site .kiez-nl-card > .gdlr-core-pbf-column-content {
  background: var(--purple); border-radius: 8px; padding: 40px 36px;
  background-image: radial-gradient(ellipse 80% 60% at 80% 0%, rgba(134, 53, 246, .35), transparent);
}
.kiez-site .kiez-nl-card .kiez-text h2 { margin-top: 0; }
.kiez-site .kiez-nl-card .nl-form { display: block; margin-top: 20px; }
.kiez-site .kiez-nl-card .nl-form .tnp-subscription form { flex-direction: column; align-items: stretch; }
.kiez-site .kiez-nl-card .nl-form .tnp-field-button input[type="submit"] { width: 100%; }
.kiez-site .kiez-nl-card .nl-form p { color: var(--white); }  /* plugin messages after submit/confirm */
@media (max-width: 960px) {
  .kiez-site .kiez-nl-signup .gdlr-core-pbf-column { width: 100%; }
  .kiez-site .kiez-nl-card { margin-top: 24px; }
}
@media (max-width: 600px) {
  .kiez-site .kiez-nl-card > .gdlr-core-pbf-column-content { padding: 28px 22px; }
}
/* After submit/confirm/unsubscribe the plugin shows a message instead of the
   form; "Jetzt anmelden" above "Herzlich willkommen!" would read oddly. */
.kiez-site .kiez-nl-card .kiez-text:not(:has(form)) > h2 { display: none; }

/* Handlungsfeld icons (found 2026-10-05 while debugging the newsletter
   video): site.css points the masks at url('img/icon-*.svg'), which resolves
   to assets/css/img/ — a folder that does not exist. A mask image that fails
   to load masks the element out entirely, so all three icons were invisible.
   The files live in assets/img/. (site.css stays a verbatim port.) */
.kiez-site .field-icon--kompetenz { --fi-mask: url('../img/icon-kompetenz.svg'); }
.kiez-site .field-icon--inferenz  { --fi-mask: url('../img/icon-inferenz.svg'); }
.kiez-site .field-icon--apps      { --fi-mask: url('../img/icon-apps.svg'); }
/* In the stacked forms (sign-up card, sidebar box) the button goes last, after
   the list choice and the required consent — not between field and consent. */
.kiez-site .kiez-nl-card .nl-form .tnp-field-button,
.kiez-site .side-block-cta .nl-form .tnp-field-button { order: 4; }

/* Handlungsfeld cards are clickable as a whole when they have a real link
   (#8811): the "Mehr erfahren" link stretches over the card. */
.kiez-site .bento-card:has(.bento-card-link) { cursor: pointer; }
.kiez-site .bento-card-link::before { content: ''; position: absolute; inset: 0; z-index: 2; border-radius: var(--r); }
.kiez-site .bento-card:has(.bento-card-link:focus-visible) { outline: 2px solid var(--violet); outline-offset: 3px; }
.kiez-site .bento-card.featured:has(.bento-card-link:focus-visible) { outline-color: var(--orange); }
.kiez-site .bento-card-link:focus-visible { outline: none; }
.kiez-site .bento-card:has(.bento-card-link):hover .btn-ghost { gap: 10px; }

/* "To the top" button (#9103). Confera prints it after the footer, but its
   styles are dequeued on design pages, so it sat unstyled in the page flow
   (bottom left). Now fixed bottom right in the CD; Confera's script adds
   .confera-scrolled after 300px of scrolling. */
.kiez-site #confera-footer-back-to-top-button {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 90;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--purple);
  color: var(--white);
  font-size: 24px;
  line-height: 1;
  box-shadow: 0 8px 24px rgba(60, 31, 102, .28);
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity .3s, visibility .3s, transform .3s, background .2s;
}
.kiez-site #confera-footer-back-to-top-button.confera-scrolled { opacity: 1; visibility: visible; transform: none; }
.kiez-site #confera-footer-back-to-top-button:hover { background: var(--violet); }
.kiez-site #confera-footer-back-to-top-button:focus-visible { outline: 2px solid var(--orange); outline-offset: 3px; }
.kiez-site #confera-footer-back-to-top-button i { margin-top: -2px; }
@media (max-width: 600px) {
  .kiez-site #confera-footer-back-to-top-button { right: 16px; bottom: 16px; width: 44px; height: 44px; font-size: 22px; }
}
@media (prefers-reduced-motion: reduce) {
  .kiez-site #confera-footer-back-to-top-button { transition: none; transform: none; }
}

/* Blog views (#8920): Confera-like layouts from the design's card variants. */
.kiez-site .kiez-blog-list { display: flex; flex-direction: column; gap: 24px; margin-bottom: 48px; }
.kiez-site .kiez-blog-lead { margin-bottom: 24px; }
.kiez-site .blog-grid.blog-grid--large { grid-template-columns: 1fr; max-width: 880px; }
/* Tags under the excerpt (Blog-Vorschau "Meta Option", 2026-10-12). Above the
   card's full-size link overlay, so each tag stays its own link. */
.kiez-site .blog-tags { display: flex; flex-wrap: wrap; gap: 6px 10px; margin: -4px 0 14px; font-family: var(--display); font-size: 12px; font-weight: 600; }
.kiez-site .blog-tags a { position: relative; z-index: 1; color: var(--violet); text-decoration: none; padding: 3px 0; margin: -3px 0; }   /* 25px tap target, same line box */
.kiez-site .blog-tags a:hover { text-decoration: underline; }
.kiez-site .blog-card-dark .blog-tags a { color: #C39AFB; }
/* Horizontal teaser ("List, image left", the lead of "Lead post + grid", the
   KI:EZ Card's horizontal variant), client 2026-10-12: side by side only from a
   1040px card. Narrower, two 280px columns made the text so tall that the
   image became a portrait crop (335 × 553 at 768px, a quarter of a 1100 × 460
   image). Stacked, the image runs the full card width in the featured-image
   format; side by side it is at least that tall and fills the text's height
   (no aspect-ratio there: stretched, it widened the image into the text). */
.kiez-site .blog-grid-2 { container: kiez-teaser / inline-size; grid-template-columns: repeat(auto-fit, minmax(min(520px, 100%), 1fr)); }
.kiez-site .blog-block-3 { min-height: 0; aspect-ratio: var(--kiez-post-ratio); }
@container kiez-teaser (min-width: 1040px) {
  .kiez-site .blog-block-3 { position: relative; aspect-ratio: auto; min-height: calc(50cqi / (var(--kiez-post-ratio))); }
  /* Out of the flow: an in-flow image kept its own height (height:100% had
     nothing definite to resolve against), so a portrait photo stretched the
     card to 897px beside a short text (audit 10-12). */
  .kiez-site .blog-block-3 > .blog-el { position: absolute; inset: 0; }
}
.kiez-site .blog-grid--large .blog-label { font-size: clamp(20px, 1.8vw, 28px); }
.kiez-site .kiez-blog-compact { list-style: none; margin: 0 0 48px; padding: 0; border-top: 1px solid rgba(134, 53, 246, .14); }
.kiez-site .kiez-blog-compact li { border-bottom: 1px solid rgba(134, 53, 246, .14); padding: 22px 0; }
.kiez-site .kiez-blog-compact-meta {
  font-family: var(--display); font-size: 12px; font-weight: 600; letter-spacing: .04em;
  color: var(--orange); margin-bottom: 8px;
}
.kiez-site .kiez-blog-compact-title { font-family: var(--display); font-size: 19px; font-weight: 700; line-height: 1.3; letter-spacing: -.01em; margin: 0 0 6px; }
.kiez-site .kiez-blog-compact-title a { color: var(--violet); }
.kiez-site .kiez-blog-compact-title a:hover { color: var(--orange); }
.kiez-site .kiez-blog-compact p { font-size: 15px; line-height: 1.6; color: #776294; max-width: 75ch; }
@media (min-width: 1800px) {
  .kiez-site .kiez-blog-compact-title { font-size: 24px; }
  .kiez-site .kiez-blog-compact p { font-size: 18px; }
}

/* --------------------------------------------------------------------------
   YouTube, two clicks (#9111) — markup from kiez_youtube_markup()
   (inc/youtube.php), behaviour in assets/js/kiez-youtube.js. The frame shows
   the local poster (or a brand gradient) with a play button; the notice
   under it explains what loading means and disappears once the video is
   loaded or the visitor has accepted YouTube in the cookie banner.
   -------------------------------------------------------------------------- */
.kiez-site .kiez-yt { margin: 0; max-width: 960px; }
.kiez-site .kiez-yt-title { font-family: var(--display); font-weight: 700; font-size: 22px; line-height: 1.25; color: var(--purple); margin: 0 0 12px; }
.kiez-site .kiez-yt-frame {
  position: relative; aspect-ratio: 16 / 9; border-radius: var(--r); overflow: hidden; isolation: isolate;
  background: radial-gradient(120% 120% at 20% 10%, #8635F6 0%, #3C1F66 60%);
}
.kiez-site .kiez-yt--4x3 .kiez-yt-frame { aspect-ratio: 4 / 3; }
.kiez-site .kiez-yt--1x1 .kiez-yt-frame { aspect-ratio: 1 / 1; }
.kiez-site .kiez-yt--21x9 .kiez-yt-frame { aspect-ratio: 21 / 9; }
.kiez-site .kiez-yt--9x16 { max-width: 400px; }
.kiez-site .kiez-yt--9x16 .kiez-yt-frame { aspect-ratio: 9 / 16; }
.kiez-site .kiez-yt-poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -1; }
.kiez-site .kiez-yt-frame::after {   /* scrim: the button reads on any poster */
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(60, 31, 102, .05) 30%, rgba(60, 31, 102, .6) 100%);
}
.kiez-site .kiez-yt-play {
  position: absolute; inset: 0; width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 16px; border: 0; background: transparent; color: var(--white); cursor: pointer;
  font: 600 15px/1.3 var(--display);
}
.kiez-site .kiez-yt-icon {
  display: grid; place-items: center; width: 72px; height: 72px; border-radius: 50%;
  background: var(--orange); box-shadow: 0 6px 24px rgba(236, 99, 41, .35); transition: transform .2s ease;
}
.kiez-site .kiez-yt-icon svg { margin-left: 4px; }
.kiez-site .kiez-yt-btn-text { background: rgba(60, 31, 102, .88); padding: 7px 16px; border-radius: 999px; }
.kiez-site .kiez-yt-play:hover .kiez-yt-icon { transform: scale(1.06); }
.kiez-site .kiez-yt-play:focus-visible { outline: 3px solid var(--white); outline-offset: -8px; }
.kiez-site .kiez-yt-play:focus-visible .kiez-yt-icon { box-shadow: 0 0 0 3px var(--white), 0 0 0 6px var(--violet); }
.kiez-site .kiez-yt-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.kiez-site .kiez-yt-noscript { position: absolute; inset: auto 0 0; margin: 0; padding: 8px 12px; font-size: 13px; color: var(--white); background: rgba(60, 31, 102, .88); }
.kiez-site .kiez-yt-notice { margin: 10px 0 0; font-size: 13px; line-height: 1.5; color: #5B4B73; max-width: 70ch; }
.kiez-site .kiez-yt-notice a { color: var(--violet); text-decoration: underline; text-underline-offset: .2em; }
.kiez-site .kiez-yt--allowed .kiez-yt-notice,
.kiez-site .kiez-yt--loaded .kiez-yt-notice { display: none; }
.kiez-site .kiez-yt-caption { margin-top: 8px; font-size: 14px; line-height: 1.5; color: #5B4B73; }
/* A pasted link inside article text: full text width, normal paragraph gap. */
.kiez-site .post-body .kiez-yt,
.kiez-site .kiez-text .kiez-yt { margin: 1.4em 0; }
@media (prefers-reduced-motion: reduce) {
  .kiez-site .kiez-yt-icon { transition: none; }
  .kiez-site .kiez-yt-play:hover .kiez-yt-icon { transform: none; }
}

/* --------------------------------------------------------------------------
   #9105 final responsive/element test
   Every page, archive and event plus every element in its variants and in
   1/3 and 1/4 columns, at 320-1920px; fixes verified in headless Chromium.
   -------------------------------------------------------------------------- */

/* Text. Long words broke out of their boxes on 320px phones ("Öffentlichkeits-
   arbeit", pasted URLs): break-word only breaks a word that would otherwise
   overflow. Headings hyphenate on phones, as page titles do (#9108), but only
   long words: short ones made "Unabhängig den-ken". "KI:Expertisezentrum.nrw"
   gets a soft hyphen in PHP (kiez_soft_brand), since ":" and "." stop the
   browser's hyphenation. */
.kiez-site { overflow-wrap: break-word; }
@media (max-width: 767px) {
  .kiez-site :is(h1, h2, h3, h4, h5, h6, .sth) { hyphens: auto; hyphenate-limit-chars: 12 5 5; }
  .kiez-site .hero h1 { hyphens: manual; }   /* the claim's words fit; browsers without the limit */
  /* Long titles and post titles: 26px left seven lines on a 390px phone. */
  .kiez-site .page-title--long,
  .kiez-site .post-header .page-title { font-size: clamp(22px, 6.2vw, 26px); }
}
/* Content headings inherited the 1.75 body leading: a wrapped H2 read as two. */
.kiez-site .post-body :is(h2, h3, h4, h5, h6) { line-height: 1.25; }
/* The brand in HTML titles (kiez_brand_html): one unit that moves to the next
   line whole and breaks at "Expertise-" only when wider than the line. An
   inline-block does not inherit a link's underline, so it takes the link's own. */
.kiez-site .kiez-brand { display: inline-block; max-width: 100%; }
.kiez-site a > .kiez-brand { text-decoration: inherit; text-underline-offset: inherit; }
/* #9105 re-check: an inline-block that has to wrap is as wide as the line, so
   "zentrum.nrw" stood alone and short words before it were stranded (post H1
   at 320px: 3 → 5 lines). Where the title box is narrower than the name
   (about 12.5em, 12em in the display sizes), the brand goes back to inline
   and the soft hyphen breaks it in place. */
.kiez-site :is(h1, h2, h3, h4, h5, h6, li):has(.kiez-brand) { container: kiez-title / inline-size; }
.kiez-site :is(.page-title, .sth):has(.kiez-brand) { container-name: kiez-title-display; }
@container kiez-title (max-width: 12.5em) { .kiez-site .kiez-brand { display: inline; } }
@container kiez-title-display (max-width: 12em) { .kiez-site .kiez-brand { display: inline; } }

/* GoodLayers wrappers below 768px. "Full width, no space" wrappers are capped
   at 500px there (page-builder.css), left-aligned: at 601-767px the hero and
   every band stopped at x 500. */
@media (max-width: 767px) {
  .kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter) .gdlr-core-pbf-wrapper-full-no-space { max-width: none; }
  /* Columns of hand-built wrappers lose their 10px half-gap (GoodLayers zeroes it
     with !important), so their content sat 10px left of titles and KI:EZ
     sections. Restored like .kiez-gutter; an editor's per-column mobile padding
     (#gdlr-core-column-N) still wins. Posts keep theirs (#9118). */
  .kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):not(.post-builder *) :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full).gdlr-core-pbf-wrapper-container .gdlr-core-pbf-column-content-margin {
    padding-left: 10px !important;
    padding-right: 10px !important;
  }
  /* The post template's 10px half-gap inset the article body from date and image. */
  .kiez-site .post-builder:not(#kiez-post) .gdlr-core-pbf-column-content-margin[style*="padding: 0px 10px 0px 10px"] { padding-left: 0 !important; padding-right: 0 !important; }
}
/* After a "Full width, no space" wrapper holding an ordinary element (KI:EZ
   Audio on 12890) the next wrapper's top padding was collapsed as if the first
   one had padding, so the two touched. Collapse only after a padded neighbour. */
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):not(:has(> .gdlr-core-pbf-wrapper-content > :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full))):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) + .gdlr-core-pbf-wrapper:not(.kiez-gutter):has(> .gdlr-core-pbf-wrapper-content > :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full)):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) {
  padding-top: var(--kiez-space-wrap, 48px);
}
/* (Board 2026-10-14: the 70-character cap on GoodLayers text boxes of full-width
   page columns, #9105, is gone; text uses the content width like the header.) */

/* KI:EZ Highlight, dark variant: the library's dark card has no title, so the
   element's title kept the light card's purple, invisible on purple (1.00:1).
   Title white, eyebrow off-white as on every dark surface (#8801). */
.kiez-site .highlight-card-dark .highlight-label { color: var(--white); }
.kiez-site .highlight-card-dark .highlight-eyebrow { color: var(--label-on-dark, #F4E8FF); }

/* Event rows (.ev: homepage band, Termin-Feed, Termin-Zeile). The title column
   was 1fr, which cannot shrink below its longest word (60px past a 320px
   screen). Below 961px site.css hides "Anmelden", the row's only link to the
   event; it now sits under the title, and the date lines up with the title's
   first line. Small phones put the date above the title. */
.kiez-site .ev { grid-template-columns: 88px minmax(0, 1fr) auto; }
@media (max-width: 960px) {
  .kiez-site .ev { grid-template-columns: 72px minmax(0, 1fr); align-items: start; row-gap: 14px; }
  .kiez-site .ev > a.btn.btn-outline:last-child:not(.ev-day) { display: inline-flex; grid-column: 2; justify-self: start; }
}
@media (max-width: 400px) {
  .kiez-site .ev { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .kiez-site .ev > :first-child { display: flex; align-items: baseline; gap: 10px; }
  .kiez-site .ev :is(.ev-day, .ev-month) { text-align: left; }
  .kiez-site .ev > a.btn.btn-outline:last-child:not(.ev-day) { grid-column: 1; }
}
/* KI:EZ Termin-Zeile in a builder column: date | title | button needs ~560px;
   in 1/3 and 1/4 columns the title shrank to one letter per line. */
.kiez-site .gdlr-core-pbf-element:has(> .ev) { container-type: inline-size; }
@media (min-width: 961px) {
  @container (max-width: 559px) {
    .kiez-site .ev { grid-template-columns: 72px minmax(0, 1fr); }
    .kiez-site .ev > .btn { grid-column: 2; justify-self: start; }
  }
}
/* Under 260px the phone layout: date on one line above the title, button
   below. The <=960px rule above puts "Anmelden" in column 2 with more weight,
   so it is reset here; a 72px date column left the title track narrower than
   the button (1/4 column at 768px: month one letter per line). */
@container (max-width: 259px) {
  .kiez-site .ev { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .kiez-site .ev > :first-child { display: flex; align-items: baseline; gap: 10px; }
  .kiez-site .ev :is(.ev-day, .ev-month) { text-align: left; }
  .kiez-site .ev > a.btn.btn-outline:last-child:not(.ev-day) { grid-column: 1; justify-self: start; }
  .kiez-site .ev h4 { hyphens: auto; }
}
/* Events band on inner pages (templates, Termin-Feed): its homepage padding
   (120px) left a 168px gap above "Termine", and its button was the only
   centred one. The KI:EZ Termine block keeps the band rhythm of the other
   blocks it is stacked with (.kiez-events-band, inc/blocks.php). */
.kiez-site:not(.home) section.events:not(.kiez-events-band *) { padding-top: 48px; padding-bottom: 48px; }
.kiez-site:not(.home) section.events:not(.kiez-events-band *) .events-list { margin-top: 24px; }
.kiez-site:not(.home) section.events:not(.kiez-events-band *) .events-list + .rv[style*="text-align:center"] { text-align: left !important; }

/* Mission items on phones: the 336px picture forced a 296px track into a
   232–280px box (64px past a 320px screen). The picture now scales with it. */
@media (max-width: 600px) {
  .kiez-site .mission-item { grid-template-columns: minmax(0, 1fr); }
  .kiez-site .mission-visual { width: min(336px, calc(100% + 40px)); height: auto; aspect-ratio: 1; }
}
/* KI:EZ Mission Item in a builder column: the row layout (number | text | 360px
   picture) needs about 720px; in a 1/4 column at 768px the picture ran 466px
   past the screen. Below that width it stacks like the phone layout above. */
.kiez-site .gdlr-core-pbf-element:has(> .mission-item) { container-type: inline-size; }
/* The item is built for the purple Mission band (white title and number). On a
   plain section it was white on white (client test page 12890, 1.00:1); outside
   the band it now brings its own purple, like the Personnel purple cards. */
.kiez-site .mission-item:not(.mission .mission-item) { background: var(--purple); }
@container (max-width: 719px) {
  .kiez-site .mission-item { grid-template-columns: minmax(0, 1fr); gap: 20px; text-align: center; justify-items: center; padding: 40px 20px; }
  .kiez-site .mission-num { order: 1; font-size: 36px; }
  .kiez-site .mission-visual { order: 2; width: min(336px, calc(100% + 40px)); height: auto; aspect-ratio: 1; margin: -20px; }
  .kiez-site .mission-body { order: 3; }
  .kiez-site .mission-body p { max-width: none; }
}

/* Field cards in three columns at tablet width (768px): 40px side padding left
   131px for "Kompetenz" (139px), and the 52px icon covered the "Handlungsfeld"
   tag. Narrow cards get the phone padding and icon; very narrow ones put the
   icon above the tag. A light card with the Kompetenz icon drew it white. */
.kiez-site .gdlr-core-pbf-element:has(> .bento-card) { container-type: inline-size; }
.kiez-site .bento-card:not(.featured) .field-icon--kompetenz { --fi-color: var(--purple); }
.kiez-site .bento-card:not(.featured):hover .field-icon--kompetenz { --fi-color: var(--violet); }
@container (max-width: 260px) {
  .kiez-site .bento-card { padding-left: 22px; padding-right: 22px; }
  .kiez-site .bento-card :is(h4, p) { hyphens: auto; hyphenate-limit-chars: 12 5 5; }   /* no "bera-ten" (2026-10-12) */
  .kiez-site .bento-card .field-icon { top: 20px; right: 20px; width: 40px; height: 40px; }
}
@container (max-width: 201px) {
  .kiez-site .bento-card .field-icon { position: static; margin: 0 0 20px; }
}

/* Tabs: the active tab's violet on the vertical tabs' lilac panel was 4.26:1;
   a touch darker violet gives 4.9:1 there and 6.2:1 on white. Vertical tabs
   used the library's equal-track grid while the list is capped at 280px, so
   the panel text began mid-card; stacked on phones the list stopped short. */
.kiez-site .tabs-tab-btn[aria-selected="true"],
.kiez-site .tabs-tab-btn-vertical[aria-selected="true"] { color: #7B2FE6; }
.kiez-site .tabs-grid[data-kiez-tabs-vertical] { grid-template-columns: minmax(0, 280px) minmax(0, 1fr); }
@media (max-width: 600px) {
  .kiez-site .tabs-grid[data-kiez-tabs-vertical] { grid-template-columns: minmax(0, 1fr); }
  .kiez-site .tabs-grid[data-kiez-tabs-vertical] > .tabs-block-2 { max-width: none; border-right: 0; border-bottom: 1.5px solid rgba(134, 53, 246, .12); }
}

/* Newsletter band. On phones site.css bleeds the purple box out of a 20px
   .wrap the band does not have (margin 0 -20px) while var(--max) still caps
   it: at 390px it ran from x -20 to 322. It is now the edge-to-edge band the
   phone rule meant. After a band with its own background (contact, header,
   hero) it had no space above. In a KI:EZ Text element (sign-up page) the
   consent link was violet on purple (2.4:1). */
@media (max-width: 600px) {
  .kiez-site .nl-inner { max-width: none; margin-left: 0; margin-right: 0; }
}
.kiez-site .gdlr-core-pbf-element:has(> section:is(.contact, .page-header, .hero)) + .gdlr-core-pbf-element > section.newsletter { padding-top: 120px; }
@media (max-width: 600px) {
  .kiez-site .gdlr-core-pbf-element:has(> section:is(.contact, .page-header, .hero)) + .gdlr-core-pbf-element > section.newsletter { padding-top: 80px; }
}
.kiez-site .post-body .nl-form .tnp-privacy-field a { color: var(--text-on-dark-soft, #F2ECFF); }

/* Footer at 480px and below: link groups and partner blocks stack in one
   column, but site.css keeps the two-column row-gap of 0, so "Rechtliches" and
   "Gefördert von" sat flush under the group above (also in chrome.css). */
@media (max-width: 480px) {
  .kiez-site .footer-links-grid,
  .kiez-site .footer-partners { row-gap: 48px; }
}
/* Back-to-top over the footer (same purple): a light ring keeps its outline. */
.kiez-site #confera-footer-back-to-top-button { box-shadow: 0 0 0 2px rgba(255, 255, 255, .4), 0 8px 24px rgba(60, 31, 102, .28); }

/* Aktuelles (news track). A 280px card was wider than the track on a 320px
   phone and in the catalogue, so the first card was never whole; on phones
   the track started 4px right of the heading (and 24px left of it from
   1800px). "Lesen" links sit at the card foot, like the blog cards. */
.kiez-site .news-track > .news-card { max-width: 100%; display: flex; flex-direction: column; }
.kiez-site .news-track > .news-card > .link { margin-top: auto; padding-top: 18px; align-self: flex-start; }
@media (max-width: 600px) {
  .kiez-site .news > .wrap + div { padding-inline: max(20px, calc((100% - var(--max)) / 2 + 20px)) !important; }   /* beats kiez-card.php's inline inset */
  .kiez-site .news-track > .news-card { flex-basis: min(280px, calc(100vw - 88px)); min-width: 0; }
}
@media (min-width: 1800px) {
  .kiez-site .news > .wrap + div { padding-inline: max(48px, calc((100% - var(--max)) / 2 + 48px)) !important; }
}

/* Konsortium: max-width 1260px replaced .kiez-gutter's var(--max) instead of
   capping it, so below 1308px the tiles stood 24px wider than every other
   block on each side. On phones two tiles per row, as the reference build. */
.kiez-site .consortium .gdlr-core-pbf-wrapper-container { max-width: min(1260px, var(--max)); }
@media (min-width: 1800px) {
  .kiez-site .consortium .gdlr-core-pbf-wrapper-container { max-width: min(1400px, var(--max)); }
}
@media (min-width: 360px) and (max-width: 767px) {
  .kiez-site .consortium .gdlr-core-pbf-column.gdlr-core-column-15 { width: 50%; }
  .kiez-site .consortium .logo-pill img { max-width: 100%; height: auto; }
}
/* KI:EZ Logo-Kachel outside the purple band: a white-filtered logo on a
   translucent white tile was invisible on a light section (12890). There it
   shows the logo in its own colours on a white tile. */
.kiez-site .logo-pill:not(:is(.consortium, .kiez-block-dark) .logo-pill) { background: var(--white); border-color: var(--violet-10); }
.kiez-site .logo-pill:not(:is(.consortium, .kiez-block-dark) .logo-pill) img { filter: none; }
.kiez-site .logo-pill:not(:is(.consortium, .kiez-block-dark) .logo-pill) span { color: var(--purple); }

/* Kontakt. The address breaks after "@" only (kiez-contact.php), never at the
   domain's own hyphen; on small phones the arrow follows the text instead of
   the box's far edge. The CF7 consent box was the browser's 13px default,
   its wrapped label lines running under it. */
.kiez-site .contact-link-domain { white-space: nowrap; }
/* #9105 re-check: the unbreakable "ki-expertisezentrum.nrw→" (183px at 14px)
   ran 19px out of the 164px box of a boxed band at 320px. */
.kiez-site .contact-info { container: kiez-contact-info / inline-size; }
@container kiez-contact-info (max-width: 182px) { .kiez-site .contact-link { font-size: 12px; } }
@media (max-width: 480px) {
  .kiez-site .contact-link { display: inline; }
  .kiez-site .contact-link > span + span { margin-left: 6px; }
}
.kiez-site .contact-form .wpcf7-acceptance .wpcf7-list-item { display: block; margin: 0; }
.kiez-site .contact-form .wpcf7-acceptance label { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.kiez-site .contact-form .wpcf7-acceptance input[type="checkbox"] { flex: 0 0 auto; width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--violet); }
.kiez-site .contact-form .wpcf7-acceptance .wpcf7-list-item-label::before,
.kiez-site .contact-form .wpcf7-acceptance .wpcf7-list-item-label::after { content: none; }

/* Team and Kontakt blocks: sections built from atoms get their rhythm from a
   section class (.fields, .mission …); these two had none (inc/blocks.php). */
.kiez-site .team { padding: 120px 0; }
.kiez-site .contacts { padding-top: 120px; }   /* the following .contact band gives the space below */
/* ...inside its grey box only: the cards stood flush on its edge (Kontakt page, 2026-10-12). */
.kiez-site .contacts:has(+ .gdlr-core-pbf-wrapper section.contact) { padding-bottom: 96px; }
@media (max-width: 600px) {
  .kiez-site .contacts:has(+ .gdlr-core-pbf-wrapper section.contact) { padding-bottom: 64px; }
}

/* KI:EZ Tabelle on narrow screens. The caption is part of the table box, so
   in a scrolling table it was as wide as the table and ran out of view
   mid-word; it now wraps within the visible width and stays put while the
   columns scroll. Edge shadows show that more columns follow (only on the
   side that can still scroll). Narrow wraps get tighter cells, so a
   three-column table fits a 320px phone. */
.kiez-site .kiez-table-wrap {
  container: kiez-table / inline-size;
  background:
    linear-gradient(90deg, #fff 30%, rgba(255, 255, 255, 0)) left / 28px 100% no-repeat local,
    linear-gradient(270deg, #fff 30%, rgba(255, 255, 255, 0)) right / 28px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(60, 31, 102, .2), rgba(60, 31, 102, 0)) left / 12px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(60, 31, 102, .2), rgba(60, 31, 102, 0)) right / 12px 100% no-repeat scroll,
    #fff;
}
.kiez-site .kiez-table caption { position: sticky; left: 0; max-width: 100cqi; box-sizing: border-box; }
.kiez-site .kiez-table--compact caption { padding-left: 14px; padding-right: 14px; }
@container kiez-table (max-width: 280px) {
  .kiez-site .kiez-table :is(th, td, caption) { padding-left: 8px; padding-right: 8px; }
}
/* Below 220px (a 1/3 column at 768px) three columns still ran 17px past the
   wrap; long cell words hyphenate there. 320px phones (230px) keep whole words. */
@container kiez-table (max-width: 220px) {
  .kiez-site .kiez-table td { hyphens: auto; }
}

/* KI:EZ Video. The play button is a flex item and shrank to an ellipse in a
   131px-high 16:9 frame (320px phone); short frames get a smaller round one.
   A portrait video in a narrow column was capped narrower than the column. */
.kiez-site .kiez-yt-icon { flex-shrink: 0; }
.kiez-site .kiez-yt-frame { container: kiez-yt-frame / size; }
@container kiez-yt-frame (max-height: 160px) {
  .kiez-site .kiez-yt-play { gap: 8px; }
  .kiez-site .kiez-yt-icon { width: 56px; height: 56px; }
}
.kiez-site .gdlr-core-pbf-element:has(.kiez-yt--9x16) { container: kiez-yt-col / inline-size; }
@container kiez-yt-col (max-width: 480px) {
  .kiez-site .kiez-yt--9x16 { max-width: none; }
}
/* Above ~1580px a 1/3 column passes 480px, the 400px cap returns, and the
   portrait sat flush left in its column; centred in partial columns. */
.kiez-site .gdlr-core-pbf-column:not(.gdlr-core-column-60) .kiez-yt--9x16 { margin-inline: auto; }

/* Blog cards and feed. Automatic columns left an empty fourth track for the
   default three posts from 1288px. In cards under 260px (1/3 and 1/4 columns
   from 768px) words were cut without a hyphen. An image-less search or archive
   card was stretched to its image-card neighbour (330px of empty card). */
.kiez-site .kiez-blog-feed--grid .blog-grid:not([class*="blog-grid--cols-"]):has(> :nth-child(3):last-child) {
  grid-template-columns: repeat(auto-fill, minmax(max(min(280px, 100%), calc((100% - 48px) / 3)), 1fr));
}
.kiez-site :is(.blog-card-light, .blog-card-dark) { container-type: inline-size; }
@media (min-width: 768px) {
  @container (max-width: 260px) {
    .kiez-site :is(.blog-label, .blog-label-2, .blog-body-text, .blog-body-text-2) { hyphens: auto; }
  }
  /* Up to 180px (1/4 column at 768px) both halves of "KI:Expertise-|zentrum.nrw"
     are wider than an 18px title line, so the brand still broke mid-word. */
  @container (max-width: 180px) {
    .kiez-site :is(.blog-label, .blog-label-2) { font-size: 16px; }
  }
}
/* Only a text card beside an image card stays short (#9105 re-check: two text
   cards side by side were 211 and 132px tall, "Lesen" 79px apart). The
   archive grid has two columns. */
.kiez-site .archive-grid > .blog-card-light:nth-child(odd):not(:has(.blog-block)):has(+ .blog-card-light .blog-block),
.kiez-site .archive-grid > .blog-card-light:has(.blog-block) + .blog-card-light:nth-child(even):not(:has(.blog-block)) { align-self: start; }

/* KI:EZ Icon-Karten: the library's flex-wrap row let a wrapped card grow to
   the full row ("Apps" twice as wide as its siblings). A grid keeps one size. */
.kiez-site .icon-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr)); }
.kiez-site .icon-row:has(> .icon-card-dark) { grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); }
.kiez-site .icon-row > * { min-width: 0; }

/* Roadmap lists: inside bullets made centred lists ragged and gave the
   vertical layout no hanging indent. The list is a left-aligned block, centred
   as a whole in the horizontal layout and flush left in the vertical one. */
.kiez-site .kiez-roadmap-text :is(ul, ol) { display: table; margin-left: auto; margin-right: auto; padding-left: 1.3em; text-align: left; }
.kiez-site .kiez-roadmap-text li { list-style-position: outside; }
.kiez-site .kiez-roadmap--vertical .kiez-roadmap-text :is(ul, ol) { margin-left: 0; }
@container kiez-roadmap (max-width: 699px) {
  .kiez-site .kiez-roadmap--auto .kiez-roadmap-text :is(ul, ol) { margin-left: 0; }
}
@container kiez-roadmap (max-width: 959px) {
  .kiez-site .kiez-roadmap--auto.kiez-roadmap--many .kiez-roadmap-text :is(ul, ol) { margin-left: 0; }
}

/* KI:EZ Alert, Code and Audio in narrow columns. The alert text could not
   shrink below its longest word and ran into the next column; the code
   header's copy button was clipped ("KOPIERE"); the audio times ran together
   ("0:000:00") under a 58px track, which now moves under the button. */
.kiez-site :is(.alert-card, .alert-card-2, .alert-card-3, .alert-card-4, .alert-card-dark) > div:last-child { min-width: 0; hyphens: auto; hyphenate-limit-chars: 12 5 5; }   /* no "No-vember" */
.kiez-site .code-block { flex-wrap: wrap; gap: 4px 12px; }
.kiez-site .code-meta { min-width: 0; overflow-wrap: anywhere; }
.kiez-site :is(.audio-row-2, .audio-row-3) { gap: 8px; }
.kiez-site .audio-row { flex-wrap: wrap; }
.kiez-site .audio-block { min-width: 96px; }

/* KI:EZ Countdown: the inline flex row wrapped by content width (3 + 1 on a
   390px phone, four unequal tiles). Four equal tiles in a row when they fit,
   otherwise two by two; three-tile countdowns keep the flex row. */
.kiez-site .kiez-countdown-units:not([hidden]):has(> :nth-child(4)) {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, max(91px, min(112px, calc(50% - 8px)))), 1fr));
  max-width: clamp(240px, (100% - 495px) * 999, 496px);
  margin-inline: auto;
}
.kiez-site .kiez-countdown--left .kiez-countdown-units:has(> :nth-child(4)) { margin-inline: 0; }
.kiez-site .kiez-countdown-units:has(> :nth-child(4)) > .kiez-cd-unit { min-width: 0; padding-left: 8px; padding-right: 8px; }

/* KI:EZ Galerie in a narrow column: columns followed the viewport only, so
   three columns in a 1/4 column at 768px gave 40px thumbnails. Above the
   phone breakpoint the gallery's own width caps them (>= ~100px each). */
.kiez-site .gdlr-core-pbf-element:has(.kiez-gallery) { container-type: inline-size; }
@media (min-width: 601px) {
  @container (max-width: 559px) { .kiez-site .kiez-gallery:is(.kiez-gallery--cols-4, .kiez-gallery--cols-5, .kiez-gallery--cols-6) { --kg-cols: 3; } }
  @container (max-width: 339px) { .kiez-site .kiez-gallery:not(.kiez-gallery--cols-1) { --kg-cols: 2; } }
  @container (max-width: 219px) { .kiez-site .kiez-gallery:not(.kiez-gallery--cols-1) { --kg-cols: 1; } }
}

/* KI:EZ Diagramm. Each bar column could not shrink below its label, so four
   bars ran out of narrow cards (Elemente page, 29px at 320px); equal columns,
   bars on one baseline row, labels on one label row. The 150px ring ran out
   of a 1/4 column. */
.kiez-site .chart-row { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; column-gap: clamp(6px, 6%, 18px); row-gap: 8px; }
.kiez-site .chart-row-2 { display: grid; grid-row: span 2; grid-template-rows: subgrid; justify-content: stretch; height: auto; }
.kiez-site .chart-row-2 > :first-child { align-self: end; }
.kiez-site .chart-label-2 { overflow-wrap: anywhere; hyphens: auto; }
.kiez-site .chart-circle { width: min(150px, 100%); height: auto; aspect-ratio: 1; }
.kiez-site .chart-circle-2 { width: 58.7%; height: auto; aspect-ratio: 1; }

/* Pullquote on phones: at the desktop 28px a quote ran to seven lines of two
   or three words. */
@media (max-width: 600px) {
  .kiez-site .pullquote { font-size: 22px; padding-left: 20px; }
}

/* GoodLayers Skill Bar on KI:EZ pages: track and fill colours come only from
   Confera's options CSS, which design pages drop, so only the labels showed. */
.kiez-site .gdlr-core-skill-bar-item .gdlr-core-skill-bar-head { display: flow-root; }
.kiez-site .gdlr-core-skill-bar-item .gdlr-core-skill-bar-progress { background-color: var(--violet-10); border-radius: 3px; overflow: hidden; }
.kiez-site .gdlr-core-skill-bar-item :is(.gdlr-core-skill-bar-filled, .gdlr-core-skill-bar-filled-indicator) { background-color: var(--violet); }
/* #9105 re-check: "Rectangle 2" draws its label (top -36px) and 22px
   indicator inside the fill, so the track must not clip them; "large" lays
   the head over the 40px violet fill, where purple text read 2.44:1. */
.kiez-site .gdlr-core-skill-bar-item.gdlr-core-type-rectangle2 .gdlr-core-skill-bar-progress { overflow: visible; }
.kiez-site .gdlr-core-skill-bar-item.gdlr-core-size-large .gdlr-core-skill-bar-head :is(.gdlr-core-skill-bar-title, .gdlr-core-skill-bar-right, .gdlr-core-skill-bar-icon) { color: var(--white); }

/* The Events Calendar. Its accent was never mapped (Customizer empty), so the
   default blue #334AFF showed: selected day, event dots, multiday bars,
   "Kalender abonnieren". Same variables TEC's accent setting writes, in brand
   violet. Its view container added its own padding and min-height on top of
   the archive's (183px above the search bar at 1440). A disabled "Nächste"
   stood 16px against 12px for its siblings on phones. */
.kiez-site {
  --tec-color-accent-primary: #8635F6;
  --tec-color-accent-primary-hover: rgba(134, 53, 246, .8);
  --tec-color-accent-primary-active: rgba(134, 53, 246, .9);
  --tec-color-accent-primary-background: rgba(134, 53, 246, .07);
  --tec-color-accent-primary-multiday: rgba(134, 53, 246, .24);
  --tec-color-accent-primary-multiday-hover: rgba(134, 53, 246, .34);
  --tec-color-accent-primary-background-datepicker: #8635F6;
  --tec-color-background-secondary-datepicker: rgba(134, 53, 246, .5);
  --tec-color-button-primary: #8635F6;
  --tec-color-button-primary-hover: rgba(134, 53, 246, .8);
  --tec-color-button-primary-active: rgba(134, 53, 246, .9);
  --tec-color-button-primary-background: rgba(134, 53, 246, .07);
  --tec-color-day-marker-current-month: #8635F6;
  --tec-color-day-marker-current-month-hover: rgba(134, 53, 246, .8);
  --tec-color-day-marker-current-month-active: rgba(134, 53, 246, .9);
  --tec-color-background-primary-multiday: rgba(134, 53, 246, .24);
  --tec-color-background-primary-multiday-hover: rgba(134, 53, 246, .34);
  --tec-color-background-primary-multiday-active: rgba(134, 53, 246, .34);
  --tec-color-background-secondary-multiday: rgba(134, 53, 246, .24);
  --tec-color-background-secondary-multiday-hover: rgba(134, 53, 246, .34);
  --tec-color-event-icon-hover: #8635F6;
  --tec-color-icon-focus: #8635F6;
  --tec-color-link-accent-hover: rgba(134, 53, 246, .8);
}
.kiez-site .kiez-events-archive .tribe-events-calendar-month__day-cell--selected .tribe-events-calendar-month__day-date-daynum { color: var(--white); }
.kiez-site .kiez-events-archive .tribe-common-l-container,
.kiez-site .kiez-events-archive .tribe-events-l-container { padding-top: 0; padding-bottom: 0; min-height: 0; }
.kiez-site .kiez-events-archive .tribe-events:not(.tribe-common--breakpoint-medium) .tribe-events-c-nav__prev:disabled,
.kiez-site .kiez-events-archive .tribe-events:not(.tribe-common--breakpoint-medium) .tribe-events-c-nav__next:disabled {
  font-size: var(--tec-font-size-1); line-height: var(--tec-line-height-0);
}
.kiez-site .tribe-common .tribe-events-c-subscribe-dropdown__button { border: 1.5px solid var(--violet-25); border-radius: var(--r); color: var(--violet); background-color: transparent; }
.kiez-site .tribe-common .tribe-events-c-subscribe-dropdown__button:is(:hover, :focus-within) { border-color: var(--violet); background-color: var(--violet-06); color: var(--violet); }   /* TEC's white label was 1.09:1 on the tint (2026-10-12) */

/* Sidebar: the Handlungsfelder links carry 10px side padding for their pill,
   so their text sat 10px right of the heading; pulled out by the same amount. */
.kiez-site .side-cats { margin-left: -10px; margin-right: -10px; }

/* --------------------------------------------------------------------------
   Personnel profile page (single-personnel.php): the portrait beside the
   contact facts (the event page's fact box) and the biography, then other
   people as Personnel cards. One column below 900px.
   -------------------------------------------------------------------------- */
.kiez-site .profile-layout {
  display: grid;
  grid-template-columns: minmax(0, 240px) minmax(0, 1fr);   /* was 300px for a 4:5 photo */
  gap: 56px;
  align-items: start;
}
/* The portrait stays in view beside a long biography (nav height + 20px). */
.kiez-site .profile-photo { position: sticky; top: 110px; }
/* A circle (user 2026-10-12), as the round Personnel cards: the team photos are
   squares, and a burned-in credit in their corner falls outside it. */
.kiez-site .profile-photo-img,
.kiez-site .profile-initials {
  display: block; width: 100%; height: auto;
  aspect-ratio: 1 / 1; border-radius: 50%;
}
.kiez-site .profile-photo-img { object-fit: cover; object-position: 50% 25%; }   /* heads sit in the upper third */
.kiez-site .profile-initials {
  display: grid; place-items: center;
  background: var(--violet-06); color: var(--violet);
  font-family: var(--display); font-size: clamp(48px, 6vw, 88px); font-weight: 700;
}
.kiez-site .profile-main { min-width: 0; max-width: 820px; }
.kiez-site .profile-facts { margin-bottom: 40px; max-width: 70ch; }   /* as wide as the biography, not 820px for one line (review 10-12) */
.kiez-site .profile-photo-credit { margin: 10px 0 0; font-size: 13px; line-height: 1.4; color: #5C447E; text-align: center; }
.kiez-site .profile-facts a { color: var(--violet); text-decoration: underline; text-underline-offset: 3px; }
.kiez-site .profile-facts a:hover { color: var(--orange); }
/* An inline-block does not inherit the link's underline: draw its own. */
/* inline: as an inline-block the domain drew its own second focus ring (review 10-12). */
.kiez-site .profile-facts .kiez-person-mail-domain { display: inline; white-space: nowrap; text-decoration: underline; text-underline-offset: 3px; }
.kiez-site .profile-bio { max-width: 70ch; }
.kiez-site .profile-hint {
  max-width: 70ch; margin: 0; padding: 20px 24px;
  border: 1.5px dashed var(--violet-25); border-radius: var(--r);
  font-size: 15px; line-height: 1.6; color: var(--text-on-light-soft, #5C447E);
}
.kiez-site .profile-hint a { color: var(--violet); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.kiez-site .profile-builder { margin-top: 56px; }
.kiez-site .profile-more { margin-top: 96px; padding-top: 64px; border-top: 1.5px solid var(--violet-10); }
.kiez-site .profile-more .sth { margin-bottom: 40px; }
.kiez-site .profile-team-link { margin-top: 32px; }
@media (max-width: 900px) {
  .kiez-site .profile-layout { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .kiez-site .profile-photo { position: static; width: min(240px, 60%); }
  .kiez-site .profile-more { margin-top: 64px; padding-top: 48px; }
}
@media (max-width: 600px) {
  .kiez-site .profile-photo { width: 180px; }
  .kiez-site .profile-facts { margin-bottom: 32px; }
}


/* --------------------------------------------------------------------------
   Responsive check 2026-10-12 (review "content pages", measured and tested by
   injection at 320–1920px).
   -------------------------------------------------------------------------- */
/* Profile "Weitere Personen": three cards fitted only from 804px, so tablets
   got 2 + a lone card. Three from 684px, one per row below. */
.kiez-site .profile-more .kiez-people { --kp-min: 180px; }
@media (max-width: 683px) {
  .kiez-site .profile-more .kiez-people { grid-template-columns: minmax(0, 1fr); }
}
/* Footer: the fixed back-to-top button covered the ministry crest at the end
   of the page (320/768); "Learning AID" wrapped onto two lines at 961–1150px. */
@media (max-width: 1023px) { .kiez-site .footer { padding-bottom: 80px; } }
@media (max-width: 600px)  { .kiez-site .footer { padding-bottom: 68px; } }
.kiez-site .footer-col-links a { white-space: nowrap; }
/* Short pages show white below the footer. Not fixed with a purple <html>:
   that stops the body's white from reaching the canvas, and GoodLayers'
   wrapper backgrounds (z-index -2) then vanish under it (reverted 2026-10-12). */

/* Responsive check 2026-10-12 (review "blog & events", tested by injection). */
/* Old GoodLayers gallery carousel in posts: one slide at a fixed 180px height
   between 600 and 767px cropped the portrait group photo to a thin strip. */
@media (max-width: 767px) {
  .kiez-site .post-builder .gdlr-core-gallery-item .flexslider .slides img { height: auto; aspect-ratio: 3 / 2; }
}
/* From 1800px the root scales to 144%: the post navigation titles and the
   sidebar "→" links grew to 23/18px beside 12–15px labels and lists. */
.kiez-site .post-nav a { font-size: 16px; }
.kiez-site :is(.side-block, .event-facts) .btn-ghost { font-size: 13px; }
/* Keyboard focus on checkboxes and submit buttons (review "content pages",
   confirmed): site.css sets outline:none on every form input and only the
   text fields get a border colour on focus. Mouse clicks get no ring. */
.kiez-site .contact-form input:is([type="checkbox"], [type="radio"], [type="submit"]):focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; }
.kiez-site .nl-form input:is([type="checkbox"], [type="radio"], [type="submit"]):focus-visible { outline: 2px solid var(--white); outline-offset: 3px; }

/* Responsive check 2026-10-12 (review "elements", confirmed by a second check). */
/* "Lead post + grid": with 2 or 3 cards under the full-width lead, auto-fill
   left empty tracks on wide screens (342px at 1440, 675px at 1920). Full rows
   of 4 or more keep their tracks. */
.kiez-site .kiez-blog-feed--featured .blog-grid:not([class*="blog-grid--cols-"]):has(> :nth-child(2)):not(:has(> :nth-child(4))) {
  grid-template-columns: repeat(auto-fit, minmax(max(min(280px, 100%), calc((100% - 48px) / 3)), 1fr));
}
/* Long German words in narrow columns were cut at a random letter without a
   hyphen ("Unterstützu|ngsangebot|en", "Boverma|nn"): hyphenate where the box
   is narrow. The list teaser title also stops scaling with the viewport there. */
.kiez-site .kiez-blog-compact { container: kiez-compact / inline-size; }
@container kiez-teaser (max-width: 400px) {
  .kiez-site .blog-label-3 { font-size: 20px; hyphens: auto; hyphenate-limit-chars: 12 5 5; }
}
@media (min-width: 1800px) {
  @container kiez-teaser (max-width: 400px) { .kiez-site .blog-label-3 { font-size: 24px; } }
}
@container kiez-compact (max-width: 400px) {
  .kiez-site .kiez-blog-compact-title { hyphens: auto; hyphenate-limit-chars: 12 5 5; }
}
@container kiez-person (max-width: 200px) {
  .kiez-site :is(.kiez-person-name, .kiez-person-inst) { hyphens: auto; hyphenate-limit-chars: 8 4 4; }
}
/* Newsletter "E-mail + button only": the plugin capped the field at 300px and
   the button stretched (472px at 1920). Now as in the full form. */
.kiez-site .nl-form .tnp-subscription-minimal .tnp-email { max-width: none; margin-right: 0; }
.kiez-site .nl-form .tnp-subscription-minimal .tnp-submit { flex: 0 0 auto; }

/* Responsive check 2026-10-12 (review "blog & events", confirmed by a second check). */
/* Old GoodLayers quote and notice boxes in posts kept their desktop indents on
   phones: 133–136px text columns with words cut at random letters. */
@media (max-width: 767px) {
  .kiez-site .gdlr-core-testimonial-style-image-left .gdlr-core-testimonial-content-wrap { padding-left: 0; padding-right: 0; }
  .kiez-site .gdlr-core-alert-box-item.gdlr-core-left-align .gdlr-core-alert-box-item-content { padding-left: 0; }
  /* Running text, sidebar lists and the post navigation: long German words
     were cut without a hyphen ("Hochschulqualitätsentwicklun|g"). Only words
     of 18+ letters hyphenate, so short ones stay whole. */
  .kiez-site :is(.post-body, .post-builder, .archive-side, .post-nav) { hyphens: auto; hyphenate-limit-chars: 18 6 6; }
}
/* TEC date picker: fixed 48px day cells made a 336px table that ran off
   320–390px screens (page scrolled sideways, burger gone). */
.kiez-site .kiez-events-archive .datepicker table { width: 100%; table-layout: fixed; }
.kiez-site .kiez-events-archive .datepicker .day { width: auto; }
/* TEC focus: "Heute"/"Dieser Monat" and the mobile day cells only changed a
   background tint (1.07:1). */
.kiez-site .kiez-events-archive .tribe-events-c-top-bar__today-button:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; }
.kiez-site .kiez-events-archive .tribe-events-calendar-month__day-cell--mobile:focus-visible { outline: 2px solid var(--violet); outline-offset: -2px; }
/* Event content copied from the old site (Learning AID): TEC's own content
   wrapper set a fallback font and near-black, and GoodLayers [button]
   shortcodes showed as small underlined links. Better: clean the content. */
.kiez-site .post-body .tribe-events-content { color: inherit; font-family: inherit; }
.kiez-site .post-body .tribe-events-content p { font-size: inherit; line-height: inherit; margin: 0 0 1.1em; }
.kiez-site .post-body .tribe-events-content p:last-child { margin-bottom: 0; }
.kiez-site .post-body a.gdlr-core-button { display: inline-block; padding: 14px 28px; border: 0; border-radius: var(--r); background: var(--orange); color: #fff; text-decoration: none; font-family: var(--display); font-size: 15px; font-weight: 600; letter-spacing: 0; text-transform: none; line-height: 1.3; }
.kiez-site .post-body a.gdlr-core-button .gdlr-core-content { color: inherit; }
/* Old GoodLayers accordion in posts: keyboard access added in site.js. */
.kiez-site .gdlr-core-accordion-item-title:focus-visible { outline: 2px solid var(--violet); outline-offset: 4px; border-radius: 4px; }

/* Responsive check 2026-10-12 (review "site frame & homepage"). */
/* Search results mix image and text cards; the row-height rule above assumes
   two columns, but from ~1485px auto-fill made three (uneven first row, lone
   last card). Mixed grids stay at two columns; pure post archives keep three. */
/* (:has() cannot be nested: a text-only card is one whose text block comes first.) */
.kiez-site .archive-grid:has(> .blog-card-light > .blog-block-2:first-child) {
  grid-template-columns: repeat(auto-fill, minmax(max(min(320px, 100%), calc(50% - 12px)), 1fr));
}

/* --------------------------------------------------------------------------
   Board 2026-10-14 (Confluence "KIEZ-Webseite", open cards)
   -------------------------------------------------------------------------- */

/* "H3 (Title Section) is larger than H2": KI:EZ Section Title printed every
   level with the big title class (42px, 60px from 1800px), while an H2 in a
   text is 24-32px. As H3 it now stays below every H2 on the page. */
.kiez-site h3.sth { font-size: clamp(20px, 2.2vw, 28px); line-height: 1.2; letter-spacing: -.02em; }

/* Blog post: date, author and tags under the title (kiez_post_meta_html), in
   the purple header or, with the title in the article, above the text. */
.kiez-site .page-meta { margin-top: 18px; display: flex; flex-direction: column; gap: 12px; }
.kiez-site .post-meta-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.kiez-site .page-meta .post-meta-line { font-family: var(--display); font-size: 15px; font-weight: 600; color: var(--text-on-dark-soft, #F2ECFF); }
.kiez-site .post-meta-tags { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; }
.kiez-site .post-meta .post-meta-tags { margin-top: 10px; }
.kiez-site .post-meta-tags a {
  display: inline-block; padding: 4px 12px; border-radius: 999px;
  font-family: var(--display); font-size: 13px; font-weight: 600; line-height: 1.4;
  text-decoration: none; border: 1.5px solid var(--violet-25); color: var(--violet);
  transition: background .2s, border-color .2s;
}
.kiez-site .post-meta-tags a:hover { background: var(--violet-06); border-color: var(--violet); }
.kiez-site .page-meta .post-meta-tags a { border-color: rgba(255, 255, 255, .45); color: var(--white); }
.kiez-site .page-meta .post-meta-tags a:hover { background: rgba(255, 255, 255, .12); border-color: var(--white); }
.kiez-site .post-meta-tags a:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.kiez-site .post-meta-sep { margin-right: 6px; }

/* Sidebar tags (KI:EZ Schlagwörter): the post tag chips with a count. */
.kiez-site .side-tags a .side-tags-count { opacity: .65; font-weight: 500; margin-left: 2px; }
.kiez-site .side-tags a[aria-current="page"] { background: var(--violet); border-color: var(--violet); color: var(--white); }

/* KI:EZ Übersichtskarte (board 2026-10-14): the blog card with an icon in
   place of the image. Cards in the columns of one builder row share their
   height (as the field cards), and the link sits at the card's foot. */
.kiez-site .kiez-ov-card { display: flex; flex-direction: column; height: 100%; }
.kiez-site .kiez-ov-card > .blog-block-2 { flex: 1 1 auto; display: flex; flex-direction: column; }
.kiez-site .kiez-ov-card > .blog-block-2 > .card-link-arrow { margin-top: auto; padding-top: 18px; }
.kiez-site .kiez-ov-card .blog-icon { padding: 28px 28px 0; line-height: 1; }
.kiez-site .kiez-ov-card .blog-icon .kiez-icon-font { font-size: 44px; color: var(--violet); }
.kiez-site .kiez-ov-card .blog-icon .kiez-icon-font.kiez-ico { font-size: 56px; }
.kiez-site .blog-card-dark.kiez-ov-card .blog-icon .kiez-icon-font { color: var(--orange); }
.kiez-site .gdlr-core-pbf-wrapper-container:has(> .gdlr-core-pbf-column .kiez-ov-card) { display: flex; flex-wrap: wrap; }
.kiez-site .gdlr-core-pbf-wrapper-container:has(> .gdlr-core-pbf-column .kiez-ov-card)::before,
.kiez-site .gdlr-core-pbf-wrapper-container:has(> .gdlr-core-pbf-column .kiez-ov-card)::after { content: none; }   /* clearfix, would become flex items */
.kiez-site .gdlr-core-pbf-column:has(.kiez-ov-card) > .gdlr-core-pbf-column-content-margin,
.kiez-site .gdlr-core-pbf-column:has(.kiez-ov-card) .gdlr-core-pbf-column-content { height: 100%; }
.kiez-site .gdlr-core-pbf-column:has(.kiez-ov-card) .gdlr-core-pbf-column-content { display: flex; flex-direction: column; }
.kiez-site .gdlr-core-pbf-column:has(.kiez-ov-card) .gdlr-core-pbf-column-content > .gdlr-core-pbf-element:has(.kiez-ov-card) { flex: 1 1 auto; }

/* Vertical spacing (board 2026-10-14: "define vertical spacing for wrappers
   and columns"). One scale for hand-built content: wrappers sit
   var(--kiez-space-wrap) apart (64px desktop, 56px tablet, 48px phone; two
   neighbours share one gap, rules under "Vertical rhythm"), rows of columns
   var(--kiez-space-col) apart: stacked on phones, and also where a row wraps
   on wider screens (it touched before). Purple bands keep their 120px and the
   design's own sections (.kiez-gutter) their 20px card gap. Values an editor
   enters in a wrapper or column still win. */
/* Board 2026-10-16 "make the section spacing larger (all wrappers)": 96 / 72 /
   56px, was 64 / 56 / 48px (2026-10-14). */
.kiez-site { --kiez-space-wrap: 96px; --kiez-space-col: 24px; }
@media (max-width: 1023px) { .kiez-site { --kiez-space-wrap: 72px; } }
@media (max-width: 767px) { .kiez-site { --kiez-space-wrap: 56px; } }
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) .gdlr-core-column-first ~ .gdlr-core-column-first,
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) .gdlr-core-column-first ~ .gdlr-core-column-first ~ .gdlr-core-pbf-column { margin-top: var(--kiez-space-col); }

/* A full-width row of columns that opens with a section title starts a new
   section, also when an editor put it in the same wrapper as the section
   before. It gets the wrapper gap, not the 24px row gap (team page,
   2026-10-14: "Handlungsfeld Governance" sat 24px under the cards above).
   Full-width rows only: in a split row the other columns would not move. */
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) .gdlr-core-column-first ~ .gdlr-core-column-60.gdlr-core-column-first:has(> .gdlr-core-pbf-column-content-margin > .gdlr-core-pbf-column-content > .gdlr-core-pbf-element:first-child :is(.sth, .stl)) { margin-top: var(--kiez-space-wrap); }

/* An empty wrapper (no element in it) adds no gap of its own: on the team
   page one doubled the gap between two sections to 128px. Only the bottom
   padding goes. The top is already shared with a plain wrapper before it,
   and after a band it still leaves the one gap. Padding typed in by an
   editor is inline and still wins. */
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):has(> .gdlr-core-pbf-wrapper-content > :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full)):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))):not(:has(.gdlr-core-pbf-element)) { padding-bottom: 0; }

/* WP-DownloadManager (board 2026-10-14): its templates use these classes
   (settings set on the clone, see backlog). One file per row, the name as
   the link, size and date below it; the search form at the end. */
.kiez-site .kiez-dl-cat { font-family: var(--display); font-size: clamp(20px, 2.2vw, 28px); font-weight: 700; color: var(--violet); margin: 40px 0 12px; }
.kiez-site .kiez-dl-cat:first-child { margin-top: 0; }   /* the section already spaces it from the header */
.kiez-site .kiez-dl-item { display: grid; gap: 2px; padding: 16px 0; border-bottom: 1.5px solid var(--violet-10); }
.kiez-site .kiez-dl-item:first-of-type { border-top: 1.5px solid var(--violet-10); }
.kiez-site .kiez-dl-link { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--violet); text-decoration: underline; text-underline-offset: 3px; }
.kiez-site a.kiez-dl-link::before { content: "\2193"; display: inline-block; margin-right: 8px; text-decoration: none; }   /* download arrow */
.kiez-site .kiez-dl-meta { font-size: 13px; color: var(--text-on-light-soft, #5C447E); }
.kiez-site .kiez-dl-desc:empty { display: none; }
.kiez-site .kiez-dl-desc { font-size: 15px; line-height: 1.6; color: var(--purple); }
.kiez-site .kiez-dl-denied { margin: 4px 0 0; font-size: 13px; color: var(--purple); font-style: italic; }
.kiez-site .kiez-dl-search { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 28px; }
.kiez-site .kiez-dl-search input[type="search"] { flex: 1 1 220px; min-width: 0; padding: 10px 14px; border: 1.5px solid #9B7BD0; border-radius: var(--r); font: inherit; color: var(--purple); }
.kiez-site .kiez-dl-search input[type="submit"] { padding: 10px 20px; border: 0; border-radius: var(--r); background: var(--purple); color: var(--white); font-family: var(--display); font-weight: 600; cursor: pointer; }
.kiez-site .kiez-dl-search input[type="submit"]:hover { background: var(--violet); }
.kiez-site .kiez-dl-search :is(input):focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   Board update 2026-10-19 (cards of 15./16.10.)
   -------------------------------------------------------------------------- */
/* Overview pages (Übersichtsseite template): the card row is a bare
   .kiez-gutter section. Those belong to no designed band (.fields, .mission …)
   and got no vertical spacing, so the cards sat directly on the page header
   (Inferenz-Angebot, 0px). They follow the wrapper scale like hand-built
   content; two padded neighbours share one gap. The last card row's 20px
   column margin counts towards the gap below. */
.kiez-site .gdlr-core-pbf-wrapper.kiez-gutter:not(.kiez-spec-row, .spec-demo-row, .fields, .mission, .consortium, .team, .contacts):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) {
  padding-top: var(--kiez-space-wrap);
  padding-bottom: calc(var(--kiez-space-wrap) - 20px);
}
.kiez-site .gdlr-core-pbf-wrapper:not(.kiez-gutter):has(> .gdlr-core-pbf-wrapper-content > :is(.gdlr-core-container, .gdlr-core-container-custom, .gdlr-core-pbf-wrapper-full)):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) + .gdlr-core-pbf-wrapper.kiez-gutter:not(.kiez-spec-row, .spec-demo-row, .fields, .mission, .consortium, .team, .contacts):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))),
.kiez-site .gdlr-core-pbf-wrapper.kiez-gutter:not(.kiez-spec-row, .spec-demo-row, .fields, .mission, .consortium, .team, .contacts):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) + .gdlr-core-pbf-wrapper:not(.kiez-gutter):not(:has(section:is(.hero, .about, .news, .events, .newsletter, .contact, .page-header))) {
  padding-top: 0;
}

/* Tabs and accordion use the full width (board 15.10.: "text wraps instead of
   using the full width"); the component library capped panel text at 560-680px
   and the accordion at 820px. */
.kiez-site :is(.tabs-body-text, .tabs-body-text-2, .faq-body-text), .kiez-site .faq-row { max-width: none; }

/* Rich text in boxes (alert, highlight, field card, tabs, accordion): the
   editor's links looked like plain text (site.css resets links) and lists had
   no bullets (board 16.10., "Generative KI an Hochschulen"). Same treatment as
   article text; white on the dark variants. */
.kiez-site :is(.kiez-rich, .bento-card) a:not(.btn, .btn-ghost, .bento-card-link) { color: var(--violet); text-decoration: underline; text-underline-offset: .2em; }
.kiez-site :is(.kiez-rich, .bento-card) a:not(.btn, .btn-ghost, .bento-card-link):hover { color: var(--purple); }
.kiez-site :is(.highlight-card-dark, .alert-card-dark, .bento-card.featured) a:not(.btn, .btn-ghost, .bento-card-link) { color: var(--white); }
.kiez-site :is(.kiez-rich, .bento-card) :is(ul, ol) { padding-left: 1.3em; margin: .6em 0; }
.kiez-site :is(.kiez-rich, .bento-card) li { list-style: disc; margin-top: .3em; }
.kiez-site :is(.kiez-rich, .bento-card) ol > li { list-style: decimal; }
.kiez-site .kiez-rich > p + p { margin-top: .6em; }
.kiez-site .kiez-rich > :last-child { margin-bottom: 0; }
.kiez-site .kiez-rich :is(strong, b) { font-weight: 700; }

/* Text size "Larger" for boxes, tabs and accordion (board 15.10.: "two
   variants like the table"): each text about 2px larger. */
.kiez-site .kiez-size-lg :is(.highlight-body-text, .highlight-body-text-2) { font-size: 16px; }
.kiez-site .kiez-size-lg .highlight-label { font-size: 19px; }
.kiez-site .kiez-size-lg :is(.alert-label, .alert-label-2) { font-size: 16px; }
.kiez-site .kiez-size-lg :is(.tabs-body-text, .tabs-body-text-2) { font-size: 17px; }
.kiez-site .kiez-size-lg :is(.tabs-tab-btn, .tabs-tab-btn-vertical) { font-size: 16px; }
.kiez-site .kiez-size-lg .tabs-label { font-size: 22px; }
.kiez-site .kiez-size-lg .faq-el { font-size: 18px; }
.kiez-site .kiez-size-lg .faq-body-text { font-size: 16px; }
/* Also field cards and overview cards (user, 2026-10-19). */
.kiez-site .bento-card.kiez-size-lg > :is(p, ul, ol) { font-size: 17px; }
@media (min-width: 1800px) { .kiez-site .bento-card.kiez-size-lg > :is(p, ul, ol) { font-size: 24px; } }
.kiez-site .kiez-ov-card.kiez-size-lg :is(.blog-label, .blog-label-2) { font-size: 20px; }
.kiez-site .kiez-ov-card.kiez-size-lg :is(.blog-body-text, .blog-body-text-2) { font-size: 16px; }

/* Placeholder avatar = the team's own upload "Personnel" (user, 2026-10-19):
   a purple silhouette on lilac without a frame, so it is shown like a photo.
   The zoom and the ring on purple cards that were here belonged to the older
   framed "Avatar-Personnel", whose square frame showed in round frames. */

/* GoodLayers text boxes (Datenschutz, Impressum, older posts): links looked
   like plain text (site.css resets links) and headings sat flush on the next
   line (privacy text 2026-10-19). */
.kiez-site .gdlr-core-text-box-item-content a:not(.gdlr-core-button) { color: var(--violet); text-decoration: underline; text-underline-offset: .2em; overflow-wrap: anywhere; }
.kiez-site .gdlr-core-text-box-item-content :is(h2, h3) { margin: 1.4em 0 .45em; line-height: 1.25; }
.kiez-site .gdlr-core-text-box-item-content > :is(h2, h3):first-child { margin-top: 0; }

/* KI:EZ Blog-Vorschau, view "Slider" (board 15.10.): one strip of cards with
   the news element's arrows (ui.js hides them when everything fits). */
.kiez-site .kiez-blog-slider-nav { justify-content: flex-end; margin-bottom: 16px; }
.kiez-site .kiez-blog-slider { display: flex; gap: 24px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: thin; padding-bottom: 12px; }
.kiez-site .kiez-blog-slider > * { flex: 0 0 min(360px, 85%); scroll-snap-align: start; }
.kiez-site .kiez-blog-slider:focus-visible { outline: 2px solid var(--violet); outline-offset: 4px; }
@media (prefers-reduced-motion: no-preference) {
  .kiez-site .kiez-blog-slider { scroll-behavior: smooth; }
}


/* ==========================================================================
   Responsive check 2026-10-26 (session html-6e), applied 20261026-125844 on the
   user's instruction. Findings and verification: tmp/KIEZ-RESPONSIVE-CHECK-2026-10-26.md
   ========================================================================== */

/* R1  Scrolling table in a half column widened the phone layout viewport
   (390px phone rendered at 480px, 768px tablet at 829px; page 12852).
   The wrap is overflow-x:auto but static, so the absolutely positioned
   screen-reader span of a new-tab link escaped it and counted as page
   overflow. Making the wrap the containing block clips it. */
.kiez-site .kiez-table-wrap { position: relative; }

/* R2  Long German compounds broke mid-word without a hyphen in pull quotes,
   highlight-box headings and rich text (12880, 13417, 13430, 12833). */
.kiez-site .pullquote,
.kiez-site .highlight-label,
.kiez-site .blog-card-link,
.kiez-site .kiez-rich { hyphens: auto; hyphenate-limit-chars: 12 5 5; }

/* R3  "Main + side" rows kept desktop proportions on tablets. At 768px a 1/4
   side column is 173px wide, a 1/3 column 231px, a 2/5 column 277px: side
   boxes ("Gut zu wissen", "Auf einen Blick", "Passend dazu", "Hinweis …")
   ran 1–3 words per line and grew 900–1200px tall, and pull quotes broke
   inside words (12833, 12838, 12845, 12880, 13417, 13430). Below 960px the
   pair stacks. Rows of equal columns (3 × 1/3 cards, 1/4 logo grids, 1/2 +
   1/2) are not matched and stay side by side. */
@media (max-width: 960px) {
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-45:has(+ .gdlr-core-column-15),
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-45 + .gdlr-core-column-15,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-15:has(+ .gdlr-core-column-45),
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-15 + .gdlr-core-column-45,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-40:has(+ .gdlr-core-column-20),
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-40 + .gdlr-core-column-20,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-20:has(+ .gdlr-core-column-40),
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-20 + .gdlr-core-column-40,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-36:has(+ .gdlr-core-column-24),
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-36 + .gdlr-core-column-24,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-24:has(+ .gdlr-core-column-36),
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-24 + .gdlr-core-column-36 { width: 100%; }
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-45 + .gdlr-core-column-15,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-15 + .gdlr-core-column-45,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-40 + .gdlr-core-column-20,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-20 + .gdlr-core-column-40,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-36 + .gdlr-core-column-24,
  .kiez-site .gdlr-core-pbf-wrapper-container > .gdlr-core-column-24 + .gdlr-core-column-36 { margin-top: var(--kiez-space-col, 24px); }
}

/* R4  Consortium logo labels were 9px on phones (site.css line 516). */
@media (max-width: 600px) {
  .kiez-site .logo-pill span { font-size: 11px; }
}

/* R5  Touch targets under 24px on phones: breadcrumb links, card links, the
   newsletter / consent checkboxes. */
@media (max-width: 1024px) {
  .kiez-site .page-crumbs a,
  .kiez-site .news-card .link,
  .kiez-site .bento-card-link,
  .kiez-site .kiez-person-contact a { min-height: 24px; display: inline-flex; align-items: center; }
  .kiez-site .tnp-field input[type="checkbox"],
  .kiez-site .wpcf7-acceptance input[type="checkbox"] { width: 20px; height: 20px; }
}

/* ---- Event registration (inc/rsvp.php, 2026-10-26) ------------------------
   One person per registration: the guest-count field of the RSVP form and
   the +/- counter of the attendee step are hidden (the count is also capped
   at 1 server-side, tribe_tickets_get_ticket_max_purchase). */
.kiez-site .tribe-tickets__form-field:has(> .tribe-tickets__rsvp-form-field-quantity),
.kiez-site .tribe-tickets__rsvp-ar-quantity { display: none !important; }
/* With one person there is nothing to list in the attendee step's sidebar
   (guest counter, guest list); the form takes the full width. The plugin
   loads its RSVP stylesheet lazily after ours, hence !important. */
.kiez-site .tribe-tickets__rsvp-ar-sidebar { display: none !important; }
.kiez-site .tribe-tickets__rsvp-ar-form { width: 100% !important; max-width: none !important; }
/* "Sie Sind Angemeldet": the plugin capitalises the success line. */
.kiez-site .tribe-tickets__rsvp-actions-success-going-text { text-transform: none !important; }

/* R5b (same day, after the re-sweep): the newsletter checkbox stayed 14px wide
   because the plugin caps it at max-width: 1em, and the contact-form checkbox
   stayed 18px because the theme's own selector is more specific. Sidebar list
   links and ghost buttons were 20–21px high. */
@media (max-width: 1024px) {
  .kiez-site .nl-form input[type="checkbox"],
  .kiez-site .tnp-subscription input[type="checkbox"] { width: 20px; height: 20px; max-width: none; }
  .kiez-site .contact-form .wpcf7-acceptance input[type="checkbox"] { width: 20px; height: 20px; }
  .kiez-site .side-list a { min-height: 24px; }
  .kiez-site .btn-ghost { min-height: 24px; }
}
/* No counters in the registration block (user, 2026-10-26): neither "1
   angemeldet" nor "19 Plätze frei". The "Ausgebucht" state is a separate
   element (.tribe-tickets__rsvp-actions-full) and stays visible. */
.kiez-site .tribe-tickets__rsvp-attendance,
.kiez-site .tribe-tickets__rsvp-availability { display: none !important; }

/* 2026-10-26 (user): the news-card body text (#8A79A3, site.css:115, 3.93:1 on
   white) looked different from the bento cards; same body colour everywhere. */
.kiez-site .news-card p { color: #776294; }

/* ==========================================================================
   Client list 2026-10-27
   ========================================================================== */

/* #1 Text selection on dark surfaces. site.css:36 gives the whole site a
   violet-25 selection with purple text; on purple surfaces that is purple on
   dark violet, unreadable. Dark surfaces: near-white selection, purple text.
   Orange buttons: purple selection, white text. Light surfaces unchanged. */
.kiez-site :is(.hero, .mission, .mission-item, .consortium, .nl-inner, .footer, .page-header, .bento-card.featured, .blog-card-dark, .side-block-cta, .kiez-block-dark, .kiez-people--purple, .kiez-nl-card, .kiez-roadmap--dark, .kiez-timeline--dark, .kiez-icon-dark, .kiez-highlight-dark, .kiez-bento-featured, .kiez-consortium, .kiez-cta, .kiez-topbar--dark, .nav-links.open) ::selection,
.kiez-site :is(.hero, .mission, .mission-item, .consortium, .nl-inner, .footer, .page-header, .bento-card.featured, .blog-card-dark, .side-block-cta, .kiez-block-dark, .kiez-people--purple, .kiez-nl-card, .kiez-roadmap--dark, .kiez-timeline--dark, .kiez-icon-dark, .kiez-highlight-dark, .kiez-bento-featured, .kiez-consortium, .kiez-cta, .kiez-topbar--dark, .nav-links.open)::selection {
  background: rgba(255, 255, 255, .92);
  color: var(--purple);
}
.kiez-site :is(.btn, .btn-fill, a.nav-cta, .nl-form button, .nl-form .tnp-submit, .contact-form input[type="submit"], .tnp-submit)::selection,
.kiez-site :is(.btn, .btn-fill, a.nav-cta, .nl-form button, .contact-form input[type="submit"]) ::selection {
  background: var(--purple);
  color: #fff;
}

/* #7 Card body text at least 16px on phones and tablets. Body copy is 17px
   (.post-body, .about-left p), but card paragraphs were 14–15px: news 14,
   field cards 15, newsletter 15, person 14, roadmap 14, timeline, compact
   blog and download 15, highlight 14. Desktop keeps the agency sizes.
   16px in the fields also stops iOS from zooming into them. */
@media (max-width: 1024px) {
  .kiez-site .news-card p,
  .kiez-site .bento-card > p,
  .kiez-site .nl-grid p,
  .kiez-site .kiez-person-text,
  .kiez-site .kiez-roadmap-text,
  .kiez-site .kiez-timeline-text,
  .kiez-site .kiez-blog-compact p,
  .kiez-site .kiez-dl-desc,
  .kiez-site .footer-brand p,
  .confera-body.kiez-site .kiez-bento-text,
  .confera-body.kiez-site .kiez-mission-text,
  .confera-body.kiez-site .kiez-highlight-text,
  .confera-body.kiez-site .kiez-cta-text { font-size: 16px; line-height: 1.6; }
  .kiez-site .ev .meta,
  .kiez-site .footer-copy { font-size: 15px; }
  .kiez-site .nl-form input:not([type="checkbox"]),
  .kiez-site .contact-form input:not([type="checkbox"]):not([type="submit"]),
  .kiez-site .contact-form textarea { font-size: 16px; }
}

/* #2/#4 Newsletter form: the privacy text toggles the box, only the word
   "Datenschutzerklärung" is a link; inline validation messages (site.js) on
   the dark card and on the light sidebar box. */
.kiez-site .nl-form .nl-privacy-text a { text-decoration: underline; text-underline-offset: 2px; }
.kiez-site .nl-form .nl-error {
  flex-basis: 100%;
  margin: 6px 0 0;
  font-size: 14px;
  line-height: 1.45;
  color: #FFD2BD;
}
.kiez-site .nl-form .nl-error--form { margin: 0 0 12px; padding: 10px 14px; border-radius: var(--r); background: rgba(255, 255, 255, .1); color: #fff; }
.kiez-site .nl-form .nl-error--form:focus { outline: 2px solid var(--orange); outline-offset: 2px; }
.kiez-site .nl-form input[aria-invalid="true"] { border-color: var(--orange) !important; }
.kiez-site .side-block .nl-form .nl-error { color: #B8431A; }
.kiez-site .side-block .nl-form .nl-error--form { background: rgba(236, 99, 41, .08); color: #B8431A; }

/* ==========================================================================
   Client list 2026-10-28, item 2: text contrast to WCAG AA (4.5:1)
   Measured before: footer copyright #6D578C 2.2:1, footer column labels
   #776294 2.5:1, mission text #9484AB 3.9:1, footer text #9E8FB3 4.5:1, event
   meta #9E8FB3 on white 3.0:1 — all fixed below.
   The brand orange #EC6329 as text on light surfaces (3.2:1) and as button
   background with white text (3.3:1) was darkened to #C2410C on 28 Oct and
   REVERTED the same day on the user's decision ("do 1": keep the brand
   colour, accept the rating). Document it in the accessibility statement
   under "nicht barrierefreie Inhalte".
   ========================================================================== */
.kiez-site { --text-on-dark-2: #C4B8DB; }

/* Secondary text on purple: 2.2–4.5:1 -> 7.1:1; column labels off-white (11.3:1). */
.kiez-site :is(.mission-body p, .footer-brand p, .footer-copy, .nl-grid p) { color: var(--text-on-dark-2); }
.kiez-site :is(.footer-col-label, .footer-partner-label) { color: var(--label-on-dark, #F4E8FF); }

/* Event meta (time, place) on white: 3.0:1 -> 5.8:1. */
.kiez-site .ev .meta { color: #6E5E88; }

/* ==========================================================================
   Client list 2026-10-28 (second list), item 1: KI:EZ News cards show the
   post's featured image. .has-media moves the card padding onto .news-body
   so the picture bleeds to the card edges under the rounded border overlay;
   text-only cards keep the old padding on the card itself.
   ========================================================================== */
.kiez-site .news-card.has-media { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.kiez-site .news-card.has-media .news-body { padding: 36px 30px; display: flex; flex-direction: column; flex: 1 1 auto; }
.kiez-site .news-card.has-media .news-body .link { margin-top: auto; padding-top: 18px; }
.kiez-site .news-card .news-media { flex: 0 0 auto; aspect-ratio: 16 / 9; overflow: hidden; background: var(--violet-10); }
.kiez-site .news-card .news-media img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .5s cubic-bezier(.22, 1, .36, 1); }
.kiez-site .news-card:hover .news-media img { transform: scale(1.04); }
@media (min-width: 1800px) { .kiez-site .news-card.has-media .news-body { padding: 50px 40px; } }
@media (max-width: 600px) { .kiez-site .news-card.has-media .news-body { padding: 28px 22px; } }
@media (prefers-reduced-motion: reduce) {
  .kiez-site .news-card .news-media img { transition: none; }
  .kiez-site .news-card:hover .news-media img { transform: none; }
}
