@font-face{font-family:'Open Sans';src:url("../fonts/opensans-latin.woff2") format('woff2');font-weight:300 800;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Open Sans';src:url("../fonts/opensans-latin-ext.woff2") format('woff2');font-weight:300 800;font-style:normal;font-display:swap;unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Montserrat';src:url("../fonts/montserrat-latin.woff2") format('woff2');font-weight:100 900;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Montserrat';src:url("../fonts/montserrat-latin-ext.woff2") format('woff2');font-weight:100 900;font-style:normal;font-display:swap;unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}

/* Metric-matched fallbacks (Arial, size-adjusted) so the swap from fallback to
   the self-hosted webfont barely moves layout — kills most font-swap CLS while
   the real Montserrat/Open Sans still render once loaded. */
@font-face{font-family:'Montserrat-fallback';src:local('Arial');ascent-override:81.62%;descent-override:21.16%;line-gap-override:0%;size-adjust:112.46%}
@font-face{font-family:'Open Sans-fallback';src:local('Arial');ascent-override:101.68%;descent-override:27.86%;line-gap-override:0%;size-adjust:105.11%}

  :root{
    --blue-1:#092043; --blue-4:#C3CDDB; --blue-6:#EEF1F8;
    --coral-1:#EB5C47; --coral-2:#F18B71; --coral-3:#F6B49F;
    /* Coral als TEXT auf Weiß braucht eine dunklere Stufe: #EB5C47 misst nur
       3,4:1 (axe: serious). --coral-text haelt 5,2:1 und bleibt im Farbton.
       Fuer Flaechen (Badges) bleibt --coral-1. */
    --coral-text:#C2402D;
    --green-1:#84BC34; --green-2:#A0C860; --green-4:#E2EDCF; --green-7:#659A0A;
    --grey-1:#FBFDFF;
    --font-body:"Open Sans","Open Sans-fallback",system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;
    /* Echte freenet.de-Headline-Schrift (Typekit-Kit ccv5wla). Montserrat
       bleibt als metrisch aehnlicher Fallback, bis das Kit geladen ist. */
    --font-display:"canada-type-gibson","Montserrat","Montserrat-fallback",var(--font-body);
    --navy:var(--blue-1); --navy-2:#0E2243; --green:var(--green-1); --green-d:var(--green-7); --green-dd:#3E701E;
    --t-9c:var(--green-2); --t-b3:#C6DFA0; --t-e1:var(--green-4);
    --red:#df002e;
    --white:var(--grey-1); --g-f2:#f2f2f2; --g-e5:#e5e5e5; --g-ca:#cacaca;
    --slate:#5A6982; --soft:#E3E8F3;
    --ink:var(--blue-1);
    --radius:16px; --radius-sm:8px; --radius-btn:28px; --radius-pill:9999px; --radius-input:4px;
    --shadow-sm:0 2px 8px rgba(9,32,67,.16);
    --shadow-md:0 2px 8px rgba(9,32,67,.16);
    --shadow-lg:0 4px 16px rgba(9,32,67,.20);
    --maxw:1240px;
    --fs:clamp(16px,1rem,17px);
  }
  *{box-sizing:border-box}
  button,input,select,textarea,.btn{font-family:var(--font-body)}
  h1,h2,h3,h4,.display{font-family:var(--font-display);font-weight:700;letter-spacing:-.01em}
  html{-webkit-text-size-adjust:100%}
  body{
    margin:0;
    font-family:var(--font-body);
    font-size:var(--fs);
    line-height:1.55;
    color:var(--navy);
    background:var(--white);
    -webkit-font-smoothing:antialiased;
    text-rendering:optimizeLegibility;
  }
  h1,h2,h3{line-height:1.13;letter-spacing:-.02em;margin:0;font-weight:800}
  p{margin:0}
  a{color:inherit}
  img,svg{display:block}
  .wrap{max-width:var(--maxw);margin-inline:auto;padding-inline:20px}
  /* Der Header klebt oben. Ohne scroll-margin landet jedes Sprungziel
     ("Tarif ansehen" -> #tarif, "Haeufige Fragen" -> #faq-h2) unter dem
     Header: die Eyebrow-Zeile stand bei 46px, der Header endet bei 62px.
     62px Header + 12px Luft. Gilt auf allen Breiten: die Utility-Leiste steht
     als eigenes Element UEBER dem Header und klebt nicht mit. */
  #tarif,#bundles,#faq-h2{scroll-margin-top:74px}
  .eyebrow{
    font-size:.76rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
    color:var(--green-dd);margin:0 0 14px;
  }
  .eyebrow.on-navy{color:var(--t-9c)}
  .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

  /* ---------- Buttons ---------- */
  .btn{
    display:inline-flex;align-items:center;justify-content:center;gap:.5em;
    min-height:52px;padding:14px 26px;border-radius:999px;
    font-size:1.02rem;font-weight:800;letter-spacing:-.01em;
    text-decoration:none;cursor:pointer;border:0;
    transition:transform .14s ease, box-shadow .14s ease, background-color .14s ease, border-color .14s ease;
    will-change:transform;
  }
  .btn-primary{background:var(--blue-1);color:var(--grey-1);box-shadow:var(--shadow-sm)}
  .btn-coral{background:var(--coral-2);color:var(--blue-1);box-shadow:var(--shadow-sm)}
  .btn-green{background:var(--green-2);color:var(--blue-1)}
  
  .btn-primary:active{transform:translateY(0)}
  .btn-ghost{background:transparent;color:var(--navy);border:1px solid var(--g-ca);min-height:52px;padding:14px 26px}
  .btn-ghost:hover{border-color:var(--navy)}
  .btn-ghost.on-navy{color:#fff;border-color:rgba(255,255,255,.42)}
  .btn-ghost.on-navy:hover{border-color:#fff;background:rgba(255,255,255,.07)}
  .btn-block{width:100%}
  a:focus-visible,button:focus-visible,summary:focus-visible,input:focus-visible,select:focus-visible{
    outline:3px solid var(--green);outline-offset:2px;border-radius:8px;
  }
  .hero a:focus-visible,.hero button:focus-visible{outline-color:#cfe6a3}

  /* ---------- Header ---------- */
  /* Header 1:1 wie freenet.de: fast-schwarzes Navy, UPPERCASE-Nav,
     Lime-Rule unter dem Header. */
  /* Farbwerte direkt aus freenets eigenem CSS (fn-web4): Header #21314d,
     Utility-Chips #e3e8f3 auf Navy-Text, Mail-Chip #84bc34 mit weissem Text.
     (Der fruehere #0b1022 stammte aus einem vom Consent-Modal abgedunkelten
     Screenshot.) */
  header.site{
    position:sticky;top:0;z-index:50;background:#21314d;
  }
  /* 1:1 freenet.de (gemessen 05.08., 1280w): 3px Gruenstrich als ::after —
     zusammen mit Utility (28) + Nav (59) ergibt das deren exakt 90px. */
  header.site::after{content:"";display:block;height:3px;background:var(--green-1)}
  /* Header-Container: laeuft im GLEICHEN Raster wie der Seiteninhalt (--maxw).
     Vorher stand hier ein eigenes 1124er-Raster. Das war am 06.08. korrekt an
     freenet.de gemessen — uebersehen wurde nur, dass freenet seinen Inhalt
     ebenfalls schmal fuehrt: auf /handytarife/ohne-handy/ liegt .row bei 1104
     (x=168 @1440), das Logo bei x=178. Dort steht das Logo also praktisch
     buendig zur Headline. Bei uns blieb der Content auf --maxw (1240, x=120),
     also klafften Header und Inhalt 58px auseinander; unter 1123px kippte es
     durch das 10px-Padding auf 10px in die Gegenrichtung.
     Entscheidung Hendrik 13.08.: buendig schlaegt Pixeltreue, Header folgt
     --maxw. Strikte 1:1-Alternative waere andersrum --maxw auf 1104.
     Rueckbau = diese Regeln wieder aktivieren:
       .util .wrap,header.site .wrap{max-width:1124px}
       @media(max-width:1123px){.util .wrap,header.site .wrap{padding-inline:10px}} */
  /* Das Seitenraster gilt ohne Ausnahme, auch auf den schmalsten Geraeten.
     Moeglich geworden durch zwei Aenderungen an der Header-Zeile selbst:
     der Logo-Umschaltpunkt liegt bei 520 statt 460 (index.html.erb) und
     unter 400px traegt die Icon-Reihe vier statt sechs Eintraege (siehe
     .nav-icons__slim). Vorher lief der Header bei 320px 40px und zwischen
     460 und 499px bis zu 22px ueber den Rand. */
  .nav{display:flex;align-items:center;gap:12px;height:59px}
  /* Hoehe der Trefferflaeche auf 44 (HIG); Breite folgt dem Logo. */
  .brand{display:flex;align-items:center;text-decoration:none;padding-block:8px;margin-block:-8px}
  /* Gemessen ueber die ganze Breitenachse (06.08.): freenet fuehrt das Logo
     bis 767px 30px hoch, ab 768px 28px. Wir hatten durchgehend 28. */
  .brand-logo{height:30px;width:auto;display:block}
  @media(min-width:768px){.brand-logo{height:28px}}
  .nav-spacer{flex:1}
  .nav-help{display:inline-flex;align-items:center;gap:8px;font-size:.92rem;font-weight:700;color:#fff;text-decoration:none;padding:9px 12px;border-radius:8px;min-height:44px}
  .nav-help:hover{color:var(--green-1);background:rgba(255,255,255,.08)}
  .nav-help svg{width:18px;height:18px}
  .nav-help .lbl{display:none}
  @media(min-width:560px){.nav-help .lbl{display:inline}}

  /* ---------- Utility-Leiste + Navigation (Carry-over freenet.de) ---------- */
  .util{background:#21314d;color:#e3e8f3;font-size:13px}
  .util-row{display:flex;align-items:stretch;gap:0;min-height:0}
  /* 1:1 gemessen (06.08.): weisse Segmente, Navy-Text, 13px in NORMALER
     Staerke — nicht halbfett — und 15px Innenabstand. */
  .util-seg{display:inline-flex;align-items:center;gap:8px;background:#fff;color:#21314d;text-decoration:none;font-weight:400;white-space:nowrap;padding:5px 15px;line-height:18px;border-left:1px solid rgba(33,49,77,.18)}
  .util-seg:hover,.util-seg:focus-visible{background:var(--green-1);color:#fff}
  /* Bewusste Mikro-Abweichung: freenet setzt hier weiss auf gruen (2,1:1,
     verletzt WCAG — unser axe-Gate blockt das zu Recht). Navy auf gruen
     misst 5,7:1 und bleibt optisch derselbe Chip. */
  .util-seg--mail{background:var(--green-1);color:#21314d;font-weight:400}
  .util-seg--mail:hover,.util-seg--mail:focus-visible{background:var(--green-2);color:#21314d}
  .util svg{width:15px;height:15px;flex:none}
  .util-spacer{flex:1}
  @media(max-width:1023px){.util{display:none}}

  /* Hauptnavigation 1:1 gemessen (06.08., 1440px): 16px/22,4px, 700, WEISS
     fuer jeden Eintrag, keine Sperrung, kein Innenabstand — die Eintraege
     stehen mit exakt 24px Abstand nebeneinander. Vorher waren alle ausser dem
     aktiven grau, dazu 0,32px Sperrung und 8/12px Padding. */
  .nav-main{display:none;align-items:center;gap:24px}
  .nav-main a{font-size:16px;line-height:22.4px;font-weight:700;color:#fff;text-decoration:none;padding:0;white-space:nowrap;text-transform:uppercase}
  /* Hover faerbt, statt eine Flaeche zu setzen: bei Padding 0 saehe ein
     Hintergrund wie ein abgeschnittener Block aus. */
  .nav-main a:hover,.nav-main a:focus-visible{color:var(--green-1)}
  @media(min-width:1024px){.nav-main{display:flex}}

  .nav-search{display:flex;align-items:center;background:transparent;border-radius:999px;transition:background .15s ease}
  .nav-search[data-search-collapsed="true"] input{width:0;padding:0;opacity:0;pointer-events:none}
  .nav-search[data-search-collapsed="false"]{background:#fff;padding-left:16px}
  .nav-search[data-search-collapsed="false"] input{width:150px;opacity:1;padding:8px 6px}
  .nav-search input{border:0;background:transparent;font-size:.9rem;color:var(--navy);min-height:36px;outline:none;transition:width .15s ease,opacity .15s ease}
  .nav-search input::placeholder{color:var(--slate)}
  .nav-search button{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border:0;border-radius:50%;background:transparent;color:#fff;cursor:pointer}
  .nav-search[data-search-collapsed="false"] button{background:var(--navy);color:#fff;width:36px;height:36px;margin:4px}
  .nav-search button:hover{background:var(--green-dd)}
  .nav-search svg{width:16px;height:16px}
  /* Die Lupe im Kopf ist die Desktop-Variante; mobil steckt die Suche in der
     Icon-Reihe (steht NACH der Basisregel, sonst gewinnt display:flex). */
  @media(max-width:1023px){.nav-search{display:none}}
  @media(min-width:1080px){.nav-search{display:flex}}

  .nav-icon{display:inline-flex;align-items:center;gap:8px;color:#fff;text-decoration:none;font-weight:700;font-size:.92rem;padding:9px 12px;border-radius:8px;min-height:44px;white-space:nowrap}
  .nav-icon:hover{color:var(--green-1);background:rgba(255,255,255,.08)}
  .nav-icon svg{width:20px;height:20px;flex:none}
  .nav-icon .lbl{display:none}
  @media(min-width:1240px){.nav-icon .lbl{display:inline}}

  /* Mobile Icon-Reihe (bis 1023px) — 1:1 gemessen am 06.08. bei 390px:
     je 36,3 x 38,2px, Schrittweite 37,7px, also 1,4px Abstand; Mail gruen,
     Rest weiss. Ab 1024px uebernehmen Hauptnavigation und Lupe. */
  .nav-icons{display:flex;align-items:center;gap:1.4px;margin-left:auto}
  /* 36,3x38,2 ist die gemessene freenet-Groesse und bleibt sichtbar so. Die
     Hoehe der Trefferflaeche geht per padding/margin auf 44 (Apple HIG), ohne
     dass sich die Zeile bewegt. Die BREITE bleibt bei 36,3: mehr wuerde die
     Zeile auf schmalen Geraeten wieder sprengen — bewusst akzeptierter T1. */
  .nav-icons a{display:inline-flex;align-items:center;justify-content:center;width:36.3px;height:44px;color:#fff;
    margin-block:-2.9px}
  .nav-icons a:hover{color:var(--green-1)}
  .nav-icons svg{width:22px;height:22px}
  /* a.nav-icons__mail, sonst gewinnt .nav-icons a mit hoeherer Spezifitaet. */
  .nav-icons a.nav-icons__mail{color:var(--green-1)}
  .nav-icons a.nav-icons__mail:hover{color:var(--green-2)}
  /* freenet zeigt die Icon-Reihe bis 1023px und schaltet erst ab 1024 auf die
     Textnavigation um — wir schalteten schon bei 900. */
  @media(min-width:1024px){.nav-icons{display:none}}
  /* Die 400px-Ausblendung von Shop-Finder und Telefon ist am 25.08.2026
     ENTFALLEN. Sie war noetig, solange sechs Icons in der Zeile standen
     (Blade 34,4 + 6x36,3 + Burger 47,2 + Abstaende = 391px, iPhone SE hat
     320). Mit Steppes Aenderung vom 24.08. sind es nur noch vier — Warenkorb
     raus, Telefon fest ins Burger-Menue — und die Zeile passt auch bei 320px.
     Damit ist der Shop-Finder ("Location/mein Shop", ihr Vorschlag) auf JEDEM
     Geraet sichtbar statt genau dort zu verschwinden, wo sie ihn haben will. */

  /* Der Burger sitzt hinter einem senkrechten Trenner und traegt "Menü". */
  .burger{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;width:auto;min-width:44px;height:44px;padding:0 4px 0 12px;margin-left:8px;border:0;border-left:1px solid rgba(255,255,255,.28);background:transparent;border-radius:0;color:#fff;cursor:pointer;flex:none}
  .burger:hover{color:var(--green-1)}
  .burger svg{width:22px;height:22px}
  .burger__label{font-size:11px;font-weight:400;line-height:1}
  .burger .ico-close{display:none}
  .burger[aria-expanded="true"] .ico-open{display:none}
  .burger[aria-expanded="true"] .ico-close{display:block}
  @media(min-width:1024px){.burger{display:none}}

  .mnav{display:none;border-top:1px solid var(--g-e5);background:#fff;max-height:calc(100dvh - 62px);overflow-y:auto;overscroll-behavior:contain}
  .mnav[data-open="true"]{display:block}
  @media(min-width:1024px){.mnav[data-open="true"]{display:none}}
  .mnav .wrap{padding-block:14px 22px}
  .mnav form{display:flex;gap:8px;margin-bottom:6px}
  /* text-overflow greift auch auf den Platzhalter: bei 320px passt
     "Suchbegriff eingeben" nicht in das Feld und wurde hart abgeschnitten
     ("Suchbegriff eingeb"). Mit Ellipse liest es sich als gekuerzt, nicht als
     kaputt. font-size bleibt bei 1rem — darunter zoomt iOS Safari beim Fokus. */
  .mnav form input{flex:1;min-width:0;min-height:48px;border:1px solid var(--g-ca);border-radius:var(--radius-input);padding:0 14px;font-size:1rem;color:var(--navy);background:#fff;text-overflow:ellipsis}
  .mnav form button{min-height:48px;padding:0 18px;border:0;border-radius:var(--radius-input);background:var(--navy);color:#fff;font-weight:700;cursor:pointer;flex:none}
  .mnav form button:hover{background:var(--green-dd)}
  .mnav-group{font-size:.72rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--slate);margin:18px 0 2px}
  .mnav a{display:flex;align-items:center;gap:12px;min-height:48px;padding:6px 2px;color:var(--navy);text-decoration:none;font-weight:600;border-bottom:1px solid var(--g-f2)}
  .mnav a:hover{color:var(--green-dd)}
  .mnav a svg{width:18px;height:18px;flex:none;color:var(--slate)}

  /* ---------- Such-Overlay (mobil, 31.08.2026) ----------
     Nachgebaut nach freenet.de, gemessen am 31.08.2026 bei 390x844:
     .search-overlay ist position:fixed, beginnt bei y=60 (deren Headerhoehe),
     laeuft bis unten, ist weiss und hat auf mobil KEINEN Backdrop — deren
     .search-overlay__backdrop traegt "show-for-large". Unser Header misst
     59px Zeile + 3px Gruenstrich = 62px, also faengt das Overlay bei 62 an.
     Der Header bleibt dadurch sichtbar und bedienbar, genau wie drueben. */
  .search-ov{position:fixed;top:62px;left:0;right:0;bottom:0;z-index:5;background:#fff;
    overflow-y:auto;overscroll-behavior:contain}
  .search-ov[hidden]{display:none}
  /* Ab 1024px uebernimmt die aufklappbare Lupe im Kopf (.nav-search); das
     Overlay darf dort nie stehenbleiben, auch nicht wenn beim Drehen des
     Geraets aus 390 plotzlich 1024 werden. */
  @media(min-width:1024px){.search-ov{display:none}}

  /* Die Zeile: Zurueck-Pfeil, Feld, Loeschen-X, Lupe — 1:1 deren Reihenfolge.
     Untere Haarlinie wie drueben, damit die Zeile vom weissen Rest abgesetzt
     ist. Alle drei Knoepfe messen 44px (Apple HIG / WCAG 2.2 AA). */
  .search-ov__row{display:flex;align-items:center;gap:4px;padding:8px 10px;border-bottom:1px solid var(--g-e5)}
  .search-ov__back,.search-ov__clear,.search-ov__submit{display:inline-flex;align-items:center;justify-content:center;
    width:44px;height:44px;flex:none;border:0;background:transparent;color:var(--navy);cursor:pointer;border-radius:8px}
  .search-ov__back:hover,.search-ov__clear:hover,.search-ov__submit:hover{color:var(--green-dd)}
  .search-ov__back svg,.search-ov__submit svg{width:22px;height:22px}
  .search-ov__clear svg{width:20px;height:20px;color:var(--slate)}
  .search-ov__clear[hidden]{display:none}
  /* font-size bleibt bei 1rem: darunter zoomt iOS Safari beim Fokus in das
     Feld hinein und der Header rutscht aus dem Bild (gleiche Regel wie bei
     .mnav form input). Rahmenlos wie drueben — die Zeile selbst ist das
     Feld, deshalb traegt sie die Trennlinie und nicht der Input. */
  .search-ov__input{flex:1;min-width:0;min-height:44px;border:0;outline:none;background:transparent;
    font-size:1rem;color:var(--navy);padding:0 4px;text-overflow:ellipsis}
  .search-ov__input::placeholder{color:var(--slate)}
  /* Das native X von type="search" waere ein zweites Loeschen-Icon neben
     unserem eigenen. */
  .search-ov__input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
  /* Fokus liegt fast immer im Feld (wir setzen ihn beim Oeffnen), deshalb
     traegt ihn die Zeile als 2px-Navy-Linie statt als Rahmen um den Input.
     Navy und nicht Gruen: ein gruener Balken direkt unter dem gruenen
     Header-Strich haette wie ein zweiter Header ausgesehen. */
  .search-ov__input:focus-visible{outline:none}
  .search-ov__row:focus-within{box-shadow:inset 0 -2px 0 0 var(--navy)}
  /* Hinweistext: drueben 14px, zentriert, Navy, 20px unter der Zeile. */
  .search-ov__hint{margin:20px 16px 30px;text-align:center;font-size:.875rem;line-height:1.4;color:var(--navy)}

  /* ---------- Hero ---------- */
  .hero{
    position:relative;overflow:hidden;color:#fff;
    /* Die generische Polsterung aus `section{padding-block:46px}` gilt fuer
       die Buehne NICHT — sie bringt ihre eigene mit (.hero-grid).
       Rueckmeldung Stephanie Wolf ueber Hendrik, 31.08.2026 abends, mit
       Screenshot: der Abstand zwischen Header und "FREENET MOBILFUNK" ist
       auf dem Telefon zu gross.
       Nachgemessen: 46px (section) + 44px (.hero-grid) = 90px leere Flaeche
       zwischen Header-Unterkante und Eyebrow, auf JEDER Breite bis 1023.
       Die 46px waren nie als Luft gedacht: bis zum 31.08. stand das gruene
       Aktionsband genau dort, INNERHALB von .hero und ueber dem Raster. Mit
       dem Ausbau des Bandes (#145) blieb seine Polsterung stehen und ist zu
       einem Loch geworden. Die Buehne polstert jetzt nur noch ueber
       .hero-grid — also die 44px, die dort seit jeher als Mass stehen
       (Desktop 62px, ebenfalls unveraendert uebernommen). */
    padding-block:0;
    background:
      radial-gradient(120% 92% at 86% -12%, rgba(132,188,52,.36) 0%, rgba(132,188,52,0) 52%),
      radial-gradient(92% 80% at -8% 112%, rgba(156,208,83,.18) 0%, rgba(156,208,83,0) 55%),
      linear-gradient(180deg,var(--blue-1) 0%,#1b2740 100%);
  }
  .hero-grid{display:grid;grid-template-columns:1fr;gap:30px;padding-block:44px 50px;align-items:center}
  .hero h1{font-size:clamp(2.05rem,7.6vw,3.5rem);font-weight:800;letter-spacing:-.03em;margin:0 0 16px;max-width:15ch}
  .hero h1 .hl{color:var(--green)}
  .lede{font-size:clamp(1.04rem,2.4vw,1.2rem);color:#48566f;max-width:48ch;margin:0 0 24px;font-weight:400}
  .hero .lede{color:var(--blue-4)}
  .lede b{color:#fff;font-weight:800}
  .hero-cta{display:flex;flex-wrap:wrap;gap:12px;align-items:center}
  .hero-cta .btn-primary{background:var(--grey-1);color:var(--blue-1)}
  .hero-cta .btn-primary:hover{background:#fff;box-shadow:0 4px 16px rgba(9,32,67,.30)}
  .hero-cta .btn-primary{min-height:54px}
  .hero-cta .btn-ghost{min-height:54px}
  .micro{margin-top:16px;font-size:.86rem;color:var(--slate);display:flex;flex-wrap:wrap;gap:6px 16px}
  .micro span{display:inline-flex;align-items:center;gap:7px}
  .micro svg{width:15px;height:15px;color:var(--t-9c)}

  /* hero price card */
  .hero-card{
    background:#fff;color:var(--navy);border-radius:var(--radius);padding:22px 22px 24px;
    box-shadow:var(--shadow-lg);position:relative;border:1px solid rgba(255,255,255,.5);
  }
  .flag{position:absolute;top:-13px;right:22px;left:auto;background:var(--green);color:var(--navy);font-size:.74rem;font-weight:700;letter-spacing:0;padding:6px 14px;border-radius:999px;box-shadow:var(--shadow-sm)}
  /* Die Aktionszeile in der Karte. Sie steht zwischen Preis und Leistungen,
     also genau da, wo der Kunde den Anschlusspreis gerade gelesen hat.
     Bewusst OHNE Rahmen um die ganze Karte: ein coraler Ring auf weiss vor
     Navy las sich wie ein Fehlerzustand, und die Seite kennt sonst keine
     Rahmen als Auszeichnung. Flag und Zeile tragen das Signal. */
  /* Gruen, nicht coral (Hendrik + Designerin, 31.08.2026). Coral sass auf
     demselben Bildschirm dreimal — Ersparnis-Badge, Rastermarker und diese
     Zeile. Coral bleibt jetzt dem Ersparnis-Badge, die Aktion traegt das
     freenet-Gruen, das ohnehin die Primaerfarbe der Seite ist. */
  .hero-promo{font-size:.86rem;font-weight:600;line-height:1.45;color:var(--blue-1);
    background:var(--t-e1);border-radius:12px;padding:10px 12px;margin:0 0 16px}
  .hero-promo .promo-code{background:var(--green-dd);color:#fff;border-radius:6px;
    padding:1px 7px;letter-spacing:.04em;white-space:nowrap}
  .card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;margin-top:6px}
  /* Unter 360px steht das Ersparnis-Badge UNTER dem Tarifnamen statt daneben.
     Grund ist die neue Beschriftung vom 01.09.2026: "55 % Ersparnis" ist mit
     112px mehr als doppelt so breit wie das frühere "– 55 %" und nahm dem
     Namen genau den Platz, den er auf einem iPhone SE noch hat. Gemessen bei
     320px: der Tarifname wuchs von 95px auf 127px, also von drei auf vier
     Zeilen. Nebeneinander bleibt es, sobald der Platz da ist. */
  @media(max-width:359px){
    .card-top{flex-direction:column;align-items:flex-start;gap:8px}
  }
  /* text-wrap:balance verhindert die Waise am Zeilenende: bei 320px stand
     "Allnet Flat 40" / "GB", die Einheit alleine auf Zeile zwei. Balanciert
     wird daraus "Allnet" / "Flat 40 GB". Aeltere Browser ignorieren die
     Eigenschaft und brechen wie bisher. */
  .card-name{font-size:1.28rem;font-weight:800;text-wrap:balance}
  .card-net{font-size:.84rem;color:var(--slate);font-weight:600;margin-top:3px}
  .save-badge{background:var(--coral-1);color:var(--blue-1);font-size:.76rem;font-weight:800;padding:6px 11px;border-radius:999px;white-space:nowrap}
  .price-row{display:flex;align-items:baseline;gap:10px;margin:16px 0 4px}
  .price-was{color:var(--slate);text-decoration:line-through;font-size:1.05rem;font-weight:600}
  .price-now{font-size:2.5rem;font-weight:800;letter-spacing:-.03em}
  .price-now small{font-size:1rem;font-weight:700;color:var(--slate);letter-spacing:0}
  .price-sub{font-size:.84rem;color:var(--slate);margin-bottom:16px}
  .checks{list-style:none;margin:0 0 18px;padding:0;display:grid;gap:11px}
  .checks li{display:flex;gap:10px;align-items:flex-start;font-size:.96rem;font-weight:600}
  .checks li b{font-weight:800}
  .ck{flex:0 0 auto;width:21px;height:21px;border-radius:50%;background:var(--t-e1);display:grid;place-items:center;margin-top:1px}
  .ck svg{width:13px;height:13px;color:var(--green-dd)}
  .hero-compare{margin:12px 0 0;text-align:center}
  /* Trefferflaeche wie bei .tdetails: 18px Text, 24px sind Pflicht. */
  .hero-compare a{color:var(--blue-1);font-weight:700;text-decoration:underline;
    display:inline-block;padding-block:12px;margin-block:-12px}

  @media(min-width:880px){
    .hero-grid{grid-template-columns:1.05fr .95fr;gap:46px;padding-block:62px 70px}
    .hero-card{padding:26px 26px 28px}
  }

  /* ---------- Tariff selection grid ---------- */
  .tariffs{background:var(--white)}
  .tgrid{display:grid;grid-template-columns:1fr;gap:16px}
  @media(min-width:620px){.tgrid{grid-template-columns:repeat(2,1fr)}}
  @media(min-width:1040px){.tgrid{grid-template-columns:repeat(4,1fr);gap:18px}}
  /* Sechs Karten (zwei je Netz) statt vier: drei Spalten, damit der
     freenet-Tarif und der Original-Netztarif desselben Netzes
     untereinander stehen und der Speed-Unterschied direkt vergleichbar ist. */
  @media(min-width:1040px){.tgrid-6{grid-template-columns:repeat(3,1fr)}}
  /* Die Karte ist seit dem Landing-Port ein <a> (Deep-Link in den Funnel).
     Ohne text-decoration:none unterstreicht der Browser-Default JEDEN
     Kartentext (Name, Netz, Speed, Blurb, Preis) — sah live kaputt aus.
     color:inherit, damit der Anchor nicht das Link-Blau auf ungefärbte
     Textknoten legt. Gezielte Unterstreichungen (.tdetails, .was s) setzen
     sich selbst und bleiben unberührt. */
  .tcard{
    position:relative;display:block;background:#fff;border:1.5px solid var(--g-ca);
    border-radius:var(--radius);padding:22px 20px 22px;cursor:pointer;
    text-decoration:none;color:inherit;
    transition:border-color .14s ease, box-shadow .14s ease, transform .14s ease;
    box-shadow:var(--shadow-sm);
  }
  .tcard:hover{border-color:var(--green-d);transform:translateY(-2px);box-shadow:var(--shadow-md)}
  .tcard input{position:absolute;opacity:0;width:0;height:0}
  .tcard:has(input:checked){border-color:var(--blue-1);box-shadow:0 0 0 3px rgba(9,32,67,.20), var(--shadow-sm)}
  .tcard:has(input:focus-visible){outline:3px solid var(--green);outline-offset:2px}
  .tcard:active{transform:translateY(0);box-shadow:var(--shadow-sm)}
  .tcard.popular{border-color:var(--green-d)}
  .tcard.popular:has(input:checked){border-color:var(--blue-1)}
  .tflag{position:absolute;top:-12px;right:20px;left:auto;background:var(--green);color:var(--navy);font-size:.7rem;font-weight:700;letter-spacing:0;padding:5px 13px;border-radius:999px;box-shadow:var(--shadow-sm)}
  /* Bis zum 31.08.2026 stand der Aktionsmarker in Coral, um sich vom
     "Beliebtester Tarif"-Flag zu unterscheiden. Die Designerin hat ihn
     zurueckgeholt: "das Label muesste auch in gruen dargestellt werden
     (siehe andere Tarife)". Die Klasse bleibt als Haken fuer Tests und fuer
     den Fall, dass die beiden Label doch wieder auseinander sollen. */
  .tflag-promo{background:var(--green);color:var(--navy)}
  .tcard .tname{font-size:1.16rem;font-weight:800;letter-spacing:-.01em;padding-right:32px}
  .tcard .tgb{display:flex;align-items:baseline;gap:8px;margin:10px 0 2px}
  .tcard .tgb .num{font-size:1.7rem;font-weight:800;letter-spacing:-.03em;line-height:1}
  .tcard .tgb .unit{font-size:.92rem;font-weight:700;color:var(--slate)}
  .tcard .tnet{font-size:.8rem;color:var(--slate);font-weight:600;margin-bottom:14px}
  .tcard .tprice{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;margin-bottom:4px}
  .tcard .tprice .was{color:var(--coral-text);text-decoration:line-through;font-size:.92rem;font-weight:600}
  .tcard .tprice .now{font-size:1.5rem;font-weight:800;letter-spacing:-.02em}
  .tcard .tprice .now small{font-size:.82rem;font-weight:700;color:var(--slate);letter-spacing:0}
  /* Preis-Anatomie wie freenet.de (Steppe, 14.08.): Komma gross auf der
     Grundlinie (steckt im .eur-Span), der .cent-Block klein daneben.

     KORREKTUR 25.08.2026 — Steppe, 24.08.: "Das EUR-Zeichen vom Streichpreis
     ist bei den Bundle-Teasern verrutscht". Das ist FN-04, das am 03.08. als
     erledigt und live geprueft abgehakt war und zurueckkam, weil der Fix
     damals nur die Tarifkarten traf.

     Zwei Ursachen, beide hier:
       1. align-items:center zentrierte den kleinen .cent-Block vertikal gegen
          die grosse Zahl. Bei .eur line-height:1 und .cent line-height:1.1
          sind die beiden Boxen unterschiedlich hoch, der Zentrier-Versatz ist
          also kein runder Wert — sichtbar als "verrutscht".
       2. das €-Zeichen steckte im .cent-Span und erbte dessen Groesse UND
          dessen Zentrierung; es konnte gar nicht auf der Grundlinie sitzen.

     Jetzt: align-items:baseline (alle drei Teile auf EINER Grundlinie) und
     ein eigener .cur-Span fuer die Waehrung, dessen Abstand als margin
     gesetzt wird statt als ASCII-Leerzeichen, das letter-spacing:-.02em auf
     .now sonst wieder zusammenzieht.

     Gilt fuer alle drei Preisdarstellungen (Hero, Tarifkarte, Bundle-Teaser)
     gemeinsam — die Trennung war der Grund fuer die Regression.
     Gepinnt von test/e2e/price_typography.rb. */
  .price-now{display:inline-flex;align-items:baseline}
  #heroNow{display:inline-flex;align-items:baseline}
  .price-now .eur{font-size:2.5rem;line-height:1}
  .price-now .cent{font-size:1.15rem;line-height:1;font-weight:800;margin-left:2px}
  .price-now .cur{font-size:1.15rem;line-height:1;font-weight:800;margin-left:5px;letter-spacing:0}
  .price-now small{margin-left:5px}
  .now{display:inline-flex;align-items:baseline}
  .now .eur{font-size:1.9rem;line-height:1}
  .now .cent{font-size:.95rem;line-height:1;font-weight:800;margin-left:2px}
  .now .cur{font-size:.95rem;line-height:1;font-weight:800;margin-left:4px;letter-spacing:0}
  .tcard .tsave{display:block;width:max-content;background:var(--coral-1);color:var(--blue-1);font-size:.72rem;font-weight:800;padding:3px 9px;border-radius:999px;margin-bottom:10px}
  .tcard .tsub{font-size:.8rem;color:var(--slate);min-height:1.2em}
  .tariff-cta{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-top:28px}
  .tariff-cta .btn-primary{min-height:54px}
  .tariff-cta .tc-hint{font-size:.88rem;color:var(--slate);font-weight:600}

  /* ---------- Trust row ---------- */
  .trust{background:var(--white);border-bottom:1px solid var(--g-e5);padding:0}
  .trust-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:14px 18px;padding-block:22px}
  .trust-item{display:flex;gap:10px;align-items:center;font-size:.88rem;font-weight:700;color:var(--navy)}
  .trust-item svg{width:22px;height:22px;color:var(--green-d);flex:0 0 auto}
  /* Spalten auf Inhaltsbreite + gleichmaessig verteilt statt vier gleich
     breiter 1fr-Spalten: bei linksbuendigen Inhalten riss hinter dem
     kuerzesten Element (Nr. 3) sonst eine doppelt so grosse Luecke auf
     (Steppe, 14.08.). */
  @media(min-width:760px){.trust-grid{grid-template-columns:repeat(4,auto);justify-content:space-between;padding-block:26px}}

  /* ---------- Social-proof bar ---------- */
  .proofbar{background:var(--navy);color:#fff;padding-block:0}
  .proof-grid{display:grid;grid-template-columns:1fr;gap:16px;padding-block:22px;text-align:center}
  .proof-item{display:flex;flex-direction:column;gap:3px}
  .proof-num{font-size:1.5rem;font-weight:800;letter-spacing:-.02em;color:var(--t-9c)}
  .proof-lbl{font-size:.86rem;font-weight:600;color:rgba(255,255,255,.82);line-height:1.35}
  @media(min-width:760px){.proof-grid{grid-template-columns:repeat(3,1fr);padding-block:26px}.proof-item{border-left:1px solid rgba(255,255,255,.14);padding-left:22px}.proof-item:first-child{border-left:0;padding-left:0}}

  /* ---------- Reassurance band at the pay CTA ---------- */
  .reassure{list-style:none;display:flex;flex-wrap:wrap;justify-content:center;gap:8px 14px;margin:18px 0 14px;padding:0}
  .reassure li{display:inline-flex;align-items:center;gap:7px;font-size:.85rem;font-weight:700;color:var(--navy)}
  .reassure li::before{content:"";width:18px;height:18px;flex:0 0 auto;border-radius:50%;background:var(--t-e1);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235d8c20' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");background-size:13px;background-repeat:no-repeat;background-position:center}

  /* ---------- inline field-status hints ---------- */
  .ok-hint{color:var(--green-dd);font-weight:700}
  .hint.bad{color:var(--red);font-weight:700}

  /* ---------- Section base ---------- */
  section{padding-block:46px}
  .sec-head{max-width:40ch;margin-bottom:30px}
  .sec-head.wide{max-width:52ch}
  /* Desktop: Sektionskopf und Einleitungstexte laufen ueber die volle
     Rasterbreite (freenet-Feedback 04.09.2026: "Der Text laeuft Desktop
     nicht ueber die gesamte Breite"). Der 40ch/52ch-Deckel gilt weiter
     unterhalb von 1024px, dort ist der Container ohnehin schmaler. */
  @media(min-width:1024px){
    .sec-head,.sec-head.wide,.bundles .lede,.tgrid-head p{max-width:none}
  }
  .sec-head h2{font-size:clamp(1.6rem,4.6vw,2.25rem);margin:0 0 12px}
  .sec-head p{color:var(--slate);font-size:1.04rem}

  /* ---------- Feelings trio ---------- */
  .feelings{background:var(--soft)}
  .trio{display:grid;grid-template-columns:1fr;gap:16px}
  .feel{background:#fff;border-radius:var(--radius);padding:24px 22px;box-shadow:var(--shadow-sm);border:1px solid var(--g-e5)}
  .feel .ico{width:46px;height:46px;border-radius:16px;background:var(--t-e1);display:grid;place-items:center;margin-bottom:14px}
  .feel .ico svg{width:24px;height:24px;color:var(--green-dd)}
  .feel h3{font-size:1.18rem;margin:0 0 7px}
  .feel p{color:var(--slate);font-size:.97rem}
  @media(min-width:760px){.trio{grid-template-columns:repeat(3,1fr);gap:20px}}

  /* ---------- Testimonial ---------- */
  .quote-card{background:var(--navy);color:#fff;border-radius:var(--radius);padding:32px 26px;position:relative;overflow:hidden;
    background-image:radial-gradient(90% 120% at 100% 0%, rgba(132,188,52,.22) 0%, rgba(132,188,52,0) 55%);}
  .quote-mark{font-size:3.2rem;line-height:.6;color:var(--t-9c);font-weight:800;opacity:.9}
  .quote-card blockquote{margin:6px 0 22px;font-size:clamp(1.18rem,3vw,1.5rem);font-weight:700;letter-spacing:-.01em;max-width:32ch}
  .quote-by{display:flex;align-items:center;gap:13px}
  /* Bei 320px bricht die Rolle ("freenet Kundin seit 2025, Leipzig") um; der
     zentrierte Avatar steht dann auf Hoehe der zweiten Zeile statt beim Namen. */
  @media(max-width:560px){.quote-by{align-items:flex-start}}
  .avatar{width:48px;height:48px;border-radius:50%;background:linear-gradient(135deg,var(--green) 0%,var(--green-dd) 100%);color:var(--navy);display:grid;place-items:center;font-weight:800;font-size:1.02rem;flex:0 0 auto}
  .quote-by .who{font-weight:800}
  .quote-by .role{font-size:.86rem;color:var(--slate)}
  .stars{display:flex;gap:2px;margin-top:3px}
  .stars svg{width:14px;height:14px;color:var(--green)}

  /* ---------- FAQ ---------- */
  .faq{background:var(--soft)}
  .faq-list{max-width:760px;display:grid;gap:12px}
  details.qa{background:#fff;border-radius:var(--radius-sm);border:1px solid var(--g-e5);box-shadow:var(--shadow-sm);overflow:hidden}
  details.qa summary{list-style:none;cursor:pointer;padding:17px 18px;font-weight:800;font-size:1.02rem;display:flex;align-items:center;justify-content:space-between;gap:14px;min-height:44px}
  details.qa summary::-webkit-details-marker{display:none}
  details.qa summary .chev{flex:0 0 auto;width:22px;height:22px;color:var(--green-d);transition:transform .2s ease}
  details.qa[open] summary .chev{transform:rotate(180deg)}
  details.qa .ans{padding:0 18px 18px;color:var(--slate);font-size:.97rem}

  /* ---------- Footer ----------
     Liegt jetzt in site-footer.css, weil ihn die Bestellstrecke genauso
     braucht (Impressum/AGB auf jedem Schritt) und landing.css bewusst nur
     auf dem Landing-Layout geladen wird.
     Markup: app/views/shared/_site_footer.html.erb */

  /* ---------- Sticky mobile CTA ---------- */
  .sticky-cta{
    position:fixed;left:0;right:0;bottom:0;z-index:45;
    background:rgba(255,255,255,.97);backdrop-filter:blur(8px);
    border-top:1px solid var(--g-e5);padding:10px 16px calc(10px + env(safe-area-inset-bottom));
    display:flex;align-items:center;gap:12px;box-shadow:0 -2px 8px rgba(9,32,67,.16);
    transform:translateY(120%);transition:transform .25s ease;
  }
  .sticky-cta.show{transform:translateY(0)}
  /* Never let the fixed bar permanently hide content: tuck it away once the
     footer scrolls into view (JS toggles .at-footer), and reserve its height at
     the page bottom so the last footer line is always reachable on mobile. */
  .sticky-cta.at-footer{transform:translateY(120%)}
  /* Die Reserve haengt am Footer, nicht am body: der body ist fast weiss, der
     Footer navy. Auf dem body stand unter dem Footer ein 72px hoher weisser
     Streifen am Seitenende — sah aus wie ein Renderfehler. Am Footer laeuft
     das Navy bis unten durch. :not(.in-checkout), damit die Bestellstrecke
     (kein Sticky-CTA) die Reserve nicht mitschleppt; die hoehere Spezifitaet
     schlaegt ausserdem site-footer.css, das nach dieser Datei geladen wird. */
  @media(max-width:879px){
    body:not(.in-checkout) footer.site{
      padding-bottom:calc(30px + 72px + env(safe-area-inset-bottom));
    }
  }
  /* min-width:0 ist noetig, damit der Textblock im Flex-Row ueberhaupt
     schrumpfen darf — sonst draengt er den Button schmal und "Tarif waehlen"
     bricht um. Der Balken war dadurch bei 320px 102px hoch statt 73. */
  .sticky-cta .sc-price{flex:1;min-width:0;line-height:1.2}
  .sticky-cta .sc-price b{font-size:1.12rem;font-weight:800;display:block}
  /* Der Tarifname ist Beiwerk: eine Zeile, Rest gekuerzt. Zwei umgebrochene
     Zeilen fressen auf einem kleinen Display zu viel Hoehe. */
  .sticky-cta .sc-price span{font-size:.78rem;color:var(--slate);display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .sticky-cta .btn{min-height:48px;padding:12px 22px;white-space:nowrap;flex:none}
  @media(max-width:399px){
    .sticky-cta{padding-inline:12px;gap:10px}
    .sticky-cta .sc-price b{font-size:.98rem;white-space:nowrap}
    .sticky-cta .btn{padding:12px 16px;font-size:.95rem}
  }
  @media(min-width:880px){.sticky-cta{display:none}}

  /* =================================================================
     WIZARD
     ================================================================= */
  .checkout{display:none;background:var(--soft);min-height:100vh;padding-block:24px 60px}
  .checkout.active{display:block}
  body.in-checkout .sticky-cta{display:none !important}

  .co-grid{display:grid;grid-template-columns:1fr;gap:22px;align-items:start}
  @media(min-width:980px){.co-grid{grid-template-columns:1fr 340px;gap:32px}}

  .co-main{background:#fff;border-radius:var(--radius);box-shadow:var(--shadow-md);padding:22px 18px 24px;border:1px solid var(--g-e5)}
  @media(min-width:560px){.co-main{padding:30px 30px 32px}}

  .co-back-top{display:inline-flex;align-items:center;gap:8px;background:none;border:0;color:var(--slate);font-weight:700;font-size:.9rem;cursor:pointer;padding:8px 4px;margin-bottom:6px;min-height:40px}
  .co-back-top:hover{color:var(--navy)}
  .co-back-top svg{width:16px;height:16px}

  /* progress */
  .progress{margin-bottom:24px}
  .progress-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:9px}
  .progress-top .step-label{font-size:.86rem;font-weight:800;color:var(--navy)}
  .progress-top .step-name{font-size:.86rem;color:var(--slate);font-weight:600}
  .bar{height:8px;background:var(--g-e5);border-radius:999px;overflow:hidden}
  .bar i{display:block;height:100%;width:20%;background:linear-gradient(90deg,var(--green) 0%,var(--t-9c) 100%);border-radius:999px;transition:width .35s cubic-bezier(.4,0,.2,1)}

  .step{display:none}
  .step.active{display:block;animation:fade .3s ease}
  @keyframes fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
  .step h2{font-size:1.5rem;margin:0 0 6px;outline:none}
  .step .step-intro{color:var(--slate);font-size:.98rem;margin-bottom:22px;max-width:50ch}

  /* form bits */
  .field{margin-bottom:16px}
  .field label.lbl,.field .lbl{display:block;font-size:.88rem;font-weight:800;margin-bottom:7px;color:var(--navy)}
  .field .lbl .req{color:var(--red);font-weight:800}
  .field input,.field select{
    width:100%;min-height:50px;padding:13px 14px;border:1.5px solid var(--g-ca);border-radius:12px;
    font-size:1rem;font-family:inherit;color:var(--navy);background:#fff;transition:border-color .14s ease, box-shadow .14s ease;
  }
  .field input::placeholder{color:#aab2c0}
  .field input:focus,.field select:focus{border-color:var(--green-d);box-shadow:0 0 0 3px rgba(132,188,52,.18);outline:none}
  .field input[aria-invalid="true"],.field select[aria-invalid="true"]{border-color:var(--red);box-shadow:0 0 0 3px rgba(223,0,46,.12)}
  .field .hint{font-size:.8rem;color:var(--slate);margin-top:6px}
  .field .err{font-size:.8rem;color:var(--red);font-weight:700;margin-top:6px;display:none}
  .field .err.show{display:block}
  .row2{display:grid;grid-template-columns:1fr;gap:0 14px}
  @media(min-width:520px){.row2{grid-template-columns:1fr 1fr}.row2.r-32{grid-template-columns:1.4fr .9fr}.row2.r-pc{grid-template-columns:.8fr 1.4fr}}

  /* option cards (radio-as-card) */
  .opts{display:grid;gap:12px;margin-bottom:6px}
  .opt{position:relative;display:flex;gap:13px;align-items:flex-start;padding:16px 16px;border:1.5px solid var(--g-ca);border-radius:16px;cursor:pointer;background:#fff;transition:border-color .14s ease, background-color .14s ease, box-shadow .14s ease}
  .opt:hover{border-color:var(--green-d)}
  .opt input{position:absolute;opacity:0;width:0;height:0}
  .opt .radio{flex:0 0 auto;width:22px;height:22px;border-radius:50%;border:1px solid var(--g-ca);margin-top:1px;display:grid;place-items:center;transition:border-color .14s ease}
  .opt .radio::after{content:"";width:11px;height:11px;border-radius:50%;background:var(--green-d);transform:scale(0);transition:transform .15s ease}
  .opt:has(input:checked){border-color:var(--green-d);background:var(--t-e1);box-shadow:0 0 0 3px rgba(132,188,52,.16)}
  .opt:has(input:checked) .radio{border-color:var(--green-d)}
  .opt:has(input:checked) .radio::after{transform:scale(1)}
  .opt input:focus-visible ~ .radio{outline:3px solid var(--green);outline-offset:2px}
  .opt .opt-body{flex:1}
  .opt .opt-title{font-weight:800;font-size:1.02rem;display:flex;align-items:center;gap:9px;flex-wrap:wrap}
  .opt .opt-desc{font-size:.88rem;color:var(--slate);margin-top:3px}
  .pill{font-size:.78rem;font-weight:700;letter-spacing:0;padding:4px 12px;border-radius:999px;background:var(--green-1);color:var(--blue-1)}
  .pill-outline{background:transparent;border:1.5px solid var(--green-1);color:var(--blue-1)}
  .pill.soft{background:var(--t-e1);color:var(--green-dd)}

  /* conditional block */
  .cond{display:none;margin-top:6px;padding:16px;background:var(--g-f2);border-radius:16px;border:1px solid var(--g-e5)}
  .cond.show{display:block;animation:fade .25s ease}

  /* checkbox consents */
  .consent{display:flex;gap:12px;align-items:flex-start;padding:13px 14px;border:1.5px solid var(--g-e5);border-radius:12px;cursor:pointer;margin-bottom:11px;background:#fff;transition:border-color .14s ease}
  .consent:hover{border-color:var(--green-d)}
  .consent input{position:absolute;opacity:0;width:0;height:0}
  .consent .box{flex:0 0 auto;width:24px;height:24px;border-radius:7px;border:1px solid var(--g-ca);display:grid;place-items:center;margin-top:1px;transition:all .14s ease}
  .consent .box svg{width:14px;height:14px;color:#fff;opacity:0;transform:scale(.4);transition:all .14s ease}
  .consent:has(input:checked) .box{background:var(--green-d);border-color:var(--green-d)}
  .consent:has(input:checked) .box svg{opacity:1;transform:scale(1)}
  .consent input:focus-visible ~ .box{outline:3px solid var(--green);outline-offset:2px}
  .consent .ctxt{font-size:.9rem;line-height:1.45}
  .consent .ctxt .req{color:var(--red);font-weight:800}
  .consent a{color:var(--blue-1);font-weight:700;text-decoration:underline}
  .consent.invalid{border-color:var(--red);box-shadow:0 0 0 3px rgba(223,0,46,.10)}

  /* reassurance note */
  .note{display:flex;gap:11px;align-items:flex-start;background:var(--t-e1);border-radius:12px;padding:13px 15px;font-size:.9rem;color:#3a4d22;margin:4px 0 0;line-height:1.45}
  .note svg{flex:0 0 auto;width:19px;height:19px;color:var(--green-dd);margin-top:1px}
  .note.cool{background:#eef2fa;color:#3a4663}
  .note.cool svg{color:var(--navy)}

  .ssl{display:inline-flex;align-items:center;gap:8px;font-size:.84rem;color:var(--slate);font-weight:700;margin-top:14px}
  .ssl svg{width:16px;height:16px;color:var(--green-d);flex:0 0 auto}

  /* summary rows (step 5) */
  .sumcard{border:1px solid var(--g-e5);border-radius:16px;overflow:hidden;margin-bottom:18px}
  .sumrow{display:flex;justify-content:space-between;gap:14px;padding:14px 16px;border-bottom:1px solid var(--g-e5);align-items:flex-start}
  .sumrow:last-child{border-bottom:0}
  .sumrow .sr-k{font-size:.74rem;color:var(--slate);font-weight:800;text-transform:uppercase;letter-spacing:.05em;margin-bottom:3px}
  .sumrow .sr-v{font-weight:700;font-size:.95rem;line-height:1.4}
  .sumrow .edit{background:none;border:0;color:var(--green-dd);font-weight:800;font-size:.85rem;cursor:pointer;padding:6px 6px;min-height:40px;white-space:nowrap}
  .sumrow .edit:hover{text-decoration:underline}
  .sumrow .sr-main{flex:1;min-width:0}
  .total-line{display:flex;justify-content:space-between;align-items:baseline;padding:16px 2px 2px;font-weight:800}
  .total-line .tl-amt{font-size:1.7rem;letter-spacing:-.02em}
  .total-line .tl-amt small{font-size:.95rem;color:var(--slate);font-weight:700}

  /* nav buttons */
  .co-nav{display:flex;gap:12px;align-items:center;margin-top:26px}
  .co-nav .btn-ghost{flex:0 0 auto}
  .co-nav .btn-primary{flex:1}

  /* sidebar order summary */
  .co-side{position:sticky;top:78px}
  .summary-box{background:#fff;border-radius:var(--radius);box-shadow:var(--shadow-md);border:1px solid var(--g-e5);overflow:hidden}
  .summary-box .sb-head{background:var(--navy);color:#fff;padding:16px 18px;display:flex;align-items:center;justify-content:space-between;gap:10px}
  .summary-box .sb-head .sbh-t{font-weight:800;font-size:1rem}
  .summary-box .sb-head .toggle{display:none;background:none;border:0;color:#fff;cursor:pointer;min-height:40px;align-items:center;gap:6px;font-weight:700;font-size:.85rem}
  .summary-box .sb-head .toggle svg{width:18px;height:18px;transition:transform .2s ease}
  .summary-box .sb-body{padding:18px}
  .sb-tariff{font-weight:800;font-size:1.12rem;margin-bottom:3px}
  .sb-net{font-size:.82rem;color:var(--slate);margin-bottom:14px}
  .sb-feat{list-style:none;margin:0 0 16px;padding:0;display:grid;gap:9px}
  .sb-feat li{display:flex;gap:9px;font-size:.88rem;align-items:flex-start}
  .sb-feat .ck{width:18px;height:18px}
  .sb-feat .ck svg{width:11px;height:11px}
  .sb-price{border-top:1px dashed var(--g-ca);padding-top:14px;display:flex;justify-content:space-between;align-items:baseline}
  .sb-price .sbp-amt{font-size:1.5rem;font-weight:800;letter-spacing:-.02em}
  .sb-price .sbp-amt small{font-size:.85rem;color:var(--slate);font-weight:700}
  .sb-foot{margin-top:12px;font-size:.78rem;color:var(--slate);display:flex;gap:7px;align-items:center}
  .sb-foot svg{width:14px;height:14px;color:var(--green-d);flex:0 0 auto}

  @media(max-width:979px){
    .co-side{position:static;order:-1}
    .summary-box .sb-head .toggle{display:inline-flex}
    .summary-box .sb-head{cursor:pointer}
    .summary-box.collapsed .sb-body{display:none}
    .summary-box.collapsed .sb-head .toggle svg{transform:rotate(180deg)}
  }

  /* ---------- Step 6 success ---------- */
  .success{text-align:center;max-width:560px;margin-inline:auto;padding-block:14px}
  .check-wrap{width:104px;height:104px;margin:0 auto 22px;position:relative}
  .check-ring{position:absolute;inset:0;border-radius:50%;background:radial-gradient(circle at 50% 40%, var(--t-e1) 0%, #fff 72%);box-shadow:0 12px 36px rgba(132,188,52,.30)}
  .check-disc{position:absolute;inset:18px;border-radius:50%;background:linear-gradient(135deg,var(--green) 0%,var(--green-dd) 100%);display:grid;place-items:center}
  .check-disc svg{width:42px;height:42px}
  .check-disc path{stroke:#fff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill:none;stroke-dasharray:48;stroke-dashoffset:48}
  .success.go .check-disc path{animation:draw .55s .18s cubic-bezier(.6,0,.3,1) forwards}
  .success.go .check-ring{animation:pop .5s cubic-bezier(.2,.8,.3,1.2)}
  @keyframes draw{to{stroke-dashoffset:0}}
  @keyframes pop{0%{transform:scale(.6);opacity:0}100%{transform:scale(1);opacity:1}}
  .success h2{font-size:clamp(1.7rem,5vw,2.3rem);margin:0 0 10px}
  .success .lead{color:var(--slate);font-size:1.06rem;margin-bottom:22px}
  .ordernr{display:inline-flex;flex-direction:column;gap:2px;background:var(--soft);border-radius:16px;padding:14px 26px;margin-bottom:26px}
  .ordernr .k{font-size:.74rem;letter-spacing:.1em;text-transform:uppercase;color:var(--slate);font-weight:800}
  .ordernr .v{font-size:1.3rem;font-weight:800;letter-spacing:.02em}
  .next-steps{text-align:left;display:grid;gap:14px;margin:0 auto 26px;max-width:480px}
  .ns{display:flex;gap:14px;align-items:flex-start;background:#fff;border:1px solid var(--g-e5);border-radius:16px;padding:16px;box-shadow:var(--shadow-sm)}
  .ns .ns-ico{flex:0 0 auto;width:42px;height:42px;border-radius:12px;background:var(--t-e1);display:grid;place-items:center}
  .ns .ns-ico svg{width:22px;height:22px;color:var(--green-dd)}
  .ns h3{font-size:1.02rem;margin:0 0 3px}
  .ns p{font-size:.9rem;color:var(--slate)}
  .ns .ns-num{font-weight:800;color:var(--green-dd)}

  @media (prefers-reduced-motion: reduce){
    *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important;scroll-behavior:auto !important}
    .success.go .check-disc path{stroke-dashoffset:0}
  }

  /* ---- Official freenet button states (coral / blue / white / green) ---- */
  /* Each: default -> hover LIGHTENS the fill (never changes hue) -> focus adds
     a ring -> active presses -> disabled fades. Matches the Figma matrix. */
  .btn{border:2px solid transparent;font-weight:700;transition:background .15s ease,box-shadow .15s ease,border-color .15s ease,transform .05s ease}
  .btn:disabled,.btn[aria-disabled="true"]{opacity:.42;cursor:not-allowed;pointer-events:none;box-shadow:none}
  .btn svg{flex:0 0 auto}

  /* CORAL */
  .btn-coral{background:var(--coral-1);color:#fff;box-shadow:var(--shadow-sm)}
  .btn-coral:hover{background:var(--coral-2)}
  .btn-coral:active{background:var(--coral-1);transform:translateY(1px)}
  .btn-coral:focus-visible{outline:none;box-shadow:0 0 0 3px var(--blue-1)}

  /* BLUE (primary on light surfaces) */
  .btn-primary{background:var(--blue-1);color:var(--grey-1);box-shadow:var(--shadow-sm)}
  .btn-primary:hover{background:#1d3358;transform:none}
  .btn-primary:active{background:var(--blue-1);transform:translateY(1px)}
  .btn-primary:focus-visible{outline:none;box-shadow:0 0 0 3px var(--coral-1)}

  /* WHITE / outline */
  .btn-white{background:var(--grey-1);color:var(--blue-1);border-color:var(--g-e5);box-shadow:var(--shadow-sm)}
  .btn-white:hover{background:var(--blue-6)}
  .btn-white:active{background:var(--grey-1);transform:translateY(1px)}
  .btn-white:focus-visible{outline:none;box-shadow:0 0 0 3px var(--blue-1)}

  /* GREEN */
  .btn-green{background:var(--green-1);color:var(--blue-1);box-shadow:var(--shadow-sm)}
  .btn-green:hover{background:var(--green-2)}
  .btn-green:active{background:var(--green-1);transform:translateY(1px)}
  .btn-green:focus-visible{outline:none;box-shadow:0 0 0 3px var(--blue-1)}

  /* hero primary keeps the inverted white-on-navy treatment */
  .hero-cta .btn-primary{background:var(--grey-1);color:var(--blue-1)}
  .hero-cta .btn-primary:hover{background:var(--blue-6);transform:none;box-shadow:0 4px 16px rgba(9,32,67,.30)}
  .hero-cta .btn-primary:focus-visible{box-shadow:0 0 0 3px var(--coral-1)}

  /* ---- SIM-only card, freenet data-first design language ---- */
  .tcard-wrap{display:flex;flex-direction:column}
  .tcard{overflow:visible;padding:20px 20px 24px}
  .tcard .tgb{display:flex;align-items:baseline;gap:6px;margin:4px 0 2px}
  .tcard .tgb .num{font-family:var(--font-display);font-size:2.6rem;font-weight:700;letter-spacing:-.02em;line-height:1;color:var(--blue-1)}
  .tcard .tgb .num-unlim{font-size:1.7rem}
  .tcard .tgb .unit{font-size:1.05rem;font-weight:700;color:var(--blue-1)}
  .tcard .tname{font-size:.95rem;font-weight:600;color:var(--slate);margin:0 0 14px}
  .tnets{display:flex;gap:6px}
  .netchip{width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:.82rem;font-weight:800;color:#fff;line-height:1}
  .netchip sub{font-size:.62em;line-height:1}
  .nc-tk{background:#E20074}
  .nc-vf{background:#E60000}
  .nc-o2{background:#001E50}

  /* Das Aktionsband (Steppe 14.08.) ist am 31.08.2026 abends ausgebaut
     (Hendrik: "lenkt nur ab") — Verknappung, Code und Bedingung stehen
     gebuendelt in der Aktionszeile der Buehnen-Kachel (.hero-promo). */

  /* ---- Laufzeit-Switch (Molekül: Stepper/Switch) ----
     Ersetzt den früheren Netz-Switch. freenet.de fährt exakt diesen Toggle
     ("24 Monate Laufzeit | Monatlich kündbar") über dem Tarif-Raster. */
  .termswitch-wrap{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:2px 0 22px}
  .termswitch-lbl{font-size:.9rem;font-weight:700;color:var(--blue-1)}
  .termswitch{display:inline-flex;background:var(--blue-6);border:1.5px solid var(--g-e5);border-radius:999px;padding:4px;gap:4px;flex-wrap:wrap}
  .tsopt{position:relative;display:inline-flex;align-items:center;justify-content:center;padding:9px 22px;border-radius:999px;cursor:pointer;transition:background .15s ease,color .15s ease;color:var(--blue-1)}
  .tsopt input{position:absolute;opacity:0;width:0;height:0}
  .tsname{font-size:.92rem;font-weight:700}
  .tsopt:hover{background:#fff}
  .tsopt:has(input:checked){background:var(--blue-1);color:#fff}
  .tsopt:has(input:focus-visible){box-shadow:0 0 0 3px rgba(132,188,52,.45)}
  @media(max-width:560px){
    .termswitch{width:100%}
    .tsopt{flex:1 1 0;border-radius:999px}
  }

  /* ---- Netz-Zeile + Speed-Zeile in der Tarifkarte ----
     Susanne Boldt (23.07.2026): der Speed muss im Layout stehen, weil er den
     Unterschied zwischen freenet-Tarif und Original-Netztarif trägt. */
  .tnetrow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px}
  .tnetrow .netlogo{height:28px;width:28px;border-radius:7px;display:block}
  .tnetlbl{font-size:.82rem;font-weight:700;color:var(--blue-1)}
  .tfam{font-size:.7rem;font-weight:800;letter-spacing:.02em;padding:3px 9px;border-radius:999px;white-space:nowrap}
  /* Chip-Text in green-dd: green-7 (#659A0A) misst auf der hellen Flaeche
     nur 3,1:1 (axe: serious bei 11px bold). green-dd haelt 5,3:1. */
  .tfam-freenet{background:var(--green-6,#eef6e3);color:var(--green-dd);border:1px solid var(--green-1)}
  .tfam-original{background:var(--blue-6);color:var(--blue-1);border:1px solid var(--g-e5)}
  /* Blockueberschrift im Tarifraster (25.08.2026). Volle Gitterbreite, damit
     das Raster ein Raster bleibt und kein zweiter Container noetig ist. Der
     Untertitel sagt an, was die grosse Zahl im folgenden Block bedeutet — im
     Unlimited-Block ist das die Geschwindigkeit statt des Volumens. */
  .tgrid-head{grid-column:1/-1;margin:6px 0 -4px}
  .tgrid-head:not(:first-child){margin-top:26px;padding-top:22px;border-top:1px solid var(--g-e5)}
  .tgrid-head h3{font-family:var(--font-display);font-size:1.35rem;font-weight:700;letter-spacing:-.015em;color:var(--blue-1);margin:0 0 4px}
  .tgrid-head p{font-size:.92rem;color:var(--slate);margin:0;max-width:62ch}
  /* Der farbige Vorlauf (Steppe, 01.09.2026). Gruen ist --green-dd (#3E701E),
     nicht --green-1: das helle Markengruen misst auf Weiss 2,1:1 und faellt
     im axe-Gate durch, das dunkle 6,5:1. Optisch ist es derselbe gruene
     Akzent, den auch .bundles .eyebrow und die Aktionscode-Pille tragen. */
  .tgrid-lead{color:var(--green-dd);font-weight:800}
  .tspeed{display:flex;align-items:center;gap:7px;font-size:.86rem;font-weight:700;color:var(--slate);margin-bottom:14px;min-height:1.3em}
  .tspeed svg{width:16px;height:16px;flex:none}
  .tspeed-fast{color:var(--blue-1)}
  .tgrid-more{margin:22px 0 0;text-align:right}
  /* Trefferflaeche wie bei .tdetails: 19px Text, 24px sind Pflicht. */
  .tgrid-more a{font-size:.9rem;font-weight:700;color:var(--blue-1);text-decoration:underline;text-underline-offset:3px;
    display:inline-block;padding-block:12px;margin-block:-12px}
  .tpills{display:flex;flex-direction:column;gap:8px;margin-bottom:18px;align-items:flex-start}
  /* Gleiches Problem wie bei den Bundle-Teasern: der Blurb bricht je nach
     Tarif zwei- oder dreizeilig um, dadurch stehen die Monatspreise auf
     verschiedenen Höhen. Mindesthöhe nur in der mehrspaltigen Ansicht. */
  @media(min-width:620px){ .tpills{min-height:112px} }
  .tcard .tpills .pill{font-size:.8rem;padding:7px 14px;text-align:left;line-height:1.25}
  .pill-outline{background:#fff;border:1.5px solid var(--green-1);color:var(--blue-1)}
  .tprice-block{margin-bottom:2px}
  .tprice-label{font-size:.8rem;color:var(--slate);font-weight:600;display:block;margin-bottom:2px}
  .tcard .tprice{margin:0}
  /* immer gerendert, auch leer: reservierter Platz statt springender Höhe */
  .tcard .was{display:block;color:var(--slate);font-size:.8rem;font-weight:600;margin-top:3px;min-height:1.15em}
  /* Gleiche Regel wie bei .bwas — der Streichpreis der Tarifkarte bricht
     nicht zwischen Zahl und Waehrung um. */
  .tcard .was s{color:var(--coral-text);text-decoration-line:line-through;text-decoration-color:var(--coral-text);white-space:nowrap}
  .tcta{position:absolute;right:18px;bottom:-20px;width:52px;height:52px;border-radius:50%;background:var(--coral-1);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 18px rgba(235,92,71,.4);transition:background .15s ease,transform .1s ease;z-index:2}
  .tcta svg{width:22px;height:22px}
  .tcard:hover .tcta{background:var(--coral-2)}
  .tcard:active .tcta{transform:translateY(1px)}
  /* Mobile: the shorter single-column cards let the half-out arrow drop into the
     inter-card gap and clip the "Tarif- und Preisdetails" link. Tuck it back
     inside the card with room to spare. Desktop keeps the half-out look. */
  @media(max-width:640px){
    .tcard{padding-bottom:66px}
    .tcard .tcta{bottom:16px}
  }
  .tlegal{margin-top:30px;padding:0 4px}
  .tlegal-fine{display:block;font-size:.72rem;color:var(--slate);line-height:1.45;margin-bottom:5px}
  /* Trefferflaeche: der Text ist 17px hoch, WCAG 2.2 SC 2.5.8 verlangt 24.
     padding + negatives margin vergroessert nur den Treffer, nicht das Layout. */
  .tdetails{font-size:.78rem;font-weight:700;color:var(--blue-1);text-decoration:underline;text-underline-offset:2px;
    display:inline-block;padding-block:14px;margin-block:-14px}
  .tdetails:hover{color:var(--coral-1)}
  /* Klartext-Variante, solange freenet die Dokument-URLs nicht geliefert hat
     (Steppe, 24.08.2026). BEWUSST ohne Blau und ohne Unterstreichung: die
     alte Fassung sah aus wie ein Link und war keiner. Slate + normale Staerke
     sagen "Hinweis", nicht "klick mich". Gepinnt in no_dead_links_test.rb. */
  .tdetails-plain{display:block;font-size:.72rem;font-weight:600;color:var(--slate);line-height:1.45}
  .tdetails + .tdetails{margin-left:14px}

  /* ---- device bundle cards + slider (freenet HWO design language) ---- */
  .bundles{background:var(--blue-6)}
  .lede-tight{margin-bottom:18px}
  .bslider{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;padding:14px 2px 8px}
  /* Der Router-Reiter fuehrt zwei Geraete statt drei, mit der Alle-Angebote-
     Kachel also drei Spalten. Steht VOR den max-width-Regeln, damit die
     schmalen Breiten weiterhin gewinnen. */
  .bslider-router{grid-template-columns:repeat(3,1fr)}
  @media(max-width:1040px){.bslider{grid-template-columns:repeat(2,1fr)}}
  @media(max-width:600px){.bslider{grid-template-columns:1fr}}

  /* ---- Umschalter Handy/Router (Modul "Geraete mit Tarif") ----
     Ohne JavaScript: die Radios im Switch schalten die Panels per :has().
     Faellt :has() aus, stehen beide Listen untereinander — es fehlt nie ein
     Angebot, es ist nur laenger. Deshalb kein [hidden] und kein JS-Toggle. */
  .bundles:has(#devHandy:checked) .bslider-router{display:none}
  .bundles:has(#devRouter:checked) .bslider-handy{display:none}
  .bslider::-webkit-scrollbar{height:8px}
  .bslider::-webkit-scrollbar-thumb{background:var(--blue-4);border-radius:999px}
  .bcard{flex:none;min-width:0;position:relative;display:flex;flex-direction:column;background:#fff;border:1.5px solid var(--g-e5);border-radius:16px;padding:20px 20px 22px;box-shadow:var(--shadow-sm);text-decoration:none;color:var(--blue-1);transition:box-shadow .15s ease,transform .15s ease,border-color .15s ease;overflow:visible}
  .bcard:hover{box-shadow:var(--shadow-md);transform:translateY(-3px);border-color:var(--blue-4)}
  .bflag{position:absolute;top:-12px;right:20px;background:var(--green-1);color:var(--blue-1);font-size:.72rem;font-weight:700;padding:5px 13px;border-radius:999px;box-shadow:var(--shadow-sm)}
  .bhead .bname{font-family:var(--font-display);font-size:1.25rem;font-weight:700;line-height:1.15}
  .bhead .bsub{font-size:.9rem;color:var(--slate);font-weight:600;margin-top:2px}
  .bnets{display:flex;gap:6px;margin:12px 0 6px}
  .bmedia{position:relative;display:flex;justify-content:flex-start;align-items:center;height:196px;margin:4px 0 14px}
  .bmedia img{height:100%;width:auto;object-fit:contain}
  .bvol{position:absolute;right:2px;top:50%;transform:translateY(-50%);width:80px;height:80px;border-radius:50%;background:var(--blue-6);border:1px solid var(--blue-4);display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:var(--blue-1)}
  .bvol b{font-size:1.02rem;font-weight:800;line-height:1.05}
  .bvol small{font-size:.62rem;color:var(--slate)}
  /* Lange Labels ("Unlimited") sind bei 1,02rem 81px breit und laufen damit
     aus dem 80px-Kreis heraus. freenet verkleinert dort ebenfalls. Die Klasse
     setzt die View, wenn das Label nicht mehr in den Kreis passt. */
  .bvol-long b{font-size:.78rem;letter-spacing:-.01em}
  .bvol-long small{font-size:.58rem}
  .bpills{margin-bottom:14px}
  /* Die Pill bricht je nach Gerätename ein- oder zweizeilig um. Ohne feste
     Mindesthöhe wandert der Preisblock der kurzen Karte nach oben und die
     Preise "springen" im Kartenvergleich. */
  @media(min-width:601px){ .bpills{min-height:56px;display:flex;align-items:flex-start} }
  .bcard .pill-outline{font-size:.76rem;padding:7px 13px;display:inline-block}
  /* Beide Preisspalten haben denselben Aufbau (Label, Preis, .bwas), damit
     die Preise auf einer gemeinsamen Grundlinie sitzen. flex-start statt
     flex-end, sonst richten sich die Spaltenunterkanten aus und der
     Einmalpreis rutscht um die Höhe der Streichpreis-Zeile nach unten. */
  .bprices{display:flex;gap:20px;align-items:flex-start;margin-bottom:2px}
  .bcol{display:flex;flex-direction:column}
  .bprice-label{font-size:.76rem;color:var(--slate);font-weight:600;margin-bottom:2px}
  .bcard .now{font-size:1rem;font-weight:800;letter-spacing:-.02em}
  .bcard .now .eur{font-size:1.7rem;line-height:1}
  .bcard .now .cent{font-size:.82rem;line-height:1;font-weight:800;margin-left:2px}
  .bcard .now .cur{font-size:.82rem;line-height:1;font-weight:800;margin-left:4px;letter-spacing:0}
  /* Streichpreis wie auf freenet.de und wie in den Tarifkarten: das Label
     "statt regulär" bleibt in Slate stehen, durchgestrichen wird nur der
     Preis inklusive €-Zeichen. */
  .bwas{display:block;min-height:1em;margin-top:2px;font-size:.78rem;font-weight:600;color:var(--slate)}
  /* Das Euro-Zeichen darf NIE allein in die naechste Zeile fallen (Steppe
     24.08. fuer die Tarifkarten, Hendrik 27.08. erneut fuer die Bundles: dort
     stand "statt regulaer 54,99" und darunter einsam "EUR"). Der Streichpreis
     bleibt als Block zusammen; umbrochen wird davor, nach "statt regulaer". */
  .bwas s{color:var(--coral-text);text-decoration-line:line-through;text-decoration-color:var(--coral-text);white-space:nowrap}
  .blegal{margin-top:14px;padding-right:56px}
  .bcta{position:absolute;right:18px;bottom:18px}
  /* "all offers" promo card
     Barrierefreiheit: der Korall-CTA lag vorher auf dem dunklen Ende des
     Grünverlaufs (Luminanz-Kontrast ~1:1, WCAG 1.4.11 verlangt 3:1). Jetzt
     helle Grünfläche + dunkelblauer Button — über 12:1, Kachel bleibt grün. */
  /* "all offers" promo card: content is vertically centred as one group
     (heading + text + arrow) so the tile reads intentional instead of a heading
     stranded at the top with a huge empty middle.
     Fläche MUSS hellgrün bleiben (green-4, wie im abgenommenen Prototyp):
     Steppes Brandbook-Ticket verlangte "helle Fläche und Button in dunkelblau"
     (Option b), zugesagt wurde Kontrast über 12:1. Auf green-2 misst der
     Navy-Text nur 8,4:1 und die Fläche ist nicht mehr "hell" — das war eine
     Regression gegen die Abnahme, nicht nur Geschmack. Navy auf green-4: 13,3:1. */
  .bcard-all{background:var(--green-4);border:1.5px solid var(--green-d);justify-content:center;align-items:flex-start;gap:18px;min-height:520px}
  .bcard-all .bname{color:var(--blue-1);font-family:var(--font-display);font-size:1.3rem;font-weight:700;line-height:1.2}
  .bcard-all .ball-text{color:var(--blue-1);font-size:.95rem;margin-top:12px;max-width:100%}
  .bcard-all .bcta{position:static;background:var(--blue-1);color:#fff;width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 18px rgba(9,32,67,.28)}
  .bcard-all:hover .bcta{background:var(--navy-2)}
  @media(max-width:600px){ .bcard-all{min-height:0;padding-bottom:22px} }

  /* real carrier logos + bundle-section legibility */
  .netlogo{height:34px;width:34px;display:inline-block;vertical-align:middle;border-radius:8px}
  .bnets .netlogo{height:34px;width:34px}
  /* green-dd statt green-7: auf der hellblauen Sektionsflaeche misst green-7 nur 3,0:1 */
  .bundles .eyebrow{color:var(--green-dd);font-weight:800;letter-spacing:.12em}
  .bundles h2{color:var(--blue-1)}
  .bundles .lede{color:#48566f}

  /* 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(--navy);color:#fff;font-weight:800;
    border-radius:var(--radius-sm);text-decoration:none;transition:top .15s ease;
  }
  .skip-link:focus{top:8px;outline:3px solid var(--green);outline-offset:2px}

  /* ---------------------------------------------------------------------
     Nur rendern, was man sehen kann (29.08.2026, Performance)

     Die Startseite ist rund 10.700 px hoch und traegt 1265 Knoten, davon
     etwa 1000 unterhalb des ersten Bildschirms. Der Browser hat sie beim
     ersten Aufbau trotzdem alle vermessen: "Style & Layout" war mit 579 ms
     der groesste Einzelposten der Seite, groesser als jedes Skript.

     content-visibility ueberspringt Layout und Malen fuer Abschnitte, die
     noch nicht sichtbar sind. contain-intrinsic-size gibt dem Browser die
     erwartete Hoehe, damit die Scrollleiste nicht springt und Sprungmarken
     (#tarif aus den Hero-CTAs) an der richtigen Stelle landen — die Werte
     sind die gemessenen Hoehen, nicht geraten.

     #tarif bleibt bewusst AUSSEN VOR: es ist das Ziel der Hero-Buttons und
     der wichtigste Abschnitt der Seite. Ein Sprung dorthin soll nicht davon
     abhaengen, dass eine Schaetzung stimmt.
     --------------------------------------------------------------------- */
  #bundles { content-visibility: auto; contain-intrinsic-size: auto 1438px; }
  .trust { content-visibility: auto; contain-intrinsic-size: auto 75px; }
  .feelings { content-visibility: auto; contain-intrinsic-size: auto 630px; }
  .faq { content-visibility: auto; contain-intrinsic-size: auto 557px; }
  .site-footer, footer.site { content-visibility: auto; contain-intrinsic-size: auto 912px; }
