/* Global styles for the TDM Impact port (/k:port-identical).
   The original is the Claude Design export in _harvest/raw/design/. This file carries the
   original's global CSS VERBATIM (SPEC.md Part A1/A3), plus the template obligations
   (focus, sr-only, skip link) added so they do not change the measured look.
   Self-hosted fonts: public/fonts/*.otf, referenced with format('opentype') as in the source. */

@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('/fonts/CabinetGrotesk-Medium.otf') format('opentype');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('/fonts/CabinetGrotesk-Bold.otf') format('opentype');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('/fonts/CabinetGrotesk-Extrabold.otf') format('opentype');
  font-weight: 800;
  font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('/fonts/Satoshi-Light.otf') format('opentype');
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('/fonts/Satoshi-Regular.otf') format('opentype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('/fonts/Satoshi-Medium.otf') format('opentype');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('/fonts/Satoshi-Bold.otf') format('opentype');
  font-weight: 700;
  font-display: swap;
}

/* Brand palette — the original repeats these hex literals hundreds of times (SPEC A5).
   Custom properties are used only for values the original itself repeats (command rule). */
:root {
  --tdm-olive: #595a4a;
  --tdm-sand: #d8c3a5;
  --tdm-ink: #343434;
  --tdm-stone: #deddd9;
  --tdm-white: #ffffff;
  --tdm-paper: #f2f1f0;
  --tdm-sand-hover: #e6d8c5;
  --tdm-cream: #f3ede4;
  --tdm-olive-hover: #525246;
  --tdm-olive-active: #4a4b41;

  /* Template design tokens kept (mapped to the TDM palette) so the shared template components
     that read them — CookieTable, CookieBanner, ContactForm, .button-secondary — render on-brand.
     These are custom properties + class rules, so they do NOT enter the global element-rule
     parity block (which compares bare html/body/h1-h6/p/a/button/input). */
  --color-bg: #ffffff;
  --color-fg: #343434;
  --color-muted: rgba(52, 52, 52, 0.68);
  --color-accent: #595a4a;
  --color-border: #deddd9;
  --color-input-border: #767f91;
  --color-error: #dc2626;
  --color-success: #15803d;
  --font-sans: 'Satoshi', 'Helvetica Neue', Arial, sans-serif;
  --radius: 8px;
  --shadow-elevated: 0 8px 30px rgba(52, 52, 52, 0.18);
  --z-overlay: 1000;
  --content-width: 75rem;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
}

/* --- Original global CSS, verbatim (SPEC A1) --- */
html,
body {
  margin: 0;
  padding: 0;
  /* The original sets both height:100% and min-height:100% on html+body (compare global parity). */
  height: 100%;
  min-height: 100%;
  width: 100%;
  background: #ffffff;
  font-family: 'Satoshi', 'Helvetica Neue', Arial, sans-serif;
  color: #343434;
  -webkit-font-smoothing: antialiased;
}
* {
  box-sizing: border-box;
}
a {
  color: #595a4a;
  text-decoration: none;
}
a:hover {
  color: #343434;
}
h1,
h2,
h3,
h4 {
  text-wrap: balance;
  margin: 0;
}
p {
  margin: 0;
  text-wrap: pretty;
}
input,
textarea,
select,
button {
  font-family: inherit;
}

@keyframes tdm-marquee {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}
@keyframes tdm-draw {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}
@keyframes tdm-breathe {
  0%,
  100% {
    opacity: 0.5;
  }
  50% {
    opacity: 1;
  }
}
@keyframes tdm-spin {
  from {
    transform: rotate(0);
  }
  to {
    transform: rotate(360deg);
  }
}
@keyframes tdm-loop-dash {
  0%,
  100% {
    opacity: 0.5;
  }
  50% {
    opacity: 1;
  }
}
@keyframes tdm-bob {
  0%,
  100% {
    transform: translateY(-2px);
  }
  50% {
    transform: translateY(2px);
  }
}
@keyframes tdm-beam {
  from {
    stroke-dashoffset: 1000;
  }
  to {
    stroke-dashoffset: -90;
  }
}
@keyframes tdm-beam-v {
  from {
    stroke-dashoffset: 1000;
  }
  to {
    stroke-dashoffset: -90;
  }
}
@keyframes tdm-draw-path {
  from {
    stroke-dashoffset: 520;
  }
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes tdm-ping {
  0% {
    transform: scale(1);
    opacity: 0.5;
  }
  70%,
  100% {
    transform: scale(3);
    opacity: 0;
  }
}
@keyframes tdm-live {
  0%,
  100% {
    opacity: 0.35;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.35);
  }
}
@keyframes tdm-sheen {
  0% {
    transform: translateX(0);
  }
  55%,
  100% {
    transform: translateX(420%);
  }
}
@keyframes tdm-halo {
  0%,
  100% {
    opacity: 0.35;
    stroke-width: 8;
  }
  50% {
    opacity: 0.9;
    stroke-width: 11;
  }
}
@keyframes tdm-nudge {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(4px);
  }
}
@keyframes tdm-float {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-7px);
  }
}
@keyframes tdm-scroll-down {
  from {
    transform: translateY(-50%);
  }
  to {
    transform: translateY(0);
  }
}
/* austria-map.js pin ping */
@keyframes am-ping {
  0% {
    transform: scale(1);
    opacity: 0.5;
  }
  70%,
  100% {
    transform: scale(3);
    opacity: 0;
  }
}

@media (max-width: 768px) {
  .tdm-hero-puzzle {
    display: none !important;
  }
}

/* --- Template obligations, added so they do not change the measured look --- */

/* Screen-reader-only text: accessible names for icon-only / cursor:pointer controls that the
   original leaves nameless (command contract rule 6). Never affects layout. */
.sr-only {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Skip link — hidden until focused; sits above everything when a keyboard user tabs to it. */
.skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 10000;
  background: #595a4a;
  color: #fff;
  padding: 10px 16px;
  border-radius: 8px;
  font:
    500 14px/1.2 'Satoshi',
    'Helvetica Neue',
    Arial,
    sans-serif;
  transition: top 0.2s ease;
}
.skip-link:focus {
  top: 8px;
  color: #fff;
}

/* Visible keyboard focus (WCAG 2.4.7). The original has no focus style; we add one that does
   not change any element's box (outline + offset only follow the existing border-radius). */
:focus-visible {
  outline: 2px solid #595a4a;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Neutral secondary button kept for the cookie-policy settings control (template obligation). */
.button-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  font: inherit;
  font-weight: 500;
  font-size: 0.9rem;
  color: #343434;
  background: #f2f1f0;
  border: 1px solid #595a4a;
  border-radius: 8px;
  padding: 0.5rem 0.9rem;
  cursor: pointer;
}
.button-secondary[hidden] {
  display: none;
}
.cookie-table-wrap[data-astro-cid-tvfkjaz5] {
  overflow-x: auto;
}

.cookie-table[data-astro-cid-tvfkjaz5] {
  width: 100%;
  border-collapse: collapse;
  font-size: .85rem;
  text-align: left;
}

th[data-astro-cid-tvfkjaz5], td[data-astro-cid-tvfkjaz5] {
  padding: .4rem .6rem;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
  hyphens: auto;
  -webkit-hyphens: auto;
}

th[data-astro-cid-tvfkjaz5] {
  font-weight: 600;
  color: var(--color-muted);
  white-space: nowrap;
}

td[data-astro-cid-tvfkjaz5]:first-child, td[data-astro-cid-tvfkjaz5]:last-child {
  white-space: nowrap;
}

code[data-astro-cid-tvfkjaz5] {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .85em;
  overflow-wrap: anywhere;
}

.empty[data-astro-cid-tvfkjaz5] {
  color: var(--color-muted);
  font-style: italic;
}
.cc[data-astro-cid-hq3mgpmn] {
  position: fixed;
  inset: auto 1rem 1rem auto;
  z-index: var(--z-overlay);
  max-width: min(24rem, 100vw - 2rem);
  margin: 0;
}

.cc[data-astro-cid-hq3mgpmn][hidden] {
  display: none;
}

.cc-card[data-astro-cid-hq3mgpmn] {
  background: var(--color-bg);
  color: var(--color-fg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-elevated);
  padding: 1.1rem 1.2rem;
  max-height: calc(100vh - 2rem);
  max-height: calc(100dvh - 2rem);
  overflow-y: auto;
}

@media (prefers-reduced-motion: no-preference) {
  .cc-card[data-astro-cid-hq3mgpmn] {
    animation: .25s ease-out cc-in;
  }

  @keyframes cc-in {
    from {
      opacity: 0;
      transform: translateY(.75rem);
    }

    to {
      opacity: 1;
      transform: none;
    }
  }
}

.cc-title[data-astro-cid-hq3mgpmn] {
  margin: 0 0 .4rem;
  font-size: 1.05rem;
}

.cc-desc[data-astro-cid-hq3mgpmn] {
  margin: 0 0 .9rem;
  font-size: .9rem;
  color: var(--color-muted);
  text-align: justify;
  hyphens: auto;
}

.cc-manage[data-astro-cid-hq3mgpmn] {
  margin: 0 0 .9rem;
}

.cc-manage[data-astro-cid-hq3mgpmn][hidden] {
  display: none;
}

.cc-cats[data-astro-cid-hq3mgpmn] {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .8rem;
}

.cc-cat[data-astro-cid-hq3mgpmn] {
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: .6rem .7rem;
}

.cc-cat-head[data-astro-cid-hq3mgpmn] {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
}

.cc-switch[data-astro-cid-hq3mgpmn] {
  display: flex;
  align-items: center;
  min-height: 1.5rem;
  gap: .5rem;
  font-weight: 600;
  font-size: .9rem;
  cursor: pointer;
}

.cc-switch[data-astro-cid-hq3mgpmn] input[data-astro-cid-hq3mgpmn] {
  width: 1.1rem;
  height: 1.1rem;
  accent-color: var(--color-accent);
  cursor: pointer;
}

.cc-switch[data-astro-cid-hq3mgpmn] input[data-astro-cid-hq3mgpmn]:disabled {
  cursor: default;
}

.cc-always[data-astro-cid-hq3mgpmn] {
  font-weight: 400;
  font-style: normal;
  color: var(--color-muted);
}

.cc-expand[data-astro-cid-hq3mgpmn] {
  font: inherit;
  font-size: .8rem;
  background: none;
  border: 0;
  color: var(--color-accent);
  text-decoration: underline;
  cursor: pointer;
  padding: .25rem 0;
  white-space: nowrap;
}

.cc-cat-desc[data-astro-cid-hq3mgpmn] {
  margin: .4rem 0 0;
  font-size: .82rem;
  color: var(--color-muted);
}

.cc-tbl[data-astro-cid-hq3mgpmn] {
  margin-top: .5rem;
}

.cc-tbl[data-astro-cid-hq3mgpmn][hidden] {
  display: none;
}

.cc-links[data-astro-cid-hq3mgpmn] {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem .9rem;
  margin: 0 0 .9rem;
  font-size: .8rem;
}

.cc-links[data-astro-cid-hq3mgpmn] a[data-astro-cid-hq3mgpmn] {
  color: var(--color-muted);
}

.cc-actions[data-astro-cid-hq3mgpmn] {
  display: flex;
  gap: .5rem;
}

.cc-btn[data-astro-cid-hq3mgpmn] {
  flex: 1 1 0;
  min-width: 0;
  font: inherit;
  font-weight: 500;
  font-size: .9rem;
  border-radius: var(--radius);
  padding: .5rem .7rem;
  cursor: pointer;
  border: 1px solid var(--color-input-border);
}

.cc-primary[data-astro-cid-hq3mgpmn] {
  color: var(--color-on-accent, #fff);
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.cc-secondary[data-astro-cid-hq3mgpmn] {
  color: var(--color-fg);
  background: var(--color-bg);
}

.cc-btn[data-astro-cid-hq3mgpmn]:focus-visible, .cc-expand[data-astro-cid-hq3mgpmn]:focus-visible, .cc-switch[data-astro-cid-hq3mgpmn] input[data-astro-cid-hq3mgpmn]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

.cc-short[data-astro-cid-hq3mgpmn] {
  display: none;
}

.cc-fab[data-astro-cid-hq3mgpmn] {
  position: fixed;
  inset: auto 1rem calc(1rem + env(safe-area-inset-bottom, 0px)) auto;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--color-beige, var(--color-accent));
  border-radius: 999px;
  background: var(--color-navy, var(--color-fg));
  color: var(--color-beige, #fff);
  cursor: pointer;
}

.cc-fab[data-astro-cid-hq3mgpmn][hidden] {
  display: none;
}

.cc-fab[data-astro-cid-hq3mgpmn]:hover {
  background: color-mix(in srgb,
      var(--color-navy, var(--color-fg)) 88%,
      var(--color-beige, #fff));
}

.cc-fab[data-astro-cid-hq3mgpmn]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

@media (width <= 30rem) {
  .cc[data-astro-cid-hq3mgpmn] {
    inset: auto 0 0;
    max-width: none;
  }

  .cc-card[data-astro-cid-hq3mgpmn] {
    border-radius: var(--radius) var(--radius) 0 0;
    border-left: 0;
    border-right: 0;
    border-bottom: 0;
    padding: .6rem .9rem calc(.6rem + env(safe-area-inset-bottom, 0px));
    max-height: calc(100dvh - 4rem);
  }

  .cc-title[data-astro-cid-hq3mgpmn], .cc-desc[data-astro-cid-hq3mgpmn] {
    display: none;
  }

  .cc-short[data-astro-cid-hq3mgpmn] {
    display: block;
    margin: 0 0 .4rem;
    font-size: .85rem;
    font-weight: 600;
    color: var(--color-fg);
  }

  .cc-links[data-astro-cid-hq3mgpmn] a[data-astro-cid-hq3mgpmn]:not(.cc-link-essential) {
    display: none;
  }

  .cc-links[data-astro-cid-hq3mgpmn] {
    margin-bottom: .5rem;
    gap: 0 .75rem;
    font-size: .75rem;
  }

  .cc-btn[data-astro-cid-hq3mgpmn] {
    min-height: 44px;
    font-size: .7rem;
    padding-inline: .35rem;
  }

  .cc[data-astro-cid-hq3mgpmn][data-mode="manage"] .cc-title[data-astro-cid-hq3mgpmn], .cc[data-astro-cid-hq3mgpmn][data-mode="manage"] .cc-desc[data-astro-cid-hq3mgpmn] {
    display: block;
  }

  .cc[data-astro-cid-hq3mgpmn][data-mode="manage"] .cc-links[data-astro-cid-hq3mgpmn] a[data-astro-cid-hq3mgpmn] {
    display: inline;
  }

  .cc[data-astro-cid-hq3mgpmn][data-mode="manage"] .cc-short[data-astro-cid-hq3mgpmn] {
    display: none;
  }

  .cc[data-astro-cid-hq3mgpmn][data-mode="manage"] .cc-desc[data-astro-cid-hq3mgpmn] {
    text-align: left;
    font-size: .8rem;
    margin-bottom: .55rem;
  }
}
/* --- Edit bar — LETTER STYLE (2026-07-20): white canvas, navy #011936 ink, navy bottom edge,
     Montserrat. Replaces the legacy navy-band bar (retired #010223 + white-on-navy pills), so it
     now matches the relay mails and the Magic Edit drawer. Every control that lives IN the bar is
     restyled with it (.oe-edit, .oe-logout, .oe-snip-open); they were white-on-navy and would be
     invisible here.
     Order in the bar: label -> "Änderungen vornehmen" -> tools (LEFT group), logout pushed
     RIGHT via its own `margin-left: auto`. No `justify-content: space-between` — that spread all
     four items apart. `box-sizing: border-box` so the navy bottom border (and the horizontal
     padding) stay INSIDE the full-bleed sticky bar and can never cause horizontal overflow.

     SCHRAFFUR (2026-07-20, operator): the bar must read as CHROME, not as page content, so the
     white canvas carries a 45° navy hatch — 2px rgba(1,25,54,.085) rules every 8px. Two rules
     are load-bearing:
       * `background-color: #fff` stays SOLID under the gradient. The bar is `position: sticky`
         over arbitrary customer pages; a transparent base would let page content scroll through
         it. The hatch is painted as `background-image` ON TOP of that opaque base.
       * The alpha is capped so the DARKEST point of the hatch still clears WCAG 2.2 AA for
         everything in the bar. Composited over white, a stripe is rgb(233.4, 235.4, 237.9) —
         navy #011936 text on it scores 14.78:1 (AA body text needs 4.5:1), and the .oe-logout
         navy hairline scores the same against it (UI/non-text minimum 3:1). Between the stripes
         the base is pure white (17.59:1). Only 2 of every 8px is tinted, so it reads as texture
         rather than as a tint. The .oe-edit navy fill is opaque and sits ON the hatch, so its
         white label is unaffected (17.59:1). */
  .oe-banner {
    position: sticky;
    top: 0;
    z-index: 9999;
    box-sizing: border-box;
    width: 100%;
    display: flex;
    gap: 1rem;
    align-items: center;
    padding: 0.5rem 1rem;
    background-color: #fff;
    background-image: repeating-linear-gradient(
      45deg,
      rgba(1, 25, 54, 0.085) 0,
      rgba(1, 25, 54, 0.085) 2px,
      transparent 2px,
      transparent 8px
    );
    color: #011936;
    border-bottom: 2px solid #011936;
    font-family:
      Montserrat,
      system-ui,
      -apple-system,
      'Segoe UI',
      Roboto,
      sans-serif;
    font-size: 0.95rem;
  }
  /* Auskunft der Leiste, wenn der Inline-Editor nicht kommt (503: Store unlesbar, oder
     inline.diverged nach einem gescheiterten Overlay-Schreiben). Sie steht VOR dem
     Abmelden-Knopf, der über sein `margin-left: auto` rechts bleibt; `min-width: 0` lässt den
     Satz umbrechen, statt die Leiste zu verbreitern. Keine Signalfarbe: die Leiste ist Chrome,
     und der Satz ist ihre Auskunft, nicht ein Alarm über der Seite des Kunden. */
  .oe-banner__note {
    margin: 0;
    flex: 1 1 14rem;
    min-width: 0;
    font-size: 0.9rem;
  }
  /* Secondary/ghost on the white bar: navy text on white (17.6:1) inside a navy hairline
     (17.6:1 against white, well over the 3:1 UI minimum) — reads as a button without competing
     with the primary action. `margin-left: auto` keeps it right-aligned. */
  .oe-logout {
    margin-left: auto;
    background: transparent;
    color: #011936;
    border: 1px solid #011936;
    border-radius: 4px;
    padding: 0.35rem 0.9rem;
    font: inherit;
    cursor: pointer;
  }
  .oe-logout:hover {
    background: #f4f5f2;
  }
  /* --- Der unveröffentlichte Stand, rechts in der Leiste ------------------------------------
     Der Abstandhalter schluckt den freien Platz, damit die Gruppe auch dann rechts steht, wenn
     gerade nichts wartet (siehe die Stelle, an der sie gebaut wird). */
  .oe-spacer {
    flex: 1 1 auto;
  }
  .oe-pending {
    color: #5b5a52;
    font-size: 0.85rem;
    white-space: nowrap;
  }
  .oe-publish,
  .oe-reset {
    flex-shrink: 0;
    border-radius: 4px;
    padding: 0.35rem 0.9rem;
    font: inherit;
    cursor: pointer;
  }
  .oe-publish {
    background: #011936;
    color: #fff;
    border: 1px solid #011936;
    font-weight: 700;
  }
  .oe-publish:hover {
    background: #0a2b52;
  }
  .oe-reset {
    background: transparent;
    color: #011936;
    border: 1px solid #cdc6a5;
  }
  .oe-reset:hover {
    background: #f4f5f2;
  }
  .oe-publish:disabled,
  .oe-reset:disabled {
    opacity: 0.55;
    cursor: default;
  }
  /* LOAD-BEARING: ein eigenes display schlägt das UA-[hidden]; dieselbe Falle wie bei .oe-ih
     und .oe-spin. Ohne diese drei Regeln stünden die Knöpfe immer da. */
  .oe-pending[hidden],
  .oe-publish[hidden],
  .oe-reset[hidden] {
    display: none;
  }
  /* "Bearbeiten" — opens the Magic Edit drawer, and the bar's PRIMARY action: navy fill, white
     label (17.6:1), with an inline pencil (no icon font / external asset: the site is
     self-contained). `flex-shrink: 0` keeps it whole when the banner text wraps. */
  .oe-edit {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    gap: 0.4rem;
    background: #011936;
    color: #fff;
    border: 0;
    border-radius: 4px;
    padding: 0.35rem 0.9rem;
    font: inherit;
    font-weight: 700;
    cursor: pointer;
  }
  .oe-edit:hover {
    background: #0a2c52;
  }
  /* Wartet etwas auf Veröffentlichung, tritt der Chat zurück: dann ist ER nicht mehr der
     nächste Schritt, sondern das Veröffentlichen. Zwei gefüllte Knöpfe in einer Leiste sagen
     nichts mehr darüber, was dran ist. */
  .oe-edit--quiet {
    background: transparent;
    color: #011936;
    border: 1px solid #cdc6a5;
    font-weight: 400;
  }
  .oe-edit--quiet:hover {
    background: #f4f5f2;
  }
  /* Der Schalter für die Griffe: ein Symbolknopf in derselben Höhe wie seine Nachbarn,
     direkt nach dem Chat-Knopf. */
  .oe-ihtoggle {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    color: #011936;
    background: transparent;
    border: 1px solid #cdc6a5;
    border-radius: 4px;
    cursor: pointer;
  }
  .oe-ihtoggle:hover {
    background: #f4f5f2;
    border-color: #011936;
  }
  .oe-ihtoggle[aria-pressed='true'] {
    color: #5b5a52;
  }
  .oe-ihtoggle:focus-visible {
    outline: 2px solid #011936;
    outline-offset: 2px;
  }
  .oe-ihtoggle[hidden] {
    display: none;
  }
  .oe-edit:focus-visible,
  .oe-logout:focus-visible {
    outline: 2px solid #011936;
    outline-offset: 2px;
  }
  .oe-uploader {
    margin: 0 0 1.5rem;
    padding: 1rem 1.1rem 1.15rem;
    border: 2px dashed #3a6ea5;
    border-radius: 10px;
    background: #e7f0fb;
    box-shadow: 0 6px 22px rgba(1, 2, 35, 0.14);
  }
  /* Editor-only marker pill — dark on the tinted panel so the whole block reads as a tool
     that visitors never see, clearly distinct from page content. */
  .oe-uploader__flag {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0 0.8rem;
    padding: 0.26rem 0.65rem;
    background: #010223;
    color: #fff;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
  }
  .oe-uploader__flag::before {
    content: '🔒';
    font-size: 0.8rem;
  }
  .oe-uploader__label {
    margin: 0 0 0.6rem;
    font-weight: 700;
    font-size: 0.98rem;
    color: #010223;
  }
  .oe-uploader__hint {
    margin: 0.6rem 0 0;
    font-size: 0.85rem;
    color: #3a4a5f;
  }
  .oe-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 1rem;
    background: #3a6ea5;
    color: #fff;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.95rem;
  }
  .oe-btn:focus-within {
    outline: 3px solid #010223;
    outline-offset: 2px;
  }
  .oe-file {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    overflow: hidden;
  }
  /* Upload busy state (operator 2026-07-24): picker dimmed + unclickable, spinner beside it. */
  .oe-btn--busy {
    opacity: 0.55;
    pointer-events: none;
  }
  /* Demo: upload budget spent — same dimmed, unclickable treatment; the hint below the button
     says why, and the chat Überarbeitungen stay usable (separate budget, 2026-07-25). */
  .oe-btn--off {
    opacity: 0.55;
    pointer-events: none;
  }
  .oe-btn--req {
    background: #011936;
    margin-top: 0.5rem;
  }

  /* ── Demo-Limit-Modal: persönliche Demo anfragen ──────────────────────────────────────
     Nur auf Demo-Scopes erreichbar. Markenfarben wie der Drawer (Navy #011936 auf Weiß,
     beige Hairline), kein Cream-Band — Briefstil wie alle transaktionalen Flächen. */
  .oe-modal {
    position: fixed;
    inset: 0;
    z-index: 2147483646;
    background: rgba(1, 25, 54, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
  }
  .oe-modal__box {
    position: relative;
    width: min(30rem, 100%);
    max-height: 90vh;
    overflow-y: auto;
    background: #fff;
    color: #011936;
    border-top: 3px solid #011936;
    border-radius: 8px;
    padding: 1.5rem 1.5rem 1.25rem;
    box-shadow: 0 18px 48px rgba(1, 25, 54, 0.28);
    font-family:
      Montserrat,
      system-ui,
      -apple-system,
      'Segoe UI',
      Roboto,
      Arial,
      sans-serif;
  }
  .oe-modal__x {
    position: absolute;
    top: 0.5rem;
    right: 0.65rem;
    border: 0;
    background: none;
    color: #5b5a52;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
  }
  .oe-modal__title {
    margin: 0 0 0.5rem;
    font-size: 1.2rem;
    font-weight: 700;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid #cdc6a5;
  }
  .oe-modal__lead {
    margin: 0 0 1rem;
    font-size: 0.95rem;
    line-height: 1.5;
  }
  .oe-modal__field {
    display: block;
    margin-bottom: 0.75rem;
    font-size: 0.85rem;
    font-weight: 600;
  }
  .oe-modal__field input,
  .oe-modal__field textarea {
    display: block;
    width: 100%;
    margin-top: 0.25rem;
    padding: 0.55rem 0.7rem;
    font: inherit;
    font-weight: 400;
    color: #011936;
    background: #fff;
    border: 1px solid #7d7a6c;
    border-radius: 6px;
  }
  .oe-modal__field textarea {
    resize: vertical;
    min-height: 4.5rem;
  }
  .oe-modal__field input:focus-visible,
  .oe-modal__field textarea:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 1px;
  }
  .oe-modal__consent {
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
    margin: 0.25rem 0 1rem;
    font-size: 0.78rem;
    line-height: 1.45;
    color: #5b5a52;
  }
  .oe-modal__consent input {
    margin-top: 0.2rem;
    flex: 0 0 auto;
  }
  .oe-modal__consent a {
    color: #011936;
    text-decoration: underline;
  }
  .oe-modal__ts {
    margin-bottom: 0.5rem;
  }
  .oe-modal__send {
    display: block;
    width: 100%;
    padding: 0.7rem 1rem;
    font: inherit;
    font-weight: 600;
    color: #fff;
    background: #011936;
    border: 0;
    border-radius: 6px;
    cursor: pointer;
  }
  .oe-modal__send:hover {
    background: #0a2c52;
  }
  .oe-modal__send:disabled {
    opacity: 0.55;
    cursor: default;
  }
  .oe-modal__status {
    margin: 0.75rem 0 0;
    font-size: 0.88rem;
    line-height: 1.5;
  }
  .oe-modal__status.is-error {
    color: #b42318;
  }
  .oe-spin {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    margin-left: 0.5rem;
    vertical-align: -0.2rem;
    border: 2px solid rgba(1, 25, 54, 0.25);
    border-top-color: #011936;
    border-radius: 50%;
    animation: oe-spin 0.8s linear infinite;
  }
  /* LOAD-BEARING: `display: inline-block` oben schlägt sonst das UA-`display: none`
     des hidden-Attributs — der Spinner drehte dann schon beim Seitenaufbau
     (Operator-Fund 2026-07-24). */
  .oe-spin[hidden] {
    display: none;
  }
  @keyframes oe-spin {
    to {
      transform: rotate(360deg);
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .oe-spin {
      animation-duration: 2.4s;
    }
  }
  .oe-status {
    margin: 0.5rem 0 0;
    font-size: 0.9rem;
  }
  @media (prefers-reduced-motion: reduce) {
    .oe-banner {
      position: static;
    }
  }

  /* ── Statistik einbinden / Skript einbinden: Navbar-Buttons + Verwaltungs-Modal. Gleiche
     Palette wie Bar und Modal (Navy #011936 auf Weiß, beige Hairline #cdc6a5, Montserrat).
     Die Navbar-Buttons sind Ghost und kompakt, damit die Bar auf schmalen Screens nicht
     überquillt. ── */
  .oe-snip-open {
    background: transparent;
    color: #011936;
    border: 1px solid #011936;
    border-radius: 4px;
    padding: 0.3rem 0.75rem;
    font: inherit;
    font-size: 0.85rem;
    cursor: pointer;
    flex-shrink: 0;
  }
  .oe-snip-open:hover {
    background: #f4f5f2;
  }
  .oe-snip-open:focus-visible {
    outline: 2px solid #011936;
    outline-offset: 2px;
  }
  .oe-modal__box--wide {
    width: min(38rem, 100%);
  }
  .oe-snip__list {
    margin: 0 0 1rem;
  }
  .oe-snip__empty {
    margin: 0 0 1rem;
    font-size: 0.9rem;
    color: #5b5a52;
  }
  .oe-snip__item {
    border: 1px solid #cdc6a5;
    border-radius: 6px;
    margin-bottom: 0.5rem;
    overflow: hidden;
  }
  .oe-snip__head {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0.6rem 0.75rem;
    font: inherit;
    font-weight: 600;
    color: #011936;
    background: #fff;
    border: 0;
    cursor: pointer;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .oe-snip__head:hover {
    background: #f4f5f2;
  }
  .oe-snip__head[aria-expanded='true'] {
    border-bottom: 1px solid #cdc6a5;
  }
  .oe-snip__head:focus-visible {
    outline: 3px solid #011936;
    outline-offset: -3px;
  }
  .oe-snip__head:disabled {
    opacity: 0.55;
    cursor: default;
  }
  .oe-snip__body {
    padding: 0.75rem;
  }
  .oe-snip__ta {
    display: block;
    width: 100%;
    box-sizing: border-box;
    margin-top: 0.25rem;
    padding: 0.55rem 0.7rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.82rem;
    font-weight: 400;
    line-height: 1.45;
    color: #011936;
    background: #fff;
    border: 1px solid #7d7a6c;
    border-radius: 6px;
    resize: vertical;
  }
  .oe-snip__ta:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 1px;
  }
  .oe-snip__select {
    display: block;
    width: 100%;
    margin-top: 0.25rem;
    padding: 0.5rem 0.7rem;
    font: inherit;
    font-weight: 400;
    color: #011936;
    background: #fff;
    border: 1px solid #7d7a6c;
    border-radius: 6px;
  }
  .oe-snip__select:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 1px;
  }
  .oe-snip__actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-top: 0.75rem;
  }
  .oe-snip__actions button {
    padding: 0.5rem 0.9rem;
    font: inherit;
    font-weight: 600;
    border-radius: 6px;
    cursor: pointer;
  }
  /* Der PRIMÄRE Knopf jedes Dialogs. Geometrie und Schrift stehen HIER und nicht nur in
     `.oe-snip__actions button`: im Textmodal des Inline-Editors sitzt Übernehmen in
     `.oe-snip__foot`, hat die Regel dort also nie erreicht und stand als farbige Fläche ohne
     Innenabstand da. Der Betreiber hat ihn folgerichtig nicht für einen Knopf gehalten. */
  .oe-snip__save {
    padding: 0.5rem 0.9rem;
    font: inherit;
    font-weight: 700;
    color: #fff;
    background: #011936;
    border: 0;
    border-radius: 6px;
    cursor: pointer;
  }
  .oe-snip__save:hover {
    background: #0a2c52;
  }
  .oe-snip__save:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 2px;
  }
  .oe-snip__save:disabled {
    opacity: 0.55;
    cursor: default;
  }
  /* In den Snippet-Dialogen sitzt er in `.oe-snip__actions`, und deren Regel für JEDEN Knopf
     darin ist spezifischer. Ohne diese Zeile trüge der primäre Knopf dort dasselbe
     Schriftgewicht wie "Abbrechen" daneben. */
  .oe-snip__actions .oe-snip__save {
    font-weight: 700;
  }
  .oe-snip__ghost {
    color: #011936;
    background: #fff;
    border: 1px solid #7d7a6c;
  }
  .oe-snip__ghost:hover {
    background: #f4f5f2;
  }
  .oe-snip__rm {
    color: #b42318;
    background: #fff;
    border: 1px solid #7d7a6c;
    margin-left: auto;
  }
  .oe-snip__rm:hover {
    background: #f4f5f2;
  }
  .oe-snip__actions button:disabled {
    opacity: 0.55;
    cursor: default;
  }
  .oe-snip__actions button:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 2px;
  }
  .oe-snip__foot {
    display: flex;
    gap: 0.5rem;
    align-items: center;
  }
  /* LOAD-BEARING: eigenes display schlägt das UA-[hidden]; siehe .oe-spin oben. */
  .oe-snip__foot[hidden] {
    display: none;
  }
  .oe-snip__add {
    padding: 0.5rem 0.9rem;
    font: inherit;
    font-weight: 600;
    color: #011936;
    background: #fff;
    border: 1px solid #011936;
    border-radius: 6px;
    cursor: pointer;
  }
  .oe-snip__add:hover {
    background: #f4f5f2;
  }
  .oe-snip__add[hidden] {
    display: none;
  }
  .oe-snip__add:disabled {
    opacity: 0.55;
    cursor: default;
  }
  .oe-snip__add:focus-visible,
  .oe-snip__close:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 2px;
  }
  .oe-snip__close {
    margin-left: auto;
    padding: 0.5rem 0.9rem;
    font: inherit;
    font-weight: 600;
    color: #011936;
    background: #fff;
    border: 1px solid #7d7a6c;
    border-radius: 6px;
    cursor: pointer;
  }
  .oe-snip__close:hover {
    background: #f4f5f2;
  }
  .oe-snip__close:disabled {
    opacity: 0.55;
    cursor: default;
  }
  .oe-modal__status a {
    color: #011936;
    text-decoration: underline;
  }
  /* Die Kopfzeile eines Eintrags: Name, darunter Anbieter, Kategorie und ob er nach
     Zustimmung lädt. Grau #5b5a52 auf Weiß: 6.9:1. */
  .oe-svc__title,
  .oe-svc__meta {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .oe-svc__meta {
    margin-top: 0.15rem;
    font-size: 0.8rem;
    font-weight: 400;
    color: #5b5a52;
  }
  .oe-svc__static {
    cursor: default;
  }
  .oe-svc__static:hover {
    background: #fff;
  }
  .oe-svc__help {
    margin: 0.25rem 0 0.75rem;
    font-size: 0.82rem;
    line-height: 1.45;
    color: #5b5a52;
  }
  /* Der Satz zur Haftung, wenn der Dienst ohne Zustimmung lädt: Rot #b42318 auf Weiß, 6.4:1. */
  .oe-svc__help.is-warn {
    color: #b42318;
    font-weight: 600;
  }
  .oe-svc__help[hidden] {
    display: none;
  }
  .oe-svc__consent {
    margin: 0.25rem 0 0.75rem;
  }
  .oe-svc__switch {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-height: 2rem;
    font-size: 0.9rem;
    font-weight: 600;
  }
  /* LOAD-BEARING: display:flex oben schlägt sonst das UA-[hidden] (der Haken zur Prüfung). */
  .oe-svc__switch[hidden] {
    display: none;
  }
  .oe-svc__switch input {
    width: 1.25rem;
    height: 1.25rem;
    margin: 0;
    accent-color: #011936;
    flex: 0 0 auto;
  }
  .oe-svc__switch input:focus-visible,
  .oe-svc__radio input:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 2px;
  }
  .oe-svc__adv {
    margin: 0.5rem 0 0.25rem;
    border-top: 1px solid #cdc6a5;
    padding-top: 0.5rem;
  }
  .oe-svc__adv > summary {
    min-height: 1.75rem;
    padding: 0.2rem 0;
    font-size: 0.9rem;
    font-weight: 600;
    color: #011936;
    cursor: pointer;
  }
  .oe-svc__adv > summary:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 2px;
  }
  .oe-svc__adv[open] > summary {
    margin-bottom: 0.5rem;
  }
  .oe-svc__fs {
    margin: 0 0 0.75rem;
    padding: 0.6rem 0.75rem;
    border: 1px solid #cdc6a5;
    border-radius: 6px;
  }
  /* Die Angaben einer Vorlage, nur zum Lesen. */
  .oe-svc__facts {
    display: grid;
    grid-template-columns: minmax(7rem, max-content) 1fr;
    gap: 0.25rem 0.75rem;
    margin: 0;
    font-size: 0.85rem;
  }
  .oe-svc__facts dt {
    font-weight: 600;
  }
  .oe-svc__facts dd {
    margin: 0;
    overflow-wrap: anywhere;
  }
  .oe-svc__fs > legend {
    padding: 0 0.25rem;
    font-size: 0.85rem;
    font-weight: 600;
  }
  .oe-svc__radio {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 1.75rem;
    font-size: 0.88rem;
  }
  .oe-svc__radio input {
    width: 1.1rem;
    height: 1.1rem;
    margin: 0;
    accent-color: #011936;
    flex: 0 0 auto;
  }
  .oe-modal__field[hidden] {
    display: none;
  }

  /* ── Dienste für BESUCHER: der Platzhalter eines Dienstes, der auf die Zustimmung wartet.
     Er sitzt mitten in der Seite des Kunden und nimmt deshalb deren Farben: Text und Grund
     aus --color-fg / --color-bg (das Paar trägt den Fließtext der Site, sein Kontrast ist
     derselbe), die Rückfallwerte sind die der Vorlage. Der gefüllte Knopf kehrt das Paar um.
     Knöpfe 44px hoch (WCAG 2.5.8 verlangt 24px), sichtbarer Fokus. ── */
  .kaino-svc-ph {
    box-sizing: border-box;
    max-width: 100%;
    margin: 1rem 0;
    padding: 1rem 1.1rem;
    color: var(--color-fg, #1e293b);
    background: var(--color-bg, #f8fafc);
    border: 1px solid var(--color-input-border, #767f91);
    border-radius: var(--radius, 8px);
    font: inherit;
    line-height: 1.5;
  }
  .kaino-svc-ph__text {
    margin: 0 0 0.75rem;
  }
  .kaino-svc-ph__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
  }
  .kaino-svc-ph__btn {
    min-height: 2.75rem;
    padding: 0.5rem 1rem;
    font: inherit;
    font-weight: 600;
    color: var(--color-fg, #1e293b);
    background: transparent;
    border: 1px solid currentColor;
    border-radius: var(--radius, 8px);
    cursor: pointer;
  }
  .kaino-svc-ph__btn--pri {
    color: var(--color-bg, #f8fafc);
    background: var(--color-fg, #1e293b);
    border-color: var(--color-fg, #1e293b);
  }
  .kaino-svc-ph__btn:focus-visible {
    outline: 2px solid var(--color-fg, #1e293b);
    outline-offset: 2px;
  }

  /* ── Inline-Editor: die Griff-Ebene ────────────────────────────────────────────────────
     Die Griffe liegen in einer EIGENEN position:fixed-Ebene, nicht im DOM des Bereichs, und
     werden aus getBoundingClientRect() gesetzt. Ein umschliessendes <span> oder eine
     zusätzliche Klasse am Bereich bräche Regeln wie `.gallery > img` und Astros scoped
     styles; der Bereich trägt deshalb nur ein data-Attribut.
     Die z-Ebene liegt UNTER der Conversion-Leiste (2147483000) und unter dem minimierten
     Magic-Edit-Drawer: ein Griff, der über dem Kassen-Fenster klebt, stiehlt dessen Klicks.
     Palette wie die Bar: Navy #011936 auf Weiß mit beiger Haarlinie #cdc6a5. ── */
  .oe-ih-layer {
    position: fixed;
    inset: 0;
    z-index: 2147482500;
    pointer-events: none;
  }
  .oe-ih {
    position: absolute;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    pointer-events: auto;
    color: #011936;
    background: #fff;
    border: 1px solid #cdc6a5;
    border-radius: 6px;
    box-shadow: 0 2px 8px rgba(1, 25, 54, 0.25);
    cursor: pointer;
  }
  /* LOAD-BEARING: eigenes display schlägt das UA-[hidden]; siehe .oe-spin oben. */
  .oe-ih[hidden] {
    display: none;
  }
  .oe-ih:hover {
    background: #f4f5f2;
  }
  .oe-ih:focus-visible {
    outline: 2px solid #011936;
    outline-offset: 2px;
  }
  /* Die Griffe blenden EINMAL ein und bleiben dann stehen (Operator 19.09.2026). Vorher
     pulsierten sie dauernd; auf einer Seite mit 72 Griffen flackert dann die ganze Seite.
     Die Animation läuft auf der EBENE, nicht auf den Griffen: ein Griff wird beim Scrollen
     laufend versteckt und wieder gezeigt, und display:none startet jede Animation an ihm neu,
     also fiele das Einblenden bei jedem Scrollen wieder an. */
  @keyframes oe-ih-in {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
  .oe-ih-layer {
    animation: oe-ih-in 0.5s ease-out both;
  }
  @media (prefers-reduced-motion: reduce) {
    .oe-ih-layer {
      animation: none;
    }
  }
  /* Der Schalter in der Leiste blendet sie weg, ohne sie abzubauen: die Ebene ist dann nur
     nicht da, und jeder Griff steht beim Wiedereinblenden an seiner Stelle. */
  .oe-ih-layer[hidden] {
    display: none;
  }
  /* Die Umrandung des Elements, das der Griff unter dem Zeiger ändert. Liegt in der
     Griff-Ebene, fasst nichts an und nimmt keine Klicks. */
  .oe-ih-box {
    position: absolute;
    pointer-events: none;
    border: 2px solid #cdc6a5;
    border-radius: 6px;
    box-shadow: 0 0 0 9999px rgba(1, 25, 54, 0.04);
    transition: opacity 0.12s ease-in-out;
  }
  .oe-ih-box[hidden] {
    display: none;
  }
  /* Läuft ein Upload, trägt der Griff den Spinner: das Modal darf zu sein, und der Besitzer
     soll trotzdem sehen, dass etwas arbeitet. */
  .oe-ih--busy svg {
    display: none;
  }
  .oe-ih--busy::after {
    content: '';
    width: 14px;
    height: 14px;
    border: 2px solid #cdc6a5;
    border-top-color: #011936;
    border-radius: 50%;
    animation: oe-spin 0.8s linear infinite;
  }

  /* Die Modale des Inline-Editors benutzen die vorhandenen Klassen; nur ihre Anordnung ist
     neu: eine Zeile aus Textfeld und Minus, ein Knopf über die volle Breite, und ein Raster
     für die Mediathek. */
  .oe-ie__add {
    display: block;
    width: 100%;
    margin-bottom: 1rem;
  }
  .oe-ie__row {
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
    padding: 0.5rem 0.6rem;
  }
  .oe-ie__row > .oe-modal__field {
    flex: 1 1 auto;
    min-width: 0;
    margin-bottom: 0;
  }
  .oe-ie__minus {
    flex: 0 0 auto;
    margin-top: 0.25rem;
    padding: 0.5rem 0.75rem;
    font: inherit;
    font-weight: 700;
    color: #b42318;
    background: #fff;
    border: 1px solid #7d7a6c;
    border-radius: 6px;
    cursor: pointer;
  }
  .oe-ie__minus:disabled {
    opacity: 0.45;
    cursor: default;
  }
  .oe-ie__minus:focus-visible,
  .oe-ie__pick:focus-visible,
  .oe-ie__del:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 2px;
  }
  /* LOAD-BEARING: .oe-snip__actions bringt display:flex mit und schlägt damit das UA-[hidden];
     die Wiederholzeile stünde sonst immer da. Siehe .oe-spin und .oe-snip__foot oben. */
  .oe-ie__retry[hidden] {
    display: none;
  }
  .oe-ie__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
    gap: 0.5rem;
    margin-bottom: 1rem;
  }
  .oe-ie__tile {
    position: relative;
  }
  .oe-ie__pick {
    display: block;
    width: 100%;
    padding: 0;
    background: #fff;
    border: 1px solid #cdc6a5;
    border-radius: 6px;
    overflow: hidden;
    cursor: pointer;
  }
  .oe-ie__pick img {
    display: block;
    width: 100%;
    height: 5rem;
    object-fit: cover;
  }
  .oe-ie__del {
    position: absolute;
    top: 0.2rem;
    right: 0.2rem;
    width: 1.5rem;
    height: 1.5rem;
    padding: 0;
    line-height: 1;
    color: #011936;
    background: #fff;
    border: 1px solid #cdc6a5;
    border-radius: 4px;
    cursor: pointer;
  }
  .oe-ie__del:hover {
    color: #b42318;
  }
  /* Arbeitszustand (Operator 19.09.2026: „we need loading spinners while uploading/processing,
     and disabling buttons / elements while busy"). Was abgeschaltet ist, sieht man auch: vorher
     war der Übernehmen-Knopf zwar `disabled`, aber unverändert dunkelblau, und die Kacheln der
     Mediathek nahmen Klicks entgegen, die nichts bewirkten. */
  .oe-snip__save:disabled,
  .oe-ie__pick:disabled,
  .oe-ie__del:disabled {
    opacity: 0.55;
    cursor: default;
  }
  .oe-ih:disabled {
    cursor: default;
  }
  /* Meldung und Spinner in einer Zeile: das ist die Stelle, die arbeitet. */
  .oe-ie__work {
    display: flex;
    align-items: center;
    gap: 0.25rem;
  }
  /* Der Spinner auf der Kachel des Bildes, das gerade hochgeladen wird. */
  .oe-ie__veil {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.72);
    border-radius: 6px;
    pointer-events: none;
  }
  .oe-ie__veil .oe-spin {
    margin-left: 0;
  }

  /* --- Magic Edit drawer — LETTER STYLE (navy #011936, white, beige #cdc6a5 hairline,
     Montserrat). Same palette as the edit bar above, which joined it 2026-07-20. Retired
     colours (#010223 / #3a6ea5) survive only in the in-page .oe-uploader / .oe-btn / .oe-status
     surfaces below — outstanding debt, not the bar. --- */
  .me-strip {
    position: sticky;
    top: 0;
    z-index: 10000;
    padding: 0.5rem 1rem;
    font-family:
      Montserrat,
      system-ui,
      -apple-system,
      'Segoe UI',
      Roboto,
      sans-serif;
    font-size: 0.9rem;
    font-weight: 600;
    text-align: center;
  }
  .me-strip--preview {
    background: #011936;
    color: #fff;
  }
  .me-strip--published {
    background: #fff;
    color: #011936;
    border-bottom: 1px solid #cdc6a5;
  }
  /* The floating handle is gone (2026-07-20): the panel IS the drawer, opened only by the
     external triggers. .me-drawer stays the fixed positioning context — TOP-LEFT on desktop
     (operator 2026-07-22: 3px in from the corner, dropped below the sticky top chrome via the
     JS-measured --me-top; still off the right edge, where the preview conversion overlay is a
     right-edge, vertically-centered drawer) — but is pointer-transparent so the (zero-height)
     wrapper never shadows the page while the panel is hidden; the panel itself takes pointer
     events back. z-index sits deliberately ABOVE the conversion overlay's 2147483000 drawer
     and 2147483001 modal (web-hosting/webs-overlay/overlay.css — shadow DOM, but its fixed
     elements stack in the viewport): the chat must win (operator 2026-07-22). No integer fits
     between the overlay's two values, so the chat is above its checkout modal too. */
  .me-drawer {
    position: fixed;
    left: 3px;
    top: var(--me-top, 3px);
    z-index: 2147483100;
    width: min(400px, calc(100vw - 6px));
    font-family:
      Montserrat,
      system-ui,
      -apple-system,
      'Segoe UI',
      Roboto,
      sans-serif;
    color: #011936;
    pointer-events: none;
  }
  /* The desktop height cap arrived with top-anchoring: a bottom-anchored panel that outgrew
     the viewport clipped its (recoverable) header, a top-anchored one would push the textarea
     and Senden below the fold with no way to scroll them back. --me-top inherits from
     .me-drawer. The ≤640px sheet keeps its own 85vh cap below. */
  .me-panel {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    max-height: calc(100vh - var(--me-top, 3px) - 6px);
    overflow-y: auto;
    background: #fff;
    border: 1px solid #dcdacd;
    border-radius: 10px;
    padding: 0.85rem;
    box-shadow: 0 6px 22px rgba(1, 25, 54, 0.22);
    pointer-events: auto;
  }
  /* Letter style: band-free white header, navy title, closed by the beige hairline. The
     negative margins pull it flush to the panel edges through the panel's own padding. */
  /* Also the DRAG HANDLE (desktop): `touch-action: none` hands touch drags to the pointer
     listeners instead of the page scroller, `user-select: none` stops the title/quota text
     from being selected while dragging. The log + textarea keep normal selection — only the
     header initiates a drag. */
  .me-head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: -0.85rem -0.85rem 0;
    padding: 0.6rem 0.85rem;
    border-bottom: 1px solid #cdc6a5;
    cursor: move;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
  }
  .me-head__title {
    flex: 1 1 auto;
    font-weight: 700;
    font-size: 0.95rem;
  }
  .me-quota {
    font-size: 0.78rem;
    font-weight: 600;
    color: #5b5a52;
  }
  /* Close × — ghost navy on the white header. Sits after the quota badge; DRAG_IGNORE lists
     `button`, so pressing it never starts a header drag. */
  .me-close {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    background: transparent;
    color: #011936;
    border: 1px solid #cdc6a5;
    border-radius: 6px;
    font: inherit;
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
  }
  .me-close:hover {
    background: #f4f5f2;
    border-color: #011936;
  }
  .me-close:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 2px;
  }
  .me-log {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-height: 46vh;
    overflow-y: auto;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid #cdc6a5;
  }
  .me-msg {
    margin: 0;
    padding: 0.45rem 0.65rem;
    border-radius: 8px;
    font-size: 0.9rem;
    line-height: 1.5;
    white-space: pre-wrap;
  }
  .me-msg--user {
    align-self: flex-end;
    max-width: 85%;
    background: #011936;
    color: #fff;
  }
  .me-msg--bot {
    align-self: flex-start;
    max-width: 90%;
    background: #f4f5f2;
    color: #011936;
  }
  .me-msg--sys {
    align-self: center;
    text-align: center;
    font-size: 0.82rem;
    color: #5b5a52;
  }
  .me-status {
    margin: 0;
    min-height: 1.1em;
    font-size: 0.85rem;
    color: #5b5a52;
  }
  /* Failures are RED (operator 2026-07-29) — the brand error colour, which clears WCAG AA on the
     white panel. Muted grey made "Das hat nicht geklappt" read like ordinary progress text. */
  .me-status--err {
    color: #b42318;
    font-weight: 600;
  }
  /* Session-expired notice — rendered ONCE and only toggled, so its re-login link stays clickable
     (it used to be rebuilt every 1.5 s). The explicit [hidden] rule mirrors .me-panel/.me-actions
     below: an author `display` declaration would otherwise beat the UA's `[hidden]`. */
  .me-expired {
    margin: 0;
    font-size: 0.85rem;
    color: #011936;
  }
  .me-expired[hidden] {
    display: none;
  }
  .me-expired a {
    color: #011936;
    font-weight: 700;
  }
  .me-running .me-status::before {
    content: '';
    display: inline-block;
    width: 0.7em;
    height: 0.7em;
    margin-right: 0.45em;
    border: 2px solid #cdc6a5;
    border-top-color: #011936;
    border-radius: 50%;
    vertical-align: -1px;
    animation: me-spin 0.8s linear infinite;
  }
  @keyframes me-spin {
    to {
      transform: rotate(360deg);
    }
  }
  .me-ta {
    width: 100%;
    box-sizing: border-box;
    min-height: 3.2em;
    resize: vertical;
    padding: 0.5rem 0.6rem;
    border: 2px solid #7d7a6c;
    border-radius: 8px;
    font: inherit;
    font-size: 0.9rem;
    color: #011936;
  }
  .me-ta:disabled {
    background: #f4f5f2;
    color: #5b5a52;
  }
  /* Beiger Aufmerksamkeits-Glow nach „Änderungen vornehmen" (Operator 2026-07-25).
     Bewusst NUR ein äußerer Schein per box-shadow — die Rahmenfarbe bleibt #7d7a6c:
     Beige #cdc6a5 auf Weiß liegt bei ~1,7:1 und würde als Steuerelement-Begrenzung
     die 3:1-Schwelle (WCAG 1.4.11) reißen. Der Puls ist endlich (3 Durchläufe, ~2,4 s),
     damit nichts dauerhaft blinkt (WCAG 2.2.2); der Fokusring nutzt outline und kommt
     sich mit dem Schatten nicht ins Gehege. */
  .me-ta.me-glow {
    animation: me-glow 0.8s ease-in-out 3;
  }
  @keyframes me-glow {
    0%,
    100% {
      box-shadow: 0 0 0 0 rgba(205, 198, 165, 0);
    }
    50% {
      box-shadow: 0 0 0 5px rgba(205, 198, 165, 0.7);
    }
  }
  @media (prefers-reduced-motion: reduce) {
    /* Kein Puls, aber der Hinweis bleibt sichtbar: statischer Schein. */
    .me-ta.me-glow {
      animation: none;
      box-shadow: 0 0 0 5px rgba(205, 198, 165, 0.7);
    }
  }
  .me-send {
    padding: 0.5rem 1.1rem;
    background: #011936;
    color: #fff;
    border: 0;
    border-radius: 8px;
    font: inherit;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
  }
  /* Senden-Zeile mit der KI-Kennzeichnung. Der Hinweis nimmt den Rest der Breite, der Knopf
     behält seine natürliche. `align-items: center` zentriert den mehrzeiligen Hinweis gegen den
     einzeiligen Knopf — deshalb trägt .me-send hier KEIN `align-self: flex-end` mehr: in einer
     Zeile (Querachse = vertikal) würde das den Knopf nach UNTEN kleben statt nach rechts.
     Rechtsbündig wird die Zeile über `justify-content`, nicht über den Knopf.
     ZEILENZAHL IST NICHT STEUERBAR, und das ist Absicht (verifiziert an der Live-Demo 03.08.2026):
     Mit Montserrat bleibt der Hinweis bei 0,68rem im 400px-Drawer zweizeilig, ab 0,72rem wird er
     dreizeilig. Portierte Kundensites bringen aber ihre EIGENE Schrift mit (demo.kaino.at etwa
     Bricolage Grotesque), Montserrat fehlt dort, und die Fallback-Systemschrift ist breiter — dort
     sind es drei Zeilen. Da `system-ui` je nach Betriebssystem eine andere Schrift ist, gibt es
     keine Größe, die überall zwei Zeilen garantiert; wer das versucht, jagt einem Wert nach, der
     pro Site anders ausfällt. Drei Zeilen sind in Ordnung: Der Hinweis bleibt lesbar, vertikal
     zentriert und vollständig, und darauf kommt es rechtlich an.
     #5b5a52 auf Weiß liegt bei ~5,6:1 und damit klar über AA. */
  .me-sendrow {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 1rem;
  }
  .me-sendrow .me-send {
    flex: 0 0 auto;
  }
  .me-ainote {
    flex: 1 1 auto;
    margin: 0;
    font-size: 0.68rem;
    line-height: 1.35;
    color: #5b5a52;
  }
  .me-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
  }
  /* The UA stylesheet's `[hidden] { display: none }` is UA-origin, so ANY author
     `display` declaration beats it — and .me-panel/.me-actions both set
     `display: flex`. That made `el.hidden = true` a silent no-op, so the
     accept/discard buttons rendered permanently even with no draft to act on.
     An attribute selector (0,2,0) outranks the bare class (0,1,0), so this
     restores the intent without !important. */
  .me-panel[hidden],
  .me-actions[hidden] {
    display: none;
  }
  .me-btn {
    flex: 1;
    padding: 0.55rem 0.8rem;
    border-radius: 8px;
    font: inherit;
    font-size: 0.88rem;
    font-weight: 700;
    cursor: pointer;
  }
  .me-btn--primary {
    background: #011936;
    color: #fff;
    border: 0;
  }
  .me-btn--ghost {
    background: #fff;
    color: #011936;
    border: 1px solid #011936;
  }
  /* "Hilfe?" contact line — muted lead-in (#5b5a52, 5.6:1 on white), navy anchors. Unobtrusive:
     small, centered, no underline until hover/focus. nowrap keeps each anchor unbroken when the
     line wraps as a whole. */
  .me-help {
    margin: 0;
    font-size: 0.78rem;
    color: #5b5a52;
    text-align: center;
  }
  .me-help a {
    color: #011936;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
  }
  .me-help a:hover,
  .me-help a:focus-visible {
    text-decoration: underline;
  }
  /* .me-close is in here too: render() disables the × alongside the action buttons while an
     accept/discard is in flight, and without a disabled style it kept looking fully live while
     silently ignoring every click. */
  .me-send:disabled,
  .me-btn:disabled,
  .me-close:disabled {
    opacity: 0.5;
    cursor: default;
  }
  .me-ta:focus-visible,
  .me-send:focus-visible,
  .me-btn:focus-visible {
    outline: 3px solid #011936;
    outline-offset: 2px;
  }
  /* "Ihre Seite wurde aktualisiert." — the post-cycle confirmation that the page in front of the
     customer actually changed. Letter style: white card, navy #011936 ink, beige #cdc6a5 hairline
     with a navy leading edge, Montserrat. `position: fixed` + `pointer-events: none` make it
     non-blocking and layout-shift-free; it self-removes after 3.4 s. Under prefers-reduced-motion
     the fade is dropped — the cue still appears and still disappears, it just does not animate. */
  .me-toast {
    position: fixed;
    top: 1rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2147483101; /* above the chat drawer (2147483100), as before the raise */
    box-sizing: border-box;
    max-width: min(28rem, calc(100vw - 2rem));
    padding: 0.6rem 1.1rem;
    background: #fff;
    color: #011936;
    border: 1px solid #cdc6a5;
    border-left: 3px solid #011936;
    border-radius: 8px;
    box-shadow: 0 6px 22px rgba(1, 25, 54, 0.22);
    font-family:
      Montserrat,
      system-ui,
      -apple-system,
      'Segoe UI',
      Roboto,
      sans-serif;
    font-size: 0.9rem;
    font-weight: 600;
    text-align: center;
    pointer-events: none;
    animation:
      me-toast-in 0.28s ease-out,
      me-toast-out 0.45s ease-in 2.85s forwards;
  }
  @keyframes me-toast-in {
    from {
      opacity: 0;
      transform: translate(-50%, -0.5rem);
    }
    to {
      opacity: 1;
      transform: translate(-50%, 0);
    }
  }
  @keyframes me-toast-out {
    to {
      opacity: 0;
      transform: translate(-50%, -0.5rem);
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .me-toast {
      animation: none;
    }
  }
  /* Full-page "Wird veröffentlicht …" overlay — letter style: near-opaque white canvas, the
     .me-toast card recipe for the message, the .me-running spinner ring as its ::before.
     Topmost of everything (chat drawer 2147483100, toast 2147483101, conversion overlay
     2147483000/1). render() owns [hidden]; the explicit rule is required because the author
     `display: flex` would beat the UA's `[hidden]` (see .me-panel[hidden] above). */
  .me-pub {
    position: fixed;
    inset: 0;
    z-index: 2147483102;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.94);
    font-family:
      Montserrat,
      system-ui,
      -apple-system,
      'Segoe UI',
      Roboto,
      sans-serif;
  }
  .me-pub[hidden] {
    display: none;
  }
  .me-pub__msg {
    margin: 0;
    box-sizing: border-box;
    max-width: min(28rem, calc(100vw - 2rem));
    padding: 0.85rem 1.4rem;
    background: #fff;
    color: #011936;
    border: 1px solid #cdc6a5;
    border-left: 3px solid #011936;
    border-radius: 8px;
    box-shadow: 0 6px 22px rgba(1, 25, 54, 0.22);
    font-size: 1rem;
    font-weight: 600;
    text-align: center;
  }
  .me-pub__msg::before {
    content: '';
    display: inline-block;
    width: 0.85em;
    height: 0.85em;
    margin-right: 0.55em;
    border: 2px solid #cdc6a5;
    border-top-color: #011936;
    border-radius: 50%;
    vertical-align: -2px;
    animation: me-spin 0.8s linear infinite;
  }
  /* While a chat cycle runs, disable the menu-upload controls (two-modality coordination). */
  .me-busy .oe-btn {
    pointer-events: none;
    opacity: 0.5;
  }
  /* Mobile: the panel becomes a bottom sheet — full-bleed, square, and with only the top
     border left (the other three sit on the viewport edge). Capped height + its own scroll so
     the taller header can never push the textarea and Senden off-screen. */
  @media (max-width: 640px) {
    /* Narrow bar: let the left group wrap onto its own line(s) instead of squeezing the
       buttons. `margin-left: auto` on .oe-logout still right-aligns it within whatever
       line it lands on, so the label -> edit -> GA -> logout order is preserved. */
    .oe-banner {
      flex-wrap: wrap;
      gap: 0.5rem 0.75rem;
    }
    .me-drawer {
      /* top: auto is load-bearing: with the desktop `top` left in place, top + bottom would
         stretch the fixed wrapper full-height and break the bottom sheet. */
      top: auto;
      right: 0;
      bottom: 0;
      left: 0;
      width: 100%;
    }
    /* Bottom sheet: dragging is wrong here (the JS is gated on the same media query too). */
    .me-head {
      cursor: auto;
      touch-action: auto;
    }
    .me-panel {
      max-height: 85vh;
      overflow-y: auto;
      border-right: 0;
      border-bottom: 0;
      border-left: 0;
      border-radius: 0;
    }
  }