/* =========================================================================
   Shop-Relaunch — Warenkorb (/relaunch/cart)
   Eigenstaendiges Stylesheet, baut auf den Tokens aus relaunch.css auf
   (--ink, --line, --cta, --paper-2, --r-* …). Spec-Row-Optik wie home.html,
   Summary-Card wie der Checkout. Kein Token wird hier neu erfunden.
   ========================================================================= */

.cart-page { padding: 56px 0 88px; }
.cart-page .wrap { max-width: 1080px; }

/* ---- Kopf ---- */
.cart-page-head { max-width: 640px; margin-bottom: 34px; }
.cart-page-head h1 {
  font-size: clamp(28px, 4.4vw, 40px); line-height: 1.08; letter-spacing: -.02em;
  margin: 12px 0 0; color: var(--ink);
}
.cart-page-head .lede { margin: 14px 0 0; font-size: 16px; line-height: 1.55; color: var(--ink-2); }

/* =========================================================================
   Leerer Warenkorb
   ========================================================================= */
.cart-empty-state {
  text-align: center; max-width: 460px; margin: 30px auto 0;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-2xl);
  padding: 54px 32px; box-shadow: var(--shadow-md);
}
.cart-empty-state svg { color: var(--ink-3); }
.cart-empty-state h2 { font-size: 21px; margin: 16px 0 0; color: var(--ink); }
.cart-empty-state p { margin: 10px 0 24px; color: var(--ink-2); line-height: 1.55; }

/* =========================================================================
   Grid
   ========================================================================= */
.cart-grid {
  display: grid; grid-template-columns: 1fr 348px; gap: 34px; align-items: start;
}

/* =========================================================================
   Korb-Karte — Positionen, Laufzeit und Zusagen in EINER Flaeche
   Vorher waren das drei gestapelte Kaesten mit je eigenem Rahmen und
   Schatten. Die Karte traegt den Rahmen jetzt einmal; die Innenteile geben
   ihren eigenen ab und trennen sich nur noch mit einer Linie.
   ========================================================================= */
.cart-box { background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-md); overflow: hidden; }
.cart-box .cart-lines { background: none; border: 0; border-radius: 0;
  box-shadow: none; overflow: visible; }
.cart-box .cart-duration { margin: 0; border: 0; border-radius: 0; box-shadow: none;
  border-top: 1px solid var(--line); background: none; }

/* =========================================================================
   Positionen (Spec-Rows)
   ========================================================================= */
.cart-lines { list-style: none; margin: 0; padding: 0;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-md); overflow: hidden;
}
.cart-line {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto auto 34px;
  align-items: center; gap: 18px;
  padding: 20px 22px; border-top: 1px solid var(--line);
  transition: opacity .18s ease;
}
.cart-line:first-child { border-top: 0; }
.cart-line[data-busy="1"] { opacity: .5; pointer-events: none; }

.cl-logo img { width: 34px; height: 34px; border-radius: 50%; object-fit: contain;
  background: #fff; box-shadow: inset 0 0 0 1px rgba(22,32,46,.08); display: block; }
.cl-logo .badge { width: 34px; height: 34px; border-radius: 50%; color: #fff;
  font-size: 15px; font-weight: 700; display: grid; place-items: center; }

.cl-main { min-width: 0; }
/* hyphens vor break-word: passt ein langes Wort nicht in die Spalte, trennt der
   Browser es nach deutschen Silbenregeln mit Trennstrich (das <html lang="de">
   liefert das Woerterbuch). break-word bleibt als letzte Reissleine fuer Woerter
   ohne Trennstelle stehen — es allein hat mitten im Wort geschnitten.
   hyphenate-limit-chars: erst ab 12 Zeichen trennen, sonst zerlegt der Browser
   auch kurze Woerter, um die Zeile zu fuellen ("Vodafone Business Pri-me S" bei
   390px gesehen). Nur der Gesamtwert wird gesetzt — gibt man auch Mindestlaengen
   vor der und nach der Trennstelle vor, findet der Browser in einer 82px-Spalte
   keine erlaubte Stelle mehr und schneidet wieder hart mitten im Wort. */
.cl-name { display: block; font-size: 16px; font-weight: 560; color: var(--ink);
  line-height: 1.3; text-decoration: none; hyphens: auto;
  hyphenate-limit-chars: 12; overflow-wrap: break-word; }
.cl-net { font-size: 13px; color: var(--ink-3); margin-top: 2px; }
.cl-unit { font-size: 13.5px; color: var(--ink-2); margin-top: 6px; }
.cl-unit small { color: var(--ink-3); }
/* Mischwarenkorb-Hinweis (Task #101): Tarif nur mit 24 Monaten buchbar. Dezenter
   Info-Look (kein Fehler-Rot); bg = exakt der getoente CTA-Ton der Laufzeit-Wahl. */
.cl-fix24 { display: flex; align-items: flex-start; gap: 6px; margin: 8px 0 0;
  padding: 6px 9px; border-left: 2.5px solid var(--cta); border-radius: 0 6px 6px 0;
  background: rgba(255,104,0,.05); font-size: 12.5px; line-height: 1.4; color: var(--ink-2); }
.cl-fix24 svg { width: 14px; height: 14px; flex: none; margin-top: 1px; color: var(--cta); }

/* Mengen-Stepper */
.cl-qty { text-align: center; }
.cl-qty-lbl { display: block; font-size: 11px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-3); margin-bottom: 6px; }
.stepper { display: inline-flex; align-items: center;
  border: 1px solid var(--line); border-radius: 980px; background: var(--paper-2); }
/* Fokus-Ring auf die ganze Pille legen, da das randlose Zahlenfeld outline:none traegt
   (sonst verliert die Mengen-Eingabe den globalen :focus-visible-Indikator). */
.stepper:focus-within { outline: 2.5px solid var(--cta); outline-offset: 3px; }
.stepper button {
  width: 44px; height: 44px; border: 0; background: transparent; cursor: pointer;
  font-size: 19px; line-height: 1; color: var(--ink); border-radius: 50%;
  display: grid; place-items: center; transition: background .15s ease;
}
.stepper button:hover { background: rgba(22,32,46,.07); }
.stepper button:disabled { color: var(--ink-3); cursor: not-allowed; background: transparent; }
.step-val { width: 44px; align-self: stretch; border: 0; background: transparent; text-align: center;
  font-size: 16px; font-weight: 560; color: var(--ink); padding: 0; }
.step-val:focus { outline: none; }

.cl-line { text-align: right; font-size: 16px; font-weight: 600; color: var(--ink);
  white-space: nowrap; }
.cl-line small { display: block; font-size: 12px; font-weight: 480; color: var(--ink-3); }

.cl-remove { border: 0; background: transparent; cursor: pointer; color: var(--ink-3);
  width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
  transition: background .15s ease, color .15s ease; }
.cl-remove:hover { background: rgba(226,0,116,.08); color: var(--vodafone); }

/* =========================================================================
   Laufzeit-Wahl
   ========================================================================= */
.cart-duration {
  margin: 22px 0 0; padding: 22px 24px;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-md);
  display: flow-root; /* etabliert BFC, faengt den legend-Float → Box haelt die Hoehe */
  /* Ein <fieldset> traegt per UA-Voreinstellung min-inline-size:min-content und
     schrumpft nie darunter. Bei 280px ragte die Box dadurch 25px ueber den
     Seitenrand und riss die ganze Seite in den H-Scroll (gemessen, Bestand). */
  min-inline-size: 0;
}
/* Ein natives <legend> sitzt IN der oberen fieldset-Rahmenlinie und ragt ueber die
   abgerundete Ecke (r-lg). float+width:100% loest es aus dem Border-Slot in den
   normalen Fluss, sodass die Ueberschrift sauber INNERHALB der Box beginnt. */
.cart-duration legend { float: left; width: 100%; font-size: 16px; font-weight: 600; color: var(--ink); padding: 0; }
.dur-hint { font-size: 13.5px; color: var(--ink-2); margin: 6px 0 16px; line-height: 1.5; }
/* Wrapper um die beiden Optionen. Auf dem Desktop loest er sich auf, damit das
   Bestandslayout (Labels als direkte fieldset-Kinder) unveraendert bleibt; auf
   dem Telefon wird er ab 340px zum Zwei-Spalten-Raster (siehe Responsive). */
.dur-opts { display: contents; }
/* Der span um das Radio ist das Flex-Kind von .dur-opt (frueher war es das Radio
   selbst) — ohne flex:none koennte er unter Platzdruck schrumpfen. */
.dur-head { flex: none; display: inline-flex; align-items: center; }
.dur-opt { display: flex; align-items: flex-start; gap: 13px; cursor: pointer;
  padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--r-md);
  margin-top: 10px; touch-action: manipulation;
  transition: border-color .15s ease, background .15s ease; }
.dur-opt:hover { background: var(--paper-2); }
.dur-opt:has(input:checked) { border-color: var(--cta); background: rgba(255,104,0,.05); }
.dur-opt input { margin: 2px 0 0; width: 18px; height: 18px; accent-color: var(--cta); flex: none; }
.dur-body { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.dur-t { font-size: 15px; font-weight: 560; color: var(--ink); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dur-d { font-size: 13px; color: var(--ink-2); }
/* D1: Effektivpreis je Laufzeit-Option, rechtsbuendig. Wert aus durationPrices
   (Backend-Accessor); reine Anzeige, nie hier gerechnet. */
.dur-price { flex: none; margin-left: auto; text-align: right; display: flex;
  flex-direction: column; align-items: flex-end; padding-left: 12px; }
.dur-eff { font-size: 16px; font-weight: 640; color: var(--ink); white-space: nowrap; }
.dur-price small { font-size: 11px; color: var(--ink-3); margin-top: 1px; white-space: nowrap; }
/* Gruen statt Orange: die gewaehlte Option ist selbst orange getoent, darin ging
   das Badge unter. Gruen loest es aus der Flaeche und liest sich als Gewinn. */
/* Farbe bewusst dunkler als --green-strong (#1e7a3a): das Badge sitzt auf einem
   doppelt getoenten Grund (gewaehlte Option rgba(255,104,0,.05), darauf die eigene
   Fuellung rgba(30,122,58,.11) = rgb(230,234,222)). Der Token erreicht dort nur
   4,40:1 und faellt durch; #1a6b33 liefert 5,37:1. Gemessen, nicht geschaetzt. */
.dur-tag { font-size: 11.5px; font-weight: 600; color: #1a6b33;
  background: rgba(30,122,58,.11); border-radius: 980px; padding: 2px 9px; letter-spacing: .01em; }

/* =========================================================================
   Zusagen — Fussleiste derselben Karte
   Bewusst ohne eigene Flaeche und ohne eigenen Rahmen: die Zusagen gehoeren
   zum Korb und sitzen unter derselben Trennlinie wie die Laufzeit. Zwei
   Spalten, damit vier Punkte nicht als lange Liste wirken.
   ========================================================================= */
.cart-assure { list-style: none; margin: 0; padding: 13px 16px 15px;
  border-top: 1px solid var(--line);
  display: grid; grid-template-columns: 1fr 1fr; gap: 9px 20px; }
/* flex-start (nicht center): sobald eine Zusage zweizeilig umbricht, saesse ein
   zentriertes Icon zwischen den Zeilen statt an der ersten — .cl-fix24 macht es
   beim gleichen Muster genauso. */
.cart-assure li { display: flex; align-items: flex-start; gap: 8px;
  font-size: 13px; color: var(--ink-2); line-height: 1.4; }
.cart-assure li > span { min-width: 0; overflow-wrap: break-word; }
.cart-assure b { color: var(--ink); font-weight: 600; }
.cart-assure svg { width: 16px; height: 16px; color: var(--green-strong); flex: none; margin-top: 1px; }

/* =========================================================================
   Gutscheincode
   ========================================================================= */
.cart-coupon { margin: 22px 0 0; padding: 22px 24px;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-md); }
.cp-lbl { display: block; font-size: 16px; font-weight: 600; color: var(--ink); margin-bottom: 12px; }
.cp-row { display: flex; gap: 10px; }
.cp-input { flex: 1; min-width: 0; height: 44px; padding: 0 16px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--paper-2);
  /* 16px: verhindert iOS-Auto-Zoom beim Fokus (Inputs < 16px zoomen auf iPhone). */
  font-size: 16px; color: var(--ink); transition: border-color .15s ease, background .15s ease; }
.cp-input:focus { outline: none; border-color: var(--cta); background: #fff; box-shadow: 0 0 0 3px rgba(255,104,0,.12); }
.cp-input:disabled { color: var(--ink-2); }
.cp-row .btn-sm { white-space: nowrap; }
.cp-msg { font-size: 13px; line-height: 1.5; margin: 12px 0 0; min-height: 1px; overflow-wrap: break-word; }
.cp-msg.is-ok { color: var(--green-strong); }
.cp-msg.is-err { color: #c0392b; }
.cart-coupon[data-active="1"] .cp-msg { color: var(--green-strong); }

/* Von der Adressverwaltung gefuellte Felder faerbt Chrome hellblau ein und
   ueberschreibt dabei jede Hintergrundfarbe. Der Hintergrund laesst sich nur ueber
   einen fetten inset-Schatten zurueckholen (background-color allein greift nicht),
   die Schriftfarbe nur ueber -webkit-text-fill-color; die absurd lange transition
   ist der uebliche Kniff, damit das Blau nach dem Ausfuellen gar nicht erst
   durchblitzt. Die Fokus-Regel muss den inset-Schatten mitfuehren, sonst faellt
   beim Hineinklicken alles wieder auf Blau zurueck.
   BEWUSST nur das Gutscheinfeld, nicht global: die Kasse traegt ihr gruenes
   Gueltig-Haekchen als background-image IM Feld (relaunch-checkout.css,
   .co .field input.valid) — ein inset-Schatten zeichnet darueber und wuerde das
   Haekchen bei automatisch gefuellten Feldern verschlucken. Die Kasse braucht
   dafuer erst ein Haekchen, das nicht im Hintergrund liegt. Das E-Mail-Feld der
   Express-Reservierung bringt dieselbe Regel selbst mit (express-overlay.css). */
.cp-input:-webkit-autofill, .cp-input:-webkit-autofill:hover {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--paper-2) inset;
  caret-color: var(--ink);
  transition: background-color 9999s ease-in-out 0s;
}
.cp-input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--paper) inset, 0 0 0 3px rgba(255, 104, 0, .12);
}

/* Fehler-Hinweis bei fehlgeschlagener Cart-Mutation (JS-injiziert, siehe relaunch-cart.js). */
.cart-status { margin: 14px 0 0; font-size: 14px; line-height: 1.5; color: #c0392b; overflow-wrap: break-word; }
.cart-status[hidden] { display: none; }

/* =========================================================================
   Summary-Card (sticky)
   ========================================================================= */
.cart-summary { position: sticky; top: 24px; }
.cs-card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg); padding: 26px 26px 24px; }
.cs-h { font-size: 13px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-3); margin: 0 0 18px; font-weight: 600; }
/* D3: Die fruehere .cs-total-Zeile ist durch das Aufschluesselungs-Partial (.bd,
   relaunch.css) ersetzt; .bd-foot schliesst den Block ab. Davor ein Trenner zu den Aktionen. */
.cs-actions { display: flex; flex-direction: column; gap: 10px;
  margin: 20px 0 0; padding-top: 20px; border-top: 1px solid var(--line); }
.cs-actions .btn { width: 100%; }

.tnum { font-variant-numeric: tabular-nums; }

/* =========================================================================
   Responsive
   ========================================================================= */
@media (max-width: 980px) {
  .cart-grid { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .cart-summary { position: static; }
}

/* Kleben nur, solange die Karte ins Fenster passt. Gemessen: 771px hoch, plus
   24px oben und unten braucht sie 819px Fensterhoehe; laengere Aufschluesselungen
   (Rahmenrabatt + Aktion gleichzeitig) kommen darueber, daher 860px als Schwelle.
   Klebt eine zu hohe Karte, bleibt ihr unteres Ende samt Bestell-Knopf beim
   Scrollen unter der Fensterkante haengen — dann ist mitscrollen besser. */
@media (max-height: 860px) {
  .cart-summary { position: static; }
}

@media (max-width: 620px) {
  .cart-line {
    /* Spalte 3 = auto (nicht 34px): der Zeilenpreis (.cl-line, white-space:nowrap)
       ist ~59px breit und wuerde in einer 34px-Spalte horizontal ueberlaufen — der
       Preis wird rechts abgeschnitten UND der H-Overflow verschiebt das ganze
       Folge-Layout (Laufzeit-Card). auto laesst die Spalte auf Preisbreite wachsen. */
    grid-template-columns: 40px minmax(0, 1fr) auto;
    grid-template-areas:
      "logo main remove"
      "logo qty  line";
    row-gap: 14px; column-gap: 14px; padding: 18px;
  }
  .cl-logo { grid-area: logo; align-self: start; }
  .cl-main { grid-area: main; }
  .cl-qty { grid-area: qty; text-align: left; }
  .cl-qty-lbl { display: none; }
  .cl-line { grid-area: line; text-align: right; align-self: center; }
  /* Muelleimer in der jetzt preisbreiten Spalte 3 rechtsbuendig halten. */
  .cl-remove { grid-area: remove; align-self: start; justify-self: end; }

  /* Zusagen untereinander — zwei Spalten sind auf dem Telefon zu schmal. */
  .cart-assure { grid-template-columns: 1fr; gap: 9px; }

  /* Laufzeit: Preis unter den Text. Nebeneinander laufen beide unter 340px
     ineinander, weil .dur-eff und .dur-price small nowrap tragen. */
  .dur-opt { flex-direction: column; align-items: stretch; gap: 8px; padding: 12px 12px 13px; }
  .dur-opt input { margin: 0; }
  .dur-head { display: flex; align-items: center; gap: 8px; }
  .dur-body { gap: 2px; }
  .dur-t { font-size: 14px; }
  .dur-d { font-size: 12px; }
  .dur-price { margin-left: 0; text-align: left; align-items: flex-start;
    padding-left: 0; border-top: 1px solid var(--line); padding-top: 8px; }
  .dur-tag { font-size: 10.5px; padding: 2px 7px; }
}

/* Erst ab 340px ist die Spalte breit genug fuer zwei Laufzeit-Karten
   nebeneinander. Darunter bleibt es untereinander — gemessen, nicht geschaetzt:
   bei 280 und 320 zerreissen sonst „reguläre Laufzeit" und das Badge. */
@media (min-width: 340px) and (max-width: 620px) {
  .dur-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
  .dur-opt { margin-top: 0; }
}

/* Unter 360px kippt die dreispaltige Positionszeile. Gemessen bei 280px: Spalte 3
   steht auf auto und richtet sich nach dem Zeilenpreis (white-space:nowrap, rund
   108px) — dem Tarifnamen bleiben dann 65px und er zerfaellt in fuenf Zeilen,
   waehrend der 132px breite Stepper ueber seine Spalte hinauslaeuft und bis auf
   den Spaltenabstand an den Preis stoesst. Beide Beschwerden haben dieselbe
   Ursache: zu viel nebeneinander. Preis in eine eigene Zeile, Spalte 3 damit auf
   die Breite des Loeschen-Knopfs festgenagelt — der Name bekommt rund 130px. */
@media (max-width: 359px) {
  .cart-line {
    grid-template-columns: 40px minmax(0, 1fr) 44px;
    grid-template-areas:
      "logo main   remove"
      "qty  qty    qty"
      "line line   line";
    row-gap: 10px;
  }
  .cl-line { justify-self: end; }
  /* "je Karte" weg: mit dem Zusatz braucht der Einzelpreis hier drei Zeilen
     ("€ 12,58" / "/ Monat je" / "Karte"). Der Mengenwaehler steht direkt
     darunter, der Bezug bleibt ohne den Zusatz erhalten. */
  .cl-unit-je { display: none; }
}

/* Die Vorteilspreis-Zeile ist eine Flex-Zeile aus zwei nicht umbrechenden
   Haelften (Badge und Preis je white-space:nowrap). Unter 340px passen sie
   nicht nebeneinander und schoben die Seite in den H-Scroll (Bestand). */
@media (max-width: 339px) {
  .bd-row--total { flex-direction: column; align-items: flex-start; gap: 4px; }
  .bd-total { align-items: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  .cart-line, .stepper button, .cl-remove, .dur-opt, .cp-input { transition: none; }
}
