/* ==========================================================================
 * consent_banner.css — the platform consent surface on every public page.
 * --------------------------------------------------------------------------
 * Migrated 2026-08-01 to Claude Design's markup (Batch 4). The same partial —
 * includes/lp_trial/consent_banner.php — and the same logic
 * (assets/js/consent/gz-consent.js) also serve /3-monate-kostenlos/, which
 * styles them from lp_trial.css. This file restates that design against
 * public.css's tokens, WITH LITERAL FALLBACKS on every one of them.
 *
 * ⚠️ THE FALLBACKS ARE NOT DEFENSIVE HABIT, AND THIS FILE MAY DECLARE NO TOKEN.
 *
 * public.css maps --card-bg to var(--surface), and --surface is defined in
 * assets/css/theme_a/tokens.css, which impressum / agb / datenschutz / kontakt /
 * widerruf do NOT load. A bare var(--card-bg) therefore resolves to nothing
 * there — which for a background means "transparent", i.e. a consent banner
 * with the page text showing through it. Every colour below is written
 * var(--token, <literal>).
 *
 * And unlike lp_trial.css, this file may not declare :root tokens of its own:
 * it ships on pages that DO load the theme, and a --surface here would repaint
 * half the site. Same markup, two stylesheets, opposite rules.
 *
 * --------------------------------------------------------------------------
 * WHY ACCEPT AND REJECT ARE FORCED TO THE SAME BOX
 *
 * §3 of the Arbeitsauftrag: "Ablehnen darf nicht unnötig schwieriger sein als
 * Akzeptieren." With content-sized columns, "Einstellungen" / "Sazkarî" render
 * a third the width of "Alle akzeptieren", which is a visual hierarchy between
 * the choices. The actions are therefore equal-fraction grid columns in every
 * language, and the acceptance gate measures their rendered boxes AND their
 * font sizes against each other.
 *
 * --------------------------------------------------------------------------
 * WHY THE BANNER IS NOT A MODAL
 *
 * §7: the banner must not make the public main content technically
 * inaccessible. It is position:fixed, it never sets inert/aria-hidden on the
 * page, and body.cookie-banner-visible adds bottom padding so nothing the
 * visitor needs ends up underneath it. Only the settings dialog is modal, and
 * it only ever opens after a click.
 *
 * @see includes/consent_banner_mount.php     what emits this
 * @see includes/lp_trial/consent_banner.php  the markup contract
 * @see assets/css/lp_trial.css                the campaign-page half
 * ========================================================================== */

/* ── layer 1 · the banner ────────────────────────────────────────────────── */

.gz-banner {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  /* Above the offer/landing sticky CTAs (z-index 99) — a legal surface must not
     be the thing that loses a stacking contest. Below nothing else on the site. */
  z-index: 1000;
  background: var(--card-bg, #ffffff);
  color: var(--text-color, #0b1220);
  border-block-start: 2px solid var(--text-color, #0b1220);
  box-shadow: 0 -8px 32px -16px rgba(11, 18, 32, 0.34);
  padding-block: 12px calc(12px + env(safe-area-inset-bottom, 0px));
  font-size: 14px;
  line-height: 1.6;
}
.gz-banner[hidden] { display: none; }
@media (min-width: 900px) { .gz-banner { padding-block: 16px; } }

.gz-banner__in {
  width: 100%;
  max-width: var(--container, 1180px);
  margin-inline: auto;
  /* The safe-area insets matter on iPhone: without them the actions sit under
     the home indicator, which is the one place a "reject" button must not be. */
  padding-inline: max(20px, env(safe-area-inset-left, 0px)) max(20px, env(safe-area-inset-right, 0px));
  display: grid;
  gap: 11px;
}
@media (min-width: 900px) {
  .gz-banner__in { grid-template-columns: minmax(0, 1fr) minmax(440px, 0.68fr); gap: 32px; align-items: center; }
}

.gz-banner__t {
  margin: 0;
  font-size: 15px;
  font-weight: 800;
  line-height: 1.28;
  letter-spacing: -0.012em;
  color: var(--text-color, #0b1220);
}
.gz-banner__x {
  margin: 5px 0 0;
  font-size: 12px;
  line-height: 1.42;
  color: var(--muted-color, #526178);
  overflow-wrap: anywhere;
}
.gz-banner__links { margin: 6px 0 0; display: flex; flex-wrap: wrap; gap: 4px 16px; }
@media (min-width: 900px) {
  .gz-banner__t { font-size: 16px; }
  .gz-banner__x { font-size: 13px; line-height: 1.5; margin-block-start: 7px; }
  .gz-banner__links { margin-block-start: 9px; }
}

/* public.css sets `a { text-decoration: none !important; }` globally, and a
   legal link that is only distinguishable by colour fails WCAG 1.4.1. */
.gz-link {
  color: var(--link-color, #b04600);
  text-decoration: underline !important;
  font-size: 12.5px;
  font-weight: 600;
}

/* Three equal-rank actions — see the file header. */
.gz-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }

.gz-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 44px;                 /* a 44px touch target on every choice */
  padding: 8px 6px;
  border-radius: 10px;
  border: 2px solid var(--text-color, #0b1220);
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.2;
  hyphens: auto;
  cursor: pointer;
}
@media (min-width: 520px) {
  .gz-btn { font-size: 14.5px; padding: 10px 12px; min-height: 48px; hyphens: manual; }
}
.gz-btn--a {
  background: var(--button-bg, #c14a00);
  border-color: var(--button-bg, #c14a00);
  color: var(--button-text-color, #ffffff);
}
.gz-btn--b {
  background: var(--text-color, #0b1220);
  border-color: var(--text-color, #0b1220);
  color: var(--card-bg, #ffffff);
}
.gz-btn--c {
  background: var(--card-bg, #ffffff);
  color: var(--text-color, #0b1220);
}
.gz-btn:focus-visible { outline: 3px solid rgba(193, 74, 0, 0.45); outline-offset: 2px; }

/* ── layer 2 · the preference centre ─────────────────────────────────────── */

.gz-dialog {
  position: fixed;
  inset: 0;
  /* Above the sales-chat FAB (1200) and its action sheet (1310). The banner
     itself deliberately stays BELOW that layer — it never overlaps the FAB,
     because the FAB already lifts itself by --ui-cookie-banner-height — but a
     modal that a floating avatar can sit on top of is a modal in name only. */
  z-index: 1400;
  display: grid;
  place-items: end center;
}
.gz-dialog[hidden] { display: none; }
.gz-dialog__veil { position: absolute; inset: 0; background: rgba(11, 18, 32, 0.55); }

.gz-dialog__panel {
  position: relative;
  width: 100%;
  max-width: 620px;
  max-height: 92vh;
  overflow-y: auto;
  background: var(--card-bg, #ffffff);
  color: var(--text-color, #0b1220);
  border-start-start-radius: 14px;
  border-start-end-radius: 14px;
  padding: 24px 20px calc(24px + env(safe-area-inset-bottom, 0px));
}
@media (min-width: 640px) {
  .gz-dialog { place-items: center; }
  .gz-dialog__panel { border-radius: 14px; padding: 32px 30px; }
}

.gz-dialog__t {
  margin: 0;
  font-size: 21px;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -0.018em;
  padding-inline-end: 44px;
}
.gz-dialog__x { margin: 10px 0 0; font-size: 14.5px; line-height: 1.6; color: var(--muted-color, #526178); }

.gz-close {
  position: absolute;
  top: 12px;
  inset-inline-end: 12px;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--input-bg, #f1f4fa);
  border: 0;
  border-radius: 10px;
  color: var(--text-color, #0b1220);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
/* The close button's accessible name. It is TEXT, not an aria-label, because
   the language swap writes textContent — an attribute would stay German. */
.gz-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.gz-cats { margin: 22px 0 0; padding: 0; list-style: none; display: grid; gap: 12px; }
.gz-cat {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 6px 16px;
  padding: 16px;
  border: 1px solid var(--border-color, rgba(11, 18, 32, 0.12));
  border-radius: 10px;
  background: var(--page-bg, #f7f8fc);
}
.gz-cat__t { font-size: 15.5px; font-weight: 700; line-height: 1.35; cursor: pointer; }
.gz-cat__x {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted-color, #526178);
}
.gz-cat__on {
  align-self: start;
  font-size: 12px;
  font-weight: 700;
  color: var(--success-color, #0f7b4f);
  white-space: nowrap;
  padding-block-start: 3px;
}

/* The toggle is an <input type=checkbox> so the browser keeps it a real,
   keyboard-operable control and gz-consent.js can read `.checked`; only its
   painting is replaced. */
.gz-switch {
  position: relative;
  align-self: start;
  flex: 0 0 auto;
  width: 52px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: #c4ccdb;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  transition: background-color 0.16s ease;
}
.gz-switch::after {
  content: "";
  position: absolute;
  top: 3px;
  inset-inline-start: 3px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(11, 18, 32, 0.3);
  transition: inset-inline-start 0.16s ease;
}
.gz-switch:checked { background: var(--success-color, #0f7b4f); }
.gz-switch:checked::after { inset-inline-start: 25px; }
.gz-switch:disabled { opacity: 0.55; cursor: default; }
.gz-switch:focus-visible { outline: 3px solid rgba(193, 74, 0, 0.45); outline-offset: 2px; }

.gz-dialog__actions { display: grid; gap: 8px; margin-block-start: 22px; }
.gz-dialog__actions .gz-btn--save { grid-column: 1 / -1; }
@media (min-width: 520px) {
  .gz-dialog__actions { grid-template-columns: repeat(3, 1fr); }
  .gz-dialog__actions .gz-btn--save { grid-column: auto; }
}

/* ── Arabic ──────────────────────────────────────────────────────────────
   Cairo's natural line box is ~1.90em: a 1.4/1.6 line clips the descender of
   the ya'/jim family. And NEVER letter-spacing on an Arabic run — tracking
   breaks the letter joining that makes the script readable at all. */
body.cairo-font .gz-banner,
body.cairo-font .gz-dialog {
  line-height: 1.8;
  letter-spacing: normal;
}
body.cairo-font .gz-banner__t,
body.cairo-font .gz-dialog__t { line-height: 1.6; padding-block-end: 0.12em; letter-spacing: normal; }
body.cairo-font .gz-btn { line-height: 1.7; letter-spacing: normal; }

/* ── the landing page reserves for TWO bars, not one ─────────────────────
   Measured 2026-08-01, /, banner up, 390x844: the re-opener occupied 550–618
   and .lp-sticky sat at 551–618 — exactly on top of it. elementFromPoint at the
   button's own centre returned .lp-sticky__h, i.e. the permanent consent choice
   was visible and unclickable, which §3 does not allow.

   The mechanism is an interaction between three rules that are each correct:
     .lp-page              { padding-bottom: 78px }            reserve for the CTA bar
     body.cookie-banner-visible { padding-bottom: max(var(--ui-cookie-banner-height), …) }
     .lp-sticky            { bottom: var(--ui-cookie-banner-height) }
   The second REPLACES the first rather than adding to it, while the third lifts
   the bar by the same amount — so the bar ends up over the last 78px of the
   document, and the last thing in the document is the legal-links row.

   Scoped to .lp-page on purpose: it is the only page with that bar, and giving
   every public page 78px of dead space would be a worse fix than the bug. */
body.cookie-banner-visible.lp-page {
  padding-bottom: calc(78px + max(var(--ui-cookie-banner-height, 0px), env(safe-area-inset-bottom, 0px)));
}

/* ── the footer's permanent re-opener ────────────────────────────────────
   §3 requires the choice to stay changeable, from every page, forever. It is a
   <button> because it performs an action; it is styled as the footer links
   around it because that is where a visitor looks for it. The class name is
   deliberately unchanged by the redesign — includes/public_footer.php emits it
   on every page of the site and it is not part of the campaign design. */
.gzc-reopen {
  /* Matches `.footer-links a` in public.css line for line — it sits in that
     nav and must not read as a stray control, and a 44px target is the rule
     for every other link in the row. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 0;
  border: 0;
  border-radius: 8px;
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--muted-color, #526178);
  text-decoration: underline;
  cursor: pointer;
}
.gzc-reopen:hover,
.gzc-reopen:focus-visible { color: var(--text-color, #0b1220); }

/* ── dark ────────────────────────────────────────────────────────────────
   Two selectors on purpose: the site's own toggle stamps data-theme on <html>
   and must win in BOTH directions, while a visitor who never touched it gets
   the system preference. */
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .gz-banner,
  html:not([data-theme="light"]) .gz-dialog__panel {
    background: var(--card-bg, #131a26);
    color: var(--text-color, #e8ecf4);
  }
  html:not([data-theme="light"]) .gz-banner {
    border-block-start-color: var(--border-color, rgba(232, 236, 244, 0.4));
    box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.5);
  }
  html:not([data-theme="light"]) .gz-banner__t { color: var(--text-color, #e8ecf4); }
  html:not([data-theme="light"]) .gz-banner__x,
  html:not([data-theme="light"]) .gz-dialog__x,
  html:not([data-theme="light"]) .gz-cat__x { color: var(--muted-color, #9aa7bd); }
  html:not([data-theme="light"]) .gz-btn {
    border-color: var(--border-color, rgba(232, 236, 244, 0.4));
  }
  html:not([data-theme="light"]) .gz-btn--a {
    background: var(--button-bg, #ff7a18);
    color: var(--button-text-color, #1a1005);
    border-color: var(--button-bg, #ff7a18);
  }
  /* "Reject" must keep the same visual weight as "accept" in the dark theme
     too — inverting it into the page background would make refusing quieter,
     which is the exact thing §3 forbids. */
  html:not([data-theme="light"]) .gz-btn--b {
    background: var(--text-color, #e8ecf4);
    color: var(--card-bg, #131a26);
    border-color: var(--text-color, #e8ecf4);
  }
  html:not([data-theme="light"]) .gz-btn--c {
    background: var(--card-bg, #131a26);
    color: var(--text-color, #e8ecf4);
  }
  html:not([data-theme="light"]) .gz-cat {
    background: var(--page-bg, #0e141e);
    border-color: var(--border-color, rgba(232, 236, 244, 0.18));
  }
  html:not([data-theme="light"]) .gz-close {
    background: var(--input-bg, #1c2634);
    color: var(--text-color, #e8ecf4);
  }
  html:not([data-theme="light"]) .gz-link { color: var(--link-color, #ffa25c); }
  html:not([data-theme="light"]) .gz-switch { background: #46536a; }
  /* #0f7b4f only reaches ~2.4:1 on the dark card — the "always on" note and the
     switch's on-state both need the lighter green there. */
  html:not([data-theme="light"]) .gz-cat__on { color: #4ade9a; }
  html:not([data-theme="light"]) .gz-switch:checked { background: #2f9e6b; }
}

html[data-theme="dark"] .gz-banner,
html[data-theme="dark"] .gz-dialog__panel {
  background: var(--card-bg, #131a26);
  color: var(--text-color, #e8ecf4);
}
html[data-theme="dark"] .gz-banner {
  border-block-start-color: var(--border-color, rgba(232, 236, 244, 0.4));
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.5);
}
html[data-theme="dark"] .gz-banner__t { color: var(--text-color, #e8ecf4); }
html[data-theme="dark"] .gz-banner__x,
html[data-theme="dark"] .gz-dialog__x,
html[data-theme="dark"] .gz-cat__x { color: var(--muted-color, #9aa7bd); }
html[data-theme="dark"] .gz-btn { border-color: var(--border-color, rgba(232, 236, 244, 0.4)); }
html[data-theme="dark"] .gz-btn--a {
  background: var(--button-bg, #ff7a18);
  color: var(--button-text-color, #1a1005);
  border-color: var(--button-bg, #ff7a18);
}
html[data-theme="dark"] .gz-btn--b {
  background: var(--text-color, #e8ecf4);
  color: var(--card-bg, #131a26);
  border-color: var(--text-color, #e8ecf4);
}
html[data-theme="dark"] .gz-btn--c {
  background: var(--card-bg, #131a26);
  color: var(--text-color, #e8ecf4);
}
html[data-theme="dark"] .gz-cat {
  background: var(--page-bg, #0e141e);
  border-color: var(--border-color, rgba(232, 236, 244, 0.18));
}
html[data-theme="dark"] .gz-close {
  background: var(--input-bg, #1c2634);
  color: var(--text-color, #e8ecf4);
}
html[data-theme="dark"] .gz-link { color: var(--link-color, #ffa25c); }
html[data-theme="dark"] .gz-switch { background: #46536a; }
html[data-theme="dark"] .gz-cat__on { color: #4ade9a; }
html[data-theme="dark"] .gz-switch:checked { background: #2f9e6b; }

@media (prefers-reduced-motion: reduce) {
  .gz-banner, .gz-dialog, .gz-dialog__panel, .gz-switch, .gz-switch::after {
    transition: none !important;
    animation: none !important;
  }
}
