/* wizard.css — funnel components restyled to freenet's REAL design (reskin).
 * Same class names as the views; only the look changes. Navy + lime green,
 * Open Sans / Montserrat, navy pill CTAs, freenet-red errors. */

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--fn-font-body);
  color: var(--fn-ink);
  background: var(--fn-soft);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* freenet header bar */
.fn-header {
  /* echter freenet-Header-Wert (fn-web4: #21314d), nicht das CTA-Navy */
  background: #21314d;
  /* P5: die gruene Linie unter dem dunklen Checkout-Header — exakt wie im
     echten freenet-Checkout (Navy-Balken, Logo links, Lime-Rule darunter). */
  border-bottom: 4px solid var(--fn-green);
}
.fn-header__inner {
  max-width: 1240px;
  margin: 0 auto;
  height: 62px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 16px;
}
.fn-header__logo {
  height: 30px;
  width: auto;
  display: block;
}

/* layout shell */
.wizard {
  max-width: var(--fn-maxw);
  margin: 0 auto;
  padding: var(--fn-gap-lg) var(--fn-gap) 80px;
}
.wizard__step {
  background: var(--fn-surface);
  border-radius: var(--fn-radius);
  box-shadow: var(--fn-shadow);
  padding: var(--fn-gap-lg);
}
.wizard__step > h1 {
  font-family: var(--fn-font-display);
  font-size: 1.5rem;
  line-height: 1.2;
  font-weight: 800;
  color: var(--fn-navy);
  margin: 0 0 var(--fn-gap-lg);
  letter-spacing: -.01em;
}
.wizard__step p { color: var(--fn-slate); }

/* progress: step N of 6 — lime green for completed */
.stepper {
  list-style: none;
  display: flex;
  align-items: flex-start;
  margin: 26px auto 6px;
  padding: 0 8px;
  max-width: 660px;
}
.stepper__step { display: flex; flex-direction: column; align-items: center; gap: 7px; flex: none; }
.stepper__dot {
  width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: #fff; border: 2.5px solid var(--fn-green); color: var(--fn-green-d);
}
.stepper__dot svg { width: 21px; height: 21px; }
.stepper__step.is-done .stepper__dot { background: var(--fn-green); border-color: var(--fn-green); color: #fff; }
.stepper__step.is-current .stepper__dot { border-color: var(--fn-navy); color: var(--fn-navy); box-shadow: 0 0 0 4px rgba(9, 32, 67, .12); }
.stepper__step.is-todo .stepper__dot { border-color: #ccd3dd; color: #b9c2d0; }
.stepper__label { font-size: .74rem; font-weight: 700; color: var(--fn-slate, #5A6982); white-space: nowrap; }
.stepper__step.is-current .stepper__label { color: var(--fn-navy); }
.stepper__conn { flex: 1; height: 3px; border-radius: 2px; background: #dfe5ee; margin-top: 21px; }
.stepper__conn.is-done { background: var(--fn-green); }
@media (max-width: 560px) {
  .stepper { padding: 0 2px; }
  .stepper__dot { width: 36px; height: 36px; }
  .stepper__dot svg { width: 17px; height: 17px; }
  /* Mobile: nur das Label des aktiven Schritts, sonst wird es eng */
  .stepper__step:not(.is-current) .stepper__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }
  .stepper__conn { margin-top: 17px; }
}

.wizard__progress {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: var(--fn-gap-lg);
}
.wizard__progress-dot {
  flex: 1 1 auto;
  height: 6px;
  border-radius: 999px;
  background: #cfd6e4;
}
.wizard__progress-dot.is-done { background: var(--fn-green); }
.wizard__progress-dot.is-current { background: var(--fn-green-2); }
.wizard__progress-label {
  flex: 0 0 auto;
  font-size: .8125rem;
  color: var(--fn-slate);
  font-weight: 700;
  margin-left: 4px;
}

/* form fields */
.field { margin-bottom: var(--fn-gap); }
.field > label {
  display: block;
  font-size: .875rem;
  font-weight: 700;
  color: var(--fn-navy);
  margin-bottom: 6px;
}
.field input[type="text"],
.field input[type="email"],
.field input[type="date"],
.field input[type="tel"],
.field select {
  width: 100%;
  min-height: var(--fn-tap);
  padding: 0 14px;
  font-size: 1rem;
  font-family: inherit;
  color: var(--fn-ink);
  background: var(--fn-surface);
  border: 1px solid #c7cede;
  border-radius: var(--fn-radius-input);
  appearance: none;
}
.field input:focus,
.field select:focus {
  outline: none;
  border-color: var(--fn-green-d);
  box-shadow: 0 0 0 3px rgba(132, 188, 52, .25);
}
.field__hint { font-size: .8125rem; color: var(--fn-slate); margin-top: 6px; }
.field__error { display: none; font-size: .8125rem; color: var(--fn-red); margin-top: 6px; font-weight: 700; }

/* invalid state — freenet red */
.field.is-invalid input,
.field.is-invalid select { border-color: var(--fn-red); }
.field.is-invalid .field__error { display: block; }

/* checkbox row (SEPA mandate) */
.field--check { display: flex; align-items: flex-start; gap: 12px; }
.field--check input[type="checkbox"] { flex: none; width: 22px; height: 22px; margin: 1px 0 0; accent-color: var(--fn-green-d); }
.field--check label { font-weight: 400; font-size: .9375rem; color: var(--fn-slate); }

/* buttons — freenet primary CTA is NAVY, pill-radius */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--fn-tap);
  padding: 12px 22px;
  font-size: 1rem;
  font-weight: 700;
  font-family: var(--fn-font-body);
  border: none;
  border-radius: var(--fn-radius-btn);
  cursor: pointer;
  text-decoration: none;
}
.btn--primary { background: var(--fn-navy); color: #fff; width: 100%; min-height: 54px; }
.btn--primary:hover { background: var(--fn-navy-2); }
.btn--ghost { background: transparent; color: var(--fn-navy); border: 1px solid #c7cede; }
.wizard__actions { margin-top: var(--fn-gap-lg); }

/* tariff cards */
.tariff-list { display: grid; gap: 12px; }
.tariff-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  min-height: var(--fn-tap);
  padding: 16px 18px;
  text-align: left;
  background: var(--fn-surface);
  border: 1px solid #d7dce8;
  border-radius: var(--fn-radius);
  cursor: pointer;
  font-family: inherit;
}
.tariff-card:hover { border-color: var(--fn-green); }
.tariff-card.is-selected { border-color: var(--fn-green-d); background: var(--fn-green-light); box-shadow: 0 0 0 2px rgba(132, 188, 52, .35); }
/* recommended tariff — green emphasis + badge */
.tariff-card--recommended { border: 2px solid var(--fn-green-d); }
.tariff-card__badge {
  align-self: flex-start;
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--fn-navy);
  background: var(--fn-green);
  padding: 4px 10px;
  border-radius: var(--fn-radius-pill);
}
.tariff-card__row { display: flex; align-items: center; gap: 12px; }
.tariff-card__main { flex: 1 1 auto; min-width: 0; }
.tariff-card__name { display: block; font-family: var(--fn-font-display); font-weight: 800; font-size: 1.1rem; color: var(--fn-navy); }
.tariff-card__data { display: block; font-size: .8125rem; color: var(--fn-slate); font-weight: 600; margin-top: 2px; }
.tariff-card__price { flex: 0 0 auto; text-align: right; white-space: nowrap; }
.tariff-card__price .price { display: block; font-size: 1.15rem; }
.tariff-card__per { display: block; font-size: .72rem; color: var(--fn-slate); font-weight: 600; }
.tariff-card__chevron { flex: 0 0 auto; font-size: 1.6rem; line-height: 1; color: var(--fn-green-d); font-weight: 700; }

/* summary rows */
.summary-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--fn-line);
}
/* Der Wert darf wachsen, die Beschriftung nicht gequetscht werden: ohne feste
   Flex-Anteile hat "max.mustermann@example.com" das Label so weit
   zusammengedrueckt, dass "E-Mail" am Bindestrich umbrach ("E-" / "Mail")
   — gemeldet von Hendrik am 28.08.2026. */
.summary-row__label { flex: 0 0 auto; white-space: nowrap;
  color: var(--fn-slate); font-size: .875rem; }
.summary-row__value { flex: 1 1 auto; min-width: 0; text-align: right;
  color: var(--fn-ink); font-weight: 600; overflow-wrap: anywhere; }
/* Unter 360px ist fuer Beschriftung UND Wert nebeneinander kein Platz mehr:
   "19,99 €" verlor das Eurozeichen an die naechste Zeile, die Mailadresse
   brach mitten im Wort. Ab 360px (jedes aktuelle Telefon) bleibt die Zeile
   einzeilig, darunter steht der Wert unter seiner Beschriftung. */
@media (max-width: 359px) {
  .summary-row { display: block; padding: 10px 0; }
  .summary-row__value { display: block; text-align: left; margin-top: 2px; }
}
.wizard__step h2 {
  font-family: var(--fn-font-display);
  font-size: 1.15rem; font-weight: 800; color: var(--fn-navy);
  margin: var(--fn-gap-lg) 0 4px;
}

/* prices — navy display; IBAN mono for legibility */
.price { font-family: var(--fn-font-display); font-weight: 800; color: var(--fn-navy); font-variant-numeric: tabular-nums; }
.iban { font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; font-variant-numeric: tabular-nums; letter-spacing: .02em; }

/* confirmation success — lime green */
.confirm-success__badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--fn-green-d);
  font-weight: 800;
  font-family: var(--fn-font-display);
  margin-bottom: var(--fn-gap);
}
.confirm-success__ref { font-family: ui-monospace, Menlo, Consolas, monospace; }

/* green check bullets */
.checks { list-style: none; margin: 0 0 18px; padding: 0; display: grid; gap: 10px; }
.checks li { position: relative; padding-left: 28px; color: var(--fn-ink); }
.checks li::before {
  content: "✓"; position: absolute; left: 0; top: 0;
  color: var(--fn-green-d); font-weight: 900;
}

/* back navigation between steps */
.wizard__back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 14px;
  font-size: .875rem;
  font-weight: 700;
  color: var(--fn-navy);
  text-decoration: none;
  min-height: 44px;
}
.wizard__back:hover { color: var(--fn-green-d); }

/* sticky primary action on mobile — ONLY on the long review page (summary), where
   there are no input fields to hide. Short form steps keep a static CTA so the
   sticky bar never covers the last field. */
@media (max-width: 640px) {
  .wizard__step:has(.wizard__actions--sticky) { padding-bottom: 88px; }
  .wizard__actions--sticky {
    position: sticky;
    bottom: 0;
    margin: var(--fn-gap-lg) -24px -24px;
    padding: 14px 18px calc(14px + env(safe-area-inset-bottom, 0px));
    background: rgba(255, 255, 255, .96);
    border-top: 1px solid var(--fn-line);
    box-shadow: 0 -4px 16px rgba(9, 32, 67, .08);
    border-bottom-left-radius: var(--fn-radius);
    border-bottom-right-radius: var(--fn-radius);
  }
}

/* skip link — first focusable element; visually hidden until focused (a11y) */
.skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 1000;
  padding: 10px 16px;
  background: var(--fn-navy);
  color: #fff;
  font-weight: 700;
  border-radius: var(--fn-radius-sm);
  text-decoration: none;
  transition: top .15s ease;
}
.skip-link:focus {
  top: 8px;
  outline: 3px solid var(--fn-green-2);
  outline-offset: 2px;
}

/* error summary (A2, WCAG 4.1.3) — announced live on an invalid re-render */
.form-errors {
  margin-bottom: var(--fn-gap);
  padding: 12px 14px;
  border-radius: var(--fn-radius-sm);
  border: 1px solid var(--fn-red);
  border-left: 4px solid var(--fn-red);
  background: #fdecef;
  color: var(--fn-red-text);
  font-weight: 700;
  font-size: .9375rem;
}

/* Der Footer der Bestellstrecke ist derselbe wie auf der Startseite:
   Markup in app/views/shared/_site_footer.html.erb, Styles in
   site-footer.css. Der frueher hier definierte .fn-footer-Einzeiler ist
   entfallen, weil Impressum/AGB auf jedem Schritt sichtbar sein muessen.
   Den Abstand zum dunklen Footer liefert bereits .wizard (80px unten). */

/* --- P2: Person-Step 1:1 wie freenet.de ------------------------------- */
/* Anrede-Radios (Frau/Herr) als klickbare Pills */
.radio-row { display: flex; gap: 12px; }
.radio-option {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 22px; border: 1.5px solid var(--fn-border, #ccd3dd);
  border-radius: var(--fn-radius-sm, 8px); cursor: pointer; font-weight: 600;
}
.radio-option:has(input:checked) {
  border-color: var(--fn-navy, #092043);
  box-shadow: 0 0 0 1.5px var(--fn-navy, #092043) inset;
}
.radio-option input { accent-color: var(--fn-navy, #092043); width: 20px; height: 20px; }
/* .field label (display:block) wuerde das Flex-Layout der Optionspille
   ueberschreiben — Checkbox rutschte auf die Text-Baseline (Hendrik, 05.08.) */
.field label.radio-option { display: flex; align-items: center; }
.radio-option input[type="checkbox"] { flex: none; margin: 0; }

/* Geburtsdatum: drei Zahlenfelder TT/MM/JJJJ (08.08. — der native Picker
   startete auf Mobile beim aktuellen Jahr, siehe person.html.erb). */
.dob-row { display: flex; gap: 10px; max-width: 260px; }
.dob-row input { flex: 1 1 0; text-align: center; min-width: 0; }
.dob-row input:last-child { flex: 1.4 1 0; }
/* Alter Datepicker-Stil — bleibt fuer den Fall, dass irgendwo noch ein
   type=date-Feld gerendert wird. */
.field input.dob-native { max-width: 240px; }

/* Rückrufnummer: fixe Vorwahl + Nummer */
/* Aufklapper fuer optionale Felder (08.08.): Gutscheincode, Rueckrufnummer,
   Adresszusatz. Sie sind alle optional, kosteten offen im Formular aber jeden
   Kunden eine Entscheidung. <details> statt eigenem JS — ohne JS bedienbar,
   und der Browser uebernimmt die a11y-Semantik (aria-expanded, Tastatur). */
.disclosure { margin: 4px 0 20px; scroll-margin-top: 16px; }
.disclosure__toggle {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 4px 2px;
  color: var(--fn-navy); font-weight: 700; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
  list-style: none;
}
.disclosure__toggle::-webkit-details-marker { display: none; }
.disclosure__toggle::before {
  content: ""; flex: none; width: 10px; height: 10px;
  border-right: 2.2px solid currentColor; border-bottom: 2.2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .15s ease;
}
.disclosure[open] > .disclosure__toggle::before {
  transform: rotate(-135deg) translate(-2px, -2px);
}
.disclosure__toggle:focus-visible { outline: 3px solid var(--fn-green-d); outline-offset: 2px; }
.disclosure__body { padding-top: 8px; }
@media (prefers-reduced-motion: reduce) {
  .disclosure__toggle::before { transition: none; }
}

/* P3: Rechnungsadresse als Sektion im Person-Step */
.form-section-title { font-family: var(--fn-font-display); font-weight: 800; font-size: 1.15rem; color: var(--fn-navy); margin: 28px 0 4px; }

/* P4: Warenkorb-Step */
.cart-tariff { display: flex; justify-content: space-between; align-items: baseline;
  border: 1.5px solid var(--fn-navy); border-radius: var(--fn-radius-sm, 8px);
  padding: 14px 18px; margin-bottom: 20px; }
.cart-tariff__name { font-family: var(--fn-font-display); font-weight: 800; color: var(--fn-navy); }
.cart-tariff__price { font-weight: 700; }
.radio-row--stacked { flex-direction: column; }
.radio-option--rich { align-items: flex-start; }
.radio-option--rich input { margin-top: 3px; }
.radio-option--rich small { color: var(--fn-slate, #5A6982); font-weight: 400; }

/* P6: Dev-only Beispieldaten-Button */
.dev-fill { position: fixed; right: 16px; bottom: 16px; z-index: 50;
  background: #fff; border: 1.5px dashed var(--fn-navy); border-radius: 999px;
  padding: 10px 16px; font-weight: 700; cursor: pointer; box-shadow: 0 4px 14px rgba(9,32,67,.18); }
.dev-fill:hover { background: var(--fn-navy); color: #fff; }

/* ---------- Design-Port (05.08.): Bestell-Panel + Auswahl-Staerken ---------- */
.wizard-cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; align-items: start; }
@media (min-width: 1060px) {
  /* Der Wizard-Container ist einspaltig 560px (--fn-maxw); mit Sidebar
     braucht er Platz fuer Step (560) + 320 + Gap. */
  .wizard:has(.order-panel) { max-width: 940px; }
  /* Die zweite Spalte NUR, wenn es das Panel wirklich gibt (Hendrik,
     27.08.2026: "URL kopiert, anderes Fenster, Layout zerschossen").
     Ohne diese Bedingung galt grid-template-columns auch auf Seiten ohne
     Panel — der Container blieb bei 560px, 320px gingen an eine leere
     Spalte, und der Schritt quetschte sich in gut 200px: Ueberschrift
     mitten im Wort umgebrochen, Karten uebereinander. Sichtbar wurde es
     genau dann, wenn jemand einen Wizard-Link ohne Session oeffnet. */
  .wizard-cols:has(.order-panel) { grid-template-columns: minmax(0, 1fr) 320px; }
  .wizard-cols:has(.order-panel) .wizard__step { max-width: 560px; width: 100%; justify-self: center; }
  .order-panel { position: sticky; top: 18px; }
}
.order-panel { background: #fff; border-radius: var(--fn-radius, 14px); overflow: hidden;
  box-shadow: 0 2px 10px rgba(9, 32, 67, .07); }
.order-panel__head { margin: 0; background: var(--fn-navy, #092043); color: #fff;
  font-size: 1.05rem; padding: 14px 18px; }
.order-panel__body { padding: 16px 18px 18px; }
.order-panel__name { margin: 0; font-weight: 800; font-size: 1.1rem; }
.order-panel__net { margin: 2px 0 12px; color: var(--fn-slate, #5A6982); font-size: .88rem; }
.order-panel__perks { list-style: none; margin: 0 0 14px; padding: 0; display: grid; gap: 7px; font-size: .92rem; }
.order-panel__perks li { display: flex; gap: 9px; align-items: baseline; }
.order-panel__perks li::before { content: "✓"; color: var(--fn-green-d); font-weight: 800; }
/* Einmalpreis-Zeile: gleiche Anatomie wie der Monatspreis, eine Stufe
   kleiner. Sie traegt die Trennlinie, weil sie ueber dem Monatspreis steht. */
.order-panel__once { display: flex; justify-content: space-between; align-items: baseline;
  border-top: 1px dashed var(--fn-border, #ccd3dd); padding-top: 12px; margin-bottom: 6px; }
.order-panel__once span { color: var(--fn-slate, #5A6982); font-size: .92rem; }
.order-panel__once b { font-size: 1.05rem; white-space: nowrap; }
.order-panel__total { display: flex; justify-content: space-between; align-items: baseline;
  border-top: 1px dashed var(--fn-border, #ccd3dd); padding-top: 12px; }
/* Steht die Einmalzeile darueber, traegt SIE die Linie — sonst zwei. */
.order-panel__once + .order-panel__total { border-top: 0; padding-top: 0; }
.order-panel__total span { color: var(--fn-slate, #5A6982); font-size: .92rem; }
.order-panel__total b { font-size: 1.35rem; }
.order-panel__total small { font-size: .8rem; color: var(--fn-slate, #5A6982); font-weight: 400; }
.order-panel__trust { margin: 10px 0 0; font-size: .8rem; color: var(--fn-slate, #5A6982); }
@media (max-width: 1059px) {
  /* Das Panel steht UNTER dem Formular (Hendrik, 28.08.2026: "sonst im Footer
     anzeigen auf mobile? also weiter unten? user soll doch schnell
     durchklicken"). Vorher stand es oben und schob die Ueberschrift des
     Schrittes auf 412 von 664 px — zwei Drittel des ersten Bildschirms ohne
     ein einziges Eingabefeld. Jetzt beginnt der Schritt bei 265 px.
     order:1 statt der DOM-Reihenfolge zu vertrauen, damit es auch dann unten
     bleibt, wenn jemand die Reihenfolge im Layout aendert. */
  .order-panel { order: 1; box-shadow: none; border: 1.5px solid var(--fn-border, #ccd3dd); }
  .order-panel__perks, .order-panel__net, .order-panel__trust { display: none; }
  /* Unter dem Formular traegt der dunkle Kopfbalken nichts mehr bei: der
     Kunde ist im Bestellprozess, die Schrittleiste sagt ihm wo. */
  .order-panel__head { display: none; }
  .order-panel__body { padding: 12px 14px; display: grid;
    grid-template-columns: 1fr auto; gap: 6px 14px; align-items: baseline; }
  .order-panel__name { grid-column: 1 / -1; font-size: 1rem;
    padding-bottom: 8px; margin-bottom: 2px; border-bottom: 1px solid #eef1f6; }
  /* display:contents haengt Beschriftung und Betrag direkt ins Raster — sonst
     sitzen die beiden Zeilen auf verschiedenen Kanten, wie am 28.08. gemeldet
     ("das ist doch kacke auf mobile"). */
  .order-panel__once, .order-panel__total { display: contents; }
  .order-panel__once span, .order-panel__total span { grid-column: 1; }
  .order-panel__once b, .order-panel__total b { grid-column: 2; text-align: right; white-space: nowrap; }
  .order-panel__once b { font-size: 1rem; }
  .order-panel__total b { font-size: 1.1rem; }
}

/* Gewaehlter-Tarif-Karte (Warenkorb) */
.cart-tariff { display: block; border: 1.5px solid var(--fn-border, #ccd3dd);
  border-radius: var(--fn-radius-sm, 10px); padding: 14px 18px; }
.cart-tariff__eyebrow { display: block; font-size: .72rem; font-weight: 700; letter-spacing: .1em;
  color: var(--fn-slate, #5A6982); margin-bottom: 4px; }
.cart-tariff__row { display: flex; justify-content: space-between; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.cart-tariff__name { font-weight: 800; font-size: 1.08rem; }
.cart-tariff__price { font-weight: 800; font-size: 1.08rem; white-space: nowrap; }
.cart-tariff__meta { margin: 3px 0 8px; color: var(--fn-slate, #5A6982); font-size: .88rem; }
/* Einmaliger Anschlusspreis in der Warenkorb-Karte (Steppe, 28.08.2026).
   Eigene Zeile unter dem Monatspreis, Betrag rechtsbuendig unter ihm — nicht
   in die Leistungsliste, wo eine Kostenposition wie eine Inklusivleistung
   aussieht (derselbe Fehler wie im Panel am 27.08.). */
.cart-tariff__once { display: flex; justify-content: space-between; align-items: baseline;
  gap: 14px; margin: 0 0 8px; font-size: .92rem; color: var(--fn-slate, #5A6982); }
.cart-tariff__once b { color: var(--fn-navy, #092043); font-weight: 800; white-space: nowrap; }
/* Kontrast: green-d misst nur ~3,9:1 auf Weiss - axe-Gate verlangt 4,5:1,
   daher Navy wie die uebrigen Links. */
/* 19 px hoch gemessen (WCAG 2.2 verlangt 24) — dieselbe unsichtbare Hitbox
   wie bei den Dokumentlinks darueber, damit die Karte optisch gleich bleibt. */
.cart-tariff__switch { font-weight: 700; font-size: .9rem; color: var(--fn-navy, #092043);
  text-decoration: underline; display: inline-block; padding-block: 12px; margin-block: -12px; }
/* Tarifdokumente im Warenkorb (Steppe, 24.08.2026). Die Klartext-Variante
   traegt bewusst KEINE Linkoptik — sie steht nur, solange freenet die URLs
   nicht geliefert hat. Gepinnt in no_dead_links_test.rb. */
.cart-tariff__docs { margin: 0 0 8px; font-size: .84rem; display: flex; flex-wrap: wrap; gap: 14px; }
.cart-tariff__docs a { font-weight: 700; color: var(--fn-navy, #092043); text-decoration: underline; padding-block: 12px; margin-block: -12px; }
.cart-tariff__docs-plain { font-weight: 400; color: var(--fn-slate, #5A6982); }

/* Gruener Selected-State + Badges fuer reiche Optionen (wie alter Prototyp) */
.radio-option--rich:has(input:checked) {
  background: #eef5e4; border-color: var(--fn-green-d);
  box-shadow: 0 0 0 1.5px var(--fn-green-d) inset;
}
.radio-option--rich:has(input:checked) input { accent-color: var(--fn-green-d); }
.opt-badge { display: inline-block; background: var(--fn-green, #84BC34); color: var(--fn-navy, #092043);
  font-size: .72rem; font-weight: 800; border-radius: 999px; padding: 2px 10px; margin-left: 8px;
  vertical-align: 1px; letter-spacing: .02em; }

/* --- Erklaerung des Auftraggebers (Bestelluebersicht) -------------------
   1:1 aus dem echten freenet-Checkout: Erklaerungstext plus Dokumentenliste
   ueber dem Bestell-Button, darunter die (optionale) Werbeeinwilligung und
   die Kenntnisnahme der vorvertraglichen Dokumente. Bewusst ruhiger gesetzt
   als der Rest des Steps — es ist Pflichttext, kein Verkaufsargument. */
.declaration {
  margin-top: 28px;
  padding-top: 22px;
  border-top: 1px solid var(--fn-border, #ccd3dd);
  font-size: .84rem;
  line-height: 1.55;
  color: var(--fn-slate);
}
.declaration h2 { font-size: 1rem; margin: 0 0 12px; color: var(--fn-navy); }
.declaration h3 { font-size: .9rem; margin: 22px 0 8px; color: var(--fn-navy); }
.declaration p { margin: 0 0 10px; }

.declaration__docs { list-style: none; margin: 6px 0 10px; padding: 0; }
.declaration__docs li { margin: 0 0 4px; }
.declaration__docs a { color: var(--fn-navy); font-weight: 700; text-decoration: none; }
.declaration__docs a:hover { text-decoration: underline; }
/* Links im Fliesstext der Erklaerung (AGB zum Online-Postfach) sehen aus wie
   die Dokumentlinks: fett, nicht unterstrichen (Steppe, 02.09.2026). */
.declaration__link { color: var(--fn-navy); font-weight: 700; text-decoration: none; }
.declaration__link:hover { text-decoration: underline; }
/* Klartext-Eintraege in der Dokumentenliste (Tarif-Konditionen, solange
   freenet die URL nicht geliefert hat). Vorher trugen sie exakt Farbe UND
   Staerke der echten Anker daneben und waren von einem Link nicht zu
   unterscheiden — Steppe hat am 24.08.2026 genau das gemeldet ("der Link zu
   den Tarifkonditionen ist nicht verlinkt"). Jetzt Slate statt Navy und
   normale Staerke: es liest sich als Aufzaehlungspunkt, nicht als Link.
   Gepinnt in no_dead_links_test.rb. */
.declaration__docs-plain { font-weight: 400; color: var(--fn-slate); }
.declaration__docs-note { font-style: italic; }

/* Haken und Text nebeneinander, Checkbox oben buendig — der Fliesstext ist
   lang, ein zentriertes Kaestchen wandert sonst in die Textmitte.

   Trefferflaeche 25.08.2026 (Steppe: "Mobil fehlt die VZF zum Anhaken"):
   der Befund liess sich bei 390px nicht nachstellen — die Checkbox ist da
   und sichtbar. Was sich aber messen liess: sie war 18x18px in einem Block
   mit font-size .84rem, also weit unter den 44px, die WCAG 2.2 SC 2.5.8 als
   Mindest-Trefferflaeche vorsieht. Auf einem echten Telefon ist so ein
   Kaestchen leicht zu uebersehen und schwer zu treffen — das ist unabhaengig
   davon richtig zu beheben, ob es die Ursache ihres Befundes war.
   Die Trefferflaeche selbst war nie das Problem: das <input> steht INNERHALB
   des <label>, damit ist der gesamte Textblock klickbar. Gefehlt hat die
   Sichtbarkeit. Das Kaestchen waechst deshalb auf 22px und bekommt oben etwas
   Luft, damit es neben der ersten Textzeile steht statt darunter zu rutschen.
   Kein padding-Trick am nativen Checkbox-Element — der rendert je nach
   Browser unterschiedlich und haette in Safari genau das Risiko erzeugt, das
   hier gerade untersucht wird.
   Gepinnt in test/e2e/mobile_declaration.rb. */
.declaration__check { display: flex; gap: 10px; align-items: flex-start; margin: 0 0 8px; min-height: 24px; }
.declaration__check input[type="checkbox"] {
  margin-top: 1px; flex: 0 0 auto; width: 22px; height: 22px;
}

.declaration__hint { font-size: .78rem; font-style: italic; }

/* Pflicht vs. freiwillig sichtbar machen (Steppe, 14.08.): kleiner Tag
   neben der Zwischenueberschrift; der Pflicht-Tag traegt Navy, der
   freiwillige bleibt neutral. */
.declaration__tag {
  display: inline-block; vertical-align: middle; margin-left: 6px;
  font-size: .68rem; font-weight: 700; letter-spacing: .02em;
  padding: 2px 8px; border-radius: 999px;
  background: #eef1f6; color: var(--fn-slate, #5a6b85);
}
.declaration__tag--required { background: var(--fn-navy); color: #fff; }

/* Fehlerzustand des Pflicht-Hakens: dieselbe .field/.is-invalid-Mechanik
   wie bei den Formularfeldern — Rahmen um den Haken-Block, Fehlertext
   darunter sichtbar. */
.declaration__field { margin: 0 0 8px; }
/* Der .field-Wrapper bringt sein fettes Label-Styling mit — der lange
   Erklaertext soll aber wie zuvor als Fliesstext laufen. */
.declaration__field .declaration__check { font-weight: 400; }
.declaration__field .field__error { display: none; }
.declaration__field.is-invalid {
  border: 1.5px solid var(--fn-red);
  border-left-width: 4px;
  border-radius: var(--fn-radius-sm);
  padding: 10px 12px 8px;
  background: #fdecef;
}
.declaration__field.is-invalid .field__error { display: block; }


/* ---- Tarifdetail-Overlay (Hendrik, 28.08.2026) --------------------------
   freenets eigener Detail-Layer, bei uns im eigenen Fenster statt als
   Absprung. Desktop: zentriertes Fenster. Mobil: echte Vollseite mit dem
   Schliessen-Knopf im Daumenbereich — ein zentriertes Modal auf dem Handy ist
   in der Hausregel (Breakpoint-Rulebook M1/M3) ausgeschlossen, und Hendrik hat
   am 28.08. ausdruecklich "auf Mobile eine volle Seite" verlangt.

   Aufbau als Flex-Spalte statt mit Hoehen-Rechnerei: Kopf und Fuss fest, der
   Inhalt dazwischen scrollt. calc(100% - 132px) waere geraten und bricht,
   sobald der Kopf zweizeilig wird.

   Abstaende auf einem 4er-Raster: 4 / 8 / 12 / 16 / 20 / 24. Vorher standen
   hier 6, 7, 14 und 18 px nebeneinander — das ist genau die Unruhe, die
   Hendrik am 28.08. an der Einrueckung gesehen hat. */
dialog.tdov { border: 0; padding: 0; border-radius: 16px; max-width: 640px;
  width: calc(100% - 32px); max-height: 86vh; box-shadow: 0 18px 48px rgba(9, 32, 67, .3);
  color: var(--fn-ink, #092043); overflow: hidden; }
dialog.tdov[open] { display: flex; flex-direction: column; }
dialog.tdov::backdrop { background: rgba(9, 32, 67, .55); }
/* Die Seite hinter dem Overlay darf nicht mitscrollen: showModal() allein
   haelt sie auf iOS nicht fest. */
html.tdov-open, html.tdov-open body { overflow: hidden; }

.tdov__head { flex: 0 0 auto; background: var(--fn-navy, #092043); color: #fff;
  padding: 16px 20px; display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.tdov__head h2 { font-family: var(--fn-font-display); font-size: 1.05rem; margin: 0 0 4px; color: #fff; }
.tdov__head p { margin: 0; font-size: .82rem; opacity: .82; }
.tdov__x { background: none; border: 0; color: #fff; font-size: 1.6rem; line-height: 1;
  cursor: pointer; padding: 0; min-width: 44px; min-height: 44px; margin: -8px -8px 0 0;
  border-radius: 50%; }
/* showModal() setzt den Fokus auf den ersten Knopf. Ohne eigene Regel malt der
   Browser ein hartes weisses Rechteck in die dunkle Kopfzeile. */
.tdov__x:focus-visible { outline: 2px solid var(--fn-green, #84BC34); outline-offset: 2px; }

.tdov__body { flex: 1 1 auto; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch; padding: 4px 20px 24px; }

.tdov__cat + .tdov__cat { margin-top: 24px; }
.tdov__cat h3 { font-family: var(--fn-font-display); font-size: .78rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--fn-slate, #5A6982); margin: 20px 0 4px; }
.tdov__cat:first-child h3 { margin-top: 16px; }
.tdov__hl { margin: 8px 0 0; padding-left: 20px; }
.tdov__hl li { margin: 4px 0; font-size: .92rem; }

/* Schluessel/Wert: der Schluessel nimmt den Rest, der Wert nur, was er
   braucht. Ohne feste Flex-Anteile bricht bei langen Schluesseln der Wert mit
   um und die Spalte franst aus. */
.tdov__kv { display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  padding: 8px 0; border-bottom: 1px solid #eef1f6; font-size: .92rem; }
.tdov__kv:last-child { border-bottom: 0; }
.tdov__k { flex: 1 1 auto; min-width: 0; color: var(--fn-slate, #5A6982); overflow-wrap: anywhere; }
.tdov__k sup { color: var(--fn-green-d, #659A0A); font-weight: 700; margin-left: 1px; }
.tdov__v { flex: 0 0 auto; text-align: right; font-weight: 600;
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
/* Lange Werte (Laufzeittext, Netzliste) stehen unter ihrem Schluessel — rechts
   gebrochen ergeben sie eine Treppe aus zwei bis drei Woertern je Zeile. */
.tdov__kv.is-stacked { display: block; }
.tdov__kv.is-stacked .tdov__v { display: block; flex: none; text-align: left; font-weight: 400;
  margin-top: 4px; color: var(--fn-ink, #092043); }

/* Untergeordnete Zeilen als Gruppe mit einer Leiste — eine blosse Einrueckung
   liest sich wie ein Versatz, nicht wie Zugehoerigkeit. */
.tdov__group { margin: 0 0 0 4px; padding-left: 12px; border-left: 2px solid #e6ebf3; }
.tdov__group .tdov__kv:last-child { border-bottom: 0; }
.tdov__group + .tdov__kv { border-top: 1px solid #eef1f6; }

.tdov__note { margin: 12px 0 0; font-size: .8rem; color: var(--fn-slate, #5A6982); }
/* Die Fussnote lief mit .75rem auf 99 Zeichen je Zeile — ueber der Grenze von
   ~75 (Y4). Groesser gesetzt und auf 68 Zeichen begrenzt liest sie sich. */
.tdov__legal { margin: 16px 0 0; font-size: .8rem; color: var(--fn-slate, #5A6982);
  line-height: 1.55; max-width: 68ch; }
.tdov__legal sup { color: var(--fn-green-d, #659A0A); font-weight: 700; }
.tdov__src { margin: 16px 0 0; padding-top: 12px; border-top: 1px solid #eef1f6;
  font-size: .72rem; color: #7A879B; overflow-wrap: anywhere; }
/* Das Tippziel war 15 px hoch (WCAG 2.2 verlangt 24). Unsichtbare Hitbox
   ueber padding/negative margin, damit die Zeile optisch bleibt, wo sie ist —
   derselbe Griff wie bei .cart-tariff__docs a. */
.tdov__src a { color: inherit; text-decoration: underline; display: inline-block;
  padding-block: 15px; margin-block: -15px; }

/* Desktop schliesst oben rechts; der Fuss ist die Daumenzone des Handys. */
.tdov__foot { display: none; }
@media (max-width: 640px) {
  dialog.tdov { max-width: none; width: 100%; max-height: none; margin: 0; border-radius: 0;
    height: 100dvh; }
  .tdov__body { padding: 4px 16px 24px; }
  .tdov__foot { display: block; flex: 0 0 auto; background: #fff;
    border-top: 1px solid var(--fn-border, #ccd3dd);
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom)); }
  .tdov__foot button { width: 100%; min-height: 48px; background: var(--fn-navy, #092043); color: #fff;
    border: 0; border-radius: 28px; font-weight: 700; font-size: 1rem; cursor: pointer; }
}

/* --- Aktionscode (29.08.) ------------------------------------------------ */
.promo-row { display: flex; gap: 8px; align-items: stretch; }
.promo-row input { flex: 1; min-width: 0; }
.promo-apply { border: 1px solid var(--ink, #0F2A46); background: #fff; color: var(--ink, #0F2A46);
  border-radius: 10px; padding: 0 18px; font-weight: 700; cursor: pointer; white-space: nowrap; }
.promo-apply:hover { background: var(--ink, #0F2A46); color: #fff; }
.promo-chip { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: #eef7dc; border: 1px solid #b9d78a; border-radius: 10px;
  padding: 10px 14px; margin: 0 0 10px; }
.promo-chip__check { color: #4C9F38; font-weight: 800; }
.promo-chip__remove { margin-left: auto; border: none; background: none; color: #5a6982;
  text-decoration: underline; cursor: pointer; font: inherit; font-size: .85rem; padding: 0; }
.promo-chip__remove:hover { color: #b3261e; }
.promo-error { background: #fdeaea; color: #8c2f39; border-radius: 8px;
  padding: 8px 12px; margin: 8px 0 0; font-size: .9rem; }
.promo-strike { color: #8a95a5; margin-right: 6px; }
.order-panel__promo { margin: 6px 0 0; font-size: .85rem; color: #2c6b4f; }

/* Default-Button fuer die Enter-Taste im Warenkorb (siehe cart.html.erb).
   Weggeclippt statt display:none, damit er in jedem Browser ein gueltiger
   Default-Button bleibt. */
.enter-submit {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
