{"id":37275,"date":"2026-04-01T11:43:02","date_gmt":"2026-04-01T09:43:02","guid":{"rendered":"https:\/\/www.finanzen.net\/ratgeber\/?p=37275"},"modified":"2026-09-30T14:16:55","modified_gmt":"2026-09-30T12:16:55","slug":"riester-rente-umwandeln","status":"publish","type":"post","link":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/","title":{"rendered":"Riester Rente umwandeln"},"content":{"rendered":"\n<div class=\"container container--narrow\">\n    <div class=\"header\">\n                    <div class=\"header__image\">\n                <img loading=\"lazy\" decoding=\"async\" width=\"1408\" height=\"768\" src=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln.png\" class=\"attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" srcset=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln.png 1408w, https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln-300x164.png 300w, https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln-1024x559.png 1024w, https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln-768x419.png 768w\" sizes=\"auto, (max-width: 1408px) 100vw, 1408px\" \/>                            <\/div>\n                <div class=\"header__text\">\n                            <div class=\"headline headline--preline headline--h4 header__preline\">\n                                     <\/div>\n                                        <h1 class=\"headline headline--h1 header__headline headline--has-preline\">\n                    Riester-Rente umwandeln: So l\u00e4uft der Wechsel ins Altersvorsorgedepot                <\/h1>\n                        <div class=\"header__excerpt flow-content\">\n                                    <p>Die Werbung f\u00fcr den Riester-Nachfolger betont die h\u00f6here Zulage. Der eigentliche Hebel ist ein anderer: Bei 25.000 Euro Guthaben und 100 Euro monatlich \u00fcber 20 Jahre bringt die h\u00f6here F\u00f6rderung rund 4.800 Euro, der Wegfall von Beitragsgarantie und hohen Kosten dagegen rund 71.900 Euro. Dieser Ratgeber zeigt, welche vier Wege du mit deinem Vertrag hast, was die \u00dcbertragung tats\u00e4chlich kostet und wann du besser nicht wechselst, weil in deinem Altvertrag ein Garantiezins von 3,25 Prozent steht.<\/p>\n                            <\/div>\n            <div class=\"header__footer\">\n                <span class=\"header__meta\">\n                    <img loading=\"lazy\" decoding=\"async\" class=\"header__author-image\"\n                         src=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2025\/10\/Roland_Kuse-1-150x150.jpg\"\n                         width=\"58\"\n                         height=\"58\"\n                         alt=\"\">\n                    <span class=\"header__meta-info\">\n                        <span class=\"header__author-name\">\n                            von <a href=\"https:\/\/www.finanzen.net\/ratgeber\/author\/roland-kruse\/\" rel=\"author\" class=\"link link--no-underline\">Roland Kuse<\/a>                        <\/span>\n                        <span class=\"header__date\">\n                            <span class=\"hide-on-smartphone\">Aktualisiert am<\/span>\n                            <time datetime=\"2026-09-30 14:16\"\n                                  title=\"Aktualisiert am 30.09.2026\">\n                                30.09.26                            <\/time>\n                        <\/span>\n                    <\/span>\n                <\/span>\n\n                                    <div class=\"header__buttons\">\n                                                    <a class=\"fnet-button fnet-button--small\"\n                                                                  style=\"--button-background:#50ce6b;--button-hover-background:#50ce6b;\"\n                                                              href=\"https:\/\/www.finanzen.net\/ratgeber\/rechner-vergleiche\/zinseszinsrechner\/\"\n                               target=\"\">\n                                zum Zinseszinsrechner                            <\/a>\n                                                    <a class=\"fnet-button fnet-button--small hide-on-smartphone\"\n                                                                  style=\"--button-background:#d2042d;--button-hover-background:#d2042d;\"\n                                                              href=\"https:\/\/www.finanzen.net\/ratgeber\/vorsorge\/altersvorsorgedepot-rechner\/\"\n                               target=\"\">\n                                \ud83d\udc4b zum Altersvorsorgedepot Rechner                            <\/a>\n                                            <\/div>\n                            <\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n\n\n<div class=\"container container--narrow\" >\n    <div class=\"text\">\n        <div class=\"text__inner flow-content\">\n                            <h2>Das Wichtigste in K\u00fcrze<\/h2>\n<ul>\n<li>Ab dem 1. Januar 2027 werden keine neuen Riester-Vertr\u00e4ge mehr abgeschlossen. Bestehende Vertr\u00e4ge haben Bestandsschutz, alle bereits erhaltenen Zulagen und Steuervorteile bleiben dir, auch wenn du sp\u00e4ter wechselst.<\/li>\n<li>Niemals k\u00fcndigen. Eine K\u00fcndigung gilt als sch\u00e4dliche Verwendung, s\u00e4mtliche Zulagen und Steuervorteile sind zur\u00fcckzuzahlen. Bei 15 Jahren Laufzeit sind das schnell mehrere tausend Euro.<\/li>\n<li>Vier Wege stehen offen: Vertrag ruhen lassen, beim selben Anbieter in die neue F\u00f6rdersystematik wechseln, das Guthaben in ein <a href=\"https:\/\/www.finanzen.net\/ratgeber\/vorsorge\/altersvorsorgedepot\/\" data-ilm-light=\"96\" title=\"Altersvorsorgedepot\">Altersvorsorgedepot<\/a> \u00fcbertragen oder alles unver\u00e4ndert weiterlaufen lassen.<\/li>\n<li>Der Wechsel ist ab 2027 m\u00f6glich. Er l\u00e4uft \u00fcber eine K\u00fcndigung mit einer Frist von drei Monaten zum Quartalsende, nicht \u00fcber ein formloses Schreiben von heute auf morgen.<\/li>\n<li>Das neue System f\u00f6rdert st\u00e4rker: bis zu 540 Euro Grundzulage statt fester 175 Euro, Kosten von 0,1 bis 0,2 Prozent bei selbst gew\u00e4hlten ETFs statt 1,5 bis 2,5 Prozent, keine Beitragsgarantie und damit bis zu 100 Prozent Aktienquote.<\/li>\n<li>Den gr\u00f6\u00dften Unterschied macht nicht die Zulage, sondern die Rendite. Bei einem Bestand von 25.000 Euro und 100 Euro monatlich \u00fcber 20 Jahre bringt die h\u00f6here F\u00f6rderung rund 4.800 Euro, der Wegfall der Garantie rund 71.900 Euro.<\/li>\n<li>Zwei Sonderregeln erg\u00e4nzen das System: 200 Euro einmalig f\u00fcr unter 25-J\u00e4hrige und eine Grundzulage bis 175 Euro f\u00fcr mittelbar berechtigte Ehegatten. Einen Geringverdiener-Bonus gibt es nicht.<\/li>\n<li>Nicht wechseln sollten vor allem Sparer mit Altvertr\u00e4gen aus den Jahren 2002 bis 2004, weil dort ein Garantiezins von 3,25 Prozent und oft garantierte Rentenfaktoren im Vertrag stehen.<\/li>\n<\/ul>\n<!-- ZERO Ratgeber Newsletter \u2013 WordPress Snippet (Brevo-Script) -->\r\n<!-- Variante: Riester-\u00dcbertrag \u00b7 Volle Content-Breite \u00b7 Einfach in Shortcode-\/Snippet-Plugin einf\u00fcgen -->\r\n\r\n<style>\r\n  .zero-nl {\r\n    --zero-red: #E3002B;\r\n    --zero-red-hover: #c80025;\r\n    --zero-red-glow: rgba(227, 0, 43, 0.18);\r\n    --zero-card: #ffffff;\r\n    --zero-text: #0c0c0d;\r\n    --zero-muted: #6b6974;\r\n    --zero-border: #e2e0e4;\r\n    --zero-error-bg: #ffeded;\r\n    --zero-error-text: #661d1d;\r\n    --zero-error-border: #ff4949;\r\n    --zero-success-bg: #e7faf0;\r\n    --zero-success-text: #085229;\r\n    --zero-success-border: #13ce66;\r\n    --zero-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\r\n\r\n    font-family: var(--zero-font);\r\n    width: 100%;\r\n    margin-bottom: 40px;\r\n    background: #f0f0f0;\r\n    padding: 20px;\r\n    border-radius: 16px;\r\n  }\r\n\r\n  .zero-nl * { box-sizing: border-box; margin: 0; padding: 0; }\r\n\r\n  .zero-nl-card {\r\n    background: var(--zero-card);\r\n    border: 1px solid var(--zero-border);\r\n    border-radius: 12px;\r\n    width: 100%;\r\n    box-shadow: 0 2px 4px rgba(0,0,0,0.07), 0 8px 20px rgba(0,0,0,0.12), 0 16px 40px rgba(0,0,0,0.08);\r\n    overflow: hidden;\r\n  }\r\n\r\n  \/* Banner *\/\r\n  .zero-nl-banner {\r\n    background: #242424;\r\n    padding: 14px 28px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: space-between;\r\n    gap: 12px;\r\n  }\r\n\r\n  .zero-nl-banner-text {\r\n    color: #fff;\r\n    font-size: 15px;\r\n    font-weight: 700;\r\n    letter-spacing: 0.04em;\r\n    text-transform: uppercase;\r\n    white-space: nowrap;\r\n  }\r\n\r\n  .zero-nl-banner img {\r\n    height: 32px;\r\n    width: auto;\r\n    flex-shrink: 0;\r\n    display: block;\r\n  }\r\n\r\n  \/* Body \u2013 zweispaltig auf Desktop *\/\r\n  .zero-nl-body {\r\n    padding: 28px;\r\n    display: grid;\r\n    grid-template-columns: 1fr 1fr;\r\n    gap: 8px 36px;\r\n    align-items: start;\r\n  }\r\n\r\n  .zero-nl-left { grid-column: 1; }\r\n  .zero-nl-right { grid-column: 2; }\r\n\r\n  .zero-nl-title {\r\n    font-size: 26px;\r\n    font-weight: 800;\r\n    color: var(--zero-text);\r\n    line-height: 1.35;\r\n    margin-bottom: 6px;\r\n  }\r\n\r\n  .zero-nl-title em {\r\n    font-style: normal;\r\n    color: var(--zero-red);\r\n  }\r\n\r\n  .zero-nl-subtitle {\r\n    font-size: 13px;\r\n    color: var(--zero-muted);\r\n    line-height: 1.55;\r\n  }\r\n\r\n  \/* Brevo-Meldungen *\/\r\n  .zero-nl .sib-form-message-panel {\r\n    display: none;\r\n    padding: 10px 14px !important;\r\n    border-radius: 8px !important;\r\n    font-size: 13px !important;\r\n    line-height: 1.5 !important;\r\n    margin-bottom: 12px !important;\r\n    font-family: var(--zero-font) !important;\r\n    max-width: none !important;\r\n    text-align: center !important;\r\n  }\r\n\r\n  .zero-nl #error-message {\r\n    background: var(--zero-error-bg) !important;\r\n    color: var(--zero-error-text) !important;\r\n    border: 1px solid var(--zero-error-border) !important;\r\n  }\r\n\r\n  .zero-nl #success-message {\r\n    background: var(--zero-success-bg) !important;\r\n    color: var(--zero-success-text) !important;\r\n    border: 1px solid var(--zero-success-border) !important;\r\n  }\r\n\r\n  .zero-nl .sib-form-message-panel__text { justify-content: center; }\r\n  .zero-nl .sib-icon { display: none !important; }\r\n\r\n  .zero-nl #sib-container {\r\n    background: transparent !important;\r\n    border: none !important;\r\n    padding: 0 !important;\r\n    max-width: none !important;\r\n  }\r\n\r\n  \/* Label *\/\r\n  .zero-nl .zero-nl-label {\r\n    display: block;\r\n    font-size: 13px;\r\n    font-weight: 600;\r\n    color: var(--zero-muted);\r\n    margin-bottom: 5px;\r\n  }\r\n\r\n  .zero-nl .zero-nl-required {\r\n    color: var(--zero-red);\r\n    margin-left: 2px;\r\n  }\r\n\r\n  \/* Input *\/\r\n  .zero-nl .zero-nl-input {\r\n    width: 100%;\r\n    padding: 12px 14px;\r\n    font-size: 14px;\r\n    font-family: var(--zero-font);\r\n    color: var(--zero-text);\r\n    border: 1.5px solid var(--zero-border);\r\n    border-radius: 8px;\r\n    outline: none;\r\n    transition: border-color 0.2s ease, box-shadow 0.2s ease;\r\n    background: #faf9fb;\r\n  }\r\n\r\n  .zero-nl .zero-nl-input::placeholder { color: #b5b3ba; }\r\n  .zero-nl .zero-nl-input:focus {\r\n    border-color: var(--zero-red);\r\n    box-shadow: 0 0 0 3px var(--zero-red-glow);\r\n    background: #fff;\r\n  }\r\n\r\n  \/* Checkboxen *\/\r\n  .zero-nl .zero-nl-checks {\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 5px;\r\n    margin-top: 12px;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check {\r\n    display: flex;\r\n    align-items: flex-start;\r\n    gap: 8px;\r\n    cursor: pointer;\r\n    position: relative;\r\n    padding: 0;\r\n    margin: 0;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check input[type=\"checkbox\"] {\r\n    position: absolute;\r\n    opacity: 0;\r\n    width: 0;\r\n    height: 0;\r\n  }\r\n\r\n  .zero-nl .zero-nl-checkmark {\r\n    flex-shrink: 0;\r\n    width: 17px;\r\n    height: 17px;\r\n    border: 1.5px solid #ccc;\r\n    border-radius: 3px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    transition: all 0.15s ease;\r\n    margin-top: 1px;\r\n    background: #faf9fb;\r\n  }\r\n\r\n  .zero-nl .zero-nl-checkmark svg {\r\n    width: 10px;\r\n    height: 10px;\r\n    opacity: 0;\r\n    transform: scale(0.5);\r\n    transition: all 0.15s ease;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check input:checked + .zero-nl-checkmark {\r\n    background: var(--zero-red);\r\n    border-color: var(--zero-red);\r\n  }\r\n\r\n  .zero-nl .zero-nl-check input:checked + .zero-nl-checkmark svg {\r\n    opacity: 1;\r\n    transform: scale(1);\r\n  }\r\n\r\n  .zero-nl .zero-nl-check-text {\r\n    font-size: 12.5px;\r\n    line-height: 1.4;\r\n    color: var(--zero-text);\r\n  }\r\n\r\n  .zero-nl .zero-nl-check-text a {\r\n    color: var(--zero-red);\r\n    text-decoration: underline;\r\n    text-underline-offset: 2px;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check-text a:hover { text-decoration-thickness: 2px; }\r\n\r\n  .zero-nl .zero-nl-optional {\r\n    font-size: 11px;\r\n    color: var(--zero-muted);\r\n    font-weight: 400;\r\n  }\r\n\r\n  \/* CTA-Button *\/\r\n  .zero-nl .sib-form-block__button {\r\n    display: flex !important;\r\n    align-items: center !important;\r\n    justify-content: center !important;\r\n    gap: 8px !important;\r\n    width: 100% !important;\r\n    padding: 14px 24px !important;\r\n    font-size: 16px !important;\r\n    font-weight: 800 !important;\r\n    font-family: var(--zero-font) !important;\r\n    color: #fff !important;\r\n    background: #e0146a !important;\r\n    border: none !important;\r\n    border-radius: 60px !important;\r\n    cursor: pointer;\r\n    transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;\r\n    margin-top: 16px;\r\n    letter-spacing: 0.01em;\r\n    border-width: 0 !important;\r\n    box-shadow: 0 4px 16px rgba(224,20,106,0.18), 0 1px 3px rgba(0,0,0,0.08) !important;\r\n    line-height: 1.2 !important;\r\n  }\r\n\r\n  .zero-nl .sib-form-block__button:hover {\r\n    background: #c9115d !important;\r\n    box-shadow: 0 6px 24px rgba(224,20,106,0.28), 0 2px 6px rgba(0,0,0,0.1) !important;\r\n    transform: translateY(-1px);\r\n  }\r\n\r\n  .zero-nl .sib-form-block__button:active { transform: translateY(0) scale(0.985); }\r\n\r\n  .zero-nl .sib-hide-loader-icon { display: none; }\r\n\r\n  .zero-nl .entry__error {\r\n    display: block;\r\n    font-size: 12px !important;\r\n    font-family: var(--zero-font) !important;\r\n    color: var(--zero-error-text) !important;\r\n    background: transparent !important;\r\n    border: none !important;\r\n    padding: 3px 0 0 0 !important;\r\n    margin: 0 !important;\r\n    border-radius: 0 !important;\r\n  }\r\n\r\n  .zero-nl .input--hidden { position: absolute; left: -9999px; }\r\n\r\n  .zero-nl-trust {\r\n    font-size: 11px;\r\n    color: #a09da6;\r\n    text-align: center;\r\n    margin-top: 12px;\r\n    line-height: 1.4;\r\n    grid-column: 1 \/ -1;\r\n  }\r\n\r\n  \/* Mobile: einspaltig *\/\r\n  @media (max-width: 600px) {\r\n    .zero-nl {\r\n      padding: 16px;\r\n      border-radius: 12px;\r\n    }\r\n    .zero-nl-body {\r\n      grid-template-columns: 1fr;\r\n      gap: 20px;\r\n      padding: 24px 20px;\r\n    }\r\n    .zero-nl-left, .zero-nl-right { grid-column: 1; }\r\n    .zero-nl-banner {\r\n      padding: 12px 12px 12px 20px;\r\n      gap: 8px;\r\n    }\r\n    .zero-nl-banner-text {\r\n      font-size: 12px;\r\n      min-width: 0;\r\n    }\r\n    .zero-nl-banner img { height: 26px; }\r\n    .zero-nl-title { font-size: 22px; }\r\n    .zero-nl .sib-form-block__button { font-size: 15px !important; padding: 13px 20px !important; }\r\n  }\r\n<\/style>\r\n\r\n<div class=\"zero-nl\">\r\n  <div class=\"zero-nl-card\">\r\n\r\n    <!-- Banner -->\r\n    <div class=\"zero-nl-banner\">\r\n      <span class=\"zero-nl-banner-text\">\u2728 Kostenlos &amp; unverbindlich<\/span>\r\n      <img decoding=\"async\"\r\n        src=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/03\/zero_logo_26_light-1.png\"\r\n        alt=\"finanzen.net zero\"\r\n        loading=\"lazy\"\r\n      \/>\r\n    <\/div>\r\n\r\n    <div class=\"zero-nl-body\">\r\n\r\n      <!-- Linke Spalte: Text -->\r\n      <div class=\"zero-nl-left\">\r\n        <h2 class=\"zero-nl-title\">Riester-Vertrag \u00fcbertragen und bis zu <em>540&nbsp;\u20ac F\u00f6rderung<\/em> sichern.<\/h2>\r\n        <p class=\"zero-nl-subtitle\">Dein Riester-Guthaben kann ab 2027 in ein Altersvorsorgedepot bei unserem Broker finanzen.net ZERO wechseln \u2013 <strong>alle bisherigen Zulagen bleiben erhalten<\/strong>. Melde dich jetzt an, damit du am 1.&nbsp;Januar startklar bist.<\/p>\r\n      <\/div>\r\n\r\n      <!-- Rechte Spalte: Formular -->\r\n      <div class=\"zero-nl-right\">\r\n        <div class=\"sib-form\" style=\"text-align:center;background-color:transparent;\">\r\n          <div id=\"sib-form-container\" class=\"sib-form-container\">\r\n\r\n            <div id=\"error-message\" class=\"sib-form-message-panel\" style=\"font-size:16px;text-align:left;font-family:'Plus Jakarta Sans',sans-serif;color:#661d1d;background-color:#ffeded;border-radius:3px;border-color:#ff4949;max-width:540px;\">\r\n              <div class=\"sib-form-message-panel__text sib-form-message-panel__text--center\">\r\n                <span class=\"sib-form-message-panel__inner-text\">Deine Anmeldung konnte nicht gespeichert werden.<\/span>\r\n              <\/div>\r\n            <\/div>\r\n            <div><\/div>\r\n\r\n            <div id=\"success-message\" class=\"sib-form-message-panel\" style=\"font-size:16px;text-align:left;font-family:'Plus Jakarta Sans',sans-serif;color:#085229;background-color:#e7faf0;border-radius:3px;border-color:#13ce66;max-width:540px;\">\r\n              <div class=\"sib-form-message-panel__text sib-form-message-panel__text--center\">\r\n                <span class=\"sib-form-message-panel__inner-text\">Deine Anmeldung war erfolgreich! Wir melden uns bei dir.<\/span>\r\n              <\/div>\r\n            <\/div>\r\n            <div><\/div>\r\n\r\n            <div id=\"sib-container\" class=\"sib-container--large sib-container--vertical\" style=\"text-align:center;background-color:transparent;max-width:540px;border:none;direction:ltr;\">\r\n              <form id=\"sib-form\" method=\"POST\"\r\n                action=\"https:\/\/84e6d0bd.sibforms.com\/serve\/MUIFAO9KhSoKgWoRN7RzRjBQn4jIW8Scte-84jA5y2MsO70gYp35oUKg7GoJmrV2W_625cYuR4FRLB5t-JEn_xnd8XDBR_GezVkuzaDDHD44A4h0Aq9Ef5vo88q-L0XTr9WholZ2rL-JXx3sGaDFNkmtKgCdnDHxKEPdrSUJIZRkQ2KRI7WDuXm5bQRPghu5iiLwpYojVSzcJGiY\"\r\n                data-type=\"subscription\">\r\n\r\n                <!-- E-Mail -->\r\n                <div style=\"padding:0 0 4px;\">\r\n                  <div class=\"sib-input sib-form-block\">\r\n                    <div class=\"form__entry entry_block\">\r\n                      <div class=\"form__label-row\">\r\n                        <label class=\"zero-nl-label\" for=\"EMAIL\" data-required=\"*\">\r\n                          Deine E-Mail-Adresse<span class=\"zero-nl-required\">*<\/span>\r\n                        <\/label>\r\n                        <div class=\"entry__field\">\r\n                          <input class=\"zero-nl-input input\" type=\"text\" id=\"EMAIL\" name=\"EMAIL\" autocomplete=\"off\" placeholder=\"max@beispiel.de\" data-required=\"true\" required \/>\r\n                        <\/div>\r\n                      <\/div>\r\n                      <label class=\"entry__error entry__error--primary\"><\/label>\r\n                    <\/div>\r\n                  <\/div>\r\n                <\/div>\r\n\r\n                <!-- Checkboxen -->\r\n                <div class=\"zero-nl-checks\">\r\n                  <div class=\"sib-optin sib-form-block\">\r\n                    <div class=\"form__entry entry_mcq\">\r\n                      <div class=\"form__label-row\">\r\n                        <div class=\"entry__choice\">\r\n                          <label class=\"zero-nl-check\">\r\n                            <input type=\"checkbox\" class=\"input_replaced\" value=\"1\" id=\"JANEIN\" name=\"JANEIN\" \/>\r\n                            <span class=\"zero-nl-checkmark\">\r\n                              <svg viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M2 6l3 3 5-5\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>\r\n                            <\/span>\r\n                            <span class=\"zero-nl-check-text\">\r\n                              Ich habe einen Riester-Vertrag und m\u00f6chte ihn \u00fcbertragen\r\n                              <span class=\"zero-nl-optional\">(optional)<\/span>\r\n                            <\/span>\r\n                          <\/label>\r\n                        <\/div>\r\n                      <\/div>\r\n                      <label class=\"entry__error entry__error--primary\"><\/label>\r\n                    <\/div>\r\n                  <\/div>\r\n\r\n                <\/div>\r\n\r\n                <!-- CTA -->\r\n                <div style=\"padding:0;\">\r\n                  <div class=\"sib-form-block\" style=\"text-align:center;\">\r\n                    <button class=\"sib-form-block__button sib-form-block__button-with-loader\" style=\"font-size:16px;text-align:center;font-weight:800;font-family:'Plus Jakarta Sans',sans-serif;color:#FFFFFF;background-color:#e0146a;border-width:0px;\" form=\"sib-form\" type=\"submit\">\r\n                      <svg class=\"icon clickable__icon progress-indicator__icon sib-hide-loader-icon\" viewBox=\"0 0 512 512\">\r\n                        <path d=\"M460.116 373.846l-20.823-12.022c-5.541-3.199-7.54-10.159-4.663-15.874 30.137-59.886 28.343-131.652-5.386-189.946-33.641-58.394-94.896-95.833-161.827-99.676C261.028 55.961 256 50.751 256 44.352V20.309c0-6.904 5.808-12.337 12.703-11.982 83.556 4.306 160.163 50.864 202.11 123.677 42.063 72.696 44.079 162.316 6.031 236.832-3.14 6.148-10.75 8.461-16.728 5.01z\"\/>\r\n                      <\/svg>\r\n                      Jetzt Wechsel vorbereiten\r\n                    <\/button>\r\n                  <\/div>\r\n                <\/div>\r\n\r\n                <input type=\"text\" name=\"email_address_check\" value=\"\" class=\"input--hidden\">\r\n                <input type=\"hidden\" name=\"locale\" value=\"de\">\r\n              <\/form>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <p class=\"zero-nl-trust\">\ud83d\udd12 Kein Spam \u00b7 Jederzeit abmeldbar \u00b7 Deine Daten sind sicher<\/p>\r\n\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\n  window.REQUIRED_CODE_ERROR_MESSAGE = 'Bitte w\u00e4hle einen L\u00e4ndercode';\r\n  window.LOCALE = 'de';\r\n  window.EMAIL_INVALID_MESSAGE = window.SMS_INVALID_MESSAGE = \"Die angegebene E-Mail-Adresse ist ung\u00fcltig.\";\r\n  window.REQUIRED_ERROR_MESSAGE = \"Das ist ein Pflichtfeld.\";\r\n  window.GENERIC_INVALID_MESSAGE = \"Die angegebenen Daten sind ung\u00fcltig.\";\r\n  window.translation = {\r\n    common: {\r\n      selectedList: '{quantity} Liste ausgew\u00e4hlt',\r\n      selectedLists: '{quantity} Listen ausgew\u00e4hlt',\r\n      selectedOption: '{quantity} ausgew\u00e4hlt',\r\n      selectedOptions: '{quantity} ausgew\u00e4hlt'\r\n    }\r\n  };\r\n  var AUTOHIDE = Boolean(0);\r\n<\/script>\r\n<script defer src=\"https:\/\/sibforms.com\/forms\/end-form\/build\/main.js\"><\/script>\n<h2>Riester-Rente abgeschafft: was das konkret bedeutet<\/h2>\n<p>Ab dem 1. Januar 2027 sind keine Neuabschl\u00fcsse mehr m\u00f6glich. Bestehende Vertr\u00e4ge laufen weiter. Wer nichts tut, bekommt weiterhin die bisherigen 175 Euro Grundzulage und bis zu 300 Euro pro Kind, und die Beitragsgarantie bleibt bestehen.<\/p>\n<p>Der Nachfolger hei\u00dft Altersvorsorgedepot. Die F\u00f6rderung ist beitragsproportional: 50 Cent je Euro auf die ersten 360 Euro Eigenbeitrag im Jahr, 25 Cent je Euro auf die weiteren Beitr\u00e4ge bis 1.800 Euro. Die maximale Grundzulage liegt damit bei 540 Euro im Jahr. Die Kinderzulage betr\u00e4gt 100 Prozent des Eigenbeitrags bis h\u00f6chstens 300 Euro je Kind, in voller H\u00f6he also ab 25 Euro im Monat. Der Mindesteigenbeitrag liegt einheitlich bei 120 Euro im Jahr. Erstmals sind auch Gewerbetreibende und Freiberufler unmittelbar f\u00f6rderberechtigt.<\/p>\n<p>Die Grundlage ist das Altersvorsorgereformgesetz, das am 29. Mai 2026 im Bundesgesetzblatt verk\u00fcndet wurde.<\/p>\n<h2>Lohnt sich der Wechsel f\u00fcr dich?<\/h2>\n<p>Mit dem folgenden Rechner vergleichst du, ob ein Umstieg auf das Altersvorsorgedepot oder ein klassischer <a href=\"https:\/\/www.finanzen.net\/ratgeber\/etf\/praxis-strategien\/etf-sparplan\/net\/\" data-ilm-light=\"22\" title=\"ETF Sparplan\">ETF-Sparplan<\/a> mehr aus deinen Beitr\u00e4gen macht.<\/p>\n<!-- ============================================================\r\n  AVD Embed-Build | Tool 1.12 PreLaunch\r\n  Quelle: Tool_1.12_Riester_vs_Altersvorsorge_PreLaunch_Styleguide_UXUI_Preview.html\r\n  Generiert via Inline Embed\/_build\/embed_build.js\r\n  EINBAU: Kompletten Inhalt dieser Datei in EINEN WordPress-Custom-HTML-Block kopieren.\r\n  KEINE <link>-Stylesheets noetig; nur EIN Tool pro Seite einbinden.\r\n  ZEICHENSATZ: UTF-8 \u2014 \u00c4\u00d6\u00dc\u00e4\u00f6\u00fc\u00df\u20ac. Nicht entfernen: siehe Kommentar in embed_build.js.\r\n============================================================ -->\r\n<div class=\"avd-embed avdemb-t18pl\" data-avd-tool=\"1.12 PreLaunch\">\r\n<script src=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/themes\/fnet-ratgeber\/js\/libs\/chart.js\"><\/script>\r\n<script id=\"chartjs-b64\" type=\"text\/plain\">LyohCiAqIENoYXJ0LmpzIHY0LjQuMQogKiBodHRwczovL3d3dy5jaGFydGpzLm9yZwogKiAoYykgMjAyMyBDaGFydC5qcyBDb250cmlidXRvcnMKICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlCiAqLwohZnVuY3Rpb24odCxlKXsib2JqZWN0Ij09dHlwZW9mIGV4cG9ydHMmJiJ1bmRlZmluZWQiIT10eXBlb2YgbW9kdWxlP21vZHVsZS5leHBvcnRzPWUoKToiZnVuY3Rpb24iPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kP2RlZmluZShlKToodD0idW5kZWZpbmVkIiE9dHlwZW9mIGdsb2JhbFRoaXM\/Z2xvYmFsVGhpczp0fHxzZWxmKS5DaGFydD1lKCl9KHRoaXMsKGZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO3ZhciB0PU9iamVjdC5mcmVlemUoe19fcHJvdG9fXzpudWxsLGdldCBDb2xvcnMoKXtyZXR1cm4gR299LGdldCBEZWNpbWF0aW9uKCl7cmV0dXJuIFFvfSxnZXQgRmlsbGVyKCl7cmV0dXJuIG1hfSxnZXQgTGVnZW5kKCl7cmV0dXJuIHlhfSxnZXQgU3ViVGl0bGUoKXtyZXR1cm4ga2F9LGdldCBUaXRsZSgpe3JldHVybiBNYX0sZ2V0IFRvb2x0aXAoKXtyZXR1cm4gQmF9fSk7ZnVuY3Rpb24gZSgpe31jb25zdCBpPSgoKT0+e2xldCB0PTA7cmV0dXJuKCk9PnQrK30pKCk7ZnVuY3Rpb24gcyh0KXtyZXR1cm4gbnVsbD09dH1mdW5jdGlvbiBuKHQpe2lmKEFycmF5LmlzQXJyYXkmJkFycmF5LmlzQXJyYXkodCkpcmV0dXJuITA7Y29uc3QgZT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodCk7cmV0dXJuIltvYmplY3QiPT09ZS5zbGljZSgwLDcpJiYiQXJyYXldIj09PWUuc2xpY2UoLTYpfWZ1bmN0aW9uIG8odCl7cmV0dXJuIG51bGwhPT10JiYiW29iamVjdCBPYmplY3RdIj09PU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0KX1mdW5jdGlvbiBhKHQpe3JldHVybigibnVtYmVyIj09dHlwZW9mIHR8fHQgaW5zdGFuY2VvZiBOdW1iZXIpJiZpc0Zpbml0ZSgrdCl9ZnVuY3Rpb24gcih0LGUpe3JldHVybiBhKHQpP3Q6ZX1mdW5jdGlvbiBsKHQsZSl7cmV0dXJuIHZvaWQgMD09PXQ\/ZTp0fWNvbnN0IGg9KHQsZSk9PiJzdHJpbmciPT10eXBlb2YgdCYmdC5lbmRzV2l0aCgiJSIpP3BhcnNlRmxvYXQodCkvMTAwOit0L2UsYz0odCxlKT0+InN0cmluZyI9PXR5cGVvZiB0JiZ0LmVuZHNXaXRoKCIlIik\/cGFyc2VGbG9hdCh0KS8xMDAqZTordDtmdW5jdGlvbiBkKHQsZSxpKXtpZih0JiYiZnVuY3Rpb24iPT10eXBlb2YgdC5jYWxsKXJldHVybiB0LmFwcGx5KGksZSl9ZnVuY3Rpb24gdSh0LGUsaSxzKXtsZXQgYSxyLGw7aWYobih0KSlpZihyPXQubGVuZ3RoLHMpZm9yKGE9ci0xO2E+PTA7YS0tKWUuY2FsbChpLHRbYV0sYSk7ZWxzZSBmb3IoYT0wO2E8cjthKyspZS5jYWxsKGksdFthXSxhKTtlbHNlIGlmKG8odCkpZm9yKGw9T2JqZWN0LmtleXModCkscj1sLmxlbmd0aCxhPTA7YTxyO2ErKyllLmNhbGwoaSx0W2xbYV1dLGxbYV0pfWZ1bmN0aW9uIGYodCxlKXtsZXQgaSxzLG4sbztpZighdHx8IWV8fHQubGVuZ3RoIT09ZS5sZW5ndGgpcmV0dXJuITE7Zm9yKGk9MCxzPXQubGVuZ3RoO2k8czsrK2kpaWYobj10W2ldLG89ZVtpXSxuLmRhdGFzZXRJbmRleCE9PW8uZGF0YXNldEluZGV4fHxuLmluZGV4IT09by5pbmRleClyZXR1cm4hMTtyZXR1cm4hMH1mdW5jdGlvbiBnKHQpe2lmKG4odCkpcmV0dXJuIHQubWFwKGcpO2lmKG8odCkpe2NvbnN0IGU9T2JqZWN0LmNyZWF0ZShudWxsKSxpPU9iamVjdC5rZXlzKHQpLHM9aS5sZW5ndGg7bGV0IG49MDtmb3IoO248czsrK24pZVtpW25dXT1nKHRbaVtuXV0pO3JldHVybiBlfXJldHVybiB0fWZ1bmN0aW9uIHAodCl7cmV0dXJuLTE9PT1bIl9fcHJvdG9fXyIsInByb3RvdHlwZSIsImNvbnN0cnVjdG9yIl0uaW5kZXhPZih0KX1mdW5jdGlvbiBtKHQsZSxpLHMpe2lmKCFwKHQpKXJldHVybjtjb25zdCBuPWVbdF0sYT1pW3RdO28obikmJm8oYSk\/YihuLGEscyk6ZVt0XT1nKGEpfWZ1bmN0aW9uIGIodCxlLGkpe2NvbnN0IHM9bihlKT9lOltlXSxhPXMubGVuZ3RoO2lmKCFvKHQpKXJldHVybiB0O2NvbnN0IHI9KGk9aXx8e30pLm1lcmdlcnx8bTtsZXQgbDtmb3IobGV0IGU9MDtlPGE7KytlKXtpZihsPXNbZV0sIW8obCkpY29udGludWU7Y29uc3Qgbj1PYmplY3Qua2V5cyhsKTtmb3IobGV0IGU9MCxzPW4ubGVuZ3RoO2U8czsrK2UpcihuW2VdLHQsbCxpKX1yZXR1cm4gdH1mdW5jdGlvbiB4KHQsZSl7cmV0dXJuIGIodCxlLHttZXJnZXI6X30pfWZ1bmN0aW9uIF8odCxlLGkpe2lmKCFwKHQpKXJldHVybjtjb25zdCBzPWVbdF0sbj1pW3RdO28ocykmJm8obik\/eChzLG4pOk9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChlLHQpfHwoZVt0XT1nKG4pKX1jb25zdCB5PXsiIjp0PT50LHg6dD0+dC54LHk6dD0+dC55fTtmdW5jdGlvbiB2KHQpe2NvbnN0IGU9dC5zcGxpdCgiLiIpLGk9W107bGV0IHM9IiI7Zm9yKGNvbnN0IHQgb2YgZSlzKz10LHMuZW5kc1dpdGgoIlxcIik\/cz1zLnNsaWNlKDAsLTEpKyIuIjooaS5wdXNoKHMpLHM9IiIpO3JldHVybiBpfWZ1bmN0aW9uIE0odCxlKXtjb25zdCBpPXlbZV18fCh5W2VdPWZ1bmN0aW9uKHQpe2NvbnN0IGU9dih0KTtyZXR1cm4gdD0+e2Zvcihjb25zdCBpIG9mIGUpe2lmKCIiPT09aSlicmVhazt0PXQmJnRbaV19cmV0dXJuIHR9fShlKSk7cmV0dXJuIGkodCl9ZnVuY3Rpb24gdyh0KXtyZXR1cm4gdC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSt0LnNsaWNlKDEpfWNvbnN0IGs9dD0+dm9pZCAwIT09dCxTPXQ9PiJmdW5jdGlvbiI9PXR5cGVvZiB0LFA9KHQsZSk9PntpZih0LnNpemUhPT1lLnNpemUpcmV0dXJuITE7Zm9yKGNvbnN0IGkgb2YgdClpZighZS5oYXMoaSkpcmV0dXJuITE7cmV0dXJuITB9O2Z1bmN0aW9uIEQodCl7cmV0dXJuIm1vdXNldXAiPT09dC50eXBlfHwiY2xpY2siPT09dC50eXBlfHwiY29udGV4dG1lbnUiPT09dC50eXBlfWNvbnN0IEM9TWF0aC5QSSxPPTIqQyxBPU8rQyxUPU51bWJlci5QT1NJVElWRV9JTkZJTklUWSxMPUMvMTgwLEU9Qy8yLFI9Qy80LEk9MipDLzMsej1NYXRoLmxvZzEwLEY9TWF0aC5zaWduO2Z1bmN0aW9uIFYodCxlLGkpe3JldHVybiBNYXRoLmFicyh0LWUpPGl9ZnVuY3Rpb24gQih0KXtjb25zdCBlPU1hdGgucm91bmQodCk7dD1WKHQsZSx0LzFlMyk\/ZTp0O2NvbnN0IGk9TWF0aC5wb3coMTAsTWF0aC5mbG9vcih6KHQpKSkscz10L2k7cmV0dXJuKHM8PTE\/MTpzPD0yPzI6czw9NT81OjEwKSppfWZ1bmN0aW9uIFcodCl7Y29uc3QgZT1bXSxpPU1hdGguc3FydCh0KTtsZXQgcztmb3Iocz0xO3M8aTtzKyspdCVzPT0wJiYoZS5wdXNoKHMpLGUucHVzaCh0L3MpKTtyZXR1cm4gaT09PSgwfGkpJiZlLnB1c2goaSksZS5zb3J0KCgodCxlKT0+dC1lKSkucG9wKCksZX1mdW5jdGlvbiBOKHQpe3JldHVybiFpc05hTihwYXJzZUZsb2F0KHQpKSYmaXNGaW5pdGUodCl9ZnVuY3Rpb24gSCh0LGUpe2NvbnN0IGk9TWF0aC5yb3VuZCh0KTtyZXR1cm4gaS1lPD10JiZpK2U+PXR9ZnVuY3Rpb24gaih0LGUsaSl7bGV0IHMsbixvO2ZvcihzPTAsbj10Lmxlbmd0aDtzPG47cysrKW89dFtzXVtpXSxpc05hTihvKXx8KGUubWluPU1hdGgubWluKGUubWluLG8pLGUubWF4PU1hdGgubWF4KGUubWF4LG8pKX1mdW5jdGlvbiAkKHQpe3JldHVybiB0KihDLzE4MCl9ZnVuY3Rpb24gWSh0KXtyZXR1cm4gdCooMTgwL0MpfWZ1bmN0aW9uIFUodCl7aWYoIWEodCkpcmV0dXJuO2xldCBlPTEsaT0wO2Zvcig7TWF0aC5yb3VuZCh0KmUpL2UhPT10OyllKj0xMCxpKys7cmV0dXJuIGl9ZnVuY3Rpb24gWCh0LGUpe2NvbnN0IGk9ZS54LXQueCxzPWUueS10Lnksbj1NYXRoLnNxcnQoaSppK3Mqcyk7bGV0IG89TWF0aC5hdGFuMihzLGkpO3JldHVybiBvPC0uNSpDJiYobys9Tykse2FuZ2xlOm8sZGlzdGFuY2U6bn19ZnVuY3Rpb24gcSh0LGUpe3JldHVybiBNYXRoLnNxcnQoTWF0aC5wb3coZS54LXQueCwyKStNYXRoLnBvdyhlLnktdC55LDIpKX1mdW5jdGlvbiBLKHQsZSl7cmV0dXJuKHQtZStBKSVPLUN9ZnVuY3Rpb24gRyh0KXtyZXR1cm4odCVPK08pJU99ZnVuY3Rpb24gWih0LGUsaSxzKXtjb25zdCBuPUcodCksbz1HKGUpLGE9RyhpKSxyPUcoby1uKSxsPUcoYS1uKSxoPUcobi1vKSxjPUcobi1hKTtyZXR1cm4gbj09PW98fG49PT1hfHxzJiZvPT09YXx8cj5sJiZoPGN9ZnVuY3Rpb24gSih0LGUsaSl7cmV0dXJuIE1hdGgubWF4KGUsTWF0aC5taW4oaSx0KSl9ZnVuY3Rpb24gUSh0KXtyZXR1cm4gSih0LC0zMjc2OCwzMjc2Nyl9ZnVuY3Rpb24gdHQodCxlLGkscz0xZS02KXtyZXR1cm4gdD49TWF0aC5taW4oZSxpKS1zJiZ0PD1NYXRoLm1heChlLGkpK3N9ZnVuY3Rpb24gZXQodCxlLGkpe2k9aXx8KGk9PnRbaV08ZSk7bGV0IHMsbj10Lmxlbmd0aC0xLG89MDtmb3IoO24tbz4xOylzPW8rbj4+MSxpKHMpP289czpuPXM7cmV0dXJue2xvOm8saGk6bn19Y29uc3QgaXQ9KHQsZSxpLHMpPT5ldCh0LGkscz9zPT57Y29uc3Qgbj10W3NdW2VdO3JldHVybiBuPGl8fG49PT1pJiZ0W3MrMV1bZV09PT1pfTpzPT50W3NdW2VdPGkpLHN0PSh0LGUsaSk9PmV0KHQsaSwocz0+dFtzXVtlXT49aSkpO2Z1bmN0aW9uIG50KHQsZSxpKXtsZXQgcz0wLG49dC5sZW5ndGg7Zm9yKDtzPG4mJnRbc108ZTspcysrO2Zvcig7bj5zJiZ0W24tMV0+aTspbi0tO3JldHVybiBzPjB8fG48dC5sZW5ndGg\/dC5zbGljZShzLG4pOnR9Y29uc3Qgb3Q9WyJwdXNoIiwicG9wIiwic2hpZnQiLCJzcGxpY2UiLCJ1bnNoaWZ0Il07ZnVuY3Rpb24gYXQodCxlKXt0Ll9jaGFydGpzP3QuX2NoYXJ0anMubGlzdGVuZXJzLnB1c2goZSk6KE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfY2hhcnRqcyIse2NvbmZpZ3VyYWJsZTohMCxlbnVtZXJhYmxlOiExLHZhbHVlOntsaXN0ZW5lcnM6W2VdfX0pLG90LmZvckVhY2goKGU9Pntjb25zdCBpPSJfb25EYXRhIit3KGUpLHM9dFtlXTtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxlLHtjb25maWd1cmFibGU6ITAsZW51bWVyYWJsZTohMSx2YWx1ZSguLi5lKXtjb25zdCBuPXMuYXBwbHkodGhpcyxlKTtyZXR1cm4gdC5fY2hhcnRqcy5saXN0ZW5lcnMuZm9yRWFjaCgodD0+eyJmdW5jdGlvbiI9PXR5cGVvZiB0W2ldJiZ0W2ldKC4uLmUpfSkpLG59fSl9KSkpfWZ1bmN0aW9uIHJ0KHQsZSl7Y29uc3QgaT10Ll9jaGFydGpzO2lmKCFpKXJldHVybjtjb25zdCBzPWkubGlzdGVuZXJzLG49cy5pbmRleE9mKGUpOy0xIT09biYmcy5zcGxpY2UobiwxKSxzLmxlbmd0aD4wfHwob3QuZm9yRWFjaCgoZT0+e2RlbGV0ZSB0W2VdfSkpLGRlbGV0ZSB0Ll9jaGFydGpzKX1mdW5jdGlvbiBsdCh0KXtjb25zdCBlPW5ldyBTZXQodCk7cmV0dXJuIGUuc2l6ZT09PXQubGVuZ3RoP3Q6QXJyYXkuZnJvbShlKX1jb25zdCBodD0idW5kZWZpbmVkIj09dHlwZW9mIHdpbmRvdz9mdW5jdGlvbih0KXtyZXR1cm4gdCgpfTp3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lO2Z1bmN0aW9uIGN0KHQsZSl7bGV0IGk9W10scz0hMTtyZXR1cm4gZnVuY3Rpb24oLi4ubil7aT1uLHN8fChzPSEwLGh0LmNhbGwod2luZG93LCgoKT0+e3M9ITEsdC5hcHBseShlLGkpfSkpKX19ZnVuY3Rpb24gZHQodCxlKXtsZXQgaTtyZXR1cm4gZnVuY3Rpb24oLi4ucyl7cmV0dXJuIGU\/KGNsZWFyVGltZW91dChpKSxpPXNldFRpbWVvdXQodCxlLHMpKTp0LmFwcGx5KHRoaXMscyksZX19Y29uc3QgdXQ9dD0+InN0YXJ0Ij09PXQ\/ImxlZnQiOiJlbmQiPT09dD8icmlnaHQiOiJjZW50ZXIiLGZ0PSh0LGUsaSk9PiJzdGFydCI9PT10P2U6ImVuZCI9PT10P2k6KGUraSkvMixndD0odCxlLGkscyk9PnQ9PT0ocz8ibGVmdCI6InJpZ2h0Iik\/aToiY2VudGVyIj09PXQ\/KGUraSkvMjplO2Z1bmN0aW9uIHB0KHQsZSxpKXtjb25zdCBzPWUubGVuZ3RoO2xldCBuPTAsbz1zO2lmKHQuX3NvcnRlZCl7Y29uc3R7aVNjYWxlOmEsX3BhcnNlZDpyfT10LGw9YS5heGlzLHttaW46aCxtYXg6YyxtaW5EZWZpbmVkOmQsbWF4RGVmaW5lZDp1fT1hLmdldFVzZXJCb3VuZHMoKTtkJiYobj1KKE1hdGgubWluKGl0KHIsbCxoKS5sbyxpP3M6aXQoZSxsLGEuZ2V0UGl4ZWxGb3JWYWx1ZShoKSkubG8pLDAscy0xKSksbz11P0ooTWF0aC5tYXgoaXQocixhLmF4aXMsYywhMCkuaGkrMSxpPzA6aXQoZSxsLGEuZ2V0UGl4ZWxGb3JWYWx1ZShjKSwhMCkuaGkrMSksbixzKS1uOnMtbn1yZXR1cm57c3RhcnQ6bixjb3VudDpvfX1mdW5jdGlvbiBtdCh0KXtjb25zdHt4U2NhbGU6ZSx5U2NhbGU6aSxfc2NhbGVSYW5nZXM6c309dCxuPXt4bWluOmUubWluLHhtYXg6ZS5tYXgseW1pbjppLm1pbix5bWF4OmkubWF4fTtpZighcylyZXR1cm4gdC5fc2NhbGVSYW5nZXM9biwhMDtjb25zdCBvPXMueG1pbiE9PWUubWlufHxzLnhtYXghPT1lLm1heHx8cy55bWluIT09aS5taW58fHMueW1heCE9PWkubWF4O3JldHVybiBPYmplY3QuYXNzaWduKHMsbiksb31jbGFzcyBidHtjb25zdHJ1Y3Rvcigpe3RoaXMuX3JlcXVlc3Q9bnVsbCx0aGlzLl9jaGFydHM9bmV3IE1hcCx0aGlzLl9ydW5uaW5nPSExLHRoaXMuX2xhc3REYXRlPXZvaWQgMH1fbm90aWZ5KHQsZSxpLHMpe2NvbnN0IG49ZS5saXN0ZW5lcnNbc10sbz1lLmR1cmF0aW9uO24uZm9yRWFjaCgocz0+cyh7Y2hhcnQ6dCxpbml0aWFsOmUuaW5pdGlhbCxudW1TdGVwczpvLGN1cnJlbnRTdGVwOk1hdGgubWluKGktZS5zdGFydCxvKX0pKSl9X3JlZnJlc2goKXt0aGlzLl9yZXF1ZXN0fHwodGhpcy5fcnVubmluZz0hMCx0aGlzLl9yZXF1ZXN0PWh0LmNhbGwod2luZG93LCgoKT0+e3RoaXMuX3VwZGF0ZSgpLHRoaXMuX3JlcXVlc3Q9bnVsbCx0aGlzLl9ydW5uaW5nJiZ0aGlzLl9yZWZyZXNoKCl9KSkpfV91cGRhdGUodD1EYXRlLm5vdygpKXtsZXQgZT0wO3RoaXMuX2NoYXJ0cy5mb3JFYWNoKCgoaSxzKT0+e2lmKCFpLnJ1bm5pbmd8fCFpLml0ZW1zLmxlbmd0aClyZXR1cm47Y29uc3Qgbj1pLml0ZW1zO2xldCBvLGE9bi5sZW5ndGgtMSxyPSExO2Zvcig7YT49MDstLWEpbz1uW2FdLG8uX2FjdGl2ZT8oby5fdG90YWw+aS5kdXJhdGlvbiYmKGkuZHVyYXRpb249by5fdG90YWwpLG8udGljayh0KSxyPSEwKTooblthXT1uW24ubGVuZ3RoLTFdLG4ucG9wKCkpO3ImJihzLmRyYXcoKSx0aGlzLl9ub3RpZnkocyxpLHQsInByb2dyZXNzIikpLG4ubGVuZ3RofHwoaS5ydW5uaW5nPSExLHRoaXMuX25vdGlmeShzLGksdCwiY29tcGxldGUiKSxpLmluaXRpYWw9ITEpLGUrPW4ubGVuZ3RofSkpLHRoaXMuX2xhc3REYXRlPXQsMD09PWUmJih0aGlzLl9ydW5uaW5nPSExKX1fZ2V0QW5pbXModCl7Y29uc3QgZT10aGlzLl9jaGFydHM7bGV0IGk9ZS5nZXQodCk7cmV0dXJuIGl8fChpPXtydW5uaW5nOiExLGluaXRpYWw6ITAsaXRlbXM6W10sbGlzdGVuZXJzOntjb21wbGV0ZTpbXSxwcm9ncmVzczpbXX19LGUuc2V0KHQsaSkpLGl9bGlzdGVuKHQsZSxpKXt0aGlzLl9nZXRBbmltcyh0KS5saXN0ZW5lcnNbZV0ucHVzaChpKX1hZGQodCxlKXtlJiZlLmxlbmd0aCYmdGhpcy5fZ2V0QW5pbXModCkuaXRlbXMucHVzaCguLi5lKX1oYXModCl7cmV0dXJuIHRoaXMuX2dldEFuaW1zKHQpLml0ZW1zLmxlbmd0aD4wfXN0YXJ0KHQpe2NvbnN0IGU9dGhpcy5fY2hhcnRzLmdldCh0KTtlJiYoZS5ydW5uaW5nPSEwLGUuc3RhcnQ9RGF0ZS5ub3coKSxlLmR1cmF0aW9uPWUuaXRlbXMucmVkdWNlKCgodCxlKT0+TWF0aC5tYXgodCxlLl9kdXJhdGlvbikpLDApLHRoaXMuX3JlZnJlc2goKSl9cnVubmluZyh0KXtpZighdGhpcy5fcnVubmluZylyZXR1cm4hMTtjb25zdCBlPXRoaXMuX2NoYXJ0cy5nZXQodCk7cmV0dXJuISEoZSYmZS5ydW5uaW5nJiZlLml0ZW1zLmxlbmd0aCl9c3RvcCh0KXtjb25zdCBlPXRoaXMuX2NoYXJ0cy5nZXQodCk7aWYoIWV8fCFlLml0ZW1zLmxlbmd0aClyZXR1cm47Y29uc3QgaT1lLml0ZW1zO2xldCBzPWkubGVuZ3RoLTE7Zm9yKDtzPj0wOy0tcylpW3NdLmNhbmNlbCgpO2UuaXRlbXM9W10sdGhpcy5fbm90aWZ5KHQsZSxEYXRlLm5vdygpLCJjb21wbGV0ZSIpfXJlbW92ZSh0KXtyZXR1cm4gdGhpcy5fY2hhcnRzLmRlbGV0ZSh0KX19dmFyIHh0PW5ldyBidDsKLyohCiAqIEBrdXJrbGUvY29sb3IgdjAuMy4yCiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9rdXJrbGUvY29sb3IjcmVhZG1lCiAqIChjKSAyMDIzIEp1a2thIEt1cmtlbGEKICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlCiAqL2Z1bmN0aW9uIF90KHQpe3JldHVybiB0Ky41fDB9Y29uc3QgeXQ9KHQsZSxpKT0+TWF0aC5tYXgoTWF0aC5taW4odCxpKSxlKTtmdW5jdGlvbiB2dCh0KXtyZXR1cm4geXQoX3QoMi41NSp0KSwwLDI1NSl9ZnVuY3Rpb24gTXQodCl7cmV0dXJuIHl0KF90KDI1NSp0KSwwLDI1NSl9ZnVuY3Rpb24gd3QodCl7cmV0dXJuIHl0KF90KHQvMi41NSkvMTAwLDAsMSl9ZnVuY3Rpb24ga3QodCl7cmV0dXJuIHl0KF90KDEwMCp0KSwwLDEwMCl9Y29uc3QgU3Q9ezA6MCwxOjEsMjoyLDM6Myw0OjQsNTo1LDY6Niw3OjcsODo4LDk6OSxBOjEwLEI6MTEsQzoxMixEOjEzLEU6MTQsRjoxNSxhOjEwLGI6MTEsYzoxMixkOjEzLGU6MTQsZjoxNX0sUHQ9Wy4uLiIwMTIzNDU2Nzg5QUJDREVGIl0sRHQ9dD0+UHRbMTUmdF0sQ3Q9dD0+UHRbKDI0MCZ0KT4+NF0rUHRbMTUmdF0sT3Q9dD0+KDI0MCZ0KT4+ND09KDE1JnQpO2Z1bmN0aW9uIEF0KHQpe3ZhciBlPSh0PT5PdCh0LnIpJiZPdCh0LmcpJiZPdCh0LmIpJiZPdCh0LmEpKSh0KT9EdDpDdDtyZXR1cm4gdD8iIyIrZSh0LnIpK2UodC5nKStlKHQuYikrKCh0LGUpPT50PDI1NT9lKHQpOiIiKSh0LmEsZSk6dm9pZCAwfWNvbnN0IFR0PS9eKGhzbGE\/fGh3Ynxoc3YpXChccyooWy0rLmVcZF0rKSg\/OmRlZyk\/W1xzLF0rKFstKy5lXGRdKyklW1xzLF0rKFstKy5lXGRdKyklKD86W1xzLF0rKFstKy5lXGRdKykoJSk\/KT9ccypcKSQvO2Z1bmN0aW9uIEx0KHQsZSxpKXtjb25zdCBzPWUqTWF0aC5taW4oaSwxLWkpLG49KGUsbj0oZSt0LzMwKSUxMik9PmktcypNYXRoLm1heChNYXRoLm1pbihuLTMsOS1uLDEpLC0xKTtyZXR1cm5bbigwKSxuKDgpLG4oNCldfWZ1bmN0aW9uIEV0KHQsZSxpKXtjb25zdCBzPShzLG49KHMrdC82MCklNik9PmktaSplKk1hdGgubWF4KE1hdGgubWluKG4sNC1uLDEpLDApO3JldHVybltzKDUpLHMoMykscygxKV19ZnVuY3Rpb24gUnQodCxlLGkpe2NvbnN0IHM9THQodCwxLC41KTtsZXQgbjtmb3IoZStpPjEmJihuPTEvKGUraSksZSo9bixpKj1uKSxuPTA7bjwzO24rKylzW25dKj0xLWUtaSxzW25dKz1lO3JldHVybiBzfWZ1bmN0aW9uIEl0KHQpe2NvbnN0IGU9dC5yLzI1NSxpPXQuZy8yNTUscz10LmIvMjU1LG49TWF0aC5tYXgoZSxpLHMpLG89TWF0aC5taW4oZSxpLHMpLGE9KG4rbykvMjtsZXQgcixsLGg7cmV0dXJuIG4hPT1vJiYoaD1uLW8sbD1hPi41P2gvKDItbi1vKTpoLyhuK28pLHI9ZnVuY3Rpb24odCxlLGkscyxuKXtyZXR1cm4gdD09PW4\/KGUtaSkvcysoZTxpPzY6MCk6ZT09PW4\/KGktdCkvcysyOih0LWUpL3MrNH0oZSxpLHMsaCxuKSxyPTYwKnIrLjUpLFswfHIsbHx8MCxhXX1mdW5jdGlvbiB6dCh0LGUsaSxzKXtyZXR1cm4oQXJyYXkuaXNBcnJheShlKT90KGVbMF0sZVsxXSxlWzJdKTp0KGUsaSxzKSkubWFwKE10KX1mdW5jdGlvbiBGdCh0LGUsaSl7cmV0dXJuIHp0KEx0LHQsZSxpKX1mdW5jdGlvbiBWdCh0KXtyZXR1cm4odCUzNjArMzYwKSUzNjB9ZnVuY3Rpb24gQnQodCl7Y29uc3QgZT1UdC5leGVjKHQpO2xldCBpLHM9MjU1O2lmKCFlKXJldHVybjtlWzVdIT09aSYmKHM9ZVs2XT92dCgrZVs1XSk6TXQoK2VbNV0pKTtjb25zdCBuPVZ0KCtlWzJdKSxvPStlWzNdLzEwMCxhPStlWzRdLzEwMDtyZXR1cm4gaT0iaHdiIj09PWVbMV0\/ZnVuY3Rpb24odCxlLGkpe3JldHVybiB6dChSdCx0LGUsaSl9KG4sbyxhKToiaHN2Ij09PWVbMV0\/ZnVuY3Rpb24odCxlLGkpe3JldHVybiB6dChFdCx0LGUsaSl9KG4sbyxhKTpGdChuLG8sYSkse3I6aVswXSxnOmlbMV0sYjppWzJdLGE6c319Y29uc3QgV3Q9e3g6ImRhcmsiLFo6ImxpZ2h0IixZOiJyZSIsWDoiYmx1IixXOiJnciIsVjoibWVkaXVtIixVOiJzbGF0ZSIsQToiZWUiLFQ6Im9sIixTOiJvciIsQjoicmEiLEM6ImxhdGVnIixEOiJpZ2h0cyIsUjoiaW4iLFE6InR1cnF1b2lzIixFOiJoaSIsUDoicm8iLE86ImFsIixOOiJsZSIsTToiZGUiLEw6InllbGxvIixGOiJlbiIsSzoiY2giLEc6ImFya3MiLEg6ImVhIixJOiJpZ2h0ZyIsSjoid2gifSxOdD17T2ljZVhlOiJmMGY4ZmYiLGFudGlxdWV3RXRlOiJmYWViZDciLGFxdWE6ImZmZmYiLGFxdWFtYXJSZToiN2ZmZmQ0IixhenVZOiJmMGZmZmYiLGJlaWdlOiJmNWY1ZGMiLGJpc3F1ZToiZmZlNGM0IixibGFjazoiMCIsYmxhbktlZE9tb25kOiJmZmViY2QiLFhlOiJmZiIsWGV2aVRldDoiOGEyYmUyIixiUHduOiJhNTJhMmEiLGJ1cmx5d29vZDoiZGViODg3IixjYU10WGU6IjVmOWVhMCIsS2FydFl1c2U6IjdmZmYwMCIsS29jVGF0ZToiZDI2OTFlIixjU086ImZmN2Y1MCIsY1NuZmxvd2VyWGU6IjY0OTVlZCIsY1Nuc2lsazoiZmZmOGRjIixjcmltc29uOiJkYzE0M2MiLGN5YW46ImZmZmYiLHhYZToiOGIiLHhjeWFuOiI4YjhiIix4Z1RNblBkOiJiODg2MGIiLHhXYXk6ImE5YTlhOSIseGdZRjoiNjQwMCIseGdZeToiYTlhOWE5Iix4a2hha2k6ImJkYjc2YiIseG1hZ0Z0YToiOGIwMDhiIix4VGl2ZWdZRjoiNTU2YjJmIix4U2FuZ2U6ImZmOGMwMCIseFNjRWQ6Ijk5MzJjYyIseFlkOiI4YjAwMDAiLHhzT21vbjoiZTk5NjdhIix4c0hnWUY6IjhmYmM4ZiIseFVYZToiNDgzZDhiIix4VVdheToiMmY0ZjRmIix4VWdZeToiMmY0ZjRmIix4UWU6ImNlZDEiLHh2aVRldDoiOTQwMGQzIixkQXBwUms6ImZmMTQ5MyIsZEFwc2t5WGU6ImJmZmYiLGRpbVdheToiNjk2OTY5IixkaW1nWXk6IjY5Njk2OSIsZG9kZ2VyWGU6IjFlOTBmZiIsZmlZYnJpY2s6ImIyMjIyMiIsZmxTT3dFdGU6ImZmZmFmMCIsZm9Zc3RXQW46IjIyOGIyMiIsZnVLc2lhOiJmZjAwZmYiLGdhUnNiU286ImRjZGNkYyIsZ2hvc3R3RXRlOiJmOGY4ZmYiLGdUZDoiZmZkNzAwIixnVE1uUGQ6ImRhYTUyMCIsV2F5OiI4MDgwODAiLGdZRjoiODAwMCIsZ1lGTHc6ImFkZmYyZiIsZ1l5OiI4MDgwODAiLGhvbmV5TXc6ImYwZmZmMCIsaG90cFJrOiJmZjY5YjQiLFJkaWFuWWQ6ImNkNWM1YyIsUmRpZ286IjRiMDA4MiIsaXZTeToiZmZmZmYwIixraGFraToiZjBlNjhjIixsYXZGTXI6ImU2ZTZmYSIsbGF2Rk1yWHNoOiJmZmYwZjUiLGxhd25nWUY6IjdjZmMwMCIsTm1vbmNFZmZvbjoiZmZmYWNkIixaWGU6ImFkZDhlNiIsWmNTTzoiZjA4MDgwIixaY3lhbjoiZTBmZmZmIixaZ1RNblBkTHc6ImZhZmFkMiIsWldheToiZDNkM2QzIixaZ1lGOiI5MGVlOTAiLFpnWXk6ImQzZDNkMyIsWnBSazoiZmZiNmMxIixac09tb246ImZmYTA3YSIsWnNIZ1lGOiIyMGIyYWEiLFpza3lYZToiODdjZWZhIixaVVdheToiNzc4ODk5IixaVWdZeToiNzc4ODk5Iixac3RBbFhlOiJiMGM0ZGUiLFpMdzoiZmZmZmUwIixsaW1lOiJmZjAwIixsaW1lZ1lGOiIzMmNkMzIiLGxSRjoiZmFmMGU2IixtYWdGdGE6ImZmMDBmZiIsbWFQb246IjgwMDAwMCIsVmFxdWFtYXJSZToiNjZjZGFhIixWWGU6ImNkIixWU2NFZDoiYmE1NWQzIixWcHVycE46IjkzNzBkYiIsVnNIZ1lGOiIzY2IzNzEiLFZVWGU6IjdiNjhlZSIsVnNwclJnZ1lGOiJmYTlhIixWUWU6IjQ4ZDFjYyIsVnZpVGV0WWQ6ImM3MTU4NSIsbWlkbmlnaHRYZToiMTkxOTcwIixtUnRjWWFtOiJmNWZmZmEiLG1pc3R5UHNlOiJmZmU0ZTEiLG1vY2Nhc1I6ImZmZTRiNSIsbmF2YWpvd0V0ZToiZmZkZWFkIixuYXZ5OiI4MCIsVGRsYWNlOiJmZGY1ZTYiLFRpdmU6IjgwODAwMCIsVGl2ZWRCYjoiNmI4ZTIzIixTYW5nZToiZmZhNTAwIixTYW5nZVlkOiJmZjQ1MDAiLFNjRWQ6ImRhNzBkNiIscE9lZ1RNblBkOiJlZWU4YWEiLHBPZWdZRjoiOThmYjk4IixwT2VRZToiYWZlZWVlIixwT2V2aVRldFlkOiJkYjcwOTMiLHBhcGF5YXdFcDoiZmZlZmQ1IixwSEtwdWZmOiJmZmRhYjkiLHBlcnU6ImNkODUzZiIscFJrOiJmZmMwY2IiLHBsdW06ImRkYTBkZCIscG93TXJYZToiYjBlMGU2IixwdXJwTjoiODAwMDgwIixZYmVjY2FwdXJwTjoiNjYzMzk5IixZZDoiZmYwMDAwIixQc3licm93bjoiYmM4ZjhmIixQeU9YZToiNDE2OWUxIixzYWRkTmJQd246IjhiNDUxMyIsc09tb246ImZhODA3MiIsc2FuZHliUHduOiJmNGE0NjAiLHNIZ1lGOiIyZThiNTciLHNIc2hlbGw6ImZmZjVlZSIsc2lGbmE6ImEwNTIyZCIsc2lsdmVyOiJjMGMwYzAiLHNreVhlOiI4N2NlZWIiLFVYZToiNmE1YWNkIixVV2F5OiI3MDgwOTAiLFVnWXk6IjcwODA5MCIsc25vdzoiZmZmYWZhIixzcHJSZ2dZRjoiZmY3ZiIsc3RBbFhlOiI0NjgyYjQiLHRhbjoiZDJiNDhjIix0ZU86IjgwODAiLHRFc3ROOiJkOGJmZDgiLHRvbWF0bzoiZmY2MzQ3IixRZToiNDBlMGQwIix2aVRldDoiZWU4MmVlIixKSHQ6ImY1ZGViMyIsd0V0ZToiZmZmZmZmIix3RXRlc21va2U6ImY1ZjVmNSIsTHc6ImZmZmYwMCIsTHdnWUY6IjlhY2QzMiJ9O2xldCBIdDtmdW5jdGlvbiBqdCh0KXtIdHx8KEh0PWZ1bmN0aW9uKCl7Y29uc3QgdD17fSxlPU9iamVjdC5rZXlzKE50KSxpPU9iamVjdC5rZXlzKFd0KTtsZXQgcyxuLG8sYSxyO2ZvcihzPTA7czxlLmxlbmd0aDtzKyspe2ZvcihhPXI9ZVtzXSxuPTA7bjxpLmxlbmd0aDtuKyspbz1pW25dLHI9ci5yZXBsYWNlKG8sV3Rbb10pO289cGFyc2VJbnQoTnRbYV0sMTYpLHRbcl09W28+PjE2JjI1NSxvPj44JjI1NSwyNTUmb119cmV0dXJuIHR9KCksSHQudHJhbnNwYXJlbnQ9WzAsMCwwLDBdKTtjb25zdCBlPUh0W3QudG9Mb3dlckNhc2UoKV07cmV0dXJuIGUmJntyOmVbMF0sZzplWzFdLGI6ZVsyXSxhOjQ9PT1lLmxlbmd0aD9lWzNdOjI1NX19Y29uc3QgJHQ9L15yZ2JhP1woXHMqKFstKy5cZF0rKSglKT9bXHMsXSsoWy0rLmVcZF0rKSglKT9bXHMsXSsoWy0rLmVcZF0rKSglKT8oPzpbXHMsL10rKFstKy5lXGRdKykoJSk\/KT9ccypcKSQvO2NvbnN0IFl0PXQ9PnQ8PS4wMDMxMzA4PzEyLjkyKnQ6MS4wNTUqTWF0aC5wb3codCwxLzIuNCktLjA1NSxVdD10PT50PD0uMDQwNDU\/dC8xMi45MjpNYXRoLnBvdygodCsuMDU1KS8xLjA1NSwyLjQpO2Z1bmN0aW9uIFh0KHQsZSxpKXtpZih0KXtsZXQgcz1JdCh0KTtzW2VdPU1hdGgubWF4KDAsTWF0aC5taW4oc1tlXStzW2VdKmksMD09PWU\/MzYwOjEpKSxzPUZ0KHMpLHQucj1zWzBdLHQuZz1zWzFdLHQuYj1zWzJdfX1mdW5jdGlvbiBxdCh0LGUpe3JldHVybiB0P09iamVjdC5hc3NpZ24oZXx8e30sdCk6dH1mdW5jdGlvbiBLdCh0KXt2YXIgZT17cjowLGc6MCxiOjAsYToyNTV9O3JldHVybiBBcnJheS5pc0FycmF5KHQpP3QubGVuZ3RoPj0zJiYoZT17cjp0WzBdLGc6dFsxXSxiOnRbMl0sYToyNTV9LHQubGVuZ3RoPjMmJihlLmE9TXQodFszXSkpKTooZT1xdCh0LHtyOjAsZzowLGI6MCxhOjF9KSkuYT1NdChlLmEpLGV9ZnVuY3Rpb24gR3QodCl7cmV0dXJuInIiPT09dC5jaGFyQXQoMCk\/ZnVuY3Rpb24odCl7Y29uc3QgZT0kdC5leGVjKHQpO2xldCBpLHMsbixvPTI1NTtpZihlKXtpZihlWzddIT09aSl7Y29uc3QgdD0rZVs3XTtvPWVbOF0\/dnQodCk6eXQoMjU1KnQsMCwyNTUpfXJldHVybiBpPStlWzFdLHM9K2VbM10sbj0rZVs1XSxpPTI1NSYoZVsyXT92dChpKTp5dChpLDAsMjU1KSkscz0yNTUmKGVbNF0\/dnQocyk6eXQocywwLDI1NSkpLG49MjU1JihlWzZdP3Z0KG4pOnl0KG4sMCwyNTUpKSx7cjppLGc6cyxiOm4sYTpvfX19KHQpOkJ0KHQpfWNsYXNzIFp0e2NvbnN0cnVjdG9yKHQpe2lmKHQgaW5zdGFuY2VvZiBadClyZXR1cm4gdDtjb25zdCBlPXR5cGVvZiB0O2xldCBpO3ZhciBzLG4sbzsib2JqZWN0Ij09PWU\/aT1LdCh0KToic3RyaW5nIj09PWUmJihvPShzPXQpLmxlbmd0aCwiIyI9PT1zWzBdJiYoND09PW98fDU9PT1vP249e3I6MjU1JjE3KlN0W3NbMV1dLGc6MjU1JjE3KlN0W3NbMl1dLGI6MjU1JjE3KlN0W3NbM11dLGE6NT09PW8\/MTcqU3Rbc1s0XV06MjU1fTo3IT09byYmOSE9PW98fChuPXtyOlN0W3NbMV1dPDw0fFN0W3NbMl1dLGc6U3Rbc1szXV08PDR8U3Rbc1s0XV0sYjpTdFtzWzVdXTw8NHxTdFtzWzZdXSxhOjk9PT1vP1N0W3NbN11dPDw0fFN0W3NbOF1dOjI1NX0pKSxpPW58fGp0KHQpfHxHdCh0KSksdGhpcy5fcmdiPWksdGhpcy5fdmFsaWQ9ISFpfWdldCB2YWxpZCgpe3JldHVybiB0aGlzLl92YWxpZH1nZXQgcmdiKCl7dmFyIHQ9cXQodGhpcy5fcmdiKTtyZXR1cm4gdCYmKHQuYT13dCh0LmEpKSx0fXNldCByZ2IodCl7dGhpcy5fcmdiPUt0KHQpfXJnYlN0cmluZygpe3JldHVybiB0aGlzLl92YWxpZD8odD10aGlzLl9yZ2IpJiYodC5hPDI1NT9gcmdiYSgke3Qucn0sICR7dC5nfSwgJHt0LmJ9LCAke3d0KHQuYSl9KWA6YHJnYigke3Qucn0sICR7dC5nfSwgJHt0LmJ9KWApOnZvaWQgMDt2YXIgdH1oZXhTdHJpbmcoKXtyZXR1cm4gdGhpcy5fdmFsaWQ\/QXQodGhpcy5fcmdiKTp2b2lkIDB9aHNsU3RyaW5nKCl7cmV0dXJuIHRoaXMuX3ZhbGlkP2Z1bmN0aW9uKHQpe2lmKCF0KXJldHVybjtjb25zdCBlPUl0KHQpLGk9ZVswXSxzPWt0KGVbMV0pLG49a3QoZVsyXSk7cmV0dXJuIHQuYTwyNTU\/YGhzbGEoJHtpfSwgJHtzfSUsICR7bn0lLCAke3d0KHQuYSl9KWA6YGhzbCgke2l9LCAke3N9JSwgJHtufSUpYH0odGhpcy5fcmdiKTp2b2lkIDB9bWl4KHQsZSl7aWYodCl7Y29uc3QgaT10aGlzLnJnYixzPXQucmdiO2xldCBuO2NvbnN0IG89ZT09PW4\/LjU6ZSxhPTIqby0xLHI9aS5hLXMuYSxsPSgoYSpyPT0tMT9hOihhK3IpLygxK2EqcikpKzEpLzI7bj0xLWwsaS5yPTI1NSZsKmkucituKnMucisuNSxpLmc9MjU1JmwqaS5nK24qcy5nKy41LGkuYj0yNTUmbCppLmIrbipzLmIrLjUsaS5hPW8qaS5hKygxLW8pKnMuYSx0aGlzLnJnYj1pfXJldHVybiB0aGlzfWludGVycG9sYXRlKHQsZSl7cmV0dXJuIHQmJih0aGlzLl9yZ2I9ZnVuY3Rpb24odCxlLGkpe2NvbnN0IHM9VXQod3QodC5yKSksbj1VdCh3dCh0LmcpKSxvPVV0KHd0KHQuYikpO3JldHVybntyOk10KFl0KHMraSooVXQod3QoZS5yKSktcykpKSxnOk10KFl0KG4raSooVXQod3QoZS5nKSktbikpKSxiOk10KFl0KG8raSooVXQod3QoZS5iKSktbykpKSxhOnQuYStpKihlLmEtdC5hKX19KHRoaXMuX3JnYix0Ll9yZ2IsZSkpLHRoaXN9Y2xvbmUoKXtyZXR1cm4gbmV3IFp0KHRoaXMucmdiKX1hbHBoYSh0KXtyZXR1cm4gdGhpcy5fcmdiLmE9TXQodCksdGhpc31jbGVhcmVyKHQpe3JldHVybiB0aGlzLl9yZ2IuYSo9MS10LHRoaXN9Z3JleXNjYWxlKCl7Y29uc3QgdD10aGlzLl9yZ2IsZT1fdCguMyp0LnIrLjU5KnQuZysuMTEqdC5iKTtyZXR1cm4gdC5yPXQuZz10LmI9ZSx0aGlzfW9wYXF1ZXIodCl7cmV0dXJuIHRoaXMuX3JnYi5hKj0xK3QsdGhpc31uZWdhdGUoKXtjb25zdCB0PXRoaXMuX3JnYjtyZXR1cm4gdC5yPTI1NS10LnIsdC5nPTI1NS10LmcsdC5iPTI1NS10LmIsdGhpc31saWdodGVuKHQpe3JldHVybiBYdCh0aGlzLl9yZ2IsMix0KSx0aGlzfWRhcmtlbih0KXtyZXR1cm4gWHQodGhpcy5fcmdiLDIsLXQpLHRoaXN9c2F0dXJhdGUodCl7cmV0dXJuIFh0KHRoaXMuX3JnYiwxLHQpLHRoaXN9ZGVzYXR1cmF0ZSh0KXtyZXR1cm4gWHQodGhpcy5fcmdiLDEsLXQpLHRoaXN9cm90YXRlKHQpe3JldHVybiBmdW5jdGlvbih0LGUpe3ZhciBpPUl0KHQpO2lbMF09VnQoaVswXStlKSxpPUZ0KGkpLHQucj1pWzBdLHQuZz1pWzFdLHQuYj1pWzJdfSh0aGlzLl9yZ2IsdCksdGhpc319ZnVuY3Rpb24gSnQodCl7aWYodCYmIm9iamVjdCI9PXR5cGVvZiB0KXtjb25zdCBlPXQudG9TdHJpbmcoKTtyZXR1cm4iW29iamVjdCBDYW52YXNQYXR0ZXJuXSI9PT1lfHwiW29iamVjdCBDYW52YXNHcmFkaWVudF0iPT09ZX1yZXR1cm4hMX1mdW5jdGlvbiBRdCh0KXtyZXR1cm4gSnQodCk\/dDpuZXcgWnQodCl9ZnVuY3Rpb24gdGUodCl7cmV0dXJuIEp0KHQpP3Q6bmV3IFp0KHQpLnNhdHVyYXRlKC41KS5kYXJrZW4oLjEpLmhleFN0cmluZygpfWNvbnN0IGVlPVsieCIsInkiLCJib3JkZXJXaWR0aCIsInJhZGl1cyIsInRlbnNpb24iXSxpZT1bImNvbG9yIiwiYm9yZGVyQ29sb3IiLCJiYWNrZ3JvdW5kQ29sb3IiXTtjb25zdCBzZT1uZXcgTWFwO2Z1bmN0aW9uIG5lKHQsZSxpKXtyZXR1cm4gZnVuY3Rpb24odCxlKXtlPWV8fHt9O2NvbnN0IGk9dCtKU09OLnN0cmluZ2lmeShlKTtsZXQgcz1zZS5nZXQoaSk7cmV0dXJuIHN8fChzPW5ldyBJbnRsLk51bWJlckZvcm1hdCh0LGUpLHNlLnNldChpLHMpKSxzfShlLGkpLmZvcm1hdCh0KX1jb25zdCBvZT17dmFsdWVzOnQ9Pm4odCk\/dDoiIit0LG51bWVyaWModCxlLGkpe2lmKDA9PT10KXJldHVybiIwIjtjb25zdCBzPXRoaXMuY2hhcnQub3B0aW9ucy5sb2NhbGU7bGV0IG4sbz10O2lmKGkubGVuZ3RoPjEpe2NvbnN0IGU9TWF0aC5tYXgoTWF0aC5hYnMoaVswXS52YWx1ZSksTWF0aC5hYnMoaVtpLmxlbmd0aC0xXS52YWx1ZSkpOyhlPDFlLTR8fGU+MWUxNSkmJihuPSJzY2llbnRpZmljIiksbz1mdW5jdGlvbih0LGUpe2xldCBpPWUubGVuZ3RoPjM\/ZVsyXS52YWx1ZS1lWzFdLnZhbHVlOmVbMV0udmFsdWUtZVswXS52YWx1ZTtNYXRoLmFicyhpKT49MSYmdCE9PU1hdGguZmxvb3IodCkmJihpPXQtTWF0aC5mbG9vcih0KSk7cmV0dXJuIGl9KHQsaSl9Y29uc3QgYT16KE1hdGguYWJzKG8pKSxyPWlzTmFOKGEpPzE6TWF0aC5tYXgoTWF0aC5taW4oLTEqTWF0aC5mbG9vcihhKSwyMCksMCksbD17bm90YXRpb246bixtaW5pbXVtRnJhY3Rpb25EaWdpdHM6cixtYXhpbXVtRnJhY3Rpb25EaWdpdHM6cn07cmV0dXJuIE9iamVjdC5hc3NpZ24obCx0aGlzLm9wdGlvbnMudGlja3MuZm9ybWF0KSxuZSh0LHMsbCl9LGxvZ2FyaXRobWljKHQsZSxpKXtpZigwPT09dClyZXR1cm4iMCI7Y29uc3Qgcz1pW2VdLnNpZ25pZmljYW5kfHx0L01hdGgucG93KDEwLE1hdGguZmxvb3Ioeih0KSkpO3JldHVyblsxLDIsMyw1LDEwLDE1XS5pbmNsdWRlcyhzKXx8ZT4uOCppLmxlbmd0aD9vZS5udW1lcmljLmNhbGwodGhpcyx0LGUsaSk6IiJ9fTt2YXIgYWU9e2Zvcm1hdHRlcnM6b2V9O2NvbnN0IHJlPU9iamVjdC5jcmVhdGUobnVsbCksbGU9T2JqZWN0LmNyZWF0ZShudWxsKTtmdW5jdGlvbiBoZSh0LGUpe2lmKCFlKXJldHVybiB0O2NvbnN0IGk9ZS5zcGxpdCgiLiIpO2ZvcihsZXQgZT0wLHM9aS5sZW5ndGg7ZTxzOysrZSl7Y29uc3Qgcz1pW2VdO3Q9dFtzXXx8KHRbc109T2JqZWN0LmNyZWF0ZShudWxsKSl9cmV0dXJuIHR9ZnVuY3Rpb24gY2UodCxlLGkpe3JldHVybiJzdHJpbmciPT10eXBlb2YgZT9iKGhlKHQsZSksaSk6YihoZSh0LCIiKSxlKX1jbGFzcyBkZXtjb25zdHJ1Y3Rvcih0LGUpe3RoaXMuYW5pbWF0aW9uPXZvaWQgMCx0aGlzLmJhY2tncm91bmRDb2xvcj0icmdiYSgwLDAsMCwwLjEpIix0aGlzLmJvcmRlckNvbG9yPSJyZ2JhKDAsMCwwLDAuMSkiLHRoaXMuY29sb3I9IiM2NjYiLHRoaXMuZGF0YXNldHM9e30sdGhpcy5kZXZpY2VQaXhlbFJhdGlvPXQ9PnQuY2hhcnQucGxhdGZvcm0uZ2V0RGV2aWNlUGl4ZWxSYXRpbygpLHRoaXMuZWxlbWVudHM9e30sdGhpcy5ldmVudHM9WyJtb3VzZW1vdmUiLCJtb3VzZW91dCIsImNsaWNrIiwidG91Y2hzdGFydCIsInRvdWNobW92ZSJdLHRoaXMuZm9udD17ZmFtaWx5OiInSGVsdmV0aWNhIE5ldWUnLCAnSGVsdmV0aWNhJywgJ0FyaWFsJywgc2Fucy1zZXJpZiIsc2l6ZToxMixzdHlsZToibm9ybWFsIixsaW5lSGVpZ2h0OjEuMix3ZWlnaHQ6bnVsbH0sdGhpcy5ob3Zlcj17fSx0aGlzLmhvdmVyQmFja2dyb3VuZENvbG9yPSh0LGUpPT50ZShlLmJhY2tncm91bmRDb2xvciksdGhpcy5ob3ZlckJvcmRlckNvbG9yPSh0LGUpPT50ZShlLmJvcmRlckNvbG9yKSx0aGlzLmhvdmVyQ29sb3I9KHQsZSk9PnRlKGUuY29sb3IpLHRoaXMuaW5kZXhBeGlzPSJ4Iix0aGlzLmludGVyYWN0aW9uPXttb2RlOiJuZWFyZXN0IixpbnRlcnNlY3Q6ITAsaW5jbHVkZUludmlzaWJsZTohMX0sdGhpcy5tYWludGFpbkFzcGVjdFJhdGlvPSEwLHRoaXMub25Ib3Zlcj1udWxsLHRoaXMub25DbGljaz1udWxsLHRoaXMucGFyc2luZz0hMCx0aGlzLnBsdWdpbnM9e30sdGhpcy5yZXNwb25zaXZlPSEwLHRoaXMuc2NhbGU9dm9pZCAwLHRoaXMuc2NhbGVzPXt9LHRoaXMuc2hvd0xpbmU9ITAsdGhpcy5kcmF3QWN0aXZlRWxlbWVudHNPblRvcD0hMCx0aGlzLmRlc2NyaWJlKHQpLHRoaXMuYXBwbHkoZSl9c2V0KHQsZSl7cmV0dXJuIGNlKHRoaXMsdCxlKX1nZXQodCl7cmV0dXJuIGhlKHRoaXMsdCl9ZGVzY3JpYmUodCxlKXtyZXR1cm4gY2UobGUsdCxlKX1vdmVycmlkZSh0LGUpe3JldHVybiBjZShyZSx0LGUpfXJvdXRlKHQsZSxpLHMpe2NvbnN0IG49aGUodGhpcyx0KSxhPWhlKHRoaXMsaSkscj0iXyIrZTtPYmplY3QuZGVmaW5lUHJvcGVydGllcyhuLHtbcl06e3ZhbHVlOm5bZV0sd3JpdGFibGU6ITB9LFtlXTp7ZW51bWVyYWJsZTohMCxnZXQoKXtjb25zdCB0PXRoaXNbcl0sZT1hW3NdO3JldHVybiBvKHQpP09iamVjdC5hc3NpZ24oe30sZSx0KTpsKHQsZSl9LHNldCh0KXt0aGlzW3JdPXR9fX0pfWFwcGx5KHQpe3QuZm9yRWFjaCgodD0+dCh0aGlzKSkpfX12YXIgdWU9bmV3IGRlKHtfc2NyaXB0YWJsZTp0PT4hdC5zdGFydHNXaXRoKCJvbiIpLF9pbmRleGFibGU6dD0+ImV2ZW50cyIhPT10LGhvdmVyOntfZmFsbGJhY2s6ImludGVyYWN0aW9uIn0saW50ZXJhY3Rpb246e19zY3JpcHRhYmxlOiExLF9pbmRleGFibGU6ITF9fSxbZnVuY3Rpb24odCl7dC5zZXQoImFuaW1hdGlvbiIse2RlbGF5OnZvaWQgMCxkdXJhdGlvbjoxZTMsZWFzaW5nOiJlYXNlT3V0UXVhcnQiLGZuOnZvaWQgMCxmcm9tOnZvaWQgMCxsb29wOnZvaWQgMCx0bzp2b2lkIDAsdHlwZTp2b2lkIDB9KSx0LmRlc2NyaWJlKCJhbmltYXRpb24iLHtfZmFsbGJhY2s6ITEsX2luZGV4YWJsZTohMSxfc2NyaXB0YWJsZTp0PT4ib25Qcm9ncmVzcyIhPT10JiYib25Db21wbGV0ZSIhPT10JiYiZm4iIT09dH0pLHQuc2V0KCJhbmltYXRpb25zIix7Y29sb3JzOnt0eXBlOiJjb2xvciIscHJvcGVydGllczppZX0sbnVtYmVyczp7dHlwZToibnVtYmVyIixwcm9wZXJ0aWVzOmVlfX0pLHQuZGVzY3JpYmUoImFuaW1hdGlvbnMiLHtfZmFsbGJhY2s6ImFuaW1hdGlvbiJ9KSx0LnNldCgidHJhbnNpdGlvbnMiLHthY3RpdmU6e2FuaW1hdGlvbjp7ZHVyYXRpb246NDAwfX0scmVzaXplOnthbmltYXRpb246e2R1cmF0aW9uOjB9fSxzaG93OnthbmltYXRpb25zOntjb2xvcnM6e2Zyb206InRyYW5zcGFyZW50In0sdmlzaWJsZTp7dHlwZToiYm9vbGVhbiIsZHVyYXRpb246MH19fSxoaWRlOnthbmltYXRpb25zOntjb2xvcnM6e3RvOiJ0cmFuc3BhcmVudCJ9LHZpc2libGU6e3R5cGU6ImJvb2xlYW4iLGVhc2luZzoibGluZWFyIixmbjp0PT4wfHR9fX19KX0sZnVuY3Rpb24odCl7dC5zZXQoImxheW91dCIse2F1dG9QYWRkaW5nOiEwLHBhZGRpbmc6e3RvcDowLHJpZ2h0OjAsYm90dG9tOjAsbGVmdDowfX0pfSxmdW5jdGlvbih0KXt0LnNldCgic2NhbGUiLHtkaXNwbGF5OiEwLG9mZnNldDohMSxyZXZlcnNlOiExLGJlZ2luQXRaZXJvOiExLGJvdW5kczoidGlja3MiLGNsaXA6ITAsZ3JhY2U6MCxncmlkOntkaXNwbGF5OiEwLGxpbmVXaWR0aDoxLGRyYXdPbkNoYXJ0QXJlYTohMCxkcmF3VGlja3M6ITAsdGlja0xlbmd0aDo4LHRpY2tXaWR0aDoodCxlKT0+ZS5saW5lV2lkdGgsdGlja0NvbG9yOih0LGUpPT5lLmNvbG9yLG9mZnNldDohMX0sYm9yZGVyOntkaXNwbGF5OiEwLGRhc2g6W10sZGFzaE9mZnNldDowLHdpZHRoOjF9LHRpdGxlOntkaXNwbGF5OiExLHRleHQ6IiIscGFkZGluZzp7dG9wOjQsYm90dG9tOjR9fSx0aWNrczp7bWluUm90YXRpb246MCxtYXhSb3RhdGlvbjo1MCxtaXJyb3I6ITEsdGV4dFN0cm9rZVdpZHRoOjAsdGV4dFN0cm9rZUNvbG9yOiIiLHBhZGRpbmc6MyxkaXNwbGF5OiEwLGF1dG9Ta2lwOiEwLGF1dG9Ta2lwUGFkZGluZzozLGxhYmVsT2Zmc2V0OjAsY2FsbGJhY2s6YWUuZm9ybWF0dGVycy52YWx1ZXMsbWlub3I6e30sbWFqb3I6e30sYWxpZ246ImNlbnRlciIsY3Jvc3NBbGlnbjoibmVhciIsc2hvd0xhYmVsQmFja2Ryb3A6ITEsYmFja2Ryb3BDb2xvcjoicmdiYSgyNTUsIDI1NSwgMjU1LCAwLjc1KSIsYmFja2Ryb3BQYWRkaW5nOjJ9fSksdC5yb3V0ZSgic2NhbGUudGlja3MiLCJjb2xvciIsIiIsImNvbG9yIiksdC5yb3V0ZSgic2NhbGUuZ3JpZCIsImNvbG9yIiwiIiwiYm9yZGVyQ29sb3IiKSx0LnJvdXRlKCJzY2FsZS5ib3JkZXIiLCJjb2xvciIsIiIsImJvcmRlckNvbG9yIiksdC5yb3V0ZSgic2NhbGUudGl0bGUiLCJjb2xvciIsIiIsImNvbG9yIiksdC5kZXNjcmliZSgic2NhbGUiLHtfZmFsbGJhY2s6ITEsX3NjcmlwdGFibGU6dD0+IXQuc3RhcnRzV2l0aCgiYmVmb3JlIikmJiF0LnN0YXJ0c1dpdGgoImFmdGVyIikmJiJjYWxsYmFjayIhPT10JiYicGFyc2VyIiE9PXQsX2luZGV4YWJsZTp0PT4iYm9yZGVyRGFzaCIhPT10JiYidGlja0JvcmRlckRhc2giIT09dCYmImRhc2giIT09dH0pLHQuZGVzY3JpYmUoInNjYWxlcyIse19mYWxsYmFjazoic2NhbGUifSksdC5kZXNjcmliZSgic2NhbGUudGlja3MiLHtfc2NyaXB0YWJsZTp0PT4iYmFja2Ryb3BQYWRkaW5nIiE9PXQmJiJjYWxsYmFjayIhPT10LF9pbmRleGFibGU6dD0+ImJhY2tkcm9wUGFkZGluZyIhPT10fSl9XSk7ZnVuY3Rpb24gZmUoKXtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmInVuZGVmaW5lZCIhPXR5cGVvZiBkb2N1bWVudH1mdW5jdGlvbiBnZSh0KXtsZXQgZT10LnBhcmVudE5vZGU7cmV0dXJuIGUmJiJbb2JqZWN0IFNoYWRvd1Jvb3RdIj09PWUudG9TdHJpbmcoKSYmKGU9ZS5ob3N0KSxlfWZ1bmN0aW9uIHBlKHQsZSxpKXtsZXQgcztyZXR1cm4ic3RyaW5nIj09dHlwZW9mIHQ\/KHM9cGFyc2VJbnQodCwxMCksLTEhPT10LmluZGV4T2YoIiUiKSYmKHM9cy8xMDAqZS5wYXJlbnROb2RlW2ldKSk6cz10LHN9Y29uc3QgbWU9dD0+dC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUodCxudWxsKTtmdW5jdGlvbiBiZSh0LGUpe3JldHVybiBtZSh0KS5nZXRQcm9wZXJ0eVZhbHVlKGUpfWNvbnN0IHhlPVsidG9wIiwicmlnaHQiLCJib3R0b20iLCJsZWZ0Il07ZnVuY3Rpb24gX2UodCxlLGkpe2NvbnN0IHM9e307aT1pPyItIitpOiIiO2ZvcihsZXQgbj0wO248NDtuKyspe2NvbnN0IG89eGVbbl07c1tvXT1wYXJzZUZsb2F0KHRbZSsiLSIrbytpXSl8fDB9cmV0dXJuIHMud2lkdGg9cy5sZWZ0K3MucmlnaHQscy5oZWlnaHQ9cy50b3Arcy5ib3R0b20sc31jb25zdCB5ZT0odCxlLGkpPT4odD4wfHxlPjApJiYoIWl8fCFpLnNoYWRvd1Jvb3QpO2Z1bmN0aW9uIHZlKHQsZSl7aWYoIm5hdGl2ZSJpbiB0KXJldHVybiB0O2NvbnN0e2NhbnZhczppLGN1cnJlbnREZXZpY2VQaXhlbFJhdGlvOnN9PWUsbj1tZShpKSxvPSJib3JkZXItYm94Ij09PW4uYm94U2l6aW5nLGE9X2UobiwicGFkZGluZyIpLHI9X2UobiwiYm9yZGVyIiwid2lkdGgiKSx7eDpsLHk6aCxib3g6Y309ZnVuY3Rpb24odCxlKXtjb25zdCBpPXQudG91Y2hlcyxzPWkmJmkubGVuZ3RoP2lbMF06dCx7b2Zmc2V0WDpuLG9mZnNldFk6b309cztsZXQgYSxyLGw9ITE7aWYoeWUobixvLHQudGFyZ2V0KSlhPW4scj1vO2Vsc2V7Y29uc3QgdD1lLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO2E9cy5jbGllbnRYLXQubGVmdCxyPXMuY2xpZW50WS10LnRvcCxsPSEwfXJldHVybnt4OmEseTpyLGJveDpsfX0odCxpKSxkPWEubGVmdCsoYyYmci5sZWZ0KSx1PWEudG9wKyhjJiZyLnRvcCk7bGV0e3dpZHRoOmYsaGVpZ2h0Omd9PWU7cmV0dXJuIG8mJihmLT1hLndpZHRoK3Iud2lkdGgsZy09YS5oZWlnaHQrci5oZWlnaHQpLHt4Ok1hdGgucm91bmQoKGwtZCkvZippLndpZHRoL3MpLHk6TWF0aC5yb3VuZCgoaC11KS9nKmkuaGVpZ2h0L3MpfX1jb25zdCBNZT10PT5NYXRoLnJvdW5kKDEwKnQpLzEwO2Z1bmN0aW9uIHdlKHQsZSxpLHMpe2NvbnN0IG49bWUodCksbz1fZShuLCJtYXJnaW4iKSxhPXBlKG4ubWF4V2lkdGgsdCwiY2xpZW50V2lkdGgiKXx8VCxyPXBlKG4ubWF4SGVpZ2h0LHQsImNsaWVudEhlaWdodCIpfHxULGw9ZnVuY3Rpb24odCxlLGkpe2xldCBzLG47aWYodm9pZCAwPT09ZXx8dm9pZCAwPT09aSl7Y29uc3Qgbz1nZSh0KTtpZihvKXtjb25zdCB0PW8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksYT1tZShvKSxyPV9lKGEsImJvcmRlciIsIndpZHRoIiksbD1fZShhLCJwYWRkaW5nIik7ZT10LndpZHRoLWwud2lkdGgtci53aWR0aCxpPXQuaGVpZ2h0LWwuaGVpZ2h0LXIuaGVpZ2h0LHM9cGUoYS5tYXhXaWR0aCxvLCJjbGllbnRXaWR0aCIpLG49cGUoYS5tYXhIZWlnaHQsbywiY2xpZW50SGVpZ2h0Iil9ZWxzZSBlPXQuY2xpZW50V2lkdGgsaT10LmNsaWVudEhlaWdodH1yZXR1cm57d2lkdGg6ZSxoZWlnaHQ6aSxtYXhXaWR0aDpzfHxULG1heEhlaWdodDpufHxUfX0odCxlLGkpO2xldHt3aWR0aDpoLGhlaWdodDpjfT1sO2lmKCJjb250ZW50LWJveCI9PT1uLmJveFNpemluZyl7Y29uc3QgdD1fZShuLCJib3JkZXIiLCJ3aWR0aCIpLGU9X2UobiwicGFkZGluZyIpO2gtPWUud2lkdGgrdC53aWR0aCxjLT1lLmhlaWdodCt0LmhlaWdodH1oPU1hdGgubWF4KDAsaC1vLndpZHRoKSxjPU1hdGgubWF4KDAscz9oL3M6Yy1vLmhlaWdodCksaD1NZShNYXRoLm1pbihoLGEsbC5tYXhXaWR0aCkpLGM9TWUoTWF0aC5taW4oYyxyLGwubWF4SGVpZ2h0KSksaCYmIWMmJihjPU1lKGgvMikpO3JldHVybih2b2lkIDAhPT1lfHx2b2lkIDAhPT1pKSYmcyYmbC5oZWlnaHQmJmM+bC5oZWlnaHQmJihjPWwuaGVpZ2h0LGg9TWUoTWF0aC5mbG9vcihjKnMpKSkse3dpZHRoOmgsaGVpZ2h0OmN9fWZ1bmN0aW9uIGtlKHQsZSxpKXtjb25zdCBzPWV8fDEsbj1NYXRoLmZsb29yKHQuaGVpZ2h0KnMpLG89TWF0aC5mbG9vcih0LndpZHRoKnMpO3QuaGVpZ2h0PU1hdGguZmxvb3IodC5oZWlnaHQpLHQud2lkdGg9TWF0aC5mbG9vcih0LndpZHRoKTtjb25zdCBhPXQuY2FudmFzO3JldHVybiBhLnN0eWxlJiYoaXx8IWEuc3R5bGUuaGVpZ2h0JiYhYS5zdHlsZS53aWR0aCkmJihhLnN0eWxlLmhlaWdodD1gJHt0LmhlaWdodH1weGAsYS5zdHlsZS53aWR0aD1gJHt0LndpZHRofXB4YCksKHQuY3VycmVudERldmljZVBpeGVsUmF0aW8hPT1zfHxhLmhlaWdodCE9PW58fGEud2lkdGghPT1vKSYmKHQuY3VycmVudERldmljZVBpeGVsUmF0aW89cyxhLmhlaWdodD1uLGEud2lkdGg9byx0LmN0eC5zZXRUcmFuc2Zvcm0ocywwLDAscywwLDApLCEwKX1jb25zdCBTZT1mdW5jdGlvbigpe2xldCB0PSExO3RyeXtjb25zdCBlPXtnZXQgcGFzc2l2ZSgpe3JldHVybiB0PSEwLCExfX07ZmUoKSYmKHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJ0ZXN0IixudWxsLGUpLHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCJ0ZXN0IixudWxsLGUpKX1jYXRjaCh0KXt9cmV0dXJuIHR9KCk7ZnVuY3Rpb24gUGUodCxlKXtjb25zdCBpPWJlKHQsZSkscz1pJiZpLm1hdGNoKC9eKFxkKykoXC5cZCspP3B4JC8pO3JldHVybiBzPytzWzFdOnZvaWQgMH1mdW5jdGlvbiBEZSh0KXtyZXR1cm4hdHx8cyh0LnNpemUpfHxzKHQuZmFtaWx5KT9udWxsOih0LnN0eWxlP3Quc3R5bGUrIiAiOiIiKSsodC53ZWlnaHQ\/dC53ZWlnaHQrIiAiOiIiKSt0LnNpemUrInB4ICIrdC5mYW1pbHl9ZnVuY3Rpb24gQ2UodCxlLGkscyxuKXtsZXQgbz1lW25dO3JldHVybiBvfHwobz1lW25dPXQubWVhc3VyZVRleHQobikud2lkdGgsaS5wdXNoKG4pKSxvPnMmJihzPW8pLHN9ZnVuY3Rpb24gT2UodCxlLGkscyl7bGV0IG89KHM9c3x8e30pLmRhdGE9cy5kYXRhfHx7fSxhPXMuZ2FyYmFnZUNvbGxlY3Q9cy5nYXJiYWdlQ29sbGVjdHx8W107cy5mb250IT09ZSYmKG89cy5kYXRhPXt9LGE9cy5nYXJiYWdlQ29sbGVjdD1bXSxzLmZvbnQ9ZSksdC5zYXZlKCksdC5mb250PWU7bGV0IHI9MDtjb25zdCBsPWkubGVuZ3RoO2xldCBoLGMsZCx1LGY7Zm9yKGg9MDtoPGw7aCsrKWlmKHU9aVtoXSxudWxsPT11fHxuKHUpKXtpZihuKHUpKWZvcihjPTAsZD11Lmxlbmd0aDtjPGQ7YysrKWY9dVtjXSxudWxsPT1mfHxuKGYpfHwocj1DZSh0LG8sYSxyLGYpKX1lbHNlIHI9Q2UodCxvLGEscix1KTt0LnJlc3RvcmUoKTtjb25zdCBnPWEubGVuZ3RoLzI7aWYoZz5pLmxlbmd0aCl7Zm9yKGg9MDtoPGc7aCsrKWRlbGV0ZSBvW2FbaF1dO2Euc3BsaWNlKDAsZyl9cmV0dXJuIHJ9ZnVuY3Rpb24gQWUodCxlLGkpe2NvbnN0IHM9dC5jdXJyZW50RGV2aWNlUGl4ZWxSYXRpbyxuPTAhPT1pP01hdGgubWF4KGkvMiwuNSk6MDtyZXR1cm4gTWF0aC5yb3VuZCgoZS1uKSpzKS9zK259ZnVuY3Rpb24gVGUodCxlKXsoZT1lfHx0LmdldENvbnRleHQoIjJkIikpLnNhdmUoKSxlLnJlc2V0VHJhbnNmb3JtKCksZS5jbGVhclJlY3QoMCwwLHQud2lkdGgsdC5oZWlnaHQpLGUucmVzdG9yZSgpfWZ1bmN0aW9uIExlKHQsZSxpLHMpe0VlKHQsZSxpLHMsbnVsbCl9ZnVuY3Rpb24gRWUodCxlLGkscyxuKXtsZXQgbyxhLHIsbCxoLGMsZCx1O2NvbnN0IGY9ZS5wb2ludFN0eWxlLGc9ZS5yb3RhdGlvbixwPWUucmFkaXVzO2xldCBtPShnfHwwKSpMO2lmKGYmJiJvYmplY3QiPT10eXBlb2YgZiYmKG89Zi50b1N0cmluZygpLCJbb2JqZWN0IEhUTUxJbWFnZUVsZW1lbnRdIj09PW98fCJbb2JqZWN0IEhUTUxDYW52YXNFbGVtZW50XSI9PT1vKSlyZXR1cm4gdC5zYXZlKCksdC50cmFuc2xhdGUoaSxzKSx0LnJvdGF0ZShtKSx0LmRyYXdJbWFnZShmLC1mLndpZHRoLzIsLWYuaGVpZ2h0LzIsZi53aWR0aCxmLmhlaWdodCksdm9pZCB0LnJlc3RvcmUoKTtpZighKGlzTmFOKHApfHxwPD0wKSl7c3dpdGNoKHQuYmVnaW5QYXRoKCksZil7ZGVmYXVsdDpuP3QuZWxsaXBzZShpLHMsbi8yLHAsMCwwLE8pOnQuYXJjKGkscyxwLDAsTyksdC5jbG9zZVBhdGgoKTticmVhaztjYXNlInRyaWFuZ2xlIjpjPW4\/bi8yOnAsdC5tb3ZlVG8oaStNYXRoLnNpbihtKSpjLHMtTWF0aC5jb3MobSkqcCksbSs9SSx0LmxpbmVUbyhpK01hdGguc2luKG0pKmMscy1NYXRoLmNvcyhtKSpwKSxtKz1JLHQubGluZVRvKGkrTWF0aC5zaW4obSkqYyxzLU1hdGguY29zKG0pKnApLHQuY2xvc2VQYXRoKCk7YnJlYWs7Y2FzZSJyZWN0Um91bmRlZCI6aD0uNTE2KnAsbD1wLWgsYT1NYXRoLmNvcyhtK1IpKmwsZD1NYXRoLmNvcyhtK1IpKihuP24vMi1oOmwpLHI9TWF0aC5zaW4obStSKSpsLHU9TWF0aC5zaW4obStSKSoobj9uLzItaDpsKSx0LmFyYyhpLWQscy1yLGgsbS1DLG0tRSksdC5hcmMoaSt1LHMtYSxoLG0tRSxtKSx0LmFyYyhpK2QscytyLGgsbSxtK0UpLHQuYXJjKGktdSxzK2EsaCxtK0UsbStDKSx0LmNsb3NlUGF0aCgpO2JyZWFrO2Nhc2UicmVjdCI6aWYoIWcpe2w9TWF0aC5TUVJUMV8yKnAsYz1uP24vMjpsLHQucmVjdChpLWMscy1sLDIqYywyKmwpO2JyZWFrfW0rPVI7Y2FzZSJyZWN0Um90IjpkPU1hdGguY29zKG0pKihuP24vMjpwKSxhPU1hdGguY29zKG0pKnAscj1NYXRoLnNpbihtKSpwLHU9TWF0aC5zaW4obSkqKG4\/bi8yOnApLHQubW92ZVRvKGktZCxzLXIpLHQubGluZVRvKGkrdSxzLWEpLHQubGluZVRvKGkrZCxzK3IpLHQubGluZVRvKGktdSxzK2EpLHQuY2xvc2VQYXRoKCk7YnJlYWs7Y2FzZSJjcm9zc1JvdCI6bSs9UjtjYXNlImNyb3NzIjpkPU1hdGguY29zKG0pKihuP24vMjpwKSxhPU1hdGguY29zKG0pKnAscj1NYXRoLnNpbihtKSpwLHU9TWF0aC5zaW4obSkqKG4\/bi8yOnApLHQubW92ZVRvKGktZCxzLXIpLHQubGluZVRvKGkrZCxzK3IpLHQubW92ZVRvKGkrdSxzLWEpLHQubGluZVRvKGktdSxzK2EpO2JyZWFrO2Nhc2Uic3RhciI6ZD1NYXRoLmNvcyhtKSoobj9uLzI6cCksYT1NYXRoLmNvcyhtKSpwLHI9TWF0aC5zaW4obSkqcCx1PU1hdGguc2luKG0pKihuP24vMjpwKSx0Lm1vdmVUbyhpLWQscy1yKSx0LmxpbmVUbyhpK2QscytyKSx0Lm1vdmVUbyhpK3Uscy1hKSx0LmxpbmVUbyhpLXUscythKSxtKz1SLGQ9TWF0aC5jb3MobSkqKG4\/bi8yOnApLGE9TWF0aC5jb3MobSkqcCxyPU1hdGguc2luKG0pKnAsdT1NYXRoLnNpbihtKSoobj9uLzI6cCksdC5tb3ZlVG8oaS1kLHMtciksdC5saW5lVG8oaStkLHMrciksdC5tb3ZlVG8oaSt1LHMtYSksdC5saW5lVG8oaS11LHMrYSk7YnJlYWs7Y2FzZSJsaW5lIjphPW4\/bi8yOk1hdGguY29zKG0pKnAscj1NYXRoLnNpbihtKSpwLHQubW92ZVRvKGktYSxzLXIpLHQubGluZVRvKGkrYSxzK3IpO2JyZWFrO2Nhc2UiZGFzaCI6dC5tb3ZlVG8oaSxzKSx0LmxpbmVUbyhpK01hdGguY29zKG0pKihuP24vMjpwKSxzK01hdGguc2luKG0pKnApO2JyZWFrO2Nhc2UhMTp0LmNsb3NlUGF0aCgpfXQuZmlsbCgpLGUuYm9yZGVyV2lkdGg+MCYmdC5zdHJva2UoKX19ZnVuY3Rpb24gUmUodCxlLGkpe3JldHVybiBpPWl8fC41LCFlfHx0JiZ0Lng+ZS5sZWZ0LWkmJnQueDxlLnJpZ2h0K2kmJnQueT5lLnRvcC1pJiZ0Lnk8ZS5ib3R0b20raX1mdW5jdGlvbiBJZSh0LGUpe3Quc2F2ZSgpLHQuYmVnaW5QYXRoKCksdC5yZWN0KGUubGVmdCxlLnRvcCxlLnJpZ2h0LWUubGVmdCxlLmJvdHRvbS1lLnRvcCksdC5jbGlwKCl9ZnVuY3Rpb24gemUodCl7dC5yZXN0b3JlKCl9ZnVuY3Rpb24gRmUodCxlLGkscyxuKXtpZighZSlyZXR1cm4gdC5saW5lVG8oaS54LGkueSk7aWYoIm1pZGRsZSI9PT1uKXtjb25zdCBzPShlLngraS54KS8yO3QubGluZVRvKHMsZS55KSx0LmxpbmVUbyhzLGkueSl9ZWxzZSJhZnRlciI9PT1uIT0hIXM\/dC5saW5lVG8oZS54LGkueSk6dC5saW5lVG8oaS54LGUueSk7dC5saW5lVG8oaS54LGkueSl9ZnVuY3Rpb24gVmUodCxlLGkscyl7aWYoIWUpcmV0dXJuIHQubGluZVRvKGkueCxpLnkpO3QuYmV6aWVyQ3VydmVUbyhzP2UuY3AxeDplLmNwMngscz9lLmNwMXk6ZS5jcDJ5LHM\/aS5jcDJ4OmkuY3AxeCxzP2kuY3AyeTppLmNwMXksaS54LGkueSl9ZnVuY3Rpb24gQmUodCxlLGkscyxuKXtpZihuLnN0cmlrZXRocm91Z2h8fG4udW5kZXJsaW5lKXtjb25zdCBvPXQubWVhc3VyZVRleHQocyksYT1lLW8uYWN0dWFsQm91bmRpbmdCb3hMZWZ0LHI9ZStvLmFjdHVhbEJvdW5kaW5nQm94UmlnaHQsbD1pLW8uYWN0dWFsQm91bmRpbmdCb3hBc2NlbnQsaD1pK28uYWN0dWFsQm91bmRpbmdCb3hEZXNjZW50LGM9bi5zdHJpa2V0aHJvdWdoPyhsK2gpLzI6aDt0LnN0cm9rZVN0eWxlPXQuZmlsbFN0eWxlLHQuYmVnaW5QYXRoKCksdC5saW5lV2lkdGg9bi5kZWNvcmF0aW9uV2lkdGh8fDIsdC5tb3ZlVG8oYSxjKSx0LmxpbmVUbyhyLGMpLHQuc3Ryb2tlKCl9fWZ1bmN0aW9uIFdlKHQsZSl7Y29uc3QgaT10LmZpbGxTdHlsZTt0LmZpbGxTdHlsZT1lLmNvbG9yLHQuZmlsbFJlY3QoZS5sZWZ0LGUudG9wLGUud2lkdGgsZS5oZWlnaHQpLHQuZmlsbFN0eWxlPWl9ZnVuY3Rpb24gTmUodCxlLGksbyxhLHI9e30pe2NvbnN0IGw9bihlKT9lOltlXSxoPXIuc3Ryb2tlV2lkdGg+MCYmIiIhPT1yLnN0cm9rZUNvbG9yO2xldCBjLGQ7Zm9yKHQuc2F2ZSgpLHQuZm9udD1hLnN0cmluZyxmdW5jdGlvbih0LGUpe2UudHJhbnNsYXRpb24mJnQudHJhbnNsYXRlKGUudHJhbnNsYXRpb25bMF0sZS50cmFuc2xhdGlvblsxXSkscyhlLnJvdGF0aW9uKXx8dC5yb3RhdGUoZS5yb3RhdGlvbiksZS5jb2xvciYmKHQuZmlsbFN0eWxlPWUuY29sb3IpLGUudGV4dEFsaWduJiYodC50ZXh0QWxpZ249ZS50ZXh0QWxpZ24pLGUudGV4dEJhc2VsaW5lJiYodC50ZXh0QmFzZWxpbmU9ZS50ZXh0QmFzZWxpbmUpfSh0LHIpLGM9MDtjPGwubGVuZ3RoOysrYylkPWxbY10sci5iYWNrZHJvcCYmV2UodCxyLmJhY2tkcm9wKSxoJiYoci5zdHJva2VDb2xvciYmKHQuc3Ryb2tlU3R5bGU9ci5zdHJva2VDb2xvcikscyhyLnN0cm9rZVdpZHRoKXx8KHQubGluZVdpZHRoPXIuc3Ryb2tlV2lkdGgpLHQuc3Ryb2tlVGV4dChkLGksbyxyLm1heFdpZHRoKSksdC5maWxsVGV4dChkLGksbyxyLm1heFdpZHRoKSxCZSh0LGksbyxkLHIpLG8rPU51bWJlcihhLmxpbmVIZWlnaHQpO3QucmVzdG9yZSgpfWZ1bmN0aW9uIEhlKHQsZSl7Y29uc3R7eDppLHk6cyx3Om4saDpvLHJhZGl1czphfT1lO3QuYXJjKGkrYS50b3BMZWZ0LHMrYS50b3BMZWZ0LGEudG9wTGVmdCwxLjUqQyxDLCEwKSx0LmxpbmVUbyhpLHMrby1hLmJvdHRvbUxlZnQpLHQuYXJjKGkrYS5ib3R0b21MZWZ0LHMrby1hLmJvdHRvbUxlZnQsYS5ib3R0b21MZWZ0LEMsRSwhMCksdC5saW5lVG8oaStuLWEuYm90dG9tUmlnaHQscytvKSx0LmFyYyhpK24tYS5ib3R0b21SaWdodCxzK28tYS5ib3R0b21SaWdodCxhLmJvdHRvbVJpZ2h0LEUsMCwhMCksdC5saW5lVG8oaStuLHMrYS50b3BSaWdodCksdC5hcmMoaStuLWEudG9wUmlnaHQscythLnRvcFJpZ2h0LGEudG9wUmlnaHQsMCwtRSwhMCksdC5saW5lVG8oaSthLnRvcExlZnQscyl9ZnVuY3Rpb24gamUodCxlPVsiIl0saSxzLG49KCgpPT50WzBdKSl7Y29uc3Qgbz1pfHx0O3ZvaWQgMD09PXMmJihzPXRpKCJfZmFsbGJhY2siLHQpKTtjb25zdCBhPXtbU3ltYm9sLnRvU3RyaW5nVGFnXToiT2JqZWN0IixfY2FjaGVhYmxlOiEwLF9zY29wZXM6dCxfcm9vdFNjb3BlczpvLF9mYWxsYmFjazpzLF9nZXRUYXJnZXQ6bixvdmVycmlkZTppPT5qZShbaSwuLi50XSxlLG8scyl9O3JldHVybiBuZXcgUHJveHkoYSx7ZGVsZXRlUHJvcGVydHk6KGUsaSk9PihkZWxldGUgZVtpXSxkZWxldGUgZS5fa2V5cyxkZWxldGUgdFswXVtpXSwhMCksZ2V0OihpLHMpPT5xZShpLHMsKCgpPT5mdW5jdGlvbih0LGUsaSxzKXtsZXQgbjtmb3IoY29uc3QgbyBvZiBlKWlmKG49dGkoVWUobyx0KSxpKSx2b2lkIDAhPT1uKXJldHVybiBYZSh0LG4pP0plKGkscyx0LG4pOm59KHMsZSx0LGkpKSksZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOih0LGUpPT5SZWZsZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0Ll9zY29wZXNbMF0sZSksZ2V0UHJvdG90eXBlT2Y6KCk9PlJlZmxlY3QuZ2V0UHJvdG90eXBlT2YodFswXSksaGFzOih0LGUpPT5laSh0KS5pbmNsdWRlcyhlKSxvd25LZXlzOnQ9PmVpKHQpLHNldCh0LGUsaSl7Y29uc3Qgcz10Ll9zdG9yYWdlfHwodC5fc3RvcmFnZT1uKCkpO3JldHVybiB0W2VdPXNbZV09aSxkZWxldGUgdC5fa2V5cywhMH19KX1mdW5jdGlvbiAkZSh0LGUsaSxzKXtjb25zdCBhPXtfY2FjaGVhYmxlOiExLF9wcm94eTp0LF9jb250ZXh0OmUsX3N1YlByb3h5OmksX3N0YWNrOm5ldyBTZXQsX2Rlc2NyaXB0b3JzOlllKHQscyksc2V0Q29udGV4dDplPT4kZSh0LGUsaSxzKSxvdmVycmlkZTpuPT4kZSh0Lm92ZXJyaWRlKG4pLGUsaSxzKX07cmV0dXJuIG5ldyBQcm94eShhLHtkZWxldGVQcm9wZXJ0eTooZSxpKT0+KGRlbGV0ZSBlW2ldLGRlbGV0ZSB0W2ldLCEwKSxnZXQ6KHQsZSxpKT0+cWUodCxlLCgoKT0+ZnVuY3Rpb24odCxlLGkpe2NvbnN0e19wcm94eTpzLF9jb250ZXh0OmEsX3N1YlByb3h5OnIsX2Rlc2NyaXB0b3JzOmx9PXQ7bGV0IGg9c1tlXTtTKGgpJiZsLmlzU2NyaXB0YWJsZShlKSYmKGg9ZnVuY3Rpb24odCxlLGkscyl7Y29uc3R7X3Byb3h5Om4sX2NvbnRleHQ6byxfc3ViUHJveHk6YSxfc3RhY2s6cn09aTtpZihyLmhhcyh0KSl0aHJvdyBuZXcgRXJyb3IoIlJlY3Vyc2lvbiBkZXRlY3RlZDogIitBcnJheS5mcm9tKHIpLmpvaW4oIi0+IikrIi0+Iit0KTtyLmFkZCh0KTtsZXQgbD1lKG8sYXx8cyk7ci5kZWxldGUodCksWGUodCxsKSYmKGw9SmUobi5fc2NvcGVzLG4sdCxsKSk7cmV0dXJuIGx9KGUsaCx0LGkpKTtuKGgpJiZoLmxlbmd0aCYmKGg9ZnVuY3Rpb24odCxlLGkscyl7Y29uc3R7X3Byb3h5Om4sX2NvbnRleHQ6YSxfc3ViUHJveHk6cixfZGVzY3JpcHRvcnM6bH09aTtpZih2b2lkIDAhPT1hLmluZGV4JiZzKHQpKXJldHVybiBlW2EuaW5kZXglZS5sZW5ndGhdO2lmKG8oZVswXSkpe2NvbnN0IGk9ZSxzPW4uX3Njb3Blcy5maWx0ZXIoKHQ9PnQhPT1pKSk7ZT1bXTtmb3IoY29uc3QgbyBvZiBpKXtjb25zdCBpPUplKHMsbix0LG8pO2UucHVzaCgkZShpLGEsciYmclt0XSxsKSl9fXJldHVybiBlfShlLGgsdCxsLmlzSW5kZXhhYmxlKSk7WGUoZSxoKSYmKGg9JGUoaCxhLHImJnJbZV0sbCkpO3JldHVybiBofSh0LGUsaSkpKSxnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I6KGUsaSk9PmUuX2Rlc2NyaXB0b3JzLmFsbEtleXM\/UmVmbGVjdC5oYXModCxpKT97ZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITB9OnZvaWQgMDpSZWZsZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0LGkpLGdldFByb3RvdHlwZU9mOigpPT5SZWZsZWN0LmdldFByb3RvdHlwZU9mKHQpLGhhczooZSxpKT0+UmVmbGVjdC5oYXModCxpKSxvd25LZXlzOigpPT5SZWZsZWN0Lm93bktleXModCksc2V0OihlLGkscyk9Pih0W2ldPXMsZGVsZXRlIGVbaV0sITApfSl9ZnVuY3Rpb24gWWUodCxlPXtzY3JpcHRhYmxlOiEwLGluZGV4YWJsZTohMH0pe2NvbnN0e19zY3JpcHRhYmxlOmk9ZS5zY3JpcHRhYmxlLF9pbmRleGFibGU6cz1lLmluZGV4YWJsZSxfYWxsS2V5czpuPWUuYWxsS2V5c309dDtyZXR1cm57YWxsS2V5czpuLHNjcmlwdGFibGU6aSxpbmRleGFibGU6cyxpc1NjcmlwdGFibGU6UyhpKT9pOigpPT5pLGlzSW5kZXhhYmxlOlMocyk\/czooKT0+c319Y29uc3QgVWU9KHQsZSk9PnQ\/dCt3KGUpOmUsWGU9KHQsZSk9Pm8oZSkmJiJhZGFwdGVycyIhPT10JiYobnVsbD09PU9iamVjdC5nZXRQcm90b3R5cGVPZihlKXx8ZS5jb25zdHJ1Y3Rvcj09PU9iamVjdCk7ZnVuY3Rpb24gcWUodCxlLGkpe2lmKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0LGUpKXJldHVybiB0W2VdO2NvbnN0IHM9aSgpO3JldHVybiB0W2VdPXMsc31mdW5jdGlvbiBLZSh0LGUsaSl7cmV0dXJuIFModCk\/dChlLGkpOnR9Y29uc3QgR2U9KHQsZSk9PiEwPT09dD9lOiJzdHJpbmciPT10eXBlb2YgdD9NKGUsdCk6dm9pZCAwO2Z1bmN0aW9uIFplKHQsZSxpLHMsbil7Zm9yKGNvbnN0IG8gb2YgZSl7Y29uc3QgZT1HZShpLG8pO2lmKGUpe3QuYWRkKGUpO2NvbnN0IG89S2UoZS5fZmFsbGJhY2ssaSxuKTtpZih2b2lkIDAhPT1vJiZvIT09aSYmbyE9PXMpcmV0dXJuIG99ZWxzZSBpZighMT09PWUmJnZvaWQgMCE9PXMmJmkhPT1zKXJldHVybiBudWxsfXJldHVybiExfWZ1bmN0aW9uIEplKHQsZSxpLHMpe2NvbnN0IGE9ZS5fcm9vdFNjb3BlcyxyPUtlKGUuX2ZhbGxiYWNrLGkscyksbD1bLi4udCwuLi5hXSxoPW5ldyBTZXQ7aC5hZGQocyk7bGV0IGM9UWUoaCxsLGkscnx8aSxzKTtyZXR1cm4gbnVsbCE9PWMmJigodm9pZCAwPT09cnx8cj09PWl8fChjPVFlKGgsbCxyLGMscyksbnVsbCE9PWMpKSYmamUoQXJyYXkuZnJvbShoKSxbIiJdLGEsciwoKCk9PmZ1bmN0aW9uKHQsZSxpKXtjb25zdCBzPXQuX2dldFRhcmdldCgpO2UgaW4gc3x8KHNbZV09e30pO2NvbnN0IGE9c1tlXTtpZihuKGEpJiZvKGkpKXJldHVybiBpO3JldHVybiBhfHx7fX0oZSxpLHMpKSkpfWZ1bmN0aW9uIFFlKHQsZSxpLHMsbil7Zm9yKDtpOylpPVplKHQsZSxpLHMsbik7cmV0dXJuIGl9ZnVuY3Rpb24gdGkodCxlKXtmb3IoY29uc3QgaSBvZiBlKXtpZighaSljb250aW51ZTtjb25zdCBlPWlbdF07aWYodm9pZCAwIT09ZSlyZXR1cm4gZX19ZnVuY3Rpb24gZWkodCl7bGV0IGU9dC5fa2V5cztyZXR1cm4gZXx8KGU9dC5fa2V5cz1mdW5jdGlvbih0KXtjb25zdCBlPW5ldyBTZXQ7Zm9yKGNvbnN0IGkgb2YgdClmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhpKS5maWx0ZXIoKHQ9PiF0LnN0YXJ0c1dpdGgoIl8iKSkpKWUuYWRkKHQpO3JldHVybiBBcnJheS5mcm9tKGUpfSh0Ll9zY29wZXMpKSxlfWZ1bmN0aW9uIGlpKHQsZSxpLHMpe2NvbnN0e2lTY2FsZTpufT10LHtrZXk6bz0iciJ9PXRoaXMuX3BhcnNpbmcsYT1uZXcgQXJyYXkocyk7bGV0IHIsbCxoLGM7Zm9yKHI9MCxsPXM7cjxsOysrciloPXIraSxjPWVbaF0sYVtyXT17cjpuLnBhcnNlKE0oYyxvKSxoKX07cmV0dXJuIGF9Y29uc3Qgc2k9TnVtYmVyLkVQU0lMT058fDFlLTE0LG5pPSh0LGUpPT5lPHQubGVuZ3RoJiYhdFtlXS5za2lwJiZ0W2VdLG9pPXQ9PiJ4Ij09PXQ\/InkiOiJ4IjtmdW5jdGlvbiBhaSh0LGUsaSxzKXtjb25zdCBuPXQuc2tpcD9lOnQsbz1lLGE9aS5za2lwP2U6aSxyPXEobyxuKSxsPXEoYSxvKTtsZXQgaD1yLyhyK2wpLGM9bC8ocitsKTtoPWlzTmFOKGgpPzA6aCxjPWlzTmFOKGMpPzA6Yztjb25zdCBkPXMqaCx1PXMqYztyZXR1cm57cHJldmlvdXM6e3g6by54LWQqKGEueC1uLngpLHk6by55LWQqKGEueS1uLnkpfSxuZXh0Ont4Om8ueCt1KihhLngtbi54KSx5Om8ueSt1KihhLnktbi55KX19fWZ1bmN0aW9uIHJpKHQsZT0ieCIpe2NvbnN0IGk9b2koZSkscz10Lmxlbmd0aCxuPUFycmF5KHMpLmZpbGwoMCksbz1BcnJheShzKTtsZXQgYSxyLGwsaD1uaSh0LDApO2ZvcihhPTA7YTxzOysrYSlpZihyPWwsbD1oLGg9bmkodCxhKzEpLGwpe2lmKGgpe2NvbnN0IHQ9aFtlXS1sW2VdO25bYV09MCE9PXQ\/KGhbaV0tbFtpXSkvdDowfW9bYV09cj9oP0YoblthLTFdKSE9PUYoblthXSk\/MDooblthLTFdK25bYV0pLzI6blthLTFdOm5bYV19IWZ1bmN0aW9uKHQsZSxpKXtjb25zdCBzPXQubGVuZ3RoO2xldCBuLG8sYSxyLGwsaD1uaSh0LDApO2ZvcihsZXQgYz0wO2M8cy0xOysrYylsPWgsaD1uaSh0LGMrMSksbCYmaCYmKFYoZVtjXSwwLHNpKT9pW2NdPWlbYysxXT0wOihuPWlbY10vZVtjXSxvPWlbYysxXS9lW2NdLHI9TWF0aC5wb3cobiwyKStNYXRoLnBvdyhvLDIpLHI8PTl8fChhPTMvTWF0aC5zcXJ0KHIpLGlbY109biphKmVbY10saVtjKzFdPW8qYSplW2NdKSkpfSh0LG4sbyksZnVuY3Rpb24odCxlLGk9IngiKXtjb25zdCBzPW9pKGkpLG49dC5sZW5ndGg7bGV0IG8sYSxyLGw9bmkodCwwKTtmb3IobGV0IGg9MDtoPG47KytoKXtpZihhPXIscj1sLGw9bmkodCxoKzEpLCFyKWNvbnRpbnVlO2NvbnN0IG49cltpXSxjPXJbc107YSYmKG89KG4tYVtpXSkvMyxyW2BjcDEke2l9YF09bi1vLHJbYGNwMSR7c31gXT1jLW8qZVtoXSksbCYmKG89KGxbaV0tbikvMyxyW2BjcDIke2l9YF09bitvLHJbYGNwMiR7c31gXT1jK28qZVtoXSl9fSh0LG8sZSl9ZnVuY3Rpb24gbGkodCxlLGkpe3JldHVybiBNYXRoLm1heChNYXRoLm1pbih0LGkpLGUpfWZ1bmN0aW9uIGhpKHQsZSxpLHMsbil7bGV0IG8sYSxyLGw7aWYoZS5zcGFuR2FwcyYmKHQ9dC5maWx0ZXIoKHQ9PiF0LnNraXApKSksIm1vbm90b25lIj09PWUuY3ViaWNJbnRlcnBvbGF0aW9uTW9kZSlyaSh0LG4pO2Vsc2V7bGV0IGk9cz90W3QubGVuZ3RoLTFdOnRbMF07Zm9yKG89MCxhPXQubGVuZ3RoO288YTsrK28pcj10W29dLGw9YWkoaSxyLHRbTWF0aC5taW4obysxLGEtKHM\/MDoxKSklYV0sZS50ZW5zaW9uKSxyLmNwMXg9bC5wcmV2aW91cy54LHIuY3AxeT1sLnByZXZpb3VzLnksci5jcDJ4PWwubmV4dC54LHIuY3AyeT1sLm5leHQueSxpPXJ9ZS5jYXBCZXppZXJQb2ludHMmJmZ1bmN0aW9uKHQsZSl7bGV0IGkscyxuLG8sYSxyPVJlKHRbMF0sZSk7Zm9yKGk9MCxzPXQubGVuZ3RoO2k8czsrK2kpYT1vLG89cixyPWk8cy0xJiZSZSh0W2krMV0sZSksbyYmKG49dFtpXSxhJiYobi5jcDF4PWxpKG4uY3AxeCxlLmxlZnQsZS5yaWdodCksbi5jcDF5PWxpKG4uY3AxeSxlLnRvcCxlLmJvdHRvbSkpLHImJihuLmNwMng9bGkobi5jcDJ4LGUubGVmdCxlLnJpZ2h0KSxuLmNwMnk9bGkobi5jcDJ5LGUudG9wLGUuYm90dG9tKSkpfSh0LGkpfWNvbnN0IGNpPXQ9PjA9PT10fHwxPT09dCxkaT0odCxlLGkpPT4tTWF0aC5wb3coMiwxMCoodC09MSkpKk1hdGguc2luKCh0LWUpKk8vaSksdWk9KHQsZSxpKT0+TWF0aC5wb3coMiwtMTAqdCkqTWF0aC5zaW4oKHQtZSkqTy9pKSsxLGZpPXtsaW5lYXI6dD0+dCxlYXNlSW5RdWFkOnQ9PnQqdCxlYXNlT3V0UXVhZDp0PT4tdCoodC0yKSxlYXNlSW5PdXRRdWFkOnQ9Pih0Lz0uNSk8MT8uNSp0KnQ6LS41KigtLXQqKHQtMiktMSksZWFzZUluQ3ViaWM6dD0+dCp0KnQsZWFzZU91dEN1YmljOnQ9Pih0LT0xKSp0KnQrMSxlYXNlSW5PdXRDdWJpYzp0PT4odC89LjUpPDE\/LjUqdCp0KnQ6LjUqKCh0LT0yKSp0KnQrMiksZWFzZUluUXVhcnQ6dD0+dCp0KnQqdCxlYXNlT3V0UXVhcnQ6dD0+LSgodC09MSkqdCp0KnQtMSksZWFzZUluT3V0UXVhcnQ6dD0+KHQvPS41KTwxPy41KnQqdCp0KnQ6LS41KigodC09MikqdCp0KnQtMiksZWFzZUluUXVpbnQ6dD0+dCp0KnQqdCp0LGVhc2VPdXRRdWludDp0PT4odC09MSkqdCp0KnQqdCsxLGVhc2VJbk91dFF1aW50OnQ9Pih0Lz0uNSk8MT8uNSp0KnQqdCp0KnQ6LjUqKCh0LT0yKSp0KnQqdCp0KzIpLGVhc2VJblNpbmU6dD0+MS1NYXRoLmNvcyh0KkUpLGVhc2VPdXRTaW5lOnQ9Pk1hdGguc2luKHQqRSksZWFzZUluT3V0U2luZTp0PT4tLjUqKE1hdGguY29zKEMqdCktMSksZWFzZUluRXhwbzp0PT4wPT09dD8wOk1hdGgucG93KDIsMTAqKHQtMSkpLGVhc2VPdXRFeHBvOnQ9PjE9PT10PzE6MS1NYXRoLnBvdygyLC0xMCp0KSxlYXNlSW5PdXRFeHBvOnQ9PmNpKHQpP3Q6dDwuNT8uNSpNYXRoLnBvdygyLDEwKigyKnQtMSkpOi41KigyLU1hdGgucG93KDIsLTEwKigyKnQtMSkpKSxlYXNlSW5DaXJjOnQ9PnQ+PTE\/dDotKE1hdGguc3FydCgxLXQqdCktMSksZWFzZU91dENpcmM6dD0+TWF0aC5zcXJ0KDEtKHQtPTEpKnQpLGVhc2VJbk91dENpcmM6dD0+KHQvPS41KTwxPy0uNSooTWF0aC5zcXJ0KDEtdCp0KS0xKTouNSooTWF0aC5zcXJ0KDEtKHQtPTIpKnQpKzEpLGVhc2VJbkVsYXN0aWM6dD0+Y2kodCk\/dDpkaSh0LC4wNzUsLjMpLGVhc2VPdXRFbGFzdGljOnQ9PmNpKHQpP3Q6dWkodCwuMDc1LC4zKSxlYXNlSW5PdXRFbGFzdGljKHQpe2NvbnN0IGU9LjExMjU7cmV0dXJuIGNpKHQpP3Q6dDwuNT8uNSpkaSgyKnQsZSwuNDUpOi41Ky41KnVpKDIqdC0xLGUsLjQ1KX0sZWFzZUluQmFjayh0KXtjb25zdCBlPTEuNzAxNTg7cmV0dXJuIHQqdCooKGUrMSkqdC1lKX0sZWFzZU91dEJhY2sodCl7Y29uc3QgZT0xLjcwMTU4O3JldHVybih0LT0xKSp0KigoZSsxKSp0K2UpKzF9LGVhc2VJbk91dEJhY2sodCl7bGV0IGU9MS43MDE1ODtyZXR1cm4odC89LjUpPDE\/dCp0KigoMSsoZSo9MS41MjUpKSp0LWUpKi41Oi41KigodC09MikqdCooKDErKGUqPTEuNTI1KSkqdCtlKSsyKX0sZWFzZUluQm91bmNlOnQ9PjEtZmkuZWFzZU91dEJvdW5jZSgxLXQpLGVhc2VPdXRCb3VuY2UodCl7Y29uc3QgZT03LjU2MjUsaT0yLjc1O3JldHVybiB0PDEvaT9lKnQqdDp0PDIvaT9lKih0LT0xLjUvaSkqdCsuNzU6dDwyLjUvaT9lKih0LT0yLjI1L2kpKnQrLjkzNzU6ZSoodC09Mi42MjUvaSkqdCsuOTg0Mzc1fSxlYXNlSW5PdXRCb3VuY2U6dD0+dDwuNT8uNSpmaS5lYXNlSW5Cb3VuY2UoMip0KTouNSpmaS5lYXNlT3V0Qm91bmNlKDIqdC0xKSsuNX07ZnVuY3Rpb24gZ2kodCxlLGkscyl7cmV0dXJue3g6dC54K2kqKGUueC10LngpLHk6dC55K2kqKGUueS10LnkpfX1mdW5jdGlvbiBwaSh0LGUsaSxzKXtyZXR1cm57eDp0LngraSooZS54LXQueCkseToibWlkZGxlIj09PXM\/aTwuNT90Lnk6ZS55OiJhZnRlciI9PT1zP2k8MT90Lnk6ZS55Omk+MD9lLnk6dC55fX1mdW5jdGlvbiBtaSh0LGUsaSxzKXtjb25zdCBuPXt4OnQuY3AyeCx5OnQuY3AyeX0sbz17eDplLmNwMXgseTplLmNwMXl9LGE9Z2kodCxuLGkpLHI9Z2kobixvLGkpLGw9Z2kobyxlLGkpLGg9Z2koYSxyLGkpLGM9Z2kocixsLGkpO3JldHVybiBnaShoLGMsaSl9Y29uc3QgYmk9L14obm9ybWFsfChcZCsoPzpcLlxkKyk\/KShweHxlbXwlKT8pJC8seGk9L14obm9ybWFsfGl0YWxpY3xpbml0aWFsfGluaGVyaXR8dW5zZXR8KG9ibGlxdWUoIC0\/WzAtOV0\/WzAtOV1kZWcpPykpJC87ZnVuY3Rpb24gX2kodCxlKXtjb25zdCBpPSgiIit0KS5tYXRjaChiaSk7aWYoIWl8fCJub3JtYWwiPT09aVsxXSlyZXR1cm4gMS4yKmU7c3dpdGNoKHQ9K2lbMl0saVszXSl7Y2FzZSJweCI6cmV0dXJuIHQ7Y2FzZSIlIjp0Lz0xMDB9cmV0dXJuIGUqdH1jb25zdCB5aT10PT4rdHx8MDtmdW5jdGlvbiB2aSh0LGUpe2NvbnN0IGk9e30scz1vKGUpLG49cz9PYmplY3Qua2V5cyhlKTplLGE9byh0KT9zP2k9PmwodFtpXSx0W2VbaV1dKTplPT50W2VdOigpPT50O2Zvcihjb25zdCB0IG9mIG4paVt0XT15aShhKHQpKTtyZXR1cm4gaX1mdW5jdGlvbiBNaSh0KXtyZXR1cm4gdmkodCx7dG9wOiJ5IixyaWdodDoieCIsYm90dG9tOiJ5IixsZWZ0OiJ4In0pfWZ1bmN0aW9uIHdpKHQpe3JldHVybiB2aSh0LFsidG9wTGVmdCIsInRvcFJpZ2h0IiwiYm90dG9tTGVmdCIsImJvdHRvbVJpZ2h0Il0pfWZ1bmN0aW9uIGtpKHQpe2NvbnN0IGU9TWkodCk7cmV0dXJuIGUud2lkdGg9ZS5sZWZ0K2UucmlnaHQsZS5oZWlnaHQ9ZS50b3ArZS5ib3R0b20sZX1mdW5jdGlvbiBTaSh0LGUpe3Q9dHx8e30sZT1lfHx1ZS5mb250O2xldCBpPWwodC5zaXplLGUuc2l6ZSk7InN0cmluZyI9PXR5cGVvZiBpJiYoaT1wYXJzZUludChpLDEwKSk7bGV0IHM9bCh0LnN0eWxlLGUuc3R5bGUpO3MmJiEoIiIrcykubWF0Y2goeGkpJiYoY29uc29sZS53YXJuKCdJbnZhbGlkIGZvbnQgc3R5bGUgc3BlY2lmaWVkOiAiJytzKyciJykscz12b2lkIDApO2NvbnN0IG49e2ZhbWlseTpsKHQuZmFtaWx5LGUuZmFtaWx5KSxsaW5lSGVpZ2h0Ol9pKGwodC5saW5lSGVpZ2h0LGUubGluZUhlaWdodCksaSksc2l6ZTppLHN0eWxlOnMsd2VpZ2h0OmwodC53ZWlnaHQsZS53ZWlnaHQpLHN0cmluZzoiIn07cmV0dXJuIG4uc3RyaW5nPURlKG4pLG59ZnVuY3Rpb24gUGkodCxlLGkscyl7bGV0IG8sYSxyLGw9ITA7Zm9yKG89MCxhPXQubGVuZ3RoO288YTsrK28paWYocj10W29dLHZvaWQgMCE9PXImJih2b2lkIDAhPT1lJiYiZnVuY3Rpb24iPT10eXBlb2YgciYmKHI9cihlKSxsPSExKSx2b2lkIDAhPT1pJiZuKHIpJiYocj1yW2klci5sZW5ndGhdLGw9ITEpLHZvaWQgMCE9PXIpKXJldHVybiBzJiYhbCYmKHMuY2FjaGVhYmxlPSExKSxyfWZ1bmN0aW9uIERpKHQsZSxpKXtjb25zdHttaW46cyxtYXg6bn09dCxvPWMoZSwobi1zKS8yKSxhPSh0LGUpPT5pJiYwPT09dD8wOnQrZTtyZXR1cm57bWluOmEocywtTWF0aC5hYnMobykpLG1heDphKG4sbyl9fWZ1bmN0aW9uIENpKHQsZSl7cmV0dXJuIE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZSh0KSxlKX1mdW5jdGlvbiBPaSh0LGUsaSl7cmV0dXJuIHQ\/ZnVuY3Rpb24odCxlKXtyZXR1cm57eDppPT50K3QrZS1pLHNldFdpZHRoKHQpe2U9dH0sdGV4dEFsaWduOnQ9PiJjZW50ZXIiPT09dD90OiJyaWdodCI9PT10PyJsZWZ0IjoicmlnaHQiLHhQbHVzOih0LGUpPT50LWUsbGVmdEZvckx0cjoodCxlKT0+dC1lfX0oZSxpKTp7eDp0PT50LHNldFdpZHRoKHQpe30sdGV4dEFsaWduOnQ9PnQseFBsdXM6KHQsZSk9PnQrZSxsZWZ0Rm9yTHRyOih0LGUpPT50fX1mdW5jdGlvbiBBaSh0LGUpe2xldCBpLHM7Imx0ciIhPT1lJiYicnRsIiE9PWV8fChpPXQuY2FudmFzLnN0eWxlLHM9W2kuZ2V0UHJvcGVydHlWYWx1ZSgiZGlyZWN0aW9uIiksaS5nZXRQcm9wZXJ0eVByaW9yaXR5KCJkaXJlY3Rpb24iKV0saS5zZXRQcm9wZXJ0eSgiZGlyZWN0aW9uIixlLCJpbXBvcnRhbnQiKSx0LnByZXZUZXh0RGlyZWN0aW9uPXMpfWZ1bmN0aW9uIFRpKHQsZSl7dm9pZCAwIT09ZSYmKGRlbGV0ZSB0LnByZXZUZXh0RGlyZWN0aW9uLHQuY2FudmFzLnN0eWxlLnNldFByb3BlcnR5KCJkaXJlY3Rpb24iLGVbMF0sZVsxXSkpfWZ1bmN0aW9uIExpKHQpe3JldHVybiJhbmdsZSI9PT10P3tiZXR3ZWVuOlosY29tcGFyZTpLLG5vcm1hbGl6ZTpHfTp7YmV0d2Vlbjp0dCxjb21wYXJlOih0LGUpPT50LWUsbm9ybWFsaXplOnQ9PnR9fWZ1bmN0aW9uIEVpKHtzdGFydDp0LGVuZDplLGNvdW50OmksbG9vcDpzLHN0eWxlOm59KXtyZXR1cm57c3RhcnQ6dCVpLGVuZDplJWksbG9vcDpzJiYoZS10KzEpJWk9PTAsc3R5bGU6bn19ZnVuY3Rpb24gUmkodCxlLGkpe2lmKCFpKXJldHVyblt0XTtjb25zdHtwcm9wZXJ0eTpzLHN0YXJ0Om4sZW5kOm99PWksYT1lLmxlbmd0aCx7Y29tcGFyZTpyLGJldHdlZW46bCxub3JtYWxpemU6aH09TGkocykse3N0YXJ0OmMsZW5kOmQsbG9vcDp1LHN0eWxlOmZ9PWZ1bmN0aW9uKHQsZSxpKXtjb25zdHtwcm9wZXJ0eTpzLHN0YXJ0Om4sZW5kOm99PWkse2JldHdlZW46YSxub3JtYWxpemU6cn09TGkocyksbD1lLmxlbmd0aDtsZXQgaCxjLHtzdGFydDpkLGVuZDp1LGxvb3A6Zn09dDtpZihmKXtmb3IoZCs9bCx1Kz1sLGg9MCxjPWw7aDxjJiZhKHIoZVtkJWxdW3NdKSxuLG8pOysraClkLS0sdS0tO2QlPWwsdSU9bH1yZXR1cm4gdTxkJiYodSs9bCkse3N0YXJ0OmQsZW5kOnUsbG9vcDpmLHN0eWxlOnQuc3R5bGV9fSh0LGUsaSksZz1bXTtsZXQgcCxtLGIseD0hMSxfPW51bGw7Y29uc3QgeT0oKT0+eHx8bChuLGIscCkmJjAhPT1yKG4sYiksdj0oKT0+IXh8fDA9PT1yKG8scCl8fGwobyxiLHApO2ZvcihsZXQgdD1jLGk9Yzt0PD1kOysrdCltPWVbdCVhXSxtLnNraXB8fChwPWgobVtzXSkscCE9PWImJih4PWwocCxuLG8pLG51bGw9PT1fJiZ5KCkmJihfPTA9PT1yKHAsbik\/dDppKSxudWxsIT09XyYmdigpJiYoZy5wdXNoKEVpKHtzdGFydDpfLGVuZDp0LGxvb3A6dSxjb3VudDphLHN0eWxlOmZ9KSksXz1udWxsKSxpPXQsYj1wKSk7cmV0dXJuIG51bGwhPT1fJiZnLnB1c2goRWkoe3N0YXJ0Ol8sZW5kOmQsbG9vcDp1LGNvdW50OmEsc3R5bGU6Zn0pKSxnfWZ1bmN0aW9uIElpKHQsZSl7Y29uc3QgaT1bXSxzPXQuc2VnbWVudHM7Zm9yKGxldCBuPTA7bjxzLmxlbmd0aDtuKyspe2NvbnN0IG89Umkoc1tuXSx0LnBvaW50cyxlKTtvLmxlbmd0aCYmaS5wdXNoKC4uLm8pfXJldHVybiBpfWZ1bmN0aW9uIHppKHQsZSl7Y29uc3QgaT10LnBvaW50cyxzPXQub3B0aW9ucy5zcGFuR2FwcyxuPWkubGVuZ3RoO2lmKCFuKXJldHVybltdO2NvbnN0IG89ISF0Ll9sb29wLHtzdGFydDphLGVuZDpyfT1mdW5jdGlvbih0LGUsaSxzKXtsZXQgbj0wLG89ZS0xO2lmKGkmJiFzKWZvcig7bjxlJiYhdFtuXS5za2lwOyluKys7Zm9yKDtuPGUmJnRbbl0uc2tpcDspbisrO2ZvcihuJT1lLGkmJihvKz1uKTtvPm4mJnRbbyVlXS5za2lwOylvLS07cmV0dXJuIG8lPWUse3N0YXJ0Om4sZW5kOm99fShpLG4sbyxzKTtpZighMD09PXMpcmV0dXJuIEZpKHQsW3tzdGFydDphLGVuZDpyLGxvb3A6b31dLGksZSk7cmV0dXJuIEZpKHQsZnVuY3Rpb24odCxlLGkscyl7Y29uc3Qgbj10Lmxlbmd0aCxvPVtdO2xldCBhLHI9ZSxsPXRbZV07Zm9yKGE9ZSsxO2E8PWk7KythKXtjb25zdCBpPXRbYSVuXTtpLnNraXB8fGkuc3RvcD9sLnNraXB8fChzPSExLG8ucHVzaCh7c3RhcnQ6ZSVuLGVuZDooYS0xKSVuLGxvb3A6c30pLGU9cj1pLnN0b3A\/YTpudWxsKToocj1hLGwuc2tpcCYmKGU9YSkpLGw9aX1yZXR1cm4gbnVsbCE9PXImJm8ucHVzaCh7c3RhcnQ6ZSVuLGVuZDpyJW4sbG9vcDpzfSksb30oaSxhLHI8YT9yK246ciwhIXQuX2Z1bGxMb29wJiYwPT09YSYmcj09PW4tMSksaSxlKX1mdW5jdGlvbiBGaSh0LGUsaSxzKXtyZXR1cm4gcyYmcy5zZXRDb250ZXh0JiZpP2Z1bmN0aW9uKHQsZSxpLHMpe2NvbnN0IG49dC5fY2hhcnQuZ2V0Q29udGV4dCgpLG89VmkodC5vcHRpb25zKSx7X2RhdGFzZXRJbmRleDphLG9wdGlvbnM6e3NwYW5HYXBzOnJ9fT10LGw9aS5sZW5ndGgsaD1bXTtsZXQgYz1vLGQ9ZVswXS5zdGFydCx1PWQ7ZnVuY3Rpb24gZih0LGUscyxuKXtjb25zdCBvPXI\/LTE6MTtpZih0IT09ZSl7Zm9yKHQrPWw7aVt0JWxdLnNraXA7KXQtPW87Zm9yKDtpW2UlbF0uc2tpcDspZSs9bzt0JWwhPWUlbCYmKGgucHVzaCh7c3RhcnQ6dCVsLGVuZDplJWwsbG9vcDpzLHN0eWxlOm59KSxjPW4sZD1lJWwpfX1mb3IoY29uc3QgdCBvZiBlKXtkPXI\/ZDp0LnN0YXJ0O2xldCBlLG89aVtkJWxdO2Zvcih1PWQrMTt1PD10LmVuZDt1Kyspe2NvbnN0IHI9aVt1JWxdO2U9Vmkocy5zZXRDb250ZXh0KENpKG4se3R5cGU6InNlZ21lbnQiLHAwOm8scDE6cixwMERhdGFJbmRleDoodS0xKSVsLHAxRGF0YUluZGV4OnUlbCxkYXRhc2V0SW5kZXg6YX0pKSksQmkoZSxjKSYmZihkLHUtMSx0Lmxvb3AsYyksbz1yLGM9ZX1kPHUtMSYmZihkLHUtMSx0Lmxvb3AsYyl9cmV0dXJuIGh9KHQsZSxpLHMpOmV9ZnVuY3Rpb24gVmkodCl7cmV0dXJue2JhY2tncm91bmRDb2xvcjp0LmJhY2tncm91bmRDb2xvcixib3JkZXJDYXBTdHlsZTp0LmJvcmRlckNhcFN0eWxlLGJvcmRlckRhc2g6dC5ib3JkZXJEYXNoLGJvcmRlckRhc2hPZmZzZXQ6dC5ib3JkZXJEYXNoT2Zmc2V0LGJvcmRlckpvaW5TdHlsZTp0LmJvcmRlckpvaW5TdHlsZSxib3JkZXJXaWR0aDp0LmJvcmRlcldpZHRoLGJvcmRlckNvbG9yOnQuYm9yZGVyQ29sb3J9fWZ1bmN0aW9uIEJpKHQsZSl7aWYoIWUpcmV0dXJuITE7Y29uc3QgaT1bXSxzPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIEp0KGUpPyhpLmluY2x1ZGVzKGUpfHxpLnB1c2goZSksaS5pbmRleE9mKGUpKTplfTtyZXR1cm4gSlNPTi5zdHJpbmdpZnkodCxzKSE9PUpTT04uc3RyaW5naWZ5KGUscyl9dmFyIFdpPU9iamVjdC5mcmVlemUoe19fcHJvdG9fXzpudWxsLEhBTEZfUEk6RSxJTkZJTklUWTpULFBJOkMsUElUQVU6QSxRVUFSVEVSX1BJOlIsUkFEX1BFUl9ERUc6TCxUQVU6TyxUV09fVEhJUkRTX1BJOkksX2FkZEdyYWNlOkRpLF9hbGlnblBpeGVsOkFlLF9hbGlnblN0YXJ0RW5kOmZ0LF9hbmdsZUJldHdlZW46WixfYW5nbGVEaWZmOkssX2FycmF5VW5pcXVlOmx0LF9hdHRhY2hDb250ZXh0OiRlLF9iZXppZXJDdXJ2ZVRvOlZlLF9iZXppZXJJbnRlcnBvbGF0aW9uOm1pLF9ib3VuZFNlZ21lbnQ6UmksX2JvdW5kU2VnbWVudHM6SWksX2NhcGl0YWxpemU6dyxfY29tcHV0ZVNlZ21lbnRzOnppLF9jcmVhdGVSZXNvbHZlcjpqZSxfZGVjaW1hbFBsYWNlczpVLF9kZXByZWNhdGVkOmZ1bmN0aW9uKHQsZSxpLHMpe3ZvaWQgMCE9PWUmJmNvbnNvbGUud2Fybih0Kyc6ICInK2krJyIgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSAiJytzKyciIGluc3RlYWQnKX0sX2Rlc2NyaXB0b3JzOlllLF9lbGVtZW50c0VxdWFsOmYsX2ZhY3Rvcml6ZTpXLF9maWx0ZXJCZXR3ZWVuOm50LF9nZXRQYXJlbnROb2RlOmdlLF9nZXRTdGFydEFuZENvdW50T2ZWaXNpYmxlUG9pbnRzOnB0LF9pbnQxNlJhbmdlOlEsX2lzQmV0d2Vlbjp0dCxfaXNDbGlja0V2ZW50OkQsX2lzRG9tU3VwcG9ydGVkOmZlLF9pc1BvaW50SW5BcmVhOlJlLF9saW1pdFZhbHVlOkosX2xvbmdlc3RUZXh0Ok9lLF9sb29rdXA6ZXQsX2xvb2t1cEJ5S2V5Oml0LF9tZWFzdXJlVGV4dDpDZSxfbWVyZ2VyOm0sX21lcmdlcklmOl8sX25vcm1hbGl6ZUFuZ2xlOkcsX3BhcnNlT2JqZWN0RGF0YVJhZGlhbFNjYWxlOmlpLF9wb2ludEluTGluZTpnaSxfcmVhZFZhbHVlVG9Qcm9wczp2aSxfcmxvb2t1cEJ5S2V5OnN0LF9zY2FsZVJhbmdlc0NoYW5nZWQ6bXQsX3NldE1pbkFuZE1heEJ5S2V5OmosX3NwbGl0S2V5OnYsX3N0ZXBwZWRJbnRlcnBvbGF0aW9uOnBpLF9zdGVwcGVkTGluZVRvOkZlLF90ZXh0WDpndCxfdG9MZWZ0UmlnaHRDZW50ZXI6dXQsX3VwZGF0ZUJlemllckNvbnRyb2xQb2ludHM6aGksYWRkUm91bmRlZFJlY3RQYXRoOkhlLGFsbW9zdEVxdWFsczpWLGFsbW9zdFdob2xlOkgsY2FsbGJhY2s6ZCxjbGVhckNhbnZhczpUZSxjbGlwQXJlYTpJZSxjbG9uZTpnLGNvbG9yOlF0LGNyZWF0ZUNvbnRleHQ6Q2ksZGVib3VuY2U6ZHQsZGVmaW5lZDprLGRpc3RhbmNlQmV0d2VlblBvaW50czpxLGRyYXdQb2ludDpMZSxkcmF3UG9pbnRMZWdlbmQ6RWUsZWFjaDp1LGVhc2luZ0VmZmVjdHM6ZmksZmluaXRlT3JEZWZhdWx0OnIsZm9udFN0cmluZzpmdW5jdGlvbih0LGUsaSl7cmV0dXJuIGUrIiAiK3QrInB4ICIraX0sZm9ybWF0TnVtYmVyOm5lLGdldEFuZ2xlRnJvbVBvaW50OlgsZ2V0SG92ZXJDb2xvcjp0ZSxnZXRNYXhpbXVtU2l6ZTp3ZSxnZXRSZWxhdGl2ZVBvc2l0aW9uOnZlLGdldFJ0bEFkYXB0ZXI6T2ksZ2V0U3R5bGU6YmUsaXNBcnJheTpuLGlzRmluaXRlOmEsaXNGdW5jdGlvbjpTLGlzTnVsbE9yVW5kZWY6cyxpc051bWJlcjpOLGlzT2JqZWN0Om8saXNQYXR0ZXJuT3JHcmFkaWVudDpKdCxsaXN0ZW5BcnJheUV2ZW50czphdCxsb2cxMDp6LG1lcmdlOmIsbWVyZ2VJZjp4LG5pY2VOdW06Qixub29wOmUsb3ZlcnJpZGVUZXh0RGlyZWN0aW9uOkFpLHJlYWRVc2VkU2l6ZTpQZSxyZW5kZXJUZXh0Ok5lLHJlcXVlc3RBbmltRnJhbWU6aHQscmVzb2x2ZTpQaSxyZXNvbHZlT2JqZWN0S2V5Ok0scmVzdG9yZVRleHREaXJlY3Rpb246VGkscmV0aW5hU2NhbGU6a2Usc2V0c0VxdWFsOlAsc2lnbjpGLHNwbGluZUN1cnZlOmFpLHNwbGluZUN1cnZlTW9ub3RvbmU6cmksc3VwcG9ydHNFdmVudExpc3RlbmVyT3B0aW9uczpTZSx0aHJvdHRsZWQ6Y3QsdG9EZWdyZWVzOlksdG9EaW1lbnNpb246Yyx0b0ZvbnQ6U2ksdG9Gb250U3RyaW5nOkRlLHRvTGluZUhlaWdodDpfaSx0b1BhZGRpbmc6a2ksdG9QZXJjZW50YWdlOmgsdG9SYWRpYW5zOiQsdG9UUkJMOk1pLHRvVFJCTENvcm5lcnM6d2ksdWlkOmksdW5jbGlwQXJlYTp6ZSx1bmxpc3RlbkFycmF5RXZlbnRzOnJ0LHZhbHVlT3JEZWZhdWx0Omx9KTtmdW5jdGlvbiBOaSh0LGUsaSxzKXtjb25zdHtjb250cm9sbGVyOm4sZGF0YTpvLF9zb3J0ZWQ6YX09dCxyPW4uX2NhY2hlZE1ldGEuaVNjYWxlO2lmKHImJmU9PT1yLmF4aXMmJiJyIiE9PWUmJmEmJm8ubGVuZ3RoKXtjb25zdCB0PXIuX3JldmVyc2VQaXhlbHM\/c3Q6aXQ7aWYoIXMpcmV0dXJuIHQobyxlLGkpO2lmKG4uX3NoYXJlZE9wdGlvbnMpe2NvbnN0IHM9b1swXSxuPSJmdW5jdGlvbiI9PXR5cGVvZiBzLmdldFJhbmdlJiZzLmdldFJhbmdlKGUpO2lmKG4pe2NvbnN0IHM9dChvLGUsaS1uKSxhPXQobyxlLGkrbik7cmV0dXJue2xvOnMubG8saGk6YS5oaX19fX1yZXR1cm57bG86MCxoaTpvLmxlbmd0aC0xfX1mdW5jdGlvbiBIaSh0LGUsaSxzLG4pe2NvbnN0IG89dC5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCksYT1pW2VdO2ZvcihsZXQgdD0wLGk9by5sZW5ndGg7dDxpOysrdCl7Y29uc3R7aW5kZXg6aSxkYXRhOnJ9PW9bdF0se2xvOmwsaGk6aH09Tmkob1t0XSxlLGEsbik7Zm9yKGxldCB0PWw7dDw9aDsrK3Qpe2NvbnN0IGU9clt0XTtlLnNraXB8fHMoZSxpLHQpfX19ZnVuY3Rpb24gamkodCxlLGkscyxuKXtjb25zdCBvPVtdO2lmKCFuJiYhdC5pc1BvaW50SW5BcmVhKGUpKXJldHVybiBvO3JldHVybiBIaSh0LGksZSwoZnVuY3Rpb24oaSxhLHIpeyhufHxSZShpLHQuY2hhcnRBcmVhLDApKSYmaS5pblJhbmdlKGUueCxlLnkscykmJm8ucHVzaCh7ZWxlbWVudDppLGRhdGFzZXRJbmRleDphLGluZGV4OnJ9KX0pLCEwKSxvfWZ1bmN0aW9uICRpKHQsZSxpLHMsbixvKXtsZXQgYT1bXTtjb25zdCByPWZ1bmN0aW9uKHQpe2NvbnN0IGU9LTEhPT10LmluZGV4T2YoIngiKSxpPS0xIT09dC5pbmRleE9mKCJ5Iik7cmV0dXJuIGZ1bmN0aW9uKHQscyl7Y29uc3Qgbj1lP01hdGguYWJzKHQueC1zLngpOjAsbz1pP01hdGguYWJzKHQueS1zLnkpOjA7cmV0dXJuIE1hdGguc3FydChNYXRoLnBvdyhuLDIpK01hdGgucG93KG8sMikpfX0oaSk7bGV0IGw9TnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO3JldHVybiBIaSh0LGksZSwoZnVuY3Rpb24oaSxoLGMpe2NvbnN0IGQ9aS5pblJhbmdlKGUueCxlLnksbik7aWYocyYmIWQpcmV0dXJuO2NvbnN0IHU9aS5nZXRDZW50ZXJQb2ludChuKTtpZighKCEhb3x8dC5pc1BvaW50SW5BcmVhKHUpKSYmIWQpcmV0dXJuO2NvbnN0IGY9cihlLHUpO2Y8bD8oYT1be2VsZW1lbnQ6aSxkYXRhc2V0SW5kZXg6aCxpbmRleDpjfV0sbD1mKTpmPT09bCYmYS5wdXNoKHtlbGVtZW50OmksZGF0YXNldEluZGV4OmgsaW5kZXg6Y30pfSkpLGF9ZnVuY3Rpb24gWWkodCxlLGkscyxuLG8pe3JldHVybiBvfHx0LmlzUG9pbnRJbkFyZWEoZSk\/InIiIT09aXx8cz8kaSh0LGUsaSxzLG4sbyk6ZnVuY3Rpb24odCxlLGkscyl7bGV0IG49W107cmV0dXJuIEhpKHQsaSxlLChmdW5jdGlvbih0LGksbyl7Y29uc3R7c3RhcnRBbmdsZTphLGVuZEFuZ2xlOnJ9PXQuZ2V0UHJvcHMoWyJzdGFydEFuZ2xlIiwiZW5kQW5nbGUiXSxzKSx7YW5nbGU6bH09WCh0LHt4OmUueCx5OmUueX0pO1oobCxhLHIpJiZuLnB1c2goe2VsZW1lbnQ6dCxkYXRhc2V0SW5kZXg6aSxpbmRleDpvfSl9KSksbn0odCxlLGksbik6W119ZnVuY3Rpb24gVWkodCxlLGkscyxuKXtjb25zdCBvPVtdLGE9IngiPT09aT8iaW5YUmFuZ2UiOiJpbllSYW5nZSI7bGV0IHI9ITE7cmV0dXJuIEhpKHQsaSxlLCgodCxzLGwpPT57dFthXShlW2ldLG4pJiYoby5wdXNoKHtlbGVtZW50OnQsZGF0YXNldEluZGV4OnMsaW5kZXg6bH0pLHI9cnx8dC5pblJhbmdlKGUueCxlLnksbikpfSkpLHMmJiFyP1tdOm99dmFyIFhpPXtldmFsdWF0ZUludGVyYWN0aW9uSXRlbXM6SGksbW9kZXM6e2luZGV4KHQsZSxpLHMpe2NvbnN0IG49dmUoZSx0KSxvPWkuYXhpc3x8IngiLGE9aS5pbmNsdWRlSW52aXNpYmxlfHwhMSxyPWkuaW50ZXJzZWN0P2ppKHQsbixvLHMsYSk6WWkodCxuLG8sITEscyxhKSxsPVtdO3JldHVybiByLmxlbmd0aD8odC5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCkuZm9yRWFjaCgodD0+e2NvbnN0IGU9clswXS5pbmRleCxpPXQuZGF0YVtlXTtpJiYhaS5za2lwJiZsLnB1c2goe2VsZW1lbnQ6aSxkYXRhc2V0SW5kZXg6dC5pbmRleCxpbmRleDplfSl9KSksbCk6W119LGRhdGFzZXQodCxlLGkscyl7Y29uc3Qgbj12ZShlLHQpLG89aS5heGlzfHwieHkiLGE9aS5pbmNsdWRlSW52aXNpYmxlfHwhMTtsZXQgcj1pLmludGVyc2VjdD9qaSh0LG4sbyxzLGEpOllpKHQsbixvLCExLHMsYSk7aWYoci5sZW5ndGg+MCl7Y29uc3QgZT1yWzBdLmRhdGFzZXRJbmRleCxpPXQuZ2V0RGF0YXNldE1ldGEoZSkuZGF0YTtyPVtdO2ZvcihsZXQgdD0wO3Q8aS5sZW5ndGg7Kyt0KXIucHVzaCh7ZWxlbWVudDppW3RdLGRhdGFzZXRJbmRleDplLGluZGV4OnR9KX1yZXR1cm4gcn0scG9pbnQ6KHQsZSxpLHMpPT5qaSh0LHZlKGUsdCksaS5heGlzfHwieHkiLHMsaS5pbmNsdWRlSW52aXNpYmxlfHwhMSksbmVhcmVzdCh0LGUsaSxzKXtjb25zdCBuPXZlKGUsdCksbz1pLmF4aXN8fCJ4eSIsYT1pLmluY2x1ZGVJbnZpc2libGV8fCExO3JldHVybiBZaSh0LG4sbyxpLmludGVyc2VjdCxzLGEpfSx4Oih0LGUsaSxzKT0+VWkodCx2ZShlLHQpLCJ4IixpLmludGVyc2VjdCxzKSx5Oih0LGUsaSxzKT0+VWkodCx2ZShlLHQpLCJ5IixpLmludGVyc2VjdCxzKX19O2NvbnN0IHFpPVsibGVmdCIsInRvcCIsInJpZ2h0IiwiYm90dG9tIl07ZnVuY3Rpb24gS2kodCxlKXtyZXR1cm4gdC5maWx0ZXIoKHQ9PnQucG9zPT09ZSkpfWZ1bmN0aW9uIEdpKHQsZSl7cmV0dXJuIHQuZmlsdGVyKCh0PT4tMT09PXFpLmluZGV4T2YodC5wb3MpJiZ0LmJveC5heGlzPT09ZSkpfWZ1bmN0aW9uIFppKHQsZSl7cmV0dXJuIHQuc29ydCgoKHQsaSk9Pntjb25zdCBzPWU\/aTp0LG49ZT90Omk7cmV0dXJuIHMud2VpZ2h0PT09bi53ZWlnaHQ\/cy5pbmRleC1uLmluZGV4OnMud2VpZ2h0LW4ud2VpZ2h0fSkpfWZ1bmN0aW9uIEppKHQsZSl7Y29uc3QgaT1mdW5jdGlvbih0KXtjb25zdCBlPXt9O2Zvcihjb25zdCBpIG9mIHQpe2NvbnN0e3N0YWNrOnQscG9zOnMsc3RhY2tXZWlnaHQ6bn09aTtpZighdHx8IXFpLmluY2x1ZGVzKHMpKWNvbnRpbnVlO2NvbnN0IG89ZVt0XXx8KGVbdF09e2NvdW50OjAscGxhY2VkOjAsd2VpZ2h0OjAsc2l6ZTowfSk7by5jb3VudCsrLG8ud2VpZ2h0Kz1ufXJldHVybiBlfSh0KSx7dkJveE1heFdpZHRoOnMsaEJveE1heEhlaWdodDpufT1lO2xldCBvLGEscjtmb3Iobz0wLGE9dC5sZW5ndGg7bzxhOysrbyl7cj10W29dO2NvbnN0e2Z1bGxTaXplOmF9PXIuYm94LGw9aVtyLnN0YWNrXSxoPWwmJnIuc3RhY2tXZWlnaHQvbC53ZWlnaHQ7ci5ob3Jpem9udGFsPyhyLndpZHRoPWg\/aCpzOmEmJmUuYXZhaWxhYmxlV2lkdGgsci5oZWlnaHQ9bik6KHIud2lkdGg9cyxyLmhlaWdodD1oP2gqbjphJiZlLmF2YWlsYWJsZUhlaWdodCl9cmV0dXJuIGl9ZnVuY3Rpb24gUWkodCxlLGkscyl7cmV0dXJuIE1hdGgubWF4KHRbaV0sZVtpXSkrTWF0aC5tYXgodFtzXSxlW3NdKX1mdW5jdGlvbiB0cyh0LGUpe3QudG9wPU1hdGgubWF4KHQudG9wLGUudG9wKSx0LmxlZnQ9TWF0aC5tYXgodC5sZWZ0LGUubGVmdCksdC5ib3R0b209TWF0aC5tYXgodC5ib3R0b20sZS5ib3R0b20pLHQucmlnaHQ9TWF0aC5tYXgodC5yaWdodCxlLnJpZ2h0KX1mdW5jdGlvbiBlcyh0LGUsaSxzKXtjb25zdHtwb3M6bixib3g6YX09aSxyPXQubWF4UGFkZGluZztpZighbyhuKSl7aS5zaXplJiYodFtuXS09aS5zaXplKTtjb25zdCBlPXNbaS5zdGFja118fHtzaXplOjAsY291bnQ6MX07ZS5zaXplPU1hdGgubWF4KGUuc2l6ZSxpLmhvcml6b250YWw\/YS5oZWlnaHQ6YS53aWR0aCksaS5zaXplPWUuc2l6ZS9lLmNvdW50LHRbbl0rPWkuc2l6ZX1hLmdldFBhZGRpbmcmJnRzKHIsYS5nZXRQYWRkaW5nKCkpO2NvbnN0IGw9TWF0aC5tYXgoMCxlLm91dGVyV2lkdGgtUWkocix0LCJsZWZ0IiwicmlnaHQiKSksaD1NYXRoLm1heCgwLGUub3V0ZXJIZWlnaHQtUWkocix0LCJ0b3AiLCJib3R0b20iKSksYz1sIT09dC53LGQ9aCE9PXQuaDtyZXR1cm4gdC53PWwsdC5oPWgsaS5ob3Jpem9udGFsP3tzYW1lOmMsb3RoZXI6ZH06e3NhbWU6ZCxvdGhlcjpjfX1mdW5jdGlvbiBpcyh0LGUpe2NvbnN0IGk9ZS5tYXhQYWRkaW5nO2Z1bmN0aW9uIHModCl7Y29uc3Qgcz17bGVmdDowLHRvcDowLHJpZ2h0OjAsYm90dG9tOjB9O3JldHVybiB0LmZvckVhY2goKHQ9PntzW3RdPU1hdGgubWF4KGVbdF0saVt0XSl9KSksc31yZXR1cm4gcyh0P1sibGVmdCIsInJpZ2h0Il06WyJ0b3AiLCJib3R0b20iXSl9ZnVuY3Rpb24gc3ModCxlLGkscyl7Y29uc3Qgbj1bXTtsZXQgbyxhLHIsbCxoLGM7Zm9yKG89MCxhPXQubGVuZ3RoLGg9MDtvPGE7KytvKXtyPXRbb10sbD1yLmJveCxsLnVwZGF0ZShyLndpZHRofHxlLncsci5oZWlnaHR8fGUuaCxpcyhyLmhvcml6b250YWwsZSkpO2NvbnN0e3NhbWU6YSxvdGhlcjpkfT1lcyhlLGkscixzKTtofD1hJiZuLmxlbmd0aCxjPWN8fGQsbC5mdWxsU2l6ZXx8bi5wdXNoKHIpfXJldHVybiBoJiZzcyhuLGUsaSxzKXx8Y31mdW5jdGlvbiBucyh0LGUsaSxzLG4pe3QudG9wPWksdC5sZWZ0PWUsdC5yaWdodD1lK3MsdC5ib3R0b209aStuLHQud2lkdGg9cyx0LmhlaWdodD1ufWZ1bmN0aW9uIG9zKHQsZSxpLHMpe2NvbnN0IG49aS5wYWRkaW5nO2xldHt4Om8seTphfT1lO2Zvcihjb25zdCByIG9mIHQpe2NvbnN0IHQ9ci5ib3gsbD1zW3Iuc3RhY2tdfHx7Y291bnQ6MSxwbGFjZWQ6MCx3ZWlnaHQ6MX0saD1yLnN0YWNrV2VpZ2h0L2wud2VpZ2h0fHwxO2lmKHIuaG9yaXpvbnRhbCl7Y29uc3Qgcz1lLncqaCxvPWwuc2l6ZXx8dC5oZWlnaHQ7ayhsLnN0YXJ0KSYmKGE9bC5zdGFydCksdC5mdWxsU2l6ZT9ucyh0LG4ubGVmdCxhLGkub3V0ZXJXaWR0aC1uLnJpZ2h0LW4ubGVmdCxvKTpucyh0LGUubGVmdCtsLnBsYWNlZCxhLHMsbyksbC5zdGFydD1hLGwucGxhY2VkKz1zLGE9dC5ib3R0b219ZWxzZXtjb25zdCBzPWUuaCpoLGE9bC5zaXplfHx0LndpZHRoO2sobC5zdGFydCkmJihvPWwuc3RhcnQpLHQuZnVsbFNpemU\/bnModCxvLG4udG9wLGEsaS5vdXRlckhlaWdodC1uLmJvdHRvbS1uLnRvcCk6bnModCxvLGUudG9wK2wucGxhY2VkLGEscyksbC5zdGFydD1vLGwucGxhY2VkKz1zLG89dC5yaWdodH19ZS54PW8sZS55PWF9dmFyIGFzPXthZGRCb3godCxlKXt0LmJveGVzfHwodC5ib3hlcz1bXSksZS5mdWxsU2l6ZT1lLmZ1bGxTaXplfHwhMSxlLnBvc2l0aW9uPWUucG9zaXRpb258fCJ0b3AiLGUud2VpZ2h0PWUud2VpZ2h0fHwwLGUuX2xheWVycz1lLl9sYXllcnN8fGZ1bmN0aW9uKCl7cmV0dXJuW3t6OjAsZHJhdyh0KXtlLmRyYXcodCl9fV19LHQuYm94ZXMucHVzaChlKX0scmVtb3ZlQm94KHQsZSl7Y29uc3QgaT10LmJveGVzP3QuYm94ZXMuaW5kZXhPZihlKTotMTstMSE9PWkmJnQuYm94ZXMuc3BsaWNlKGksMSl9LGNvbmZpZ3VyZSh0LGUsaSl7ZS5mdWxsU2l6ZT1pLmZ1bGxTaXplLGUucG9zaXRpb249aS5wb3NpdGlvbixlLndlaWdodD1pLndlaWdodH0sdXBkYXRlKHQsZSxpLHMpe2lmKCF0KXJldHVybjtjb25zdCBuPWtpKHQub3B0aW9ucy5sYXlvdXQucGFkZGluZyksbz1NYXRoLm1heChlLW4ud2lkdGgsMCksYT1NYXRoLm1heChpLW4uaGVpZ2h0LDApLHI9ZnVuY3Rpb24odCl7Y29uc3QgZT1mdW5jdGlvbih0KXtjb25zdCBlPVtdO2xldCBpLHMsbixvLGEscjtmb3IoaT0wLHM9KHR8fFtdKS5sZW5ndGg7aTxzOysraSluPXRbaV0sKHtwb3NpdGlvbjpvLG9wdGlvbnM6e3N0YWNrOmEsc3RhY2tXZWlnaHQ6cj0xfX09biksZS5wdXNoKHtpbmRleDppLGJveDpuLHBvczpvLGhvcml6b250YWw6bi5pc0hvcml6b250YWwoKSx3ZWlnaHQ6bi53ZWlnaHQsc3RhY2s6YSYmbythLHN0YWNrV2VpZ2h0OnJ9KTtyZXR1cm4gZX0odCksaT1aaShlLmZpbHRlcigodD0+dC5ib3guZnVsbFNpemUpKSwhMCkscz1aaShLaShlLCJsZWZ0IiksITApLG49WmkoS2koZSwicmlnaHQiKSksbz1aaShLaShlLCJ0b3AiKSwhMCksYT1aaShLaShlLCJib3R0b20iKSkscj1HaShlLCJ4IiksbD1HaShlLCJ5Iik7cmV0dXJue2Z1bGxTaXplOmksbGVmdEFuZFRvcDpzLmNvbmNhdChvKSxyaWdodEFuZEJvdHRvbTpuLmNvbmNhdChsKS5jb25jYXQoYSkuY29uY2F0KHIpLGNoYXJ0QXJlYTpLaShlLCJjaGFydEFyZWEiKSx2ZXJ0aWNhbDpzLmNvbmNhdChuKS5jb25jYXQobCksaG9yaXpvbnRhbDpvLmNvbmNhdChhKS5jb25jYXQocil9fSh0LmJveGVzKSxsPXIudmVydGljYWwsaD1yLmhvcml6b250YWw7dSh0LmJveGVzLCh0PT57ImZ1bmN0aW9uIj09dHlwZW9mIHQuYmVmb3JlTGF5b3V0JiZ0LmJlZm9yZUxheW91dCgpfSkpO2NvbnN0IGM9bC5yZWR1Y2UoKCh0LGUpPT5lLmJveC5vcHRpb25zJiYhMT09PWUuYm94Lm9wdGlvbnMuZGlzcGxheT90OnQrMSksMCl8fDEsZD1PYmplY3QuZnJlZXplKHtvdXRlcldpZHRoOmUsb3V0ZXJIZWlnaHQ6aSxwYWRkaW5nOm4sYXZhaWxhYmxlV2lkdGg6byxhdmFpbGFibGVIZWlnaHQ6YSx2Qm94TWF4V2lkdGg6by8yL2MsaEJveE1heEhlaWdodDphLzJ9KSxmPU9iamVjdC5hc3NpZ24oe30sbik7dHMoZixraShzKSk7Y29uc3QgZz1PYmplY3QuYXNzaWduKHttYXhQYWRkaW5nOmYsdzpvLGg6YSx4Om4ubGVmdCx5Om4udG9wfSxuKSxwPUppKGwuY29uY2F0KGgpLGQpO3NzKHIuZnVsbFNpemUsZyxkLHApLHNzKGwsZyxkLHApLHNzKGgsZyxkLHApJiZzcyhsLGcsZCxwKSxmdW5jdGlvbih0KXtjb25zdCBlPXQubWF4UGFkZGluZztmdW5jdGlvbiBpKGkpe2NvbnN0IHM9TWF0aC5tYXgoZVtpXS10W2ldLDApO3JldHVybiB0W2ldKz1zLHN9dC55Kz1pKCJ0b3AiKSx0LngrPWkoImxlZnQiKSxpKCJyaWdodCIpLGkoImJvdHRvbSIpfShnKSxvcyhyLmxlZnRBbmRUb3AsZyxkLHApLGcueCs9Zy53LGcueSs9Zy5oLG9zKHIucmlnaHRBbmRCb3R0b20sZyxkLHApLHQuY2hhcnRBcmVhPXtsZWZ0OmcubGVmdCx0b3A6Zy50b3AscmlnaHQ6Zy5sZWZ0K2cudyxib3R0b206Zy50b3ArZy5oLGhlaWdodDpnLmgsd2lkdGg6Zy53fSx1KHIuY2hhcnRBcmVhLChlPT57Y29uc3QgaT1lLmJveDtPYmplY3QuYXNzaWduKGksdC5jaGFydEFyZWEpLGkudXBkYXRlKGcudyxnLmgse2xlZnQ6MCx0b3A6MCxyaWdodDowLGJvdHRvbTowfSl9KSl9fTtjbGFzcyByc3thY3F1aXJlQ29udGV4dCh0LGUpe31yZWxlYXNlQ29udGV4dCh0KXtyZXR1cm4hMX1hZGRFdmVudExpc3RlbmVyKHQsZSxpKXt9cmVtb3ZlRXZlbnRMaXN0ZW5lcih0LGUsaSl7fWdldERldmljZVBpeGVsUmF0aW8oKXtyZXR1cm4gMX1nZXRNYXhpbXVtU2l6ZSh0LGUsaSxzKXtyZXR1cm4gZT1NYXRoLm1heCgwLGV8fHQud2lkdGgpLGk9aXx8dC5oZWlnaHQse3dpZHRoOmUsaGVpZ2h0Ok1hdGgubWF4KDAscz9NYXRoLmZsb29yKGUvcyk6aSl9fWlzQXR0YWNoZWQodCl7cmV0dXJuITB9dXBkYXRlQ29uZmlnKHQpe319Y2xhc3MgbHMgZXh0ZW5kcyByc3thY3F1aXJlQ29udGV4dCh0KXtyZXR1cm4gdCYmdC5nZXRDb250ZXh0JiZ0LmdldENvbnRleHQoIjJkIil8fG51bGx9dXBkYXRlQ29uZmlnKHQpe3Qub3B0aW9ucy5hbmltYXRpb249ITF9fWNvbnN0IGhzPSIkY2hhcnRqcyIsY3M9e3RvdWNoc3RhcnQ6Im1vdXNlZG93biIsdG91Y2htb3ZlOiJtb3VzZW1vdmUiLHRvdWNoZW5kOiJtb3VzZXVwIixwb2ludGVyZW50ZXI6Im1vdXNlZW50ZXIiLHBvaW50ZXJkb3duOiJtb3VzZWRvd24iLHBvaW50ZXJtb3ZlOiJtb3VzZW1vdmUiLHBvaW50ZXJ1cDoibW91c2V1cCIscG9pbnRlcmxlYXZlOiJtb3VzZW91dCIscG9pbnRlcm91dDoibW91c2VvdXQifSxkcz10PT5udWxsPT09dHx8IiI9PT10O2NvbnN0IHVzPSEhU2UmJntwYXNzaXZlOiEwfTtmdW5jdGlvbiBmcyh0LGUsaSl7dC5jYW52YXMucmVtb3ZlRXZlbnRMaXN0ZW5lcihlLGksdXMpfWZ1bmN0aW9uIGdzKHQsZSl7Zm9yKGNvbnN0IGkgb2YgdClpZihpPT09ZXx8aS5jb250YWlucyhlKSlyZXR1cm4hMH1mdW5jdGlvbiBwcyh0LGUsaSl7Y29uc3Qgcz10LmNhbnZhcyxuPW5ldyBNdXRhdGlvbk9ic2VydmVyKCh0PT57bGV0IGU9ITE7Zm9yKGNvbnN0IGkgb2YgdCllPWV8fGdzKGkuYWRkZWROb2RlcyxzKSxlPWUmJiFncyhpLnJlbW92ZWROb2RlcyxzKTtlJiZpKCl9KSk7cmV0dXJuIG4ub2JzZXJ2ZShkb2N1bWVudCx7Y2hpbGRMaXN0OiEwLHN1YnRyZWU6ITB9KSxufWZ1bmN0aW9uIG1zKHQsZSxpKXtjb25zdCBzPXQuY2FudmFzLG49bmV3IE11dGF0aW9uT2JzZXJ2ZXIoKHQ9PntsZXQgZT0hMTtmb3IoY29uc3QgaSBvZiB0KWU9ZXx8Z3MoaS5yZW1vdmVkTm9kZXMscyksZT1lJiYhZ3MoaS5hZGRlZE5vZGVzLHMpO2UmJmkoKX0pKTtyZXR1cm4gbi5vYnNlcnZlKGRvY3VtZW50LHtjaGlsZExpc3Q6ITAsc3VidHJlZTohMH0pLG59Y29uc3QgYnM9bmV3IE1hcDtsZXQgeHM9MDtmdW5jdGlvbiBfcygpe2NvbnN0IHQ9d2luZG93LmRldmljZVBpeGVsUmF0aW87dCE9PXhzJiYoeHM9dCxicy5mb3JFYWNoKCgoZSxpKT0+e2kuY3VycmVudERldmljZVBpeGVsUmF0aW8hPT10JiZlKCl9KSkpfWZ1bmN0aW9uIHlzKHQsZSxpKXtjb25zdCBzPXQuY2FudmFzLG49cyYmZ2Uocyk7aWYoIW4pcmV0dXJuO2NvbnN0IG89Y3QoKCh0LGUpPT57Y29uc3Qgcz1uLmNsaWVudFdpZHRoO2kodCxlKSxzPG4uY2xpZW50V2lkdGgmJmkoKX0pLHdpbmRvdyksYT1uZXcgUmVzaXplT2JzZXJ2ZXIoKHQ9Pntjb25zdCBlPXRbMF0saT1lLmNvbnRlbnRSZWN0LndpZHRoLHM9ZS5jb250ZW50UmVjdC5oZWlnaHQ7MD09PWkmJjA9PT1zfHxvKGkscyl9KSk7cmV0dXJuIGEub2JzZXJ2ZShuKSxmdW5jdGlvbih0LGUpe2JzLnNpemV8fHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJyZXNpemUiLF9zKSxicy5zZXQodCxlKX0odCxvKSxhfWZ1bmN0aW9uIHZzKHQsZSxpKXtpJiZpLmRpc2Nvbm5lY3QoKSwicmVzaXplIj09PWUmJmZ1bmN0aW9uKHQpe2JzLmRlbGV0ZSh0KSxicy5zaXplfHx3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigicmVzaXplIixfcyl9KHQpfWZ1bmN0aW9uIE1zKHQsZSxpKXtjb25zdCBzPXQuY2FudmFzLG49Y3QoKGU9PntudWxsIT09dC5jdHgmJmkoZnVuY3Rpb24odCxlKXtjb25zdCBpPWNzW3QudHlwZV18fHQudHlwZSx7eDpzLHk6bn09dmUodCxlKTtyZXR1cm57dHlwZTppLGNoYXJ0OmUsbmF0aXZlOnQseDp2b2lkIDAhPT1zP3M6bnVsbCx5OnZvaWQgMCE9PW4\/bjpudWxsfX0oZSx0KSl9KSx0KTtyZXR1cm4gZnVuY3Rpb24odCxlLGkpe3QuYWRkRXZlbnRMaXN0ZW5lcihlLGksdXMpfShzLGUsbiksbn1jbGFzcyB3cyBleHRlbmRzIHJze2FjcXVpcmVDb250ZXh0KHQsZSl7Y29uc3QgaT10JiZ0LmdldENvbnRleHQmJnQuZ2V0Q29udGV4dCgiMmQiKTtyZXR1cm4gaSYmaS5jYW52YXM9PT10PyhmdW5jdGlvbih0LGUpe2NvbnN0IGk9dC5zdHlsZSxzPXQuZ2V0QXR0cmlidXRlKCJoZWlnaHQiKSxuPXQuZ2V0QXR0cmlidXRlKCJ3aWR0aCIpO2lmKHRbaHNdPXtpbml0aWFsOntoZWlnaHQ6cyx3aWR0aDpuLHN0eWxlOntkaXNwbGF5OmkuZGlzcGxheSxoZWlnaHQ6aS5oZWlnaHQsd2lkdGg6aS53aWR0aH19fSxpLmRpc3BsYXk9aS5kaXNwbGF5fHwiYmxvY2siLGkuYm94U2l6aW5nPWkuYm94U2l6aW5nfHwiYm9yZGVyLWJveCIsZHMobikpe2NvbnN0IGU9UGUodCwid2lkdGgiKTt2b2lkIDAhPT1lJiYodC53aWR0aD1lKX1pZihkcyhzKSlpZigiIj09PXQuc3R5bGUuaGVpZ2h0KXQuaGVpZ2h0PXQud2lkdGgvKGV8fDIpO2Vsc2V7Y29uc3QgZT1QZSh0LCJoZWlnaHQiKTt2b2lkIDAhPT1lJiYodC5oZWlnaHQ9ZSl9fSh0LGUpLGkpOm51bGx9cmVsZWFzZUNvbnRleHQodCl7Y29uc3QgZT10LmNhbnZhcztpZighZVtoc10pcmV0dXJuITE7Y29uc3QgaT1lW2hzXS5pbml0aWFsO1siaGVpZ2h0Iiwid2lkdGgiXS5mb3JFYWNoKCh0PT57Y29uc3Qgbj1pW3RdO3Mobik\/ZS5yZW1vdmVBdHRyaWJ1dGUodCk6ZS5zZXRBdHRyaWJ1dGUodCxuKX0pKTtjb25zdCBuPWkuc3R5bGV8fHt9O3JldHVybiBPYmplY3Qua2V5cyhuKS5mb3JFYWNoKCh0PT57ZS5zdHlsZVt0XT1uW3RdfSkpLGUud2lkdGg9ZS53aWR0aCxkZWxldGUgZVtoc10sITB9YWRkRXZlbnRMaXN0ZW5lcih0LGUsaSl7dGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKHQsZSk7Y29uc3Qgcz10LiRwcm94aWVzfHwodC4kcHJveGllcz17fSksbj17YXR0YWNoOnBzLGRldGFjaDptcyxyZXNpemU6eXN9W2VdfHxNcztzW2VdPW4odCxlLGkpfXJlbW92ZUV2ZW50TGlzdGVuZXIodCxlKXtjb25zdCBpPXQuJHByb3hpZXN8fCh0LiRwcm94aWVzPXt9KSxzPWlbZV07aWYoIXMpcmV0dXJuOyh7YXR0YWNoOnZzLGRldGFjaDp2cyxyZXNpemU6dnN9W2VdfHxmcykodCxlLHMpLGlbZV09dm9pZCAwfWdldERldmljZVBpeGVsUmF0aW8oKXtyZXR1cm4gd2luZG93LmRldmljZVBpeGVsUmF0aW99Z2V0TWF4aW11bVNpemUodCxlLGkscyl7cmV0dXJuIHdlKHQsZSxpLHMpfWlzQXR0YWNoZWQodCl7Y29uc3QgZT1nZSh0KTtyZXR1cm4hKCFlfHwhZS5pc0Nvbm5lY3RlZCl9fWZ1bmN0aW9uIGtzKHQpe3JldHVybiFmZSgpfHwidW5kZWZpbmVkIiE9dHlwZW9mIE9mZnNjcmVlbkNhbnZhcyYmdCBpbnN0YW5jZW9mIE9mZnNjcmVlbkNhbnZhcz9sczp3c312YXIgU3M9T2JqZWN0LmZyZWV6ZSh7X19wcm90b19fOm51bGwsQmFzZVBsYXRmb3JtOnJzLEJhc2ljUGxhdGZvcm06bHMsRG9tUGxhdGZvcm06d3MsX2RldGVjdFBsYXRmb3JtOmtzfSk7Y29uc3QgUHM9InRyYW5zcGFyZW50IixEcz17Ym9vbGVhbjoodCxlLGkpPT5pPi41P2U6dCxjb2xvcih0LGUsaSl7Y29uc3Qgcz1RdCh0fHxQcyksbj1zLnZhbGlkJiZRdChlfHxQcyk7cmV0dXJuIG4mJm4udmFsaWQ\/bi5taXgocyxpKS5oZXhTdHJpbmcoKTplfSxudW1iZXI6KHQsZSxpKT0+dCsoZS10KSppfTtjbGFzcyBDc3tjb25zdHJ1Y3Rvcih0LGUsaSxzKXtjb25zdCBuPWVbaV07cz1QaShbdC50byxzLG4sdC5mcm9tXSk7Y29uc3Qgbz1QaShbdC5mcm9tLG4sc10pO3RoaXMuX2FjdGl2ZT0hMCx0aGlzLl9mbj10LmZufHxEc1t0LnR5cGV8fHR5cGVvZiBvXSx0aGlzLl9lYXNpbmc9ZmlbdC5lYXNpbmddfHxmaS5saW5lYXIsdGhpcy5fc3RhcnQ9TWF0aC5mbG9vcihEYXRlLm5vdygpKyh0LmRlbGF5fHwwKSksdGhpcy5fZHVyYXRpb249dGhpcy5fdG90YWw9TWF0aC5mbG9vcih0LmR1cmF0aW9uKSx0aGlzLl9sb29wPSEhdC5sb29wLHRoaXMuX3RhcmdldD1lLHRoaXMuX3Byb3A9aSx0aGlzLl9mcm9tPW8sdGhpcy5fdG89cyx0aGlzLl9wcm9taXNlcz12b2lkIDB9YWN0aXZlKCl7cmV0dXJuIHRoaXMuX2FjdGl2ZX11cGRhdGUodCxlLGkpe2lmKHRoaXMuX2FjdGl2ZSl7dGhpcy5fbm90aWZ5KCExKTtjb25zdCBzPXRoaXMuX3RhcmdldFt0aGlzLl9wcm9wXSxuPWktdGhpcy5fc3RhcnQsbz10aGlzLl9kdXJhdGlvbi1uO3RoaXMuX3N0YXJ0PWksdGhpcy5fZHVyYXRpb249TWF0aC5mbG9vcihNYXRoLm1heChvLHQuZHVyYXRpb24pKSx0aGlzLl90b3RhbCs9bix0aGlzLl9sb29wPSEhdC5sb29wLHRoaXMuX3RvPVBpKFt0LnRvLGUscyx0LmZyb21dKSx0aGlzLl9mcm9tPVBpKFt0LmZyb20scyxlXSl9fWNhbmNlbCgpe3RoaXMuX2FjdGl2ZSYmKHRoaXMudGljayhEYXRlLm5vdygpKSx0aGlzLl9hY3RpdmU9ITEsdGhpcy5fbm90aWZ5KCExKSl9dGljayh0KXtjb25zdCBlPXQtdGhpcy5fc3RhcnQsaT10aGlzLl9kdXJhdGlvbixzPXRoaXMuX3Byb3Asbj10aGlzLl9mcm9tLG89dGhpcy5fbG9vcCxhPXRoaXMuX3RvO2xldCByO2lmKHRoaXMuX2FjdGl2ZT1uIT09YSYmKG98fGU8aSksIXRoaXMuX2FjdGl2ZSlyZXR1cm4gdGhpcy5fdGFyZ2V0W3NdPWEsdm9pZCB0aGlzLl9ub3RpZnkoITApO2U8MD90aGlzLl90YXJnZXRbc109bjoocj1lL2klMixyPW8mJnI+MT8yLXI6cixyPXRoaXMuX2Vhc2luZyhNYXRoLm1pbigxLE1hdGgubWF4KDAscikpKSx0aGlzLl90YXJnZXRbc109dGhpcy5fZm4obixhLHIpKX13YWl0KCl7Y29uc3QgdD10aGlzLl9wcm9taXNlc3x8KHRoaXMuX3Byb21pc2VzPVtdKTtyZXR1cm4gbmV3IFByb21pc2UoKChlLGkpPT57dC5wdXNoKHtyZXM6ZSxyZWo6aX0pfSkpfV9ub3RpZnkodCl7Y29uc3QgZT10PyJyZXMiOiJyZWoiLGk9dGhpcy5fcHJvbWlzZXN8fFtdO2ZvcihsZXQgdD0wO3Q8aS5sZW5ndGg7dCsrKWlbdF1bZV0oKX19Y2xhc3MgT3N7Y29uc3RydWN0b3IodCxlKXt0aGlzLl9jaGFydD10LHRoaXMuX3Byb3BlcnRpZXM9bmV3IE1hcCx0aGlzLmNvbmZpZ3VyZShlKX1jb25maWd1cmUodCl7aWYoIW8odCkpcmV0dXJuO2NvbnN0IGU9T2JqZWN0LmtleXModWUuYW5pbWF0aW9uKSxpPXRoaXMuX3Byb3BlcnRpZXM7T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModCkuZm9yRWFjaCgocz0+e2NvbnN0IGE9dFtzXTtpZighbyhhKSlyZXR1cm47Y29uc3Qgcj17fTtmb3IoY29uc3QgdCBvZiBlKXJbdF09YVt0XTsobihhLnByb3BlcnRpZXMpJiZhLnByb3BlcnRpZXN8fFtzXSkuZm9yRWFjaCgodD0+e3QhPT1zJiZpLmhhcyh0KXx8aS5zZXQodCxyKX0pKX0pKX1fYW5pbWF0ZU9wdGlvbnModCxlKXtjb25zdCBpPWUub3B0aW9ucyxzPWZ1bmN0aW9uKHQsZSl7aWYoIWUpcmV0dXJuO2xldCBpPXQub3B0aW9ucztpZighaSlyZXR1cm4gdm9pZCh0Lm9wdGlvbnM9ZSk7aS4kc2hhcmVkJiYodC5vcHRpb25zPWk9T2JqZWN0LmFzc2lnbih7fSxpLHskc2hhcmVkOiExLCRhbmltYXRpb25zOnt9fSkpO3JldHVybiBpfSh0LGkpO2lmKCFzKXJldHVybltdO2NvbnN0IG49dGhpcy5fY3JlYXRlQW5pbWF0aW9ucyhzLGkpO3JldHVybiBpLiRzaGFyZWQmJmZ1bmN0aW9uKHQsZSl7Y29uc3QgaT1bXSxzPU9iamVjdC5rZXlzKGUpO2ZvcihsZXQgZT0wO2U8cy5sZW5ndGg7ZSsrKXtjb25zdCBuPXRbc1tlXV07biYmbi5hY3RpdmUoKSYmaS5wdXNoKG4ud2FpdCgpKX1yZXR1cm4gUHJvbWlzZS5hbGwoaSl9KHQub3B0aW9ucy4kYW5pbWF0aW9ucyxpKS50aGVuKCgoKT0+e3Qub3B0aW9ucz1pfSksKCgpPT57fSkpLG59X2NyZWF0ZUFuaW1hdGlvbnModCxlKXtjb25zdCBpPXRoaXMuX3Byb3BlcnRpZXMscz1bXSxuPXQuJGFuaW1hdGlvbnN8fCh0LiRhbmltYXRpb25zPXt9KSxvPU9iamVjdC5rZXlzKGUpLGE9RGF0ZS5ub3coKTtsZXQgcjtmb3Iocj1vLmxlbmd0aC0xO3I+PTA7LS1yKXtjb25zdCBsPW9bcl07aWYoIiQiPT09bC5jaGFyQXQoMCkpY29udGludWU7aWYoIm9wdGlvbnMiPT09bCl7cy5wdXNoKC4uLnRoaXMuX2FuaW1hdGVPcHRpb25zKHQsZSkpO2NvbnRpbnVlfWNvbnN0IGg9ZVtsXTtsZXQgYz1uW2xdO2NvbnN0IGQ9aS5nZXQobCk7aWYoYyl7aWYoZCYmYy5hY3RpdmUoKSl7Yy51cGRhdGUoZCxoLGEpO2NvbnRpbnVlfWMuY2FuY2VsKCl9ZCYmZC5kdXJhdGlvbj8obltsXT1jPW5ldyBDcyhkLHQsbCxoKSxzLnB1c2goYykpOnRbbF09aH1yZXR1cm4gc311cGRhdGUodCxlKXtpZigwPT09dGhpcy5fcHJvcGVydGllcy5zaXplKXJldHVybiB2b2lkIE9iamVjdC5hc3NpZ24odCxlKTtjb25zdCBpPXRoaXMuX2NyZWF0ZUFuaW1hdGlvbnModCxlKTtyZXR1cm4gaS5sZW5ndGg\/KHh0LmFkZCh0aGlzLl9jaGFydCxpKSwhMCk6dm9pZCAwfX1mdW5jdGlvbiBBcyh0LGUpe2NvbnN0IGk9dCYmdC5vcHRpb25zfHx7fSxzPWkucmV2ZXJzZSxuPXZvaWQgMD09PWkubWluP2U6MCxvPXZvaWQgMD09PWkubWF4P2U6MDtyZXR1cm57c3RhcnQ6cz9vOm4sZW5kOnM\/bjpvfX1mdW5jdGlvbiBUcyh0LGUpe2NvbnN0IGk9W10scz10Ll9nZXRTb3J0ZWREYXRhc2V0TWV0YXMoZSk7bGV0IG4sbztmb3Iobj0wLG89cy5sZW5ndGg7bjxvOysrbilpLnB1c2goc1tuXS5pbmRleCk7cmV0dXJuIGl9ZnVuY3Rpb24gTHModCxlLGkscz17fSl7Y29uc3Qgbj10LmtleXMsbz0ic2luZ2xlIj09PXMubW9kZTtsZXQgcixsLGgsYztpZihudWxsIT09ZSl7Zm9yKHI9MCxsPW4ubGVuZ3RoO3I8bDsrK3Ipe2lmKGg9K25bcl0saD09PWkpe2lmKHMuYWxsKWNvbnRpbnVlO2JyZWFrfWM9dC52YWx1ZXNbaF0sYShjKSYmKG98fDA9PT1lfHxGKGUpPT09RihjKSkmJihlKz1jKX1yZXR1cm4gZX19ZnVuY3Rpb24gRXModCxlKXtjb25zdCBpPXQmJnQub3B0aW9ucy5zdGFja2VkO3JldHVybiBpfHx2b2lkIDA9PT1pJiZ2b2lkIDAhPT1lLnN0YWNrfWZ1bmN0aW9uIFJzKHQsZSxpKXtjb25zdCBzPXRbZV18fCh0W2VdPXt9KTtyZXR1cm4gc1tpXXx8KHNbaV09e30pfWZ1bmN0aW9uIElzKHQsZSxpLHMpe2Zvcihjb25zdCBuIG9mIGUuZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXMocykucmV2ZXJzZSgpKXtjb25zdCBlPXRbbi5pbmRleF07aWYoaSYmZT4wfHwhaSYmZTwwKXJldHVybiBuLmluZGV4fXJldHVybiBudWxsfWZ1bmN0aW9uIHpzKHQsZSl7Y29uc3R7Y2hhcnQ6aSxfY2FjaGVkTWV0YTpzfT10LG49aS5fc3RhY2tzfHwoaS5fc3RhY2tzPXt9KSx7aVNjYWxlOm8sdlNjYWxlOmEsaW5kZXg6cn09cyxsPW8uYXhpcyxoPWEuYXhpcyxjPWZ1bmN0aW9uKHQsZSxpKXtyZXR1cm5gJHt0LmlkfS4ke2UuaWR9LiR7aS5zdGFja3x8aS50eXBlfWB9KG8sYSxzKSxkPWUubGVuZ3RoO2xldCB1O2ZvcihsZXQgdD0wO3Q8ZDsrK3Qpe2NvbnN0IGk9ZVt0XSx7W2xdOm8sW2hdOmR9PWk7dT0oaS5fc3RhY2tzfHwoaS5fc3RhY2tzPXt9KSlbaF09UnMobixjLG8pLHVbcl09ZCx1Ll90b3A9SXModSxhLCEwLHMudHlwZSksdS5fYm90dG9tPUlzKHUsYSwhMSxzLnR5cGUpOyh1Ll92aXN1YWxWYWx1ZXN8fCh1Ll92aXN1YWxWYWx1ZXM9e30pKVtyXT1kfX1mdW5jdGlvbiBGcyh0LGUpe2NvbnN0IGk9dC5zY2FsZXM7cmV0dXJuIE9iamVjdC5rZXlzKGkpLmZpbHRlcigodD0+aVt0XS5heGlzPT09ZSkpLnNoaWZ0KCl9ZnVuY3Rpb24gVnModCxlKXtjb25zdCBpPXQuY29udHJvbGxlci5pbmRleCxzPXQudlNjYWxlJiZ0LnZTY2FsZS5heGlzO2lmKHMpe2U9ZXx8dC5fcGFyc2VkO2Zvcihjb25zdCB0IG9mIGUpe2NvbnN0IGU9dC5fc3RhY2tzO2lmKCFlfHx2b2lkIDA9PT1lW3NdfHx2b2lkIDA9PT1lW3NdW2ldKXJldHVybjtkZWxldGUgZVtzXVtpXSx2b2lkIDAhPT1lW3NdLl92aXN1YWxWYWx1ZXMmJnZvaWQgMCE9PWVbc10uX3Zpc3VhbFZhbHVlc1tpXSYmZGVsZXRlIGVbc10uX3Zpc3VhbFZhbHVlc1tpXX19fWNvbnN0IEJzPXQ9PiJyZXNldCI9PT10fHwibm9uZSI9PT10LFdzPSh0LGUpPT5lP3Q6T2JqZWN0LmFzc2lnbih7fSx0KTtjbGFzcyBOc3tzdGF0aWMgZGVmYXVsdHM9e307c3RhdGljIGRhdGFzZXRFbGVtZW50VHlwZT1udWxsO3N0YXRpYyBkYXRhRWxlbWVudFR5cGU9bnVsbDtjb25zdHJ1Y3Rvcih0LGUpe3RoaXMuY2hhcnQ9dCx0aGlzLl9jdHg9dC5jdHgsdGhpcy5pbmRleD1lLHRoaXMuX2NhY2hlZERhdGFPcHRzPXt9LHRoaXMuX2NhY2hlZE1ldGE9dGhpcy5nZXRNZXRhKCksdGhpcy5fdHlwZT10aGlzLl9jYWNoZWRNZXRhLnR5cGUsdGhpcy5vcHRpb25zPXZvaWQgMCx0aGlzLl9wYXJzaW5nPSExLHRoaXMuX2RhdGE9dm9pZCAwLHRoaXMuX29iamVjdERhdGE9dm9pZCAwLHRoaXMuX3NoYXJlZE9wdGlvbnM9dm9pZCAwLHRoaXMuX2RyYXdTdGFydD12b2lkIDAsdGhpcy5fZHJhd0NvdW50PXZvaWQgMCx0aGlzLmVuYWJsZU9wdGlvblNoYXJpbmc9ITEsdGhpcy5zdXBwb3J0c0RlY2ltYXRpb249ITEsdGhpcy4kY29udGV4dD12b2lkIDAsdGhpcy5fc3luY0xpc3Q9W10sdGhpcy5kYXRhc2V0RWxlbWVudFR5cGU9bmV3LnRhcmdldC5kYXRhc2V0RWxlbWVudFR5cGUsdGhpcy5kYXRhRWxlbWVudFR5cGU9bmV3LnRhcmdldC5kYXRhRWxlbWVudFR5cGUsdGhpcy5pbml0aWFsaXplKCl9aW5pdGlhbGl6ZSgpe2NvbnN0IHQ9dGhpcy5fY2FjaGVkTWV0YTt0aGlzLmNvbmZpZ3VyZSgpLHRoaXMubGlua1NjYWxlcygpLHQuX3N0YWNrZWQ9RXModC52U2NhbGUsdCksdGhpcy5hZGRFbGVtZW50cygpLHRoaXMub3B0aW9ucy5maWxsJiYhdGhpcy5jaGFydC5pc1BsdWdpbkVuYWJsZWQoImZpbGxlciIpJiZjb25zb2xlLndhcm4oIlRyaWVkIHRvIHVzZSB0aGUgJ2ZpbGwnIG9wdGlvbiB3aXRob3V0IHRoZSAnRmlsbGVyJyBwbHVnaW4gZW5hYmxlZC4gUGxlYXNlIGltcG9ydCBhbmQgcmVnaXN0ZXIgdGhlICdGaWxsZXInIHBsdWdpbiBhbmQgbWFrZSBzdXJlIGl0IGlzIG5vdCBkaXNhYmxlZCBpbiB0aGUgb3B0aW9ucyIpfXVwZGF0ZUluZGV4KHQpe3RoaXMuaW5kZXghPT10JiZWcyh0aGlzLl9jYWNoZWRNZXRhKSx0aGlzLmluZGV4PXR9bGlua1NjYWxlcygpe2NvbnN0IHQ9dGhpcy5jaGFydCxlPXRoaXMuX2NhY2hlZE1ldGEsaT10aGlzLmdldERhdGFzZXQoKSxzPSh0LGUsaSxzKT0+IngiPT09dD9lOiJyIj09PXQ\/czppLG49ZS54QXhpc0lEPWwoaS54QXhpc0lELEZzKHQsIngiKSksbz1lLnlBeGlzSUQ9bChpLnlBeGlzSUQsRnModCwieSIpKSxhPWUuckF4aXNJRD1sKGkuckF4aXNJRCxGcyh0LCJyIikpLHI9ZS5pbmRleEF4aXMsaD1lLmlBeGlzSUQ9cyhyLG4sbyxhKSxjPWUudkF4aXNJRD1zKHIsbyxuLGEpO2UueFNjYWxlPXRoaXMuZ2V0U2NhbGVGb3JJZChuKSxlLnlTY2FsZT10aGlzLmdldFNjYWxlRm9ySWQobyksZS5yU2NhbGU9dGhpcy5nZXRTY2FsZUZvcklkKGEpLGUuaVNjYWxlPXRoaXMuZ2V0U2NhbGVGb3JJZChoKSxlLnZTY2FsZT10aGlzLmdldFNjYWxlRm9ySWQoYyl9Z2V0RGF0YXNldCgpe3JldHVybiB0aGlzLmNoYXJ0LmRhdGEuZGF0YXNldHNbdGhpcy5pbmRleF19Z2V0TWV0YSgpe3JldHVybiB0aGlzLmNoYXJ0LmdldERhdGFzZXRNZXRhKHRoaXMuaW5kZXgpfWdldFNjYWxlRm9ySWQodCl7cmV0dXJuIHRoaXMuY2hhcnQuc2NhbGVzW3RdfV9nZXRPdGhlclNjYWxlKHQpe2NvbnN0IGU9dGhpcy5fY2FjaGVkTWV0YTtyZXR1cm4gdD09PWUuaVNjYWxlP2UudlNjYWxlOmUuaVNjYWxlfXJlc2V0KCl7dGhpcy5fdXBkYXRlKCJyZXNldCIpfV9kZXN0cm95KCl7Y29uc3QgdD10aGlzLl9jYWNoZWRNZXRhO3RoaXMuX2RhdGEmJnJ0KHRoaXMuX2RhdGEsdGhpcyksdC5fc3RhY2tlZCYmVnModCl9X2RhdGFDaGVjaygpe2NvbnN0IHQ9dGhpcy5nZXREYXRhc2V0KCksZT10LmRhdGF8fCh0LmRhdGE9W10pLGk9dGhpcy5fZGF0YTtpZihvKGUpKXRoaXMuX2RhdGE9ZnVuY3Rpb24odCl7Y29uc3QgZT1PYmplY3Qua2V5cyh0KSxpPW5ldyBBcnJheShlLmxlbmd0aCk7bGV0IHMsbixvO2ZvcihzPTAsbj1lLmxlbmd0aDtzPG47KytzKW89ZVtzXSxpW3NdPXt4Om8seTp0W29dfTtyZXR1cm4gaX0oZSk7ZWxzZSBpZihpIT09ZSl7aWYoaSl7cnQoaSx0aGlzKTtjb25zdCB0PXRoaXMuX2NhY2hlZE1ldGE7VnModCksdC5fcGFyc2VkPVtdfWUmJk9iamVjdC5pc0V4dGVuc2libGUoZSkmJmF0KGUsdGhpcyksdGhpcy5fc3luY0xpc3Q9W10sdGhpcy5fZGF0YT1lfX1hZGRFbGVtZW50cygpe2NvbnN0IHQ9dGhpcy5fY2FjaGVkTWV0YTt0aGlzLl9kYXRhQ2hlY2soKSx0aGlzLmRhdGFzZXRFbGVtZW50VHlwZSYmKHQuZGF0YXNldD1uZXcgdGhpcy5kYXRhc2V0RWxlbWVudFR5cGUpfWJ1aWxkT3JVcGRhdGVFbGVtZW50cyh0KXtjb25zdCBlPXRoaXMuX2NhY2hlZE1ldGEsaT10aGlzLmdldERhdGFzZXQoKTtsZXQgcz0hMTt0aGlzLl9kYXRhQ2hlY2soKTtjb25zdCBuPWUuX3N0YWNrZWQ7ZS5fc3RhY2tlZD1FcyhlLnZTY2FsZSxlKSxlLnN0YWNrIT09aS5zdGFjayYmKHM9ITAsVnMoZSksZS5zdGFjaz1pLnN0YWNrKSx0aGlzLl9yZXN5bmNFbGVtZW50cyh0KSwoc3x8biE9PWUuX3N0YWNrZWQpJiZ6cyh0aGlzLGUuX3BhcnNlZCl9Y29uZmlndXJlKCl7Y29uc3QgdD10aGlzLmNoYXJ0LmNvbmZpZyxlPXQuZGF0YXNldFNjb3BlS2V5cyh0aGlzLl90eXBlKSxpPXQuZ2V0T3B0aW9uU2NvcGVzKHRoaXMuZ2V0RGF0YXNldCgpLGUsITApO3RoaXMub3B0aW9ucz10LmNyZWF0ZVJlc29sdmVyKGksdGhpcy5nZXRDb250ZXh0KCkpLHRoaXMuX3BhcnNpbmc9dGhpcy5vcHRpb25zLnBhcnNpbmcsdGhpcy5fY2FjaGVkRGF0YU9wdHM9e319cGFyc2UodCxlKXtjb25zdHtfY2FjaGVkTWV0YTppLF9kYXRhOnN9PXRoaXMse2lTY2FsZTphLF9zdGFja2VkOnJ9PWksbD1hLmF4aXM7bGV0IGgsYyxkLHU9MD09PXQmJmU9PT1zLmxlbmd0aHx8aS5fc29ydGVkLGY9dD4wJiZpLl9wYXJzZWRbdC0xXTtpZighMT09PXRoaXMuX3BhcnNpbmcpaS5fcGFyc2VkPXMsaS5fc29ydGVkPSEwLGQ9cztlbHNle2Q9bihzW3RdKT90aGlzLnBhcnNlQXJyYXlEYXRhKGkscyx0LGUpOm8oc1t0XSk\/dGhpcy5wYXJzZU9iamVjdERhdGEoaSxzLHQsZSk6dGhpcy5wYXJzZVByaW1pdGl2ZURhdGEoaSxzLHQsZSk7Y29uc3QgYT0oKT0+bnVsbD09PWNbbF18fGYmJmNbbF08ZltsXTtmb3IoaD0wO2g8ZTsrK2gpaS5fcGFyc2VkW2grdF09Yz1kW2hdLHUmJihhKCkmJih1PSExKSxmPWMpO2kuX3NvcnRlZD11fXImJnpzKHRoaXMsZCl9cGFyc2VQcmltaXRpdmVEYXRhKHQsZSxpLHMpe2NvbnN0e2lTY2FsZTpuLHZTY2FsZTpvfT10LGE9bi5heGlzLHI9by5heGlzLGw9bi5nZXRMYWJlbHMoKSxoPW49PT1vLGM9bmV3IEFycmF5KHMpO2xldCBkLHUsZjtmb3IoZD0wLHU9cztkPHU7KytkKWY9ZCtpLGNbZF09e1thXTpofHxuLnBhcnNlKGxbZl0sZiksW3JdOm8ucGFyc2UoZVtmXSxmKX07cmV0dXJuIGN9cGFyc2VBcnJheURhdGEodCxlLGkscyl7Y29uc3R7eFNjYWxlOm4seVNjYWxlOm99PXQsYT1uZXcgQXJyYXkocyk7bGV0IHIsbCxoLGM7Zm9yKHI9MCxsPXM7cjxsOysrciloPXIraSxjPWVbaF0sYVtyXT17eDpuLnBhcnNlKGNbMF0saCkseTpvLnBhcnNlKGNbMV0saCl9O3JldHVybiBhfXBhcnNlT2JqZWN0RGF0YSh0LGUsaSxzKXtjb25zdHt4U2NhbGU6bix5U2NhbGU6b309dCx7eEF4aXNLZXk6YT0ieCIseUF4aXNLZXk6cj0ieSJ9PXRoaXMuX3BhcnNpbmcsbD1uZXcgQXJyYXkocyk7bGV0IGgsYyxkLHU7Zm9yKGg9MCxjPXM7aDxjOysraClkPWgraSx1PWVbZF0sbFtoXT17eDpuLnBhcnNlKE0odSxhKSxkKSx5Om8ucGFyc2UoTSh1LHIpLGQpfTtyZXR1cm4gbH1nZXRQYXJzZWQodCl7cmV0dXJuIHRoaXMuX2NhY2hlZE1ldGEuX3BhcnNlZFt0XX1nZXREYXRhRWxlbWVudCh0KXtyZXR1cm4gdGhpcy5fY2FjaGVkTWV0YS5kYXRhW3RdfWFwcGx5U3RhY2sodCxlLGkpe2NvbnN0IHM9dGhpcy5jaGFydCxuPXRoaXMuX2NhY2hlZE1ldGEsbz1lW3QuYXhpc107cmV0dXJuIExzKHtrZXlzOlRzKHMsITApLHZhbHVlczplLl9zdGFja3NbdC5heGlzXS5fdmlzdWFsVmFsdWVzfSxvLG4uaW5kZXgse21vZGU6aX0pfXVwZGF0ZVJhbmdlRnJvbVBhcnNlZCh0LGUsaSxzKXtjb25zdCBuPWlbZS5heGlzXTtsZXQgbz1udWxsPT09bj9OYU46bjtjb25zdCBhPXMmJmkuX3N0YWNrc1tlLmF4aXNdO3MmJmEmJihzLnZhbHVlcz1hLG89THMocyxuLHRoaXMuX2NhY2hlZE1ldGEuaW5kZXgpKSx0Lm1pbj1NYXRoLm1pbih0Lm1pbixvKSx0Lm1heD1NYXRoLm1heCh0Lm1heCxvKX1nZXRNaW5NYXgodCxlKXtjb25zdCBpPXRoaXMuX2NhY2hlZE1ldGEscz1pLl9wYXJzZWQsbj1pLl9zb3J0ZWQmJnQ9PT1pLmlTY2FsZSxvPXMubGVuZ3RoLHI9dGhpcy5fZ2V0T3RoZXJTY2FsZSh0KSxsPSgodCxlLGkpPT50JiYhZS5oaWRkZW4mJmUuX3N0YWNrZWQmJntrZXlzOlRzKGksITApLHZhbHVlczpudWxsfSkoZSxpLHRoaXMuY2hhcnQpLGg9e21pbjpOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksbWF4Ok51bWJlci5ORUdBVElWRV9JTkZJTklUWX0se21pbjpjLG1heDpkfT1mdW5jdGlvbih0KXtjb25zdHttaW46ZSxtYXg6aSxtaW5EZWZpbmVkOnMsbWF4RGVmaW5lZDpufT10LmdldFVzZXJCb3VuZHMoKTtyZXR1cm57bWluOnM\/ZTpOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksbWF4Om4\/aTpOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFl9fShyKTtsZXQgdSxmO2Z1bmN0aW9uIGcoKXtmPXNbdV07Y29uc3QgZT1mW3IuYXhpc107cmV0dXJuIWEoZlt0LmF4aXNdKXx8Yz5lfHxkPGV9Zm9yKHU9MDt1PG8mJihnKCl8fCh0aGlzLnVwZGF0ZVJhbmdlRnJvbVBhcnNlZChoLHQsZixsKSwhbikpOysrdSk7aWYobilmb3IodT1vLTE7dT49MDstLXUpaWYoIWcoKSl7dGhpcy51cGRhdGVSYW5nZUZyb21QYXJzZWQoaCx0LGYsbCk7YnJlYWt9cmV0dXJuIGh9Z2V0QWxsUGFyc2VkVmFsdWVzKHQpe2NvbnN0IGU9dGhpcy5fY2FjaGVkTWV0YS5fcGFyc2VkLGk9W107bGV0IHMsbixvO2ZvcihzPTAsbj1lLmxlbmd0aDtzPG47KytzKW89ZVtzXVt0LmF4aXNdLGEobykmJmkucHVzaChvKTtyZXR1cm4gaX1nZXRNYXhPdmVyZmxvdygpe3JldHVybiExfWdldExhYmVsQW5kVmFsdWUodCl7Y29uc3QgZT10aGlzLl9jYWNoZWRNZXRhLGk9ZS5pU2NhbGUscz1lLnZTY2FsZSxuPXRoaXMuZ2V0UGFyc2VkKHQpO3JldHVybntsYWJlbDppPyIiK2kuZ2V0TGFiZWxGb3JWYWx1ZShuW2kuYXhpc10pOiIiLHZhbHVlOnM\/IiIrcy5nZXRMYWJlbEZvclZhbHVlKG5bcy5heGlzXSk6IiJ9fV91cGRhdGUodCl7Y29uc3QgZT10aGlzLl9jYWNoZWRNZXRhO3RoaXMudXBkYXRlKHR8fCJkZWZhdWx0IiksZS5fY2xpcD1mdW5jdGlvbih0KXtsZXQgZSxpLHMsbjtyZXR1cm4gbyh0KT8oZT10LnRvcCxpPXQucmlnaHQscz10LmJvdHRvbSxuPXQubGVmdCk6ZT1pPXM9bj10LHt0b3A6ZSxyaWdodDppLGJvdHRvbTpzLGxlZnQ6bixkaXNhYmxlZDohMT09PXR9fShsKHRoaXMub3B0aW9ucy5jbGlwLGZ1bmN0aW9uKHQsZSxpKXtpZighMT09PWkpcmV0dXJuITE7Y29uc3Qgcz1Bcyh0LGkpLG49QXMoZSxpKTtyZXR1cm57dG9wOm4uZW5kLHJpZ2h0OnMuZW5kLGJvdHRvbTpuLnN0YXJ0LGxlZnQ6cy5zdGFydH19KGUueFNjYWxlLGUueVNjYWxlLHRoaXMuZ2V0TWF4T3ZlcmZsb3coKSkpKX11cGRhdGUodCl7fWRyYXcoKXtjb25zdCB0PXRoaXMuX2N0eCxlPXRoaXMuY2hhcnQsaT10aGlzLl9jYWNoZWRNZXRhLHM9aS5kYXRhfHxbXSxuPWUuY2hhcnRBcmVhLG89W10sYT10aGlzLl9kcmF3U3RhcnR8fDAscj10aGlzLl9kcmF3Q291bnR8fHMubGVuZ3RoLWEsbD10aGlzLm9wdGlvbnMuZHJhd0FjdGl2ZUVsZW1lbnRzT25Ub3A7bGV0IGg7Zm9yKGkuZGF0YXNldCYmaS5kYXRhc2V0LmRyYXcodCxuLGEsciksaD1hO2g8YStyOysraCl7Y29uc3QgZT1zW2hdO2UuaGlkZGVufHwoZS5hY3RpdmUmJmw\/by5wdXNoKGUpOmUuZHJhdyh0LG4pKX1mb3IoaD0wO2g8by5sZW5ndGg7KytoKW9baF0uZHJhdyh0LG4pfWdldFN0eWxlKHQsZSl7Y29uc3QgaT1lPyJhY3RpdmUiOiJkZWZhdWx0IjtyZXR1cm4gdm9pZCAwPT09dCYmdGhpcy5fY2FjaGVkTWV0YS5kYXRhc2V0P3RoaXMucmVzb2x2ZURhdGFzZXRFbGVtZW50T3B0aW9ucyhpKTp0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnModHx8MCxpKX1nZXRDb250ZXh0KHQsZSxpKXtjb25zdCBzPXRoaXMuZ2V0RGF0YXNldCgpO2xldCBuO2lmKHQ+PTAmJnQ8dGhpcy5fY2FjaGVkTWV0YS5kYXRhLmxlbmd0aCl7Y29uc3QgZT10aGlzLl9jYWNoZWRNZXRhLmRhdGFbdF07bj1lLiRjb250ZXh0fHwoZS4kY29udGV4dD1mdW5jdGlvbih0LGUsaSl7cmV0dXJuIENpKHQse2FjdGl2ZTohMSxkYXRhSW5kZXg6ZSxwYXJzZWQ6dm9pZCAwLHJhdzp2b2lkIDAsZWxlbWVudDppLGluZGV4OmUsbW9kZToiZGVmYXVsdCIsdHlwZToiZGF0YSJ9KX0odGhpcy5nZXRDb250ZXh0KCksdCxlKSksbi5wYXJzZWQ9dGhpcy5nZXRQYXJzZWQodCksbi5yYXc9cy5kYXRhW3RdLG4uaW5kZXg9bi5kYXRhSW5kZXg9dH1lbHNlIG49dGhpcy4kY29udGV4dHx8KHRoaXMuJGNvbnRleHQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gQ2kodCx7YWN0aXZlOiExLGRhdGFzZXQ6dm9pZCAwLGRhdGFzZXRJbmRleDplLGluZGV4OmUsbW9kZToiZGVmYXVsdCIsdHlwZToiZGF0YXNldCJ9KX0odGhpcy5jaGFydC5nZXRDb250ZXh0KCksdGhpcy5pbmRleCkpLG4uZGF0YXNldD1zLG4uaW5kZXg9bi5kYXRhc2V0SW5kZXg9dGhpcy5pbmRleDtyZXR1cm4gbi5hY3RpdmU9ISFlLG4ubW9kZT1pLG59cmVzb2x2ZURhdGFzZXRFbGVtZW50T3B0aW9ucyh0KXtyZXR1cm4gdGhpcy5fcmVzb2x2ZUVsZW1lbnRPcHRpb25zKHRoaXMuZGF0YXNldEVsZW1lbnRUeXBlLmlkLHQpfXJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnModCxlKXtyZXR1cm4gdGhpcy5fcmVzb2x2ZUVsZW1lbnRPcHRpb25zKHRoaXMuZGF0YUVsZW1lbnRUeXBlLmlkLGUsdCl9X3Jlc29sdmVFbGVtZW50T3B0aW9ucyh0LGU9ImRlZmF1bHQiLGkpe2NvbnN0IHM9ImFjdGl2ZSI9PT1lLG49dGhpcy5fY2FjaGVkRGF0YU9wdHMsbz10KyItIitlLGE9bltvXSxyPXRoaXMuZW5hYmxlT3B0aW9uU2hhcmluZyYmayhpKTtpZihhKXJldHVybiBXcyhhLHIpO2NvbnN0IGw9dGhpcy5jaGFydC5jb25maWcsaD1sLmRhdGFzZXRFbGVtZW50U2NvcGVLZXlzKHRoaXMuX3R5cGUsdCksYz1zP1tgJHt0fUhvdmVyYCwiaG92ZXIiLHQsIiJdOlt0LCIiXSxkPWwuZ2V0T3B0aW9uU2NvcGVzKHRoaXMuZ2V0RGF0YXNldCgpLGgpLHU9T2JqZWN0LmtleXModWUuZWxlbWVudHNbdF0pLGY9bC5yZXNvbHZlTmFtZWRPcHRpb25zKGQsdSwoKCk9PnRoaXMuZ2V0Q29udGV4dChpLHMsZSkpLGMpO3JldHVybiBmLiRzaGFyZWQmJihmLiRzaGFyZWQ9cixuW29dPU9iamVjdC5mcmVlemUoV3MoZixyKSkpLGZ9X3Jlc29sdmVBbmltYXRpb25zKHQsZSxpKXtjb25zdCBzPXRoaXMuY2hhcnQsbj10aGlzLl9jYWNoZWREYXRhT3B0cyxvPWBhbmltYXRpb24tJHtlfWAsYT1uW29dO2lmKGEpcmV0dXJuIGE7bGV0IHI7aWYoITEhPT1zLm9wdGlvbnMuYW5pbWF0aW9uKXtjb25zdCBzPXRoaXMuY2hhcnQuY29uZmlnLG49cy5kYXRhc2V0QW5pbWF0aW9uU2NvcGVLZXlzKHRoaXMuX3R5cGUsZSksbz1zLmdldE9wdGlvblNjb3Blcyh0aGlzLmdldERhdGFzZXQoKSxuKTtyPXMuY3JlYXRlUmVzb2x2ZXIobyx0aGlzLmdldENvbnRleHQodCxpLGUpKX1jb25zdCBsPW5ldyBPcyhzLHImJnIuYW5pbWF0aW9ucyk7cmV0dXJuIHImJnIuX2NhY2hlYWJsZSYmKG5bb109T2JqZWN0LmZyZWV6ZShsKSksbH1nZXRTaGFyZWRPcHRpb25zKHQpe2lmKHQuJHNoYXJlZClyZXR1cm4gdGhpcy5fc2hhcmVkT3B0aW9uc3x8KHRoaXMuX3NoYXJlZE9wdGlvbnM9T2JqZWN0LmFzc2lnbih7fSx0KSl9aW5jbHVkZU9wdGlvbnModCxlKXtyZXR1cm4hZXx8QnModCl8fHRoaXMuY2hhcnQuX2FuaW1hdGlvbnNEaXNhYmxlZH1fZ2V0U2hhcmVkT3B0aW9ucyh0LGUpe2NvbnN0IGk9dGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKHQsZSkscz10aGlzLl9zaGFyZWRPcHRpb25zLG49dGhpcy5nZXRTaGFyZWRPcHRpb25zKGkpLG89dGhpcy5pbmNsdWRlT3B0aW9ucyhlLG4pfHxuIT09cztyZXR1cm4gdGhpcy51cGRhdGVTaGFyZWRPcHRpb25zKG4sZSxpKSx7c2hhcmVkT3B0aW9uczpuLGluY2x1ZGVPcHRpb25zOm99fXVwZGF0ZUVsZW1lbnQodCxlLGkscyl7QnMocyk\/T2JqZWN0LmFzc2lnbih0LGkpOnRoaXMuX3Jlc29sdmVBbmltYXRpb25zKGUscykudXBkYXRlKHQsaSl9dXBkYXRlU2hhcmVkT3B0aW9ucyh0LGUsaSl7dCYmIUJzKGUpJiZ0aGlzLl9yZXNvbHZlQW5pbWF0aW9ucyh2b2lkIDAsZSkudXBkYXRlKHQsaSl9X3NldFN0eWxlKHQsZSxpLHMpe3QuYWN0aXZlPXM7Y29uc3Qgbj10aGlzLmdldFN0eWxlKGUscyk7dGhpcy5fcmVzb2x2ZUFuaW1hdGlvbnMoZSxpLHMpLnVwZGF0ZSh0LHtvcHRpb25zOiFzJiZ0aGlzLmdldFNoYXJlZE9wdGlvbnMobil8fG59KX1yZW1vdmVIb3ZlclN0eWxlKHQsZSxpKXt0aGlzLl9zZXRTdHlsZSh0LGksImFjdGl2ZSIsITEpfXNldEhvdmVyU3R5bGUodCxlLGkpe3RoaXMuX3NldFN0eWxlKHQsaSwiYWN0aXZlIiwhMCl9X3JlbW92ZURhdGFzZXRIb3ZlclN0eWxlKCl7Y29uc3QgdD10aGlzLl9jYWNoZWRNZXRhLmRhdGFzZXQ7dCYmdGhpcy5fc2V0U3R5bGUodCx2b2lkIDAsImFjdGl2ZSIsITEpfV9zZXREYXRhc2V0SG92ZXJTdHlsZSgpe2NvbnN0IHQ9dGhpcy5fY2FjaGVkTWV0YS5kYXRhc2V0O3QmJnRoaXMuX3NldFN0eWxlKHQsdm9pZCAwLCJhY3RpdmUiLCEwKX1fcmVzeW5jRWxlbWVudHModCl7Y29uc3QgZT10aGlzLl9kYXRhLGk9dGhpcy5fY2FjaGVkTWV0YS5kYXRhO2Zvcihjb25zdFt0LGUsaV1vZiB0aGlzLl9zeW5jTGlzdCl0aGlzW3RdKGUsaSk7dGhpcy5fc3luY0xpc3Q9W107Y29uc3Qgcz1pLmxlbmd0aCxuPWUubGVuZ3RoLG89TWF0aC5taW4obixzKTtvJiZ0aGlzLnBhcnNlKDAsbyksbj5zP3RoaXMuX2luc2VydEVsZW1lbnRzKHMsbi1zLHQpOm48cyYmdGhpcy5fcmVtb3ZlRWxlbWVudHMobixzLW4pfV9pbnNlcnRFbGVtZW50cyh0LGUsaT0hMCl7Y29uc3Qgcz10aGlzLl9jYWNoZWRNZXRhLG49cy5kYXRhLG89dCtlO2xldCBhO2NvbnN0IHI9dD0+e2Zvcih0Lmxlbmd0aCs9ZSxhPXQubGVuZ3RoLTE7YT49bzthLS0pdFthXT10W2EtZV19O2ZvcihyKG4pLGE9dDthPG87KythKW5bYV09bmV3IHRoaXMuZGF0YUVsZW1lbnRUeXBlO3RoaXMuX3BhcnNpbmcmJnIocy5fcGFyc2VkKSx0aGlzLnBhcnNlKHQsZSksaSYmdGhpcy51cGRhdGVFbGVtZW50cyhuLHQsZSwicmVzZXQiKX11cGRhdGVFbGVtZW50cyh0LGUsaSxzKXt9X3JlbW92ZUVsZW1lbnRzKHQsZSl7Y29uc3QgaT10aGlzLl9jYWNoZWRNZXRhO2lmKHRoaXMuX3BhcnNpbmcpe2NvbnN0IHM9aS5fcGFyc2VkLnNwbGljZSh0LGUpO2kuX3N0YWNrZWQmJlZzKGkscyl9aS5kYXRhLnNwbGljZSh0LGUpfV9zeW5jKHQpe2lmKHRoaXMuX3BhcnNpbmcpdGhpcy5fc3luY0xpc3QucHVzaCh0KTtlbHNle2NvbnN0W2UsaSxzXT10O3RoaXNbZV0oaSxzKX10aGlzLmNoYXJ0Ll9kYXRhQ2hhbmdlcy5wdXNoKFt0aGlzLmluZGV4LC4uLnRdKX1fb25EYXRhUHVzaCgpe2NvbnN0IHQ9YXJndW1lbnRzLmxlbmd0aDt0aGlzLl9zeW5jKFsiX2luc2VydEVsZW1lbnRzIix0aGlzLmdldERhdGFzZXQoKS5kYXRhLmxlbmd0aC10LHRdKX1fb25EYXRhUG9wKCl7dGhpcy5fc3luYyhbIl9yZW1vdmVFbGVtZW50cyIsdGhpcy5fY2FjaGVkTWV0YS5kYXRhLmxlbmd0aC0xLDFdKX1fb25EYXRhU2hpZnQoKXt0aGlzLl9zeW5jKFsiX3JlbW92ZUVsZW1lbnRzIiwwLDFdKX1fb25EYXRhU3BsaWNlKHQsZSl7ZSYmdGhpcy5fc3luYyhbIl9yZW1vdmVFbGVtZW50cyIsdCxlXSk7Y29uc3QgaT1hcmd1bWVudHMubGVuZ3RoLTI7aSYmdGhpcy5fc3luYyhbIl9pbnNlcnRFbGVtZW50cyIsdCxpXSl9X29uRGF0YVVuc2hpZnQoKXt0aGlzLl9zeW5jKFsiX2luc2VydEVsZW1lbnRzIiwwLGFyZ3VtZW50cy5sZW5ndGhdKX19Y2xhc3MgSHN7c3RhdGljIGRlZmF1bHRzPXt9O3N0YXRpYyBkZWZhdWx0Um91dGVzPXZvaWQgMDt4O3k7YWN0aXZlPSExO29wdGlvbnM7JGFuaW1hdGlvbnM7dG9vbHRpcFBvc2l0aW9uKHQpe2NvbnN0e3g6ZSx5Oml9PXRoaXMuZ2V0UHJvcHMoWyJ4IiwieSJdLHQpO3JldHVybnt4OmUseTppfX1oYXNWYWx1ZSgpe3JldHVybiBOKHRoaXMueCkmJk4odGhpcy55KX1nZXRQcm9wcyh0LGUpe2NvbnN0IGk9dGhpcy4kYW5pbWF0aW9ucztpZighZXx8IWkpcmV0dXJuIHRoaXM7Y29uc3Qgcz17fTtyZXR1cm4gdC5mb3JFYWNoKCh0PT57c1t0XT1pW3RdJiZpW3RdLmFjdGl2ZSgpP2lbdF0uX3RvOnRoaXNbdF19KSksc319ZnVuY3Rpb24ganModCxlKXtjb25zdCBpPXQub3B0aW9ucy50aWNrcyxuPWZ1bmN0aW9uKHQpe2NvbnN0IGU9dC5vcHRpb25zLm9mZnNldCxpPXQuX3RpY2tTaXplKCkscz10Ll9sZW5ndGgvaSsoZT8wOjEpLG49dC5fbWF4TGVuZ3RoL2k7cmV0dXJuIE1hdGguZmxvb3IoTWF0aC5taW4ocyxuKSl9KHQpLG89TWF0aC5taW4oaS5tYXhUaWNrc0xpbWl0fHxuLG4pLGE9aS5tYWpvci5lbmFibGVkP2Z1bmN0aW9uKHQpe2NvbnN0IGU9W107bGV0IGkscztmb3IoaT0wLHM9dC5sZW5ndGg7aTxzO2krKyl0W2ldLm1ham9yJiZlLnB1c2goaSk7cmV0dXJuIGV9KGUpOltdLHI9YS5sZW5ndGgsbD1hWzBdLGg9YVtyLTFdLGM9W107aWYocj5vKXJldHVybiBmdW5jdGlvbih0LGUsaSxzKXtsZXQgbixvPTAsYT1pWzBdO2ZvcihzPU1hdGguY2VpbChzKSxuPTA7bjx0Lmxlbmd0aDtuKyspbj09PWEmJihlLnB1c2godFtuXSksbysrLGE9aVtvKnNdKX0oZSxjLGEsci9vKSxjO2NvbnN0IGQ9ZnVuY3Rpb24odCxlLGkpe2NvbnN0IHM9ZnVuY3Rpb24odCl7Y29uc3QgZT10Lmxlbmd0aDtsZXQgaSxzO2lmKGU8MilyZXR1cm4hMTtmb3Iocz10WzBdLGk9MTtpPGU7KytpKWlmKHRbaV0tdFtpLTFdIT09cylyZXR1cm4hMTtyZXR1cm4gc30odCksbj1lLmxlbmd0aC9pO2lmKCFzKXJldHVybiBNYXRoLm1heChuLDEpO2NvbnN0IG89VyhzKTtmb3IobGV0IHQ9MCxlPW8ubGVuZ3RoLTE7dDxlO3QrKyl7Y29uc3QgZT1vW3RdO2lmKGU+bilyZXR1cm4gZX1yZXR1cm4gTWF0aC5tYXgobiwxKX0oYSxlLG8pO2lmKHI+MCl7bGV0IHQsaTtjb25zdCBuPXI+MT9NYXRoLnJvdW5kKChoLWwpLyhyLTEpKTpudWxsO2ZvcigkcyhlLGMsZCxzKG4pPzA6bC1uLGwpLHQ9MCxpPXItMTt0PGk7dCsrKSRzKGUsYyxkLGFbdF0sYVt0KzFdKTtyZXR1cm4gJHMoZSxjLGQsaCxzKG4pP2UubGVuZ3RoOmgrbiksY31yZXR1cm4gJHMoZSxjLGQpLGN9ZnVuY3Rpb24gJHModCxlLGkscyxuKXtjb25zdCBvPWwocywwKSxhPU1hdGgubWluKGwobix0Lmxlbmd0aCksdC5sZW5ndGgpO2xldCByLGgsYyxkPTA7Zm9yKGk9TWF0aC5jZWlsKGkpLG4mJihyPW4tcyxpPXIvTWF0aC5mbG9vcihyL2kpKSxjPW87YzwwOylkKyssYz1NYXRoLnJvdW5kKG8rZCppKTtmb3IoaD1NYXRoLm1heChvLDApO2g8YTtoKyspaD09PWMmJihlLnB1c2godFtoXSksZCsrLGM9TWF0aC5yb3VuZChvK2QqaSkpfWNvbnN0IFlzPSh0LGUsaSk9PiJ0b3AiPT09ZXx8ImxlZnQiPT09ZT90W2VdK2k6dFtlXS1pLFVzPSh0LGUpPT5NYXRoLm1pbihlfHx0LHQpO2Z1bmN0aW9uIFhzKHQsZSl7Y29uc3QgaT1bXSxzPXQubGVuZ3RoL2Usbj10Lmxlbmd0aDtsZXQgbz0wO2Zvcig7bzxuO28rPXMpaS5wdXNoKHRbTWF0aC5mbG9vcihvKV0pO3JldHVybiBpfWZ1bmN0aW9uIHFzKHQsZSxpKXtjb25zdCBzPXQudGlja3MubGVuZ3RoLG49TWF0aC5taW4oZSxzLTEpLG89dC5fc3RhcnRQaXhlbCxhPXQuX2VuZFBpeGVsLHI9MWUtNjtsZXQgbCxoPXQuZ2V0UGl4ZWxGb3JUaWNrKG4pO2lmKCEoaSYmKGw9MT09PXM\/TWF0aC5tYXgoaC1vLGEtaCk6MD09PWU\/KHQuZ2V0UGl4ZWxGb3JUaWNrKDEpLWgpLzI6KGgtdC5nZXRQaXhlbEZvclRpY2sobi0xKSkvMixoKz1uPGU\/bDotbCxoPG8tcnx8aD5hK3IpKSlyZXR1cm4gaH1mdW5jdGlvbiBLcyh0KXtyZXR1cm4gdC5kcmF3VGlja3M\/dC50aWNrTGVuZ3RoOjB9ZnVuY3Rpb24gR3ModCxlKXtpZighdC5kaXNwbGF5KXJldHVybiAwO2NvbnN0IGk9U2kodC5mb250LGUpLHM9a2kodC5wYWRkaW5nKTtyZXR1cm4obih0LnRleHQpP3QudGV4dC5sZW5ndGg6MSkqaS5saW5lSGVpZ2h0K3MuaGVpZ2h0fWZ1bmN0aW9uIFpzKHQsZSxpKXtsZXQgcz11dCh0KTtyZXR1cm4oaSYmInJpZ2h0IiE9PWV8fCFpJiYicmlnaHQiPT09ZSkmJihzPSh0PT4ibGVmdCI9PT10PyJyaWdodCI6InJpZ2h0Ij09PXQ\/ImxlZnQiOnQpKHMpKSxzfWNsYXNzIEpzIGV4dGVuZHMgSHN7Y29uc3RydWN0b3IodCl7c3VwZXIoKSx0aGlzLmlkPXQuaWQsdGhpcy50eXBlPXQudHlwZSx0aGlzLm9wdGlvbnM9dm9pZCAwLHRoaXMuY3R4PXQuY3R4LHRoaXMuY2hhcnQ9dC5jaGFydCx0aGlzLnRvcD12b2lkIDAsdGhpcy5ib3R0b209dm9pZCAwLHRoaXMubGVmdD12b2lkIDAsdGhpcy5yaWdodD12b2lkIDAsdGhpcy53aWR0aD12b2lkIDAsdGhpcy5oZWlnaHQ9dm9pZCAwLHRoaXMuX21hcmdpbnM9e2xlZnQ6MCxyaWdodDowLHRvcDowLGJvdHRvbTowfSx0aGlzLm1heFdpZHRoPXZvaWQgMCx0aGlzLm1heEhlaWdodD12b2lkIDAsdGhpcy5wYWRkaW5nVG9wPXZvaWQgMCx0aGlzLnBhZGRpbmdCb3R0b209dm9pZCAwLHRoaXMucGFkZGluZ0xlZnQ9dm9pZCAwLHRoaXMucGFkZGluZ1JpZ2h0PXZvaWQgMCx0aGlzLmF4aXM9dm9pZCAwLHRoaXMubGFiZWxSb3RhdGlvbj12b2lkIDAsdGhpcy5taW49dm9pZCAwLHRoaXMubWF4PXZvaWQgMCx0aGlzLl9yYW5nZT12b2lkIDAsdGhpcy50aWNrcz1bXSx0aGlzLl9ncmlkTGluZUl0ZW1zPW51bGwsdGhpcy5fbGFiZWxJdGVtcz1udWxsLHRoaXMuX2xhYmVsU2l6ZXM9bnVsbCx0aGlzLl9sZW5ndGg9MCx0aGlzLl9tYXhMZW5ndGg9MCx0aGlzLl9sb25nZXN0VGV4dENhY2hlPXt9LHRoaXMuX3N0YXJ0UGl4ZWw9dm9pZCAwLHRoaXMuX2VuZFBpeGVsPXZvaWQgMCx0aGlzLl9yZXZlcnNlUGl4ZWxzPSExLHRoaXMuX3VzZXJNYXg9dm9pZCAwLHRoaXMuX3VzZXJNaW49dm9pZCAwLHRoaXMuX3N1Z2dlc3RlZE1heD12b2lkIDAsdGhpcy5fc3VnZ2VzdGVkTWluPXZvaWQgMCx0aGlzLl90aWNrc0xlbmd0aD0wLHRoaXMuX2JvcmRlclZhbHVlPTAsdGhpcy5fY2FjaGU9e30sdGhpcy5fZGF0YUxpbWl0c0NhY2hlZD0hMSx0aGlzLiRjb250ZXh0PXZvaWQgMH1pbml0KHQpe3RoaXMub3B0aW9ucz10LnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KCkpLHRoaXMuYXhpcz10LmF4aXMsdGhpcy5fdXNlck1pbj10aGlzLnBhcnNlKHQubWluKSx0aGlzLl91c2VyTWF4PXRoaXMucGFyc2UodC5tYXgpLHRoaXMuX3N1Z2dlc3RlZE1pbj10aGlzLnBhcnNlKHQuc3VnZ2VzdGVkTWluKSx0aGlzLl9zdWdnZXN0ZWRNYXg9dGhpcy5wYXJzZSh0LnN1Z2dlc3RlZE1heCl9cGFyc2UodCxlKXtyZXR1cm4gdH1nZXRVc2VyQm91bmRzKCl7bGV0e191c2VyTWluOnQsX3VzZXJNYXg6ZSxfc3VnZ2VzdGVkTWluOmksX3N1Z2dlc3RlZE1heDpzfT10aGlzO3JldHVybiB0PXIodCxOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpLGU9cihlLE51bWJlci5ORUdBVElWRV9JTkZJTklUWSksaT1yKGksTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZKSxzPXIocyxOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFkpLHttaW46cih0LGkpLG1heDpyKGUscyksbWluRGVmaW5lZDphKHQpLG1heERlZmluZWQ6YShlKX19Z2V0TWluTWF4KHQpe2xldCBlLHttaW46aSxtYXg6cyxtaW5EZWZpbmVkOm4sbWF4RGVmaW5lZDpvfT10aGlzLmdldFVzZXJCb3VuZHMoKTtpZihuJiZvKXJldHVybnttaW46aSxtYXg6c307Y29uc3QgYT10aGlzLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKCk7Zm9yKGxldCByPTAsbD1hLmxlbmd0aDtyPGw7KytyKWU9YVtyXS5jb250cm9sbGVyLmdldE1pbk1heCh0aGlzLHQpLG58fChpPU1hdGgubWluKGksZS5taW4pKSxvfHwocz1NYXRoLm1heChzLGUubWF4KSk7cmV0dXJuIGk9byYmaT5zP3M6aSxzPW4mJmk+cz9pOnMse21pbjpyKGkscihzLGkpKSxtYXg6cihzLHIoaSxzKSl9fWdldFBhZGRpbmcoKXtyZXR1cm57bGVmdDp0aGlzLnBhZGRpbmdMZWZ0fHwwLHRvcDp0aGlzLnBhZGRpbmdUb3B8fDAscmlnaHQ6dGhpcy5wYWRkaW5nUmlnaHR8fDAsYm90dG9tOnRoaXMucGFkZGluZ0JvdHRvbXx8MH19Z2V0VGlja3MoKXtyZXR1cm4gdGhpcy50aWNrc31nZXRMYWJlbHMoKXtjb25zdCB0PXRoaXMuY2hhcnQuZGF0YTtyZXR1cm4gdGhpcy5vcHRpb25zLmxhYmVsc3x8KHRoaXMuaXNIb3Jpem9udGFsKCk\/dC54TGFiZWxzOnQueUxhYmVscyl8fHQubGFiZWxzfHxbXX1nZXRMYWJlbEl0ZW1zKHQ9dGhpcy5jaGFydC5jaGFydEFyZWEpe3JldHVybiB0aGlzLl9sYWJlbEl0ZW1zfHwodGhpcy5fbGFiZWxJdGVtcz10aGlzLl9jb21wdXRlTGFiZWxJdGVtcyh0KSl9YmVmb3JlTGF5b3V0KCl7dGhpcy5fY2FjaGU9e30sdGhpcy5fZGF0YUxpbWl0c0NhY2hlZD0hMX1iZWZvcmVVcGRhdGUoKXtkKHRoaXMub3B0aW9ucy5iZWZvcmVVcGRhdGUsW3RoaXNdKX11cGRhdGUodCxlLGkpe2NvbnN0e2JlZ2luQXRaZXJvOnMsZ3JhY2U6bix0aWNrczpvfT10aGlzLm9wdGlvbnMsYT1vLnNhbXBsZVNpemU7dGhpcy5iZWZvcmVVcGRhdGUoKSx0aGlzLm1heFdpZHRoPXQsdGhpcy5tYXhIZWlnaHQ9ZSx0aGlzLl9tYXJnaW5zPWk9T2JqZWN0LmFzc2lnbih7bGVmdDowLHJpZ2h0OjAsdG9wOjAsYm90dG9tOjB9LGkpLHRoaXMudGlja3M9bnVsbCx0aGlzLl9sYWJlbFNpemVzPW51bGwsdGhpcy5fZ3JpZExpbmVJdGVtcz1udWxsLHRoaXMuX2xhYmVsSXRlbXM9bnVsbCx0aGlzLmJlZm9yZVNldERpbWVuc2lvbnMoKSx0aGlzLnNldERpbWVuc2lvbnMoKSx0aGlzLmFmdGVyU2V0RGltZW5zaW9ucygpLHRoaXMuX21heExlbmd0aD10aGlzLmlzSG9yaXpvbnRhbCgpP3RoaXMud2lkdGgraS5sZWZ0K2kucmlnaHQ6dGhpcy5oZWlnaHQraS50b3AraS5ib3R0b20sdGhpcy5fZGF0YUxpbWl0c0NhY2hlZHx8KHRoaXMuYmVmb3JlRGF0YUxpbWl0cygpLHRoaXMuZGV0ZXJtaW5lRGF0YUxpbWl0cygpLHRoaXMuYWZ0ZXJEYXRhTGltaXRzKCksdGhpcy5fcmFuZ2U9RGkodGhpcyxuLHMpLHRoaXMuX2RhdGFMaW1pdHNDYWNoZWQ9ITApLHRoaXMuYmVmb3JlQnVpbGRUaWNrcygpLHRoaXMudGlja3M9dGhpcy5idWlsZFRpY2tzKCl8fFtdLHRoaXMuYWZ0ZXJCdWlsZFRpY2tzKCk7Y29uc3Qgcj1hPHRoaXMudGlja3MubGVuZ3RoO3RoaXMuX2NvbnZlcnRUaWNrc1RvTGFiZWxzKHI\/WHModGhpcy50aWNrcyxhKTp0aGlzLnRpY2tzKSx0aGlzLmNvbmZpZ3VyZSgpLHRoaXMuYmVmb3JlQ2FsY3VsYXRlTGFiZWxSb3RhdGlvbigpLHRoaXMuY2FsY3VsYXRlTGFiZWxSb3RhdGlvbigpLHRoaXMuYWZ0ZXJDYWxjdWxhdGVMYWJlbFJvdGF0aW9uKCksby5kaXNwbGF5JiYoby5hdXRvU2tpcHx8ImF1dG8iPT09by5zb3VyY2UpJiYodGhpcy50aWNrcz1qcyh0aGlzLHRoaXMudGlja3MpLHRoaXMuX2xhYmVsU2l6ZXM9bnVsbCx0aGlzLmFmdGVyQXV0b1NraXAoKSksciYmdGhpcy5fY29udmVydFRpY2tzVG9MYWJlbHModGhpcy50aWNrcyksdGhpcy5iZWZvcmVGaXQoKSx0aGlzLmZpdCgpLHRoaXMuYWZ0ZXJGaXQoKSx0aGlzLmFmdGVyVXBkYXRlKCl9Y29uZmlndXJlKCl7bGV0IHQsZSxpPXRoaXMub3B0aW9ucy5yZXZlcnNlO3RoaXMuaXNIb3Jpem9udGFsKCk\/KHQ9dGhpcy5sZWZ0LGU9dGhpcy5yaWdodCk6KHQ9dGhpcy50b3AsZT10aGlzLmJvdHRvbSxpPSFpKSx0aGlzLl9zdGFydFBpeGVsPXQsdGhpcy5fZW5kUGl4ZWw9ZSx0aGlzLl9yZXZlcnNlUGl4ZWxzPWksdGhpcy5fbGVuZ3RoPWUtdCx0aGlzLl9hbGlnblRvUGl4ZWxzPXRoaXMub3B0aW9ucy5hbGlnblRvUGl4ZWxzfWFmdGVyVXBkYXRlKCl7ZCh0aGlzLm9wdGlvbnMuYWZ0ZXJVcGRhdGUsW3RoaXNdKX1iZWZvcmVTZXREaW1lbnNpb25zKCl7ZCh0aGlzLm9wdGlvbnMuYmVmb3JlU2V0RGltZW5zaW9ucyxbdGhpc10pfXNldERpbWVuc2lvbnMoKXt0aGlzLmlzSG9yaXpvbnRhbCgpPyh0aGlzLndpZHRoPXRoaXMubWF4V2lkdGgsdGhpcy5sZWZ0PTAsdGhpcy5yaWdodD10aGlzLndpZHRoKToodGhpcy5oZWlnaHQ9dGhpcy5tYXhIZWlnaHQsdGhpcy50b3A9MCx0aGlzLmJvdHRvbT10aGlzLmhlaWdodCksdGhpcy5wYWRkaW5nTGVmdD0wLHRoaXMucGFkZGluZ1RvcD0wLHRoaXMucGFkZGluZ1JpZ2h0PTAsdGhpcy5wYWRkaW5nQm90dG9tPTB9YWZ0ZXJTZXREaW1lbnNpb25zKCl7ZCh0aGlzLm9wdGlvbnMuYWZ0ZXJTZXREaW1lbnNpb25zLFt0aGlzXSl9X2NhbGxIb29rcyh0KXt0aGlzLmNoYXJ0Lm5vdGlmeVBsdWdpbnModCx0aGlzLmdldENvbnRleHQoKSksZCh0aGlzLm9wdGlvbnNbdF0sW3RoaXNdKX1iZWZvcmVEYXRhTGltaXRzKCl7dGhpcy5fY2FsbEhvb2tzKCJiZWZvcmVEYXRhTGltaXRzIil9ZGV0ZXJtaW5lRGF0YUxpbWl0cygpe31hZnRlckRhdGFMaW1pdHMoKXt0aGlzLl9jYWxsSG9va3MoImFmdGVyRGF0YUxpbWl0cyIpfWJlZm9yZUJ1aWxkVGlja3MoKXt0aGlzLl9jYWxsSG9va3MoImJlZm9yZUJ1aWxkVGlja3MiKX1idWlsZFRpY2tzKCl7cmV0dXJuW119YWZ0ZXJCdWlsZFRpY2tzKCl7dGhpcy5fY2FsbEhvb2tzKCJhZnRlckJ1aWxkVGlja3MiKX1iZWZvcmVUaWNrVG9MYWJlbENvbnZlcnNpb24oKXtkKHRoaXMub3B0aW9ucy5iZWZvcmVUaWNrVG9MYWJlbENvbnZlcnNpb24sW3RoaXNdKX1nZW5lcmF0ZVRpY2tMYWJlbHModCl7Y29uc3QgZT10aGlzLm9wdGlvbnMudGlja3M7bGV0IGkscyxuO2ZvcihpPTAscz10Lmxlbmd0aDtpPHM7aSsrKW49dFtpXSxuLmxhYmVsPWQoZS5jYWxsYmFjayxbbi52YWx1ZSxpLHRdLHRoaXMpfWFmdGVyVGlja1RvTGFiZWxDb252ZXJzaW9uKCl7ZCh0aGlzLm9wdGlvbnMuYWZ0ZXJUaWNrVG9MYWJlbENvbnZlcnNpb24sW3RoaXNdKX1iZWZvcmVDYWxjdWxhdGVMYWJlbFJvdGF0aW9uKCl7ZCh0aGlzLm9wdGlvbnMuYmVmb3JlQ2FsY3VsYXRlTGFiZWxSb3RhdGlvbixbdGhpc10pfWNhbGN1bGF0ZUxhYmVsUm90YXRpb24oKXtjb25zdCB0PXRoaXMub3B0aW9ucyxlPXQudGlja3MsaT1Vcyh0aGlzLnRpY2tzLmxlbmd0aCx0LnRpY2tzLm1heFRpY2tzTGltaXQpLHM9ZS5taW5Sb3RhdGlvbnx8MCxuPWUubWF4Um90YXRpb247bGV0IG8sYSxyLGw9cztpZighdGhpcy5faXNWaXNpYmxlKCl8fCFlLmRpc3BsYXl8fHM+PW58fGk8PTF8fCF0aGlzLmlzSG9yaXpvbnRhbCgpKXJldHVybiB2b2lkKHRoaXMubGFiZWxSb3RhdGlvbj1zKTtjb25zdCBoPXRoaXMuX2dldExhYmVsU2l6ZXMoKSxjPWgud2lkZXN0LndpZHRoLGQ9aC5oaWdoZXN0LmhlaWdodCx1PUoodGhpcy5jaGFydC53aWR0aC1jLDAsdGhpcy5tYXhXaWR0aCk7bz10Lm9mZnNldD90aGlzLm1heFdpZHRoL2k6dS8oaS0xKSxjKzY+byYmKG89dS8oaS0odC5vZmZzZXQ\/LjU6MSkpLGE9dGhpcy5tYXhIZWlnaHQtS3ModC5ncmlkKS1lLnBhZGRpbmctR3ModC50aXRsZSx0aGlzLmNoYXJ0Lm9wdGlvbnMuZm9udCkscj1NYXRoLnNxcnQoYypjK2QqZCksbD1ZKE1hdGgubWluKE1hdGguYXNpbihKKChoLmhpZ2hlc3QuaGVpZ2h0KzYpL28sLTEsMSkpLE1hdGguYXNpbihKKGEvciwtMSwxKSktTWF0aC5hc2luKEooZC9yLC0xLDEpKSkpLGw9TWF0aC5tYXgocyxNYXRoLm1pbihuLGwpKSksdGhpcy5sYWJlbFJvdGF0aW9uPWx9YWZ0ZXJDYWxjdWxhdGVMYWJlbFJvdGF0aW9uKCl7ZCh0aGlzLm9wdGlvbnMuYWZ0ZXJDYWxjdWxhdGVMYWJlbFJvdGF0aW9uLFt0aGlzXSl9YWZ0ZXJBdXRvU2tpcCgpe31iZWZvcmVGaXQoKXtkKHRoaXMub3B0aW9ucy5iZWZvcmVGaXQsW3RoaXNdKX1maXQoKXtjb25zdCB0PXt3aWR0aDowLGhlaWdodDowfSx7Y2hhcnQ6ZSxvcHRpb25zOnt0aWNrczppLHRpdGxlOnMsZ3JpZDpufX09dGhpcyxvPXRoaXMuX2lzVmlzaWJsZSgpLGE9dGhpcy5pc0hvcml6b250YWwoKTtpZihvKXtjb25zdCBvPUdzKHMsZS5vcHRpb25zLmZvbnQpO2lmKGE\/KHQud2lkdGg9dGhpcy5tYXhXaWR0aCx0LmhlaWdodD1LcyhuKStvKToodC5oZWlnaHQ9dGhpcy5tYXhIZWlnaHQsdC53aWR0aD1LcyhuKStvKSxpLmRpc3BsYXkmJnRoaXMudGlja3MubGVuZ3RoKXtjb25zdHtmaXJzdDplLGxhc3Q6cyx3aWRlc3Q6bixoaWdoZXN0Om99PXRoaXMuX2dldExhYmVsU2l6ZXMoKSxyPTIqaS5wYWRkaW5nLGw9JCh0aGlzLmxhYmVsUm90YXRpb24pLGg9TWF0aC5jb3MobCksYz1NYXRoLnNpbihsKTtpZihhKXtjb25zdCBlPWkubWlycm9yPzA6YypuLndpZHRoK2gqby5oZWlnaHQ7dC5oZWlnaHQ9TWF0aC5taW4odGhpcy5tYXhIZWlnaHQsdC5oZWlnaHQrZStyKX1lbHNle2NvbnN0IGU9aS5taXJyb3I\/MDpoKm4ud2lkdGgrYypvLmhlaWdodDt0LndpZHRoPU1hdGgubWluKHRoaXMubWF4V2lkdGgsdC53aWR0aCtlK3IpfXRoaXMuX2NhbGN1bGF0ZVBhZGRpbmcoZSxzLGMsaCl9fXRoaXMuX2hhbmRsZU1hcmdpbnMoKSxhPyh0aGlzLndpZHRoPXRoaXMuX2xlbmd0aD1lLndpZHRoLXRoaXMuX21hcmdpbnMubGVmdC10aGlzLl9tYXJnaW5zLnJpZ2h0LHRoaXMuaGVpZ2h0PXQuaGVpZ2h0KToodGhpcy53aWR0aD10LndpZHRoLHRoaXMuaGVpZ2h0PXRoaXMuX2xlbmd0aD1lLmhlaWdodC10aGlzLl9tYXJnaW5zLnRvcC10aGlzLl9tYXJnaW5zLmJvdHRvbSl9X2NhbGN1bGF0ZVBhZGRpbmcodCxlLGkscyl7Y29uc3R7dGlja3M6e2FsaWduOm4scGFkZGluZzpvfSxwb3NpdGlvbjphfT10aGlzLm9wdGlvbnMscj0wIT09dGhpcy5sYWJlbFJvdGF0aW9uLGw9InRvcCIhPT1hJiYieCI9PT10aGlzLmF4aXM7aWYodGhpcy5pc0hvcml6b250YWwoKSl7Y29uc3QgYT10aGlzLmdldFBpeGVsRm9yVGljaygwKS10aGlzLmxlZnQsaD10aGlzLnJpZ2h0LXRoaXMuZ2V0UGl4ZWxGb3JUaWNrKHRoaXMudGlja3MubGVuZ3RoLTEpO2xldCBjPTAsZD0wO3I\/bD8oYz1zKnQud2lkdGgsZD1pKmUuaGVpZ2h0KTooYz1pKnQuaGVpZ2h0LGQ9cyplLndpZHRoKToic3RhcnQiPT09bj9kPWUud2lkdGg6ImVuZCI9PT1uP2M9dC53aWR0aDoiaW5uZXIiIT09biYmKGM9dC53aWR0aC8yLGQ9ZS53aWR0aC8yKSx0aGlzLnBhZGRpbmdMZWZ0PU1hdGgubWF4KChjLWErbykqdGhpcy53aWR0aC8odGhpcy53aWR0aC1hKSwwKSx0aGlzLnBhZGRpbmdSaWdodD1NYXRoLm1heCgoZC1oK28pKnRoaXMud2lkdGgvKHRoaXMud2lkdGgtaCksMCl9ZWxzZXtsZXQgaT1lLmhlaWdodC8yLHM9dC5oZWlnaHQvMjsic3RhcnQiPT09bj8oaT0wLHM9dC5oZWlnaHQpOiJlbmQiPT09biYmKGk9ZS5oZWlnaHQscz0wKSx0aGlzLnBhZGRpbmdUb3A9aStvLHRoaXMucGFkZGluZ0JvdHRvbT1zK299fV9oYW5kbGVNYXJnaW5zKCl7dGhpcy5fbWFyZ2lucyYmKHRoaXMuX21hcmdpbnMubGVmdD1NYXRoLm1heCh0aGlzLnBhZGRpbmdMZWZ0LHRoaXMuX21hcmdpbnMubGVmdCksdGhpcy5fbWFyZ2lucy50b3A9TWF0aC5tYXgodGhpcy5wYWRkaW5nVG9wLHRoaXMuX21hcmdpbnMudG9wKSx0aGlzLl9tYXJnaW5zLnJpZ2h0PU1hdGgubWF4KHRoaXMucGFkZGluZ1JpZ2h0LHRoaXMuX21hcmdpbnMucmlnaHQpLHRoaXMuX21hcmdpbnMuYm90dG9tPU1hdGgubWF4KHRoaXMucGFkZGluZ0JvdHRvbSx0aGlzLl9tYXJnaW5zLmJvdHRvbSkpfWFmdGVyRml0KCl7ZCh0aGlzLm9wdGlvbnMuYWZ0ZXJGaXQsW3RoaXNdKX1pc0hvcml6b250YWwoKXtjb25zdHtheGlzOnQscG9zaXRpb246ZX09dGhpcy5vcHRpb25zO3JldHVybiJ0b3AiPT09ZXx8ImJvdHRvbSI9PT1lfHwieCI9PT10fWlzRnVsbFNpemUoKXtyZXR1cm4gdGhpcy5vcHRpb25zLmZ1bGxTaXplfV9jb252ZXJ0VGlja3NUb0xhYmVscyh0KXtsZXQgZSxpO2Zvcih0aGlzLmJlZm9yZVRpY2tUb0xhYmVsQ29udmVyc2lvbigpLHRoaXMuZ2VuZXJhdGVUaWNrTGFiZWxzKHQpLGU9MCxpPXQubGVuZ3RoO2U8aTtlKyspcyh0W2VdLmxhYmVsKSYmKHQuc3BsaWNlKGUsMSksaS0tLGUtLSk7dGhpcy5hZnRlclRpY2tUb0xhYmVsQ29udmVyc2lvbigpfV9nZXRMYWJlbFNpemVzKCl7bGV0IHQ9dGhpcy5fbGFiZWxTaXplcztpZighdCl7Y29uc3QgZT10aGlzLm9wdGlvbnMudGlja3Muc2FtcGxlU2l6ZTtsZXQgaT10aGlzLnRpY2tzO2U8aS5sZW5ndGgmJihpPVhzKGksZSkpLHRoaXMuX2xhYmVsU2l6ZXM9dD10aGlzLl9jb21wdXRlTGFiZWxTaXplcyhpLGkubGVuZ3RoLHRoaXMub3B0aW9ucy50aWNrcy5tYXhUaWNrc0xpbWl0KX1yZXR1cm4gdH1fY29tcHV0ZUxhYmVsU2l6ZXModCxlLGkpe2NvbnN0e2N0eDpvLF9sb25nZXN0VGV4dENhY2hlOmF9PXRoaXMscj1bXSxsPVtdLGg9TWF0aC5mbG9vcihlL1VzKGUsaSkpO2xldCBjLGQsZixnLHAsbSxiLHgsXyx5LHYsTT0wLHc9MDtmb3IoYz0wO2M8ZTtjKz1oKXtpZihnPXRbY10ubGFiZWwscD10aGlzLl9yZXNvbHZlVGlja0ZvbnRPcHRpb25zKGMpLG8uZm9udD1tPXAuc3RyaW5nLGI9YVttXT1hW21dfHx7ZGF0YTp7fSxnYzpbXX0seD1wLmxpbmVIZWlnaHQsXz15PTAscyhnKXx8bihnKSl7aWYobihnKSlmb3IoZD0wLGY9Zy5sZW5ndGg7ZDxmOysrZCl2PWdbZF0scyh2KXx8bih2KXx8KF89Q2UobyxiLmRhdGEsYi5nYyxfLHYpLHkrPXgpfWVsc2UgXz1DZShvLGIuZGF0YSxiLmdjLF8sZykseT14O3IucHVzaChfKSxsLnB1c2goeSksTT1NYXRoLm1heChfLE0pLHc9TWF0aC5tYXgoeSx3KX0hZnVuY3Rpb24odCxlKXt1KHQsKHQ9Pntjb25zdCBpPXQuZ2Mscz1pLmxlbmd0aC8yO2xldCBuO2lmKHM+ZSl7Zm9yKG49MDtuPHM7KytuKWRlbGV0ZSB0LmRhdGFbaVtuXV07aS5zcGxpY2UoMCxzKX19KSl9KGEsZSk7Y29uc3Qgaz1yLmluZGV4T2YoTSksUz1sLmluZGV4T2YodyksUD10PT4oe3dpZHRoOnJbdF18fDAsaGVpZ2h0OmxbdF18fDB9KTtyZXR1cm57Zmlyc3Q6UCgwKSxsYXN0OlAoZS0xKSx3aWRlc3Q6UChrKSxoaWdoZXN0OlAoUyksd2lkdGhzOnIsaGVpZ2h0czpsfX1nZXRMYWJlbEZvclZhbHVlKHQpe3JldHVybiB0fWdldFBpeGVsRm9yVmFsdWUodCxlKXtyZXR1cm4gTmFOfWdldFZhbHVlRm9yUGl4ZWwodCl7fWdldFBpeGVsRm9yVGljayh0KXtjb25zdCBlPXRoaXMudGlja3M7cmV0dXJuIHQ8MHx8dD5lLmxlbmd0aC0xP251bGw6dGhpcy5nZXRQaXhlbEZvclZhbHVlKGVbdF0udmFsdWUpfWdldFBpeGVsRm9yRGVjaW1hbCh0KXt0aGlzLl9yZXZlcnNlUGl4ZWxzJiYodD0xLXQpO2NvbnN0IGU9dGhpcy5fc3RhcnRQaXhlbCt0KnRoaXMuX2xlbmd0aDtyZXR1cm4gUSh0aGlzLl9hbGlnblRvUGl4ZWxzP0FlKHRoaXMuY2hhcnQsZSwwKTplKX1nZXREZWNpbWFsRm9yUGl4ZWwodCl7Y29uc3QgZT0odC10aGlzLl9zdGFydFBpeGVsKS90aGlzLl9sZW5ndGg7cmV0dXJuIHRoaXMuX3JldmVyc2VQaXhlbHM\/MS1lOmV9Z2V0QmFzZVBpeGVsKCl7cmV0dXJuIHRoaXMuZ2V0UGl4ZWxGb3JWYWx1ZSh0aGlzLmdldEJhc2VWYWx1ZSgpKX1nZXRCYXNlVmFsdWUoKXtjb25zdHttaW46dCxtYXg6ZX09dGhpcztyZXR1cm4gdDwwJiZlPDA\/ZTp0PjAmJmU+MD90OjB9Z2V0Q29udGV4dCh0KXtjb25zdCBlPXRoaXMudGlja3N8fFtdO2lmKHQ+PTAmJnQ8ZS5sZW5ndGgpe2NvbnN0IGk9ZVt0XTtyZXR1cm4gaS4kY29udGV4dHx8KGkuJGNvbnRleHQ9ZnVuY3Rpb24odCxlLGkpe3JldHVybiBDaSh0LHt0aWNrOmksaW5kZXg6ZSx0eXBlOiJ0aWNrIn0pfSh0aGlzLmdldENvbnRleHQoKSx0LGkpKX1yZXR1cm4gdGhpcy4kY29udGV4dHx8KHRoaXMuJGNvbnRleHQ9Q2kodGhpcy5jaGFydC5nZXRDb250ZXh0KCkse3NjYWxlOnRoaXMsdHlwZToic2NhbGUifSkpfV90aWNrU2l6ZSgpe2NvbnN0IHQ9dGhpcy5vcHRpb25zLnRpY2tzLGU9JCh0aGlzLmxhYmVsUm90YXRpb24pLGk9TWF0aC5hYnMoTWF0aC5jb3MoZSkpLHM9TWF0aC5hYnMoTWF0aC5zaW4oZSkpLG49dGhpcy5fZ2V0TGFiZWxTaXplcygpLG89dC5hdXRvU2tpcFBhZGRpbmd8fDAsYT1uP24ud2lkZXN0LndpZHRoK286MCxyPW4\/bi5oaWdoZXN0LmhlaWdodCtvOjA7cmV0dXJuIHRoaXMuaXNIb3Jpem9udGFsKCk\/cippPmEqcz9hL2k6ci9zOnIqczxhKmk\/ci9pOmEvc31faXNWaXNpYmxlKCl7Y29uc3QgdD10aGlzLm9wdGlvbnMuZGlzcGxheTtyZXR1cm4iYXV0byIhPT10PyEhdDp0aGlzLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKCkubGVuZ3RoPjB9X2NvbXB1dGVHcmlkTGluZUl0ZW1zKHQpe2NvbnN0IGU9dGhpcy5heGlzLGk9dGhpcy5jaGFydCxzPXRoaXMub3B0aW9ucyx7Z3JpZDpuLHBvc2l0aW9uOmEsYm9yZGVyOnJ9PXMsaD1uLm9mZnNldCxjPXRoaXMuaXNIb3Jpem9udGFsKCksZD10aGlzLnRpY2tzLmxlbmd0aCsoaD8xOjApLHU9S3MobiksZj1bXSxnPXIuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoKSkscD1nLmRpc3BsYXk\/Zy53aWR0aDowLG09cC8yLGI9ZnVuY3Rpb24odCl7cmV0dXJuIEFlKGksdCxwKX07bGV0IHgsXyx5LHYsTSx3LGssUyxQLEQsQyxPO2lmKCJ0b3AiPT09YSl4PWIodGhpcy5ib3R0b20pLHc9dGhpcy5ib3R0b20tdSxTPXgtbSxEPWIodC50b3ApK20sTz10LmJvdHRvbTtlbHNlIGlmKCJib3R0b20iPT09YSl4PWIodGhpcy50b3ApLEQ9dC50b3AsTz1iKHQuYm90dG9tKS1tLHc9eCttLFM9dGhpcy50b3ArdTtlbHNlIGlmKCJsZWZ0Ij09PWEpeD1iKHRoaXMucmlnaHQpLE09dGhpcy5yaWdodC11LGs9eC1tLFA9Yih0LmxlZnQpK20sQz10LnJpZ2h0O2Vsc2UgaWYoInJpZ2h0Ij09PWEpeD1iKHRoaXMubGVmdCksUD10LmxlZnQsQz1iKHQucmlnaHQpLW0sTT14K20saz10aGlzLmxlZnQrdTtlbHNlIGlmKCJ4Ij09PWUpe2lmKCJjZW50ZXIiPT09YSl4PWIoKHQudG9wK3QuYm90dG9tKS8yKy41KTtlbHNlIGlmKG8oYSkpe2NvbnN0IHQ9T2JqZWN0LmtleXMoYSlbMF0sZT1hW3RdO3g9Yih0aGlzLmNoYXJ0LnNjYWxlc1t0XS5nZXRQaXhlbEZvclZhbHVlKGUpKX1EPXQudG9wLE89dC5ib3R0b20sdz14K20sUz13K3V9ZWxzZSBpZigieSI9PT1lKXtpZigiY2VudGVyIj09PWEpeD1iKCh0LmxlZnQrdC5yaWdodCkvMik7ZWxzZSBpZihvKGEpKXtjb25zdCB0PU9iamVjdC5rZXlzKGEpWzBdLGU9YVt0XTt4PWIodGhpcy5jaGFydC5zY2FsZXNbdF0uZ2V0UGl4ZWxGb3JWYWx1ZShlKSl9TT14LW0saz1NLXUsUD10LmxlZnQsQz10LnJpZ2h0fWNvbnN0IEE9bChzLnRpY2tzLm1heFRpY2tzTGltaXQsZCksVD1NYXRoLm1heCgxLE1hdGguY2VpbChkL0EpKTtmb3IoXz0wO188ZDtfKz1UKXtjb25zdCB0PXRoaXMuZ2V0Q29udGV4dChfKSxlPW4uc2V0Q29udGV4dCh0KSxzPXIuc2V0Q29udGV4dCh0KSxvPWUubGluZVdpZHRoLGE9ZS5jb2xvcixsPXMuZGFzaHx8W10sZD1zLmRhc2hPZmZzZXQsdT1lLnRpY2tXaWR0aCxnPWUudGlja0NvbG9yLHA9ZS50aWNrQm9yZGVyRGFzaHx8W10sbT1lLnRpY2tCb3JkZXJEYXNoT2Zmc2V0O3k9cXModGhpcyxfLGgpLHZvaWQgMCE9PXkmJih2PUFlKGkseSxvKSxjP009az1QPUM9djp3PVM9RD1PPXYsZi5wdXNoKHt0eDE6TSx0eTE6dyx0eDI6ayx0eTI6Uyx4MTpQLHkxOkQseDI6Qyx5MjpPLHdpZHRoOm8sY29sb3I6YSxib3JkZXJEYXNoOmwsYm9yZGVyRGFzaE9mZnNldDpkLHRpY2tXaWR0aDp1LHRpY2tDb2xvcjpnLHRpY2tCb3JkZXJEYXNoOnAsdGlja0JvcmRlckRhc2hPZmZzZXQ6bX0pKX1yZXR1cm4gdGhpcy5fdGlja3NMZW5ndGg9ZCx0aGlzLl9ib3JkZXJWYWx1ZT14LGZ9X2NvbXB1dGVMYWJlbEl0ZW1zKHQpe2NvbnN0IGU9dGhpcy5heGlzLGk9dGhpcy5vcHRpb25zLHtwb3NpdGlvbjpzLHRpY2tzOmF9PWkscj10aGlzLmlzSG9yaXpvbnRhbCgpLGw9dGhpcy50aWNrcyx7YWxpZ246aCxjcm9zc0FsaWduOmMscGFkZGluZzpkLG1pcnJvcjp1fT1hLGY9S3MoaS5ncmlkKSxnPWYrZCxwPXU\/LWQ6ZyxtPS0kKHRoaXMubGFiZWxSb3RhdGlvbiksYj1bXTtsZXQgeCxfLHksdixNLHcsayxTLFAsRCxDLE8sQT0ibWlkZGxlIjtpZigidG9wIj09PXMpdz10aGlzLmJvdHRvbS1wLGs9dGhpcy5fZ2V0WEF4aXNMYWJlbEFsaWdubWVudCgpO2Vsc2UgaWYoImJvdHRvbSI9PT1zKXc9dGhpcy50b3ArcCxrPXRoaXMuX2dldFhBeGlzTGFiZWxBbGlnbm1lbnQoKTtlbHNlIGlmKCJsZWZ0Ij09PXMpe2NvbnN0IHQ9dGhpcy5fZ2V0WUF4aXNMYWJlbEFsaWdubWVudChmKTtrPXQudGV4dEFsaWduLE09dC54fWVsc2UgaWYoInJpZ2h0Ij09PXMpe2NvbnN0IHQ9dGhpcy5fZ2V0WUF4aXNMYWJlbEFsaWdubWVudChmKTtrPXQudGV4dEFsaWduLE09dC54fWVsc2UgaWYoIngiPT09ZSl7aWYoImNlbnRlciI9PT1zKXc9KHQudG9wK3QuYm90dG9tKS8yK2c7ZWxzZSBpZihvKHMpKXtjb25zdCB0PU9iamVjdC5rZXlzKHMpWzBdLGU9c1t0XTt3PXRoaXMuY2hhcnQuc2NhbGVzW3RdLmdldFBpeGVsRm9yVmFsdWUoZSkrZ31rPXRoaXMuX2dldFhBeGlzTGFiZWxBbGlnbm1lbnQoKX1lbHNlIGlmKCJ5Ij09PWUpe2lmKCJjZW50ZXIiPT09cylNPSh0LmxlZnQrdC5yaWdodCkvMi1nO2Vsc2UgaWYobyhzKSl7Y29uc3QgdD1PYmplY3Qua2V5cyhzKVswXSxlPXNbdF07TT10aGlzLmNoYXJ0LnNjYWxlc1t0XS5nZXRQaXhlbEZvclZhbHVlKGUpfWs9dGhpcy5fZ2V0WUF4aXNMYWJlbEFsaWdubWVudChmKS50ZXh0QWxpZ259InkiPT09ZSYmKCJzdGFydCI9PT1oP0E9InRvcCI6ImVuZCI9PT1oJiYoQT0iYm90dG9tIikpO2NvbnN0IFQ9dGhpcy5fZ2V0TGFiZWxTaXplcygpO2Zvcih4PTAsXz1sLmxlbmd0aDt4PF87Kyt4KXt5PWxbeF0sdj15LmxhYmVsO2NvbnN0IHQ9YS5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCh4KSk7Uz10aGlzLmdldFBpeGVsRm9yVGljayh4KSthLmxhYmVsT2Zmc2V0LFA9dGhpcy5fcmVzb2x2ZVRpY2tGb250T3B0aW9ucyh4KSxEPVAubGluZUhlaWdodCxDPW4odik\/di5sZW5ndGg6MTtjb25zdCBlPUMvMixpPXQuY29sb3Isbz10LnRleHRTdHJva2VDb2xvcixoPXQudGV4dFN0cm9rZVdpZHRoO2xldCBkLGY9aztpZihyPyhNPVMsImlubmVyIj09PWsmJihmPXg9PT1fLTE\/dGhpcy5vcHRpb25zLnJldmVyc2U\/ImxlZnQiOiJyaWdodCI6MD09PXg\/dGhpcy5vcHRpb25zLnJldmVyc2U\/InJpZ2h0IjoibGVmdCI6ImNlbnRlciIpLE89InRvcCI9PT1zPyJuZWFyIj09PWN8fDAhPT1tPy1DKkQrRC8yOiJjZW50ZXIiPT09Yz8tVC5oaWdoZXN0LmhlaWdodC8yLWUqRCtEOi1ULmhpZ2hlc3QuaGVpZ2h0K0QvMjoibmVhciI9PT1jfHwwIT09bT9ELzI6ImNlbnRlciI9PT1jP1QuaGlnaGVzdC5oZWlnaHQvMi1lKkQ6VC5oaWdoZXN0LmhlaWdodC1DKkQsdSYmKE8qPS0xKSwwPT09bXx8dC5zaG93TGFiZWxCYWNrZHJvcHx8KE0rPUQvMipNYXRoLnNpbihtKSkpOih3PVMsTz0oMS1DKSpELzIpLHQuc2hvd0xhYmVsQmFja2Ryb3Ape2NvbnN0IGU9a2kodC5iYWNrZHJvcFBhZGRpbmcpLGk9VC5oZWlnaHRzW3hdLHM9VC53aWR0aHNbeF07bGV0IG49Ty1lLnRvcCxvPTAtZS5sZWZ0O3N3aXRjaChBKXtjYXNlIm1pZGRsZSI6bi09aS8yO2JyZWFrO2Nhc2UiYm90dG9tIjpuLT1pfXN3aXRjaChrKXtjYXNlImNlbnRlciI6by09cy8yO2JyZWFrO2Nhc2UicmlnaHQiOm8tPXM7YnJlYWs7Y2FzZSJpbm5lciI6eD09PV8tMT9vLT1zOng+MCYmKG8tPXMvMil9ZD17bGVmdDpvLHRvcDpuLHdpZHRoOnMrZS53aWR0aCxoZWlnaHQ6aStlLmhlaWdodCxjb2xvcjp0LmJhY2tkcm9wQ29sb3J9fWIucHVzaCh7bGFiZWw6dixmb250OlAsdGV4dE9mZnNldDpPLG9wdGlvbnM6e3JvdGF0aW9uOm0sY29sb3I6aSxzdHJva2VDb2xvcjpvLHN0cm9rZVdpZHRoOmgsdGV4dEFsaWduOmYsdGV4dEJhc2VsaW5lOkEsdHJhbnNsYXRpb246W00sd10sYmFja2Ryb3A6ZH19KX1yZXR1cm4gYn1fZ2V0WEF4aXNMYWJlbEFsaWdubWVudCgpe2NvbnN0e3Bvc2l0aW9uOnQsdGlja3M6ZX09dGhpcy5vcHRpb25zO2lmKC0kKHRoaXMubGFiZWxSb3RhdGlvbikpcmV0dXJuInRvcCI9PT10PyJsZWZ0IjoicmlnaHQiO2xldCBpPSJjZW50ZXIiO3JldHVybiJzdGFydCI9PT1lLmFsaWduP2k9ImxlZnQiOiJlbmQiPT09ZS5hbGlnbj9pPSJyaWdodCI6ImlubmVyIj09PWUuYWxpZ24mJihpPSJpbm5lciIpLGl9X2dldFlBeGlzTGFiZWxBbGlnbm1lbnQodCl7Y29uc3R7cG9zaXRpb246ZSx0aWNrczp7Y3Jvc3NBbGlnbjppLG1pcnJvcjpzLHBhZGRpbmc6bn19PXRoaXMub3B0aW9ucyxvPXQrbixhPXRoaXMuX2dldExhYmVsU2l6ZXMoKS53aWRlc3Qud2lkdGg7bGV0IHIsbDtyZXR1cm4ibGVmdCI9PT1lP3M\/KGw9dGhpcy5yaWdodCtuLCJuZWFyIj09PWk\/cj0ibGVmdCI6ImNlbnRlciI9PT1pPyhyPSJjZW50ZXIiLGwrPWEvMik6KHI9InJpZ2h0IixsKz1hKSk6KGw9dGhpcy5yaWdodC1vLCJuZWFyIj09PWk\/cj0icmlnaHQiOiJjZW50ZXIiPT09aT8ocj0iY2VudGVyIixsLT1hLzIpOihyPSJsZWZ0IixsPXRoaXMubGVmdCkpOiJyaWdodCI9PT1lP3M\/KGw9dGhpcy5sZWZ0K24sIm5lYXIiPT09aT9yPSJyaWdodCI6ImNlbnRlciI9PT1pPyhyPSJjZW50ZXIiLGwtPWEvMik6KHI9ImxlZnQiLGwtPWEpKToobD10aGlzLmxlZnQrbywibmVhciI9PT1pP3I9ImxlZnQiOiJjZW50ZXIiPT09aT8ocj0iY2VudGVyIixsKz1hLzIpOihyPSJyaWdodCIsbD10aGlzLnJpZ2h0KSk6cj0icmlnaHQiLHt0ZXh0QWxpZ246cix4Omx9fV9jb21wdXRlTGFiZWxBcmVhKCl7aWYodGhpcy5vcHRpb25zLnRpY2tzLm1pcnJvcilyZXR1cm47Y29uc3QgdD10aGlzLmNoYXJ0LGU9dGhpcy5vcHRpb25zLnBvc2l0aW9uO3JldHVybiJsZWZ0Ij09PWV8fCJyaWdodCI9PT1lP3t0b3A6MCxsZWZ0OnRoaXMubGVmdCxib3R0b206dC5oZWlnaHQscmlnaHQ6dGhpcy5yaWdodH06InRvcCI9PT1lfHwiYm90dG9tIj09PWU\/e3RvcDp0aGlzLnRvcCxsZWZ0OjAsYm90dG9tOnRoaXMuYm90dG9tLHJpZ2h0OnQud2lkdGh9OnZvaWQgMH1kcmF3QmFja2dyb3VuZCgpe2NvbnN0e2N0eDp0LG9wdGlvbnM6e2JhY2tncm91bmRDb2xvcjplfSxsZWZ0OmksdG9wOnMsd2lkdGg6bixoZWlnaHQ6b309dGhpcztlJiYodC5zYXZlKCksdC5maWxsU3R5bGU9ZSx0LmZpbGxSZWN0KGkscyxuLG8pLHQucmVzdG9yZSgpKX1nZXRMaW5lV2lkdGhGb3JWYWx1ZSh0KXtjb25zdCBlPXRoaXMub3B0aW9ucy5ncmlkO2lmKCF0aGlzLl9pc1Zpc2libGUoKXx8IWUuZGlzcGxheSlyZXR1cm4gMDtjb25zdCBpPXRoaXMudGlja3MuZmluZEluZGV4KChlPT5lLnZhbHVlPT09dCkpO2lmKGk+PTApe3JldHVybiBlLnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KGkpKS5saW5lV2lkdGh9cmV0dXJuIDB9ZHJhd0dyaWQodCl7Y29uc3QgZT10aGlzLm9wdGlvbnMuZ3JpZCxpPXRoaXMuY3R4LHM9dGhpcy5fZ3JpZExpbmVJdGVtc3x8KHRoaXMuX2dyaWRMaW5lSXRlbXM9dGhpcy5fY29tcHV0ZUdyaWRMaW5lSXRlbXModCkpO2xldCBuLG87Y29uc3QgYT0odCxlLHMpPT57cy53aWR0aCYmcy5jb2xvciYmKGkuc2F2ZSgpLGkubGluZVdpZHRoPXMud2lkdGgsaS5zdHJva2VTdHlsZT1zLmNvbG9yLGkuc2V0TGluZURhc2gocy5ib3JkZXJEYXNofHxbXSksaS5saW5lRGFzaE9mZnNldD1zLmJvcmRlckRhc2hPZmZzZXQsaS5iZWdpblBhdGgoKSxpLm1vdmVUbyh0LngsdC55KSxpLmxpbmVUbyhlLngsZS55KSxpLnN0cm9rZSgpLGkucmVzdG9yZSgpKX07aWYoZS5kaXNwbGF5KWZvcihuPTAsbz1zLmxlbmd0aDtuPG87KytuKXtjb25zdCB0PXNbbl07ZS5kcmF3T25DaGFydEFyZWEmJmEoe3g6dC54MSx5OnQueTF9LHt4OnQueDIseTp0LnkyfSx0KSxlLmRyYXdUaWNrcyYmYSh7eDp0LnR4MSx5OnQudHkxfSx7eDp0LnR4Mix5OnQudHkyfSx7Y29sb3I6dC50aWNrQ29sb3Isd2lkdGg6dC50aWNrV2lkdGgsYm9yZGVyRGFzaDp0LnRpY2tCb3JkZXJEYXNoLGJvcmRlckRhc2hPZmZzZXQ6dC50aWNrQm9yZGVyRGFzaE9mZnNldH0pfX1kcmF3Qm9yZGVyKCl7Y29uc3R7Y2hhcnQ6dCxjdHg6ZSxvcHRpb25zOntib3JkZXI6aSxncmlkOnN9fT10aGlzLG49aS5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCgpKSxvPWkuZGlzcGxheT9uLndpZHRoOjA7aWYoIW8pcmV0dXJuO2NvbnN0IGE9cy5zZXRDb250ZXh0KHRoaXMuZ2V0Q29udGV4dCgwKSkubGluZVdpZHRoLHI9dGhpcy5fYm9yZGVyVmFsdWU7bGV0IGwsaCxjLGQ7dGhpcy5pc0hvcml6b250YWwoKT8obD1BZSh0LHRoaXMubGVmdCxvKS1vLzIsaD1BZSh0LHRoaXMucmlnaHQsYSkrYS8yLGM9ZD1yKTooYz1BZSh0LHRoaXMudG9wLG8pLW8vMixkPUFlKHQsdGhpcy5ib3R0b20sYSkrYS8yLGw9aD1yKSxlLnNhdmUoKSxlLmxpbmVXaWR0aD1uLndpZHRoLGUuc3Ryb2tlU3R5bGU9bi5jb2xvcixlLmJlZ2luUGF0aCgpLGUubW92ZVRvKGwsYyksZS5saW5lVG8oaCxkKSxlLnN0cm9rZSgpLGUucmVzdG9yZSgpfWRyYXdMYWJlbHModCl7aWYoIXRoaXMub3B0aW9ucy50aWNrcy5kaXNwbGF5KXJldHVybjtjb25zdCBlPXRoaXMuY3R4LGk9dGhpcy5fY29tcHV0ZUxhYmVsQXJlYSgpO2kmJkllKGUsaSk7Y29uc3Qgcz10aGlzLmdldExhYmVsSXRlbXModCk7Zm9yKGNvbnN0IHQgb2Ygcyl7Y29uc3QgaT10Lm9wdGlvbnMscz10LmZvbnQ7TmUoZSx0LmxhYmVsLDAsdC50ZXh0T2Zmc2V0LHMsaSl9aSYmemUoZSl9ZHJhd1RpdGxlKCl7Y29uc3R7Y3R4OnQsb3B0aW9uczp7cG9zaXRpb246ZSx0aXRsZTppLHJldmVyc2U6c319PXRoaXM7aWYoIWkuZGlzcGxheSlyZXR1cm47Y29uc3QgYT1TaShpLmZvbnQpLHI9a2koaS5wYWRkaW5nKSxsPWkuYWxpZ247bGV0IGg9YS5saW5lSGVpZ2h0LzI7ImJvdHRvbSI9PT1lfHwiY2VudGVyIj09PWV8fG8oZSk\/KGgrPXIuYm90dG9tLG4oaS50ZXh0KSYmKGgrPWEubGluZUhlaWdodCooaS50ZXh0Lmxlbmd0aC0xKSkpOmgrPXIudG9wO2NvbnN0e3RpdGxlWDpjLHRpdGxlWTpkLG1heFdpZHRoOnUscm90YXRpb246Zn09ZnVuY3Rpb24odCxlLGkscyl7Y29uc3R7dG9wOm4sbGVmdDphLGJvdHRvbTpyLHJpZ2h0OmwsY2hhcnQ6aH09dCx7Y2hhcnRBcmVhOmMsc2NhbGVzOmR9PWg7bGV0IHUsZixnLHA9MDtjb25zdCBtPXItbixiPWwtYTtpZih0LmlzSG9yaXpvbnRhbCgpKXtpZihmPWZ0KHMsYSxsKSxvKGkpKXtjb25zdCB0PU9iamVjdC5rZXlzKGkpWzBdLHM9aVt0XTtnPWRbdF0uZ2V0UGl4ZWxGb3JWYWx1ZShzKSttLWV9ZWxzZSBnPSJjZW50ZXIiPT09aT8oYy5ib3R0b20rYy50b3ApLzIrbS1lOllzKHQsaSxlKTt1PWwtYX1lbHNle2lmKG8oaSkpe2NvbnN0IHQ9T2JqZWN0LmtleXMoaSlbMF0scz1pW3RdO2Y9ZFt0XS5nZXRQaXhlbEZvclZhbHVlKHMpLWIrZX1lbHNlIGY9ImNlbnRlciI9PT1pPyhjLmxlZnQrYy5yaWdodCkvMi1iK2U6WXModCxpLGUpO2c9ZnQocyxyLG4pLHA9ImxlZnQiPT09aT8tRTpFfXJldHVybnt0aXRsZVg6Zix0aXRsZVk6ZyxtYXhXaWR0aDp1LHJvdGF0aW9uOnB9fSh0aGlzLGgsZSxsKTtOZSh0LGkudGV4dCwwLDAsYSx7Y29sb3I6aS5jb2xvcixtYXhXaWR0aDp1LHJvdGF0aW9uOmYsdGV4dEFsaWduOlpzKGwsZSxzKSx0ZXh0QmFzZWxpbmU6Im1pZGRsZSIsdHJhbnNsYXRpb246W2MsZF19KX1kcmF3KHQpe3RoaXMuX2lzVmlzaWJsZSgpJiYodGhpcy5kcmF3QmFja2dyb3VuZCgpLHRoaXMuZHJhd0dyaWQodCksdGhpcy5kcmF3Qm9yZGVyKCksdGhpcy5kcmF3VGl0bGUoKSx0aGlzLmRyYXdMYWJlbHModCkpfV9sYXllcnMoKXtjb25zdCB0PXRoaXMub3B0aW9ucyxlPXQudGlja3MmJnQudGlja3Muenx8MCxpPWwodC5ncmlkJiZ0LmdyaWQueiwtMSkscz1sKHQuYm9yZGVyJiZ0LmJvcmRlci56LDApO3JldHVybiB0aGlzLl9pc1Zpc2libGUoKSYmdGhpcy5kcmF3PT09SnMucHJvdG90eXBlLmRyYXc\/W3t6OmksZHJhdzp0PT57dGhpcy5kcmF3QmFja2dyb3VuZCgpLHRoaXMuZHJhd0dyaWQodCksdGhpcy5kcmF3VGl0bGUoKX19LHt6OnMsZHJhdzooKT0+e3RoaXMuZHJhd0JvcmRlcigpfX0se3o6ZSxkcmF3OnQ9Pnt0aGlzLmRyYXdMYWJlbHModCl9fV06W3t6OmUsZHJhdzp0PT57dGhpcy5kcmF3KHQpfX1dfWdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKHQpe2NvbnN0IGU9dGhpcy5jaGFydC5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCksaT10aGlzLmF4aXMrIkF4aXNJRCIscz1bXTtsZXQgbixvO2ZvcihuPTAsbz1lLmxlbmd0aDtuPG87KytuKXtjb25zdCBvPWVbbl07b1tpXSE9PXRoaXMuaWR8fHQmJm8udHlwZSE9PXR8fHMucHVzaChvKX1yZXR1cm4gc31fcmVzb2x2ZVRpY2tGb250T3B0aW9ucyh0KXtyZXR1cm4gU2kodGhpcy5vcHRpb25zLnRpY2tzLnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KHQpKS5mb250KX1fbWF4RGlnaXRzKCl7Y29uc3QgdD10aGlzLl9yZXNvbHZlVGlja0ZvbnRPcHRpb25zKDApLmxpbmVIZWlnaHQ7cmV0dXJuKHRoaXMuaXNIb3Jpem9udGFsKCk\/dGhpcy53aWR0aDp0aGlzLmhlaWdodCkvdH19Y2xhc3MgUXN7Y29uc3RydWN0b3IodCxlLGkpe3RoaXMudHlwZT10LHRoaXMuc2NvcGU9ZSx0aGlzLm92ZXJyaWRlPWksdGhpcy5pdGVtcz1PYmplY3QuY3JlYXRlKG51bGwpfWlzRm9yVHlwZSh0KXtyZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mLmNhbGwodGhpcy50eXBlLnByb3RvdHlwZSx0LnByb3RvdHlwZSl9cmVnaXN0ZXIodCl7Y29uc3QgZT1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCk7bGV0IGk7KGZ1bmN0aW9uKHQpe3JldHVybiJpZCJpbiB0JiYiZGVmYXVsdHMiaW4gdH0pKGUpJiYoaT10aGlzLnJlZ2lzdGVyKGUpKTtjb25zdCBzPXRoaXMuaXRlbXMsbj10LmlkLG89dGhpcy5zY29wZSsiLiIrbjtpZighbil0aHJvdyBuZXcgRXJyb3IoImNsYXNzIGRvZXMgbm90IGhhdmUgaWQ6ICIrdCk7cmV0dXJuIG4gaW4gc3x8KHNbbl09dCxmdW5jdGlvbih0LGUsaSl7Y29uc3Qgcz1iKE9iamVjdC5jcmVhdGUobnVsbCksW2k\/dWUuZ2V0KGkpOnt9LHVlLmdldChlKSx0LmRlZmF1bHRzXSk7dWUuc2V0KGUscyksdC5kZWZhdWx0Um91dGVzJiZmdW5jdGlvbih0LGUpe09iamVjdC5rZXlzKGUpLmZvckVhY2goKGk9Pntjb25zdCBzPWkuc3BsaXQoIi4iKSxuPXMucG9wKCksbz1bdF0uY29uY2F0KHMpLmpvaW4oIi4iKSxhPWVbaV0uc3BsaXQoIi4iKSxyPWEucG9wKCksbD1hLmpvaW4oIi4iKTt1ZS5yb3V0ZShvLG4sbCxyKX0pKX0oZSx0LmRlZmF1bHRSb3V0ZXMpO3QuZGVzY3JpcHRvcnMmJnVlLmRlc2NyaWJlKGUsdC5kZXNjcmlwdG9ycyl9KHQsbyxpKSx0aGlzLm92ZXJyaWRlJiZ1ZS5vdmVycmlkZSh0LmlkLHQub3ZlcnJpZGVzKSksb31nZXQodCl7cmV0dXJuIHRoaXMuaXRlbXNbdF19dW5yZWdpc3Rlcih0KXtjb25zdCBlPXRoaXMuaXRlbXMsaT10LmlkLHM9dGhpcy5zY29wZTtpIGluIGUmJmRlbGV0ZSBlW2ldLHMmJmkgaW4gdWVbc10mJihkZWxldGUgdWVbc11baV0sdGhpcy5vdmVycmlkZSYmZGVsZXRlIHJlW2ldKX19Y2xhc3MgdG57Y29uc3RydWN0b3IoKXt0aGlzLmNvbnRyb2xsZXJzPW5ldyBRcyhOcywiZGF0YXNldHMiLCEwKSx0aGlzLmVsZW1lbnRzPW5ldyBRcyhIcywiZWxlbWVudHMiKSx0aGlzLnBsdWdpbnM9bmV3IFFzKE9iamVjdCwicGx1Z2lucyIpLHRoaXMuc2NhbGVzPW5ldyBRcyhKcywic2NhbGVzIiksdGhpcy5fdHlwZWRSZWdpc3RyaWVzPVt0aGlzLmNvbnRyb2xsZXJzLHRoaXMuc2NhbGVzLHRoaXMuZWxlbWVudHNdfWFkZCguLi50KXt0aGlzLl9lYWNoKCJyZWdpc3RlciIsdCl9cmVtb3ZlKC4uLnQpe3RoaXMuX2VhY2goInVucmVnaXN0ZXIiLHQpfWFkZENvbnRyb2xsZXJzKC4uLnQpe3RoaXMuX2VhY2goInJlZ2lzdGVyIix0LHRoaXMuY29udHJvbGxlcnMpfWFkZEVsZW1lbnRzKC4uLnQpe3RoaXMuX2VhY2goInJlZ2lzdGVyIix0LHRoaXMuZWxlbWVudHMpfWFkZFBsdWdpbnMoLi4udCl7dGhpcy5fZWFjaCgicmVnaXN0ZXIiLHQsdGhpcy5wbHVnaW5zKX1hZGRTY2FsZXMoLi4udCl7dGhpcy5fZWFjaCgicmVnaXN0ZXIiLHQsdGhpcy5zY2FsZXMpfWdldENvbnRyb2xsZXIodCl7cmV0dXJuIHRoaXMuX2dldCh0LHRoaXMuY29udHJvbGxlcnMsImNvbnRyb2xsZXIiKX1nZXRFbGVtZW50KHQpe3JldHVybiB0aGlzLl9nZXQodCx0aGlzLmVsZW1lbnRzLCJlbGVtZW50Iil9Z2V0UGx1Z2luKHQpe3JldHVybiB0aGlzLl9nZXQodCx0aGlzLnBsdWdpbnMsInBsdWdpbiIpfWdldFNjYWxlKHQpe3JldHVybiB0aGlzLl9nZXQodCx0aGlzLnNjYWxlcywic2NhbGUiKX1yZW1vdmVDb250cm9sbGVycyguLi50KXt0aGlzLl9lYWNoKCJ1bnJlZ2lzdGVyIix0LHRoaXMuY29udHJvbGxlcnMpfXJlbW92ZUVsZW1lbnRzKC4uLnQpe3RoaXMuX2VhY2goInVucmVnaXN0ZXIiLHQsdGhpcy5lbGVtZW50cyl9cmVtb3ZlUGx1Z2lucyguLi50KXt0aGlzLl9lYWNoKCJ1bnJlZ2lzdGVyIix0LHRoaXMucGx1Z2lucyl9cmVtb3ZlU2NhbGVzKC4uLnQpe3RoaXMuX2VhY2goInVucmVnaXN0ZXIiLHQsdGhpcy5zY2FsZXMpfV9lYWNoKHQsZSxpKXtbLi4uZV0uZm9yRWFjaCgoZT0+e2NvbnN0IHM9aXx8dGhpcy5fZ2V0UmVnaXN0cnlGb3JUeXBlKGUpO2l8fHMuaXNGb3JUeXBlKGUpfHxzPT09dGhpcy5wbHVnaW5zJiZlLmlkP3RoaXMuX2V4ZWModCxzLGUpOnUoZSwoZT0+e2NvbnN0IHM9aXx8dGhpcy5fZ2V0UmVnaXN0cnlGb3JUeXBlKGUpO3RoaXMuX2V4ZWModCxzLGUpfSkpfSkpfV9leGVjKHQsZSxpKXtjb25zdCBzPXcodCk7ZChpWyJiZWZvcmUiK3NdLFtdLGkpLGVbdF0oaSksZChpWyJhZnRlciIrc10sW10saSl9X2dldFJlZ2lzdHJ5Rm9yVHlwZSh0KXtmb3IobGV0IGU9MDtlPHRoaXMuX3R5cGVkUmVnaXN0cmllcy5sZW5ndGg7ZSsrKXtjb25zdCBpPXRoaXMuX3R5cGVkUmVnaXN0cmllc1tlXTtpZihpLmlzRm9yVHlwZSh0KSlyZXR1cm4gaX1yZXR1cm4gdGhpcy5wbHVnaW5zfV9nZXQodCxlLGkpe2NvbnN0IHM9ZS5nZXQodCk7aWYodm9pZCAwPT09cyl0aHJvdyBuZXcgRXJyb3IoJyInK3QrJyIgaXMgbm90IGEgcmVnaXN0ZXJlZCAnK2krIi4iKTtyZXR1cm4gc319dmFyIGVuPW5ldyB0bjtjbGFzcyBzbntjb25zdHJ1Y3Rvcigpe3RoaXMuX2luaXQ9W119bm90aWZ5KHQsZSxpLHMpeyJiZWZvcmVJbml0Ij09PWUmJih0aGlzLl9pbml0PXRoaXMuX2NyZWF0ZURlc2NyaXB0b3JzKHQsITApLHRoaXMuX25vdGlmeSh0aGlzLl9pbml0LHQsImluc3RhbGwiKSk7Y29uc3Qgbj1zP3RoaXMuX2Rlc2NyaXB0b3JzKHQpLmZpbHRlcihzKTp0aGlzLl9kZXNjcmlwdG9ycyh0KSxvPXRoaXMuX25vdGlmeShuLHQsZSxpKTtyZXR1cm4iYWZ0ZXJEZXN0cm95Ij09PWUmJih0aGlzLl9ub3RpZnkobix0LCJzdG9wIiksdGhpcy5fbm90aWZ5KHRoaXMuX2luaXQsdCwidW5pbnN0YWxsIikpLG99X25vdGlmeSh0LGUsaSxzKXtzPXN8fHt9O2Zvcihjb25zdCBuIG9mIHQpe2NvbnN0IHQ9bi5wbHVnaW47aWYoITE9PT1kKHRbaV0sW2UscyxuLm9wdGlvbnNdLHQpJiZzLmNhbmNlbGFibGUpcmV0dXJuITF9cmV0dXJuITB9aW52YWxpZGF0ZSgpe3ModGhpcy5fY2FjaGUpfHwodGhpcy5fb2xkQ2FjaGU9dGhpcy5fY2FjaGUsdGhpcy5fY2FjaGU9dm9pZCAwKX1fZGVzY3JpcHRvcnModCl7aWYodGhpcy5fY2FjaGUpcmV0dXJuIHRoaXMuX2NhY2hlO2NvbnN0IGU9dGhpcy5fY2FjaGU9dGhpcy5fY3JlYXRlRGVzY3JpcHRvcnModCk7cmV0dXJuIHRoaXMuX25vdGlmeVN0YXRlQ2hhbmdlcyh0KSxlfV9jcmVhdGVEZXNjcmlwdG9ycyh0LGUpe2NvbnN0IGk9dCYmdC5jb25maWcscz1sKGkub3B0aW9ucyYmaS5vcHRpb25zLnBsdWdpbnMse30pLG49ZnVuY3Rpb24odCl7Y29uc3QgZT17fSxpPVtdLHM9T2JqZWN0LmtleXMoZW4ucGx1Z2lucy5pdGVtcyk7Zm9yKGxldCB0PTA7dDxzLmxlbmd0aDt0KyspaS5wdXNoKGVuLmdldFBsdWdpbihzW3RdKSk7Y29uc3Qgbj10LnBsdWdpbnN8fFtdO2ZvcihsZXQgdD0wO3Q8bi5sZW5ndGg7dCsrKXtjb25zdCBzPW5bdF07LTE9PT1pLmluZGV4T2YocykmJihpLnB1c2gocyksZVtzLmlkXT0hMCl9cmV0dXJue3BsdWdpbnM6aSxsb2NhbElkczplfX0oaSk7cmV0dXJuITEhPT1zfHxlP2Z1bmN0aW9uKHQse3BsdWdpbnM6ZSxsb2NhbElkczppfSxzLG4pe2NvbnN0IG89W10sYT10LmdldENvbnRleHQoKTtmb3IoY29uc3QgciBvZiBlKXtjb25zdCBlPXIuaWQsbD1ubihzW2VdLG4pO251bGwhPT1sJiZvLnB1c2goe3BsdWdpbjpyLG9wdGlvbnM6b24odC5jb25maWcse3BsdWdpbjpyLGxvY2FsOmlbZV19LGwsYSl9KX1yZXR1cm4gb30odCxuLHMsZSk6W119X25vdGlmeVN0YXRlQ2hhbmdlcyh0KXtjb25zdCBlPXRoaXMuX29sZENhY2hlfHxbXSxpPXRoaXMuX2NhY2hlLHM9KHQsZSk9PnQuZmlsdGVyKCh0PT4hZS5zb21lKChlPT50LnBsdWdpbi5pZD09PWUucGx1Z2luLmlkKSkpKTt0aGlzLl9ub3RpZnkocyhlLGkpLHQsInN0b3AiKSx0aGlzLl9ub3RpZnkocyhpLGUpLHQsInN0YXJ0Iil9fWZ1bmN0aW9uIG5uKHQsZSl7cmV0dXJuIGV8fCExIT09dD8hMD09PXQ\/e306dDpudWxsfWZ1bmN0aW9uIG9uKHQse3BsdWdpbjplLGxvY2FsOml9LHMsbil7Y29uc3Qgbz10LnBsdWdpblNjb3BlS2V5cyhlKSxhPXQuZ2V0T3B0aW9uU2NvcGVzKHMsbyk7cmV0dXJuIGkmJmUuZGVmYXVsdHMmJmEucHVzaChlLmRlZmF1bHRzKSx0LmNyZWF0ZVJlc29sdmVyKGEsbixbIiJdLHtzY3JpcHRhYmxlOiExLGluZGV4YWJsZTohMSxhbGxLZXlzOiEwfSl9ZnVuY3Rpb24gYW4odCxlKXtjb25zdCBpPXVlLmRhdGFzZXRzW3RdfHx7fTtyZXR1cm4oKGUuZGF0YXNldHN8fHt9KVt0XXx8e30pLmluZGV4QXhpc3x8ZS5pbmRleEF4aXN8fGkuaW5kZXhBeGlzfHwieCJ9ZnVuY3Rpb24gcm4odCl7aWYoIngiPT09dHx8InkiPT09dHx8InIiPT09dClyZXR1cm4gdH1mdW5jdGlvbiBsbih0LC4uLmUpe2lmKHJuKHQpKXJldHVybiB0O2Zvcihjb25zdCBzIG9mIGUpe2NvbnN0IGU9cy5heGlzfHwoInRvcCI9PT0oaT1zLnBvc2l0aW9uKXx8ImJvdHRvbSI9PT1pPyJ4IjoibGVmdCI9PT1pfHwicmlnaHQiPT09aT8ieSI6dm9pZCAwKXx8dC5sZW5ndGg+MSYmcm4odFswXS50b0xvd2VyQ2FzZSgpKTtpZihlKXJldHVybiBlfXZhciBpO3Rocm93IG5ldyBFcnJvcihgQ2Fubm90IGRldGVybWluZSB0eXBlIG9mICcke3R9JyBheGlzLiBQbGVhc2UgcHJvdmlkZSAnYXhpcycgb3IgJ3Bvc2l0aW9uJyBvcHRpb24uYCl9ZnVuY3Rpb24gaG4odCxlLGkpe2lmKGlbZSsiQXhpc0lEIl09PT10KXJldHVybntheGlzOmV9fWZ1bmN0aW9uIGNuKHQsZSl7Y29uc3QgaT1yZVt0LnR5cGVdfHx7c2NhbGVzOnt9fSxzPWUuc2NhbGVzfHx7fSxuPWFuKHQudHlwZSxlKSxhPU9iamVjdC5jcmVhdGUobnVsbCk7cmV0dXJuIE9iamVjdC5rZXlzKHMpLmZvckVhY2goKGU9Pntjb25zdCByPXNbZV07aWYoIW8ocikpcmV0dXJuIGNvbnNvbGUuZXJyb3IoYEludmFsaWQgc2NhbGUgY29uZmlndXJhdGlvbiBmb3Igc2NhbGU6ICR7ZX1gKTtpZihyLl9wcm94eSlyZXR1cm4gY29uc29sZS53YXJuKGBJZ25vcmluZyByZXNvbHZlciBwYXNzZWQgYXMgb3B0aW9ucyBmb3Igc2NhbGU6ICR7ZX1gKTtjb25zdCBsPWxuKGUscixmdW5jdGlvbih0LGUpe2lmKGUuZGF0YSYmZS5kYXRhLmRhdGFzZXRzKXtjb25zdCBpPWUuZGF0YS5kYXRhc2V0cy5maWx0ZXIoKGU9PmUueEF4aXNJRD09PXR8fGUueUF4aXNJRD09PXQpKTtpZihpLmxlbmd0aClyZXR1cm4gaG4odCwieCIsaVswXSl8fGhuKHQsInkiLGlbMF0pfXJldHVybnt9fShlLHQpLHVlLnNjYWxlc1tyLnR5cGVdKSxoPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQ9PT1lPyJfaW5kZXhfIjoiX3ZhbHVlXyJ9KGwsbiksYz1pLnNjYWxlc3x8e307YVtlXT14KE9iamVjdC5jcmVhdGUobnVsbCksW3theGlzOmx9LHIsY1tsXSxjW2hdXSl9KSksdC5kYXRhLmRhdGFzZXRzLmZvckVhY2goKGk9Pntjb25zdCBuPWkudHlwZXx8dC50eXBlLG89aS5pbmRleEF4aXN8fGFuKG4sZSkscj0ocmVbbl18fHt9KS5zY2FsZXN8fHt9O09iamVjdC5rZXlzKHIpLmZvckVhY2goKHQ9Pntjb25zdCBlPWZ1bmN0aW9uKHQsZSl7bGV0IGk9dDtyZXR1cm4iX2luZGV4XyI9PT10P2k9ZToiX3ZhbHVlXyI9PT10JiYoaT0ieCI9PT1lPyJ5IjoieCIpLGl9KHQsbyksbj1pW2UrIkF4aXNJRCJdfHxlO2Fbbl09YVtuXXx8T2JqZWN0LmNyZWF0ZShudWxsKSx4KGFbbl0sW3theGlzOmV9LHNbbl0sclt0XV0pfSkpfSkpLE9iamVjdC5rZXlzKGEpLmZvckVhY2goKHQ9Pntjb25zdCBlPWFbdF07eChlLFt1ZS5zY2FsZXNbZS50eXBlXSx1ZS5zY2FsZV0pfSkpLGF9ZnVuY3Rpb24gZG4odCl7Y29uc3QgZT10Lm9wdGlvbnN8fCh0Lm9wdGlvbnM9e30pO2UucGx1Z2lucz1sKGUucGx1Z2lucyx7fSksZS5zY2FsZXM9Y24odCxlKX1mdW5jdGlvbiB1bih0KXtyZXR1cm4odD10fHx7fSkuZGF0YXNldHM9dC5kYXRhc2V0c3x8W10sdC5sYWJlbHM9dC5sYWJlbHN8fFtdLHR9Y29uc3QgZm49bmV3IE1hcCxnbj1uZXcgU2V0O2Z1bmN0aW9uIHBuKHQsZSl7bGV0IGk9Zm4uZ2V0KHQpO3JldHVybiBpfHwoaT1lKCksZm4uc2V0KHQsaSksZ24uYWRkKGkpKSxpfWNvbnN0IG1uPSh0LGUsaSk9Pntjb25zdCBzPU0oZSxpKTt2b2lkIDAhPT1zJiZ0LmFkZChzKX07Y2xhc3MgYm57Y29uc3RydWN0b3IodCl7dGhpcy5fY29uZmlnPWZ1bmN0aW9uKHQpe3JldHVybih0PXR8fHt9KS5kYXRhPXVuKHQuZGF0YSksZG4odCksdH0odCksdGhpcy5fc2NvcGVDYWNoZT1uZXcgTWFwLHRoaXMuX3Jlc29sdmVyQ2FjaGU9bmV3IE1hcH1nZXQgcGxhdGZvcm0oKXtyZXR1cm4gdGhpcy5fY29uZmlnLnBsYXRmb3JtfWdldCB0eXBlKCl7cmV0dXJuIHRoaXMuX2NvbmZpZy50eXBlfXNldCB0eXBlKHQpe3RoaXMuX2NvbmZpZy50eXBlPXR9Z2V0IGRhdGEoKXtyZXR1cm4gdGhpcy5fY29uZmlnLmRhdGF9c2V0IGRhdGEodCl7dGhpcy5fY29uZmlnLmRhdGE9dW4odCl9Z2V0IG9wdGlvbnMoKXtyZXR1cm4gdGhpcy5fY29uZmlnLm9wdGlvbnN9c2V0IG9wdGlvbnModCl7dGhpcy5fY29uZmlnLm9wdGlvbnM9dH1nZXQgcGx1Z2lucygpe3JldHVybiB0aGlzLl9jb25maWcucGx1Z2luc311cGRhdGUoKXtjb25zdCB0PXRoaXMuX2NvbmZpZzt0aGlzLmNsZWFyQ2FjaGUoKSxkbih0KX1jbGVhckNhY2hlKCl7dGhpcy5fc2NvcGVDYWNoZS5jbGVhcigpLHRoaXMuX3Jlc29sdmVyQ2FjaGUuY2xlYXIoKX1kYXRhc2V0U2NvcGVLZXlzKHQpe3JldHVybiBwbih0LCgoKT0+W1tgZGF0YXNldHMuJHt0fWAsIiJdXSkpfWRhdGFzZXRBbmltYXRpb25TY29wZUtleXModCxlKXtyZXR1cm4gcG4oYCR7dH0udHJhbnNpdGlvbi4ke2V9YCwoKCk9PltbYGRhdGFzZXRzLiR7dH0udHJhbnNpdGlvbnMuJHtlfWAsYHRyYW5zaXRpb25zLiR7ZX1gXSxbYGRhdGFzZXRzLiR7dH1gLCIiXV0pKX1kYXRhc2V0RWxlbWVudFNjb3BlS2V5cyh0LGUpe3JldHVybiBwbihgJHt0fS0ke2V9YCwoKCk9PltbYGRhdGFzZXRzLiR7dH0uZWxlbWVudHMuJHtlfWAsYGRhdGFzZXRzLiR7dH1gLGBlbGVtZW50cy4ke2V9YCwiIl1dKSl9cGx1Z2luU2NvcGVLZXlzKHQpe2NvbnN0IGU9dC5pZDtyZXR1cm4gcG4oYCR7dGhpcy50eXBlfS1wbHVnaW4tJHtlfWAsKCgpPT5bW2BwbHVnaW5zLiR7ZX1gLC4uLnQuYWRkaXRpb25hbE9wdGlvblNjb3Blc3x8W11dXSkpfV9jYWNoZWRTY29wZXModCxlKXtjb25zdCBpPXRoaXMuX3Njb3BlQ2FjaGU7bGV0IHM9aS5nZXQodCk7cmV0dXJuIHMmJiFlfHwocz1uZXcgTWFwLGkuc2V0KHQscykpLHN9Z2V0T3B0aW9uU2NvcGVzKHQsZSxpKXtjb25zdHtvcHRpb25zOnMsdHlwZTpufT10aGlzLG89dGhpcy5fY2FjaGVkU2NvcGVzKHQsaSksYT1vLmdldChlKTtpZihhKXJldHVybiBhO2NvbnN0IHI9bmV3IFNldDtlLmZvckVhY2goKGU9Pnt0JiYoci5hZGQodCksZS5mb3JFYWNoKChlPT5tbihyLHQsZSkpKSksZS5mb3JFYWNoKCh0PT5tbihyLHMsdCkpKSxlLmZvckVhY2goKHQ9Pm1uKHIscmVbbl18fHt9LHQpKSksZS5mb3JFYWNoKCh0PT5tbihyLHVlLHQpKSksZS5mb3JFYWNoKCh0PT5tbihyLGxlLHQpKSl9KSk7Y29uc3QgbD1BcnJheS5mcm9tKHIpO3JldHVybiAwPT09bC5sZW5ndGgmJmwucHVzaChPYmplY3QuY3JlYXRlKG51bGwpKSxnbi5oYXMoZSkmJm8uc2V0KGUsbCksbH1jaGFydE9wdGlvblNjb3Blcygpe2NvbnN0e29wdGlvbnM6dCx0eXBlOmV9PXRoaXM7cmV0dXJuW3QscmVbZV18fHt9LHVlLmRhdGFzZXRzW2VdfHx7fSx7dHlwZTplfSx1ZSxsZV19cmVzb2x2ZU5hbWVkT3B0aW9ucyh0LGUsaSxzPVsiIl0pe2NvbnN0IG89eyRzaGFyZWQ6ITB9LHtyZXNvbHZlcjphLHN1YlByZWZpeGVzOnJ9PXhuKHRoaXMuX3Jlc29sdmVyQ2FjaGUsdCxzKTtsZXQgbD1hO2lmKGZ1bmN0aW9uKHQsZSl7Y29uc3R7aXNTY3JpcHRhYmxlOmksaXNJbmRleGFibGU6c309WWUodCk7Zm9yKGNvbnN0IG8gb2YgZSl7Y29uc3QgZT1pKG8pLGE9cyhvKSxyPShhfHxlKSYmdFtvXTtpZihlJiYoUyhyKXx8X24ocikpfHxhJiZuKHIpKXJldHVybiEwfXJldHVybiExfShhLGUpKXtvLiRzaGFyZWQ9ITE7bD0kZShhLGk9UyhpKT9pKCk6aSx0aGlzLmNyZWF0ZVJlc29sdmVyKHQsaSxyKSl9Zm9yKGNvbnN0IHQgb2YgZSlvW3RdPWxbdF07cmV0dXJuIG99Y3JlYXRlUmVzb2x2ZXIodCxlLGk9WyIiXSxzKXtjb25zdHtyZXNvbHZlcjpufT14bih0aGlzLl9yZXNvbHZlckNhY2hlLHQsaSk7cmV0dXJuIG8oZSk\/JGUobixlLHZvaWQgMCxzKTpufX1mdW5jdGlvbiB4bih0LGUsaSl7bGV0IHM9dC5nZXQoZSk7c3x8KHM9bmV3IE1hcCx0LnNldChlLHMpKTtjb25zdCBuPWkuam9pbigpO2xldCBvPXMuZ2V0KG4pO2lmKCFvKXtvPXtyZXNvbHZlcjpqZShlLGkpLHN1YlByZWZpeGVzOmkuZmlsdGVyKCh0PT4hdC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCJob3ZlciIpKSl9LHMuc2V0KG4sbyl9cmV0dXJuIG99Y29uc3QgX249dD0+byh0KSYmT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModCkuc29tZSgoZT0+Uyh0W2VdKSkpO2NvbnN0IHluPVsidG9wIiwiYm90dG9tIiwibGVmdCIsInJpZ2h0IiwiY2hhcnRBcmVhIl07ZnVuY3Rpb24gdm4odCxlKXtyZXR1cm4idG9wIj09PXR8fCJib3R0b20iPT09dHx8LTE9PT15bi5pbmRleE9mKHQpJiYieCI9PT1lfWZ1bmN0aW9uIE1uKHQsZSl7cmV0dXJuIGZ1bmN0aW9uKGkscyl7cmV0dXJuIGlbdF09PT1zW3RdP2lbZV0tc1tlXTppW3RdLXNbdF19fWZ1bmN0aW9uIHduKHQpe2NvbnN0IGU9dC5jaGFydCxpPWUub3B0aW9ucy5hbmltYXRpb247ZS5ub3RpZnlQbHVnaW5zKCJhZnRlclJlbmRlciIpLGQoaSYmaS5vbkNvbXBsZXRlLFt0XSxlKX1mdW5jdGlvbiBrbih0KXtjb25zdCBlPXQuY2hhcnQsaT1lLm9wdGlvbnMuYW5pbWF0aW9uO2QoaSYmaS5vblByb2dyZXNzLFt0XSxlKX1mdW5jdGlvbiBTbih0KXtyZXR1cm4gZmUoKSYmInN0cmluZyI9PXR5cGVvZiB0P3Q9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodCk6dCYmdC5sZW5ndGgmJih0PXRbMF0pLHQmJnQuY2FudmFzJiYodD10LmNhbnZhcyksdH1jb25zdCBQbj17fSxEbj10PT57Y29uc3QgZT1Tbih0KTtyZXR1cm4gT2JqZWN0LnZhbHVlcyhQbikuZmlsdGVyKCh0PT50LmNhbnZhcz09PWUpKS5wb3AoKX07ZnVuY3Rpb24gQ24odCxlLGkpe2NvbnN0IHM9T2JqZWN0LmtleXModCk7Zm9yKGNvbnN0IG4gb2Ygcyl7Y29uc3Qgcz0rbjtpZihzPj1lKXtjb25zdCBvPXRbbl07ZGVsZXRlIHRbbl0sKGk+MHx8cz5lKSYmKHRbcytpXT1vKX19fWZ1bmN0aW9uIE9uKHQsZSxpKXtyZXR1cm4gdC5vcHRpb25zLmNsaXA\/dFtpXTplW2ldfWNsYXNzIEFue3N0YXRpYyBkZWZhdWx0cz11ZTtzdGF0aWMgaW5zdGFuY2VzPVBuO3N0YXRpYyBvdmVycmlkZXM9cmU7c3RhdGljIHJlZ2lzdHJ5PWVuO3N0YXRpYyB2ZXJzaW9uPSI0LjQuMSI7c3RhdGljIGdldENoYXJ0PURuO3N0YXRpYyByZWdpc3RlciguLi50KXtlbi5hZGQoLi4udCksVG4oKX1zdGF0aWMgdW5yZWdpc3RlciguLi50KXtlbi5yZW1vdmUoLi4udCksVG4oKX1jb25zdHJ1Y3Rvcih0LGUpe2NvbnN0IHM9dGhpcy5jb25maWc9bmV3IGJuKGUpLG49U24odCksbz1EbihuKTtpZihvKXRocm93IG5ldyBFcnJvcigiQ2FudmFzIGlzIGFscmVhZHkgaW4gdXNlLiBDaGFydCB3aXRoIElEICciK28uaWQrIicgbXVzdCBiZSBkZXN0cm95ZWQgYmVmb3JlIHRoZSBjYW52YXMgd2l0aCBJRCAnIitvLmNhbnZhcy5pZCsiJyBjYW4gYmUgcmV1c2VkLiIpO2NvbnN0IGE9cy5jcmVhdGVSZXNvbHZlcihzLmNoYXJ0T3B0aW9uU2NvcGVzKCksdGhpcy5nZXRDb250ZXh0KCkpO3RoaXMucGxhdGZvcm09bmV3KHMucGxhdGZvcm18fGtzKG4pKSx0aGlzLnBsYXRmb3JtLnVwZGF0ZUNvbmZpZyhzKTtjb25zdCByPXRoaXMucGxhdGZvcm0uYWNxdWlyZUNvbnRleHQobixhLmFzcGVjdFJhdGlvKSxsPXImJnIuY2FudmFzLGg9bCYmbC5oZWlnaHQsYz1sJiZsLndpZHRoO3RoaXMuaWQ9aSgpLHRoaXMuY3R4PXIsdGhpcy5jYW52YXM9bCx0aGlzLndpZHRoPWMsdGhpcy5oZWlnaHQ9aCx0aGlzLl9vcHRpb25zPWEsdGhpcy5fYXNwZWN0UmF0aW89dGhpcy5hc3BlY3RSYXRpbyx0aGlzLl9sYXllcnM9W10sdGhpcy5fbWV0YXNldHM9W10sdGhpcy5fc3RhY2tzPXZvaWQgMCx0aGlzLmJveGVzPVtdLHRoaXMuY3VycmVudERldmljZVBpeGVsUmF0aW89dm9pZCAwLHRoaXMuY2hhcnRBcmVhPXZvaWQgMCx0aGlzLl9hY3RpdmU9W10sdGhpcy5fbGFzdEV2ZW50PXZvaWQgMCx0aGlzLl9saXN0ZW5lcnM9e30sdGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycz12b2lkIDAsdGhpcy5fc29ydGVkTWV0YXNldHM9W10sdGhpcy5zY2FsZXM9e30sdGhpcy5fcGx1Z2lucz1uZXcgc24sdGhpcy4kcHJveGllcz17fSx0aGlzLl9oaWRkZW5JbmRpY2VzPXt9LHRoaXMuYXR0YWNoZWQ9ITEsdGhpcy5fYW5pbWF0aW9uc0Rpc2FibGVkPXZvaWQgMCx0aGlzLiRjb250ZXh0PXZvaWQgMCx0aGlzLl9kb1Jlc2l6ZT1kdCgodD0+dGhpcy51cGRhdGUodCkpLGEucmVzaXplRGVsYXl8fDApLHRoaXMuX2RhdGFDaGFuZ2VzPVtdLFBuW3RoaXMuaWRdPXRoaXMsciYmbD8oeHQubGlzdGVuKHRoaXMsImNvbXBsZXRlIix3bikseHQubGlzdGVuKHRoaXMsInByb2dyZXNzIixrbiksdGhpcy5faW5pdGlhbGl6ZSgpLHRoaXMuYXR0YWNoZWQmJnRoaXMudXBkYXRlKCkpOmNvbnNvbGUuZXJyb3IoIkZhaWxlZCB0byBjcmVhdGUgY2hhcnQ6IGNhbid0IGFjcXVpcmUgY29udGV4dCBmcm9tIHRoZSBnaXZlbiBpdGVtIil9Z2V0IGFzcGVjdFJhdGlvKCl7Y29uc3R7b3B0aW9uczp7YXNwZWN0UmF0aW86dCxtYWludGFpbkFzcGVjdFJhdGlvOmV9LHdpZHRoOmksaGVpZ2h0Om4sX2FzcGVjdFJhdGlvOm99PXRoaXM7cmV0dXJuIHModCk\/ZSYmbz9vOm4\/aS9uOm51bGw6dH1nZXQgZGF0YSgpe3JldHVybiB0aGlzLmNvbmZpZy5kYXRhfXNldCBkYXRhKHQpe3RoaXMuY29uZmlnLmRhdGE9dH1nZXQgb3B0aW9ucygpe3JldHVybiB0aGlzLl9vcHRpb25zfXNldCBvcHRpb25zKHQpe3RoaXMuY29uZmlnLm9wdGlvbnM9dH1nZXQgcmVnaXN0cnkoKXtyZXR1cm4gZW59X2luaXRpYWxpemUoKXtyZXR1cm4gdGhpcy5ub3RpZnlQbHVnaW5zKCJiZWZvcmVJbml0IiksdGhpcy5vcHRpb25zLnJlc3BvbnNpdmU\/dGhpcy5yZXNpemUoKTprZSh0aGlzLHRoaXMub3B0aW9ucy5kZXZpY2VQaXhlbFJhdGlvKSx0aGlzLmJpbmRFdmVudHMoKSx0aGlzLm5vdGlmeVBsdWdpbnMoImFmdGVySW5pdCIpLHRoaXN9Y2xlYXIoKXtyZXR1cm4gVGUodGhpcy5jYW52YXMsdGhpcy5jdHgpLHRoaXN9c3RvcCgpe3JldHVybiB4dC5zdG9wKHRoaXMpLHRoaXN9cmVzaXplKHQsZSl7eHQucnVubmluZyh0aGlzKT90aGlzLl9yZXNpemVCZWZvcmVEcmF3PXt3aWR0aDp0LGhlaWdodDplfTp0aGlzLl9yZXNpemUodCxlKX1fcmVzaXplKHQsZSl7Y29uc3QgaT10aGlzLm9wdGlvbnMscz10aGlzLmNhbnZhcyxuPWkubWFpbnRhaW5Bc3BlY3RSYXRpbyYmdGhpcy5hc3BlY3RSYXRpbyxvPXRoaXMucGxhdGZvcm0uZ2V0TWF4aW11bVNpemUocyx0LGUsbiksYT1pLmRldmljZVBpeGVsUmF0aW98fHRoaXMucGxhdGZvcm0uZ2V0RGV2aWNlUGl4ZWxSYXRpbygpLHI9dGhpcy53aWR0aD8icmVzaXplIjoiYXR0YWNoIjt0aGlzLndpZHRoPW8ud2lkdGgsdGhpcy5oZWlnaHQ9by5oZWlnaHQsdGhpcy5fYXNwZWN0UmF0aW89dGhpcy5hc3BlY3RSYXRpbyxrZSh0aGlzLGEsITApJiYodGhpcy5ub3RpZnlQbHVnaW5zKCJyZXNpemUiLHtzaXplOm99KSxkKGkub25SZXNpemUsW3RoaXMsb10sdGhpcyksdGhpcy5hdHRhY2hlZCYmdGhpcy5fZG9SZXNpemUocikmJnRoaXMucmVuZGVyKCkpfWVuc3VyZVNjYWxlc0hhdmVJRHMoKXt1KHRoaXMub3B0aW9ucy5zY2FsZXN8fHt9LCgodCxlKT0+e3QuaWQ9ZX0pKX1idWlsZE9yVXBkYXRlU2NhbGVzKCl7Y29uc3QgdD10aGlzLm9wdGlvbnMsZT10LnNjYWxlcyxpPXRoaXMuc2NhbGVzLHM9T2JqZWN0LmtleXMoaSkucmVkdWNlKCgodCxlKT0+KHRbZV09ITEsdCkpLHt9KTtsZXQgbj1bXTtlJiYobj1uLmNvbmNhdChPYmplY3Qua2V5cyhlKS5tYXAoKHQ9Pntjb25zdCBpPWVbdF0scz1sbih0LGkpLG49InIiPT09cyxvPSJ4Ij09PXM7cmV0dXJue29wdGlvbnM6aSxkcG9zaXRpb246bj8iY2hhcnRBcmVhIjpvPyJib3R0b20iOiJsZWZ0IixkdHlwZTpuPyJyYWRpYWxMaW5lYXIiOm8\/ImNhdGVnb3J5IjoibGluZWFyIn19KSkpKSx1KG4sKGU9Pntjb25zdCBuPWUub3B0aW9ucyxvPW4uaWQsYT1sbihvLG4pLHI9bChuLnR5cGUsZS5kdHlwZSk7dm9pZCAwIT09bi5wb3NpdGlvbiYmdm4obi5wb3NpdGlvbixhKT09PXZuKGUuZHBvc2l0aW9uKXx8KG4ucG9zaXRpb249ZS5kcG9zaXRpb24pLHNbb109ITA7bGV0IGg9bnVsbDtpZihvIGluIGkmJmlbb10udHlwZT09PXIpaD1pW29dO2Vsc2V7aD1uZXcoZW4uZ2V0U2NhbGUocikpKHtpZDpvLHR5cGU6cixjdHg6dGhpcy5jdHgsY2hhcnQ6dGhpc30pLGlbaC5pZF09aH1oLmluaXQobix0KX0pKSx1KHMsKCh0LGUpPT57dHx8ZGVsZXRlIGlbZV19KSksdShpLCh0PT57YXMuY29uZmlndXJlKHRoaXMsdCx0Lm9wdGlvbnMpLGFzLmFkZEJveCh0aGlzLHQpfSkpfV91cGRhdGVNZXRhc2V0cygpe2NvbnN0IHQ9dGhpcy5fbWV0YXNldHMsZT10aGlzLmRhdGEuZGF0YXNldHMubGVuZ3RoLGk9dC5sZW5ndGg7aWYodC5zb3J0KCgodCxlKT0+dC5pbmRleC1lLmluZGV4KSksaT5lKXtmb3IobGV0IHQ9ZTt0PGk7Kyt0KXRoaXMuX2Rlc3Ryb3lEYXRhc2V0TWV0YSh0KTt0LnNwbGljZShlLGktZSl9dGhpcy5fc29ydGVkTWV0YXNldHM9dC5zbGljZSgwKS5zb3J0KE1uKCJvcmRlciIsImluZGV4IikpfV9yZW1vdmVVbnJlZmVyZW5jZWRNZXRhc2V0cygpe2NvbnN0e19tZXRhc2V0czp0LGRhdGE6e2RhdGFzZXRzOmV9fT10aGlzO3QubGVuZ3RoPmUubGVuZ3RoJiZkZWxldGUgdGhpcy5fc3RhY2tzLHQuZm9yRWFjaCgoKHQsaSk9PnswPT09ZS5maWx0ZXIoKGU9PmU9PT10Ll9kYXRhc2V0KSkubGVuZ3RoJiZ0aGlzLl9kZXN0cm95RGF0YXNldE1ldGEoaSl9KSl9YnVpbGRPclVwZGF0ZUNvbnRyb2xsZXJzKCl7Y29uc3QgdD1bXSxlPXRoaXMuZGF0YS5kYXRhc2V0cztsZXQgaSxzO2Zvcih0aGlzLl9yZW1vdmVVbnJlZmVyZW5jZWRNZXRhc2V0cygpLGk9MCxzPWUubGVuZ3RoO2k8cztpKyspe2NvbnN0IHM9ZVtpXTtsZXQgbj10aGlzLmdldERhdGFzZXRNZXRhKGkpO2NvbnN0IG89cy50eXBlfHx0aGlzLmNvbmZpZy50eXBlO2lmKG4udHlwZSYmbi50eXBlIT09byYmKHRoaXMuX2Rlc3Ryb3lEYXRhc2V0TWV0YShpKSxuPXRoaXMuZ2V0RGF0YXNldE1ldGEoaSkpLG4udHlwZT1vLG4uaW5kZXhBeGlzPXMuaW5kZXhBeGlzfHxhbihvLHRoaXMub3B0aW9ucyksbi5vcmRlcj1zLm9yZGVyfHwwLG4uaW5kZXg9aSxuLmxhYmVsPSIiK3MubGFiZWwsbi52aXNpYmxlPXRoaXMuaXNEYXRhc2V0VmlzaWJsZShpKSxuLmNvbnRyb2xsZXIpbi5jb250cm9sbGVyLnVwZGF0ZUluZGV4KGkpLG4uY29udHJvbGxlci5saW5rU2NhbGVzKCk7ZWxzZXtjb25zdCBlPWVuLmdldENvbnRyb2xsZXIobykse2RhdGFzZXRFbGVtZW50VHlwZTpzLGRhdGFFbGVtZW50VHlwZTphfT11ZS5kYXRhc2V0c1tvXTtPYmplY3QuYXNzaWduKGUse2RhdGFFbGVtZW50VHlwZTplbi5nZXRFbGVtZW50KGEpLGRhdGFzZXRFbGVtZW50VHlwZTpzJiZlbi5nZXRFbGVtZW50KHMpfSksbi5jb250cm9sbGVyPW5ldyBlKHRoaXMsaSksdC5wdXNoKG4uY29udHJvbGxlcil9fXJldHVybiB0aGlzLl91cGRhdGVNZXRhc2V0cygpLHR9X3Jlc2V0RWxlbWVudHMoKXt1KHRoaXMuZGF0YS5kYXRhc2V0cywoKHQsZSk9Pnt0aGlzLmdldERhdGFzZXRNZXRhKGUpLmNvbnRyb2xsZXIucmVzZXQoKX0pLHRoaXMpfXJlc2V0KCl7dGhpcy5fcmVzZXRFbGVtZW50cygpLHRoaXMubm90aWZ5UGx1Z2lucygicmVzZXQiKX11cGRhdGUodCl7Y29uc3QgZT10aGlzLmNvbmZpZztlLnVwZGF0ZSgpO2NvbnN0IGk9dGhpcy5fb3B0aW9ucz1lLmNyZWF0ZVJlc29sdmVyKGUuY2hhcnRPcHRpb25TY29wZXMoKSx0aGlzLmdldENvbnRleHQoKSkscz10aGlzLl9hbmltYXRpb25zRGlzYWJsZWQ9IWkuYW5pbWF0aW9uO2lmKHRoaXMuX3VwZGF0ZVNjYWxlcygpLHRoaXMuX2NoZWNrRXZlbnRCaW5kaW5ncygpLHRoaXMuX3VwZGF0ZUhpZGRlbkluZGljZXMoKSx0aGlzLl9wbHVnaW5zLmludmFsaWRhdGUoKSwhMT09PXRoaXMubm90aWZ5UGx1Z2lucygiYmVmb3JlVXBkYXRlIix7bW9kZTp0LGNhbmNlbGFibGU6ITB9KSlyZXR1cm47Y29uc3Qgbj10aGlzLmJ1aWxkT3JVcGRhdGVDb250cm9sbGVycygpO3RoaXMubm90aWZ5UGx1Z2lucygiYmVmb3JlRWxlbWVudHNVcGRhdGUiKTtsZXQgbz0wO2ZvcihsZXQgdD0wLGU9dGhpcy5kYXRhLmRhdGFzZXRzLmxlbmd0aDt0PGU7dCsrKXtjb25zdHtjb250cm9sbGVyOmV9PXRoaXMuZ2V0RGF0YXNldE1ldGEodCksaT0hcyYmLTE9PT1uLmluZGV4T2YoZSk7ZS5idWlsZE9yVXBkYXRlRWxlbWVudHMoaSksbz1NYXRoLm1heCgrZS5nZXRNYXhPdmVyZmxvdygpLG8pfW89dGhpcy5fbWluUGFkZGluZz1pLmxheW91dC5hdXRvUGFkZGluZz9vOjAsdGhpcy5fdXBkYXRlTGF5b3V0KG8pLHN8fHUobiwodD0+e3QucmVzZXQoKX0pKSx0aGlzLl91cGRhdGVEYXRhc2V0cyh0KSx0aGlzLm5vdGlmeVBsdWdpbnMoImFmdGVyVXBkYXRlIix7bW9kZTp0fSksdGhpcy5fbGF5ZXJzLnNvcnQoTW4oInoiLCJfaWR4IikpO2NvbnN0e19hY3RpdmU6YSxfbGFzdEV2ZW50OnJ9PXRoaXM7cj90aGlzLl9ldmVudEhhbmRsZXIociwhMCk6YS5sZW5ndGgmJnRoaXMuX3VwZGF0ZUhvdmVyU3R5bGVzKGEsYSwhMCksdGhpcy5yZW5kZXIoKX1fdXBkYXRlU2NhbGVzKCl7dSh0aGlzLnNjYWxlcywodD0+e2FzLnJlbW92ZUJveCh0aGlzLHQpfSkpLHRoaXMuZW5zdXJlU2NhbGVzSGF2ZUlEcygpLHRoaXMuYnVpbGRPclVwZGF0ZVNjYWxlcygpfV9jaGVja0V2ZW50QmluZGluZ3MoKXtjb25zdCB0PXRoaXMub3B0aW9ucyxlPW5ldyBTZXQoT2JqZWN0LmtleXModGhpcy5fbGlzdGVuZXJzKSksaT1uZXcgU2V0KHQuZXZlbnRzKTtQKGUsaSkmJiEhdGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycz09PXQucmVzcG9uc2l2ZXx8KHRoaXMudW5iaW5kRXZlbnRzKCksdGhpcy5iaW5kRXZlbnRzKCkpfV91cGRhdGVIaWRkZW5JbmRpY2VzKCl7Y29uc3R7X2hpZGRlbkluZGljZXM6dH09dGhpcyxlPXRoaXMuX2dldFVuaWZvcm1EYXRhQ2hhbmdlcygpfHxbXTtmb3IoY29uc3R7bWV0aG9kOmksc3RhcnQ6cyxjb3VudDpufW9mIGUpe0NuKHQscywiX3JlbW92ZUVsZW1lbnRzIj09PWk\/LW46bil9fV9nZXRVbmlmb3JtRGF0YUNoYW5nZXMoKXtjb25zdCB0PXRoaXMuX2RhdGFDaGFuZ2VzO2lmKCF0fHwhdC5sZW5ndGgpcmV0dXJuO3RoaXMuX2RhdGFDaGFuZ2VzPVtdO2NvbnN0IGU9dGhpcy5kYXRhLmRhdGFzZXRzLmxlbmd0aCxpPWU9Pm5ldyBTZXQodC5maWx0ZXIoKHQ9PnRbMF09PT1lKSkubWFwKCgodCxlKT0+ZSsiLCIrdC5zcGxpY2UoMSkuam9pbigiLCIpKSkpLHM9aSgwKTtmb3IobGV0IHQ9MTt0PGU7dCsrKWlmKCFQKHMsaSh0KSkpcmV0dXJuO3JldHVybiBBcnJheS5mcm9tKHMpLm1hcCgodD0+dC5zcGxpdCgiLCIpKSkubWFwKCh0PT4oe21ldGhvZDp0WzFdLHN0YXJ0Oit0WzJdLGNvdW50Oit0WzNdfSkpKX1fdXBkYXRlTGF5b3V0KHQpe2lmKCExPT09dGhpcy5ub3RpZnlQbHVnaW5zKCJiZWZvcmVMYXlvdXQiLHtjYW5jZWxhYmxlOiEwfSkpcmV0dXJuO2FzLnVwZGF0ZSh0aGlzLHRoaXMud2lkdGgsdGhpcy5oZWlnaHQsdCk7Y29uc3QgZT10aGlzLmNoYXJ0QXJlYSxpPWUud2lkdGg8PTB8fGUuaGVpZ2h0PD0wO3RoaXMuX2xheWVycz1bXSx1KHRoaXMuYm94ZXMsKHQ9PntpJiYiY2hhcnRBcmVhIj09PXQucG9zaXRpb258fCh0LmNvbmZpZ3VyZSYmdC5jb25maWd1cmUoKSx0aGlzLl9sYXllcnMucHVzaCguLi50Ll9sYXllcnMoKSkpfSksdGhpcyksdGhpcy5fbGF5ZXJzLmZvckVhY2goKCh0LGUpPT57dC5faWR4PWV9KSksdGhpcy5ub3RpZnlQbHVnaW5zKCJhZnRlckxheW91dCIpfV91cGRhdGVEYXRhc2V0cyh0KXtpZighMSE9PXRoaXMubm90aWZ5UGx1Z2lucygiYmVmb3JlRGF0YXNldHNVcGRhdGUiLHttb2RlOnQsY2FuY2VsYWJsZTohMH0pKXtmb3IobGV0IHQ9MCxlPXRoaXMuZGF0YS5kYXRhc2V0cy5sZW5ndGg7dDxlOysrdCl0aGlzLmdldERhdGFzZXRNZXRhKHQpLmNvbnRyb2xsZXIuY29uZmlndXJlKCk7Zm9yKGxldCBlPTAsaT10aGlzLmRhdGEuZGF0YXNldHMubGVuZ3RoO2U8aTsrK2UpdGhpcy5fdXBkYXRlRGF0YXNldChlLFModCk\/dCh7ZGF0YXNldEluZGV4OmV9KTp0KTt0aGlzLm5vdGlmeVBsdWdpbnMoImFmdGVyRGF0YXNldHNVcGRhdGUiLHttb2RlOnR9KX19X3VwZGF0ZURhdGFzZXQodCxlKXtjb25zdCBpPXRoaXMuZ2V0RGF0YXNldE1ldGEodCkscz17bWV0YTppLGluZGV4OnQsbW9kZTplLGNhbmNlbGFibGU6ITB9OyExIT09dGhpcy5ub3RpZnlQbHVnaW5zKCJiZWZvcmVEYXRhc2V0VXBkYXRlIixzKSYmKGkuY29udHJvbGxlci5fdXBkYXRlKGUpLHMuY2FuY2VsYWJsZT0hMSx0aGlzLm5vdGlmeVBsdWdpbnMoImFmdGVyRGF0YXNldFVwZGF0ZSIscykpfXJlbmRlcigpeyExIT09dGhpcy5ub3RpZnlQbHVnaW5zKCJiZWZvcmVSZW5kZXIiLHtjYW5jZWxhYmxlOiEwfSkmJih4dC5oYXModGhpcyk\/dGhpcy5hdHRhY2hlZCYmIXh0LnJ1bm5pbmcodGhpcykmJnh0LnN0YXJ0KHRoaXMpOih0aGlzLmRyYXcoKSx3bih7Y2hhcnQ6dGhpc30pKSl9ZHJhdygpe2xldCB0O2lmKHRoaXMuX3Jlc2l6ZUJlZm9yZURyYXcpe2NvbnN0e3dpZHRoOnQsaGVpZ2h0OmV9PXRoaXMuX3Jlc2l6ZUJlZm9yZURyYXc7dGhpcy5fcmVzaXplKHQsZSksdGhpcy5fcmVzaXplQmVmb3JlRHJhdz1udWxsfWlmKHRoaXMuY2xlYXIoKSx0aGlzLndpZHRoPD0wfHx0aGlzLmhlaWdodDw9MClyZXR1cm47aWYoITE9PT10aGlzLm5vdGlmeVBsdWdpbnMoImJlZm9yZURyYXciLHtjYW5jZWxhYmxlOiEwfSkpcmV0dXJuO2NvbnN0IGU9dGhpcy5fbGF5ZXJzO2Zvcih0PTA7dDxlLmxlbmd0aCYmZVt0XS56PD0wOysrdCllW3RdLmRyYXcodGhpcy5jaGFydEFyZWEpO2Zvcih0aGlzLl9kcmF3RGF0YXNldHMoKTt0PGUubGVuZ3RoOysrdCllW3RdLmRyYXcodGhpcy5jaGFydEFyZWEpO3RoaXMubm90aWZ5UGx1Z2lucygiYWZ0ZXJEcmF3Iil9X2dldFNvcnRlZERhdGFzZXRNZXRhcyh0KXtjb25zdCBlPXRoaXMuX3NvcnRlZE1ldGFzZXRzLGk9W107bGV0IHMsbjtmb3Iocz0wLG49ZS5sZW5ndGg7czxuOysrcyl7Y29uc3Qgbj1lW3NdO3QmJiFuLnZpc2libGV8fGkucHVzaChuKX1yZXR1cm4gaX1nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCl7cmV0dXJuIHRoaXMuX2dldFNvcnRlZERhdGFzZXRNZXRhcyghMCl9X2RyYXdEYXRhc2V0cygpe2lmKCExPT09dGhpcy5ub3RpZnlQbHVnaW5zKCJiZWZvcmVEYXRhc2V0c0RyYXciLHtjYW5jZWxhYmxlOiEwfSkpcmV0dXJuO2NvbnN0IHQ9dGhpcy5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCk7Zm9yKGxldCBlPXQubGVuZ3RoLTE7ZT49MDstLWUpdGhpcy5fZHJhd0RhdGFzZXQodFtlXSk7dGhpcy5ub3RpZnlQbHVnaW5zKCJhZnRlckRhdGFzZXRzRHJhdyIpfV9kcmF3RGF0YXNldCh0KXtjb25zdCBlPXRoaXMuY3R4LGk9dC5fY2xpcCxzPSFpLmRpc2FibGVkLG49ZnVuY3Rpb24odCxlKXtjb25zdHt4U2NhbGU6aSx5U2NhbGU6c309dDtyZXR1cm4gaSYmcz97bGVmdDpPbihpLGUsImxlZnQiKSxyaWdodDpPbihpLGUsInJpZ2h0IiksdG9wOk9uKHMsZSwidG9wIiksYm90dG9tOk9uKHMsZSwiYm90dG9tIil9OmV9KHQsdGhpcy5jaGFydEFyZWEpLG89e21ldGE6dCxpbmRleDp0LmluZGV4LGNhbmNlbGFibGU6ITB9OyExIT09dGhpcy5ub3RpZnlQbHVnaW5zKCJiZWZvcmVEYXRhc2V0RHJhdyIsbykmJihzJiZJZShlLHtsZWZ0OiExPT09aS5sZWZ0PzA6bi5sZWZ0LWkubGVmdCxyaWdodDohMT09PWkucmlnaHQ\/dGhpcy53aWR0aDpuLnJpZ2h0K2kucmlnaHQsdG9wOiExPT09aS50b3A\/MDpuLnRvcC1pLnRvcCxib3R0b206ITE9PT1pLmJvdHRvbT90aGlzLmhlaWdodDpuLmJvdHRvbStpLmJvdHRvbX0pLHQuY29udHJvbGxlci5kcmF3KCkscyYmemUoZSksby5jYW5jZWxhYmxlPSExLHRoaXMubm90aWZ5UGx1Z2lucygiYWZ0ZXJEYXRhc2V0RHJhdyIsbykpfWlzUG9pbnRJbkFyZWEodCl7cmV0dXJuIFJlKHQsdGhpcy5jaGFydEFyZWEsdGhpcy5fbWluUGFkZGluZyl9Z2V0RWxlbWVudHNBdEV2ZW50Rm9yTW9kZSh0LGUsaSxzKXtjb25zdCBuPVhpLm1vZGVzW2VdO3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiBuP24odGhpcyx0LGkscyk6W119Z2V0RGF0YXNldE1ldGEodCl7Y29uc3QgZT10aGlzLmRhdGEuZGF0YXNldHNbdF0saT10aGlzLl9tZXRhc2V0cztsZXQgcz1pLmZpbHRlcigodD0+dCYmdC5fZGF0YXNldD09PWUpKS5wb3AoKTtyZXR1cm4gc3x8KHM9e3R5cGU6bnVsbCxkYXRhOltdLGRhdGFzZXQ6bnVsbCxjb250cm9sbGVyOm51bGwsaGlkZGVuOm51bGwseEF4aXNJRDpudWxsLHlBeGlzSUQ6bnVsbCxvcmRlcjplJiZlLm9yZGVyfHwwLGluZGV4OnQsX2RhdGFzZXQ6ZSxfcGFyc2VkOltdLF9zb3J0ZWQ6ITF9LGkucHVzaChzKSksc31nZXRDb250ZXh0KCl7cmV0dXJuIHRoaXMuJGNvbnRleHR8fCh0aGlzLiRjb250ZXh0PUNpKG51bGwse2NoYXJ0OnRoaXMsdHlwZToiY2hhcnQifSkpfWdldFZpc2libGVEYXRhc2V0Q291bnQoKXtyZXR1cm4gdGhpcy5nZXRTb3J0ZWRWaXNpYmxlRGF0YXNldE1ldGFzKCkubGVuZ3RofWlzRGF0YXNldFZpc2libGUodCl7Y29uc3QgZT10aGlzLmRhdGEuZGF0YXNldHNbdF07aWYoIWUpcmV0dXJuITE7Y29uc3QgaT10aGlzLmdldERhdGFzZXRNZXRhKHQpO3JldHVybiJib29sZWFuIj09dHlwZW9mIGkuaGlkZGVuPyFpLmhpZGRlbjohZS5oaWRkZW59c2V0RGF0YXNldFZpc2liaWxpdHkodCxlKXt0aGlzLmdldERhdGFzZXRNZXRhKHQpLmhpZGRlbj0hZX10b2dnbGVEYXRhVmlzaWJpbGl0eSh0KXt0aGlzLl9oaWRkZW5JbmRpY2VzW3RdPSF0aGlzLl9oaWRkZW5JbmRpY2VzW3RdfWdldERhdGFWaXNpYmlsaXR5KHQpe3JldHVybiF0aGlzLl9oaWRkZW5JbmRpY2VzW3RdfV91cGRhdGVWaXNpYmlsaXR5KHQsZSxpKXtjb25zdCBzPWk\/InNob3ciOiJoaWRlIixuPXRoaXMuZ2V0RGF0YXNldE1ldGEodCksbz1uLmNvbnRyb2xsZXIuX3Jlc29sdmVBbmltYXRpb25zKHZvaWQgMCxzKTtrKGUpPyhuLmRhdGFbZV0uaGlkZGVuPSFpLHRoaXMudXBkYXRlKCkpOih0aGlzLnNldERhdGFzZXRWaXNpYmlsaXR5KHQsaSksby51cGRhdGUobix7dmlzaWJsZTppfSksdGhpcy51cGRhdGUoKGU9PmUuZGF0YXNldEluZGV4PT09dD9zOnZvaWQgMCkpKX1oaWRlKHQsZSl7dGhpcy5fdXBkYXRlVmlzaWJpbGl0eSh0LGUsITEpfXNob3codCxlKXt0aGlzLl91cGRhdGVWaXNpYmlsaXR5KHQsZSwhMCl9X2Rlc3Ryb3lEYXRhc2V0TWV0YSh0KXtjb25zdCBlPXRoaXMuX21ldGFzZXRzW3RdO2UmJmUuY29udHJvbGxlciYmZS5jb250cm9sbGVyLl9kZXN0cm95KCksZGVsZXRlIHRoaXMuX21ldGFzZXRzW3RdfV9zdG9wKCl7bGV0IHQsZTtmb3IodGhpcy5zdG9wKCkseHQucmVtb3ZlKHRoaXMpLHQ9MCxlPXRoaXMuZGF0YS5kYXRhc2V0cy5sZW5ndGg7dDxlOysrdCl0aGlzLl9kZXN0cm95RGF0YXNldE1ldGEodCl9ZGVzdHJveSgpe3RoaXMubm90aWZ5UGx1Z2lucygiYmVmb3JlRGVzdHJveSIpO2NvbnN0e2NhbnZhczp0LGN0eDplfT10aGlzO3RoaXMuX3N0b3AoKSx0aGlzLmNvbmZpZy5jbGVhckNhY2hlKCksdCYmKHRoaXMudW5iaW5kRXZlbnRzKCksVGUodCxlKSx0aGlzLnBsYXRmb3JtLnJlbGVhc2VDb250ZXh0KGUpLHRoaXMuY2FudmFzPW51bGwsdGhpcy5jdHg9bnVsbCksZGVsZXRlIFBuW3RoaXMuaWRdLHRoaXMubm90aWZ5UGx1Z2lucygiYWZ0ZXJEZXN0cm95Iil9dG9CYXNlNjRJbWFnZSguLi50KXtyZXR1cm4gdGhpcy5jYW52YXMudG9EYXRhVVJMKC4uLnQpfWJpbmRFdmVudHMoKXt0aGlzLmJpbmRVc2VyRXZlbnRzKCksdGhpcy5vcHRpb25zLnJlc3BvbnNpdmU\/dGhpcy5iaW5kUmVzcG9uc2l2ZUV2ZW50cygpOnRoaXMuYXR0YWNoZWQ9ITB9YmluZFVzZXJFdmVudHMoKXtjb25zdCB0PXRoaXMuX2xpc3RlbmVycyxlPXRoaXMucGxhdGZvcm0saT0oaSxzKT0+e2UuYWRkRXZlbnRMaXN0ZW5lcih0aGlzLGkscyksdFtpXT1zfSxzPSh0LGUsaSk9Pnt0Lm9mZnNldFg9ZSx0Lm9mZnNldFk9aSx0aGlzLl9ldmVudEhhbmRsZXIodCl9O3UodGhpcy5vcHRpb25zLmV2ZW50cywodD0+aSh0LHMpKSl9YmluZFJlc3BvbnNpdmVFdmVudHMoKXt0aGlzLl9yZXNwb25zaXZlTGlzdGVuZXJzfHwodGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycz17fSk7Y29uc3QgdD10aGlzLl9yZXNwb25zaXZlTGlzdGVuZXJzLGU9dGhpcy5wbGF0Zm9ybSxpPShpLHMpPT57ZS5hZGRFdmVudExpc3RlbmVyKHRoaXMsaSxzKSx0W2ldPXN9LHM9KGkscyk9Pnt0W2ldJiYoZS5yZW1vdmVFdmVudExpc3RlbmVyKHRoaXMsaSxzKSxkZWxldGUgdFtpXSl9LG49KHQsZSk9Pnt0aGlzLmNhbnZhcyYmdGhpcy5yZXNpemUodCxlKX07bGV0IG87Y29uc3QgYT0oKT0+e3MoImF0dGFjaCIsYSksdGhpcy5hdHRhY2hlZD0hMCx0aGlzLnJlc2l6ZSgpLGkoInJlc2l6ZSIsbiksaSgiZGV0YWNoIixvKX07bz0oKT0+e3RoaXMuYXR0YWNoZWQ9ITEscygicmVzaXplIixuKSx0aGlzLl9zdG9wKCksdGhpcy5fcmVzaXplKDAsMCksaSgiYXR0YWNoIixhKX0sZS5pc0F0dGFjaGVkKHRoaXMuY2FudmFzKT9hKCk6bygpfXVuYmluZEV2ZW50cygpe3UodGhpcy5fbGlzdGVuZXJzLCgodCxlKT0+e3RoaXMucGxhdGZvcm0ucmVtb3ZlRXZlbnRMaXN0ZW5lcih0aGlzLGUsdCl9KSksdGhpcy5fbGlzdGVuZXJzPXt9LHUodGhpcy5fcmVzcG9uc2l2ZUxpc3RlbmVycywoKHQsZSk9Pnt0aGlzLnBsYXRmb3JtLnJlbW92ZUV2ZW50TGlzdGVuZXIodGhpcyxlLHQpfSkpLHRoaXMuX3Jlc3BvbnNpdmVMaXN0ZW5lcnM9dm9pZCAwfXVwZGF0ZUhvdmVyU3R5bGUodCxlLGkpe2NvbnN0IHM9aT8ic2V0IjoicmVtb3ZlIjtsZXQgbixvLGEscjtmb3IoImRhdGFzZXQiPT09ZSYmKG49dGhpcy5nZXREYXRhc2V0TWV0YSh0WzBdLmRhdGFzZXRJbmRleCksbi5jb250cm9sbGVyWyJfIitzKyJEYXRhc2V0SG92ZXJTdHlsZSJdKCkpLGE9MCxyPXQubGVuZ3RoO2E8cjsrK2Epe289dFthXTtjb25zdCBlPW8mJnRoaXMuZ2V0RGF0YXNldE1ldGEoby5kYXRhc2V0SW5kZXgpLmNvbnRyb2xsZXI7ZSYmZVtzKyJIb3ZlclN0eWxlIl0oby5lbGVtZW50LG8uZGF0YXNldEluZGV4LG8uaW5kZXgpfX1nZXRBY3RpdmVFbGVtZW50cygpe3JldHVybiB0aGlzLl9hY3RpdmV8fFtdfXNldEFjdGl2ZUVsZW1lbnRzKHQpe2NvbnN0IGU9dGhpcy5fYWN0aXZlfHxbXSxpPXQubWFwKCgoe2RhdGFzZXRJbmRleDp0LGluZGV4OmV9KT0+e2NvbnN0IGk9dGhpcy5nZXREYXRhc2V0TWV0YSh0KTtpZighaSl0aHJvdyBuZXcgRXJyb3IoIk5vIGRhdGFzZXQgZm91bmQgYXQgaW5kZXggIit0KTtyZXR1cm57ZGF0YXNldEluZGV4OnQsZWxlbWVudDppLmRhdGFbZV0saW5kZXg6ZX19KSk7IWYoaSxlKSYmKHRoaXMuX2FjdGl2ZT1pLHRoaXMuX2xhc3RFdmVudD1udWxsLHRoaXMuX3VwZGF0ZUhvdmVyU3R5bGVzKGksZSkpfW5vdGlmeVBsdWdpbnModCxlLGkpe3JldHVybiB0aGlzLl9wbHVnaW5zLm5vdGlmeSh0aGlzLHQsZSxpKX1pc1BsdWdpbkVuYWJsZWQodCl7cmV0dXJuIDE9PT10aGlzLl9wbHVnaW5zLl9jYWNoZS5maWx0ZXIoKGU9PmUucGx1Z2luLmlkPT09dCkpLmxlbmd0aH1fdXBkYXRlSG92ZXJTdHlsZXModCxlLGkpe2NvbnN0IHM9dGhpcy5vcHRpb25zLmhvdmVyLG49KHQsZSk9PnQuZmlsdGVyKCh0PT4hZS5zb21lKChlPT50LmRhdGFzZXRJbmRleD09PWUuZGF0YXNldEluZGV4JiZ0LmluZGV4PT09ZS5pbmRleCkpKSksbz1uKGUsdCksYT1pP3Q6bih0LGUpO28ubGVuZ3RoJiZ0aGlzLnVwZGF0ZUhvdmVyU3R5bGUobyxzLm1vZGUsITEpLGEubGVuZ3RoJiZzLm1vZGUmJnRoaXMudXBkYXRlSG92ZXJTdHlsZShhLHMubW9kZSwhMCl9X2V2ZW50SGFuZGxlcih0LGUpe2NvbnN0IGk9e2V2ZW50OnQscmVwbGF5OmUsY2FuY2VsYWJsZTohMCxpbkNoYXJ0QXJlYTp0aGlzLmlzUG9pbnRJbkFyZWEodCl9LHM9ZT0+KGUub3B0aW9ucy5ldmVudHN8fHRoaXMub3B0aW9ucy5ldmVudHMpLmluY2x1ZGVzKHQubmF0aXZlLnR5cGUpO2lmKCExPT09dGhpcy5ub3RpZnlQbHVnaW5zKCJiZWZvcmVFdmVudCIsaSxzKSlyZXR1cm47Y29uc3Qgbj10aGlzLl9oYW5kbGVFdmVudCh0LGUsaS5pbkNoYXJ0QXJlYSk7cmV0dXJuIGkuY2FuY2VsYWJsZT0hMSx0aGlzLm5vdGlmeVBsdWdpbnMoImFmdGVyRXZlbnQiLGkscyksKG58fGkuY2hhbmdlZCkmJnRoaXMucmVuZGVyKCksdGhpc31faGFuZGxlRXZlbnQodCxlLGkpe2NvbnN0e19hY3RpdmU6cz1bXSxvcHRpb25zOm59PXRoaXMsbz1lLGE9dGhpcy5fZ2V0QWN0aXZlRWxlbWVudHModCxzLGksbykscj1EKHQpLGw9ZnVuY3Rpb24odCxlLGkscyl7cmV0dXJuIGkmJiJtb3VzZW91dCIhPT10LnR5cGU\/cz9lOnQ6bnVsbH0odCx0aGlzLl9sYXN0RXZlbnQsaSxyKTtpJiYodGhpcy5fbGFzdEV2ZW50PW51bGwsZChuLm9uSG92ZXIsW3QsYSx0aGlzXSx0aGlzKSxyJiZkKG4ub25DbGljayxbdCxhLHRoaXNdLHRoaXMpKTtjb25zdCBoPSFmKGEscyk7cmV0dXJuKGh8fGUpJiYodGhpcy5fYWN0aXZlPWEsdGhpcy5fdXBkYXRlSG92ZXJTdHlsZXMoYSxzLGUpKSx0aGlzLl9sYXN0RXZlbnQ9bCxofV9nZXRBY3RpdmVFbGVtZW50cyh0LGUsaSxzKXtpZigibW91c2VvdXQiPT09dC50eXBlKXJldHVybltdO2lmKCFpKXJldHVybiBlO2NvbnN0IG49dGhpcy5vcHRpb25zLmhvdmVyO3JldHVybiB0aGlzLmdldEVsZW1lbnRzQXRFdmVudEZvck1vZGUodCxuLm1vZGUsbixzKX19ZnVuY3Rpb24gVG4oKXtyZXR1cm4gdShBbi5pbnN0YW5jZXMsKHQ9PnQuX3BsdWdpbnMuaW52YWxpZGF0ZSgpKSl9ZnVuY3Rpb24gTG4oKXt0aHJvdyBuZXcgRXJyb3IoIlRoaXMgbWV0aG9kIGlzIG5vdCBpbXBsZW1lbnRlZDogQ2hlY2sgdGhhdCBhIGNvbXBsZXRlIGRhdGUgYWRhcHRlciBpcyBwcm92aWRlZC4iKX1jbGFzcyBFbntzdGF0aWMgb3ZlcnJpZGUodCl7T2JqZWN0LmFzc2lnbihFbi5wcm90b3R5cGUsdCl9b3B0aW9ucztjb25zdHJ1Y3Rvcih0KXt0aGlzLm9wdGlvbnM9dHx8e319aW5pdCgpe31mb3JtYXRzKCl7cmV0dXJuIExuKCl9cGFyc2UoKXtyZXR1cm4gTG4oKX1mb3JtYXQoKXtyZXR1cm4gTG4oKX1hZGQoKXtyZXR1cm4gTG4oKX1kaWZmKCl7cmV0dXJuIExuKCl9c3RhcnRPZigpe3JldHVybiBMbigpfWVuZE9mKCl7cmV0dXJuIExuKCl9fXZhciBSbj17X2RhdGU6RW59O2Z1bmN0aW9uIEluKHQpe2NvbnN0IGU9dC5pU2NhbGUsaT1mdW5jdGlvbih0LGUpe2lmKCF0Ll9jYWNoZS4kYmFyKXtjb25zdCBpPXQuZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXMoZSk7bGV0IHM9W107Zm9yKGxldCBlPTAsbj1pLmxlbmd0aDtlPG47ZSsrKXM9cy5jb25jYXQoaVtlXS5jb250cm9sbGVyLmdldEFsbFBhcnNlZFZhbHVlcyh0KSk7dC5fY2FjaGUuJGJhcj1sdChzLnNvcnQoKCh0LGUpPT50LWUpKSl9cmV0dXJuIHQuX2NhY2hlLiRiYXJ9KGUsdC50eXBlKTtsZXQgcyxuLG8sYSxyPWUuX2xlbmd0aDtjb25zdCBsPSgpPT57MzI3NjchPT1vJiYtMzI3NjghPT1vJiYoayhhKSYmKHI9TWF0aC5taW4ocixNYXRoLmFicyhvLWEpfHxyKSksYT1vKX07Zm9yKHM9MCxuPWkubGVuZ3RoO3M8bjsrK3Mpbz1lLmdldFBpeGVsRm9yVmFsdWUoaVtzXSksbCgpO2ZvcihhPXZvaWQgMCxzPTAsbj1lLnRpY2tzLmxlbmd0aDtzPG47KytzKW89ZS5nZXRQaXhlbEZvclRpY2socyksbCgpO3JldHVybiByfWZ1bmN0aW9uIHpuKHQsZSxpLHMpe3JldHVybiBuKHQpP2Z1bmN0aW9uKHQsZSxpLHMpe2NvbnN0IG49aS5wYXJzZSh0WzBdLHMpLG89aS5wYXJzZSh0WzFdLHMpLGE9TWF0aC5taW4obixvKSxyPU1hdGgubWF4KG4sbyk7bGV0IGw9YSxoPXI7TWF0aC5hYnMoYSk+TWF0aC5hYnMocikmJihsPXIsaD1hKSxlW2kuYXhpc109aCxlLl9jdXN0b209e2JhclN0YXJ0OmwsYmFyRW5kOmgsc3RhcnQ6bixlbmQ6byxtaW46YSxtYXg6cn19KHQsZSxpLHMpOmVbaS5heGlzXT1pLnBhcnNlKHQscyksZX1mdW5jdGlvbiBGbih0LGUsaSxzKXtjb25zdCBuPXQuaVNjYWxlLG89dC52U2NhbGUsYT1uLmdldExhYmVscygpLHI9bj09PW8sbD1bXTtsZXQgaCxjLGQsdTtmb3IoaD1pLGM9aStzO2g8YzsrK2gpdT1lW2hdLGQ9e30sZFtuLmF4aXNdPXJ8fG4ucGFyc2UoYVtoXSxoKSxsLnB1c2goem4odSxkLG8saCkpO3JldHVybiBsfWZ1bmN0aW9uIFZuKHQpe3JldHVybiB0JiZ2b2lkIDAhPT10LmJhclN0YXJ0JiZ2b2lkIDAhPT10LmJhckVuZH1mdW5jdGlvbiBCbih0LGUsaSxzKXtsZXQgbj1lLmJvcmRlclNraXBwZWQ7Y29uc3Qgbz17fTtpZighbilyZXR1cm4gdm9pZCh0LmJvcmRlclNraXBwZWQ9byk7aWYoITA9PT1uKXJldHVybiB2b2lkKHQuYm9yZGVyU2tpcHBlZD17dG9wOiEwLHJpZ2h0OiEwLGJvdHRvbTohMCxsZWZ0OiEwfSk7Y29uc3R7c3RhcnQ6YSxlbmQ6cixyZXZlcnNlOmwsdG9wOmgsYm90dG9tOmN9PWZ1bmN0aW9uKHQpe2xldCBlLGkscyxuLG87cmV0dXJuIHQuaG9yaXpvbnRhbD8oZT10LmJhc2U+dC54LGk9ImxlZnQiLHM9InJpZ2h0Iik6KGU9dC5iYXNlPHQueSxpPSJib3R0b20iLHM9InRvcCIpLGU\/KG49ImVuZCIsbz0ic3RhcnQiKToobj0ic3RhcnQiLG89ImVuZCIpLHtzdGFydDppLGVuZDpzLHJldmVyc2U6ZSx0b3A6bixib3R0b206b319KHQpOyJtaWRkbGUiPT09biYmaSYmKHQuZW5hYmxlQm9yZGVyUmFkaXVzPSEwLChpLl90b3B8fDApPT09cz9uPWg6KGkuX2JvdHRvbXx8MCk9PT1zP249Yzoob1tXbihjLGEscixsKV09ITAsbj1oKSksb1tXbihuLGEscixsKV09ITAsdC5ib3JkZXJTa2lwcGVkPW99ZnVuY3Rpb24gV24odCxlLGkscyl7dmFyIG4sbyxhO3JldHVybiBzPyhhPWksdD1Obih0PShuPXQpPT09KG89ZSk\/YTpuPT09YT9vOm4saSxlKSk6dD1Obih0LGUsaSksdH1mdW5jdGlvbiBObih0LGUsaSl7cmV0dXJuInN0YXJ0Ij09PXQ\/ZToiZW5kIj09PXQ\/aTp0fWZ1bmN0aW9uIEhuKHQse2luZmxhdGVBbW91bnQ6ZX0saSl7dC5pbmZsYXRlQW1vdW50PSJhdXRvIj09PWU\/MT09PWk\/LjMzOjA6ZX1jbGFzcyBqbiBleHRlbmRzIE5ze3N0YXRpYyBpZD0iZG91Z2hudXQiO3N0YXRpYyBkZWZhdWx0cz17ZGF0YXNldEVsZW1lbnRUeXBlOiExLGRhdGFFbGVtZW50VHlwZToiYXJjIixhbmltYXRpb246e2FuaW1hdGVSb3RhdGU6ITAsYW5pbWF0ZVNjYWxlOiExfSxhbmltYXRpb25zOntudW1iZXJzOnt0eXBlOiJudW1iZXIiLHByb3BlcnRpZXM6WyJjaXJjdW1mZXJlbmNlIiwiZW5kQW5nbGUiLCJpbm5lclJhZGl1cyIsIm91dGVyUmFkaXVzIiwic3RhcnRBbmdsZSIsIngiLCJ5Iiwib2Zmc2V0IiwiYm9yZGVyV2lkdGgiLCJzcGFjaW5nIl19fSxjdXRvdXQ6IjUwJSIscm90YXRpb246MCxjaXJjdW1mZXJlbmNlOjM2MCxyYWRpdXM6IjEwMCUiLHNwYWNpbmc6MCxpbmRleEF4aXM6InIifTtzdGF0aWMgZGVzY3JpcHRvcnM9e19zY3JpcHRhYmxlOnQ9PiJzcGFjaW5nIiE9PXQsX2luZGV4YWJsZTp0PT4ic3BhY2luZyIhPT10JiYhdC5zdGFydHNXaXRoKCJib3JkZXJEYXNoIikmJiF0LnN0YXJ0c1dpdGgoImhvdmVyQm9yZGVyRGFzaCIpfTtzdGF0aWMgb3ZlcnJpZGVzPXthc3BlY3RSYXRpbzoxLHBsdWdpbnM6e2xlZ2VuZDp7bGFiZWxzOntnZW5lcmF0ZUxhYmVscyh0KXtjb25zdCBlPXQuZGF0YTtpZihlLmxhYmVscy5sZW5ndGgmJmUuZGF0YXNldHMubGVuZ3RoKXtjb25zdHtsYWJlbHM6e3BvaW50U3R5bGU6aSxjb2xvcjpzfX09dC5sZWdlbmQub3B0aW9ucztyZXR1cm4gZS5sYWJlbHMubWFwKCgoZSxuKT0+e2NvbnN0IG89dC5nZXREYXRhc2V0TWV0YSgwKS5jb250cm9sbGVyLmdldFN0eWxlKG4pO3JldHVybnt0ZXh0OmUsZmlsbFN0eWxlOm8uYmFja2dyb3VuZENvbG9yLHN0cm9rZVN0eWxlOm8uYm9yZGVyQ29sb3IsZm9udENvbG9yOnMsbGluZVdpZHRoOm8uYm9yZGVyV2lkdGgscG9pbnRTdHlsZTppLGhpZGRlbjohdC5nZXREYXRhVmlzaWJpbGl0eShuKSxpbmRleDpufX0pKX1yZXR1cm5bXX19LG9uQ2xpY2sodCxlLGkpe2kuY2hhcnQudG9nZ2xlRGF0YVZpc2liaWxpdHkoZS5pbmRleCksaS5jaGFydC51cGRhdGUoKX19fX07Y29uc3RydWN0b3IodCxlKXtzdXBlcih0LGUpLHRoaXMuZW5hYmxlT3B0aW9uU2hhcmluZz0hMCx0aGlzLmlubmVyUmFkaXVzPXZvaWQgMCx0aGlzLm91dGVyUmFkaXVzPXZvaWQgMCx0aGlzLm9mZnNldFg9dm9pZCAwLHRoaXMub2Zmc2V0WT12b2lkIDB9bGlua1NjYWxlcygpe31wYXJzZSh0LGUpe2NvbnN0IGk9dGhpcy5nZXREYXRhc2V0KCkuZGF0YSxzPXRoaXMuX2NhY2hlZE1ldGE7aWYoITE9PT10aGlzLl9wYXJzaW5nKXMuX3BhcnNlZD1pO2Vsc2V7bGV0IG4sYSxyPXQ9PitpW3RdO2lmKG8oaVt0XSkpe2NvbnN0e2tleTp0PSJ2YWx1ZSJ9PXRoaXMuX3BhcnNpbmc7cj1lPT4rTShpW2VdLHQpfWZvcihuPXQsYT10K2U7bjxhOysrbilzLl9wYXJzZWRbbl09cihuKX19X2dldFJvdGF0aW9uKCl7cmV0dXJuICQodGhpcy5vcHRpb25zLnJvdGF0aW9uLTkwKX1fZ2V0Q2lyY3VtZmVyZW5jZSgpe3JldHVybiAkKHRoaXMub3B0aW9ucy5jaXJjdW1mZXJlbmNlKX1fZ2V0Um90YXRpb25FeHRlbnRzKCl7bGV0IHQ9TyxlPS1PO2ZvcihsZXQgaT0wO2k8dGhpcy5jaGFydC5kYXRhLmRhdGFzZXRzLmxlbmd0aDsrK2kpaWYodGhpcy5jaGFydC5pc0RhdGFzZXRWaXNpYmxlKGkpJiZ0aGlzLmNoYXJ0LmdldERhdGFzZXRNZXRhKGkpLnR5cGU9PT10aGlzLl90eXBlKXtjb25zdCBzPXRoaXMuY2hhcnQuZ2V0RGF0YXNldE1ldGEoaSkuY29udHJvbGxlcixuPXMuX2dldFJvdGF0aW9uKCksbz1zLl9nZXRDaXJjdW1mZXJlbmNlKCk7dD1NYXRoLm1pbih0LG4pLGU9TWF0aC5tYXgoZSxuK28pfXJldHVybntyb3RhdGlvbjp0LGNpcmN1bWZlcmVuY2U6ZS10fX11cGRhdGUodCl7Y29uc3QgZT10aGlzLmNoYXJ0LHtjaGFydEFyZWE6aX09ZSxzPXRoaXMuX2NhY2hlZE1ldGEsbj1zLmRhdGEsbz10aGlzLmdldE1heEJvcmRlcldpZHRoKCkrdGhpcy5nZXRNYXhPZmZzZXQobikrdGhpcy5vcHRpb25zLnNwYWNpbmcsYT1NYXRoLm1heCgoTWF0aC5taW4oaS53aWR0aCxpLmhlaWdodCktbykvMiwwKSxyPU1hdGgubWluKGgodGhpcy5vcHRpb25zLmN1dG91dCxhKSwxKSxsPXRoaXMuX2dldFJpbmdXZWlnaHQodGhpcy5pbmRleCkse2NpcmN1bWZlcmVuY2U6ZCxyb3RhdGlvbjp1fT10aGlzLl9nZXRSb3RhdGlvbkV4dGVudHMoKSx7cmF0aW9YOmYscmF0aW9ZOmcsb2Zmc2V0WDpwLG9mZnNldFk6bX09ZnVuY3Rpb24odCxlLGkpe2xldCBzPTEsbj0xLG89MCxhPTA7aWYoZTxPKXtjb25zdCByPXQsbD1yK2UsaD1NYXRoLmNvcyhyKSxjPU1hdGguc2luKHIpLGQ9TWF0aC5jb3MobCksdT1NYXRoLnNpbihsKSxmPSh0LGUscyk9PloodCxyLGwsITApPzE6TWF0aC5tYXgoZSxlKmkscyxzKmkpLGc9KHQsZSxzKT0+Wih0LHIsbCwhMCk\/LTE6TWF0aC5taW4oZSxlKmkscyxzKmkpLHA9ZigwLGgsZCksbT1mKEUsYyx1KSxiPWcoQyxoLGQpLHg9ZyhDK0UsYyx1KTtzPShwLWIpLzIsbj0obS14KS8yLG89LShwK2IpLzIsYT0tKG0reCkvMn1yZXR1cm57cmF0aW9YOnMscmF0aW9ZOm4sb2Zmc2V0WDpvLG9mZnNldFk6YX19KHUsZCxyKSxiPShpLndpZHRoLW8pL2YseD0oaS5oZWlnaHQtbykvZyxfPU1hdGgubWF4KE1hdGgubWluKGIseCkvMiwwKSx5PWModGhpcy5vcHRpb25zLnJhZGl1cyxfKSx2PSh5LU1hdGgubWF4KHkqciwwKSkvdGhpcy5fZ2V0VmlzaWJsZURhdGFzZXRXZWlnaHRUb3RhbCgpO3RoaXMub2Zmc2V0WD1wKnksdGhpcy5vZmZzZXRZPW0qeSxzLnRvdGFsPXRoaXMuY2FsY3VsYXRlVG90YWwoKSx0aGlzLm91dGVyUmFkaXVzPXktdip0aGlzLl9nZXRSaW5nV2VpZ2h0T2Zmc2V0KHRoaXMuaW5kZXgpLHRoaXMuaW5uZXJSYWRpdXM9TWF0aC5tYXgodGhpcy5vdXRlclJhZGl1cy12KmwsMCksdGhpcy51cGRhdGVFbGVtZW50cyhuLDAsbi5sZW5ndGgsdCl9X2NpcmN1bWZlcmVuY2UodCxlKXtjb25zdCBpPXRoaXMub3B0aW9ucyxzPXRoaXMuX2NhY2hlZE1ldGEsbj10aGlzLl9nZXRDaXJjdW1mZXJlbmNlKCk7cmV0dXJuIGUmJmkuYW5pbWF0aW9uLmFuaW1hdGVSb3RhdGV8fCF0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KHQpfHxudWxsPT09cy5fcGFyc2VkW3RdfHxzLmRhdGFbdF0uaGlkZGVuPzA6dGhpcy5jYWxjdWxhdGVDaXJjdW1mZXJlbmNlKHMuX3BhcnNlZFt0XSpuL08pfXVwZGF0ZUVsZW1lbnRzKHQsZSxpLHMpe2NvbnN0IG49InJlc2V0Ij09PXMsbz10aGlzLmNoYXJ0LGE9by5jaGFydEFyZWEscj1vLm9wdGlvbnMuYW5pbWF0aW9uLGw9KGEubGVmdCthLnJpZ2h0KS8yLGg9KGEudG9wK2EuYm90dG9tKS8yLGM9biYmci5hbmltYXRlU2NhbGUsZD1jPzA6dGhpcy5pbm5lclJhZGl1cyx1PWM\/MDp0aGlzLm91dGVyUmFkaXVzLHtzaGFyZWRPcHRpb25zOmYsaW5jbHVkZU9wdGlvbnM6Z309dGhpcy5fZ2V0U2hhcmVkT3B0aW9ucyhlLHMpO2xldCBwLG09dGhpcy5fZ2V0Um90YXRpb24oKTtmb3IocD0wO3A8ZTsrK3ApbSs9dGhpcy5fY2lyY3VtZmVyZW5jZShwLG4pO2ZvcihwPWU7cDxlK2k7KytwKXtjb25zdCBlPXRoaXMuX2NpcmN1bWZlcmVuY2UocCxuKSxpPXRbcF0sbz17eDpsK3RoaXMub2Zmc2V0WCx5OmgrdGhpcy5vZmZzZXRZLHN0YXJ0QW5nbGU6bSxlbmRBbmdsZTptK2UsY2lyY3VtZmVyZW5jZTplLG91dGVyUmFkaXVzOnUsaW5uZXJSYWRpdXM6ZH07ZyYmKG8ub3B0aW9ucz1mfHx0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMocCxpLmFjdGl2ZT8iYWN0aXZlIjpzKSksbSs9ZSx0aGlzLnVwZGF0ZUVsZW1lbnQoaSxwLG8scyl9fWNhbGN1bGF0ZVRvdGFsKCl7Y29uc3QgdD10aGlzLl9jYWNoZWRNZXRhLGU9dC5kYXRhO2xldCBpLHM9MDtmb3IoaT0wO2k8ZS5sZW5ndGg7aSsrKXtjb25zdCBuPXQuX3BhcnNlZFtpXTtudWxsPT09bnx8aXNOYU4obil8fCF0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpfHxlW2ldLmhpZGRlbnx8KHMrPU1hdGguYWJzKG4pKX1yZXR1cm4gc31jYWxjdWxhdGVDaXJjdW1mZXJlbmNlKHQpe2NvbnN0IGU9dGhpcy5fY2FjaGVkTWV0YS50b3RhbDtyZXR1cm4gZT4wJiYhaXNOYU4odCk\/TyooTWF0aC5hYnModCkvZSk6MH1nZXRMYWJlbEFuZFZhbHVlKHQpe2NvbnN0IGU9dGhpcy5fY2FjaGVkTWV0YSxpPXRoaXMuY2hhcnQscz1pLmRhdGEubGFiZWxzfHxbXSxuPW5lKGUuX3BhcnNlZFt0XSxpLm9wdGlvbnMubG9jYWxlKTtyZXR1cm57bGFiZWw6c1t0XXx8IiIsdmFsdWU6bn19Z2V0TWF4Qm9yZGVyV2lkdGgodCl7bGV0IGU9MDtjb25zdCBpPXRoaXMuY2hhcnQ7bGV0IHMsbixvLGEscjtpZighdClmb3Iocz0wLG49aS5kYXRhLmRhdGFzZXRzLmxlbmd0aDtzPG47KytzKWlmKGkuaXNEYXRhc2V0VmlzaWJsZShzKSl7bz1pLmdldERhdGFzZXRNZXRhKHMpLHQ9by5kYXRhLGE9by5jb250cm9sbGVyO2JyZWFrfWlmKCF0KXJldHVybiAwO2ZvcihzPTAsbj10Lmxlbmd0aDtzPG47KytzKXI9YS5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKHMpLCJpbm5lciIhPT1yLmJvcmRlckFsaWduJiYoZT1NYXRoLm1heChlLHIuYm9yZGVyV2lkdGh8fDAsci5ob3ZlckJvcmRlcldpZHRofHwwKSk7cmV0dXJuIGV9Z2V0TWF4T2Zmc2V0KHQpe2xldCBlPTA7Zm9yKGxldCBpPTAscz10Lmxlbmd0aDtpPHM7KytpKXtjb25zdCB0PXRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpKTtlPU1hdGgubWF4KGUsdC5vZmZzZXR8fDAsdC5ob3Zlck9mZnNldHx8MCl9cmV0dXJuIGV9X2dldFJpbmdXZWlnaHRPZmZzZXQodCl7bGV0IGU9MDtmb3IobGV0IGk9MDtpPHQ7KytpKXRoaXMuY2hhcnQuaXNEYXRhc2V0VmlzaWJsZShpKSYmKGUrPXRoaXMuX2dldFJpbmdXZWlnaHQoaSkpO3JldHVybiBlfV9nZXRSaW5nV2VpZ2h0KHQpe3JldHVybiBNYXRoLm1heChsKHRoaXMuY2hhcnQuZGF0YS5kYXRhc2V0c1t0XS53ZWlnaHQsMSksMCl9X2dldFZpc2libGVEYXRhc2V0V2VpZ2h0VG90YWwoKXtyZXR1cm4gdGhpcy5fZ2V0UmluZ1dlaWdodE9mZnNldCh0aGlzLmNoYXJ0LmRhdGEuZGF0YXNldHMubGVuZ3RoKXx8MX19Y2xhc3MgJG4gZXh0ZW5kcyBOc3tzdGF0aWMgaWQ9InBvbGFyQXJlYSI7c3RhdGljIGRlZmF1bHRzPXtkYXRhRWxlbWVudFR5cGU6ImFyYyIsYW5pbWF0aW9uOnthbmltYXRlUm90YXRlOiEwLGFuaW1hdGVTY2FsZTohMH0sYW5pbWF0aW9uczp7bnVtYmVyczp7dHlwZToibnVtYmVyIixwcm9wZXJ0aWVzOlsieCIsInkiLCJzdGFydEFuZ2xlIiwiZW5kQW5nbGUiLCJpbm5lclJhZGl1cyIsIm91dGVyUmFkaXVzIl19fSxpbmRleEF4aXM6InIiLHN0YXJ0QW5nbGU6MH07c3RhdGljIG92ZXJyaWRlcz17YXNwZWN0UmF0aW86MSxwbHVnaW5zOntsZWdlbmQ6e2xhYmVsczp7Z2VuZXJhdGVMYWJlbHModCl7Y29uc3QgZT10LmRhdGE7aWYoZS5sYWJlbHMubGVuZ3RoJiZlLmRhdGFzZXRzLmxlbmd0aCl7Y29uc3R7bGFiZWxzOntwb2ludFN0eWxlOmksY29sb3I6c319PXQubGVnZW5kLm9wdGlvbnM7cmV0dXJuIGUubGFiZWxzLm1hcCgoKGUsbik9Pntjb25zdCBvPXQuZ2V0RGF0YXNldE1ldGEoMCkuY29udHJvbGxlci5nZXRTdHlsZShuKTtyZXR1cm57dGV4dDplLGZpbGxTdHlsZTpvLmJhY2tncm91bmRDb2xvcixzdHJva2VTdHlsZTpvLmJvcmRlckNvbG9yLGZvbnRDb2xvcjpzLGxpbmVXaWR0aDpvLmJvcmRlcldpZHRoLHBvaW50U3R5bGU6aSxoaWRkZW46IXQuZ2V0RGF0YVZpc2liaWxpdHkobiksaW5kZXg6bn19KSl9cmV0dXJuW119fSxvbkNsaWNrKHQsZSxpKXtpLmNoYXJ0LnRvZ2dsZURhdGFWaXNpYmlsaXR5KGUuaW5kZXgpLGkuY2hhcnQudXBkYXRlKCl9fX0sc2NhbGVzOntyOnt0eXBlOiJyYWRpYWxMaW5lYXIiLGFuZ2xlTGluZXM6e2Rpc3BsYXk6ITF9LGJlZ2luQXRaZXJvOiEwLGdyaWQ6e2NpcmN1bGFyOiEwfSxwb2ludExhYmVsczp7ZGlzcGxheTohMX0sc3RhcnRBbmdsZTowfX19O2NvbnN0cnVjdG9yKHQsZSl7c3VwZXIodCxlKSx0aGlzLmlubmVyUmFkaXVzPXZvaWQgMCx0aGlzLm91dGVyUmFkaXVzPXZvaWQgMH1nZXRMYWJlbEFuZFZhbHVlKHQpe2NvbnN0IGU9dGhpcy5fY2FjaGVkTWV0YSxpPXRoaXMuY2hhcnQscz1pLmRhdGEubGFiZWxzfHxbXSxuPW5lKGUuX3BhcnNlZFt0XS5yLGkub3B0aW9ucy5sb2NhbGUpO3JldHVybntsYWJlbDpzW3RdfHwiIix2YWx1ZTpufX1wYXJzZU9iamVjdERhdGEodCxlLGkscyl7cmV0dXJuIGlpLmJpbmQodGhpcykodCxlLGkscyl9dXBkYXRlKHQpe2NvbnN0IGU9dGhpcy5fY2FjaGVkTWV0YS5kYXRhO3RoaXMuX3VwZGF0ZVJhZGl1cygpLHRoaXMudXBkYXRlRWxlbWVudHMoZSwwLGUubGVuZ3RoLHQpfWdldE1pbk1heCgpe2NvbnN0IHQ9dGhpcy5fY2FjaGVkTWV0YSxlPXttaW46TnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLG1heDpOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFl9O3JldHVybiB0LmRhdGEuZm9yRWFjaCgoKHQsaSk9Pntjb25zdCBzPXRoaXMuZ2V0UGFyc2VkKGkpLnI7IWlzTmFOKHMpJiZ0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KGkpJiYoczxlLm1pbiYmKGUubWluPXMpLHM+ZS5tYXgmJihlLm1heD1zKSl9KSksZX1fdXBkYXRlUmFkaXVzKCl7Y29uc3QgdD10aGlzLmNoYXJ0LGU9dC5jaGFydEFyZWEsaT10Lm9wdGlvbnMscz1NYXRoLm1pbihlLnJpZ2h0LWUubGVmdCxlLmJvdHRvbS1lLnRvcCksbj1NYXRoLm1heChzLzIsMCksbz0obi1NYXRoLm1heChpLmN1dG91dFBlcmNlbnRhZ2U\/bi8xMDAqaS5jdXRvdXRQZXJjZW50YWdlOjEsMCkpL3QuZ2V0VmlzaWJsZURhdGFzZXRDb3VudCgpO3RoaXMub3V0ZXJSYWRpdXM9bi1vKnRoaXMuaW5kZXgsdGhpcy5pbm5lclJhZGl1cz10aGlzLm91dGVyUmFkaXVzLW99dXBkYXRlRWxlbWVudHModCxlLGkscyl7Y29uc3Qgbj0icmVzZXQiPT09cyxvPXRoaXMuY2hhcnQsYT1vLm9wdGlvbnMuYW5pbWF0aW9uLHI9dGhpcy5fY2FjaGVkTWV0YS5yU2NhbGUsbD1yLnhDZW50ZXIsaD1yLnlDZW50ZXIsYz1yLmdldEluZGV4QW5nbGUoMCktLjUqQztsZXQgZCx1PWM7Y29uc3QgZj0zNjAvdGhpcy5jb3VudFZpc2libGVFbGVtZW50cygpO2ZvcihkPTA7ZDxlOysrZCl1Kz10aGlzLl9jb21wdXRlQW5nbGUoZCxzLGYpO2ZvcihkPWU7ZDxlK2k7ZCsrKXtjb25zdCBlPXRbZF07bGV0IGk9dSxnPXUrdGhpcy5fY29tcHV0ZUFuZ2xlKGQscyxmKSxwPW8uZ2V0RGF0YVZpc2liaWxpdHkoZCk\/ci5nZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZSh0aGlzLmdldFBhcnNlZChkKS5yKTowO3U9ZyxuJiYoYS5hbmltYXRlU2NhbGUmJihwPTApLGEuYW5pbWF0ZVJvdGF0ZSYmKGk9Zz1jKSk7Y29uc3QgbT17eDpsLHk6aCxpbm5lclJhZGl1czowLG91dGVyUmFkaXVzOnAsc3RhcnRBbmdsZTppLGVuZEFuZ2xlOmcsb3B0aW9uczp0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoZCxlLmFjdGl2ZT8iYWN0aXZlIjpzKX07dGhpcy51cGRhdGVFbGVtZW50KGUsZCxtLHMpfX1jb3VudFZpc2libGVFbGVtZW50cygpe2NvbnN0IHQ9dGhpcy5fY2FjaGVkTWV0YTtsZXQgZT0wO3JldHVybiB0LmRhdGEuZm9yRWFjaCgoKHQsaSk9PnshaXNOYU4odGhpcy5nZXRQYXJzZWQoaSkucikmJnRoaXMuY2hhcnQuZ2V0RGF0YVZpc2liaWxpdHkoaSkmJmUrK30pKSxlfV9jb21wdXRlQW5nbGUodCxlLGkpe3JldHVybiB0aGlzLmNoYXJ0LmdldERhdGFWaXNpYmlsaXR5KHQpPyQodGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKHQsZSkuYW5nbGV8fGkpOjB9fXZhciBZbj1PYmplY3QuZnJlZXplKHtfX3Byb3RvX186bnVsbCxCYXJDb250cm9sbGVyOmNsYXNzIGV4dGVuZHMgTnN7c3RhdGljIGlkPSJiYXIiO3N0YXRpYyBkZWZhdWx0cz17ZGF0YXNldEVsZW1lbnRUeXBlOiExLGRhdGFFbGVtZW50VHlwZToiYmFyIixjYXRlZ29yeVBlcmNlbnRhZ2U6LjgsYmFyUGVyY2VudGFnZTouOSxncm91cGVkOiEwLGFuaW1hdGlvbnM6e251bWJlcnM6e3R5cGU6Im51bWJlciIscHJvcGVydGllczpbIngiLCJ5IiwiYmFzZSIsIndpZHRoIiwiaGVpZ2h0Il19fX07c3RhdGljIG92ZXJyaWRlcz17c2NhbGVzOntfaW5kZXhfOnt0eXBlOiJjYXRlZ29yeSIsb2Zmc2V0OiEwLGdyaWQ6e29mZnNldDohMH19LF92YWx1ZV86e3R5cGU6ImxpbmVhciIsYmVnaW5BdFplcm86ITB9fX07cGFyc2VQcmltaXRpdmVEYXRhKHQsZSxpLHMpe3JldHVybiBGbih0LGUsaSxzKX1wYXJzZUFycmF5RGF0YSh0LGUsaSxzKXtyZXR1cm4gRm4odCxlLGkscyl9cGFyc2VPYmplY3REYXRhKHQsZSxpLHMpe2NvbnN0e2lTY2FsZTpuLHZTY2FsZTpvfT10LHt4QXhpc0tleTphPSJ4Iix5QXhpc0tleTpyPSJ5In09dGhpcy5fcGFyc2luZyxsPSJ4Ij09PW4uYXhpcz9hOnIsaD0ieCI9PT1vLmF4aXM\/YTpyLGM9W107bGV0IGQsdSxmLGc7Zm9yKGQ9aSx1PWkrcztkPHU7KytkKWc9ZVtkXSxmPXt9LGZbbi5heGlzXT1uLnBhcnNlKE0oZyxsKSxkKSxjLnB1c2goem4oTShnLGgpLGYsbyxkKSk7cmV0dXJuIGN9dXBkYXRlUmFuZ2VGcm9tUGFyc2VkKHQsZSxpLHMpe3N1cGVyLnVwZGF0ZVJhbmdlRnJvbVBhcnNlZCh0LGUsaSxzKTtjb25zdCBuPWkuX2N1c3RvbTtuJiZlPT09dGhpcy5fY2FjaGVkTWV0YS52U2NhbGUmJih0Lm1pbj1NYXRoLm1pbih0Lm1pbixuLm1pbiksdC5tYXg9TWF0aC5tYXgodC5tYXgsbi5tYXgpKX1nZXRNYXhPdmVyZmxvdygpe3JldHVybiAwfWdldExhYmVsQW5kVmFsdWUodCl7Y29uc3QgZT10aGlzLl9jYWNoZWRNZXRhLHtpU2NhbGU6aSx2U2NhbGU6c309ZSxuPXRoaXMuZ2V0UGFyc2VkKHQpLG89bi5fY3VzdG9tLGE9Vm4obyk\/IlsiK28uc3RhcnQrIiwgIitvLmVuZCsiXSI6IiIrcy5nZXRMYWJlbEZvclZhbHVlKG5bcy5heGlzXSk7cmV0dXJue2xhYmVsOiIiK2kuZ2V0TGFiZWxGb3JWYWx1ZShuW2kuYXhpc10pLHZhbHVlOmF9fWluaXRpYWxpemUoKXt0aGlzLmVuYWJsZU9wdGlvblNoYXJpbmc9ITAsc3VwZXIuaW5pdGlhbGl6ZSgpO3RoaXMuX2NhY2hlZE1ldGEuc3RhY2s9dGhpcy5nZXREYXRhc2V0KCkuc3RhY2t9dXBkYXRlKHQpe2NvbnN0IGU9dGhpcy5fY2FjaGVkTWV0YTt0aGlzLnVwZGF0ZUVsZW1lbnRzKGUuZGF0YSwwLGUuZGF0YS5sZW5ndGgsdCl9dXBkYXRlRWxlbWVudHModCxlLGksbil7Y29uc3Qgbz0icmVzZXQiPT09bix7aW5kZXg6YSxfY2FjaGVkTWV0YTp7dlNjYWxlOnJ9fT10aGlzLGw9ci5nZXRCYXNlUGl4ZWwoKSxoPXIuaXNIb3Jpem9udGFsKCksYz10aGlzLl9nZXRSdWxlcigpLHtzaGFyZWRPcHRpb25zOmQsaW5jbHVkZU9wdGlvbnM6dX09dGhpcy5fZ2V0U2hhcmVkT3B0aW9ucyhlLG4pO2ZvcihsZXQgZj1lO2Y8ZStpO2YrKyl7Y29uc3QgZT10aGlzLmdldFBhcnNlZChmKSxpPW98fHMoZVtyLmF4aXNdKT97YmFzZTpsLGhlYWQ6bH06dGhpcy5fY2FsY3VsYXRlQmFyVmFsdWVQaXhlbHMoZiksZz10aGlzLl9jYWxjdWxhdGVCYXJJbmRleFBpeGVscyhmLGMpLHA9KGUuX3N0YWNrc3x8e30pW3IuYXhpc10sbT17aG9yaXpvbnRhbDpoLGJhc2U6aS5iYXNlLGVuYWJsZUJvcmRlclJhZGl1czohcHx8Vm4oZS5fY3VzdG9tKXx8YT09PXAuX3RvcHx8YT09PXAuX2JvdHRvbSx4Omg\/aS5oZWFkOmcuY2VudGVyLHk6aD9nLmNlbnRlcjppLmhlYWQsaGVpZ2h0Omg\/Zy5zaXplOk1hdGguYWJzKGkuc2l6ZSksd2lkdGg6aD9NYXRoLmFicyhpLnNpemUpOmcuc2l6ZX07dSYmKG0ub3B0aW9ucz1kfHx0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoZix0W2ZdLmFjdGl2ZT8iYWN0aXZlIjpuKSk7Y29uc3QgYj1tLm9wdGlvbnN8fHRbZl0ub3B0aW9ucztCbihtLGIscCxhKSxIbihtLGIsYy5yYXRpbyksdGhpcy51cGRhdGVFbGVtZW50KHRbZl0sZixtLG4pfX1fZ2V0U3RhY2tzKHQsZSl7Y29uc3R7aVNjYWxlOml9PXRoaXMuX2NhY2hlZE1ldGEsbj1pLmdldE1hdGNoaW5nVmlzaWJsZU1ldGFzKHRoaXMuX3R5cGUpLmZpbHRlcigodD0+dC5jb250cm9sbGVyLm9wdGlvbnMuZ3JvdXBlZCkpLG89aS5vcHRpb25zLnN0YWNrZWQsYT1bXSxyPXQ9Pntjb25zdCBpPXQuY29udHJvbGxlci5nZXRQYXJzZWQoZSksbj1pJiZpW3QudlNjYWxlLmF4aXNdO2lmKHMobil8fGlzTmFOKG4pKXJldHVybiEwfTtmb3IoY29uc3QgaSBvZiBuKWlmKCh2b2lkIDA9PT1lfHwhcihpKSkmJigoITE9PT1vfHwtMT09PWEuaW5kZXhPZihpLnN0YWNrKXx8dm9pZCAwPT09byYmdm9pZCAwPT09aS5zdGFjaykmJmEucHVzaChpLnN0YWNrKSxpLmluZGV4PT09dCkpYnJlYWs7cmV0dXJuIGEubGVuZ3RofHxhLnB1c2godm9pZCAwKSxhfV9nZXRTdGFja0NvdW50KHQpe3JldHVybiB0aGlzLl9nZXRTdGFja3Modm9pZCAwLHQpLmxlbmd0aH1fZ2V0U3RhY2tJbmRleCh0LGUsaSl7Y29uc3Qgcz10aGlzLl9nZXRTdGFja3ModCxpKSxuPXZvaWQgMCE9PWU\/cy5pbmRleE9mKGUpOi0xO3JldHVybi0xPT09bj9zLmxlbmd0aC0xOm59X2dldFJ1bGVyKCl7Y29uc3QgdD10aGlzLm9wdGlvbnMsZT10aGlzLl9jYWNoZWRNZXRhLGk9ZS5pU2NhbGUscz1bXTtsZXQgbixvO2ZvcihuPTAsbz1lLmRhdGEubGVuZ3RoO248bzsrK24pcy5wdXNoKGkuZ2V0UGl4ZWxGb3JWYWx1ZSh0aGlzLmdldFBhcnNlZChuKVtpLmF4aXNdLG4pKTtjb25zdCBhPXQuYmFyVGhpY2tuZXNzO3JldHVybnttaW46YXx8SW4oZSkscGl4ZWxzOnMsc3RhcnQ6aS5fc3RhcnRQaXhlbCxlbmQ6aS5fZW5kUGl4ZWwsc3RhY2tDb3VudDp0aGlzLl9nZXRTdGFja0NvdW50KCksc2NhbGU6aSxncm91cGVkOnQuZ3JvdXBlZCxyYXRpbzphPzE6dC5jYXRlZ29yeVBlcmNlbnRhZ2UqdC5iYXJQZXJjZW50YWdlfX1fY2FsY3VsYXRlQmFyVmFsdWVQaXhlbHModCl7Y29uc3R7X2NhY2hlZE1ldGE6e3ZTY2FsZTplLF9zdGFja2VkOmksaW5kZXg6bn0sb3B0aW9uczp7YmFzZTpvLG1pbkJhckxlbmd0aDphfX09dGhpcyxyPW98fDAsbD10aGlzLmdldFBhcnNlZCh0KSxoPWwuX2N1c3RvbSxjPVZuKGgpO2xldCBkLHUsZj1sW2UuYXhpc10sZz0wLHA9aT90aGlzLmFwcGx5U3RhY2soZSxsLGkpOmY7cCE9PWYmJihnPXAtZixwPWYpLGMmJihmPWguYmFyU3RhcnQscD1oLmJhckVuZC1oLmJhclN0YXJ0LDAhPT1mJiZGKGYpIT09RihoLmJhckVuZCkmJihnPTApLGcrPWYpO2NvbnN0IG09cyhvKXx8Yz9nOm87bGV0IGI9ZS5nZXRQaXhlbEZvclZhbHVlKG0pO2lmKGQ9dGhpcy5jaGFydC5nZXREYXRhVmlzaWJpbGl0eSh0KT9lLmdldFBpeGVsRm9yVmFsdWUoZytwKTpiLHU9ZC1iLE1hdGguYWJzKHUpPGEpe3U9ZnVuY3Rpb24odCxlLGkpe3JldHVybiAwIT09dD9GKHQpOihlLmlzSG9yaXpvbnRhbCgpPzE6LTEpKihlLm1pbj49aT8xOi0xKX0odSxlLHIpKmEsZj09PXImJihiLT11LzIpO2NvbnN0IHQ9ZS5nZXRQaXhlbEZvckRlY2ltYWwoMCkscz1lLmdldFBpeGVsRm9yRGVjaW1hbCgxKSxvPU1hdGgubWluKHQscyksaD1NYXRoLm1heCh0LHMpO2I9TWF0aC5tYXgoTWF0aC5taW4oYixoKSxvKSxkPWIrdSxpJiYhYyYmKGwuX3N0YWNrc1tlLmF4aXNdLl92aXN1YWxWYWx1ZXNbbl09ZS5nZXRWYWx1ZUZvclBpeGVsKGQpLWUuZ2V0VmFsdWVGb3JQaXhlbChiKSl9aWYoYj09PWUuZ2V0UGl4ZWxGb3JWYWx1ZShyKSl7Y29uc3QgdD1GKHUpKmUuZ2V0TGluZVdpZHRoRm9yVmFsdWUocikvMjtiKz10LHUtPXR9cmV0dXJue3NpemU6dSxiYXNlOmIsaGVhZDpkLGNlbnRlcjpkK3UvMn19X2NhbGN1bGF0ZUJhckluZGV4UGl4ZWxzKHQsZSl7Y29uc3QgaT1lLnNjYWxlLG49dGhpcy5vcHRpb25zLG89bi5za2lwTnVsbCxhPWwobi5tYXhCYXJUaGlja25lc3MsMS8wKTtsZXQgcixoO2lmKGUuZ3JvdXBlZCl7Y29uc3QgaT1vP3RoaXMuX2dldFN0YWNrQ291bnQodCk6ZS5zdGFja0NvdW50LGw9ImZsZXgiPT09bi5iYXJUaGlja25lc3M\/ZnVuY3Rpb24odCxlLGkscyl7Y29uc3Qgbj1lLnBpeGVscyxvPW5bdF07bGV0IGE9dD4wP25bdC0xXTpudWxsLHI9dDxuLmxlbmd0aC0xP25bdCsxXTpudWxsO2NvbnN0IGw9aS5jYXRlZ29yeVBlcmNlbnRhZ2U7bnVsbD09PWEmJihhPW8tKG51bGw9PT1yP2UuZW5kLWUuc3RhcnQ6ci1vKSksbnVsbD09PXImJihyPW8rby1hKTtjb25zdCBoPW8tKG8tTWF0aC5taW4oYSxyKSkvMipsO3JldHVybntjaHVuazpNYXRoLmFicyhyLWEpLzIqbC9zLHJhdGlvOmkuYmFyUGVyY2VudGFnZSxzdGFydDpofX0odCxlLG4saSk6ZnVuY3Rpb24odCxlLGksbil7Y29uc3Qgbz1pLmJhclRoaWNrbmVzcztsZXQgYSxyO3JldHVybiBzKG8pPyhhPWUubWluKmkuY2F0ZWdvcnlQZXJjZW50YWdlLHI9aS5iYXJQZXJjZW50YWdlKTooYT1vKm4scj0xKSx7Y2h1bms6YS9uLHJhdGlvOnIsc3RhcnQ6ZS5waXhlbHNbdF0tYS8yfX0odCxlLG4saSksYz10aGlzLl9nZXRTdGFja0luZGV4KHRoaXMuaW5kZXgsdGhpcy5fY2FjaGVkTWV0YS5zdGFjayxvP3Q6dm9pZCAwKTtyPWwuc3RhcnQrbC5jaHVuaypjK2wuY2h1bmsvMixoPU1hdGgubWluKGEsbC5jaHVuaypsLnJhdGlvKX1lbHNlIHI9aS5nZXRQaXhlbEZvclZhbHVlKHRoaXMuZ2V0UGFyc2VkKHQpW2kuYXhpc10sdCksaD1NYXRoLm1pbihhLGUubWluKmUucmF0aW8pO3JldHVybntiYXNlOnItaC8yLGhlYWQ6citoLzIsY2VudGVyOnIsc2l6ZTpofX1kcmF3KCl7Y29uc3QgdD10aGlzLl9jYWNoZWRNZXRhLGU9dC52U2NhbGUsaT10LmRhdGEscz1pLmxlbmd0aDtsZXQgbj0wO2Zvcig7bjxzOysrbiludWxsIT09dGhpcy5nZXRQYXJzZWQobilbZS5heGlzXSYmaVtuXS5kcmF3KHRoaXMuX2N0eCl9fSxCdWJibGVDb250cm9sbGVyOmNsYXNzIGV4dGVuZHMgTnN7c3RhdGljIGlkPSJidWJibGUiO3N0YXRpYyBkZWZhdWx0cz17ZGF0YXNldEVsZW1lbnRUeXBlOiExLGRhdGFFbGVtZW50VHlwZToicG9pbnQiLGFuaW1hdGlvbnM6e251bWJlcnM6e3R5cGU6Im51bWJlciIscHJvcGVydGllczpbIngiLCJ5IiwiYm9yZGVyV2lkdGgiLCJyYWRpdXMiXX19fTtzdGF0aWMgb3ZlcnJpZGVzPXtzY2FsZXM6e3g6e3R5cGU6ImxpbmVhciJ9LHk6e3R5cGU6ImxpbmVhciJ9fX07aW5pdGlhbGl6ZSgpe3RoaXMuZW5hYmxlT3B0aW9uU2hhcmluZz0hMCxzdXBlci5pbml0aWFsaXplKCl9cGFyc2VQcmltaXRpdmVEYXRhKHQsZSxpLHMpe2NvbnN0IG49c3VwZXIucGFyc2VQcmltaXRpdmVEYXRhKHQsZSxpLHMpO2ZvcihsZXQgdD0wO3Q8bi5sZW5ndGg7dCsrKW5bdF0uX2N1c3RvbT10aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnModCtpKS5yYWRpdXM7cmV0dXJuIG59cGFyc2VBcnJheURhdGEodCxlLGkscyl7Y29uc3Qgbj1zdXBlci5wYXJzZUFycmF5RGF0YSh0LGUsaSxzKTtmb3IobGV0IHQ9MDt0PG4ubGVuZ3RoO3QrKyl7Y29uc3Qgcz1lW2krdF07blt0XS5fY3VzdG9tPWwoc1syXSx0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnModCtpKS5yYWRpdXMpfXJldHVybiBufXBhcnNlT2JqZWN0RGF0YSh0LGUsaSxzKXtjb25zdCBuPXN1cGVyLnBhcnNlT2JqZWN0RGF0YSh0LGUsaSxzKTtmb3IobGV0IHQ9MDt0PG4ubGVuZ3RoO3QrKyl7Y29uc3Qgcz1lW2krdF07blt0XS5fY3VzdG9tPWwocyYmcy5yJiYrcy5yLHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyh0K2kpLnJhZGl1cyl9cmV0dXJuIG59Z2V0TWF4T3ZlcmZsb3coKXtjb25zdCB0PXRoaXMuX2NhY2hlZE1ldGEuZGF0YTtsZXQgZT0wO2ZvcihsZXQgaT10Lmxlbmd0aC0xO2k+PTA7LS1pKWU9TWF0aC5tYXgoZSx0W2ldLnNpemUodGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGkpKS8yKTtyZXR1cm4gZT4wJiZlfWdldExhYmVsQW5kVmFsdWUodCl7Y29uc3QgZT10aGlzLl9jYWNoZWRNZXRhLGk9dGhpcy5jaGFydC5kYXRhLmxhYmVsc3x8W10se3hTY2FsZTpzLHlTY2FsZTpufT1lLG89dGhpcy5nZXRQYXJzZWQodCksYT1zLmdldExhYmVsRm9yVmFsdWUoby54KSxyPW4uZ2V0TGFiZWxGb3JWYWx1ZShvLnkpLGw9by5fY3VzdG9tO3JldHVybntsYWJlbDppW3RdfHwiIix2YWx1ZToiKCIrYSsiLCAiK3IrKGw\/IiwgIitsOiIiKSsiKSJ9fXVwZGF0ZSh0KXtjb25zdCBlPXRoaXMuX2NhY2hlZE1ldGEuZGF0YTt0aGlzLnVwZGF0ZUVsZW1lbnRzKGUsMCxlLmxlbmd0aCx0KX11cGRhdGVFbGVtZW50cyh0LGUsaSxzKXtjb25zdCBuPSJyZXNldCI9PT1zLHtpU2NhbGU6byx2U2NhbGU6YX09dGhpcy5fY2FjaGVkTWV0YSx7c2hhcmVkT3B0aW9uczpyLGluY2x1ZGVPcHRpb25zOmx9PXRoaXMuX2dldFNoYXJlZE9wdGlvbnMoZSxzKSxoPW8uYXhpcyxjPWEuYXhpcztmb3IobGV0IGQ9ZTtkPGUraTtkKyspe2NvbnN0IGU9dFtkXSxpPSFuJiZ0aGlzLmdldFBhcnNlZChkKSx1PXt9LGY9dVtoXT1uP28uZ2V0UGl4ZWxGb3JEZWNpbWFsKC41KTpvLmdldFBpeGVsRm9yVmFsdWUoaVtoXSksZz11W2NdPW4\/YS5nZXRCYXNlUGl4ZWwoKTphLmdldFBpeGVsRm9yVmFsdWUoaVtjXSk7dS5za2lwPWlzTmFOKGYpfHxpc05hTihnKSxsJiYodS5vcHRpb25zPXJ8fHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhkLGUuYWN0aXZlPyJhY3RpdmUiOnMpLG4mJih1Lm9wdGlvbnMucmFkaXVzPTApKSx0aGlzLnVwZGF0ZUVsZW1lbnQoZSxkLHUscyl9fXJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnModCxlKXtjb25zdCBpPXRoaXMuZ2V0UGFyc2VkKHQpO2xldCBzPXN1cGVyLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnModCxlKTtzLiRzaGFyZWQmJihzPU9iamVjdC5hc3NpZ24oe30scyx7JHNoYXJlZDohMX0pKTtjb25zdCBuPXMucmFkaXVzO3JldHVybiJhY3RpdmUiIT09ZSYmKHMucmFkaXVzPTApLHMucmFkaXVzKz1sKGkmJmkuX2N1c3RvbSxuKSxzfX0sRG91Z2hudXRDb250cm9sbGVyOmpuLExpbmVDb250cm9sbGVyOmNsYXNzIGV4dGVuZHMgTnN7c3RhdGljIGlkPSJsaW5lIjtzdGF0aWMgZGVmYXVsdHM9e2RhdGFzZXRFbGVtZW50VHlwZToibGluZSIsZGF0YUVsZW1lbnRUeXBlOiJwb2ludCIsc2hvd0xpbmU6ITAsc3BhbkdhcHM6ITF9O3N0YXRpYyBvdmVycmlkZXM9e3NjYWxlczp7X2luZGV4Xzp7dHlwZToiY2F0ZWdvcnkifSxfdmFsdWVfOnt0eXBlOiJsaW5lYXIifX19O2luaXRpYWxpemUoKXt0aGlzLmVuYWJsZU9wdGlvblNoYXJpbmc9ITAsdGhpcy5zdXBwb3J0c0RlY2ltYXRpb249ITAsc3VwZXIuaW5pdGlhbGl6ZSgpfXVwZGF0ZSh0KXtjb25zdCBlPXRoaXMuX2NhY2hlZE1ldGEse2RhdGFzZXQ6aSxkYXRhOnM9W10sX2RhdGFzZXQ6bn09ZSxvPXRoaXMuY2hhcnQuX2FuaW1hdGlvbnNEaXNhYmxlZDtsZXR7c3RhcnQ6YSxjb3VudDpyfT1wdChlLHMsbyk7dGhpcy5fZHJhd1N0YXJ0PWEsdGhpcy5fZHJhd0NvdW50PXIsbXQoZSkmJihhPTAscj1zLmxlbmd0aCksaS5fY2hhcnQ9dGhpcy5jaGFydCxpLl9kYXRhc2V0SW5kZXg9dGhpcy5pbmRleCxpLl9kZWNpbWF0ZWQ9ISFuLl9kZWNpbWF0ZWQsaS5wb2ludHM9cztjb25zdCBsPXRoaXMucmVzb2x2ZURhdGFzZXRFbGVtZW50T3B0aW9ucyh0KTt0aGlzLm9wdGlvbnMuc2hvd0xpbmV8fChsLmJvcmRlcldpZHRoPTApLGwuc2VnbWVudD10aGlzLm9wdGlvbnMuc2VnbWVudCx0aGlzLnVwZGF0ZUVsZW1lbnQoaSx2b2lkIDAse2FuaW1hdGVkOiFvLG9wdGlvbnM6bH0sdCksdGhpcy51cGRhdGVFbGVtZW50cyhzLGEscix0KX11cGRhdGVFbGVtZW50cyh0LGUsaSxuKXtjb25zdCBvPSJyZXNldCI9PT1uLHtpU2NhbGU6YSx2U2NhbGU6cixfc3RhY2tlZDpsLF9kYXRhc2V0Omh9PXRoaXMuX2NhY2hlZE1ldGEse3NoYXJlZE9wdGlvbnM6YyxpbmNsdWRlT3B0aW9uczpkfT10aGlzLl9nZXRTaGFyZWRPcHRpb25zKGUsbiksdT1hLmF4aXMsZj1yLmF4aXMse3NwYW5HYXBzOmcsc2VnbWVudDpwfT10aGlzLm9wdGlvbnMsbT1OKGcpP2c6TnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLGI9dGhpcy5jaGFydC5fYW5pbWF0aW9uc0Rpc2FibGVkfHxvfHwibm9uZSI9PT1uLHg9ZStpLF89dC5sZW5ndGg7bGV0IHk9ZT4wJiZ0aGlzLmdldFBhcnNlZChlLTEpO2ZvcihsZXQgaT0wO2k8XzsrK2kpe2NvbnN0IGc9dFtpXSxfPWI\/Zzp7fTtpZihpPGV8fGk+PXgpe18uc2tpcD0hMDtjb250aW51ZX1jb25zdCB2PXRoaXMuZ2V0UGFyc2VkKGkpLE09cyh2W2ZdKSx3PV9bdV09YS5nZXRQaXhlbEZvclZhbHVlKHZbdV0saSksaz1fW2ZdPW98fE0\/ci5nZXRCYXNlUGl4ZWwoKTpyLmdldFBpeGVsRm9yVmFsdWUobD90aGlzLmFwcGx5U3RhY2socix2LGwpOnZbZl0saSk7Xy5za2lwPWlzTmFOKHcpfHxpc05hTihrKXx8TSxfLnN0b3A9aT4wJiZNYXRoLmFicyh2W3VdLXlbdV0pPm0scCYmKF8ucGFyc2VkPXYsXy5yYXc9aC5kYXRhW2ldKSxkJiYoXy5vcHRpb25zPWN8fHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhpLGcuYWN0aXZlPyJhY3RpdmUiOm4pKSxifHx0aGlzLnVwZGF0ZUVsZW1lbnQoZyxpLF8sbikseT12fX1nZXRNYXhPdmVyZmxvdygpe2NvbnN0IHQ9dGhpcy5fY2FjaGVkTWV0YSxlPXQuZGF0YXNldCxpPWUub3B0aW9ucyYmZS5vcHRpb25zLmJvcmRlcldpZHRofHwwLHM9dC5kYXRhfHxbXTtpZighcy5sZW5ndGgpcmV0dXJuIGk7Y29uc3Qgbj1zWzBdLnNpemUodGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKDApKSxvPXNbcy5sZW5ndGgtMV0uc2l6ZSh0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMocy5sZW5ndGgtMSkpO3JldHVybiBNYXRoLm1heChpLG4sbykvMn1kcmF3KCl7Y29uc3QgdD10aGlzLl9jYWNoZWRNZXRhO3QuZGF0YXNldC51cGRhdGVDb250cm9sUG9pbnRzKHRoaXMuY2hhcnQuY2hhcnRBcmVhLHQuaVNjYWxlLmF4aXMpLHN1cGVyLmRyYXcoKX19LFBpZUNvbnRyb2xsZXI6Y2xhc3MgZXh0ZW5kcyBqbntzdGF0aWMgaWQ9InBpZSI7c3RhdGljIGRlZmF1bHRzPXtjdXRvdXQ6MCxyb3RhdGlvbjowLGNpcmN1bWZlcmVuY2U6MzYwLHJhZGl1czoiMTAwJSJ9fSxQb2xhckFyZWFDb250cm9sbGVyOiRuLFJhZGFyQ29udHJvbGxlcjpjbGFzcyBleHRlbmRzIE5ze3N0YXRpYyBpZD0icmFkYXIiO3N0YXRpYyBkZWZhdWx0cz17ZGF0YXNldEVsZW1lbnRUeXBlOiJsaW5lIixkYXRhRWxlbWVudFR5cGU6InBvaW50IixpbmRleEF4aXM6InIiLHNob3dMaW5lOiEwLGVsZW1lbnRzOntsaW5lOntmaWxsOiJzdGFydCJ9fX07c3RhdGljIG92ZXJyaWRlcz17YXNwZWN0UmF0aW86MSxzY2FsZXM6e3I6e3R5cGU6InJhZGlhbExpbmVhciJ9fX07Z2V0TGFiZWxBbmRWYWx1ZSh0KXtjb25zdCBlPXRoaXMuX2NhY2hlZE1ldGEudlNjYWxlLGk9dGhpcy5nZXRQYXJzZWQodCk7cmV0dXJue2xhYmVsOmUuZ2V0TGFiZWxzKClbdF0sdmFsdWU6IiIrZS5nZXRMYWJlbEZvclZhbHVlKGlbZS5heGlzXSl9fXBhcnNlT2JqZWN0RGF0YSh0LGUsaSxzKXtyZXR1cm4gaWkuYmluZCh0aGlzKSh0LGUsaSxzKX11cGRhdGUodCl7Y29uc3QgZT10aGlzLl9jYWNoZWRNZXRhLGk9ZS5kYXRhc2V0LHM9ZS5kYXRhfHxbXSxuPWUuaVNjYWxlLmdldExhYmVscygpO2lmKGkucG9pbnRzPXMsInJlc2l6ZSIhPT10KXtjb25zdCBlPXRoaXMucmVzb2x2ZURhdGFzZXRFbGVtZW50T3B0aW9ucyh0KTt0aGlzLm9wdGlvbnMuc2hvd0xpbmV8fChlLmJvcmRlcldpZHRoPTApO2NvbnN0IG89e19sb29wOiEwLF9mdWxsTG9vcDpuLmxlbmd0aD09PXMubGVuZ3RoLG9wdGlvbnM6ZX07dGhpcy51cGRhdGVFbGVtZW50KGksdm9pZCAwLG8sdCl9dGhpcy51cGRhdGVFbGVtZW50cyhzLDAscy5sZW5ndGgsdCl9dXBkYXRlRWxlbWVudHModCxlLGkscyl7Y29uc3Qgbj10aGlzLl9jYWNoZWRNZXRhLnJTY2FsZSxvPSJyZXNldCI9PT1zO2ZvcihsZXQgYT1lO2E8ZStpO2ErKyl7Y29uc3QgZT10W2FdLGk9dGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGEsZS5hY3RpdmU\/ImFjdGl2ZSI6cykscj1uLmdldFBvaW50UG9zaXRpb25Gb3JWYWx1ZShhLHRoaXMuZ2V0UGFyc2VkKGEpLnIpLGw9bz9uLnhDZW50ZXI6ci54LGg9bz9uLnlDZW50ZXI6ci55LGM9e3g6bCx5OmgsYW5nbGU6ci5hbmdsZSxza2lwOmlzTmFOKGwpfHxpc05hTihoKSxvcHRpb25zOml9O3RoaXMudXBkYXRlRWxlbWVudChlLGEsYyxzKX19fSxTY2F0dGVyQ29udHJvbGxlcjpjbGFzcyBleHRlbmRzIE5ze3N0YXRpYyBpZD0ic2NhdHRlciI7c3RhdGljIGRlZmF1bHRzPXtkYXRhc2V0RWxlbWVudFR5cGU6ITEsZGF0YUVsZW1lbnRUeXBlOiJwb2ludCIsc2hvd0xpbmU6ITEsZmlsbDohMX07c3RhdGljIG92ZXJyaWRlcz17aW50ZXJhY3Rpb246e21vZGU6InBvaW50In0sc2NhbGVzOnt4Ont0eXBlOiJsaW5lYXIifSx5Ont0eXBlOiJsaW5lYXIifX19O2dldExhYmVsQW5kVmFsdWUodCl7Y29uc3QgZT10aGlzLl9jYWNoZWRNZXRhLGk9dGhpcy5jaGFydC5kYXRhLmxhYmVsc3x8W10se3hTY2FsZTpzLHlTY2FsZTpufT1lLG89dGhpcy5nZXRQYXJzZWQodCksYT1zLmdldExhYmVsRm9yVmFsdWUoby54KSxyPW4uZ2V0TGFiZWxGb3JWYWx1ZShvLnkpO3JldHVybntsYWJlbDppW3RdfHwiIix2YWx1ZToiKCIrYSsiLCAiK3IrIikifX11cGRhdGUodCl7Y29uc3QgZT10aGlzLl9jYWNoZWRNZXRhLHtkYXRhOmk9W119PWUscz10aGlzLmNoYXJ0Ll9hbmltYXRpb25zRGlzYWJsZWQ7bGV0e3N0YXJ0Om4sY291bnQ6b309cHQoZSxpLHMpO2lmKHRoaXMuX2RyYXdTdGFydD1uLHRoaXMuX2RyYXdDb3VudD1vLG10KGUpJiYobj0wLG89aS5sZW5ndGgpLHRoaXMub3B0aW9ucy5zaG93TGluZSl7dGhpcy5kYXRhc2V0RWxlbWVudFR5cGV8fHRoaXMuYWRkRWxlbWVudHMoKTtjb25zdHtkYXRhc2V0Om4sX2RhdGFzZXQ6b309ZTtuLl9jaGFydD10aGlzLmNoYXJ0LG4uX2RhdGFzZXRJbmRleD10aGlzLmluZGV4LG4uX2RlY2ltYXRlZD0hIW8uX2RlY2ltYXRlZCxuLnBvaW50cz1pO2NvbnN0IGE9dGhpcy5yZXNvbHZlRGF0YXNldEVsZW1lbnRPcHRpb25zKHQpO2Euc2VnbWVudD10aGlzLm9wdGlvbnMuc2VnbWVudCx0aGlzLnVwZGF0ZUVsZW1lbnQobix2b2lkIDAse2FuaW1hdGVkOiFzLG9wdGlvbnM6YX0sdCl9ZWxzZSB0aGlzLmRhdGFzZXRFbGVtZW50VHlwZSYmKGRlbGV0ZSBlLmRhdGFzZXQsdGhpcy5kYXRhc2V0RWxlbWVudFR5cGU9ITEpO3RoaXMudXBkYXRlRWxlbWVudHMoaSxuLG8sdCl9YWRkRWxlbWVudHMoKXtjb25zdHtzaG93TGluZTp0fT10aGlzLm9wdGlvbnM7IXRoaXMuZGF0YXNldEVsZW1lbnRUeXBlJiZ0JiYodGhpcy5kYXRhc2V0RWxlbWVudFR5cGU9dGhpcy5jaGFydC5yZWdpc3RyeS5nZXRFbGVtZW50KCJsaW5lIikpLHN1cGVyLmFkZEVsZW1lbnRzKCl9dXBkYXRlRWxlbWVudHModCxlLGksbil7Y29uc3Qgbz0icmVzZXQiPT09bix7aVNjYWxlOmEsdlNjYWxlOnIsX3N0YWNrZWQ6bCxfZGF0YXNldDpofT10aGlzLl9jYWNoZWRNZXRhLGM9dGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKGUsbiksZD10aGlzLmdldFNoYXJlZE9wdGlvbnMoYyksdT10aGlzLmluY2x1ZGVPcHRpb25zKG4sZCksZj1hLmF4aXMsZz1yLmF4aXMse3NwYW5HYXBzOnAsc2VnbWVudDptfT10aGlzLm9wdGlvbnMsYj1OKHApP3A6TnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLHg9dGhpcy5jaGFydC5fYW5pbWF0aW9uc0Rpc2FibGVkfHxvfHwibm9uZSI9PT1uO2xldCBfPWU+MCYmdGhpcy5nZXRQYXJzZWQoZS0xKTtmb3IobGV0IGM9ZTtjPGUraTsrK2Mpe2NvbnN0IGU9dFtjXSxpPXRoaXMuZ2V0UGFyc2VkKGMpLHA9eD9lOnt9LHk9cyhpW2ddKSx2PXBbZl09YS5nZXRQaXhlbEZvclZhbHVlKGlbZl0sYyksTT1wW2ddPW98fHk\/ci5nZXRCYXNlUGl4ZWwoKTpyLmdldFBpeGVsRm9yVmFsdWUobD90aGlzLmFwcGx5U3RhY2socixpLGwpOmlbZ10sYyk7cC5za2lwPWlzTmFOKHYpfHxpc05hTihNKXx8eSxwLnN0b3A9Yz4wJiZNYXRoLmFicyhpW2ZdLV9bZl0pPmIsbSYmKHAucGFyc2VkPWkscC5yYXc9aC5kYXRhW2NdKSx1JiYocC5vcHRpb25zPWR8fHRoaXMucmVzb2x2ZURhdGFFbGVtZW50T3B0aW9ucyhjLGUuYWN0aXZlPyJhY3RpdmUiOm4pKSx4fHx0aGlzLnVwZGF0ZUVsZW1lbnQoZSxjLHAsbiksXz1pfXRoaXMudXBkYXRlU2hhcmVkT3B0aW9ucyhkLG4sYyl9Z2V0TWF4T3ZlcmZsb3coKXtjb25zdCB0PXRoaXMuX2NhY2hlZE1ldGEsZT10LmRhdGF8fFtdO2lmKCF0aGlzLm9wdGlvbnMuc2hvd0xpbmUpe2xldCB0PTA7Zm9yKGxldCBpPWUubGVuZ3RoLTE7aT49MDstLWkpdD1NYXRoLm1heCh0LGVbaV0uc2l6ZSh0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoaSkpLzIpO3JldHVybiB0PjAmJnR9Y29uc3QgaT10LmRhdGFzZXQscz1pLm9wdGlvbnMmJmkub3B0aW9ucy5ib3JkZXJXaWR0aHx8MDtpZighZS5sZW5ndGgpcmV0dXJuIHM7Y29uc3Qgbj1lWzBdLnNpemUodGhpcy5yZXNvbHZlRGF0YUVsZW1lbnRPcHRpb25zKDApKSxvPWVbZS5sZW5ndGgtMV0uc2l6ZSh0aGlzLnJlc29sdmVEYXRhRWxlbWVudE9wdGlvbnMoZS5sZW5ndGgtMSkpO3JldHVybiBNYXRoLm1heChzLG4sbykvMn19fSk7ZnVuY3Rpb24gVW4odCxlLGkscyl7Y29uc3Qgbj12aSh0Lm9wdGlvbnMuYm9yZGVyUmFkaXVzLFsib3V0ZXJTdGFydCIsIm91dGVyRW5kIiwiaW5uZXJTdGFydCIsImlubmVyRW5kIl0pO2NvbnN0IG89KGktZSkvMixhPU1hdGgubWluKG8scyplLzIpLHI9dD0+e2NvbnN0IGU9KGktTWF0aC5taW4obyx0KSkqcy8yO3JldHVybiBKKHQsMCxNYXRoLm1pbihvLGUpKX07cmV0dXJue291dGVyU3RhcnQ6cihuLm91dGVyU3RhcnQpLG91dGVyRW5kOnIobi5vdXRlckVuZCksaW5uZXJTdGFydDpKKG4uaW5uZXJTdGFydCwwLGEpLGlubmVyRW5kOkoobi5pbm5lckVuZCwwLGEpfX1mdW5jdGlvbiBYbih0LGUsaSxzKXtyZXR1cm57eDppK3QqTWF0aC5jb3MoZSkseTpzK3QqTWF0aC5zaW4oZSl9fWZ1bmN0aW9uIHFuKHQsZSxpLHMsbixvKXtjb25zdHt4OmEseTpyLHN0YXJ0QW5nbGU6bCxwaXhlbE1hcmdpbjpoLGlubmVyUmFkaXVzOmN9PWUsZD1NYXRoLm1heChlLm91dGVyUmFkaXVzK3MraS1oLDApLHU9Yz4wP2MrcytpK2g6MDtsZXQgZj0wO2NvbnN0IGc9bi1sO2lmKHMpe2NvbnN0IHQ9KChjPjA\/Yy1zOjApKyhkPjA\/ZC1zOjApKS8yO2Y9KGctKDAhPT10P2cqdC8odCtzKTpnKSkvMn1jb25zdCBwPShnLU1hdGgubWF4KC4wMDEsZypkLWkvQykvZCkvMixtPWwrcCtmLGI9bi1wLWYse291dGVyU3RhcnQ6eCxvdXRlckVuZDpfLGlubmVyU3RhcnQ6eSxpbm5lckVuZDp2fT1VbihlLHUsZCxiLW0pLE09ZC14LHc9ZC1fLGs9bSt4L00sUz1iLV8vdyxQPXUreSxEPXUrdixPPW0reS9QLEE9Yi12L0Q7aWYodC5iZWdpblBhdGgoKSxvKXtjb25zdCBlPShrK1MpLzI7aWYodC5hcmMoYSxyLGQsayxlKSx0LmFyYyhhLHIsZCxlLFMpLF8+MCl7Y29uc3QgZT1Ybih3LFMsYSxyKTt0LmFyYyhlLngsZS55LF8sUyxiK0UpfWNvbnN0IGk9WG4oRCxiLGEscik7aWYodC5saW5lVG8oaS54LGkueSksdj4wKXtjb25zdCBlPVhuKEQsQSxhLHIpO3QuYXJjKGUueCxlLnksdixiK0UsQStNYXRoLlBJKX1jb25zdCBzPShiLXYvdSsobSt5L3UpKS8yO2lmKHQuYXJjKGEscix1LGItdi91LHMsITApLHQuYXJjKGEscix1LHMsbSt5L3UsITApLHk+MCl7Y29uc3QgZT1YbihQLE8sYSxyKTt0LmFyYyhlLngsZS55LHksTytNYXRoLlBJLG0tRSl9Y29uc3Qgbj1YbihNLG0sYSxyKTtpZih0LmxpbmVUbyhuLngsbi55KSx4PjApe2NvbnN0IGU9WG4oTSxrLGEscik7dC5hcmMoZS54LGUueSx4LG0tRSxrKX19ZWxzZXt0Lm1vdmVUbyhhLHIpO2NvbnN0IGU9TWF0aC5jb3MoaykqZCthLGk9TWF0aC5zaW4oaykqZCtyO3QubGluZVRvKGUsaSk7Y29uc3Qgcz1NYXRoLmNvcyhTKSpkK2Esbj1NYXRoLnNpbihTKSpkK3I7dC5saW5lVG8ocyxuKX10LmNsb3NlUGF0aCgpfWZ1bmN0aW9uIEtuKHQsZSxpLHMsbil7Y29uc3R7ZnVsbENpcmNsZXM6byxzdGFydEFuZ2xlOmEsY2lyY3VtZmVyZW5jZTpyLG9wdGlvbnM6bH09ZSx7Ym9yZGVyV2lkdGg6aCxib3JkZXJKb2luU3R5bGU6Yyxib3JkZXJEYXNoOmQsYm9yZGVyRGFzaE9mZnNldDp1fT1sLGY9ImlubmVyIj09PWwuYm9yZGVyQWxpZ247aWYoIWgpcmV0dXJuO3Quc2V0TGluZURhc2goZHx8W10pLHQubGluZURhc2hPZmZzZXQ9dSxmPyh0LmxpbmVXaWR0aD0yKmgsdC5saW5lSm9pbj1jfHwicm91bmQiKToodC5saW5lV2lkdGg9aCx0LmxpbmVKb2luPWN8fCJiZXZlbCIpO2xldCBnPWUuZW5kQW5nbGU7aWYobyl7cW4odCxlLGkscyxnLG4pO2ZvcihsZXQgZT0wO2U8bzsrK2UpdC5zdHJva2UoKTtpc05hTihyKXx8KGc9YSsociVPfHxPKSl9ZiYmZnVuY3Rpb24odCxlLGkpe2NvbnN0e3N0YXJ0QW5nbGU6cyxwaXhlbE1hcmdpbjpuLHg6byx5OmEsb3V0ZXJSYWRpdXM6cixpbm5lclJhZGl1czpsfT1lO2xldCBoPW4vcjt0LmJlZ2luUGF0aCgpLHQuYXJjKG8sYSxyLHMtaCxpK2gpLGw+bj8oaD1uL2wsdC5hcmMobyxhLGwsaStoLHMtaCwhMCkpOnQuYXJjKG8sYSxuLGkrRSxzLUUpLHQuY2xvc2VQYXRoKCksdC5jbGlwKCl9KHQsZSxnKSxvfHwocW4odCxlLGkscyxnLG4pLHQuc3Ryb2tlKCkpfWZ1bmN0aW9uIEduKHQsZSxpPWUpe3QubGluZUNhcD1sKGkuYm9yZGVyQ2FwU3R5bGUsZS5ib3JkZXJDYXBTdHlsZSksdC5zZXRMaW5lRGFzaChsKGkuYm9yZGVyRGFzaCxlLmJvcmRlckRhc2gpKSx0LmxpbmVEYXNoT2Zmc2V0PWwoaS5ib3JkZXJEYXNoT2Zmc2V0LGUuYm9yZGVyRGFzaE9mZnNldCksdC5saW5lSm9pbj1sKGkuYm9yZGVySm9pblN0eWxlLGUuYm9yZGVySm9pblN0eWxlKSx0LmxpbmVXaWR0aD1sKGkuYm9yZGVyV2lkdGgsZS5ib3JkZXJXaWR0aCksdC5zdHJva2VTdHlsZT1sKGkuYm9yZGVyQ29sb3IsZS5ib3JkZXJDb2xvcil9ZnVuY3Rpb24gWm4odCxlLGkpe3QubGluZVRvKGkueCxpLnkpfWZ1bmN0aW9uIEpuKHQsZSxpPXt9KXtjb25zdCBzPXQubGVuZ3RoLHtzdGFydDpuPTAsZW5kOm89cy0xfT1pLHtzdGFydDphLGVuZDpyfT1lLGw9TWF0aC5tYXgobixhKSxoPU1hdGgubWluKG8sciksYz1uPGEmJm88YXx8bj5yJiZvPnI7cmV0dXJue2NvdW50OnMsc3RhcnQ6bCxsb29wOmUubG9vcCxpbGVuOmg8bCYmIWM\/cytoLWw6aC1sfX1mdW5jdGlvbiBRbih0LGUsaSxzKXtjb25zdHtwb2ludHM6bixvcHRpb25zOm99PWUse2NvdW50OmEsc3RhcnQ6cixsb29wOmwsaWxlbjpofT1KbihuLGkscyksYz1mdW5jdGlvbih0KXtyZXR1cm4gdC5zdGVwcGVkP0ZlOnQudGVuc2lvbnx8Im1vbm90b25lIj09PXQuY3ViaWNJbnRlcnBvbGF0aW9uTW9kZT9WZTpabn0obyk7bGV0IGQsdSxmLHttb3ZlOmc9ITAscmV2ZXJzZTpwfT1zfHx7fTtmb3IoZD0wO2Q8PWg7KytkKXU9blsocisocD9oLWQ6ZCkpJWFdLHUuc2tpcHx8KGc\/KHQubW92ZVRvKHUueCx1LnkpLGc9ITEpOmModCxmLHUscCxvLnN0ZXBwZWQpLGY9dSk7cmV0dXJuIGwmJih1PW5bKHIrKHA\/aDowKSklYV0sYyh0LGYsdSxwLG8uc3RlcHBlZCkpLCEhbH1mdW5jdGlvbiB0byh0LGUsaSxzKXtjb25zdCBuPWUucG9pbnRzLHtjb3VudDpvLHN0YXJ0OmEsaWxlbjpyfT1KbihuLGkscykse21vdmU6bD0hMCxyZXZlcnNlOmh9PXN8fHt9O2xldCBjLGQsdSxmLGcscCxtPTAsYj0wO2NvbnN0IHg9dD0+KGErKGg\/ci10OnQpKSVvLF89KCk9PntmIT09ZyYmKHQubGluZVRvKG0sZyksdC5saW5lVG8obSxmKSx0LmxpbmVUbyhtLHApKX07Zm9yKGwmJihkPW5beCgwKV0sdC5tb3ZlVG8oZC54LGQueSkpLGM9MDtjPD1yOysrYyl7aWYoZD1uW3goYyldLGQuc2tpcCljb250aW51ZTtjb25zdCBlPWQueCxpPWQueSxzPTB8ZTtzPT09dT8oaTxmP2Y9aTppPmcmJihnPWkpLG09KGIqbStlKS8rK2IpOihfKCksdC5saW5lVG8oZSxpKSx1PXMsYj0wLGY9Zz1pKSxwPWl9XygpfWZ1bmN0aW9uIGVvKHQpe2NvbnN0IGU9dC5vcHRpb25zLGk9ZS5ib3JkZXJEYXNoJiZlLmJvcmRlckRhc2gubGVuZ3RoO3JldHVybiEodC5fZGVjaW1hdGVkfHx0Ll9sb29wfHxlLnRlbnNpb258fCJtb25vdG9uZSI9PT1lLmN1YmljSW50ZXJwb2xhdGlvbk1vZGV8fGUuc3RlcHBlZHx8aSk\/dG86UW59Y29uc3QgaW89ImZ1bmN0aW9uIj09dHlwZW9mIFBhdGgyRDtmdW5jdGlvbiBzbyh0LGUsaSxzKXtpbyYmIWUub3B0aW9ucy5zZWdtZW50P2Z1bmN0aW9uKHQsZSxpLHMpe2xldCBuPWUuX3BhdGg7bnx8KG49ZS5fcGF0aD1uZXcgUGF0aDJELGUucGF0aChuLGkscykmJm4uY2xvc2VQYXRoKCkpLEduKHQsZS5vcHRpb25zKSx0LnN0cm9rZShuKX0odCxlLGkscyk6ZnVuY3Rpb24odCxlLGkscyl7Y29uc3R7c2VnbWVudHM6bixvcHRpb25zOm99PWUsYT1lbyhlKTtmb3IoY29uc3QgciBvZiBuKUduKHQsbyxyLnN0eWxlKSx0LmJlZ2luUGF0aCgpLGEodCxlLHIse3N0YXJ0OmksZW5kOmkrcy0xfSkmJnQuY2xvc2VQYXRoKCksdC5zdHJva2UoKX0odCxlLGkscyl9Y2xhc3Mgbm8gZXh0ZW5kcyBIc3tzdGF0aWMgaWQ9ImxpbmUiO3N0YXRpYyBkZWZhdWx0cz17Ym9yZGVyQ2FwU3R5bGU6ImJ1dHQiLGJvcmRlckRhc2g6W10sYm9yZGVyRGFzaE9mZnNldDowLGJvcmRlckpvaW5TdHlsZToibWl0ZXIiLGJvcmRlcldpZHRoOjMsY2FwQmV6aWVyUG9pbnRzOiEwLGN1YmljSW50ZXJwb2xhdGlvbk1vZGU6ImRlZmF1bHQiLGZpbGw6ITEsc3BhbkdhcHM6ITEsc3RlcHBlZDohMSx0ZW5zaW9uOjB9O3N0YXRpYyBkZWZhdWx0Um91dGVzPXtiYWNrZ3JvdW5kQ29sb3I6ImJhY2tncm91bmRDb2xvciIsYm9yZGVyQ29sb3I6ImJvcmRlckNvbG9yIn07c3RhdGljIGRlc2NyaXB0b3JzPXtfc2NyaXB0YWJsZTohMCxfaW5kZXhhYmxlOnQ9PiJib3JkZXJEYXNoIiE9PXQmJiJmaWxsIiE9PXR9O2NvbnN0cnVjdG9yKHQpe3N1cGVyKCksdGhpcy5hbmltYXRlZD0hMCx0aGlzLm9wdGlvbnM9dm9pZCAwLHRoaXMuX2NoYXJ0PXZvaWQgMCx0aGlzLl9sb29wPXZvaWQgMCx0aGlzLl9mdWxsTG9vcD12b2lkIDAsdGhpcy5fcGF0aD12b2lkIDAsdGhpcy5fcG9pbnRzPXZvaWQgMCx0aGlzLl9zZWdtZW50cz12b2lkIDAsdGhpcy5fZGVjaW1hdGVkPSExLHRoaXMuX3BvaW50c1VwZGF0ZWQ9ITEsdGhpcy5fZGF0YXNldEluZGV4PXZvaWQgMCx0JiZPYmplY3QuYXNzaWduKHRoaXMsdCl9dXBkYXRlQ29udHJvbFBvaW50cyh0LGUpe2NvbnN0IGk9dGhpcy5vcHRpb25zO2lmKChpLnRlbnNpb258fCJtb25vdG9uZSI9PT1pLmN1YmljSW50ZXJwb2xhdGlvbk1vZGUpJiYhaS5zdGVwcGVkJiYhdGhpcy5fcG9pbnRzVXBkYXRlZCl7Y29uc3Qgcz1pLnNwYW5HYXBzP3RoaXMuX2xvb3A6dGhpcy5fZnVsbExvb3A7aGkodGhpcy5fcG9pbnRzLGksdCxzLGUpLHRoaXMuX3BvaW50c1VwZGF0ZWQ9ITB9fXNldCBwb2ludHModCl7dGhpcy5fcG9pbnRzPXQsZGVsZXRlIHRoaXMuX3NlZ21lbnRzLGRlbGV0ZSB0aGlzLl9wYXRoLHRoaXMuX3BvaW50c1VwZGF0ZWQ9ITF9Z2V0IHBvaW50cygpe3JldHVybiB0aGlzLl9wb2ludHN9Z2V0IHNlZ21lbnRzKCl7cmV0dXJuIHRoaXMuX3NlZ21lbnRzfHwodGhpcy5fc2VnbWVudHM9emkodGhpcyx0aGlzLm9wdGlvbnMuc2VnbWVudCkpfWZpcnN0KCl7Y29uc3QgdD10aGlzLnNlZ21lbnRzLGU9dGhpcy5wb2ludHM7cmV0dXJuIHQubGVuZ3RoJiZlW3RbMF0uc3RhcnRdfWxhc3QoKXtjb25zdCB0PXRoaXMuc2VnbWVudHMsZT10aGlzLnBvaW50cyxpPXQubGVuZ3RoO3JldHVybiBpJiZlW3RbaS0xXS5lbmRdfWludGVycG9sYXRlKHQsZSl7Y29uc3QgaT10aGlzLm9wdGlvbnMscz10W2VdLG49dGhpcy5wb2ludHMsbz1JaSh0aGlzLHtwcm9wZXJ0eTplLHN0YXJ0OnMsZW5kOnN9KTtpZighby5sZW5ndGgpcmV0dXJuO2NvbnN0IGE9W10scj1mdW5jdGlvbih0KXtyZXR1cm4gdC5zdGVwcGVkP3BpOnQudGVuc2lvbnx8Im1vbm90b25lIj09PXQuY3ViaWNJbnRlcnBvbGF0aW9uTW9kZT9taTpnaX0oaSk7bGV0IGwsaDtmb3IobD0wLGg9by5sZW5ndGg7bDxoOysrbCl7Y29uc3R7c3RhcnQ6aCxlbmQ6Y309b1tsXSxkPW5baF0sdT1uW2NdO2lmKGQ9PT11KXthLnB1c2goZCk7Y29udGludWV9Y29uc3QgZj1yKGQsdSxNYXRoLmFicygocy1kW2VdKS8odVtlXS1kW2VdKSksaS5zdGVwcGVkKTtmW2VdPXRbZV0sYS5wdXNoKGYpfXJldHVybiAxPT09YS5sZW5ndGg\/YVswXTphfXBhdGhTZWdtZW50KHQsZSxpKXtyZXR1cm4gZW8odGhpcykodCx0aGlzLGUsaSl9cGF0aCh0LGUsaSl7Y29uc3Qgcz10aGlzLnNlZ21lbnRzLG49ZW8odGhpcyk7bGV0IG89dGhpcy5fbG9vcDtlPWV8fDAsaT1pfHx0aGlzLnBvaW50cy5sZW5ndGgtZTtmb3IoY29uc3QgYSBvZiBzKW8mPW4odCx0aGlzLGEse3N0YXJ0OmUsZW5kOmUraS0xfSk7cmV0dXJuISFvfWRyYXcodCxlLGkscyl7Y29uc3Qgbj10aGlzLm9wdGlvbnN8fHt9Oyh0aGlzLnBvaW50c3x8W10pLmxlbmd0aCYmbi5ib3JkZXJXaWR0aCYmKHQuc2F2ZSgpLHNvKHQsdGhpcyxpLHMpLHQucmVzdG9yZSgpKSx0aGlzLmFuaW1hdGVkJiYodGhpcy5fcG9pbnRzVXBkYXRlZD0hMSx0aGlzLl9wYXRoPXZvaWQgMCl9fWZ1bmN0aW9uIG9vKHQsZSxpLHMpe2NvbnN0IG49dC5vcHRpb25zLHtbaV06b309dC5nZXRQcm9wcyhbaV0scyk7cmV0dXJuIE1hdGguYWJzKGUtbyk8bi5yYWRpdXMrbi5oaXRSYWRpdXN9ZnVuY3Rpb24gYW8odCxlKXtjb25zdHt4OmkseTpzLGJhc2U6bix3aWR0aDpvLGhlaWdodDphfT10LmdldFByb3BzKFsieCIsInkiLCJiYXNlIiwid2lkdGgiLCJoZWlnaHQiXSxlKTtsZXQgcixsLGgsYyxkO3JldHVybiB0Lmhvcml6b250YWw\/KGQ9YS8yLHI9TWF0aC5taW4oaSxuKSxsPU1hdGgubWF4KGksbiksaD1zLWQsYz1zK2QpOihkPW8vMixyPWktZCxsPWkrZCxoPU1hdGgubWluKHMsbiksYz1NYXRoLm1heChzLG4pKSx7bGVmdDpyLHRvcDpoLHJpZ2h0OmwsYm90dG9tOmN9fWZ1bmN0aW9uIHJvKHQsZSxpLHMpe3JldHVybiB0PzA6SihlLGkscyl9ZnVuY3Rpb24gbG8odCl7Y29uc3QgZT1hbyh0KSxpPWUucmlnaHQtZS5sZWZ0LHM9ZS5ib3R0b20tZS50b3Asbj1mdW5jdGlvbih0LGUsaSl7Y29uc3Qgcz10Lm9wdGlvbnMuYm9yZGVyV2lkdGgsbj10LmJvcmRlclNraXBwZWQsbz1NaShzKTtyZXR1cm57dDpybyhuLnRvcCxvLnRvcCwwLGkpLHI6cm8obi5yaWdodCxvLnJpZ2h0LDAsZSksYjpybyhuLmJvdHRvbSxvLmJvdHRvbSwwLGkpLGw6cm8obi5sZWZ0LG8ubGVmdCwwLGUpfX0odCxpLzIscy8yKSxhPWZ1bmN0aW9uKHQsZSxpKXtjb25zdHtlbmFibGVCb3JkZXJSYWRpdXM6c309dC5nZXRQcm9wcyhbImVuYWJsZUJvcmRlclJhZGl1cyJdKSxuPXQub3B0aW9ucy5ib3JkZXJSYWRpdXMsYT13aShuKSxyPU1hdGgubWluKGUsaSksbD10LmJvcmRlclNraXBwZWQsaD1zfHxvKG4pO3JldHVybnt0b3BMZWZ0OnJvKCFofHxsLnRvcHx8bC5sZWZ0LGEudG9wTGVmdCwwLHIpLHRvcFJpZ2h0OnJvKCFofHxsLnRvcHx8bC5yaWdodCxhLnRvcFJpZ2h0LDAsciksYm90dG9tTGVmdDpybyghaHx8bC5ib3R0b218fGwubGVmdCxhLmJvdHRvbUxlZnQsMCxyKSxib3R0b21SaWdodDpybyghaHx8bC5ib3R0b218fGwucmlnaHQsYS5ib3R0b21SaWdodCwwLHIpfX0odCxpLzIscy8yKTtyZXR1cm57b3V0ZXI6e3g6ZS5sZWZ0LHk6ZS50b3AsdzppLGg6cyxyYWRpdXM6YX0saW5uZXI6e3g6ZS5sZWZ0K24ubCx5OmUudG9wK24udCx3Omktbi5sLW4ucixoOnMtbi50LW4uYixyYWRpdXM6e3RvcExlZnQ6TWF0aC5tYXgoMCxhLnRvcExlZnQtTWF0aC5tYXgobi50LG4ubCkpLHRvcFJpZ2h0Ok1hdGgubWF4KDAsYS50b3BSaWdodC1NYXRoLm1heChuLnQsbi5yKSksYm90dG9tTGVmdDpNYXRoLm1heCgwLGEuYm90dG9tTGVmdC1NYXRoLm1heChuLmIsbi5sKSksYm90dG9tUmlnaHQ6TWF0aC5tYXgoMCxhLmJvdHRvbVJpZ2h0LU1hdGgubWF4KG4uYixuLnIpKX19fX1mdW5jdGlvbiBobyh0LGUsaSxzKXtjb25zdCBuPW51bGw9PT1lLG89bnVsbD09PWksYT10JiYhKG4mJm8pJiZhbyh0LHMpO3JldHVybiBhJiYobnx8dHQoZSxhLmxlZnQsYS5yaWdodCkpJiYob3x8dHQoaSxhLnRvcCxhLmJvdHRvbSkpfWZ1bmN0aW9uIGNvKHQsZSl7dC5yZWN0KGUueCxlLnksZS53LGUuaCl9ZnVuY3Rpb24gdW8odCxlLGk9e30pe2NvbnN0IHM9dC54IT09aS54Py1lOjAsbj10LnkhPT1pLnk\/LWU6MCxvPSh0LngrdC53IT09aS54K2kudz9lOjApLXMsYT0odC55K3QuaCE9PWkueStpLmg\/ZTowKS1uO3JldHVybnt4OnQueCtzLHk6dC55K24sdzp0LncrbyxoOnQuaCthLHJhZGl1czp0LnJhZGl1c319dmFyIGZvPU9iamVjdC5mcmVlemUoe19fcHJvdG9fXzpudWxsLEFyY0VsZW1lbnQ6Y2xhc3MgZXh0ZW5kcyBIc3tzdGF0aWMgaWQ9ImFyYyI7c3RhdGljIGRlZmF1bHRzPXtib3JkZXJBbGlnbjoiY2VudGVyIixib3JkZXJDb2xvcjoiI2ZmZiIsYm9yZGVyRGFzaDpbXSxib3JkZXJEYXNoT2Zmc2V0OjAsYm9yZGVySm9pblN0eWxlOnZvaWQgMCxib3JkZXJSYWRpdXM6MCxib3JkZXJXaWR0aDoyLG9mZnNldDowLHNwYWNpbmc6MCxhbmdsZTp2b2lkIDAsY2lyY3VsYXI6ITB9O3N0YXRpYyBkZWZhdWx0Um91dGVzPXtiYWNrZ3JvdW5kQ29sb3I6ImJhY2tncm91bmRDb2xvciJ9O3N0YXRpYyBkZXNjcmlwdG9ycz17X3NjcmlwdGFibGU6ITAsX2luZGV4YWJsZTp0PT4iYm9yZGVyRGFzaCIhPT10fTtjaXJjdW1mZXJlbmNlO2VuZEFuZ2xlO2Z1bGxDaXJjbGVzO2lubmVyUmFkaXVzO291dGVyUmFkaXVzO3BpeGVsTWFyZ2luO3N0YXJ0QW5nbGU7Y29uc3RydWN0b3IodCl7c3VwZXIoKSx0aGlzLm9wdGlvbnM9dm9pZCAwLHRoaXMuY2lyY3VtZmVyZW5jZT12b2lkIDAsdGhpcy5zdGFydEFuZ2xlPXZvaWQgMCx0aGlzLmVuZEFuZ2xlPXZvaWQgMCx0aGlzLmlubmVyUmFkaXVzPXZvaWQgMCx0aGlzLm91dGVyUmFkaXVzPXZvaWQgMCx0aGlzLnBpeGVsTWFyZ2luPTAsdGhpcy5mdWxsQ2lyY2xlcz0wLHQmJk9iamVjdC5hc3NpZ24odGhpcyx0KX1pblJhbmdlKHQsZSxpKXtjb25zdCBzPXRoaXMuZ2V0UHJvcHMoWyJ4IiwieSJdLGkpLHthbmdsZTpuLGRpc3RhbmNlOm99PVgocyx7eDp0LHk6ZX0pLHtzdGFydEFuZ2xlOmEsZW5kQW5nbGU6cixpbm5lclJhZGl1czpoLG91dGVyUmFkaXVzOmMsY2lyY3VtZmVyZW5jZTpkfT10aGlzLmdldFByb3BzKFsic3RhcnRBbmdsZSIsImVuZEFuZ2xlIiwiaW5uZXJSYWRpdXMiLCJvdXRlclJhZGl1cyIsImNpcmN1bWZlcmVuY2UiXSxpKSx1PSh0aGlzLm9wdGlvbnMuc3BhY2luZyt0aGlzLm9wdGlvbnMuYm9yZGVyV2lkdGgpLzIsZj1sKGQsci1hKT49T3x8WihuLGEsciksZz10dChvLGgrdSxjK3UpO3JldHVybiBmJiZnfWdldENlbnRlclBvaW50KHQpe2NvbnN0e3g6ZSx5Omksc3RhcnRBbmdsZTpzLGVuZEFuZ2xlOm4saW5uZXJSYWRpdXM6byxvdXRlclJhZGl1czphfT10aGlzLmdldFByb3BzKFsieCIsInkiLCJzdGFydEFuZ2xlIiwiZW5kQW5nbGUiLCJpbm5lclJhZGl1cyIsIm91dGVyUmFkaXVzIl0sdCkse29mZnNldDpyLHNwYWNpbmc6bH09dGhpcy5vcHRpb25zLGg9KHMrbikvMixjPShvK2ErbCtyKS8yO3JldHVybnt4OmUrTWF0aC5jb3MoaCkqYyx5OmkrTWF0aC5zaW4oaCkqY319dG9vbHRpcFBvc2l0aW9uKHQpe3JldHVybiB0aGlzLmdldENlbnRlclBvaW50KHQpfWRyYXcodCl7Y29uc3R7b3B0aW9uczplLGNpcmN1bWZlcmVuY2U6aX09dGhpcyxzPShlLm9mZnNldHx8MCkvNCxuPShlLnNwYWNpbmd8fDApLzIsbz1lLmNpcmN1bGFyO2lmKHRoaXMucGl4ZWxNYXJnaW49ImlubmVyIj09PWUuYm9yZGVyQWxpZ24\/LjMzOjAsdGhpcy5mdWxsQ2lyY2xlcz1pPk8\/TWF0aC5mbG9vcihpL08pOjAsMD09PWl8fHRoaXMuaW5uZXJSYWRpdXM8MHx8dGhpcy5vdXRlclJhZGl1czwwKXJldHVybjt0LnNhdmUoKTtjb25zdCBhPSh0aGlzLnN0YXJ0QW5nbGUrdGhpcy5lbmRBbmdsZSkvMjt0LnRyYW5zbGF0ZShNYXRoLmNvcyhhKSpzLE1hdGguc2luKGEpKnMpO2NvbnN0IHI9cyooMS1NYXRoLnNpbihNYXRoLm1pbihDLGl8fDApKSk7dC5maWxsU3R5bGU9ZS5iYWNrZ3JvdW5kQ29sb3IsdC5zdHJva2VTdHlsZT1lLmJvcmRlckNvbG9yLGZ1bmN0aW9uKHQsZSxpLHMsbil7Y29uc3R7ZnVsbENpcmNsZXM6byxzdGFydEFuZ2xlOmEsY2lyY3VtZmVyZW5jZTpyfT1lO2xldCBsPWUuZW5kQW5nbGU7aWYobyl7cW4odCxlLGkscyxsLG4pO2ZvcihsZXQgZT0wO2U8bzsrK2UpdC5maWxsKCk7aXNOYU4ocil8fChsPWErKHIlT3x8TykpfXFuKHQsZSxpLHMsbCxuKSx0LmZpbGwoKX0odCx0aGlzLHIsbixvKSxLbih0LHRoaXMscixuLG8pLHQucmVzdG9yZSgpfX0sQmFyRWxlbWVudDpjbGFzcyBleHRlbmRzIEhze3N0YXRpYyBpZD0iYmFyIjtzdGF0aWMgZGVmYXVsdHM9e2JvcmRlclNraXBwZWQ6InN0YXJ0Iixib3JkZXJXaWR0aDowLGJvcmRlclJhZGl1czowLGluZmxhdGVBbW91bnQ6ImF1dG8iLHBvaW50U3R5bGU6dm9pZCAwfTtzdGF0aWMgZGVmYXVsdFJvdXRlcz17YmFja2dyb3VuZENvbG9yOiJiYWNrZ3JvdW5kQ29sb3IiLGJvcmRlckNvbG9yOiJib3JkZXJDb2xvciJ9O2NvbnN0cnVjdG9yKHQpe3N1cGVyKCksdGhpcy5vcHRpb25zPXZvaWQgMCx0aGlzLmhvcml6b250YWw9dm9pZCAwLHRoaXMuYmFzZT12b2lkIDAsdGhpcy53aWR0aD12b2lkIDAsdGhpcy5oZWlnaHQ9dm9pZCAwLHRoaXMuaW5mbGF0ZUFtb3VudD12b2lkIDAsdCYmT2JqZWN0LmFzc2lnbih0aGlzLHQpfWRyYXcodCl7Y29uc3R7aW5mbGF0ZUFtb3VudDplLG9wdGlvbnM6e2JvcmRlckNvbG9yOmksYmFja2dyb3VuZENvbG9yOnN9fT10aGlzLHtpbm5lcjpuLG91dGVyOm99PWxvKHRoaXMpLGE9KHI9by5yYWRpdXMpLnRvcExlZnR8fHIudG9wUmlnaHR8fHIuYm90dG9tTGVmdHx8ci5ib3R0b21SaWdodD9IZTpjbzt2YXIgcjt0LnNhdmUoKSxvLnc9PT1uLncmJm8uaD09PW4uaHx8KHQuYmVnaW5QYXRoKCksYSh0LHVvKG8sZSxuKSksdC5jbGlwKCksYSh0LHVvKG4sLWUsbykpLHQuZmlsbFN0eWxlPWksdC5maWxsKCJldmVub2RkIikpLHQuYmVnaW5QYXRoKCksYSh0LHVvKG4sZSkpLHQuZmlsbFN0eWxlPXMsdC5maWxsKCksdC5yZXN0b3JlKCl9aW5SYW5nZSh0LGUsaSl7cmV0dXJuIGhvKHRoaXMsdCxlLGkpfWluWFJhbmdlKHQsZSl7cmV0dXJuIGhvKHRoaXMsdCxudWxsLGUpfWluWVJhbmdlKHQsZSl7cmV0dXJuIGhvKHRoaXMsbnVsbCx0LGUpfWdldENlbnRlclBvaW50KHQpe2NvbnN0e3g6ZSx5OmksYmFzZTpzLGhvcml6b250YWw6bn09dGhpcy5nZXRQcm9wcyhbIngiLCJ5IiwiYmFzZSIsImhvcml6b250YWwiXSx0KTtyZXR1cm57eDpuPyhlK3MpLzI6ZSx5Om4\/aTooaStzKS8yfX1nZXRSYW5nZSh0KXtyZXR1cm4ieCI9PT10P3RoaXMud2lkdGgvMjp0aGlzLmhlaWdodC8yfX0sTGluZUVsZW1lbnQ6bm8sUG9pbnRFbGVtZW50OmNsYXNzIGV4dGVuZHMgSHN7c3RhdGljIGlkPSJwb2ludCI7cGFyc2VkO3NraXA7c3RvcDtzdGF0aWMgZGVmYXVsdHM9e2JvcmRlcldpZHRoOjEsaGl0UmFkaXVzOjEsaG92ZXJCb3JkZXJXaWR0aDoxLGhvdmVyUmFkaXVzOjQscG9pbnRTdHlsZToiY2lyY2xlIixyYWRpdXM6Myxyb3RhdGlvbjowfTtzdGF0aWMgZGVmYXVsdFJvdXRlcz17YmFja2dyb3VuZENvbG9yOiJiYWNrZ3JvdW5kQ29sb3IiLGJvcmRlckNvbG9yOiJib3JkZXJDb2xvciJ9O2NvbnN0cnVjdG9yKHQpe3N1cGVyKCksdGhpcy5vcHRpb25zPXZvaWQgMCx0aGlzLnBhcnNlZD12b2lkIDAsdGhpcy5za2lwPXZvaWQgMCx0aGlzLnN0b3A9dm9pZCAwLHQmJk9iamVjdC5hc3NpZ24odGhpcyx0KX1pblJhbmdlKHQsZSxpKXtjb25zdCBzPXRoaXMub3B0aW9ucyx7eDpuLHk6b309dGhpcy5nZXRQcm9wcyhbIngiLCJ5Il0saSk7cmV0dXJuIE1hdGgucG93KHQtbiwyKStNYXRoLnBvdyhlLW8sMik8TWF0aC5wb3cocy5oaXRSYWRpdXMrcy5yYWRpdXMsMil9aW5YUmFuZ2UodCxlKXtyZXR1cm4gb28odGhpcyx0LCJ4IixlKX1pbllSYW5nZSh0LGUpe3JldHVybiBvbyh0aGlzLHQsInkiLGUpfWdldENlbnRlclBvaW50KHQpe2NvbnN0e3g6ZSx5Oml9PXRoaXMuZ2V0UHJvcHMoWyJ4IiwieSJdLHQpO3JldHVybnt4OmUseTppfX1zaXplKHQpe2xldCBlPSh0PXR8fHRoaXMub3B0aW9uc3x8e30pLnJhZGl1c3x8MDtlPU1hdGgubWF4KGUsZSYmdC5ob3ZlclJhZGl1c3x8MCk7cmV0dXJuIDIqKGUrKGUmJnQuYm9yZGVyV2lkdGh8fDApKX1kcmF3KHQsZSl7Y29uc3QgaT10aGlzLm9wdGlvbnM7dGhpcy5za2lwfHxpLnJhZGl1czwuMXx8IVJlKHRoaXMsZSx0aGlzLnNpemUoaSkvMil8fCh0LnN0cm9rZVN0eWxlPWkuYm9yZGVyQ29sb3IsdC5saW5lV2lkdGg9aS5ib3JkZXJXaWR0aCx0LmZpbGxTdHlsZT1pLmJhY2tncm91bmRDb2xvcixMZSh0LGksdGhpcy54LHRoaXMueSkpfWdldFJhbmdlKCl7Y29uc3QgdD10aGlzLm9wdGlvbnN8fHt9O3JldHVybiB0LnJhZGl1cyt0LmhpdFJhZGl1c319fSk7ZnVuY3Rpb24gZ28odCxlLGkscyl7Y29uc3Qgbj10LmluZGV4T2YoZSk7aWYoLTE9PT1uKXJldHVybigodCxlLGkscyk9Pigic3RyaW5nIj09dHlwZW9mIGU\/KGk9dC5wdXNoKGUpLTEscy51bnNoaWZ0KHtpbmRleDppLGxhYmVsOmV9KSk6aXNOYU4oZSkmJihpPW51bGwpLGkpKSh0LGUsaSxzKTtyZXR1cm4gbiE9PXQubGFzdEluZGV4T2YoZSk\/aTpufWZ1bmN0aW9uIHBvKHQpe2NvbnN0IGU9dGhpcy5nZXRMYWJlbHMoKTtyZXR1cm4gdD49MCYmdDxlLmxlbmd0aD9lW3RdOnR9ZnVuY3Rpb24gbW8odCxlLHtob3Jpem9udGFsOmksbWluUm90YXRpb246c30pe2NvbnN0IG49JChzKSxvPShpP01hdGguc2luKG4pOk1hdGguY29zKG4pKXx8LjAwMSxhPS43NSplKigiIit0KS5sZW5ndGg7cmV0dXJuIE1hdGgubWluKGUvbyxhKX1jbGFzcyBibyBleHRlbmRzIEpze2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpLHRoaXMuc3RhcnQ9dm9pZCAwLHRoaXMuZW5kPXZvaWQgMCx0aGlzLl9zdGFydFZhbHVlPXZvaWQgMCx0aGlzLl9lbmRWYWx1ZT12b2lkIDAsdGhpcy5fdmFsdWVSYW5nZT0wfXBhcnNlKHQsZSl7cmV0dXJuIHModCl8fCgibnVtYmVyIj09dHlwZW9mIHR8fHQgaW5zdGFuY2VvZiBOdW1iZXIpJiYhaXNGaW5pdGUoK3QpP251bGw6K3R9aGFuZGxlVGlja1JhbmdlT3B0aW9ucygpe2NvbnN0e2JlZ2luQXRaZXJvOnR9PXRoaXMub3B0aW9ucyx7bWluRGVmaW5lZDplLG1heERlZmluZWQ6aX09dGhpcy5nZXRVc2VyQm91bmRzKCk7bGV0e21pbjpzLG1heDpufT10aGlzO2NvbnN0IG89dD0+cz1lP3M6dCxhPXQ9Pm49aT9uOnQ7aWYodCl7Y29uc3QgdD1GKHMpLGU9RihuKTt0PDAmJmU8MD9hKDApOnQ+MCYmZT4wJiZvKDApfWlmKHM9PT1uKXtsZXQgZT0wPT09bj8xOk1hdGguYWJzKC4wNSpuKTthKG4rZSksdHx8byhzLWUpfXRoaXMubWluPXMsdGhpcy5tYXg9bn1nZXRUaWNrTGltaXQoKXtjb25zdCB0PXRoaXMub3B0aW9ucy50aWNrcztsZXQgZSx7bWF4VGlja3NMaW1pdDppLHN0ZXBTaXplOnN9PXQ7cmV0dXJuIHM\/KGU9TWF0aC5jZWlsKHRoaXMubWF4L3MpLU1hdGguZmxvb3IodGhpcy5taW4vcykrMSxlPjFlMyYmKGNvbnNvbGUud2Fybihgc2NhbGVzLiR7dGhpcy5pZH0udGlja3Muc3RlcFNpemU6ICR7c30gd291bGQgcmVzdWx0IGdlbmVyYXRpbmcgdXAgdG8gJHtlfSB0aWNrcy4gTGltaXRpbmcgdG8gMTAwMC5gKSxlPTFlMykpOihlPXRoaXMuY29tcHV0ZVRpY2tMaW1pdCgpLGk9aXx8MTEpLGkmJihlPU1hdGgubWluKGksZSkpLGV9Y29tcHV0ZVRpY2tMaW1pdCgpe3JldHVybiBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFl9YnVpbGRUaWNrcygpe2NvbnN0IHQ9dGhpcy5vcHRpb25zLGU9dC50aWNrcztsZXQgaT10aGlzLmdldFRpY2tMaW1pdCgpO2k9TWF0aC5tYXgoMixpKTtjb25zdCBuPWZ1bmN0aW9uKHQsZSl7Y29uc3QgaT1bXSx7Ym91bmRzOm4sc3RlcDpvLG1pbjphLG1heDpyLHByZWNpc2lvbjpsLGNvdW50OmgsbWF4VGlja3M6YyxtYXhEaWdpdHM6ZCxpbmNsdWRlQm91bmRzOnV9PXQsZj1vfHwxLGc9Yy0xLHttaW46cCxtYXg6bX09ZSxiPSFzKGEpLHg9IXMociksXz0hcyhoKSx5PShtLXApLyhkKzEpO2xldCB2LE0sdyxrLFM9QigobS1wKS9nL2YpKmY7aWYoUzwxZS0xNCYmIWImJiF4KXJldHVyblt7dmFsdWU6cH0se3ZhbHVlOm19XTtrPU1hdGguY2VpbChtL1MpLU1hdGguZmxvb3IocC9TKSxrPmcmJihTPUIoaypTL2cvZikqZikscyhsKXx8KHY9TWF0aC5wb3coMTAsbCksUz1NYXRoLmNlaWwoUyp2KS92KSwidGlja3MiPT09bj8oTT1NYXRoLmZsb29yKHAvUykqUyx3PU1hdGguY2VpbChtL1MpKlMpOihNPXAsdz1tKSxiJiZ4JiZvJiZIKChyLWEpL28sUy8xZTMpPyhrPU1hdGgucm91bmQoTWF0aC5taW4oKHItYSkvUyxjKSksUz0oci1hKS9rLE09YSx3PXIpOl8\/KE09Yj9hOk0sdz14P3I6dyxrPWgtMSxTPSh3LU0pL2spOihrPSh3LU0pL1Msaz1WKGssTWF0aC5yb3VuZChrKSxTLzFlMyk\/TWF0aC5yb3VuZChrKTpNYXRoLmNlaWwoaykpO2NvbnN0IFA9TWF0aC5tYXgoVShTKSxVKE0pKTt2PU1hdGgucG93KDEwLHMobCk\/UDpsKSxNPU1hdGgucm91bmQoTSp2KS92LHc9TWF0aC5yb3VuZCh3KnYpL3Y7bGV0IEQ9MDtmb3IoYiYmKHUmJk0hPT1hPyhpLnB1c2goe3ZhbHVlOmF9KSxNPGEmJkQrKyxWKE1hdGgucm91bmQoKE0rRCpTKSp2KS92LGEsbW8oYSx5LHQpKSYmRCsrKTpNPGEmJkQrKyk7RDxrOysrRCl7Y29uc3QgdD1NYXRoLnJvdW5kKChNK0QqUykqdikvdjtpZih4JiZ0PnIpYnJlYWs7aS5wdXNoKHt2YWx1ZTp0fSl9cmV0dXJuIHgmJnUmJnchPT1yP2kubGVuZ3RoJiZWKGlbaS5sZW5ndGgtMV0udmFsdWUscixtbyhyLHksdCkpP2lbaS5sZW5ndGgtMV0udmFsdWU9cjppLnB1c2goe3ZhbHVlOnJ9KTp4JiZ3IT09cnx8aS5wdXNoKHt2YWx1ZTp3fSksaX0oe21heFRpY2tzOmksYm91bmRzOnQuYm91bmRzLG1pbjp0Lm1pbixtYXg6dC5tYXgscHJlY2lzaW9uOmUucHJlY2lzaW9uLHN0ZXA6ZS5zdGVwU2l6ZSxjb3VudDplLmNvdW50LG1heERpZ2l0czp0aGlzLl9tYXhEaWdpdHMoKSxob3Jpem9udGFsOnRoaXMuaXNIb3Jpem9udGFsKCksbWluUm90YXRpb246ZS5taW5Sb3RhdGlvbnx8MCxpbmNsdWRlQm91bmRzOiExIT09ZS5pbmNsdWRlQm91bmRzfSx0aGlzLl9yYW5nZXx8dGhpcyk7cmV0dXJuInRpY2tzIj09PXQuYm91bmRzJiZqKG4sdGhpcywidmFsdWUiKSx0LnJldmVyc2U\/KG4ucmV2ZXJzZSgpLHRoaXMuc3RhcnQ9dGhpcy5tYXgsdGhpcy5lbmQ9dGhpcy5taW4pOih0aGlzLnN0YXJ0PXRoaXMubWluLHRoaXMuZW5kPXRoaXMubWF4KSxufWNvbmZpZ3VyZSgpe2NvbnN0IHQ9dGhpcy50aWNrcztsZXQgZT10aGlzLm1pbixpPXRoaXMubWF4O2lmKHN1cGVyLmNvbmZpZ3VyZSgpLHRoaXMub3B0aW9ucy5vZmZzZXQmJnQubGVuZ3RoKXtjb25zdCBzPShpLWUpL01hdGgubWF4KHQubGVuZ3RoLTEsMSkvMjtlLT1zLGkrPXN9dGhpcy5fc3RhcnRWYWx1ZT1lLHRoaXMuX2VuZFZhbHVlPWksdGhpcy5fdmFsdWVSYW5nZT1pLWV9Z2V0TGFiZWxGb3JWYWx1ZSh0KXtyZXR1cm4gbmUodCx0aGlzLmNoYXJ0Lm9wdGlvbnMubG9jYWxlLHRoaXMub3B0aW9ucy50aWNrcy5mb3JtYXQpfX1jbGFzcyB4byBleHRlbmRzIGJve3N0YXRpYyBpZD0ibGluZWFyIjtzdGF0aWMgZGVmYXVsdHM9e3RpY2tzOntjYWxsYmFjazphZS5mb3JtYXR0ZXJzLm51bWVyaWN9fTtkZXRlcm1pbmVEYXRhTGltaXRzKCl7Y29uc3R7bWluOnQsbWF4OmV9PXRoaXMuZ2V0TWluTWF4KCEwKTt0aGlzLm1pbj1hKHQpP3Q6MCx0aGlzLm1heD1hKGUpP2U6MSx0aGlzLmhhbmRsZVRpY2tSYW5nZU9wdGlvbnMoKX1jb21wdXRlVGlja0xpbWl0KCl7Y29uc3QgdD10aGlzLmlzSG9yaXpvbnRhbCgpLGU9dD90aGlzLndpZHRoOnRoaXMuaGVpZ2h0LGk9JCh0aGlzLm9wdGlvbnMudGlja3MubWluUm90YXRpb24pLHM9KHQ\/TWF0aC5zaW4oaSk6TWF0aC5jb3MoaSkpfHwuMDAxLG49dGhpcy5fcmVzb2x2ZVRpY2tGb250T3B0aW9ucygwKTtyZXR1cm4gTWF0aC5jZWlsKGUvTWF0aC5taW4oNDAsbi5saW5lSGVpZ2h0L3MpKX1nZXRQaXhlbEZvclZhbHVlKHQpe3JldHVybiBudWxsPT09dD9OYU46dGhpcy5nZXRQaXhlbEZvckRlY2ltYWwoKHQtdGhpcy5fc3RhcnRWYWx1ZSkvdGhpcy5fdmFsdWVSYW5nZSl9Z2V0VmFsdWVGb3JQaXhlbCh0KXtyZXR1cm4gdGhpcy5fc3RhcnRWYWx1ZSt0aGlzLmdldERlY2ltYWxGb3JQaXhlbCh0KSp0aGlzLl92YWx1ZVJhbmdlfX1jb25zdCBfbz10PT5NYXRoLmZsb29yKHoodCkpLHlvPSh0LGUpPT5NYXRoLnBvdygxMCxfbyh0KStlKTtmdW5jdGlvbiB2byh0KXtyZXR1cm4gMT09PXQvTWF0aC5wb3coMTAsX28odCkpfWZ1bmN0aW9uIE1vKHQsZSxpKXtjb25zdCBzPU1hdGgucG93KDEwLGkpLG49TWF0aC5mbG9vcih0L3MpO3JldHVybiBNYXRoLmNlaWwoZS9zKS1ufWZ1bmN0aW9uIHdvKHQse21pbjplLG1heDppfSl7ZT1yKHQubWluLGUpO2NvbnN0IHM9W10sbj1fbyhlKTtsZXQgbz1mdW5jdGlvbih0LGUpe2xldCBpPV9vKGUtdCk7Zm9yKDtNbyh0LGUsaSk+MTA7KWkrKztmb3IoO01vKHQsZSxpKTwxMDspaS0tO3JldHVybiBNYXRoLm1pbihpLF9vKHQpKX0oZSxpKSxhPW88MD9NYXRoLnBvdygxMCxNYXRoLmFicyhvKSk6MTtjb25zdCBsPU1hdGgucG93KDEwLG8pLGg9bj5vP01hdGgucG93KDEwLG4pOjAsYz1NYXRoLnJvdW5kKChlLWgpKmEpL2EsZD1NYXRoLmZsb29yKChlLWgpL2wvMTApKmwqMTA7bGV0IHU9TWF0aC5mbG9vcigoYy1kKS9NYXRoLnBvdygxMCxvKSksZj1yKHQubWluLE1hdGgucm91bmQoKGgrZCt1Kk1hdGgucG93KDEwLG8pKSphKS9hKTtmb3IoO2Y8aTspcy5wdXNoKHt2YWx1ZTpmLG1ham9yOnZvKGYpLHNpZ25pZmljYW5kOnV9KSx1Pj0xMD91PXU8MTU\/MTU6MjA6dSsrLHU+PTIwJiYobysrLHU9MixhPW8+PTA\/MTphKSxmPU1hdGgucm91bmQoKGgrZCt1Kk1hdGgucG93KDEwLG8pKSphKS9hO2NvbnN0IGc9cih0Lm1heCxmKTtyZXR1cm4gcy5wdXNoKHt2YWx1ZTpnLG1ham9yOnZvKGcpLHNpZ25pZmljYW5kOnV9KSxzfWNsYXNzIGtvIGV4dGVuZHMgSnN7c3RhdGljIGlkPSJsb2dhcml0aG1pYyI7c3RhdGljIGRlZmF1bHRzPXt0aWNrczp7Y2FsbGJhY2s6YWUuZm9ybWF0dGVycy5sb2dhcml0aG1pYyxtYWpvcjp7ZW5hYmxlZDohMH19fTtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KSx0aGlzLnN0YXJ0PXZvaWQgMCx0aGlzLmVuZD12b2lkIDAsdGhpcy5fc3RhcnRWYWx1ZT12b2lkIDAsdGhpcy5fdmFsdWVSYW5nZT0wfXBhcnNlKHQsZSl7Y29uc3QgaT1iby5wcm90b3R5cGUucGFyc2UuYXBwbHkodGhpcyxbdCxlXSk7aWYoMCE9PWkpcmV0dXJuIGEoaSkmJmk+MD9pOm51bGw7dGhpcy5femVybz0hMH1kZXRlcm1pbmVEYXRhTGltaXRzKCl7Y29uc3R7bWluOnQsbWF4OmV9PXRoaXMuZ2V0TWluTWF4KCEwKTt0aGlzLm1pbj1hKHQpP01hdGgubWF4KDAsdCk6bnVsbCx0aGlzLm1heD1hKGUpP01hdGgubWF4KDAsZSk6bnVsbCx0aGlzLm9wdGlvbnMuYmVnaW5BdFplcm8mJih0aGlzLl96ZXJvPSEwKSx0aGlzLl96ZXJvJiZ0aGlzLm1pbiE9PXRoaXMuX3N1Z2dlc3RlZE1pbiYmIWEodGhpcy5fdXNlck1pbikmJih0aGlzLm1pbj10PT09eW8odGhpcy5taW4sMCk\/eW8odGhpcy5taW4sLTEpOnlvKHRoaXMubWluLDApKSx0aGlzLmhhbmRsZVRpY2tSYW5nZU9wdGlvbnMoKX1oYW5kbGVUaWNrUmFuZ2VPcHRpb25zKCl7Y29uc3R7bWluRGVmaW5lZDp0LG1heERlZmluZWQ6ZX09dGhpcy5nZXRVc2VyQm91bmRzKCk7bGV0IGk9dGhpcy5taW4scz10aGlzLm1heDtjb25zdCBuPWU9Pmk9dD9pOmUsbz10PT5zPWU\/czp0O2k9PT1zJiYoaTw9MD8obigxKSxvKDEwKSk6KG4oeW8oaSwtMSkpLG8oeW8ocywxKSkpKSxpPD0wJiZuKHlvKHMsLTEpKSxzPD0wJiZvKHlvKGksMSkpLHRoaXMubWluPWksdGhpcy5tYXg9c31idWlsZFRpY2tzKCl7Y29uc3QgdD10aGlzLm9wdGlvbnMsZT13byh7bWluOnRoaXMuX3VzZXJNaW4sbWF4OnRoaXMuX3VzZXJNYXh9LHRoaXMpO3JldHVybiJ0aWNrcyI9PT10LmJvdW5kcyYmaihlLHRoaXMsInZhbHVlIiksdC5yZXZlcnNlPyhlLnJldmVyc2UoKSx0aGlzLnN0YXJ0PXRoaXMubWF4LHRoaXMuZW5kPXRoaXMubWluKToodGhpcy5zdGFydD10aGlzLm1pbix0aGlzLmVuZD10aGlzLm1heCksZX1nZXRMYWJlbEZvclZhbHVlKHQpe3JldHVybiB2b2lkIDA9PT10PyIwIjpuZSh0LHRoaXMuY2hhcnQub3B0aW9ucy5sb2NhbGUsdGhpcy5vcHRpb25zLnRpY2tzLmZvcm1hdCl9Y29uZmlndXJlKCl7Y29uc3QgdD10aGlzLm1pbjtzdXBlci5jb25maWd1cmUoKSx0aGlzLl9zdGFydFZhbHVlPXoodCksdGhpcy5fdmFsdWVSYW5nZT16KHRoaXMubWF4KS16KHQpfWdldFBpeGVsRm9yVmFsdWUodCl7cmV0dXJuIHZvaWQgMCE9PXQmJjAhPT10fHwodD10aGlzLm1pbiksbnVsbD09PXR8fGlzTmFOKHQpP05hTjp0aGlzLmdldFBpeGVsRm9yRGVjaW1hbCh0PT09dGhpcy5taW4\/MDooeih0KS10aGlzLl9zdGFydFZhbHVlKS90aGlzLl92YWx1ZVJhbmdlKX1nZXRWYWx1ZUZvclBpeGVsKHQpe2NvbnN0IGU9dGhpcy5nZXREZWNpbWFsRm9yUGl4ZWwodCk7cmV0dXJuIE1hdGgucG93KDEwLHRoaXMuX3N0YXJ0VmFsdWUrZSp0aGlzLl92YWx1ZVJhbmdlKX19ZnVuY3Rpb24gU28odCl7Y29uc3QgZT10LnRpY2tzO2lmKGUuZGlzcGxheSYmdC5kaXNwbGF5KXtjb25zdCB0PWtpKGUuYmFja2Ryb3BQYWRkaW5nKTtyZXR1cm4gbChlLmZvbnQmJmUuZm9udC5zaXplLHVlLmZvbnQuc2l6ZSkrdC5oZWlnaHR9cmV0dXJuIDB9ZnVuY3Rpb24gUG8odCxlLGkscyxuKXtyZXR1cm4gdD09PXN8fHQ9PT1uP3tzdGFydDplLWkvMixlbmQ6ZStpLzJ9OnQ8c3x8dD5uP3tzdGFydDplLWksZW5kOmV9OntzdGFydDplLGVuZDplK2l9fWZ1bmN0aW9uIERvKHQpe2NvbnN0IGU9e2w6dC5sZWZ0K3QuX3BhZGRpbmcubGVmdCxyOnQucmlnaHQtdC5fcGFkZGluZy5yaWdodCx0OnQudG9wK3QuX3BhZGRpbmcudG9wLGI6dC5ib3R0b20tdC5fcGFkZGluZy5ib3R0b219LGk9T2JqZWN0LmFzc2lnbih7fSxlKSxzPVtdLG89W10sYT10Ll9wb2ludExhYmVscy5sZW5ndGgscj10Lm9wdGlvbnMucG9pbnRMYWJlbHMsbD1yLmNlbnRlclBvaW50TGFiZWxzP0MvYTowO2ZvcihsZXQgdT0wO3U8YTt1Kyspe2NvbnN0IGE9ci5zZXRDb250ZXh0KHQuZ2V0UG9pbnRMYWJlbENvbnRleHQodSkpO29bdV09YS5wYWRkaW5nO2NvbnN0IGY9dC5nZXRQb2ludFBvc2l0aW9uKHUsdC5kcmF3aW5nQXJlYStvW3VdLGwpLGc9U2koYS5mb250KSxwPShoPXQuY3R4LGM9ZyxkPW4oZD10Ll9wb2ludExhYmVsc1t1XSk\/ZDpbZF0se3c6T2UoaCxjLnN0cmluZyxkKSxoOmQubGVuZ3RoKmMubGluZUhlaWdodH0pO3NbdV09cDtjb25zdCBtPUcodC5nZXRJbmRleEFuZ2xlKHUpK2wpLGI9TWF0aC5yb3VuZChZKG0pKTtDbyhpLGUsbSxQbyhiLGYueCxwLncsMCwxODApLFBvKGIsZi55LHAuaCw5MCwyNzApKX12YXIgaCxjLGQ7dC5zZXRDZW50ZXJQb2ludChlLmwtaS5sLGkuci1lLnIsZS50LWkudCxpLmItZS5iKSx0Ll9wb2ludExhYmVsSXRlbXM9ZnVuY3Rpb24odCxlLGkpe2NvbnN0IHM9W10sbj10Ll9wb2ludExhYmVscy5sZW5ndGgsbz10Lm9wdGlvbnMse2NlbnRlclBvaW50TGFiZWxzOmEsZGlzcGxheTpyfT1vLnBvaW50TGFiZWxzLGw9e2V4dHJhOlNvKG8pLzIsYWRkaXRpb25hbEFuZ2xlOmE\/Qy9uOjB9O2xldCBoO2ZvcihsZXQgbz0wO288bjtvKyspe2wucGFkZGluZz1pW29dLGwuc2l6ZT1lW29dO2NvbnN0IG49T28odCxvLGwpO3MucHVzaChuKSwiYXV0byI9PT1yJiYobi52aXNpYmxlPUFvKG4saCksbi52aXNpYmxlJiYoaD1uKSl9cmV0dXJuIHN9KHQscyxvKX1mdW5jdGlvbiBDbyh0LGUsaSxzLG4pe2NvbnN0IG89TWF0aC5hYnMoTWF0aC5zaW4oaSkpLGE9TWF0aC5hYnMoTWF0aC5jb3MoaSkpO2xldCByPTAsbD0wO3Muc3RhcnQ8ZS5sPyhyPShlLmwtcy5zdGFydCkvbyx0Lmw9TWF0aC5taW4odC5sLGUubC1yKSk6cy5lbmQ+ZS5yJiYocj0ocy5lbmQtZS5yKS9vLHQucj1NYXRoLm1heCh0LnIsZS5yK3IpKSxuLnN0YXJ0PGUudD8obD0oZS50LW4uc3RhcnQpL2EsdC50PU1hdGgubWluKHQudCxlLnQtbCkpOm4uZW5kPmUuYiYmKGw9KG4uZW5kLWUuYikvYSx0LmI9TWF0aC5tYXgodC5iLGUuYitsKSl9ZnVuY3Rpb24gT28odCxlLGkpe2NvbnN0IHM9dC5kcmF3aW5nQXJlYSx7ZXh0cmE6bixhZGRpdGlvbmFsQW5nbGU6byxwYWRkaW5nOmEsc2l6ZTpyfT1pLGw9dC5nZXRQb2ludFBvc2l0aW9uKGUscytuK2EsbyksaD1NYXRoLnJvdW5kKFkoRyhsLmFuZ2xlK0UpKSksYz1mdW5jdGlvbih0LGUsaSl7OTA9PT1pfHwyNzA9PT1pP3QtPWUvMjooaT4yNzB8fGk8OTApJiYodC09ZSk7cmV0dXJuIHR9KGwueSxyLmgsaCksZD1mdW5jdGlvbih0KXtpZigwPT09dHx8MTgwPT09dClyZXR1cm4iY2VudGVyIjtpZih0PDE4MClyZXR1cm4ibGVmdCI7cmV0dXJuInJpZ2h0In0oaCksdT1mdW5jdGlvbih0LGUsaSl7InJpZ2h0Ij09PWk\/dC09ZToiY2VudGVyIj09PWkmJih0LT1lLzIpO3JldHVybiB0fShsLngsci53LGQpO3JldHVybnt2aXNpYmxlOiEwLHg6bC54LHk6Yyx0ZXh0QWxpZ246ZCxsZWZ0OnUsdG9wOmMscmlnaHQ6dStyLncsYm90dG9tOmMrci5ofX1mdW5jdGlvbiBBbyh0LGUpe2lmKCFlKXJldHVybiEwO2NvbnN0e2xlZnQ6aSx0b3A6cyxyaWdodDpuLGJvdHRvbTpvfT10O3JldHVybiEoUmUoe3g6aSx5OnN9LGUpfHxSZSh7eDppLHk6b30sZSl8fFJlKHt4Om4seTpzfSxlKXx8UmUoe3g6bix5Om99LGUpKX1mdW5jdGlvbiBUbyh0LGUsaSl7Y29uc3R7bGVmdDpuLHRvcDpvLHJpZ2h0OmEsYm90dG9tOnJ9PWkse2JhY2tkcm9wQ29sb3I6bH09ZTtpZighcyhsKSl7Y29uc3QgaT13aShlLmJvcmRlclJhZGl1cykscz1raShlLmJhY2tkcm9wUGFkZGluZyk7dC5maWxsU3R5bGU9bDtjb25zdCBoPW4tcy5sZWZ0LGM9by1zLnRvcCxkPWEtbitzLndpZHRoLHU9ci1vK3MuaGVpZ2h0O09iamVjdC52YWx1ZXMoaSkuc29tZSgodD0+MCE9PXQpKT8odC5iZWdpblBhdGgoKSxIZSh0LHt4OmgseTpjLHc6ZCxoOnUscmFkaXVzOml9KSx0LmZpbGwoKSk6dC5maWxsUmVjdChoLGMsZCx1KX19ZnVuY3Rpb24gTG8odCxlLGkscyl7Y29uc3R7Y3R4Om59PXQ7aWYoaSluLmFyYyh0LnhDZW50ZXIsdC55Q2VudGVyLGUsMCxPKTtlbHNle2xldCBpPXQuZ2V0UG9pbnRQb3NpdGlvbigwLGUpO24ubW92ZVRvKGkueCxpLnkpO2ZvcihsZXQgbz0xO288cztvKyspaT10LmdldFBvaW50UG9zaXRpb24obyxlKSxuLmxpbmVUbyhpLngsaS55KX19Y2xhc3MgRW8gZXh0ZW5kcyBib3tzdGF0aWMgaWQ9InJhZGlhbExpbmVhciI7c3RhdGljIGRlZmF1bHRzPXtkaXNwbGF5OiEwLGFuaW1hdGU6ITAscG9zaXRpb246ImNoYXJ0QXJlYSIsYW5nbGVMaW5lczp7ZGlzcGxheTohMCxsaW5lV2lkdGg6MSxib3JkZXJEYXNoOltdLGJvcmRlckRhc2hPZmZzZXQ6MH0sZ3JpZDp7Y2lyY3VsYXI6ITF9LHN0YXJ0QW5nbGU6MCx0aWNrczp7c2hvd0xhYmVsQmFja2Ryb3A6ITAsY2FsbGJhY2s6YWUuZm9ybWF0dGVycy5udW1lcmljfSxwb2ludExhYmVsczp7YmFja2Ryb3BDb2xvcjp2b2lkIDAsYmFja2Ryb3BQYWRkaW5nOjIsZGlzcGxheTohMCxmb250OntzaXplOjEwfSxjYWxsYmFjazp0PT50LHBhZGRpbmc6NSxjZW50ZXJQb2ludExhYmVsczohMX19O3N0YXRpYyBkZWZhdWx0Um91dGVzPXsiYW5nbGVMaW5lcy5jb2xvciI6ImJvcmRlckNvbG9yIiwicG9pbnRMYWJlbHMuY29sb3IiOiJjb2xvciIsInRpY2tzLmNvbG9yIjoiY29sb3IifTtzdGF0aWMgZGVzY3JpcHRvcnM9e2FuZ2xlTGluZXM6e19mYWxsYmFjazoiZ3JpZCJ9fTtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KSx0aGlzLnhDZW50ZXI9dm9pZCAwLHRoaXMueUNlbnRlcj12b2lkIDAsdGhpcy5kcmF3aW5nQXJlYT12b2lkIDAsdGhpcy5fcG9pbnRMYWJlbHM9W10sdGhpcy5fcG9pbnRMYWJlbEl0ZW1zPVtdfXNldERpbWVuc2lvbnMoKXtjb25zdCB0PXRoaXMuX3BhZGRpbmc9a2koU28odGhpcy5vcHRpb25zKS8yKSxlPXRoaXMud2lkdGg9dGhpcy5tYXhXaWR0aC10LndpZHRoLGk9dGhpcy5oZWlnaHQ9dGhpcy5tYXhIZWlnaHQtdC5oZWlnaHQ7dGhpcy54Q2VudGVyPU1hdGguZmxvb3IodGhpcy5sZWZ0K2UvMit0LmxlZnQpLHRoaXMueUNlbnRlcj1NYXRoLmZsb29yKHRoaXMudG9wK2kvMit0LnRvcCksdGhpcy5kcmF3aW5nQXJlYT1NYXRoLmZsb29yKE1hdGgubWluKGUsaSkvMil9ZGV0ZXJtaW5lRGF0YUxpbWl0cygpe2NvbnN0e21pbjp0LG1heDplfT10aGlzLmdldE1pbk1heCghMSk7dGhpcy5taW49YSh0KSYmIWlzTmFOKHQpP3Q6MCx0aGlzLm1heD1hKGUpJiYhaXNOYU4oZSk\/ZTowLHRoaXMuaGFuZGxlVGlja1JhbmdlT3B0aW9ucygpfWNvbXB1dGVUaWNrTGltaXQoKXtyZXR1cm4gTWF0aC5jZWlsKHRoaXMuZHJhd2luZ0FyZWEvU28odGhpcy5vcHRpb25zKSl9Z2VuZXJhdGVUaWNrTGFiZWxzKHQpe2JvLnByb3RvdHlwZS5nZW5lcmF0ZVRpY2tMYWJlbHMuY2FsbCh0aGlzLHQpLHRoaXMuX3BvaW50TGFiZWxzPXRoaXMuZ2V0TGFiZWxzKCkubWFwKCgodCxlKT0+e2NvbnN0IGk9ZCh0aGlzLm9wdGlvbnMucG9pbnRMYWJlbHMuY2FsbGJhY2ssW3QsZV0sdGhpcyk7cmV0dXJuIGl8fDA9PT1pP2k6IiJ9KSkuZmlsdGVyKCgodCxlKT0+dGhpcy5jaGFydC5nZXREYXRhVmlzaWJpbGl0eShlKSkpfWZpdCgpe2NvbnN0IHQ9dGhpcy5vcHRpb25zO3QuZGlzcGxheSYmdC5wb2ludExhYmVscy5kaXNwbGF5P0RvKHRoaXMpOnRoaXMuc2V0Q2VudGVyUG9pbnQoMCwwLDAsMCl9c2V0Q2VudGVyUG9pbnQodCxlLGkscyl7dGhpcy54Q2VudGVyKz1NYXRoLmZsb29yKCh0LWUpLzIpLHRoaXMueUNlbnRlcis9TWF0aC5mbG9vcigoaS1zKS8yKSx0aGlzLmRyYXdpbmdBcmVhLT1NYXRoLm1pbih0aGlzLmRyYXdpbmdBcmVhLzIsTWF0aC5tYXgodCxlLGkscykpfWdldEluZGV4QW5nbGUodCl7cmV0dXJuIEcodCooTy8odGhpcy5fcG9pbnRMYWJlbHMubGVuZ3RofHwxKSkrJCh0aGlzLm9wdGlvbnMuc3RhcnRBbmdsZXx8MCkpfWdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKHQpe2lmKHModCkpcmV0dXJuIE5hTjtjb25zdCBlPXRoaXMuZHJhd2luZ0FyZWEvKHRoaXMubWF4LXRoaXMubWluKTtyZXR1cm4gdGhpcy5vcHRpb25zLnJldmVyc2U\/KHRoaXMubWF4LXQpKmU6KHQtdGhpcy5taW4pKmV9Z2V0VmFsdWVGb3JEaXN0YW5jZUZyb21DZW50ZXIodCl7aWYocyh0KSlyZXR1cm4gTmFOO2NvbnN0IGU9dC8odGhpcy5kcmF3aW5nQXJlYS8odGhpcy5tYXgtdGhpcy5taW4pKTtyZXR1cm4gdGhpcy5vcHRpb25zLnJldmVyc2U\/dGhpcy5tYXgtZTp0aGlzLm1pbitlfWdldFBvaW50TGFiZWxDb250ZXh0KHQpe2NvbnN0IGU9dGhpcy5fcG9pbnRMYWJlbHN8fFtdO2lmKHQ+PTAmJnQ8ZS5sZW5ndGgpe2NvbnN0IGk9ZVt0XTtyZXR1cm4gZnVuY3Rpb24odCxlLGkpe3JldHVybiBDaSh0LHtsYWJlbDppLGluZGV4OmUsdHlwZToicG9pbnRMYWJlbCJ9KX0odGhpcy5nZXRDb250ZXh0KCksdCxpKX19Z2V0UG9pbnRQb3NpdGlvbih0LGUsaT0wKXtjb25zdCBzPXRoaXMuZ2V0SW5kZXhBbmdsZSh0KS1FK2k7cmV0dXJue3g6TWF0aC5jb3MocykqZSt0aGlzLnhDZW50ZXIseTpNYXRoLnNpbihzKSplK3RoaXMueUNlbnRlcixhbmdsZTpzfX1nZXRQb2ludFBvc2l0aW9uRm9yVmFsdWUodCxlKXtyZXR1cm4gdGhpcy5nZXRQb2ludFBvc2l0aW9uKHQsdGhpcy5nZXREaXN0YW5jZUZyb21DZW50ZXJGb3JWYWx1ZShlKSl9Z2V0QmFzZVBvc2l0aW9uKHQpe3JldHVybiB0aGlzLmdldFBvaW50UG9zaXRpb25Gb3JWYWx1ZSh0fHwwLHRoaXMuZ2V0QmFzZVZhbHVlKCkpfWdldFBvaW50TGFiZWxQb3NpdGlvbih0KXtjb25zdHtsZWZ0OmUsdG9wOmkscmlnaHQ6cyxib3R0b206bn09dGhpcy5fcG9pbnRMYWJlbEl0ZW1zW3RdO3JldHVybntsZWZ0OmUsdG9wOmkscmlnaHQ6cyxib3R0b206bn19ZHJhd0JhY2tncm91bmQoKXtjb25zdHtiYWNrZ3JvdW5kQ29sb3I6dCxncmlkOntjaXJjdWxhcjplfX09dGhpcy5vcHRpb25zO2lmKHQpe2NvbnN0IGk9dGhpcy5jdHg7aS5zYXZlKCksaS5iZWdpblBhdGgoKSxMbyh0aGlzLHRoaXMuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodGhpcy5fZW5kVmFsdWUpLGUsdGhpcy5fcG9pbnRMYWJlbHMubGVuZ3RoKSxpLmNsb3NlUGF0aCgpLGkuZmlsbFN0eWxlPXQsaS5maWxsKCksaS5yZXN0b3JlKCl9fWRyYXdHcmlkKCl7Y29uc3QgdD10aGlzLmN0eCxlPXRoaXMub3B0aW9ucyx7YW5nbGVMaW5lczppLGdyaWQ6cyxib3JkZXI6bn09ZSxvPXRoaXMuX3BvaW50TGFiZWxzLmxlbmd0aDtsZXQgYSxyLGw7aWYoZS5wb2ludExhYmVscy5kaXNwbGF5JiZmdW5jdGlvbih0LGUpe2NvbnN0e2N0eDppLG9wdGlvbnM6e3BvaW50TGFiZWxzOnN9fT10O2ZvcihsZXQgbj1lLTE7bj49MDtuLS0pe2NvbnN0IGU9dC5fcG9pbnRMYWJlbEl0ZW1zW25dO2lmKCFlLnZpc2libGUpY29udGludWU7Y29uc3Qgbz1zLnNldENvbnRleHQodC5nZXRQb2ludExhYmVsQ29udGV4dChuKSk7VG8oaSxvLGUpO2NvbnN0IGE9U2koby5mb250KSx7eDpyLHk6bCx0ZXh0QWxpZ246aH09ZTtOZShpLHQuX3BvaW50TGFiZWxzW25dLHIsbCthLmxpbmVIZWlnaHQvMixhLHtjb2xvcjpvLmNvbG9yLHRleHRBbGlnbjpoLHRleHRCYXNlbGluZToibWlkZGxlIn0pfX0odGhpcyxvKSxzLmRpc3BsYXkmJnRoaXMudGlja3MuZm9yRWFjaCgoKHQsZSk9PntpZigwIT09ZSl7cj10aGlzLmdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKHQudmFsdWUpO2NvbnN0IGk9dGhpcy5nZXRDb250ZXh0KGUpLGE9cy5zZXRDb250ZXh0KGkpLGw9bi5zZXRDb250ZXh0KGkpOyFmdW5jdGlvbih0LGUsaSxzLG4pe2NvbnN0IG89dC5jdHgsYT1lLmNpcmN1bGFyLHtjb2xvcjpyLGxpbmVXaWR0aDpsfT1lOyFhJiYhc3x8IXJ8fCFsfHxpPDB8fChvLnNhdmUoKSxvLnN0cm9rZVN0eWxlPXIsby5saW5lV2lkdGg9bCxvLnNldExpbmVEYXNoKG4uZGFzaCksby5saW5lRGFzaE9mZnNldD1uLmRhc2hPZmZzZXQsby5iZWdpblBhdGgoKSxMbyh0LGksYSxzKSxvLmNsb3NlUGF0aCgpLG8uc3Ryb2tlKCksby5yZXN0b3JlKCkpfSh0aGlzLGEscixvLGwpfX0pKSxpLmRpc3BsYXkpe2Zvcih0LnNhdmUoKSxhPW8tMTthPj0wO2EtLSl7Y29uc3Qgcz1pLnNldENvbnRleHQodGhpcy5nZXRQb2ludExhYmVsQ29udGV4dChhKSkse2NvbG9yOm4sbGluZVdpZHRoOm99PXM7byYmbiYmKHQubGluZVdpZHRoPW8sdC5zdHJva2VTdHlsZT1uLHQuc2V0TGluZURhc2gocy5ib3JkZXJEYXNoKSx0LmxpbmVEYXNoT2Zmc2V0PXMuYm9yZGVyRGFzaE9mZnNldCxyPXRoaXMuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUoZS50aWNrcy5yZXZlcnNlP3RoaXMubWluOnRoaXMubWF4KSxsPXRoaXMuZ2V0UG9pbnRQb3NpdGlvbihhLHIpLHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8odGhpcy54Q2VudGVyLHRoaXMueUNlbnRlciksdC5saW5lVG8obC54LGwueSksdC5zdHJva2UoKSl9dC5yZXN0b3JlKCl9fWRyYXdCb3JkZXIoKXt9ZHJhd0xhYmVscygpe2NvbnN0IHQ9dGhpcy5jdHgsZT10aGlzLm9wdGlvbnMsaT1lLnRpY2tzO2lmKCFpLmRpc3BsYXkpcmV0dXJuO2NvbnN0IHM9dGhpcy5nZXRJbmRleEFuZ2xlKDApO2xldCBuLG87dC5zYXZlKCksdC50cmFuc2xhdGUodGhpcy54Q2VudGVyLHRoaXMueUNlbnRlciksdC5yb3RhdGUocyksdC50ZXh0QWxpZ249ImNlbnRlciIsdC50ZXh0QmFzZWxpbmU9Im1pZGRsZSIsdGhpcy50aWNrcy5mb3JFYWNoKCgocyxhKT0+e2lmKDA9PT1hJiYhZS5yZXZlcnNlKXJldHVybjtjb25zdCByPWkuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoYSkpLGw9U2koci5mb250KTtpZihuPXRoaXMuZ2V0RGlzdGFuY2VGcm9tQ2VudGVyRm9yVmFsdWUodGhpcy50aWNrc1thXS52YWx1ZSksci5zaG93TGFiZWxCYWNrZHJvcCl7dC5mb250PWwuc3RyaW5nLG89dC5tZWFzdXJlVGV4dChzLmxhYmVsKS53aWR0aCx0LmZpbGxTdHlsZT1yLmJhY2tkcm9wQ29sb3I7Y29uc3QgZT1raShyLmJhY2tkcm9wUGFkZGluZyk7dC5maWxsUmVjdCgtby8yLWUubGVmdCwtbi1sLnNpemUvMi1lLnRvcCxvK2Uud2lkdGgsbC5zaXplK2UuaGVpZ2h0KX1OZSh0LHMubGFiZWwsMCwtbixsLHtjb2xvcjpyLmNvbG9yLHN0cm9rZUNvbG9yOnIudGV4dFN0cm9rZUNvbG9yLHN0cm9rZVdpZHRoOnIudGV4dFN0cm9rZVdpZHRofSl9KSksdC5yZXN0b3JlKCl9ZHJhd1RpdGxlKCl7fX1jb25zdCBSbz17bWlsbGlzZWNvbmQ6e2NvbW1vbjohMCxzaXplOjEsc3RlcHM6MWUzfSxzZWNvbmQ6e2NvbW1vbjohMCxzaXplOjFlMyxzdGVwczo2MH0sbWludXRlOntjb21tb246ITAsc2l6ZTo2ZTQsc3RlcHM6NjB9LGhvdXI6e2NvbW1vbjohMCxzaXplOjM2ZTUsc3RlcHM6MjR9LGRheTp7Y29tbW9uOiEwLHNpemU6ODY0ZTUsc3RlcHM6MzB9LHdlZWs6e2NvbW1vbjohMSxzaXplOjYwNDhlNSxzdGVwczo0fSxtb250aDp7Y29tbW9uOiEwLHNpemU6MjYyOGU2LHN0ZXBzOjEyfSxxdWFydGVyOntjb21tb246ITEsc2l6ZTo3ODg0ZTYsc3RlcHM6NH0seWVhcjp7Y29tbW9uOiEwLHNpemU6MzE1NGU3fX0sSW89T2JqZWN0LmtleXMoUm8pO2Z1bmN0aW9uIHpvKHQsZSl7cmV0dXJuIHQtZX1mdW5jdGlvbiBGbyh0LGUpe2lmKHMoZSkpcmV0dXJuIG51bGw7Y29uc3QgaT10Ll9hZGFwdGVyLHtwYXJzZXI6bixyb3VuZDpvLGlzb1dlZWtkYXk6cn09dC5fcGFyc2VPcHRzO2xldCBsPWU7cmV0dXJuImZ1bmN0aW9uIj09dHlwZW9mIG4mJihsPW4obCkpLGEobCl8fChsPSJzdHJpbmciPT10eXBlb2Ygbj9pLnBhcnNlKGwsbik6aS5wYXJzZShsKSksbnVsbD09PWw\/bnVsbDoobyYmKGw9IndlZWsiIT09b3x8IU4ocikmJiEwIT09cj9pLnN0YXJ0T2YobCxvKTppLnN0YXJ0T2YobCwiaXNvV2VlayIscikpLCtsKX1mdW5jdGlvbiBWbyh0LGUsaSxzKXtjb25zdCBuPUlvLmxlbmd0aDtmb3IobGV0IG89SW8uaW5kZXhPZih0KTtvPG4tMTsrK28pe2NvbnN0IHQ9Um9bSW9bb11dLG49dC5zdGVwcz90LnN0ZXBzOk51bWJlci5NQVhfU0FGRV9JTlRFR0VSO2lmKHQuY29tbW9uJiZNYXRoLmNlaWwoKGktZSkvKG4qdC5zaXplKSk8PXMpcmV0dXJuIElvW29dfXJldHVybiBJb1tuLTFdfWZ1bmN0aW9uIEJvKHQsZSxpKXtpZihpKXtpZihpLmxlbmd0aCl7Y29uc3R7bG86cyxoaTpufT1ldChpLGUpO3RbaVtzXT49ZT9pW3NdOmlbbl1dPSEwfX1lbHNlIHRbZV09ITB9ZnVuY3Rpb24gV28odCxlLGkpe2NvbnN0IHM9W10sbj17fSxvPWUubGVuZ3RoO2xldCBhLHI7Zm9yKGE9MDthPG87KythKXI9ZVthXSxuW3JdPWEscy5wdXNoKHt2YWx1ZTpyLG1ham9yOiExfSk7cmV0dXJuIDAhPT1vJiZpP2Z1bmN0aW9uKHQsZSxpLHMpe2NvbnN0IG49dC5fYWRhcHRlcixvPStuLnN0YXJ0T2YoZVswXS52YWx1ZSxzKSxhPWVbZS5sZW5ndGgtMV0udmFsdWU7bGV0IHIsbDtmb3Iocj1vO3I8PWE7cj0rbi5hZGQociwxLHMpKWw9aVtyXSxsPj0wJiYoZVtsXS5tYWpvcj0hMCk7cmV0dXJuIGV9KHQscyxuLGkpOnN9Y2xhc3MgTm8gZXh0ZW5kcyBKc3tzdGF0aWMgaWQ9InRpbWUiO3N0YXRpYyBkZWZhdWx0cz17Ym91bmRzOiJkYXRhIixhZGFwdGVyczp7fSx0aW1lOntwYXJzZXI6ITEsdW5pdDohMSxyb3VuZDohMSxpc29XZWVrZGF5OiExLG1pblVuaXQ6Im1pbGxpc2Vjb25kIixkaXNwbGF5Rm9ybWF0czp7fX0sdGlja3M6e3NvdXJjZToiYXV0byIsY2FsbGJhY2s6ITEsbWFqb3I6e2VuYWJsZWQ6ITF9fX07Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpcy5fY2FjaGU9e2RhdGE6W10sbGFiZWxzOltdLGFsbDpbXX0sdGhpcy5fdW5pdD0iZGF5Iix0aGlzLl9tYWpvclVuaXQ9dm9pZCAwLHRoaXMuX29mZnNldHM9e30sdGhpcy5fbm9ybWFsaXplZD0hMSx0aGlzLl9wYXJzZU9wdHM9dm9pZCAwfWluaXQodCxlPXt9KXtjb25zdCBpPXQudGltZXx8KHQudGltZT17fSkscz10aGlzLl9hZGFwdGVyPW5ldyBSbi5fZGF0ZSh0LmFkYXB0ZXJzLmRhdGUpO3MuaW5pdChlKSx4KGkuZGlzcGxheUZvcm1hdHMscy5mb3JtYXRzKCkpLHRoaXMuX3BhcnNlT3B0cz17cGFyc2VyOmkucGFyc2VyLHJvdW5kOmkucm91bmQsaXNvV2Vla2RheTppLmlzb1dlZWtkYXl9LHN1cGVyLmluaXQodCksdGhpcy5fbm9ybWFsaXplZD1lLm5vcm1hbGl6ZWR9cGFyc2UodCxlKXtyZXR1cm4gdm9pZCAwPT09dD9udWxsOkZvKHRoaXMsdCl9YmVmb3JlTGF5b3V0KCl7c3VwZXIuYmVmb3JlTGF5b3V0KCksdGhpcy5fY2FjaGU9e2RhdGE6W10sbGFiZWxzOltdLGFsbDpbXX19ZGV0ZXJtaW5lRGF0YUxpbWl0cygpe2NvbnN0IHQ9dGhpcy5vcHRpb25zLGU9dGhpcy5fYWRhcHRlcixpPXQudGltZS51bml0fHwiZGF5IjtsZXR7bWluOnMsbWF4Om4sbWluRGVmaW5lZDpvLG1heERlZmluZWQ6cn09dGhpcy5nZXRVc2VyQm91bmRzKCk7ZnVuY3Rpb24gbCh0KXtvfHxpc05hTih0Lm1pbil8fChzPU1hdGgubWluKHMsdC5taW4pKSxyfHxpc05hTih0Lm1heCl8fChuPU1hdGgubWF4KG4sdC5tYXgpKX1vJiZyfHwobCh0aGlzLl9nZXRMYWJlbEJvdW5kcygpKSwidGlja3MiPT09dC5ib3VuZHMmJiJsYWJlbHMiPT09dC50aWNrcy5zb3VyY2V8fGwodGhpcy5nZXRNaW5NYXgoITEpKSkscz1hKHMpJiYhaXNOYU4ocyk\/czorZS5zdGFydE9mKERhdGUubm93KCksaSksbj1hKG4pJiYhaXNOYU4obik\/bjorZS5lbmRPZihEYXRlLm5vdygpLGkpKzEsdGhpcy5taW49TWF0aC5taW4ocyxuLTEpLHRoaXMubWF4PU1hdGgubWF4KHMrMSxuKX1fZ2V0TGFiZWxCb3VuZHMoKXtjb25zdCB0PXRoaXMuZ2V0TGFiZWxUaW1lc3RhbXBzKCk7bGV0IGU9TnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLGk9TnVtYmVyLk5FR0FUSVZFX0lORklOSVRZO3JldHVybiB0Lmxlbmd0aCYmKGU9dFswXSxpPXRbdC5sZW5ndGgtMV0pLHttaW46ZSxtYXg6aX19YnVpbGRUaWNrcygpe2NvbnN0IHQ9dGhpcy5vcHRpb25zLGU9dC50aW1lLGk9dC50aWNrcyxzPSJsYWJlbHMiPT09aS5zb3VyY2U\/dGhpcy5nZXRMYWJlbFRpbWVzdGFtcHMoKTp0aGlzLl9nZW5lcmF0ZSgpOyJ0aWNrcyI9PT10LmJvdW5kcyYmcy5sZW5ndGgmJih0aGlzLm1pbj10aGlzLl91c2VyTWlufHxzWzBdLHRoaXMubWF4PXRoaXMuX3VzZXJNYXh8fHNbcy5sZW5ndGgtMV0pO2NvbnN0IG49dGhpcy5taW4sbz1udChzLG4sdGhpcy5tYXgpO3JldHVybiB0aGlzLl91bml0PWUudW5pdHx8KGkuYXV0b1NraXA\/Vm8oZS5taW5Vbml0LHRoaXMubWluLHRoaXMubWF4LHRoaXMuX2dldExhYmVsQ2FwYWNpdHkobikpOmZ1bmN0aW9uKHQsZSxpLHMsbil7Zm9yKGxldCBvPUlvLmxlbmd0aC0xO28+PUlvLmluZGV4T2YoaSk7by0tKXtjb25zdCBpPUlvW29dO2lmKFJvW2ldLmNvbW1vbiYmdC5fYWRhcHRlci5kaWZmKG4scyxpKT49ZS0xKXJldHVybiBpfXJldHVybiBJb1tpP0lvLmluZGV4T2YoaSk6MF19KHRoaXMsby5sZW5ndGgsZS5taW5Vbml0LHRoaXMubWluLHRoaXMubWF4KSksdGhpcy5fbWFqb3JVbml0PWkubWFqb3IuZW5hYmxlZCYmInllYXIiIT09dGhpcy5fdW5pdD9mdW5jdGlvbih0KXtmb3IobGV0IGU9SW8uaW5kZXhPZih0KSsxLGk9SW8ubGVuZ3RoO2U8aTsrK2UpaWYoUm9bSW9bZV1dLmNvbW1vbilyZXR1cm4gSW9bZV19KHRoaXMuX3VuaXQpOnZvaWQgMCx0aGlzLmluaXRPZmZzZXRzKHMpLHQucmV2ZXJzZSYmby5yZXZlcnNlKCksV28odGhpcyxvLHRoaXMuX21ham9yVW5pdCl9YWZ0ZXJBdXRvU2tpcCgpe3RoaXMub3B0aW9ucy5vZmZzZXRBZnRlckF1dG9za2lwJiZ0aGlzLmluaXRPZmZzZXRzKHRoaXMudGlja3MubWFwKCh0PT4rdC52YWx1ZSkpKX1pbml0T2Zmc2V0cyh0PVtdKXtsZXQgZSxpLHM9MCxuPTA7dGhpcy5vcHRpb25zLm9mZnNldCYmdC5sZW5ndGgmJihlPXRoaXMuZ2V0RGVjaW1hbEZvclZhbHVlKHRbMF0pLHM9MT09PXQubGVuZ3RoPzEtZToodGhpcy5nZXREZWNpbWFsRm9yVmFsdWUodFsxXSktZSkvMixpPXRoaXMuZ2V0RGVjaW1hbEZvclZhbHVlKHRbdC5sZW5ndGgtMV0pLG49MT09PXQubGVuZ3RoP2k6KGktdGhpcy5nZXREZWNpbWFsRm9yVmFsdWUodFt0Lmxlbmd0aC0yXSkpLzIpO2NvbnN0IG89dC5sZW5ndGg8Mz8uNTouMjU7cz1KKHMsMCxvKSxuPUoobiwwLG8pLHRoaXMuX29mZnNldHM9e3N0YXJ0OnMsZW5kOm4sZmFjdG9yOjEvKHMrMStuKX19X2dlbmVyYXRlKCl7Y29uc3QgdD10aGlzLl9hZGFwdGVyLGU9dGhpcy5taW4saT10aGlzLm1heCxzPXRoaXMub3B0aW9ucyxuPXMudGltZSxvPW4udW5pdHx8Vm8obi5taW5Vbml0LGUsaSx0aGlzLl9nZXRMYWJlbENhcGFjaXR5KGUpKSxhPWwocy50aWNrcy5zdGVwU2l6ZSwxKSxyPSJ3ZWVrIj09PW8mJm4uaXNvV2Vla2RheSxoPU4ocil8fCEwPT09cixjPXt9O2xldCBkLHUsZj1lO2lmKGgmJihmPSt0LnN0YXJ0T2YoZiwiaXNvV2VlayIscikpLGY9K3Quc3RhcnRPZihmLGg\/ImRheSI6byksdC5kaWZmKGksZSxvKT4xZTUqYSl0aHJvdyBuZXcgRXJyb3IoZSsiIGFuZCAiK2krIiBhcmUgdG9vIGZhciBhcGFydCB3aXRoIHN0ZXBTaXplIG9mICIrYSsiICIrbyk7Y29uc3QgZz0iZGF0YSI9PT1zLnRpY2tzLnNvdXJjZSYmdGhpcy5nZXREYXRhVGltZXN0YW1wcygpO2ZvcihkPWYsdT0wO2Q8aTtkPSt0LmFkZChkLGEsbyksdSsrKUJvKGMsZCxnKTtyZXR1cm4gZCE9PWkmJiJ0aWNrcyIhPT1zLmJvdW5kcyYmMSE9PXV8fEJvKGMsZCxnKSxPYmplY3Qua2V5cyhjKS5zb3J0KHpvKS5tYXAoKHQ9Pit0KSl9Z2V0TGFiZWxGb3JWYWx1ZSh0KXtjb25zdCBlPXRoaXMuX2FkYXB0ZXIsaT10aGlzLm9wdGlvbnMudGltZTtyZXR1cm4gaS50b29sdGlwRm9ybWF0P2UuZm9ybWF0KHQsaS50b29sdGlwRm9ybWF0KTplLmZvcm1hdCh0LGkuZGlzcGxheUZvcm1hdHMuZGF0ZXRpbWUpfWZvcm1hdCh0LGUpe2NvbnN0IGk9dGhpcy5vcHRpb25zLnRpbWUuZGlzcGxheUZvcm1hdHMscz10aGlzLl91bml0LG49ZXx8aVtzXTtyZXR1cm4gdGhpcy5fYWRhcHRlci5mb3JtYXQodCxuKX1fdGlja0Zvcm1hdEZ1bmN0aW9uKHQsZSxpLHMpe2NvbnN0IG49dGhpcy5vcHRpb25zLG89bi50aWNrcy5jYWxsYmFjaztpZihvKXJldHVybiBkKG8sW3QsZSxpXSx0aGlzKTtjb25zdCBhPW4udGltZS5kaXNwbGF5Rm9ybWF0cyxyPXRoaXMuX3VuaXQsbD10aGlzLl9tYWpvclVuaXQsaD1yJiZhW3JdLGM9bCYmYVtsXSx1PWlbZV0sZj1sJiZjJiZ1JiZ1Lm1ham9yO3JldHVybiB0aGlzLl9hZGFwdGVyLmZvcm1hdCh0LHN8fChmP2M6aCkpfWdlbmVyYXRlVGlja0xhYmVscyh0KXtsZXQgZSxpLHM7Zm9yKGU9MCxpPXQubGVuZ3RoO2U8aTsrK2Upcz10W2VdLHMubGFiZWw9dGhpcy5fdGlja0Zvcm1hdEZ1bmN0aW9uKHMudmFsdWUsZSx0KX1nZXREZWNpbWFsRm9yVmFsdWUodCl7cmV0dXJuIG51bGw9PT10P05hTjoodC10aGlzLm1pbikvKHRoaXMubWF4LXRoaXMubWluKX1nZXRQaXhlbEZvclZhbHVlKHQpe2NvbnN0IGU9dGhpcy5fb2Zmc2V0cyxpPXRoaXMuZ2V0RGVjaW1hbEZvclZhbHVlKHQpO3JldHVybiB0aGlzLmdldFBpeGVsRm9yRGVjaW1hbCgoZS5zdGFydCtpKSplLmZhY3Rvcil9Z2V0VmFsdWVGb3JQaXhlbCh0KXtjb25zdCBlPXRoaXMuX29mZnNldHMsaT10aGlzLmdldERlY2ltYWxGb3JQaXhlbCh0KS9lLmZhY3Rvci1lLmVuZDtyZXR1cm4gdGhpcy5taW4raSoodGhpcy5tYXgtdGhpcy5taW4pfV9nZXRMYWJlbFNpemUodCl7Y29uc3QgZT10aGlzLm9wdGlvbnMudGlja3MsaT10aGlzLmN0eC5tZWFzdXJlVGV4dCh0KS53aWR0aCxzPSQodGhpcy5pc0hvcml6b250YWwoKT9lLm1heFJvdGF0aW9uOmUubWluUm90YXRpb24pLG49TWF0aC5jb3Mocyksbz1NYXRoLnNpbihzKSxhPXRoaXMuX3Jlc29sdmVUaWNrRm9udE9wdGlvbnMoMCkuc2l6ZTtyZXR1cm57dzppKm4rYSpvLGg6aSpvK2Eqbn19X2dldExhYmVsQ2FwYWNpdHkodCl7Y29uc3QgZT10aGlzLm9wdGlvbnMudGltZSxpPWUuZGlzcGxheUZvcm1hdHMscz1pW2UudW5pdF18fGkubWlsbGlzZWNvbmQsbj10aGlzLl90aWNrRm9ybWF0RnVuY3Rpb24odCwwLFdvKHRoaXMsW3RdLHRoaXMuX21ham9yVW5pdCkscyksbz10aGlzLl9nZXRMYWJlbFNpemUobiksYT1NYXRoLmZsb29yKHRoaXMuaXNIb3Jpem9udGFsKCk\/dGhpcy53aWR0aC9vLnc6dGhpcy5oZWlnaHQvby5oKS0xO3JldHVybiBhPjA\/YToxfWdldERhdGFUaW1lc3RhbXBzKCl7bGV0IHQsZSxpPXRoaXMuX2NhY2hlLmRhdGF8fFtdO2lmKGkubGVuZ3RoKXJldHVybiBpO2NvbnN0IHM9dGhpcy5nZXRNYXRjaGluZ1Zpc2libGVNZXRhcygpO2lmKHRoaXMuX25vcm1hbGl6ZWQmJnMubGVuZ3RoKXJldHVybiB0aGlzLl9jYWNoZS5kYXRhPXNbMF0uY29udHJvbGxlci5nZXRBbGxQYXJzZWRWYWx1ZXModGhpcyk7Zm9yKHQ9MCxlPXMubGVuZ3RoO3Q8ZTsrK3QpaT1pLmNvbmNhdChzW3RdLmNvbnRyb2xsZXIuZ2V0QWxsUGFyc2VkVmFsdWVzKHRoaXMpKTtyZXR1cm4gdGhpcy5fY2FjaGUuZGF0YT10aGlzLm5vcm1hbGl6ZShpKX1nZXRMYWJlbFRpbWVzdGFtcHMoKXtjb25zdCB0PXRoaXMuX2NhY2hlLmxhYmVsc3x8W107bGV0IGUsaTtpZih0Lmxlbmd0aClyZXR1cm4gdDtjb25zdCBzPXRoaXMuZ2V0TGFiZWxzKCk7Zm9yKGU9MCxpPXMubGVuZ3RoO2U8aTsrK2UpdC5wdXNoKEZvKHRoaXMsc1tlXSkpO3JldHVybiB0aGlzLl9jYWNoZS5sYWJlbHM9dGhpcy5fbm9ybWFsaXplZD90OnRoaXMubm9ybWFsaXplKHQpfW5vcm1hbGl6ZSh0KXtyZXR1cm4gbHQodC5zb3J0KHpvKSl9fWZ1bmN0aW9uIEhvKHQsZSxpKXtsZXQgcyxuLG8sYSxyPTAsbD10Lmxlbmd0aC0xO2k\/KGU+PXRbcl0ucG9zJiZlPD10W2xdLnBvcyYmKHtsbzpyLGhpOmx9PWl0KHQsInBvcyIsZSkpLCh7cG9zOnMsdGltZTpvfT10W3JdKSwoe3BvczpuLHRpbWU6YX09dFtsXSkpOihlPj10W3JdLnRpbWUmJmU8PXRbbF0udGltZSYmKHtsbzpyLGhpOmx9PWl0KHQsInRpbWUiLGUpKSwoe3RpbWU6cyxwb3M6b309dFtyXSksKHt0aW1lOm4scG9zOmF9PXRbbF0pKTtjb25zdCBoPW4tcztyZXR1cm4gaD9vKyhhLW8pKihlLXMpL2g6b312YXIgam89T2JqZWN0LmZyZWV6ZSh7X19wcm90b19fOm51bGwsQ2F0ZWdvcnlTY2FsZTpjbGFzcyBleHRlbmRzIEpze3N0YXRpYyBpZD0iY2F0ZWdvcnkiO3N0YXRpYyBkZWZhdWx0cz17dGlja3M6e2NhbGxiYWNrOnBvfX07Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpcy5fc3RhcnRWYWx1ZT12b2lkIDAsdGhpcy5fdmFsdWVSYW5nZT0wLHRoaXMuX2FkZGVkTGFiZWxzPVtdfWluaXQodCl7Y29uc3QgZT10aGlzLl9hZGRlZExhYmVscztpZihlLmxlbmd0aCl7Y29uc3QgdD10aGlzLmdldExhYmVscygpO2Zvcihjb25zdHtpbmRleDppLGxhYmVsOnN9b2YgZSl0W2ldPT09cyYmdC5zcGxpY2UoaSwxKTt0aGlzLl9hZGRlZExhYmVscz1bXX1zdXBlci5pbml0KHQpfXBhcnNlKHQsZSl7aWYocyh0KSlyZXR1cm4gbnVsbDtjb25zdCBpPXRoaXMuZ2V0TGFiZWxzKCk7cmV0dXJuKCh0LGUpPT5udWxsPT09dD9udWxsOkooTWF0aC5yb3VuZCh0KSwwLGUpKShlPWlzRmluaXRlKGUpJiZpW2VdPT09dD9lOmdvKGksdCxsKGUsdCksdGhpcy5fYWRkZWRMYWJlbHMpLGkubGVuZ3RoLTEpfWRldGVybWluZURhdGFMaW1pdHMoKXtjb25zdHttaW5EZWZpbmVkOnQsbWF4RGVmaW5lZDplfT10aGlzLmdldFVzZXJCb3VuZHMoKTtsZXR7bWluOmksbWF4OnN9PXRoaXMuZ2V0TWluTWF4KCEwKTsidGlja3MiPT09dGhpcy5vcHRpb25zLmJvdW5kcyYmKHR8fChpPTApLGV8fChzPXRoaXMuZ2V0TGFiZWxzKCkubGVuZ3RoLTEpKSx0aGlzLm1pbj1pLHRoaXMubWF4PXN9YnVpbGRUaWNrcygpe2NvbnN0IHQ9dGhpcy5taW4sZT10aGlzLm1heCxpPXRoaXMub3B0aW9ucy5vZmZzZXQscz1bXTtsZXQgbj10aGlzLmdldExhYmVscygpO249MD09PXQmJmU9PT1uLmxlbmd0aC0xP246bi5zbGljZSh0LGUrMSksdGhpcy5fdmFsdWVSYW5nZT1NYXRoLm1heChuLmxlbmd0aC0oaT8wOjEpLDEpLHRoaXMuX3N0YXJ0VmFsdWU9dGhpcy5taW4tKGk\/LjU6MCk7Zm9yKGxldCBpPXQ7aTw9ZTtpKyspcy5wdXNoKHt2YWx1ZTppfSk7cmV0dXJuIHN9Z2V0TGFiZWxGb3JWYWx1ZSh0KXtyZXR1cm4gcG8uY2FsbCh0aGlzLHQpfWNvbmZpZ3VyZSgpe3N1cGVyLmNvbmZpZ3VyZSgpLHRoaXMuaXNIb3Jpem9udGFsKCl8fCh0aGlzLl9yZXZlcnNlUGl4ZWxzPSF0aGlzLl9yZXZlcnNlUGl4ZWxzKX1nZXRQaXhlbEZvclZhbHVlKHQpe3JldHVybiJudW1iZXIiIT10eXBlb2YgdCYmKHQ9dGhpcy5wYXJzZSh0KSksbnVsbD09PXQ\/TmFOOnRoaXMuZ2V0UGl4ZWxGb3JEZWNpbWFsKCh0LXRoaXMuX3N0YXJ0VmFsdWUpL3RoaXMuX3ZhbHVlUmFuZ2UpfWdldFBpeGVsRm9yVGljayh0KXtjb25zdCBlPXRoaXMudGlja3M7cmV0dXJuIHQ8MHx8dD5lLmxlbmd0aC0xP251bGw6dGhpcy5nZXRQaXhlbEZvclZhbHVlKGVbdF0udmFsdWUpfWdldFZhbHVlRm9yUGl4ZWwodCl7cmV0dXJuIE1hdGgucm91bmQodGhpcy5fc3RhcnRWYWx1ZSt0aGlzLmdldERlY2ltYWxGb3JQaXhlbCh0KSp0aGlzLl92YWx1ZVJhbmdlKX1nZXRCYXNlUGl4ZWwoKXtyZXR1cm4gdGhpcy5ib3R0b219fSxMaW5lYXJTY2FsZTp4byxMb2dhcml0aG1pY1NjYWxlOmtvLFJhZGlhbExpbmVhclNjYWxlOkVvLFRpbWVTY2FsZTpObyxUaW1lU2VyaWVzU2NhbGU6Y2xhc3MgZXh0ZW5kcyBOb3tzdGF0aWMgaWQ9InRpbWVzZXJpZXMiO3N0YXRpYyBkZWZhdWx0cz1Oby5kZWZhdWx0cztjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KSx0aGlzLl90YWJsZT1bXSx0aGlzLl9taW5Qb3M9dm9pZCAwLHRoaXMuX3RhYmxlUmFuZ2U9dm9pZCAwfWluaXRPZmZzZXRzKCl7Y29uc3QgdD10aGlzLl9nZXRUaW1lc3RhbXBzRm9yVGFibGUoKSxlPXRoaXMuX3RhYmxlPXRoaXMuYnVpbGRMb29rdXBUYWJsZSh0KTt0aGlzLl9taW5Qb3M9SG8oZSx0aGlzLm1pbiksdGhpcy5fdGFibGVSYW5nZT1IbyhlLHRoaXMubWF4KS10aGlzLl9taW5Qb3Msc3VwZXIuaW5pdE9mZnNldHModCl9YnVpbGRMb29rdXBUYWJsZSh0KXtjb25zdHttaW46ZSxtYXg6aX09dGhpcyxzPVtdLG49W107bGV0IG8sYSxyLGwsaDtmb3Iobz0wLGE9dC5sZW5ndGg7bzxhOysrbylsPXRbb10sbD49ZSYmbDw9aSYmcy5wdXNoKGwpO2lmKHMubGVuZ3RoPDIpcmV0dXJuW3t0aW1lOmUscG9zOjB9LHt0aW1lOmkscG9zOjF9XTtmb3Iobz0wLGE9cy5sZW5ndGg7bzxhOysrbyloPXNbbysxXSxyPXNbby0xXSxsPXNbb10sTWF0aC5yb3VuZCgoaCtyKS8yKSE9PWwmJm4ucHVzaCh7dGltZTpsLHBvczpvLyhhLTEpfSk7cmV0dXJuIG59X2dlbmVyYXRlKCl7Y29uc3QgdD10aGlzLm1pbixlPXRoaXMubWF4O2xldCBpPXN1cGVyLmdldERhdGFUaW1lc3RhbXBzKCk7cmV0dXJuIGkuaW5jbHVkZXModCkmJmkubGVuZ3RofHxpLnNwbGljZSgwLDAsdCksaS5pbmNsdWRlcyhlKSYmMSE9PWkubGVuZ3RofHxpLnB1c2goZSksaS5zb3J0KCgodCxlKT0+dC1lKSl9X2dldFRpbWVzdGFtcHNGb3JUYWJsZSgpe2xldCB0PXRoaXMuX2NhY2hlLmFsbHx8W107aWYodC5sZW5ndGgpcmV0dXJuIHQ7Y29uc3QgZT10aGlzLmdldERhdGFUaW1lc3RhbXBzKCksaT10aGlzLmdldExhYmVsVGltZXN0YW1wcygpO3JldHVybiB0PWUubGVuZ3RoJiZpLmxlbmd0aD90aGlzLm5vcm1hbGl6ZShlLmNvbmNhdChpKSk6ZS5sZW5ndGg\/ZTppLHQ9dGhpcy5fY2FjaGUuYWxsPXQsdH1nZXREZWNpbWFsRm9yVmFsdWUodCl7cmV0dXJuKEhvKHRoaXMuX3RhYmxlLHQpLXRoaXMuX21pblBvcykvdGhpcy5fdGFibGVSYW5nZX1nZXRWYWx1ZUZvclBpeGVsKHQpe2NvbnN0IGU9dGhpcy5fb2Zmc2V0cyxpPXRoaXMuZ2V0RGVjaW1hbEZvclBpeGVsKHQpL2UuZmFjdG9yLWUuZW5kO3JldHVybiBIbyh0aGlzLl90YWJsZSxpKnRoaXMuX3RhYmxlUmFuZ2UrdGhpcy5fbWluUG9zLCEwKX19fSk7Y29uc3QgJG89WyJyZ2IoNTQsIDE2MiwgMjM1KSIsInJnYigyNTUsIDk5LCAxMzIpIiwicmdiKDI1NSwgMTU5LCA2NCkiLCJyZ2IoMjU1LCAyMDUsIDg2KSIsInJnYig3NSwgMTkyLCAxOTIpIiwicmdiKDE1MywgMTAyLCAyNTUpIiwicmdiKDIwMSwgMjAzLCAyMDcpIl0sWW89JG8ubWFwKCh0PT50LnJlcGxhY2UoInJnYigiLCJyZ2JhKCIpLnJlcGxhY2UoIikiLCIsIDAuNSkiKSkpO2Z1bmN0aW9uIFVvKHQpe3JldHVybiAkb1t0JSRvLmxlbmd0aF19ZnVuY3Rpb24gWG8odCl7cmV0dXJuIFlvW3QlWW8ubGVuZ3RoXX1mdW5jdGlvbiBxbyh0KXtsZXQgZT0wO3JldHVybihpLHMpPT57Y29uc3Qgbj10LmdldERhdGFzZXRNZXRhKHMpLmNvbnRyb2xsZXI7biBpbnN0YW5jZW9mIGpuP2U9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdC5iYWNrZ3JvdW5kQ29sb3I9dC5kYXRhLm1hcCgoKCk9PlVvKGUrKykpKSxlfShpLGUpOm4gaW5zdGFuY2VvZiAkbj9lPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQuYmFja2dyb3VuZENvbG9yPXQuZGF0YS5tYXAoKCgpPT5YbyhlKyspKSksZX0oaSxlKTpuJiYoZT1mdW5jdGlvbih0LGUpe3JldHVybiB0LmJvcmRlckNvbG9yPVVvKGUpLHQuYmFja2dyb3VuZENvbG9yPVhvKGUpLCsrZX0oaSxlKSl9fWZ1bmN0aW9uIEtvKHQpe2xldCBlO2ZvcihlIGluIHQpaWYodFtlXS5ib3JkZXJDb2xvcnx8dFtlXS5iYWNrZ3JvdW5kQ29sb3IpcmV0dXJuITA7cmV0dXJuITF9dmFyIEdvPXtpZDoiY29sb3JzIixkZWZhdWx0czp7ZW5hYmxlZDohMCxmb3JjZU92ZXJyaWRlOiExfSxiZWZvcmVMYXlvdXQodCxlLGkpe2lmKCFpLmVuYWJsZWQpcmV0dXJuO2NvbnN0e2RhdGE6e2RhdGFzZXRzOnN9LG9wdGlvbnM6bn09dC5jb25maWcse2VsZW1lbnRzOm99PW47aWYoIWkuZm9yY2VPdmVycmlkZSYmKEtvKHMpfHwoYT1uKSYmKGEuYm9yZGVyQ29sb3J8fGEuYmFja2dyb3VuZENvbG9yKXx8byYmS28obykpKXJldHVybjt2YXIgYTtjb25zdCByPXFvKHQpO3MuZm9yRWFjaChyKX19O2Z1bmN0aW9uIFpvKHQpe2lmKHQuX2RlY2ltYXRlZCl7Y29uc3QgZT10Ll9kYXRhO2RlbGV0ZSB0Ll9kZWNpbWF0ZWQsZGVsZXRlIHQuX2RhdGEsT2JqZWN0LmRlZmluZVByb3BlcnR5KHQsImRhdGEiLHtjb25maWd1cmFibGU6ITAsZW51bWVyYWJsZTohMCx3cml0YWJsZTohMCx2YWx1ZTplfSl9fWZ1bmN0aW9uIEpvKHQpe3QuZGF0YS5kYXRhc2V0cy5mb3JFYWNoKCh0PT57Wm8odCl9KSl9dmFyIFFvPXtpZDoiZGVjaW1hdGlvbiIsZGVmYXVsdHM6e2FsZ29yaXRobToibWluLW1heCIsZW5hYmxlZDohMX0sYmVmb3JlRWxlbWVudHNVcGRhdGU6KHQsZSxpKT0+e2lmKCFpLmVuYWJsZWQpcmV0dXJuIHZvaWQgSm8odCk7Y29uc3Qgbj10LndpZHRoO3QuZGF0YS5kYXRhc2V0cy5mb3JFYWNoKCgoZSxvKT0+e2NvbnN0e19kYXRhOmEsaW5kZXhBeGlzOnJ9PWUsbD10LmdldERhdGFzZXRNZXRhKG8pLGg9YXx8ZS5kYXRhO2lmKCJ5Ij09PVBpKFtyLHQub3B0aW9ucy5pbmRleEF4aXNdKSlyZXR1cm47aWYoIWwuY29udHJvbGxlci5zdXBwb3J0c0RlY2ltYXRpb24pcmV0dXJuO2NvbnN0IGM9dC5zY2FsZXNbbC54QXhpc0lEXTtpZigibGluZWFyIiE9PWMudHlwZSYmInRpbWUiIT09Yy50eXBlKXJldHVybjtpZih0Lm9wdGlvbnMucGFyc2luZylyZXR1cm47bGV0e3N0YXJ0OmQsY291bnQ6dX09ZnVuY3Rpb24odCxlKXtjb25zdCBpPWUubGVuZ3RoO2xldCBzLG49MDtjb25zdHtpU2NhbGU6b309dCx7bWluOmEsbWF4OnIsbWluRGVmaW5lZDpsLG1heERlZmluZWQ6aH09by5nZXRVc2VyQm91bmRzKCk7cmV0dXJuIGwmJihuPUooaXQoZSxvLmF4aXMsYSkubG8sMCxpLTEpKSxzPWg\/SihpdChlLG8uYXhpcyxyKS5oaSsxLG4saSktbjppLW4se3N0YXJ0Om4sY291bnQ6c319KGwsaCk7aWYodTw9KGkudGhyZXNob2xkfHw0Km4pKXJldHVybiB2b2lkIFpvKGUpO2xldCBmO3N3aXRjaChzKGEpJiYoZS5fZGF0YT1oLGRlbGV0ZSBlLmRhdGEsT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsImRhdGEiLHtjb25maWd1cmFibGU6ITAsZW51bWVyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZGVjaW1hdGVkfSxzZXQ6ZnVuY3Rpb24odCl7dGhpcy5fZGF0YT10fX0pKSxpLmFsZ29yaXRobSl7Y2FzZSJsdHRiIjpmPWZ1bmN0aW9uKHQsZSxpLHMsbil7Y29uc3Qgbz1uLnNhbXBsZXN8fHM7aWYobz49aSlyZXR1cm4gdC5zbGljZShlLGUraSk7Y29uc3QgYT1bXSxyPShpLTIpLyhvLTIpO2xldCBsPTA7Y29uc3QgaD1lK2ktMTtsZXQgYyxkLHUsZixnLHA9ZTtmb3IoYVtsKytdPXRbcF0sYz0wO2M8by0yO2MrKyl7bGV0IHMsbj0wLG89MDtjb25zdCBoPU1hdGguZmxvb3IoKGMrMSkqcikrMStlLG09TWF0aC5taW4oTWF0aC5mbG9vcigoYysyKSpyKSsxLGkpK2UsYj1tLWg7Zm9yKHM9aDtzPG07cysrKW4rPXRbc10ueCxvKz10W3NdLnk7bi89YixvLz1iO2NvbnN0IHg9TWF0aC5mbG9vcihjKnIpKzErZSxfPU1hdGgubWluKE1hdGguZmxvb3IoKGMrMSkqcikrMSxpKStlLHt4OnkseTp2fT10W3BdO2Zvcih1PWY9LTEscz14O3M8XztzKyspZj0uNSpNYXRoLmFicygoeS1uKSoodFtzXS55LXYpLSh5LXRbc10ueCkqKG8tdikpLGY+dSYmKHU9ZixkPXRbc10sZz1zKTthW2wrK109ZCxwPWd9cmV0dXJuIGFbbCsrXT10W2hdLGF9KGgsZCx1LG4saSk7YnJlYWs7Y2FzZSJtaW4tbWF4IjpmPWZ1bmN0aW9uKHQsZSxpLG4pe2xldCBvLGEscixsLGgsYyxkLHUsZixnLHA9MCxtPTA7Y29uc3QgYj1bXSx4PWUraS0xLF89dFtlXS54LHk9dFt4XS54LV87Zm9yKG89ZTtvPGUraTsrK28pe2E9dFtvXSxyPShhLngtXykveSpuLGw9YS55O2NvbnN0IGU9MHxyO2lmKGU9PT1oKWw8Zj8oZj1sLGM9byk6bD5nJiYoZz1sLGQ9bykscD0obSpwK2EueCkvKyttO2Vsc2V7Y29uc3QgaT1vLTE7aWYoIXMoYykmJiFzKGQpKXtjb25zdCBlPU1hdGgubWluKGMsZCkscz1NYXRoLm1heChjLGQpO2UhPT11JiZlIT09aSYmYi5wdXNoKHsuLi50W2VdLHg6cH0pLHMhPT11JiZzIT09aSYmYi5wdXNoKHsuLi50W3NdLHg6cH0pfW8+MCYmaSE9PXUmJmIucHVzaCh0W2ldKSxiLnB1c2goYSksaD1lLG09MCxmPWc9bCxjPWQ9dT1vfX1yZXR1cm4gYn0oaCxkLHUsbik7YnJlYWs7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRlY2ltYXRpb24gYWxnb3JpdGhtICcke2kuYWxnb3JpdGhtfSdgKX1lLl9kZWNpbWF0ZWQ9Zn0pKX0sZGVzdHJveSh0KXtKbyh0KX19O2Z1bmN0aW9uIHRhKHQsZSxpLHMpe2lmKHMpcmV0dXJuO2xldCBuPWVbdF0sbz1pW3RdO3JldHVybiJhbmdsZSI9PT10JiYobj1HKG4pLG89RyhvKSkse3Byb3BlcnR5OnQsc3RhcnQ6bixlbmQ6b319ZnVuY3Rpb24gZWEodCxlLGkpe2Zvcig7ZT50O2UtLSl7Y29uc3QgdD1pW2VdO2lmKCFpc05hTih0LngpJiYhaXNOYU4odC55KSlicmVha31yZXR1cm4gZX1mdW5jdGlvbiBpYSh0LGUsaSxzKXtyZXR1cm4gdCYmZT9zKHRbaV0sZVtpXSk6dD90W2ldOmU\/ZVtpXTowfWZ1bmN0aW9uIHNhKHQsZSl7bGV0IGk9W10scz0hMTtyZXR1cm4gbih0KT8ocz0hMCxpPXQpOmk9ZnVuY3Rpb24odCxlKXtjb25zdHt4Omk9bnVsbCx5OnM9bnVsbH09dHx8e30sbj1lLnBvaW50cyxvPVtdO3JldHVybiBlLnNlZ21lbnRzLmZvckVhY2goKCh7c3RhcnQ6dCxlbmQ6ZX0pPT57ZT1lYSh0LGUsbik7Y29uc3QgYT1uW3RdLHI9bltlXTtudWxsIT09cz8oby5wdXNoKHt4OmEueCx5OnN9KSxvLnB1c2goe3g6ci54LHk6c30pKTpudWxsIT09aSYmKG8ucHVzaCh7eDppLHk6YS55fSksby5wdXNoKHt4OmkseTpyLnl9KSl9KSksb30odCxlKSxpLmxlbmd0aD9uZXcgbm8oe3BvaW50czppLG9wdGlvbnM6e3RlbnNpb246MH0sX2xvb3A6cyxfZnVsbExvb3A6c30pOm51bGx9ZnVuY3Rpb24gbmEodCl7cmV0dXJuIHQmJiExIT09dC5maWxsfWZ1bmN0aW9uIG9hKHQsZSxpKXtsZXQgcz10W2VdLmZpbGw7Y29uc3Qgbj1bZV07bGV0IG87aWYoIWkpcmV0dXJuIHM7Zm9yKDshMSE9PXMmJi0xPT09bi5pbmRleE9mKHMpOyl7aWYoIWEocykpcmV0dXJuIHM7aWYobz10W3NdLCFvKXJldHVybiExO2lmKG8udmlzaWJsZSlyZXR1cm4gcztuLnB1c2gocykscz1vLmZpbGx9cmV0dXJuITF9ZnVuY3Rpb24gYWEodCxlLGkpe2NvbnN0IHM9ZnVuY3Rpb24odCl7Y29uc3QgZT10Lm9wdGlvbnMsaT1lLmZpbGw7bGV0IHM9bChpJiZpLnRhcmdldCxpKTt2b2lkIDA9PT1zJiYocz0hIWUuYmFja2dyb3VuZENvbG9yKTtpZighMT09PXN8fG51bGw9PT1zKXJldHVybiExO2lmKCEwPT09cylyZXR1cm4ib3JpZ2luIjtyZXR1cm4gc30odCk7aWYobyhzKSlyZXR1cm4haXNOYU4ocy52YWx1ZSkmJnM7bGV0IG49cGFyc2VGbG9hdChzKTtyZXR1cm4gYShuKSYmTWF0aC5mbG9vcihuKT09PW4\/ZnVuY3Rpb24odCxlLGkscyl7Ii0iIT09dCYmIisiIT09dHx8KGk9ZStpKTtpZihpPT09ZXx8aTwwfHxpPj1zKXJldHVybiExO3JldHVybiBpfShzWzBdLGUsbixpKTpbIm9yaWdpbiIsInN0YXJ0IiwiZW5kIiwic3RhY2siLCJzaGFwZSJdLmluZGV4T2Yocyk+PTAmJnN9ZnVuY3Rpb24gcmEodCxlLGkpe2NvbnN0IHM9W107Zm9yKGxldCBuPTA7bjxpLmxlbmd0aDtuKyspe2NvbnN0IG89aVtuXSx7Zmlyc3Q6YSxsYXN0OnIscG9pbnQ6bH09bGEobyxlLCJ4Iik7aWYoISghbHx8YSYmcikpaWYoYSlzLnVuc2hpZnQobCk7ZWxzZSBpZih0LnB1c2gobCksIXIpYnJlYWt9dC5wdXNoKC4uLnMpfWZ1bmN0aW9uIGxhKHQsZSxpKXtjb25zdCBzPXQuaW50ZXJwb2xhdGUoZSxpKTtpZighcylyZXR1cm57fTtjb25zdCBuPXNbaV0sbz10LnNlZ21lbnRzLGE9dC5wb2ludHM7bGV0IHI9ITEsbD0hMTtmb3IobGV0IHQ9MDt0PG8ubGVuZ3RoO3QrKyl7Y29uc3QgZT1vW3RdLHM9YVtlLnN0YXJ0XVtpXSxoPWFbZS5lbmRdW2ldO2lmKHR0KG4scyxoKSl7cj1uPT09cyxsPW49PT1oO2JyZWFrfX1yZXR1cm57Zmlyc3Q6cixsYXN0OmwscG9pbnQ6c319Y2xhc3MgaGF7Y29uc3RydWN0b3IodCl7dGhpcy54PXQueCx0aGlzLnk9dC55LHRoaXMucmFkaXVzPXQucmFkaXVzfXBhdGhTZWdtZW50KHQsZSxpKXtjb25zdHt4OnMseTpuLHJhZGl1czpvfT10aGlzO3JldHVybiBlPWV8fHtzdGFydDowLGVuZDpPfSx0LmFyYyhzLG4sbyxlLmVuZCxlLnN0YXJ0LCEwKSwhaS5ib3VuZHN9aW50ZXJwb2xhdGUodCl7Y29uc3R7eDplLHk6aSxyYWRpdXM6c309dGhpcyxuPXQuYW5nbGU7cmV0dXJue3g6ZStNYXRoLmNvcyhuKSpzLHk6aStNYXRoLnNpbihuKSpzLGFuZ2xlOm59fX1mdW5jdGlvbiBjYSh0KXtjb25zdHtjaGFydDplLGZpbGw6aSxsaW5lOnN9PXQ7aWYoYShpKSlyZXR1cm4gZnVuY3Rpb24odCxlKXtjb25zdCBpPXQuZ2V0RGF0YXNldE1ldGEoZSkscz1pJiZ0LmlzRGF0YXNldFZpc2libGUoZSk7cmV0dXJuIHM\/aS5kYXRhc2V0Om51bGx9KGUsaSk7aWYoInN0YWNrIj09PWkpcmV0dXJuIGZ1bmN0aW9uKHQpe2NvbnN0e3NjYWxlOmUsaW5kZXg6aSxsaW5lOnN9PXQsbj1bXSxvPXMuc2VnbWVudHMsYT1zLnBvaW50cyxyPWZ1bmN0aW9uKHQsZSl7Y29uc3QgaT1bXSxzPXQuZ2V0TWF0Y2hpbmdWaXNpYmxlTWV0YXMoImxpbmUiKTtmb3IobGV0IHQ9MDt0PHMubGVuZ3RoO3QrKyl7Y29uc3Qgbj1zW3RdO2lmKG4uaW5kZXg9PT1lKWJyZWFrO24uaGlkZGVufHxpLnVuc2hpZnQobi5kYXRhc2V0KX1yZXR1cm4gaX0oZSxpKTtyLnB1c2goc2Eoe3g6bnVsbCx5OmUuYm90dG9tfSxzKSk7Zm9yKGxldCB0PTA7dDxvLmxlbmd0aDt0Kyspe2NvbnN0IGU9b1t0XTtmb3IobGV0IHQ9ZS5zdGFydDt0PD1lLmVuZDt0KyspcmEobixhW3RdLHIpfXJldHVybiBuZXcgbm8oe3BvaW50czpuLG9wdGlvbnM6e319KX0odCk7aWYoInNoYXBlIj09PWkpcmV0dXJuITA7Y29uc3Qgbj1mdW5jdGlvbih0KXtjb25zdCBlPXQuc2NhbGV8fHt9O2lmKGUuZ2V0UG9pbnRQb3NpdGlvbkZvclZhbHVlKXJldHVybiBmdW5jdGlvbih0KXtjb25zdHtzY2FsZTplLGZpbGw6aX09dCxzPWUub3B0aW9ucyxuPWUuZ2V0TGFiZWxzKCkubGVuZ3RoLGE9cy5yZXZlcnNlP2UubWF4OmUubWluLHI9ZnVuY3Rpb24odCxlLGkpe2xldCBzO3JldHVybiBzPSJzdGFydCI9PT10P2k6ImVuZCI9PT10P2Uub3B0aW9ucy5yZXZlcnNlP2UubWluOmUubWF4Om8odCk\/dC52YWx1ZTplLmdldEJhc2VWYWx1ZSgpLHN9KGksZSxhKSxsPVtdO2lmKHMuZ3JpZC5jaXJjdWxhcil7Y29uc3QgdD1lLmdldFBvaW50UG9zaXRpb25Gb3JWYWx1ZSgwLGEpO3JldHVybiBuZXcgaGEoe3g6dC54LHk6dC55LHJhZGl1czplLmdldERpc3RhbmNlRnJvbUNlbnRlckZvclZhbHVlKHIpfSl9Zm9yKGxldCB0PTA7dDxuOysrdClsLnB1c2goZS5nZXRQb2ludFBvc2l0aW9uRm9yVmFsdWUodCxyKSk7cmV0dXJuIGx9KHQpO3JldHVybiBmdW5jdGlvbih0KXtjb25zdHtzY2FsZTplPXt9LGZpbGw6aX09dCxzPWZ1bmN0aW9uKHQsZSl7bGV0IGk9bnVsbDtyZXR1cm4ic3RhcnQiPT09dD9pPWUuYm90dG9tOiJlbmQiPT09dD9pPWUudG9wOm8odCk\/aT1lLmdldFBpeGVsRm9yVmFsdWUodC52YWx1ZSk6ZS5nZXRCYXNlUGl4ZWwmJihpPWUuZ2V0QmFzZVBpeGVsKCkpLGl9KGksZSk7aWYoYShzKSl7Y29uc3QgdD1lLmlzSG9yaXpvbnRhbCgpO3JldHVybnt4OnQ\/czpudWxsLHk6dD9udWxsOnN9fXJldHVybiBudWxsfSh0KX0odCk7cmV0dXJuIG4gaW5zdGFuY2VvZiBoYT9uOnNhKG4scyl9ZnVuY3Rpb24gZGEodCxlLGkpe2NvbnN0IHM9Y2EoZSkse2xpbmU6bixzY2FsZTpvLGF4aXM6YX09ZSxyPW4ub3B0aW9ucyxsPXIuZmlsbCxoPXIuYmFja2dyb3VuZENvbG9yLHthYm92ZTpjPWgsYmVsb3c6ZD1ofT1sfHx7fTtzJiZuLnBvaW50cy5sZW5ndGgmJihJZSh0LGkpLGZ1bmN0aW9uKHQsZSl7Y29uc3R7bGluZTppLHRhcmdldDpzLGFib3ZlOm4sYmVsb3c6byxhcmVhOmEsc2NhbGU6cn09ZSxsPWkuX2xvb3A\/ImFuZ2xlIjplLmF4aXM7dC5zYXZlKCksIngiPT09bCYmbyE9PW4mJih1YSh0LHMsYS50b3ApLGZhKHQse2xpbmU6aSx0YXJnZXQ6cyxjb2xvcjpuLHNjYWxlOnIscHJvcGVydHk6bH0pLHQucmVzdG9yZSgpLHQuc2F2ZSgpLHVhKHQscyxhLmJvdHRvbSkpO2ZhKHQse2xpbmU6aSx0YXJnZXQ6cyxjb2xvcjpvLHNjYWxlOnIscHJvcGVydHk6bH0pLHQucmVzdG9yZSgpfSh0LHtsaW5lOm4sdGFyZ2V0OnMsYWJvdmU6YyxiZWxvdzpkLGFyZWE6aSxzY2FsZTpvLGF4aXM6YX0pLHplKHQpKX1mdW5jdGlvbiB1YSh0LGUsaSl7Y29uc3R7c2VnbWVudHM6cyxwb2ludHM6bn09ZTtsZXQgbz0hMCxhPSExO3QuYmVnaW5QYXRoKCk7Zm9yKGNvbnN0IHIgb2Ygcyl7Y29uc3R7c3RhcnQ6cyxlbmQ6bH09cixoPW5bc10sYz1uW2VhKHMsbCxuKV07bz8odC5tb3ZlVG8oaC54LGgueSksbz0hMSk6KHQubGluZVRvKGgueCxpKSx0LmxpbmVUbyhoLngsaC55KSksYT0hIWUucGF0aFNlZ21lbnQodCxyLHttb3ZlOmF9KSxhP3QuY2xvc2VQYXRoKCk6dC5saW5lVG8oYy54LGkpfXQubGluZVRvKGUuZmlyc3QoKS54LGkpLHQuY2xvc2VQYXRoKCksdC5jbGlwKCl9ZnVuY3Rpb24gZmEodCxlKXtjb25zdHtsaW5lOmksdGFyZ2V0OnMscHJvcGVydHk6bixjb2xvcjpvLHNjYWxlOmF9PWUscj1mdW5jdGlvbih0LGUsaSl7Y29uc3Qgcz10LnNlZ21lbnRzLG49dC5wb2ludHMsbz1lLnBvaW50cyxhPVtdO2Zvcihjb25zdCB0IG9mIHMpe2xldHtzdGFydDpzLGVuZDpyfT10O3I9ZWEocyxyLG4pO2NvbnN0IGw9dGEoaSxuW3NdLG5bcl0sdC5sb29wKTtpZighZS5zZWdtZW50cyl7YS5wdXNoKHtzb3VyY2U6dCx0YXJnZXQ6bCxzdGFydDpuW3NdLGVuZDpuW3JdfSk7Y29udGludWV9Y29uc3QgaD1JaShlLGwpO2Zvcihjb25zdCBlIG9mIGgpe2NvbnN0IHM9dGEoaSxvW2Uuc3RhcnRdLG9bZS5lbmRdLGUubG9vcCkscj1SaSh0LG4scyk7Zm9yKGNvbnN0IHQgb2YgcilhLnB1c2goe3NvdXJjZTp0LHRhcmdldDplLHN0YXJ0OntbaV06aWEobCxzLCJzdGFydCIsTWF0aC5tYXgpfSxlbmQ6e1tpXTppYShsLHMsImVuZCIsTWF0aC5taW4pfX0pfX1yZXR1cm4gYX0oaSxzLG4pO2Zvcihjb25zdHtzb3VyY2U6ZSx0YXJnZXQ6bCxzdGFydDpoLGVuZDpjfW9mIHIpe2NvbnN0e3N0eWxlOntiYWNrZ3JvdW5kQ29sb3I6cj1vfT17fX09ZSxkPSEwIT09czt0LnNhdmUoKSx0LmZpbGxTdHlsZT1yLGdhKHQsYSxkJiZ0YShuLGgsYykpLHQuYmVnaW5QYXRoKCk7Y29uc3QgdT0hIWkucGF0aFNlZ21lbnQodCxlKTtsZXQgZjtpZihkKXt1P3QuY2xvc2VQYXRoKCk6cGEodCxzLGMsbik7Y29uc3QgZT0hIXMucGF0aFNlZ21lbnQodCxsLHttb3ZlOnUscmV2ZXJzZTohMH0pO2Y9dSYmZSxmfHxwYSh0LHMsaCxuKX10LmNsb3NlUGF0aCgpLHQuZmlsbChmPyJldmVub2RkIjoibm9uemVybyIpLHQucmVzdG9yZSgpfX1mdW5jdGlvbiBnYSh0LGUsaSl7Y29uc3R7dG9wOnMsYm90dG9tOm59PWUuY2hhcnQuY2hhcnRBcmVhLHtwcm9wZXJ0eTpvLHN0YXJ0OmEsZW5kOnJ9PWl8fHt9OyJ4Ij09PW8mJih0LmJlZ2luUGF0aCgpLHQucmVjdChhLHMsci1hLG4tcyksdC5jbGlwKCkpfWZ1bmN0aW9uIHBhKHQsZSxpLHMpe2NvbnN0IG49ZS5pbnRlcnBvbGF0ZShpLHMpO24mJnQubGluZVRvKG4ueCxuLnkpfXZhciBtYT17aWQ6ImZpbGxlciIsYWZ0ZXJEYXRhc2V0c1VwZGF0ZSh0LGUsaSl7Y29uc3Qgcz0odC5kYXRhLmRhdGFzZXRzfHxbXSkubGVuZ3RoLG49W107bGV0IG8sYSxyLGw7Zm9yKGE9MDthPHM7KythKW89dC5nZXREYXRhc2V0TWV0YShhKSxyPW8uZGF0YXNldCxsPW51bGwsciYmci5vcHRpb25zJiZyIGluc3RhbmNlb2Ygbm8mJihsPXt2aXNpYmxlOnQuaXNEYXRhc2V0VmlzaWJsZShhKSxpbmRleDphLGZpbGw6YWEocixhLHMpLGNoYXJ0OnQsYXhpczpvLmNvbnRyb2xsZXIub3B0aW9ucy5pbmRleEF4aXMsc2NhbGU6by52U2NhbGUsbGluZTpyfSksby4kZmlsbGVyPWwsbi5wdXNoKGwpO2ZvcihhPTA7YTxzOysrYSlsPW5bYV0sbCYmITEhPT1sLmZpbGwmJihsLmZpbGw9b2EobixhLGkucHJvcGFnYXRlKSl9LGJlZm9yZURyYXcodCxlLGkpe2NvbnN0IHM9ImJlZm9yZURyYXciPT09aS5kcmF3VGltZSxuPXQuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpLG89dC5jaGFydEFyZWE7Zm9yKGxldCBlPW4ubGVuZ3RoLTE7ZT49MDstLWUpe2NvbnN0IGk9bltlXS4kZmlsbGVyO2kmJihpLmxpbmUudXBkYXRlQ29udHJvbFBvaW50cyhvLGkuYXhpcykscyYmaS5maWxsJiZkYSh0LmN0eCxpLG8pKX19LGJlZm9yZURhdGFzZXRzRHJhdyh0LGUsaSl7aWYoImJlZm9yZURhdGFzZXRzRHJhdyIhPT1pLmRyYXdUaW1lKXJldHVybjtjb25zdCBzPXQuZ2V0U29ydGVkVmlzaWJsZURhdGFzZXRNZXRhcygpO2ZvcihsZXQgZT1zLmxlbmd0aC0xO2U+PTA7LS1lKXtjb25zdCBpPXNbZV0uJGZpbGxlcjtuYShpKSYmZGEodC5jdHgsaSx0LmNoYXJ0QXJlYSl9fSxiZWZvcmVEYXRhc2V0RHJhdyh0LGUsaSl7Y29uc3Qgcz1lLm1ldGEuJGZpbGxlcjtuYShzKSYmImJlZm9yZURhdGFzZXREcmF3Ij09PWkuZHJhd1RpbWUmJmRhKHQuY3R4LHMsdC5jaGFydEFyZWEpfSxkZWZhdWx0czp7cHJvcGFnYXRlOiEwLGRyYXdUaW1lOiJiZWZvcmVEYXRhc2V0RHJhdyJ9fTtjb25zdCBiYT0odCxlKT0+e2xldHtib3hIZWlnaHQ6aT1lLGJveFdpZHRoOnM9ZX09dDtyZXR1cm4gdC51c2VQb2ludFN0eWxlJiYoaT1NYXRoLm1pbihpLGUpLHM9dC5wb2ludFN0eWxlV2lkdGh8fE1hdGgubWluKHMsZSkpLHtib3hXaWR0aDpzLGJveEhlaWdodDppLGl0ZW1IZWlnaHQ6TWF0aC5tYXgoZSxpKX19O2NsYXNzIHhhIGV4dGVuZHMgSHN7Y29uc3RydWN0b3IodCl7c3VwZXIoKSx0aGlzLl9hZGRlZD0hMSx0aGlzLmxlZ2VuZEhpdEJveGVzPVtdLHRoaXMuX2hvdmVyZWRJdGVtPW51bGwsdGhpcy5kb3VnaG51dE1vZGU9ITEsdGhpcy5jaGFydD10LmNoYXJ0LHRoaXMub3B0aW9ucz10Lm9wdGlvbnMsdGhpcy5jdHg9dC5jdHgsdGhpcy5sZWdlbmRJdGVtcz12b2lkIDAsdGhpcy5jb2x1bW5TaXplcz12b2lkIDAsdGhpcy5saW5lV2lkdGhzPXZvaWQgMCx0aGlzLm1heEhlaWdodD12b2lkIDAsdGhpcy5tYXhXaWR0aD12b2lkIDAsdGhpcy50b3A9dm9pZCAwLHRoaXMuYm90dG9tPXZvaWQgMCx0aGlzLmxlZnQ9dm9pZCAwLHRoaXMucmlnaHQ9dm9pZCAwLHRoaXMuaGVpZ2h0PXZvaWQgMCx0aGlzLndpZHRoPXZvaWQgMCx0aGlzLl9tYXJnaW5zPXZvaWQgMCx0aGlzLnBvc2l0aW9uPXZvaWQgMCx0aGlzLndlaWdodD12b2lkIDAsdGhpcy5mdWxsU2l6ZT12b2lkIDB9dXBkYXRlKHQsZSxpKXt0aGlzLm1heFdpZHRoPXQsdGhpcy5tYXhIZWlnaHQ9ZSx0aGlzLl9tYXJnaW5zPWksdGhpcy5zZXREaW1lbnNpb25zKCksdGhpcy5idWlsZExhYmVscygpLHRoaXMuZml0KCl9c2V0RGltZW5zaW9ucygpe3RoaXMuaXNIb3Jpem9udGFsKCk\/KHRoaXMud2lkdGg9dGhpcy5tYXhXaWR0aCx0aGlzLmxlZnQ9dGhpcy5fbWFyZ2lucy5sZWZ0LHRoaXMucmlnaHQ9dGhpcy53aWR0aCk6KHRoaXMuaGVpZ2h0PXRoaXMubWF4SGVpZ2h0LHRoaXMudG9wPXRoaXMuX21hcmdpbnMudG9wLHRoaXMuYm90dG9tPXRoaXMuaGVpZ2h0KX1idWlsZExhYmVscygpe2NvbnN0IHQ9dGhpcy5vcHRpb25zLmxhYmVsc3x8e307bGV0IGU9ZCh0LmdlbmVyYXRlTGFiZWxzLFt0aGlzLmNoYXJ0XSx0aGlzKXx8W107dC5maWx0ZXImJihlPWUuZmlsdGVyKChlPT50LmZpbHRlcihlLHRoaXMuY2hhcnQuZGF0YSkpKSksdC5zb3J0JiYoZT1lLnNvcnQoKChlLGkpPT50LnNvcnQoZSxpLHRoaXMuY2hhcnQuZGF0YSkpKSksdGhpcy5vcHRpb25zLnJldmVyc2UmJmUucmV2ZXJzZSgpLHRoaXMubGVnZW5kSXRlbXM9ZX1maXQoKXtjb25zdHtvcHRpb25zOnQsY3R4OmV9PXRoaXM7aWYoIXQuZGlzcGxheSlyZXR1cm4gdm9pZCh0aGlzLndpZHRoPXRoaXMuaGVpZ2h0PTApO2NvbnN0IGk9dC5sYWJlbHMscz1TaShpLmZvbnQpLG49cy5zaXplLG89dGhpcy5fY29tcHV0ZVRpdGxlSGVpZ2h0KCkse2JveFdpZHRoOmEsaXRlbUhlaWdodDpyfT1iYShpLG4pO2xldCBsLGg7ZS5mb250PXMuc3RyaW5nLHRoaXMuaXNIb3Jpem9udGFsKCk\/KGw9dGhpcy5tYXhXaWR0aCxoPXRoaXMuX2ZpdFJvd3MobyxuLGEscikrMTApOihoPXRoaXMubWF4SGVpZ2h0LGw9dGhpcy5fZml0Q29scyhvLHMsYSxyKSsxMCksdGhpcy53aWR0aD1NYXRoLm1pbihsLHQubWF4V2lkdGh8fHRoaXMubWF4V2lkdGgpLHRoaXMuaGVpZ2h0PU1hdGgubWluKGgsdC5tYXhIZWlnaHR8fHRoaXMubWF4SGVpZ2h0KX1fZml0Um93cyh0LGUsaSxzKXtjb25zdHtjdHg6bixtYXhXaWR0aDpvLG9wdGlvbnM6e2xhYmVsczp7cGFkZGluZzphfX19PXRoaXMscj10aGlzLmxlZ2VuZEhpdEJveGVzPVtdLGw9dGhpcy5saW5lV2lkdGhzPVswXSxoPXMrYTtsZXQgYz10O24udGV4dEFsaWduPSJsZWZ0IixuLnRleHRCYXNlbGluZT0ibWlkZGxlIjtsZXQgZD0tMSx1PS1oO3JldHVybiB0aGlzLmxlZ2VuZEl0ZW1zLmZvckVhY2goKCh0LGYpPT57Y29uc3QgZz1pK2UvMituLm1lYXN1cmVUZXh0KHQudGV4dCkud2lkdGg7KDA9PT1mfHxsW2wubGVuZ3RoLTFdK2crMiphPm8pJiYoYys9aCxsW2wubGVuZ3RoLShmPjA\/MDoxKV09MCx1Kz1oLGQrKykscltmXT17bGVmdDowLHRvcDp1LHJvdzpkLHdpZHRoOmcsaGVpZ2h0OnN9LGxbbC5sZW5ndGgtMV0rPWcrYX0pKSxjfV9maXRDb2xzKHQsZSxpLHMpe2NvbnN0e2N0eDpuLG1heEhlaWdodDpvLG9wdGlvbnM6e2xhYmVsczp7cGFkZGluZzphfX19PXRoaXMscj10aGlzLmxlZ2VuZEhpdEJveGVzPVtdLGw9dGhpcy5jb2x1bW5TaXplcz1bXSxoPW8tdDtsZXQgYz1hLGQ9MCx1PTAsZj0wLGc9MDtyZXR1cm4gdGhpcy5sZWdlbmRJdGVtcy5mb3JFYWNoKCgodCxvKT0+e2NvbnN0e2l0ZW1XaWR0aDpwLGl0ZW1IZWlnaHQ6bX09ZnVuY3Rpb24odCxlLGkscyxuKXtjb25zdCBvPWZ1bmN0aW9uKHQsZSxpLHMpe2xldCBuPXQudGV4dDtuJiYic3RyaW5nIiE9dHlwZW9mIG4mJihuPW4ucmVkdWNlKCgodCxlKT0+dC5sZW5ndGg+ZS5sZW5ndGg\/dDplKSkpO3JldHVybiBlK2kuc2l6ZS8yK3MubWVhc3VyZVRleHQobikud2lkdGh9KHMsdCxlLGkpLGE9ZnVuY3Rpb24odCxlLGkpe2xldCBzPXQ7InN0cmluZyIhPXR5cGVvZiBlLnRleHQmJihzPV9hKGUsaSkpO3JldHVybiBzfShuLHMsZS5saW5lSGVpZ2h0KTtyZXR1cm57aXRlbVdpZHRoOm8saXRlbUhlaWdodDphfX0oaSxlLG4sdCxzKTtvPjAmJnUrbSsyKmE+aCYmKGMrPWQrYSxsLnB1c2goe3dpZHRoOmQsaGVpZ2h0OnV9KSxmKz1kK2EsZysrLGQ9dT0wKSxyW29dPXtsZWZ0OmYsdG9wOnUsY29sOmcsd2lkdGg6cCxoZWlnaHQ6bX0sZD1NYXRoLm1heChkLHApLHUrPW0rYX0pKSxjKz1kLGwucHVzaCh7d2lkdGg6ZCxoZWlnaHQ6dX0pLGN9YWRqdXN0SGl0Qm94ZXMoKXtpZighdGhpcy5vcHRpb25zLmRpc3BsYXkpcmV0dXJuO2NvbnN0IHQ9dGhpcy5fY29tcHV0ZVRpdGxlSGVpZ2h0KCkse2xlZ2VuZEhpdEJveGVzOmUsb3B0aW9uczp7YWxpZ246aSxsYWJlbHM6e3BhZGRpbmc6c30scnRsOm59fT10aGlzLG89T2kobix0aGlzLmxlZnQsdGhpcy53aWR0aCk7aWYodGhpcy5pc0hvcml6b250YWwoKSl7bGV0IG49MCxhPWZ0KGksdGhpcy5sZWZ0K3MsdGhpcy5yaWdodC10aGlzLmxpbmVXaWR0aHNbbl0pO2Zvcihjb25zdCByIG9mIGUpbiE9PXIucm93JiYobj1yLnJvdyxhPWZ0KGksdGhpcy5sZWZ0K3MsdGhpcy5yaWdodC10aGlzLmxpbmVXaWR0aHNbbl0pKSxyLnRvcCs9dGhpcy50b3ArdCtzLHIubGVmdD1vLmxlZnRGb3JMdHIoby54KGEpLHIud2lkdGgpLGErPXIud2lkdGgrc31lbHNle2xldCBuPTAsYT1mdChpLHRoaXMudG9wK3Qrcyx0aGlzLmJvdHRvbS10aGlzLmNvbHVtblNpemVzW25dLmhlaWdodCk7Zm9yKGNvbnN0IHIgb2YgZSlyLmNvbCE9PW4mJihuPXIuY29sLGE9ZnQoaSx0aGlzLnRvcCt0K3MsdGhpcy5ib3R0b20tdGhpcy5jb2x1bW5TaXplc1tuXS5oZWlnaHQpKSxyLnRvcD1hLHIubGVmdCs9dGhpcy5sZWZ0K3Msci5sZWZ0PW8ubGVmdEZvckx0cihvLngoci5sZWZ0KSxyLndpZHRoKSxhKz1yLmhlaWdodCtzfX1pc0hvcml6b250YWwoKXtyZXR1cm4idG9wIj09PXRoaXMub3B0aW9ucy5wb3NpdGlvbnx8ImJvdHRvbSI9PT10aGlzLm9wdGlvbnMucG9zaXRpb259ZHJhdygpe2lmKHRoaXMub3B0aW9ucy5kaXNwbGF5KXtjb25zdCB0PXRoaXMuY3R4O0llKHQsdGhpcyksdGhpcy5fZHJhdygpLHplKHQpfX1fZHJhdygpe2NvbnN0e29wdGlvbnM6dCxjb2x1bW5TaXplczplLGxpbmVXaWR0aHM6aSxjdHg6c309dGhpcyx7YWxpZ246bixsYWJlbHM6b309dCxhPXVlLmNvbG9yLHI9T2kodC5ydGwsdGhpcy5sZWZ0LHRoaXMud2lkdGgpLGg9U2koby5mb250KSx7cGFkZGluZzpjfT1vLGQ9aC5zaXplLHU9ZC8yO2xldCBmO3RoaXMuZHJhd1RpdGxlKCkscy50ZXh0QWxpZ249ci50ZXh0QWxpZ24oImxlZnQiKSxzLnRleHRCYXNlbGluZT0ibWlkZGxlIixzLmxpbmVXaWR0aD0uNSxzLmZvbnQ9aC5zdHJpbmc7Y29uc3R7Ym94V2lkdGg6Zyxib3hIZWlnaHQ6cCxpdGVtSGVpZ2h0Om19PWJhKG8sZCksYj10aGlzLmlzSG9yaXpvbnRhbCgpLHg9dGhpcy5fY29tcHV0ZVRpdGxlSGVpZ2h0KCk7Zj1iP3t4OmZ0KG4sdGhpcy5sZWZ0K2MsdGhpcy5yaWdodC1pWzBdKSx5OnRoaXMudG9wK2MreCxsaW5lOjB9Ont4OnRoaXMubGVmdCtjLHk6ZnQobix0aGlzLnRvcCt4K2MsdGhpcy5ib3R0b20tZVswXS5oZWlnaHQpLGxpbmU6MH0sQWkodGhpcy5jdHgsdC50ZXh0RGlyZWN0aW9uKTtjb25zdCBfPW0rYzt0aGlzLmxlZ2VuZEl0ZW1zLmZvckVhY2goKCh5LHYpPT57cy5zdHJva2VTdHlsZT15LmZvbnRDb2xvcixzLmZpbGxTdHlsZT15LmZvbnRDb2xvcjtjb25zdCBNPXMubWVhc3VyZVRleHQoeS50ZXh0KS53aWR0aCx3PXIudGV4dEFsaWduKHkudGV4dEFsaWdufHwoeS50ZXh0QWxpZ249by50ZXh0QWxpZ24pKSxrPWcrdStNO2xldCBTPWYueCxQPWYueTtyLnNldFdpZHRoKHRoaXMud2lkdGgpLGI\/dj4wJiZTK2srYz50aGlzLnJpZ2h0JiYoUD1mLnkrPV8sZi5saW5lKyssUz1mLng9ZnQobix0aGlzLmxlZnQrYyx0aGlzLnJpZ2h0LWlbZi5saW5lXSkpOnY+MCYmUCtfPnRoaXMuYm90dG9tJiYoUz1mLng9UytlW2YubGluZV0ud2lkdGgrYyxmLmxpbmUrKyxQPWYueT1mdChuLHRoaXMudG9wK3grYyx0aGlzLmJvdHRvbS1lW2YubGluZV0uaGVpZ2h0KSk7aWYoZnVuY3Rpb24odCxlLGkpe2lmKGlzTmFOKGcpfHxnPD0wfHxpc05hTihwKXx8cDwwKXJldHVybjtzLnNhdmUoKTtjb25zdCBuPWwoaS5saW5lV2lkdGgsMSk7aWYocy5maWxsU3R5bGU9bChpLmZpbGxTdHlsZSxhKSxzLmxpbmVDYXA9bChpLmxpbmVDYXAsImJ1dHQiKSxzLmxpbmVEYXNoT2Zmc2V0PWwoaS5saW5lRGFzaE9mZnNldCwwKSxzLmxpbmVKb2luPWwoaS5saW5lSm9pbiwibWl0ZXIiKSxzLmxpbmVXaWR0aD1uLHMuc3Ryb2tlU3R5bGU9bChpLnN0cm9rZVN0eWxlLGEpLHMuc2V0TGluZURhc2gobChpLmxpbmVEYXNoLFtdKSksby51c2VQb2ludFN0eWxlKXtjb25zdCBhPXtyYWRpdXM6cCpNYXRoLlNRUlQyLzIscG9pbnRTdHlsZTppLnBvaW50U3R5bGUscm90YXRpb246aS5yb3RhdGlvbixib3JkZXJXaWR0aDpufSxsPXIueFBsdXModCxnLzIpO0VlKHMsYSxsLGUrdSxvLnBvaW50U3R5bGVXaWR0aCYmZyl9ZWxzZXtjb25zdCBvPWUrTWF0aC5tYXgoKGQtcCkvMiwwKSxhPXIubGVmdEZvckx0cih0LGcpLGw9d2koaS5ib3JkZXJSYWRpdXMpO3MuYmVnaW5QYXRoKCksT2JqZWN0LnZhbHVlcyhsKS5zb21lKCh0PT4wIT09dCkpP0hlKHMse3g6YSx5Om8sdzpnLGg6cCxyYWRpdXM6bH0pOnMucmVjdChhLG8sZyxwKSxzLmZpbGwoKSwwIT09biYmcy5zdHJva2UoKX1zLnJlc3RvcmUoKX0oci54KFMpLFAseSksUz1ndCh3LFMrZyt1LGI\/UytrOnRoaXMucmlnaHQsdC5ydGwpLGZ1bmN0aW9uKHQsZSxpKXtOZShzLGkudGV4dCx0LGUrbS8yLGgse3N0cmlrZXRocm91Z2g6aS5oaWRkZW4sdGV4dEFsaWduOnIudGV4dEFsaWduKGkudGV4dEFsaWduKX0pfShyLngoUyksUCx5KSxiKWYueCs9aytjO2Vsc2UgaWYoInN0cmluZyIhPXR5cGVvZiB5LnRleHQpe2NvbnN0IHQ9aC5saW5lSGVpZ2h0O2YueSs9X2EoeSx0KStjfWVsc2UgZi55Kz1ffSkpLFRpKHRoaXMuY3R4LHQudGV4dERpcmVjdGlvbil9ZHJhd1RpdGxlKCl7Y29uc3QgdD10aGlzLm9wdGlvbnMsZT10LnRpdGxlLGk9U2koZS5mb250KSxzPWtpKGUucGFkZGluZyk7aWYoIWUuZGlzcGxheSlyZXR1cm47Y29uc3Qgbj1PaSh0LnJ0bCx0aGlzLmxlZnQsdGhpcy53aWR0aCksbz10aGlzLmN0eCxhPWUucG9zaXRpb24scj1pLnNpemUvMixsPXMudG9wK3I7bGV0IGgsYz10aGlzLmxlZnQsZD10aGlzLndpZHRoO2lmKHRoaXMuaXNIb3Jpem9udGFsKCkpZD1NYXRoLm1heCguLi50aGlzLmxpbmVXaWR0aHMpLGg9dGhpcy50b3ArbCxjPWZ0KHQuYWxpZ24sYyx0aGlzLnJpZ2h0LWQpO2Vsc2V7Y29uc3QgZT10aGlzLmNvbHVtblNpemVzLnJlZHVjZSgoKHQsZSk9Pk1hdGgubWF4KHQsZS5oZWlnaHQpKSwwKTtoPWwrZnQodC5hbGlnbix0aGlzLnRvcCx0aGlzLmJvdHRvbS1lLXQubGFiZWxzLnBhZGRpbmctdGhpcy5fY29tcHV0ZVRpdGxlSGVpZ2h0KCkpfWNvbnN0IHU9ZnQoYSxjLGMrZCk7by50ZXh0QWxpZ249bi50ZXh0QWxpZ24odXQoYSkpLG8udGV4dEJhc2VsaW5lPSJtaWRkbGUiLG8uc3Ryb2tlU3R5bGU9ZS5jb2xvcixvLmZpbGxTdHlsZT1lLmNvbG9yLG8uZm9udD1pLnN0cmluZyxOZShvLGUudGV4dCx1LGgsaSl9X2NvbXB1dGVUaXRsZUhlaWdodCgpe2NvbnN0IHQ9dGhpcy5vcHRpb25zLnRpdGxlLGU9U2kodC5mb250KSxpPWtpKHQucGFkZGluZyk7cmV0dXJuIHQuZGlzcGxheT9lLmxpbmVIZWlnaHQraS5oZWlnaHQ6MH1fZ2V0TGVnZW5kSXRlbUF0KHQsZSl7bGV0IGkscyxuO2lmKHR0KHQsdGhpcy5sZWZ0LHRoaXMucmlnaHQpJiZ0dChlLHRoaXMudG9wLHRoaXMuYm90dG9tKSlmb3Iobj10aGlzLmxlZ2VuZEhpdEJveGVzLGk9MDtpPG4ubGVuZ3RoOysraSlpZihzPW5baV0sdHQodCxzLmxlZnQscy5sZWZ0K3Mud2lkdGgpJiZ0dChlLHMudG9wLHMudG9wK3MuaGVpZ2h0KSlyZXR1cm4gdGhpcy5sZWdlbmRJdGVtc1tpXTtyZXR1cm4gbnVsbH1oYW5kbGVFdmVudCh0KXtjb25zdCBlPXRoaXMub3B0aW9ucztpZighZnVuY3Rpb24odCxlKXtpZigoIm1vdXNlbW92ZSI9PT10fHwibW91c2VvdXQiPT09dCkmJihlLm9uSG92ZXJ8fGUub25MZWF2ZSkpcmV0dXJuITA7aWYoZS5vbkNsaWNrJiYoImNsaWNrIj09PXR8fCJtb3VzZXVwIj09PXQpKXJldHVybiEwO3JldHVybiExfSh0LnR5cGUsZSkpcmV0dXJuO2NvbnN0IGk9dGhpcy5fZ2V0TGVnZW5kSXRlbUF0KHQueCx0LnkpO2lmKCJtb3VzZW1vdmUiPT09dC50eXBlfHwibW91c2VvdXQiPT09dC50eXBlKXtjb25zdCBvPXRoaXMuX2hvdmVyZWRJdGVtLGE9KG49aSxudWxsIT09KHM9bykmJm51bGwhPT1uJiZzLmRhdGFzZXRJbmRleD09PW4uZGF0YXNldEluZGV4JiZzLmluZGV4PT09bi5pbmRleCk7byYmIWEmJmQoZS5vbkxlYXZlLFt0LG8sdGhpc10sdGhpcyksdGhpcy5faG92ZXJlZEl0ZW09aSxpJiYhYSYmZChlLm9uSG92ZXIsW3QsaSx0aGlzXSx0aGlzKX1lbHNlIGkmJmQoZS5vbkNsaWNrLFt0LGksdGhpc10sdGhpcyk7dmFyIHMsbn19ZnVuY3Rpb24gX2EodCxlKXtyZXR1cm4gZSoodC50ZXh0P3QudGV4dC5sZW5ndGg6MCl9dmFyIHlhPXtpZDoibGVnZW5kIixfZWxlbWVudDp4YSxzdGFydCh0LGUsaSl7Y29uc3Qgcz10LmxlZ2VuZD1uZXcgeGEoe2N0eDp0LmN0eCxvcHRpb25zOmksY2hhcnQ6dH0pO2FzLmNvbmZpZ3VyZSh0LHMsaSksYXMuYWRkQm94KHQscyl9LHN0b3AodCl7YXMucmVtb3ZlQm94KHQsdC5sZWdlbmQpLGRlbGV0ZSB0LmxlZ2VuZH0sYmVmb3JlVXBkYXRlKHQsZSxpKXtjb25zdCBzPXQubGVnZW5kO2FzLmNvbmZpZ3VyZSh0LHMsaSkscy5vcHRpb25zPWl9LGFmdGVyVXBkYXRlKHQpe2NvbnN0IGU9dC5sZWdlbmQ7ZS5idWlsZExhYmVscygpLGUuYWRqdXN0SGl0Qm94ZXMoKX0sYWZ0ZXJFdmVudCh0LGUpe2UucmVwbGF5fHx0LmxlZ2VuZC5oYW5kbGVFdmVudChlLmV2ZW50KX0sZGVmYXVsdHM6e2Rpc3BsYXk6ITAscG9zaXRpb246InRvcCIsYWxpZ246ImNlbnRlciIsZnVsbFNpemU6ITAscmV2ZXJzZTohMSx3ZWlnaHQ6MWUzLG9uQ2xpY2sodCxlLGkpe2NvbnN0IHM9ZS5kYXRhc2V0SW5kZXgsbj1pLmNoYXJ0O24uaXNEYXRhc2V0VmlzaWJsZShzKT8obi5oaWRlKHMpLGUuaGlkZGVuPSEwKToobi5zaG93KHMpLGUuaGlkZGVuPSExKX0sb25Ib3ZlcjpudWxsLG9uTGVhdmU6bnVsbCxsYWJlbHM6e2NvbG9yOnQ9PnQuY2hhcnQub3B0aW9ucy5jb2xvcixib3hXaWR0aDo0MCxwYWRkaW5nOjEwLGdlbmVyYXRlTGFiZWxzKHQpe2NvbnN0IGU9dC5kYXRhLmRhdGFzZXRzLHtsYWJlbHM6e3VzZVBvaW50U3R5bGU6aSxwb2ludFN0eWxlOnMsdGV4dEFsaWduOm4sY29sb3I6byx1c2VCb3JkZXJSYWRpdXM6YSxib3JkZXJSYWRpdXM6cn19PXQubGVnZW5kLm9wdGlvbnM7cmV0dXJuIHQuX2dldFNvcnRlZERhdGFzZXRNZXRhcygpLm1hcCgodD0+e2NvbnN0IGw9dC5jb250cm9sbGVyLmdldFN0eWxlKGk\/MDp2b2lkIDApLGg9a2kobC5ib3JkZXJXaWR0aCk7cmV0dXJue3RleHQ6ZVt0LmluZGV4XS5sYWJlbCxmaWxsU3R5bGU6bC5iYWNrZ3JvdW5kQ29sb3IsZm9udENvbG9yOm8saGlkZGVuOiF0LnZpc2libGUsbGluZUNhcDpsLmJvcmRlckNhcFN0eWxlLGxpbmVEYXNoOmwuYm9yZGVyRGFzaCxsaW5lRGFzaE9mZnNldDpsLmJvcmRlckRhc2hPZmZzZXQsbGluZUpvaW46bC5ib3JkZXJKb2luU3R5bGUsbGluZVdpZHRoOihoLndpZHRoK2guaGVpZ2h0KS80LHN0cm9rZVN0eWxlOmwuYm9yZGVyQ29sb3IscG9pbnRTdHlsZTpzfHxsLnBvaW50U3R5bGUscm90YXRpb246bC5yb3RhdGlvbix0ZXh0QWxpZ246bnx8bC50ZXh0QWxpZ24sYm9yZGVyUmFkaXVzOmEmJihyfHxsLmJvcmRlclJhZGl1cyksZGF0YXNldEluZGV4OnQuaW5kZXh9fSksdGhpcyl9fSx0aXRsZTp7Y29sb3I6dD0+dC5jaGFydC5vcHRpb25zLmNvbG9yLGRpc3BsYXk6ITEscG9zaXRpb246ImNlbnRlciIsdGV4dDoiIn19LGRlc2NyaXB0b3JzOntfc2NyaXB0YWJsZTp0PT4hdC5zdGFydHNXaXRoKCJvbiIpLGxhYmVsczp7X3NjcmlwdGFibGU6dD0+IVsiZ2VuZXJhdGVMYWJlbHMiLCJmaWx0ZXIiLCJzb3J0Il0uaW5jbHVkZXModCl9fX07Y2xhc3MgdmEgZXh0ZW5kcyBIc3tjb25zdHJ1Y3Rvcih0KXtzdXBlcigpLHRoaXMuY2hhcnQ9dC5jaGFydCx0aGlzLm9wdGlvbnM9dC5vcHRpb25zLHRoaXMuY3R4PXQuY3R4LHRoaXMuX3BhZGRpbmc9dm9pZCAwLHRoaXMudG9wPXZvaWQgMCx0aGlzLmJvdHRvbT12b2lkIDAsdGhpcy5sZWZ0PXZvaWQgMCx0aGlzLnJpZ2h0PXZvaWQgMCx0aGlzLndpZHRoPXZvaWQgMCx0aGlzLmhlaWdodD12b2lkIDAsdGhpcy5wb3NpdGlvbj12b2lkIDAsdGhpcy53ZWlnaHQ9dm9pZCAwLHRoaXMuZnVsbFNpemU9dm9pZCAwfXVwZGF0ZSh0LGUpe2NvbnN0IGk9dGhpcy5vcHRpb25zO2lmKHRoaXMubGVmdD0wLHRoaXMudG9wPTAsIWkuZGlzcGxheSlyZXR1cm4gdm9pZCh0aGlzLndpZHRoPXRoaXMuaGVpZ2h0PXRoaXMucmlnaHQ9dGhpcy5ib3R0b209MCk7dGhpcy53aWR0aD10aGlzLnJpZ2h0PXQsdGhpcy5oZWlnaHQ9dGhpcy5ib3R0b209ZTtjb25zdCBzPW4oaS50ZXh0KT9pLnRleHQubGVuZ3RoOjE7dGhpcy5fcGFkZGluZz1raShpLnBhZGRpbmcpO2NvbnN0IG89cypTaShpLmZvbnQpLmxpbmVIZWlnaHQrdGhpcy5fcGFkZGluZy5oZWlnaHQ7dGhpcy5pc0hvcml6b250YWwoKT90aGlzLmhlaWdodD1vOnRoaXMud2lkdGg9b31pc0hvcml6b250YWwoKXtjb25zdCB0PXRoaXMub3B0aW9ucy5wb3NpdGlvbjtyZXR1cm4idG9wIj09PXR8fCJib3R0b20iPT09dH1fZHJhd0FyZ3ModCl7Y29uc3R7dG9wOmUsbGVmdDppLGJvdHRvbTpzLHJpZ2h0Om4sb3B0aW9uczpvfT10aGlzLGE9by5hbGlnbjtsZXQgcixsLGgsYz0wO3JldHVybiB0aGlzLmlzSG9yaXpvbnRhbCgpPyhsPWZ0KGEsaSxuKSxoPWUrdCxyPW4taSk6KCJsZWZ0Ij09PW8ucG9zaXRpb24\/KGw9aSt0LGg9ZnQoYSxzLGUpLGM9LS41KkMpOihsPW4tdCxoPWZ0KGEsZSxzKSxjPS41KkMpLHI9cy1lKSx7dGl0bGVYOmwsdGl0bGVZOmgsbWF4V2lkdGg6cixyb3RhdGlvbjpjfX1kcmF3KCl7Y29uc3QgdD10aGlzLmN0eCxlPXRoaXMub3B0aW9ucztpZighZS5kaXNwbGF5KXJldHVybjtjb25zdCBpPVNpKGUuZm9udCkscz1pLmxpbmVIZWlnaHQvMit0aGlzLl9wYWRkaW5nLnRvcCx7dGl0bGVYOm4sdGl0bGVZOm8sbWF4V2lkdGg6YSxyb3RhdGlvbjpyfT10aGlzLl9kcmF3QXJncyhzKTtOZSh0LGUudGV4dCwwLDAsaSx7Y29sb3I6ZS5jb2xvcixtYXhXaWR0aDphLHJvdGF0aW9uOnIsdGV4dEFsaWduOnV0KGUuYWxpZ24pLHRleHRCYXNlbGluZToibWlkZGxlIix0cmFuc2xhdGlvbjpbbixvXX0pfX12YXIgTWE9e2lkOiJ0aXRsZSIsX2VsZW1lbnQ6dmEsc3RhcnQodCxlLGkpeyFmdW5jdGlvbih0LGUpe2NvbnN0IGk9bmV3IHZhKHtjdHg6dC5jdHgsb3B0aW9uczplLGNoYXJ0OnR9KTthcy5jb25maWd1cmUodCxpLGUpLGFzLmFkZEJveCh0LGkpLHQudGl0bGVCbG9jaz1pfSh0LGkpfSxzdG9wKHQpe2NvbnN0IGU9dC50aXRsZUJsb2NrO2FzLnJlbW92ZUJveCh0LGUpLGRlbGV0ZSB0LnRpdGxlQmxvY2t9LGJlZm9yZVVwZGF0ZSh0LGUsaSl7Y29uc3Qgcz10LnRpdGxlQmxvY2s7YXMuY29uZmlndXJlKHQscyxpKSxzLm9wdGlvbnM9aX0sZGVmYXVsdHM6e2FsaWduOiJjZW50ZXIiLGRpc3BsYXk6ITEsZm9udDp7d2VpZ2h0OiJib2xkIn0sZnVsbFNpemU6ITAscGFkZGluZzoxMCxwb3NpdGlvbjoidG9wIix0ZXh0OiIiLHdlaWdodDoyZTN9LGRlZmF1bHRSb3V0ZXM6e2NvbG9yOiJjb2xvciJ9LGRlc2NyaXB0b3JzOntfc2NyaXB0YWJsZTohMCxfaW5kZXhhYmxlOiExfX07Y29uc3Qgd2E9bmV3IFdlYWtNYXA7dmFyIGthPXtpZDoic3VidGl0bGUiLHN0YXJ0KHQsZSxpKXtjb25zdCBzPW5ldyB2YSh7Y3R4OnQuY3R4LG9wdGlvbnM6aSxjaGFydDp0fSk7YXMuY29uZmlndXJlKHQscyxpKSxhcy5hZGRCb3godCxzKSx3YS5zZXQodCxzKX0sc3RvcCh0KXthcy5yZW1vdmVCb3godCx3YS5nZXQodCkpLHdhLmRlbGV0ZSh0KX0sYmVmb3JlVXBkYXRlKHQsZSxpKXtjb25zdCBzPXdhLmdldCh0KTthcy5jb25maWd1cmUodCxzLGkpLHMub3B0aW9ucz1pfSxkZWZhdWx0czp7YWxpZ246ImNlbnRlciIsZGlzcGxheTohMSxmb250Ont3ZWlnaHQ6Im5vcm1hbCJ9LGZ1bGxTaXplOiEwLHBhZGRpbmc6MCxwb3NpdGlvbjoidG9wIix0ZXh0OiIiLHdlaWdodDoxNTAwfSxkZWZhdWx0Um91dGVzOntjb2xvcjoiY29sb3IifSxkZXNjcmlwdG9yczp7X3NjcmlwdGFibGU6ITAsX2luZGV4YWJsZTohMX19O2NvbnN0IFNhPXthdmVyYWdlKHQpe2lmKCF0Lmxlbmd0aClyZXR1cm4hMTtsZXQgZSxpLHM9MCxuPTAsbz0wO2ZvcihlPTAsaT10Lmxlbmd0aDtlPGk7KytlKXtjb25zdCBpPXRbZV0uZWxlbWVudDtpZihpJiZpLmhhc1ZhbHVlKCkpe2NvbnN0IHQ9aS50b29sdGlwUG9zaXRpb24oKTtzKz10Lngsbis9dC55LCsrb319cmV0dXJue3g6cy9vLHk6bi9vfX0sbmVhcmVzdCh0LGUpe2lmKCF0Lmxlbmd0aClyZXR1cm4hMTtsZXQgaSxzLG4sbz1lLngsYT1lLnkscj1OdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7Zm9yKGk9MCxzPXQubGVuZ3RoO2k8czsrK2kpe2NvbnN0IHM9dFtpXS5lbGVtZW50O2lmKHMmJnMuaGFzVmFsdWUoKSl7Y29uc3QgdD1xKGUscy5nZXRDZW50ZXJQb2ludCgpKTt0PHImJihyPXQsbj1zKX19aWYobil7Y29uc3QgdD1uLnRvb2x0aXBQb3NpdGlvbigpO289dC54LGE9dC55fXJldHVybnt4Om8seTphfX19O2Z1bmN0aW9uIFBhKHQsZSl7cmV0dXJuIGUmJihuKGUpP0FycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHQsZSk6dC5wdXNoKGUpKSx0fWZ1bmN0aW9uIERhKHQpe3JldHVybigic3RyaW5nIj09dHlwZW9mIHR8fHQgaW5zdGFuY2VvZiBTdHJpbmcpJiZ0LmluZGV4T2YoIlxuIik+LTE\/dC5zcGxpdCgiXG4iKTp0fWZ1bmN0aW9uIENhKHQsZSl7Y29uc3R7ZWxlbWVudDppLGRhdGFzZXRJbmRleDpzLGluZGV4Om59PWUsbz10LmdldERhdGFzZXRNZXRhKHMpLmNvbnRyb2xsZXIse2xhYmVsOmEsdmFsdWU6cn09by5nZXRMYWJlbEFuZFZhbHVlKG4pO3JldHVybntjaGFydDp0LGxhYmVsOmEscGFyc2VkOm8uZ2V0UGFyc2VkKG4pLHJhdzp0LmRhdGEuZGF0YXNldHNbc10uZGF0YVtuXSxmb3JtYXR0ZWRWYWx1ZTpyLGRhdGFzZXQ6by5nZXREYXRhc2V0KCksZGF0YUluZGV4Om4sZGF0YXNldEluZGV4OnMsZWxlbWVudDppfX1mdW5jdGlvbiBPYSh0LGUpe2NvbnN0IGk9dC5jaGFydC5jdHgse2JvZHk6cyxmb290ZXI6bix0aXRsZTpvfT10LHtib3hXaWR0aDphLGJveEhlaWdodDpyfT1lLGw9U2koZS5ib2R5Rm9udCksaD1TaShlLnRpdGxlRm9udCksYz1TaShlLmZvb3RlckZvbnQpLGQ9by5sZW5ndGgsZj1uLmxlbmd0aCxnPXMubGVuZ3RoLHA9a2koZS5wYWRkaW5nKTtsZXQgbT1wLmhlaWdodCxiPTAseD1zLnJlZHVjZSgoKHQsZSk9PnQrZS5iZWZvcmUubGVuZ3RoK2UubGluZXMubGVuZ3RoK2UuYWZ0ZXIubGVuZ3RoKSwwKTtpZih4Kz10LmJlZm9yZUJvZHkubGVuZ3RoK3QuYWZ0ZXJCb2R5Lmxlbmd0aCxkJiYobSs9ZCpoLmxpbmVIZWlnaHQrKGQtMSkqZS50aXRsZVNwYWNpbmcrZS50aXRsZU1hcmdpbkJvdHRvbSkseCl7bSs9ZyooZS5kaXNwbGF5Q29sb3JzP01hdGgubWF4KHIsbC5saW5lSGVpZ2h0KTpsLmxpbmVIZWlnaHQpKyh4LWcpKmwubGluZUhlaWdodCsoeC0xKSplLmJvZHlTcGFjaW5nfWYmJihtKz1lLmZvb3Rlck1hcmdpblRvcCtmKmMubGluZUhlaWdodCsoZi0xKSplLmZvb3RlclNwYWNpbmcpO2xldCBfPTA7Y29uc3QgeT1mdW5jdGlvbih0KXtiPU1hdGgubWF4KGIsaS5tZWFzdXJlVGV4dCh0KS53aWR0aCtfKX07cmV0dXJuIGkuc2F2ZSgpLGkuZm9udD1oLnN0cmluZyx1KHQudGl0bGUseSksaS5mb250PWwuc3RyaW5nLHUodC5iZWZvcmVCb2R5LmNvbmNhdCh0LmFmdGVyQm9keSkseSksXz1lLmRpc3BsYXlDb2xvcnM\/YSsyK2UuYm94UGFkZGluZzowLHUocywodD0+e3UodC5iZWZvcmUseSksdSh0LmxpbmVzLHkpLHUodC5hZnRlcix5KX0pKSxfPTAsaS5mb250PWMuc3RyaW5nLHUodC5mb290ZXIseSksaS5yZXN0b3JlKCksYis9cC53aWR0aCx7d2lkdGg6YixoZWlnaHQ6bX19ZnVuY3Rpb24gQWEodCxlLGkscyl7Y29uc3R7eDpuLHdpZHRoOm99PWkse3dpZHRoOmEsY2hhcnRBcmVhOntsZWZ0OnIscmlnaHQ6bH19PXQ7bGV0IGg9ImNlbnRlciI7cmV0dXJuImNlbnRlciI9PT1zP2g9bjw9KHIrbCkvMj8ibGVmdCI6InJpZ2h0IjpuPD1vLzI\/aD0ibGVmdCI6bj49YS1vLzImJihoPSJyaWdodCIpLGZ1bmN0aW9uKHQsZSxpLHMpe2NvbnN0e3g6bix3aWR0aDpvfT1zLGE9aS5jYXJldFNpemUraS5jYXJldFBhZGRpbmc7cmV0dXJuImxlZnQiPT09dCYmbitvK2E+ZS53aWR0aHx8InJpZ2h0Ij09PXQmJm4tby1hPDB8fHZvaWQgMH0oaCx0LGUsaSkmJihoPSJjZW50ZXIiKSxofWZ1bmN0aW9uIFRhKHQsZSxpKXtjb25zdCBzPWkueUFsaWdufHxlLnlBbGlnbnx8ZnVuY3Rpb24odCxlKXtjb25zdHt5OmksaGVpZ2h0OnN9PWU7cmV0dXJuIGk8cy8yPyJ0b3AiOmk+dC5oZWlnaHQtcy8yPyJib3R0b20iOiJjZW50ZXIifSh0LGkpO3JldHVybnt4QWxpZ246aS54QWxpZ258fGUueEFsaWdufHxBYSh0LGUsaSxzKSx5QWxpZ246c319ZnVuY3Rpb24gTGEodCxlLGkscyl7Y29uc3R7Y2FyZXRTaXplOm4sY2FyZXRQYWRkaW5nOm8sY29ybmVyUmFkaXVzOmF9PXQse3hBbGlnbjpyLHlBbGlnbjpsfT1pLGg9bitvLHt0b3BMZWZ0OmMsdG9wUmlnaHQ6ZCxib3R0b21MZWZ0OnUsYm90dG9tUmlnaHQ6Zn09d2koYSk7bGV0IGc9ZnVuY3Rpb24odCxlKXtsZXR7eDppLHdpZHRoOnN9PXQ7cmV0dXJuInJpZ2h0Ij09PWU\/aS09czoiY2VudGVyIj09PWUmJihpLT1zLzIpLGl9KGUscik7Y29uc3QgcD1mdW5jdGlvbih0LGUsaSl7bGV0e3k6cyxoZWlnaHQ6bn09dDtyZXR1cm4idG9wIj09PWU\/cys9aTpzLT0iYm90dG9tIj09PWU\/bitpOm4vMixzfShlLGwsaCk7cmV0dXJuImNlbnRlciI9PT1sPyJsZWZ0Ij09PXI\/Zys9aDoicmlnaHQiPT09ciYmKGctPWgpOiJsZWZ0Ij09PXI\/Zy09TWF0aC5tYXgoYyx1KStuOiJyaWdodCI9PT1yJiYoZys9TWF0aC5tYXgoZCxmKStuKSx7eDpKKGcsMCxzLndpZHRoLWUud2lkdGgpLHk6SihwLDAscy5oZWlnaHQtZS5oZWlnaHQpfX1mdW5jdGlvbiBFYSh0LGUsaSl7Y29uc3Qgcz1raShpLnBhZGRpbmcpO3JldHVybiJjZW50ZXIiPT09ZT90LngrdC53aWR0aC8yOiJyaWdodCI9PT1lP3QueCt0LndpZHRoLXMucmlnaHQ6dC54K3MubGVmdH1mdW5jdGlvbiBSYSh0KXtyZXR1cm4gUGEoW10sRGEodCkpfWZ1bmN0aW9uIElhKHQsZSl7Y29uc3QgaT1lJiZlLmRhdGFzZXQmJmUuZGF0YXNldC50b29sdGlwJiZlLmRhdGFzZXQudG9vbHRpcC5jYWxsYmFja3M7cmV0dXJuIGk\/dC5vdmVycmlkZShpKTp0fWNvbnN0IHphPXtiZWZvcmVUaXRsZTplLHRpdGxlKHQpe2lmKHQubGVuZ3RoPjApe2NvbnN0IGU9dFswXSxpPWUuY2hhcnQuZGF0YS5sYWJlbHMscz1pP2kubGVuZ3RoOjA7aWYodGhpcyYmdGhpcy5vcHRpb25zJiYiZGF0YXNldCI9PT10aGlzLm9wdGlvbnMubW9kZSlyZXR1cm4gZS5kYXRhc2V0LmxhYmVsfHwiIjtpZihlLmxhYmVsKXJldHVybiBlLmxhYmVsO2lmKHM+MCYmZS5kYXRhSW5kZXg8cylyZXR1cm4gaVtlLmRhdGFJbmRleF19cmV0dXJuIiJ9LGFmdGVyVGl0bGU6ZSxiZWZvcmVCb2R5OmUsYmVmb3JlTGFiZWw6ZSxsYWJlbCh0KXtpZih0aGlzJiZ0aGlzLm9wdGlvbnMmJiJkYXRhc2V0Ij09PXRoaXMub3B0aW9ucy5tb2RlKXJldHVybiB0LmxhYmVsKyI6ICIrdC5mb3JtYXR0ZWRWYWx1ZXx8dC5mb3JtYXR0ZWRWYWx1ZTtsZXQgZT10LmRhdGFzZXQubGFiZWx8fCIiO2UmJihlKz0iOiAiKTtjb25zdCBpPXQuZm9ybWF0dGVkVmFsdWU7cmV0dXJuIHMoaSl8fChlKz1pKSxlfSxsYWJlbENvbG9yKHQpe2NvbnN0IGU9dC5jaGFydC5nZXREYXRhc2V0TWV0YSh0LmRhdGFzZXRJbmRleCkuY29udHJvbGxlci5nZXRTdHlsZSh0LmRhdGFJbmRleCk7cmV0dXJue2JvcmRlckNvbG9yOmUuYm9yZGVyQ29sb3IsYmFja2dyb3VuZENvbG9yOmUuYmFja2dyb3VuZENvbG9yLGJvcmRlcldpZHRoOmUuYm9yZGVyV2lkdGgsYm9yZGVyRGFzaDplLmJvcmRlckRhc2gsYm9yZGVyRGFzaE9mZnNldDplLmJvcmRlckRhc2hPZmZzZXQsYm9yZGVyUmFkaXVzOjB9fSxsYWJlbFRleHRDb2xvcigpe3JldHVybiB0aGlzLm9wdGlvbnMuYm9keUNvbG9yfSxsYWJlbFBvaW50U3R5bGUodCl7Y29uc3QgZT10LmNoYXJ0LmdldERhdGFzZXRNZXRhKHQuZGF0YXNldEluZGV4KS5jb250cm9sbGVyLmdldFN0eWxlKHQuZGF0YUluZGV4KTtyZXR1cm57cG9pbnRTdHlsZTplLnBvaW50U3R5bGUscm90YXRpb246ZS5yb3RhdGlvbn19LGFmdGVyTGFiZWw6ZSxhZnRlckJvZHk6ZSxiZWZvcmVGb290ZXI6ZSxmb290ZXI6ZSxhZnRlckZvb3RlcjplfTtmdW5jdGlvbiBGYSh0LGUsaSxzKXtjb25zdCBuPXRbZV0uY2FsbChpLHMpO3JldHVybiB2b2lkIDA9PT1uP3phW2VdLmNhbGwoaSxzKTpufWNsYXNzIFZhIGV4dGVuZHMgSHN7c3RhdGljIHBvc2l0aW9uZXJzPVNhO2NvbnN0cnVjdG9yKHQpe3N1cGVyKCksdGhpcy5vcGFjaXR5PTAsdGhpcy5fYWN0aXZlPVtdLHRoaXMuX2V2ZW50UG9zaXRpb249dm9pZCAwLHRoaXMuX3NpemU9dm9pZCAwLHRoaXMuX2NhY2hlZEFuaW1hdGlvbnM9dm9pZCAwLHRoaXMuX3Rvb2x0aXBJdGVtcz1bXSx0aGlzLiRhbmltYXRpb25zPXZvaWQgMCx0aGlzLiRjb250ZXh0PXZvaWQgMCx0aGlzLmNoYXJ0PXQuY2hhcnQsdGhpcy5vcHRpb25zPXQub3B0aW9ucyx0aGlzLmRhdGFQb2ludHM9dm9pZCAwLHRoaXMudGl0bGU9dm9pZCAwLHRoaXMuYmVmb3JlQm9keT12b2lkIDAsdGhpcy5ib2R5PXZvaWQgMCx0aGlzLmFmdGVyQm9keT12b2lkIDAsdGhpcy5mb290ZXI9dm9pZCAwLHRoaXMueEFsaWduPXZvaWQgMCx0aGlzLnlBbGlnbj12b2lkIDAsdGhpcy54PXZvaWQgMCx0aGlzLnk9dm9pZCAwLHRoaXMuaGVpZ2h0PXZvaWQgMCx0aGlzLndpZHRoPXZvaWQgMCx0aGlzLmNhcmV0WD12b2lkIDAsdGhpcy5jYXJldFk9dm9pZCAwLHRoaXMubGFiZWxDb2xvcnM9dm9pZCAwLHRoaXMubGFiZWxQb2ludFN0eWxlcz12b2lkIDAsdGhpcy5sYWJlbFRleHRDb2xvcnM9dm9pZCAwfWluaXRpYWxpemUodCl7dGhpcy5vcHRpb25zPXQsdGhpcy5fY2FjaGVkQW5pbWF0aW9ucz12b2lkIDAsdGhpcy4kY29udGV4dD12b2lkIDB9X3Jlc29sdmVBbmltYXRpb25zKCl7Y29uc3QgdD10aGlzLl9jYWNoZWRBbmltYXRpb25zO2lmKHQpcmV0dXJuIHQ7Y29uc3QgZT10aGlzLmNoYXJ0LGk9dGhpcy5vcHRpb25zLnNldENvbnRleHQodGhpcy5nZXRDb250ZXh0KCkpLHM9aS5lbmFibGVkJiZlLm9wdGlvbnMuYW5pbWF0aW9uJiZpLmFuaW1hdGlvbnMsbj1uZXcgT3ModGhpcy5jaGFydCxzKTtyZXR1cm4gcy5fY2FjaGVhYmxlJiYodGhpcy5fY2FjaGVkQW5pbWF0aW9ucz1PYmplY3QuZnJlZXplKG4pKSxufWdldENvbnRleHQoKXtyZXR1cm4gdGhpcy4kY29udGV4dHx8KHRoaXMuJGNvbnRleHQ9KHQ9dGhpcy5jaGFydC5nZXRDb250ZXh0KCksZT10aGlzLGk9dGhpcy5fdG9vbHRpcEl0ZW1zLENpKHQse3Rvb2x0aXA6ZSx0b29sdGlwSXRlbXM6aSx0eXBlOiJ0b29sdGlwIn0pKSk7dmFyIHQsZSxpfWdldFRpdGxlKHQsZSl7Y29uc3R7Y2FsbGJhY2tzOml9PWUscz1GYShpLCJiZWZvcmVUaXRsZSIsdGhpcyx0KSxuPUZhKGksInRpdGxlIix0aGlzLHQpLG89RmEoaSwiYWZ0ZXJUaXRsZSIsdGhpcyx0KTtsZXQgYT1bXTtyZXR1cm4gYT1QYShhLERhKHMpKSxhPVBhKGEsRGEobikpLGE9UGEoYSxEYShvKSksYX1nZXRCZWZvcmVCb2R5KHQsZSl7cmV0dXJuIFJhKEZhKGUuY2FsbGJhY2tzLCJiZWZvcmVCb2R5Iix0aGlzLHQpKX1nZXRCb2R5KHQsZSl7Y29uc3R7Y2FsbGJhY2tzOml9PWUscz1bXTtyZXR1cm4gdSh0LCh0PT57Y29uc3QgZT17YmVmb3JlOltdLGxpbmVzOltdLGFmdGVyOltdfSxuPUlhKGksdCk7UGEoZS5iZWZvcmUsRGEoRmEobiwiYmVmb3JlTGFiZWwiLHRoaXMsdCkpKSxQYShlLmxpbmVzLEZhKG4sImxhYmVsIix0aGlzLHQpKSxQYShlLmFmdGVyLERhKEZhKG4sImFmdGVyTGFiZWwiLHRoaXMsdCkpKSxzLnB1c2goZSl9KSksc31nZXRBZnRlckJvZHkodCxlKXtyZXR1cm4gUmEoRmEoZS5jYWxsYmFja3MsImFmdGVyQm9keSIsdGhpcyx0KSl9Z2V0Rm9vdGVyKHQsZSl7Y29uc3R7Y2FsbGJhY2tzOml9PWUscz1GYShpLCJiZWZvcmVGb290ZXIiLHRoaXMsdCksbj1GYShpLCJmb290ZXIiLHRoaXMsdCksbz1GYShpLCJhZnRlckZvb3RlciIsdGhpcyx0KTtsZXQgYT1bXTtyZXR1cm4gYT1QYShhLERhKHMpKSxhPVBhKGEsRGEobikpLGE9UGEoYSxEYShvKSksYX1fY3JlYXRlSXRlbXModCl7Y29uc3QgZT10aGlzLl9hY3RpdmUsaT10aGlzLmNoYXJ0LmRhdGEscz1bXSxuPVtdLG89W107bGV0IGEscixsPVtdO2ZvcihhPTAscj1lLmxlbmd0aDthPHI7KythKWwucHVzaChDYSh0aGlzLmNoYXJ0LGVbYV0pKTtyZXR1cm4gdC5maWx0ZXImJihsPWwuZmlsdGVyKCgoZSxzLG4pPT50LmZpbHRlcihlLHMsbixpKSkpKSx0Lml0ZW1Tb3J0JiYobD1sLnNvcnQoKChlLHMpPT50Lml0ZW1Tb3J0KGUscyxpKSkpKSx1KGwsKGU9Pntjb25zdCBpPUlhKHQuY2FsbGJhY2tzLGUpO3MucHVzaChGYShpLCJsYWJlbENvbG9yIix0aGlzLGUpKSxuLnB1c2goRmEoaSwibGFiZWxQb2ludFN0eWxlIix0aGlzLGUpKSxvLnB1c2goRmEoaSwibGFiZWxUZXh0Q29sb3IiLHRoaXMsZSkpfSkpLHRoaXMubGFiZWxDb2xvcnM9cyx0aGlzLmxhYmVsUG9pbnRTdHlsZXM9bix0aGlzLmxhYmVsVGV4dENvbG9ycz1vLHRoaXMuZGF0YVBvaW50cz1sLGx9dXBkYXRlKHQsZSl7Y29uc3QgaT10aGlzLm9wdGlvbnMuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoKSkscz10aGlzLl9hY3RpdmU7bGV0IG4sbz1bXTtpZihzLmxlbmd0aCl7Y29uc3QgdD1TYVtpLnBvc2l0aW9uXS5jYWxsKHRoaXMscyx0aGlzLl9ldmVudFBvc2l0aW9uKTtvPXRoaXMuX2NyZWF0ZUl0ZW1zKGkpLHRoaXMudGl0bGU9dGhpcy5nZXRUaXRsZShvLGkpLHRoaXMuYmVmb3JlQm9keT10aGlzLmdldEJlZm9yZUJvZHkobyxpKSx0aGlzLmJvZHk9dGhpcy5nZXRCb2R5KG8saSksdGhpcy5hZnRlckJvZHk9dGhpcy5nZXRBZnRlckJvZHkobyxpKSx0aGlzLmZvb3Rlcj10aGlzLmdldEZvb3RlcihvLGkpO2NvbnN0IGU9dGhpcy5fc2l6ZT1PYSh0aGlzLGkpLGE9T2JqZWN0LmFzc2lnbih7fSx0LGUpLHI9VGEodGhpcy5jaGFydCxpLGEpLGw9TGEoaSxhLHIsdGhpcy5jaGFydCk7dGhpcy54QWxpZ249ci54QWxpZ24sdGhpcy55QWxpZ249ci55QWxpZ24sbj17b3BhY2l0eToxLHg6bC54LHk6bC55LHdpZHRoOmUud2lkdGgsaGVpZ2h0OmUuaGVpZ2h0LGNhcmV0WDp0LngsY2FyZXRZOnQueX19ZWxzZSAwIT09dGhpcy5vcGFjaXR5JiYobj17b3BhY2l0eTowfSk7dGhpcy5fdG9vbHRpcEl0ZW1zPW8sdGhpcy4kY29udGV4dD12b2lkIDAsbiYmdGhpcy5fcmVzb2x2ZUFuaW1hdGlvbnMoKS51cGRhdGUodGhpcyxuKSx0JiZpLmV4dGVybmFsJiZpLmV4dGVybmFsLmNhbGwodGhpcyx7Y2hhcnQ6dGhpcy5jaGFydCx0b29sdGlwOnRoaXMscmVwbGF5OmV9KX1kcmF3Q2FyZXQodCxlLGkscyl7Y29uc3Qgbj10aGlzLmdldENhcmV0UG9zaXRpb24odCxpLHMpO2UubGluZVRvKG4ueDEsbi55MSksZS5saW5lVG8obi54MixuLnkyKSxlLmxpbmVUbyhuLngzLG4ueTMpfWdldENhcmV0UG9zaXRpb24odCxlLGkpe2NvbnN0e3hBbGlnbjpzLHlBbGlnbjpufT10aGlzLHtjYXJldFNpemU6byxjb3JuZXJSYWRpdXM6YX09aSx7dG9wTGVmdDpyLHRvcFJpZ2h0OmwsYm90dG9tTGVmdDpoLGJvdHRvbVJpZ2h0OmN9PXdpKGEpLHt4OmQseTp1fT10LHt3aWR0aDpmLGhlaWdodDpnfT1lO2xldCBwLG0sYix4LF8seTtyZXR1cm4iY2VudGVyIj09PW4\/KF89dStnLzIsImxlZnQiPT09cz8ocD1kLG09cC1vLHg9XytvLHk9Xy1vKToocD1kK2YsbT1wK28seD1fLW8seT1fK28pLGI9cCk6KG09ImxlZnQiPT09cz9kK01hdGgubWF4KHIsaCkrbzoicmlnaHQiPT09cz9kK2YtTWF0aC5tYXgobCxjKS1vOnRoaXMuY2FyZXRYLCJ0b3AiPT09bj8oeD11LF89eC1vLHA9bS1vLGI9bStvKTooeD11K2csXz14K28scD1tK28sYj1tLW8pLHk9eCkse3gxOnAseDI6bSx4MzpiLHkxOngseTI6Xyx5Mzp5fX1kcmF3VGl0bGUodCxlLGkpe2NvbnN0IHM9dGhpcy50aXRsZSxuPXMubGVuZ3RoO2xldCBvLGEscjtpZihuKXtjb25zdCBsPU9pKGkucnRsLHRoaXMueCx0aGlzLndpZHRoKTtmb3IodC54PUVhKHRoaXMsaS50aXRsZUFsaWduLGkpLGUudGV4dEFsaWduPWwudGV4dEFsaWduKGkudGl0bGVBbGlnbiksZS50ZXh0QmFzZWxpbmU9Im1pZGRsZSIsbz1TaShpLnRpdGxlRm9udCksYT1pLnRpdGxlU3BhY2luZyxlLmZpbGxTdHlsZT1pLnRpdGxlQ29sb3IsZS5mb250PW8uc3RyaW5nLHI9MDtyPG47KytyKWUuZmlsbFRleHQoc1tyXSxsLngodC54KSx0Lnkrby5saW5lSGVpZ2h0LzIpLHQueSs9by5saW5lSGVpZ2h0K2EscisxPT09biYmKHQueSs9aS50aXRsZU1hcmdpbkJvdHRvbS1hKX19X2RyYXdDb2xvckJveCh0LGUsaSxzLG4pe2NvbnN0IGE9dGhpcy5sYWJlbENvbG9yc1tpXSxyPXRoaXMubGFiZWxQb2ludFN0eWxlc1tpXSx7Ym94SGVpZ2h0OmwsYm94V2lkdGg6aH09bixjPVNpKG4uYm9keUZvbnQpLGQ9RWEodGhpcywibGVmdCIsbiksdT1zLngoZCksZj1sPGMubGluZUhlaWdodD8oYy5saW5lSGVpZ2h0LWwpLzI6MCxnPWUueStmO2lmKG4udXNlUG9pbnRTdHlsZSl7Y29uc3QgZT17cmFkaXVzOk1hdGgubWluKGgsbCkvMixwb2ludFN0eWxlOnIucG9pbnRTdHlsZSxyb3RhdGlvbjpyLnJvdGF0aW9uLGJvcmRlcldpZHRoOjF9LGk9cy5sZWZ0Rm9yTHRyKHUsaCkraC8yLG89ZytsLzI7dC5zdHJva2VTdHlsZT1uLm11bHRpS2V5QmFja2dyb3VuZCx0LmZpbGxTdHlsZT1uLm11bHRpS2V5QmFja2dyb3VuZCxMZSh0LGUsaSxvKSx0LnN0cm9rZVN0eWxlPWEuYm9yZGVyQ29sb3IsdC5maWxsU3R5bGU9YS5iYWNrZ3JvdW5kQ29sb3IsTGUodCxlLGksbyl9ZWxzZXt0LmxpbmVXaWR0aD1vKGEuYm9yZGVyV2lkdGgpP01hdGgubWF4KC4uLk9iamVjdC52YWx1ZXMoYS5ib3JkZXJXaWR0aCkpOmEuYm9yZGVyV2lkdGh8fDEsdC5zdHJva2VTdHlsZT1hLmJvcmRlckNvbG9yLHQuc2V0TGluZURhc2goYS5ib3JkZXJEYXNofHxbXSksdC5saW5lRGFzaE9mZnNldD1hLmJvcmRlckRhc2hPZmZzZXR8fDA7Y29uc3QgZT1zLmxlZnRGb3JMdHIodSxoKSxpPXMubGVmdEZvckx0cihzLnhQbHVzKHUsMSksaC0yKSxyPXdpKGEuYm9yZGVyUmFkaXVzKTtPYmplY3QudmFsdWVzKHIpLnNvbWUoKHQ9PjAhPT10KSk\/KHQuYmVnaW5QYXRoKCksdC5maWxsU3R5bGU9bi5tdWx0aUtleUJhY2tncm91bmQsSGUodCx7eDplLHk6Zyx3OmgsaDpsLHJhZGl1czpyfSksdC5maWxsKCksdC5zdHJva2UoKSx0LmZpbGxTdHlsZT1hLmJhY2tncm91bmRDb2xvcix0LmJlZ2luUGF0aCgpLEhlKHQse3g6aSx5OmcrMSx3OmgtMixoOmwtMixyYWRpdXM6cn0pLHQuZmlsbCgpKToodC5maWxsU3R5bGU9bi5tdWx0aUtleUJhY2tncm91bmQsdC5maWxsUmVjdChlLGcsaCxsKSx0LnN0cm9rZVJlY3QoZSxnLGgsbCksdC5maWxsU3R5bGU9YS5iYWNrZ3JvdW5kQ29sb3IsdC5maWxsUmVjdChpLGcrMSxoLTIsbC0yKSl9dC5maWxsU3R5bGU9dGhpcy5sYWJlbFRleHRDb2xvcnNbaV19ZHJhd0JvZHkodCxlLGkpe2NvbnN0e2JvZHk6c309dGhpcyx7Ym9keVNwYWNpbmc6bixib2R5QWxpZ246byxkaXNwbGF5Q29sb3JzOmEsYm94SGVpZ2h0OnIsYm94V2lkdGg6bCxib3hQYWRkaW5nOmh9PWksYz1TaShpLmJvZHlGb250KTtsZXQgZD1jLmxpbmVIZWlnaHQsZj0wO2NvbnN0IGc9T2koaS5ydGwsdGhpcy54LHRoaXMud2lkdGgpLHA9ZnVuY3Rpb24oaSl7ZS5maWxsVGV4dChpLGcueCh0LngrZiksdC55K2QvMiksdC55Kz1kK259LG09Zy50ZXh0QWxpZ24obyk7bGV0IGIseCxfLHksdixNLHc7Zm9yKGUudGV4dEFsaWduPW8sZS50ZXh0QmFzZWxpbmU9Im1pZGRsZSIsZS5mb250PWMuc3RyaW5nLHQueD1FYSh0aGlzLG0saSksZS5maWxsU3R5bGU9aS5ib2R5Q29sb3IsdSh0aGlzLmJlZm9yZUJvZHkscCksZj1hJiYicmlnaHQiIT09bT8iY2VudGVyIj09PW8\/bC8yK2g6bCsyK2g6MCx5PTAsTT1zLmxlbmd0aDt5PE07Kyt5KXtmb3IoYj1zW3ldLHg9dGhpcy5sYWJlbFRleHRDb2xvcnNbeV0sZS5maWxsU3R5bGU9eCx1KGIuYmVmb3JlLHApLF89Yi5saW5lcyxhJiZfLmxlbmd0aCYmKHRoaXMuX2RyYXdDb2xvckJveChlLHQseSxnLGkpLGQ9TWF0aC5tYXgoYy5saW5lSGVpZ2h0LHIpKSx2PTAsdz1fLmxlbmd0aDt2PHc7Kyt2KXAoX1t2XSksZD1jLmxpbmVIZWlnaHQ7dShiLmFmdGVyLHApfWY9MCxkPWMubGluZUhlaWdodCx1KHRoaXMuYWZ0ZXJCb2R5LHApLHQueS09bn1kcmF3Rm9vdGVyKHQsZSxpKXtjb25zdCBzPXRoaXMuZm9vdGVyLG49cy5sZW5ndGg7bGV0IG8sYTtpZihuKXtjb25zdCByPU9pKGkucnRsLHRoaXMueCx0aGlzLndpZHRoKTtmb3IodC54PUVhKHRoaXMsaS5mb290ZXJBbGlnbixpKSx0LnkrPWkuZm9vdGVyTWFyZ2luVG9wLGUudGV4dEFsaWduPXIudGV4dEFsaWduKGkuZm9vdGVyQWxpZ24pLGUudGV4dEJhc2VsaW5lPSJtaWRkbGUiLG89U2koaS5mb290ZXJGb250KSxlLmZpbGxTdHlsZT1pLmZvb3RlckNvbG9yLGUuZm9udD1vLnN0cmluZyxhPTA7YTxuOysrYSllLmZpbGxUZXh0KHNbYV0sci54KHQueCksdC55K28ubGluZUhlaWdodC8yKSx0LnkrPW8ubGluZUhlaWdodCtpLmZvb3RlclNwYWNpbmd9fWRyYXdCYWNrZ3JvdW5kKHQsZSxpLHMpe2NvbnN0e3hBbGlnbjpuLHlBbGlnbjpvfT10aGlzLHt4OmEseTpyfT10LHt3aWR0aDpsLGhlaWdodDpofT1pLHt0b3BMZWZ0OmMsdG9wUmlnaHQ6ZCxib3R0b21MZWZ0OnUsYm90dG9tUmlnaHQ6Zn09d2kocy5jb3JuZXJSYWRpdXMpO2UuZmlsbFN0eWxlPXMuYmFja2dyb3VuZENvbG9yLGUuc3Ryb2tlU3R5bGU9cy5ib3JkZXJDb2xvcixlLmxpbmVXaWR0aD1zLmJvcmRlcldpZHRoLGUuYmVnaW5QYXRoKCksZS5tb3ZlVG8oYStjLHIpLCJ0b3AiPT09byYmdGhpcy5kcmF3Q2FyZXQodCxlLGkscyksZS5saW5lVG8oYStsLWQsciksZS5xdWFkcmF0aWNDdXJ2ZVRvKGErbCxyLGErbCxyK2QpLCJjZW50ZXIiPT09byYmInJpZ2h0Ij09PW4mJnRoaXMuZHJhd0NhcmV0KHQsZSxpLHMpLGUubGluZVRvKGErbCxyK2gtZiksZS5xdWFkcmF0aWNDdXJ2ZVRvKGErbCxyK2gsYStsLWYscitoKSwiYm90dG9tIj09PW8mJnRoaXMuZHJhd0NhcmV0KHQsZSxpLHMpLGUubGluZVRvKGErdSxyK2gpLGUucXVhZHJhdGljQ3VydmVUbyhhLHIraCxhLHIraC11KSwiY2VudGVyIj09PW8mJiJsZWZ0Ij09PW4mJnRoaXMuZHJhd0NhcmV0KHQsZSxpLHMpLGUubGluZVRvKGEscitjKSxlLnF1YWRyYXRpY0N1cnZlVG8oYSxyLGErYyxyKSxlLmNsb3NlUGF0aCgpLGUuZmlsbCgpLHMuYm9yZGVyV2lkdGg+MCYmZS5zdHJva2UoKX1fdXBkYXRlQW5pbWF0aW9uVGFyZ2V0KHQpe2NvbnN0IGU9dGhpcy5jaGFydCxpPXRoaXMuJGFuaW1hdGlvbnMscz1pJiZpLngsbj1pJiZpLnk7aWYoc3x8bil7Y29uc3QgaT1TYVt0LnBvc2l0aW9uXS5jYWxsKHRoaXMsdGhpcy5fYWN0aXZlLHRoaXMuX2V2ZW50UG9zaXRpb24pO2lmKCFpKXJldHVybjtjb25zdCBvPXRoaXMuX3NpemU9T2EodGhpcyx0KSxhPU9iamVjdC5hc3NpZ24oe30saSx0aGlzLl9zaXplKSxyPVRhKGUsdCxhKSxsPUxhKHQsYSxyLGUpO3MuX3RvPT09bC54JiZuLl90bz09PWwueXx8KHRoaXMueEFsaWduPXIueEFsaWduLHRoaXMueUFsaWduPXIueUFsaWduLHRoaXMud2lkdGg9by53aWR0aCx0aGlzLmhlaWdodD1vLmhlaWdodCx0aGlzLmNhcmV0WD1pLngsdGhpcy5jYXJldFk9aS55LHRoaXMuX3Jlc29sdmVBbmltYXRpb25zKCkudXBkYXRlKHRoaXMsbCkpfX1fd2lsbFJlbmRlcigpe3JldHVybiEhdGhpcy5vcGFjaXR5fWRyYXcodCl7Y29uc3QgZT10aGlzLm9wdGlvbnMuc2V0Q29udGV4dCh0aGlzLmdldENvbnRleHQoKSk7bGV0IGk9dGhpcy5vcGFjaXR5O2lmKCFpKXJldHVybjt0aGlzLl91cGRhdGVBbmltYXRpb25UYXJnZXQoZSk7Y29uc3Qgcz17d2lkdGg6dGhpcy53aWR0aCxoZWlnaHQ6dGhpcy5oZWlnaHR9LG49e3g6dGhpcy54LHk6dGhpcy55fTtpPU1hdGguYWJzKGkpPC4wMDE\/MDppO2NvbnN0IG89a2koZS5wYWRkaW5nKSxhPXRoaXMudGl0bGUubGVuZ3RofHx0aGlzLmJlZm9yZUJvZHkubGVuZ3RofHx0aGlzLmJvZHkubGVuZ3RofHx0aGlzLmFmdGVyQm9keS5sZW5ndGh8fHRoaXMuZm9vdGVyLmxlbmd0aDtlLmVuYWJsZWQmJmEmJih0LnNhdmUoKSx0Lmdsb2JhbEFscGhhPWksdGhpcy5kcmF3QmFja2dyb3VuZChuLHQscyxlKSxBaSh0LGUudGV4dERpcmVjdGlvbiksbi55Kz1vLnRvcCx0aGlzLmRyYXdUaXRsZShuLHQsZSksdGhpcy5kcmF3Qm9keShuLHQsZSksdGhpcy5kcmF3Rm9vdGVyKG4sdCxlKSxUaSh0LGUudGV4dERpcmVjdGlvbiksdC5yZXN0b3JlKCkpfWdldEFjdGl2ZUVsZW1lbnRzKCl7cmV0dXJuIHRoaXMuX2FjdGl2ZXx8W119c2V0QWN0aXZlRWxlbWVudHModCxlKXtjb25zdCBpPXRoaXMuX2FjdGl2ZSxzPXQubWFwKCgoe2RhdGFzZXRJbmRleDp0LGluZGV4OmV9KT0+e2NvbnN0IGk9dGhpcy5jaGFydC5nZXREYXRhc2V0TWV0YSh0KTtpZighaSl0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCBmaW5kIGEgZGF0YXNldCBhdCBpbmRleCAiK3QpO3JldHVybntkYXRhc2V0SW5kZXg6dCxlbGVtZW50OmkuZGF0YVtlXSxpbmRleDplfX0pKSxuPSFmKGkscyksbz10aGlzLl9wb3NpdGlvbkNoYW5nZWQocyxlKTsobnx8bykmJih0aGlzLl9hY3RpdmU9cyx0aGlzLl9ldmVudFBvc2l0aW9uPWUsdGhpcy5faWdub3JlUmVwbGF5RXZlbnRzPSEwLHRoaXMudXBkYXRlKCEwKSl9aGFuZGxlRXZlbnQodCxlLGk9ITApe2lmKGUmJnRoaXMuX2lnbm9yZVJlcGxheUV2ZW50cylyZXR1cm4hMTt0aGlzLl9pZ25vcmVSZXBsYXlFdmVudHM9ITE7Y29uc3Qgcz10aGlzLm9wdGlvbnMsbj10aGlzLl9hY3RpdmV8fFtdLG89dGhpcy5fZ2V0QWN0aXZlRWxlbWVudHModCxuLGUsaSksYT10aGlzLl9wb3NpdGlvbkNoYW5nZWQobyx0KSxyPWV8fCFmKG8sbil8fGE7cmV0dXJuIHImJih0aGlzLl9hY3RpdmU9bywocy5lbmFibGVkfHxzLmV4dGVybmFsKSYmKHRoaXMuX2V2ZW50UG9zaXRpb249e3g6dC54LHk6dC55fSx0aGlzLnVwZGF0ZSghMCxlKSkpLHJ9X2dldEFjdGl2ZUVsZW1lbnRzKHQsZSxpLHMpe2NvbnN0IG49dGhpcy5vcHRpb25zO2lmKCJtb3VzZW91dCI9PT10LnR5cGUpcmV0dXJuW107aWYoIXMpcmV0dXJuIGUuZmlsdGVyKCh0PT50aGlzLmNoYXJ0LmRhdGEuZGF0YXNldHNbdC5kYXRhc2V0SW5kZXhdJiZ2b2lkIDAhPT10aGlzLmNoYXJ0LmdldERhdGFzZXRNZXRhKHQuZGF0YXNldEluZGV4KS5jb250cm9sbGVyLmdldFBhcnNlZCh0LmluZGV4KSkpO2NvbnN0IG89dGhpcy5jaGFydC5nZXRFbGVtZW50c0F0RXZlbnRGb3JNb2RlKHQsbi5tb2RlLG4saSk7cmV0dXJuIG4ucmV2ZXJzZSYmby5yZXZlcnNlKCksb31fcG9zaXRpb25DaGFuZ2VkKHQsZSl7Y29uc3R7Y2FyZXRYOmksY2FyZXRZOnMsb3B0aW9uczpufT10aGlzLG89U2Fbbi5wb3NpdGlvbl0uY2FsbCh0aGlzLHQsZSk7cmV0dXJuITEhPT1vJiYoaSE9PW8ueHx8cyE9PW8ueSl9fXZhciBCYT17aWQ6InRvb2x0aXAiLF9lbGVtZW50OlZhLHBvc2l0aW9uZXJzOlNhLGFmdGVySW5pdCh0LGUsaSl7aSYmKHQudG9vbHRpcD1uZXcgVmEoe2NoYXJ0OnQsb3B0aW9uczppfSkpfSxiZWZvcmVVcGRhdGUodCxlLGkpe3QudG9vbHRpcCYmdC50b29sdGlwLmluaXRpYWxpemUoaSl9LHJlc2V0KHQsZSxpKXt0LnRvb2x0aXAmJnQudG9vbHRpcC5pbml0aWFsaXplKGkpfSxhZnRlckRyYXcodCl7Y29uc3QgZT10LnRvb2x0aXA7aWYoZSYmZS5fd2lsbFJlbmRlcigpKXtjb25zdCBpPXt0b29sdGlwOmV9O2lmKCExPT09dC5ub3RpZnlQbHVnaW5zKCJiZWZvcmVUb29sdGlwRHJhdyIsey4uLmksY2FuY2VsYWJsZTohMH0pKXJldHVybjtlLmRyYXcodC5jdHgpLHQubm90aWZ5UGx1Z2lucygiYWZ0ZXJUb29sdGlwRHJhdyIsaSl9fSxhZnRlckV2ZW50KHQsZSl7aWYodC50b29sdGlwKXtjb25zdCBpPWUucmVwbGF5O3QudG9vbHRpcC5oYW5kbGVFdmVudChlLmV2ZW50LGksZS5pbkNoYXJ0QXJlYSkmJihlLmNoYW5nZWQ9ITApfX0sZGVmYXVsdHM6e2VuYWJsZWQ6ITAsZXh0ZXJuYWw6bnVsbCxwb3NpdGlvbjoiYXZlcmFnZSIsYmFja2dyb3VuZENvbG9yOiJyZ2JhKDAsMCwwLDAuOCkiLHRpdGxlQ29sb3I6IiNmZmYiLHRpdGxlRm9udDp7d2VpZ2h0OiJib2xkIn0sdGl0bGVTcGFjaW5nOjIsdGl0bGVNYXJnaW5Cb3R0b206Nix0aXRsZUFsaWduOiJsZWZ0Iixib2R5Q29sb3I6IiNmZmYiLGJvZHlTcGFjaW5nOjIsYm9keUZvbnQ6e30sYm9keUFsaWduOiJsZWZ0Iixmb290ZXJDb2xvcjoiI2ZmZiIsZm9vdGVyU3BhY2luZzoyLGZvb3Rlck1hcmdpblRvcDo2LGZvb3RlckZvbnQ6e3dlaWdodDoiYm9sZCJ9LGZvb3RlckFsaWduOiJsZWZ0IixwYWRkaW5nOjYsY2FyZXRQYWRkaW5nOjIsY2FyZXRTaXplOjUsY29ybmVyUmFkaXVzOjYsYm94SGVpZ2h0Oih0LGUpPT5lLmJvZHlGb250LnNpemUsYm94V2lkdGg6KHQsZSk9PmUuYm9keUZvbnQuc2l6ZSxtdWx0aUtleUJhY2tncm91bmQ6IiNmZmYiLGRpc3BsYXlDb2xvcnM6ITAsYm94UGFkZGluZzowLGJvcmRlckNvbG9yOiJyZ2JhKDAsMCwwLDApIixib3JkZXJXaWR0aDowLGFuaW1hdGlvbjp7ZHVyYXRpb246NDAwLGVhc2luZzoiZWFzZU91dFF1YXJ0In0sYW5pbWF0aW9uczp7bnVtYmVyczp7dHlwZToibnVtYmVyIixwcm9wZXJ0aWVzOlsieCIsInkiLCJ3aWR0aCIsImhlaWdodCIsImNhcmV0WCIsImNhcmV0WSJdfSxvcGFjaXR5OntlYXNpbmc6ImxpbmVhciIsZHVyYXRpb246MjAwfX0sY2FsbGJhY2tzOnphfSxkZWZhdWx0Um91dGVzOntib2R5Rm9udDoiZm9udCIsZm9vdGVyRm9udDoiZm9udCIsdGl0bGVGb250OiJmb250In0sZGVzY3JpcHRvcnM6e19zY3JpcHRhYmxlOnQ9PiJmaWx0ZXIiIT09dCYmIml0ZW1Tb3J0IiE9PXQmJiJleHRlcm5hbCIhPT10LF9pbmRleGFibGU6ITEsY2FsbGJhY2tzOntfc2NyaXB0YWJsZTohMSxfaW5kZXhhYmxlOiExfSxhbmltYXRpb246e19mYWxsYmFjazohMX0sYW5pbWF0aW9uczp7X2ZhbGxiYWNrOiJhbmltYXRpb24ifX0sYWRkaXRpb25hbE9wdGlvblNjb3BlczpbImludGVyYWN0aW9uIl19O3JldHVybiBBbi5yZWdpc3RlcihZbixqbyxmbyx0KSxBbi5oZWxwZXJzPXsuLi5XaX0sQW4uX2FkYXB0ZXJzPVJuLEFuLkFuaW1hdGlvbj1DcyxBbi5BbmltYXRpb25zPU9zLEFuLmFuaW1hdG9yPXh0LEFuLmNvbnRyb2xsZXJzPWVuLmNvbnRyb2xsZXJzLml0ZW1zLEFuLkRhdGFzZXRDb250cm9sbGVyPU5zLEFuLkVsZW1lbnQ9SHMsQW4uZWxlbWVudHM9Zm8sQW4uSW50ZXJhY3Rpb249WGksQW4ubGF5b3V0cz1hcyxBbi5wbGF0Zm9ybXM9U3MsQW4uU2NhbGU9SnMsQW4uVGlja3M9YWUsT2JqZWN0LmFzc2lnbihBbixZbixqbyxmbyx0LFNzKSxBbi5DaGFydD1BbiwidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmKHdpbmRvdy5DaGFydD1BbiksQW59KSk7<\/script>\r\n<script>\r\n(function() {\r\n  function tryLoadFallback() {\r\n    if (typeof Chart !== \"undefined\") {\r\n      return;\r\n    }\r\n    \r\n    var b64Script = document.getElementById(\"chartjs-b64\");\r\n    if (!b64Script) {\r\n      return;\r\n    }\r\n    \r\n    try {\r\n      \/\/ Base64 string aus textContent (kein HTML-encoding-Risiko bei Base64)\r\n      var b64 = b64Script.textContent.trim();\r\n      \/\/ Decode Base64 \u2192 original JS code\r\n      var code = atob(b64);\r\n      \/\/ Eval\r\n      new Function(code)();\r\n      \r\n      \/\/ Charts neu rendern wenn Berechnung schon lief\r\n      if (typeof window.berechnen === \"function\") {\r\n        var r = document.getElementById(\"results\");\r\n        if (r && r.classList.contains(\"show\")) {\r\n          window.berechnen();\r\n        }\r\n      }\r\n    } catch (err) {\r\n      console.error(\"[AVD-Tool] Base64-Fallback fehlgeschlagen:\", err);\r\n    }\r\n  }\r\n  \r\n  setTimeout(tryLoadFallback, 2000);\r\n})();\r\n<\/script>\r\n<style>\r\n  \/* \u2500\u2500 finanzen.net Ratgeber Theme \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n     Light Theme passend zu finanzen.net\/ratgeber.\r\n     Hebt sich als interaktives Widget ab, f\u00fcgt sich aber ins Seitendesign ein.\r\n  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl {\r\n    \/* Layout & Surfaces \u2013 Light Theme *\/\r\n    --bg:       #f0f4f8;       \/* Seiten-Hintergrund: leicht blau-grau \u2192 Widget hebt sich ab *\/\r\n    --surface:  #ffffff;       \/* Karten & Panels: reines Wei\u00df *\/\r\n    --surface2: #f4f6f9;       \/* Input-Hintergrund, leicht grau *\/\r\n    --border:   #dce3ea;       \/* Borders: dezentes Hellgrau *\/\r\n    --text:     #1a2332;       \/* Haupttext: fast schwarz, leicht navy *\/\r\n    --muted:    #5a6573;       \/* Sekund\u00e4rtext: mittelgrau (BFSG: AA-Kontrast) *\/\r\n    --warning:  #d97706;       \/* Warnungen: Amber *\/\r\n    --error:    #dc2626;       \/* Fehler: Rot *\/\r\n\r\n    \/* finanzen.net Prim\u00e4rfarbe \u2013 Navy Blau *\/\r\n    --accent:   #2691ff;       \/* brand-finnet: finanzen.net Navy *\/\r\n    --accent2:  #0d4d8a;       \/* Hover-Variante: etwas heller *\/\r\n\r\n    \/* Tool-spezifische Produktfarben Datenvisualisierung *\/\r\n    --riester:    #0d6efd;\r\n    --depot:      #e85d1a;\r\n    --etf:        #1D9E75;\r\n    --individual: #7c3aed;\r\n  }\r\n\r\n  \/* \u2500\u2500 Scoped Reset (WP-inline-sicher: wirkt NICHT auf die WP-Seite) \u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .tool-wrapper,\r\n  .avdemb-t18pl .tool-wrapper *,\r\n  .avdemb-t18pl .tool-wrapper *::before,\r\n  .avdemb-t18pl .tool-wrapper *::after { margin: 0; padding: 0; box-sizing: border-box; }\r\n\r\n  .avdemb-t18pl .tool-wrapper {\r\n    max-width: 900px;\r\n    margin: 0 auto;\r\n    padding: 32px 24px;\r\n    position: relative;\r\n    z-index: 1;\r\n    background: var(--bg);\r\n    color: var(--text);\r\n    font-family: \"OpenSans\", Arial, Helvetica, sans-serif;\r\n  }\r\n\r\n  \/* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .header {\r\n    margin-bottom: 48px;\r\n    animation: kft18pl-fadeUp 0.6s ease both;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-wrapper h1 {\r\n    font-size: clamp(32px, 4vw, 48px);\r\n    font-weight: 700;\r\n    line-height: 1.15;\r\n    margin-bottom: 12px;\r\n    letter-spacing: -0.01em;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-wrapper h1 span { color: var(--accent); }\r\n\r\n  .avdemb-t18pl .subtitle {\r\n    color: var(--muted);\r\n    font-size: 16px;\r\n    line-height: 1.6;\r\n    max-width: 560px;\r\n  }\r\n\r\n  \/* \u2500\u2500 Form Sections (custom \u2013 kein Panel-Component im Styleguide) \u2500\u2500 *\/\r\n  .avdemb-t18pl .form-grid {\r\n    display: grid;\r\n    gap: 16px;\r\n    margin-bottom: 32px;\r\n    overflow: visible;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-panel {\r\n    background: var(--surface);\r\n    box-shadow: 0 2px 8px rgba(38,145,255,0.08);\r\n    border: 1px solid var(--border);\r\n    border-radius: 12px;\r\n    padding: 24px;\r\n    animation: kft18pl-fadeUp 0.6s ease both;\r\n    width: 100%;\r\n    box-sizing: border-box;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-panel:nth-child(1) { animation-delay: 0.1s; }\r\n  .avdemb-t18pl .tool-panel:nth-child(2) { animation-delay: 0.2s; }\r\n  .avdemb-t18pl .tool-panel:nth-child(3) { animation-delay: 0.3s; }\r\n  .avdemb-t18pl .tool-panel:nth-child(4) { animation-delay: 0.4s; }\r\n\r\n  .avdemb-t18pl .section-label {\r\n    font-size: 11px;\r\n    font-weight: 700;\r\n    letter-spacing: 0.1em;\r\n    text-transform: uppercase;\r\n    color: var(--muted);\r\n    margin-bottom: 16px;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 8px;\r\n  }\r\n\r\n  .avdemb-t18pl .section-label::after {\r\n    content: '';\r\n    flex: 1;\r\n    height: 1px;\r\n    background: var(--border);\r\n  }\r\n\r\n  .avdemb-t18pl .fields-row {\r\n    display: grid;\r\n    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\r\n    gap: 16px;\r\n  }\r\n\r\n  .avdemb-t18pl .field {\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 8px;\r\n  }\r\n\r\n  \/* \u2500\u2500 Input-Wrapper (f\u00fcr Suffix-Einheit) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .input-wrap {\r\n    position: relative;\r\n    display: flex;\r\n    align-items: center;\r\n    background: var(--surface2);\r\n    border: 1px solid var(--border);\r\n    border-radius: 10px;\r\n    padding: 0 12px;\r\n    margin-top: 6px;\r\n  }\r\n\r\n  \/* \u00dcberschreibt .input aus Styleguide f\u00fcr transparenten Hintergrund im Wrapper *\/\r\n  .avdemb-t18pl .input-wrap .input {\r\n    background: transparent;\r\n    border: none;\r\n    border-radius: 0;\r\n    padding: 10px 0;\r\n    width: 100%;\r\n    font-size: 14px;\r\n    font-weight: 500;\r\n    color: var(--text);\r\n    box-shadow: none;\r\n  }\r\n\r\n  .avdemb-t18pl .input-wrap .input:focus {\r\n    outline: none;\r\n    box-shadow: none;\r\n  }\r\n\r\n  .avdemb-t18pl .input-wrap:focus-within {\r\n    border-color: var(--accent);\r\n    box-shadow: 0 0 0 3px rgba(38,145,255,0.12);\r\n  }\r\n\r\n  .avdemb-t18pl .currency-suffix {\r\n    font-size: 15px;\r\n    font-weight: 500;\r\n    color: var(--text);\r\n    pointer-events: none;\r\n    line-height: 1;\r\n    flex-shrink: 0;\r\n    margin-left: 4px;\r\n  }\r\n\r\n  \/* \u2500\u2500 Range Slider (kein Styleguide-\u00c4quivalent) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .slider-section {\r\n    padding: 24px;\r\n    margin-bottom: 3px;\r\n  }\r\n\r\n  .avdemb-t18pl .slider-labels {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    margin-bottom: 8px;\r\n  }\r\n\r\n  .avdemb-t18pl .slider-label {\r\n    font-size: 12px;\r\n    color: var(--muted);\r\n    font-weight: 500;\r\n  }\r\n\r\n  .avdemb-t18pl .slider-label.active {\r\n    color: var(--accent);\r\n    font-weight: 600;\r\n  }\r\n\r\n  .avdemb-t18pl .scenario-display {\r\n    text-align: center;\r\n    margin-bottom: 16px;\r\n  }\r\n\r\n  .avdemb-t18pl .scenario-name {\r\n    font-size: 20px;\r\n    font-weight: 700;\r\n    color: var(--accent);\r\n  }\r\n\r\n  .avdemb-t18pl .scenario-rates {\r\n    font-size: 13px;\r\n    color: var(--muted);\r\n    margin-top: 4px;\r\n  }\r\n\r\n  \/* Szenario-Auswahl im Ergebnis (Buttons + Regler, \u00fcber dem Hero) *\/\r\n  .avdemb-t18pl .szenario-panel {\r\n    border: 1px solid #bcd9ff;\r\n    background: #f4f9ff;\r\n    border-radius: 12px;\r\n    padding: 14px 16px;\r\n    margin-bottom: 16px;\r\n  }\r\n  .avdemb-t18pl .szenario-panel .sz-frage {\r\n    font-size: 13.5px;\r\n    font-weight: 700;\r\n    color: var(--text);\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 8px;\r\n    flex-wrap: wrap;\r\n  }\r\n  .avdemb-t18pl .szenario-buttons {\r\n    display: grid;\r\n    grid-template-columns: repeat(3, 1fr);\r\n    gap: 8px;\r\n    margin: 12px 0 8px;\r\n  }\r\n  .avdemb-t18pl .sz-btn {\r\n    border: 2px solid var(--border);\r\n    background: #fff;\r\n    border-radius: 11px;\r\n    padding: 11px 6px;\r\n    cursor: pointer;\r\n    font-family: inherit;\r\n    font-size: 13.5px;\r\n    font-weight: 800;\r\n    color: var(--text);\r\n    transition: all .15s;\r\n    text-align: center;\r\n  }\r\n  .avdemb-t18pl .sz-btn:hover { border-color: var(--accent); }\r\n  .avdemb-t18pl .sz-btn.active { border-color: #2691ff; background: #2691ff; color: #fff; }\r\n  .avdemb-t18pl .sz-btn:focus-visible { outline: 3px solid #2691ff; outline-offset: 2px; }\r\n  .avdemb-t18pl .szenario-panel .scenario-rates { text-align: center; }\r\n\r\n  .avdemb-t18pl .tool-wrapper input[type=\"range\"] {\r\n    width: 100%;\r\n    appearance: none;\r\n    -webkit-appearance: none;\r\n    height: 4px;\r\n    border-radius: 2px;\r\n    background: var(--border);\r\n    outline: none;\r\n    cursor: pointer;\r\n    transition: background 0.2s;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-wrapper input[type=\"range\"]::-webkit-slider-thumb {\r\n    -webkit-appearance: none;\r\n    width: 20px;\r\n    height: 20px;\r\n    border-radius: 50%;\r\n    background: var(--accent);\r\n    cursor: pointer;\r\n    box-shadow: 0 0 0 3px rgba(38,145,255,0.15);\r\n    transition: box-shadow 0.2s;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-wrapper input[type=\"range\"]::-webkit-slider-thumb:hover {\r\n    box-shadow: 0 0 0 6px rgba(38,145,255,0.15);\r\n  }\r\n\r\n  \/* \u2500\u2500 Kinder-Auswahl: Optik aus Tool 7.7 \u00fcbernommen \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n     Bewusst NICHT die Styleguide-Klasse .button \u2013 die zieht das schwere\r\n     Navy-Outline des Themes und l\u00e4sst die Z\u00e4hler wie Formular-Buttons\r\n     aussehen. .kinder-btn ist selbsttragend und in 7.7 erprobt.\r\n  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .kinder-btn {\r\n    padding: 8px 16px;\r\n    border-radius: 8px;\r\n    border: 1px solid var(--border);\r\n    background: transparent;\r\n    color: var(--muted);\r\n    font-family: \"OpenSans\", Arial, Helvetica, sans-serif;\r\n    font-size: 14px;\r\n    cursor: pointer;\r\n    transition: all 0.2s;\r\n  }\r\n  .avdemb-t18pl .kinder-btn.active {\r\n    background: #E8327A;\r\n    border-color: #E8327A;\r\n    color: white;\r\n    font-weight: 500;\r\n  }\r\n\r\n  \/* \u2500\u2500 Buttons: Zero Pink \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n     CTA-Buttons in Zero-Pink als Akzent-Farbe.\r\n  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .tool-wrapper .button--primary,\r\n  .avdemb-t18pl .tool-wrapper a.button--primary {\r\n    background-color: #E8327A !important;\r\n    border-color:     #E8327A !important;\r\n    color:            #ffffff !important;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-wrapper .button--primary:hover,\r\n  .avdemb-t18pl .tool-wrapper a.button--primary:hover {\r\n    background-color: #C8305A !important;\r\n    border-color:     #C8305A !important;\r\n    color:            #ffffff !important;\r\n    box-shadow: 0 4px 16px rgba(232,50,122,0.3);\r\n  }\r\n\r\n  .avdemb-t18pl .tool-wrapper .button--primary:active,\r\n  .avdemb-t18pl .tool-wrapper a.button--primary:active {\r\n    background-color: #a82248 !important;\r\n    border-color:     #a82248 !important;\r\n  }\r\n\r\n  \/* Flat-Button: Outline in Zero-Pink *\/\r\n  .avdemb-t18pl .tool-wrapper .button--flat {\r\n    background-color: transparent !important;\r\n    border-color:     #E8327A !important;\r\n    color:            #E8327A !important;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-wrapper .button--flat:hover {\r\n    background-color: rgba(232,50,122,0.06) !important;\r\n  }\r\n\r\n  \/* Kinder-Buttons aktiver Zustand ebenfalls Zero-Pink *\/\r\n  .avdemb-t18pl .kinder-btn.active {\r\n    background-color: #E8327A !important;\r\n    border-color:     #E8327A !important;\r\n    color:            #ffffff !important;\r\n  }\r\n\r\n  \/* \u2500\u2500 Child Input Fields \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .child-field {\r\n    background: var(--surface2);\r\n    border: 1px solid var(--border);\r\n    border-radius: 10px;\r\n    padding: 10px 14px;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 10px;\r\n  }\r\n\r\n  .avdemb-t18pl .child-field label { font-size: 12px; white-space: nowrap; }\r\n\r\n  .avdemb-t18pl .child-field input {\r\n    width: 60px;\r\n    background: transparent;\r\n    border: none;\r\n    border-bottom: 1px solid var(--border);\r\n    border-radius: 0;\r\n    padding: 4px 0;\r\n    font-size: 14px;\r\n    text-align: center;\r\n    color: var(--text);\r\n  }\r\n\r\n  \/* \u2500\u2500 Kinder-Geburtsjahr-Input: Optik wie .input-wrap, Gr\u00f6\u00dfe unver\u00e4ndert \u2500\u2500 *\/\r\n  .avdemb-t18pl .input--childbirth {\r\n    background: var(--surface2) !important;\r\n    border: 1px solid var(--border) !important;\r\n    border-radius: 10px !important;\r\n    box-shadow: none !important;\r\n  }\r\n  .avdemb-t18pl .input--childbirth:focus {\r\n    outline: none !important;\r\n    border-color: var(--accent) !important;\r\n    box-shadow: 0 0 0 3px rgba(38,145,255,0.12) !important;\r\n  }\r\n  .avdemb-t18pl .input--childbirth::-webkit-inner-spin-button,\r\n  .avdemb-t18pl .input--childbirth::-webkit-outer-spin-button {\r\n    -webkit-appearance: none !important;\r\n    margin: 0 !important;\r\n  }\r\n\r\n  \/* \u2500\u2500 Results \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .results {\r\n    display: none;\r\n    animation: kft18pl-fadeUp 0.5s ease both;\r\n    overflow: visible;\r\n  }\r\n\r\n  .avdemb-t18pl .results.show { display: block; }\r\n\r\n  .avdemb-t18pl .results-header {\r\n    font-size: 13px;\r\n    font-weight: 700;\r\n    letter-spacing: 0.1em;\r\n    text-transform: uppercase;\r\n    color: var(--muted);\r\n    margin-bottom: 20px;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 12px;\r\n  }\r\n\r\n  .avdemb-t18pl .results-header::after {\r\n    content: '';\r\n    flex: 1;\r\n    height: 1px;\r\n    background: var(--border);\r\n  }\r\n\r\n  \/* \u2500\u2500 Cards (custom \u2013 kein Card-Component im Styleguide) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .cards-grid {\r\n    display: grid;\r\n    grid-template-columns: repeat(2, minmax(0, 1fr));\r\n    gap: 12px;\r\n    margin-bottom: 24px;\r\n    overflow: visible;\r\n    align-items: stretch;\r\n    width: 100%;\r\n  }\r\n\r\n  @media (max-width: 900px) { .avdemb-t18pl .cards-grid { grid-template-columns: repeat(2, 1fr); } }\r\n  @media (max-width: 500px) { .avdemb-t18pl .cards-grid { grid-template-columns: 1fr; } }\r\n\r\n  .avdemb-t18pl .card {\r\n    overflow: visible !important;\r\n    background: var(--surface);\r\n    box-shadow: 0 2px 8px rgba(38,145,255,0.08);\r\n    border: 1px solid var(--border);\r\n    border-radius: 12px;\r\n    padding: 18px 16px;\r\n    position: relative;\r\n    transition: transform 0.2s;\r\n    display: flex;\r\n    flex-direction: column;\r\n    box-sizing: border-box;\r\n  }\r\n\r\n  .avdemb-t18pl .card:hover { transform: translateY(-2px); }\r\n\r\n  .avdemb-t18pl .card::before {\r\n    content: '';\r\n    position: absolute;\r\n    top: 0; left: 0; right: 0;\r\n    height: 3px;\r\n  }\r\n\r\n  .avdemb-t18pl .card.winner::after {\r\n    content: '\u2605';\r\n    position: absolute;\r\n    top: 10px; right: 12px;\r\n    font-size: 28px;\r\n    color: #FFD700;\r\n    line-height: 1;\r\n    z-index: 0;\r\n  }\r\n\r\n  .avdemb-t18pl .card.riester::before    { background: var(--riester); }\r\n  .avdemb-t18pl .card.depot::before      { background: var(--depot); }\r\n  .avdemb-t18pl .card.etf::before        { background: var(--etf); }\r\n  .avdemb-t18pl .card.individual::before { background: var(--individual); }\r\n\r\n  .avdemb-t18pl .card-label {\r\n    font-size: 11px;\r\n    font-weight: 600;\r\n    letter-spacing: 0.03em;\r\n    text-transform: uppercase;\r\n    margin-bottom: 12px;\r\n    min-height: 28px;\r\n    display: flex;\r\n    align-items: flex-start;\r\n    line-height: 1.5;\r\n  }\r\n\r\n  .avdemb-t18pl .card.riester .card-label    { color: var(--riester); }\r\n  .avdemb-t18pl .card.depot .card-label      { color: var(--depot); }\r\n  .avdemb-t18pl .card.etf .card-label        { color: var(--etf); }\r\n  .avdemb-t18pl .card.individual .card-label { color: var(--individual); }\r\n\r\n  .avdemb-t18pl .card-amount {\r\n    font-size: 22px;\r\n    font-weight: 500;\r\n    margin-bottom: 4px;\r\n    white-space: nowrap;\r\n    overflow: hidden;\r\n    text-overflow: ellipsis;\r\n    line-height: 1.3;\r\n  }\r\n\r\n  .avdemb-t18pl .card-sub {\r\n    font-size: 11px;\r\n    color: var(--muted);\r\n    margin-bottom: 16px;\r\n    line-height: 1.4;\r\n    font-weight: 400;\r\n  }\r\n\r\n  .avdemb-t18pl .card-detail {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    font-size: 11px;\r\n    padding: 5px 0;\r\n    border-top: 1px solid var(--border);\r\n    color: var(--muted);\r\n    gap: 6px;\r\n    overflow: visible;\r\n    position: relative;\r\n    z-index: 1;\r\n  }\r\n\r\n  .avdemb-t18pl .card-detail span:first-child {\r\n    flex-shrink: 0;\r\n    white-space: nowrap;\r\n  }\r\n\r\n  .avdemb-t18pl .card-detail > span:last-child {\r\n    font-weight: 600;\r\n    color: var(--text);\r\n    text-align: right;\r\n    white-space: nowrap;\r\n  }\r\n\r\n  \/* \u2500\u2500 Delta Banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .delta-banner {\r\n    background: #E8327A;\r\n    border: none;\r\n    border-radius: 12px;\r\n    padding: 28px 24px;\r\n    margin-bottom: 24px;\r\n    text-align: center;\r\n    box-shadow: 0 4px 20px rgba(232,50,122,0.35);\r\n  }\r\n\r\n  .avdemb-t18pl .delta-label {\r\n    font-size: 13px;\r\n    color: rgba(255,255,255,0.85);\r\n    margin-bottom: 8px;\r\n  }\r\n\r\n  .avdemb-t18pl .delta-amount {\r\n    font-size: clamp(40px, 5vw, 60px);\r\n    font-weight: 700;\r\n    color: #ffffff;\r\n    letter-spacing: -0.01em;\r\n    line-height: 1.1;\r\n  }\r\n\r\n  .avdemb-t18pl .delta-sub {\r\n    font-size: 14px;\r\n    color: rgba(255,255,255,0.85);\r\n    margin-top: 8px;\r\n  }\r\n\r\n  \/* \u2500\u2500 F\u00f6rderungs-Box (custom \u2013 tool-spezifisch) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .foerderung-box {\r\n    background: var(--surface);\r\n    box-shadow: 0 2px 8px rgba(38,145,255,0.08);\r\n    border: 1px solid var(--border);\r\n    border-radius: 12px;\r\n    padding: 20px;\r\n    margin-bottom: 24px;\r\n    display: grid;\r\n    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\r\n    gap: 16px;\r\n  }\r\n\r\n  .avdemb-t18pl .foerderung-item { text-align: center; }\r\n\r\n  .avdemb-t18pl .foerderung-amount {\r\n    font-size: 22px;\r\n    font-weight: 700;\r\n    color: var(--accent);\r\n  }\r\n\r\n  .avdemb-t18pl .foerderung-label {\r\n    font-size: 11px;\r\n    color: var(--muted);\r\n    margin-top: 4px;\r\n  }\r\n\r\n  \/* \u2500\u2500 Flow Box \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .flow-box {\r\n    background: var(--surface);\r\n    box-shadow: 0 2px 12px rgba(0,0,0,0.06);\r\n    border: 1px solid #bdd0e8;\r\n    border-radius: 12px;\r\n    padding: 24px;\r\n    margin-bottom: 24px;\r\n    display: none;\r\n  }\r\n\r\n  .avdemb-t18pl .flow-box.show { display: block; }\r\n\r\n  .avdemb-t18pl .flow-title {\r\n    font-size: 16px;\r\n    font-weight: 700;\r\n    margin-bottom: 8px;\r\n    color: var(--accent);\r\n  }\r\n\r\n  .avdemb-t18pl .flow-text {\r\n    font-size: 14px;\r\n    color: var(--muted);\r\n    line-height: 1.6;\r\n  }\r\n\r\n  \/* \u2500\u2500 Zero CTA Box \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .zero-cta {\r\n    background: var(--surface);\r\n    box-shadow: 0 2px 8px rgba(38,145,255,0.08);\r\n    border: 1px solid var(--border);\r\n    border-radius: 12px;\r\n    padding: 24px;\r\n    margin-bottom: 16px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: space-between;\r\n    gap: 48px;\r\n    flex-wrap: nowrap;\r\n  }\r\n\r\n  .avdemb-t18pl .zero-cta-text { max-width: 480px; flex-shrink: 1; }\r\n\r\n  .avdemb-t18pl .zero-cta-text h3 {\r\n    font-size: 18px;\r\n    font-weight: 700;\r\n    margin-bottom: 4px;\r\n  }\r\n\r\n  .avdemb-t18pl .zero-cta-text p {\r\n    font-size: 13px;\r\n    color: var(--muted);\r\n    margin-bottom: 12px;\r\n    line-height: 1.6;\r\n  }\r\n\r\n  \/* \u2500\u2500 Disclaimer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .disclaimer {\r\n    background: #eaf0f6;\r\n    border: 1.5px solid #b9c6d5;\r\n    border-radius: 10px;\r\n    padding: 16px 20px;\r\n    font-size: 11px;\r\n    color: #4a5563;\r\n    \r\n    margin: 0 auto 24px auto;\r\n    line-height: 1.7;\r\n  }\r\n\r\n  .avdemb-t18pl .disclaimer strong {\r\n    color: #093967;\r\n    font-weight: 700;\r\n    font-size: 13px;\r\n  }\r\n  \/* Hervorhebungen in den Listenpunkten in Textfarbe \u2013 nur die \"Hinweise\"-Ueberschrift (bzw. echte Links) bleibt blau *\/\r\n  .avdemb-t18pl .disclaimer li strong {\r\n    color: inherit;\r\n    font-size: inherit;\r\n  }\r\n\r\n  \/* \u2500\u2500 Animationen \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  @keyframes kft18pl-fadeUp {\r\n    \/* WICHTIG: 'to' setzt KEIN transform \u2192 nach 'animation \u2026 both' bleibt KEIN\r\n       transform am Element haften. Sonst w\u00fcrden .tool-panel\/.results\/.header zum\r\n       Containing-Block f\u00fcr position:fixed-Tooltips \u2192 Mobile-Tooltip abgeschnitten. *\/\r\n    from { opacity: 0; transform: translateY(20px); }\r\n    to   { opacity: 1; }\r\n  }\r\n\r\n  @keyframes kft18pl-pulse {\r\n    0%, 100% { opacity: 1; }\r\n    50%       { opacity: 0.4; }\r\n  }\r\n\r\n  \/* \u2500\u2500 Hinweis-Meldungen \u2013 form-note Pattern aus Styleguide\r\n     Fallback-Styles bis style-net.css geladen ist \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .form-note {\r\n    font-size: 11px;\r\n    display: none;\r\n    margin-top: 4px;\r\n    line-height: 1.4;\r\n  }\r\n\r\n  .avdemb-t18pl .form-note.show { display: block; }\r\n\r\n  .avdemb-t18pl .form-note--warning { color: var(--warning); }\r\n  .avdemb-t18pl .form-note--info    { color: var(--accent2); }\r\n  .avdemb-t18pl .form-note--error   { color: var(--error); }\r\n\r\n  \/* \u2500\u2500 Labels einheitlich grau \u2013 \u00fcberschreibt Styleguide-Default \u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .tool-panel label,\r\n  .avdemb-t18pl .field label,\r\n  .avdemb-t18pl .tool-panel label[style],\r\n  .avdemb-t18pl .field label[style] {\r\n    color: var(--muted) !important;\r\n  }\r\n\r\n  \/* \u2500\u2500 Input: Fehlerzustand \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .tool-wrapper input.error,\r\n  .avdemb-t18pl .tool-wrapper .input--invalid {\r\n    border-color: var(--error) !important;\r\n  }\r\n\r\n  \/* \u2500\u2500 Nummer-Input Spinner entfernen \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .tool-wrapper input[type=\"number\"]::-webkit-inner-spin-button,\r\n  .avdemb-t18pl .tool-wrapper input[type=\"number\"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }\r\n  .avdemb-t18pl .tool-wrapper input[type=\"number\"] { -moz-appearance: textfield; }\r\n\r\n  \/* \u2500\u2500 CSS-only Tooltips (kein script-net.js n\u00f6tig) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n    .avdemb-t18pl .tip {\r\n    display: inline-flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    width: 16px;\r\n    height: 16px;\r\n    border-radius: 50%;\r\n    background: rgba(38,145,255,0.08);\r\n    border: 1px solid rgba(38,145,255,0.2);\r\n    color: var(--muted);\r\n    font-size: 10px;\r\n    font-style: normal;\r\n    cursor: help;\r\n    vertical-align: middle;\r\n    position: relative;\r\n    flex-shrink: 0;\r\n  }\r\n\r\n  .avdemb-t18pl .tip .tip-text {\r\n    display: none;\r\n    position: absolute;\r\n    bottom: calc(100% + 8px);\r\n    left: 50%;\r\n    transform: translateX(-50%);\r\n    background: #2691ff;\r\n    color: #ffffff;\r\n    font-size: 12px;\r\n    font-weight: 400;\r\n    line-height: 1.7;\r\n    padding: 10px 14px;\r\n    border-radius: 8px;\r\n    white-space: nowrap;\r\n    z-index: 9999;\r\n    pointer-events: none;\r\n    box-shadow: 0 4px 16px rgba(38,145,255,0.35);\r\n    text-transform: none;\r\n    letter-spacing: normal;\r\n  }\r\n\r\n  \/* Anzeige NUR noch \u00fcber das JS-Portal (.tip-portal, an <body> geh\u00e4ngt).\r\n     Die alte in-place-Anzeige per :hover\/.open ist entfernt \u2013 sonst zeigte ein\r\n     in einem verschachtelten Stacking-Context \u201eeingesperrter\" Tooltip, der vom\r\n     n\u00e4chsten Panel verdeckt wurde. *\/\r\n  \/* BFSG (WCAG 2.1.1 \/ 2.4.7): sichtbarer Fokusring bleibt erhalten *\/\r\n  .avdemb-t18pl .tip:focus-visible { outline: 3px solid #2691ff; outline-offset: 2px; }\r\n  \/* BFSG: nur f\u00fcr Screenreader (visually-hidden) *\/\r\n  .avdemb-t18pl .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; }\r\n\r\n  \/* \u2500\u2500 Tooltip-PORTAL (Mobile) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n     Auf Mobile wird der Tooltip-Text per JS an <body> verschoben, damit er\r\n     im Wurzel-Stacking-Context liegt. So kann KEIN nachfolgendes .tool-panel\r\n     mehr dar\u00fcber zeichnen (Ursache des \u201eabgeschnitten\/verdeckt\"-Problems).\r\n     Diese Klasse tr\u00e4gt das komplette Aussehen, da die Descendant-Selektoren\r\n     (.tip .tip-text) nach dem Verschieben nicht mehr greifen.\r\n  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .tip-text.tip-portal {\r\n    position: fixed !important;\r\n    display: block !important;\r\n    background: #2691ff !important;\r\n    color: #ffffff !important;\r\n    font-size: 12px !important;\r\n    font-weight: 400 !important;\r\n    line-height: 1.55 !important;\r\n    padding: 12px 14px !important;\r\n    border-radius: 10px !important;\r\n    box-shadow: 0 8px 28px rgba(38,145,255,0.45) !important;\r\n    white-space: normal !important;\r\n    overflow-wrap: break-word !important;\r\n    word-break: break-word !important;\r\n    max-height: 70vh !important;\r\n    overflow-y: auto !important;\r\n    overflow-x: hidden !important;\r\n    box-sizing: border-box !important;\r\n    z-index: 2147483000 !important;\r\n    pointer-events: auto !important;\r\n    text-transform: none !important;\r\n    letter-spacing: normal !important;\r\n    transform: none !important;\r\n  }\r\n  .avdemb-t18pl .tip-text.tip-portal::before { display: none !important; }\r\n  \/* Desktop-Variante des Portals: an Icon ausgerichtete Box statt Vollbreite *\/\r\n  .avdemb-t18pl .tip-text.tip-portal.tip-portal-desktop {\r\n    left: auto;\r\n    right: auto;\r\n    max-width: 320px !important;\r\n    pointer-events: none !important;   \/* Maus \u201ef\u00e4llt durch\" \u2192 Hover-Schlie\u00dfen bleibt zuverl\u00e4ssig *\/\r\n  }\r\n\r\n  \/* Tooltip in card-detail: an die Zeile andocken (volle Kartenbreite) -> nie abgeschnitten, auch nicht am Viewport-Rand *\/\r\n  .avdemb-t18pl .card-detail .tip { margin-left: 6px; }\r\n  @media (min-width: 641px) {\r\n    .avdemb-t18pl .card-detail .tip { position: static; }\r\n    .avdemb-t18pl .card-detail .tip .tip-text {\r\n      left: 0;\r\n      right: 0;\r\n      bottom: calc(100% + 6px);\r\n      transform: none;\r\n      white-space: normal;\r\n      max-width: none;\r\n      box-sizing: border-box;\r\n    }\r\n  }\r\n\r\n  \/* CTA-Button: Desktop\/Mobile Textvarianten *\/\r\n  .avdemb-t18pl .cta-btn-mobile { display: none; }\r\n  .avdemb-t18pl .cta-btn-desktop { display: inline; }\r\n\r\n  \/* \u2500\u2500 Mobile Fixes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n     Kein HTML ge\u00e4ndert \u2013 reines CSS.\r\n     Kein overflow:hidden auf .tool-panel (w\u00fcrde Tooltips abschneiden).\r\n  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  @media (max-width: 640px) {\r\n\r\n    \/* Wrapper: Seitenabstand reduzieren *\/\r\n    .avdemb-t18pl .tool-wrapper {\r\n      padding-left: 16px;\r\n      padding-right: 16px;\r\n    }\r\n\r\n    \/* 3-Spalten-Grid \u2192 1 Spalte (kein HTML ge\u00e4ndert) *\/\r\n    .avdemb-t18pl .tool-panel > div[style*=\"grid-template-columns:1fr 1fr 1fr\"] {\r\n      grid-template-columns: 1fr !important;\r\n      gap: 16px !important;\r\n    }\r\n\r\n    \/* Tool-Wrapper darf Tooltips nicht abschneiden *\/\r\n    .avdemb-t18pl .tool-wrapper {\r\n      overflow: visible !important;\r\n    }\r\n    .avdemb-t18pl .tool-panel {\r\n      max-width: 100%;\r\n      box-sizing: border-box;\r\n    }\r\n\r\n    \/* Section-Label: Badge + Tooltip umbrechen statt rauslaufen *\/\r\n    .avdemb-t18pl .section-label {\r\n      flex-wrap: wrap;\r\n      gap: 6px;\r\n    }\r\n\r\n    \/* Karte: Hover-Transform auf Mobile aus -> sonst bricht position:fixed der Tooltips (Containing Block) *\/\r\n    .avdemb-t18pl .card:hover { transform: none; }\r\n\r\n    \/* Mobile Tooltips: viewport-sichere Box *\/\r\n    .avdemb-t18pl .tip {\r\n      position: relative !important;\r\n      z-index: 100;\r\n    }\r\n\r\n    .avdemb-t18pl .tip .tip-text {\r\n      position: fixed !important;\r\n      display: none;\r\n\r\n      left: 16px !important;\r\n      right: 16px !important;\r\n      top: auto;\r\n      bottom: auto;\r\n      transform: none !important;\r\n\r\n      width: auto !important;\r\n      max-width: none !important;\r\n      min-width: 0 !important;\r\n      max-height: 65vh !important;\r\n      overflow-y: auto !important;\r\n      overflow-x: hidden !important;\r\n\r\n      white-space: normal !important;\r\n      overflow-wrap: break-word !important;\r\n      word-break: break-word !important;\r\n\r\n      box-sizing: border-box !important;\r\n      padding: 12px 14px !important;\r\n      border-radius: 10px !important;\r\n      line-height: 1.55 !important;\r\n      font-size: 12px !important;\r\n\r\n      z-index: 999999 !important;\r\n      pointer-events: auto !important;\r\n    }\r\n\r\n    \/* In-place-Anzeige bewusst unterdr\u00fcckt: der offene Tooltip wird per JS an\r\n       <body> portaliert (.tip-portal). So kann ihn kein Panel mehr verdecken. *\/\r\n    .avdemb-t18pl .tip.open .tip-text {\r\n      display: none !important;\r\n    }\r\n\r\n    .avdemb-t18pl .tip .tip-text::before {\r\n      display: none !important;\r\n    }\r\n\r\n    \/* Zero-CTA: umbrechen statt \u00fcberlaufen *\/\r\n    .avdemb-t18pl .zero-cta {\r\n      flex-wrap: wrap;\r\n      gap: 16px;\r\n    }\r\n\r\n    \/* Slider-Panel: Innenabstand kompakter *\/\r\n    .avdemb-t18pl .slider-section {\r\n      padding: 16px;\r\n    }\r\n\r\n    \/* Delta-Banner Subtext: besser lesbar auf kleinen Screens *\/\r\n    .avdemb-t18pl .delta-sub {\r\n      font-size: 12px;\r\n    }\r\n\r\n    \/* CTA-Button Text: Mobile-Variante einblenden *\/\r\n    .avdemb-t18pl .cta-btn-desktop { display: none; }\r\n    .avdemb-t18pl .cta-btn-mobile { display: inline; }\r\n\r\n    \/* CTA-Box mobil kompakter *\/\r\n    .avdemb-t18pl #cta-kasten > div {\r\n      padding: 20px !important;\r\n    }\r\n\r\n    \/* CTA-Button: volle Breite auf Mobile \u2192 sauberer Umbruch *\/\r\n    .avdemb-t18pl #cta-kasten .button--primary,\r\n    .avdemb-t18pl #cta-kasten a.button--primary {\r\n      width: 100% !important;\r\n      max-width: 100%;\r\n      text-align: center;\r\n      white-space: normal !important;\r\n      overflow-wrap: anywhere;\r\n      line-height: 1.35 !important;\r\n      padding: 14px 16px !important;\r\n      box-sizing: border-box;\r\n    }\r\n  }\r\n\r\n  \/* \u2500\u2500 Mobile Chart Tap-to-Expand \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n     Nur sichtbar auf Touch-Ger\u00e4ten \/ kleinen Screens.\r\n     Pinch-Zoom wird NICHT verwendet (fehleranf\u00e4llig in WordPress).\r\n     Stattdessen: Tap \u2192 Overlay \u2192 Chart neu rendern \u2192 X \/ au\u00dfen schlie\u00dfen.\r\n  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n\r\n  \/* Wrapper um jeden Chart-Container *\/\r\n  .avdemb-t18pl .chart-tap-wrapper {\r\n    position: relative;\r\n    cursor: pointer;\r\n    -webkit-tap-highlight-color: transparent;\r\n  }\r\n\r\n  \/* Puls-Hint Badge: NUR auf Mobile sichtbar *\/\r\n  .avdemb-t18pl .chart-tap-hint {\r\n    display: none;\r\n  }\r\n\r\n  @media (max-width: 768px) {\r\n    .avdemb-t18pl .chart-tap-hint {\r\n      display: flex;\r\n      align-items: center;\r\n      gap: 5px;\r\n      position: absolute;\r\n      bottom: 8px;\r\n      right: 8px;\r\n      background: rgba(38,145,255,0.80);\r\n      color: #fff;\r\n      font-size: 10px;\r\n      font-weight: 600;\r\n      padding: 4px 9px 4px 7px;\r\n      border-radius: 20px;\r\n      letter-spacing: 0.03em;\r\n      pointer-events: none;\r\n      z-index: 4;\r\n      backdrop-filter: blur(4px);\r\n      animation: kft18pl-tapHintPulse 2.4s ease-in-out infinite;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .avdemb-t18pl .chart-tap-hint svg {\r\n      flex-shrink: 0;\r\n      opacity: 0.95;\r\n    }\r\n\r\n    \/* Leichter Tap-Effekt auf dem Wrapper *\/\r\n    .avdemb-t18pl .chart-tap-wrapper:active::after {\r\n      content: '';\r\n      position: absolute;\r\n      inset: 0;\r\n      background: rgba(38,145,255,0.06);\r\n      border-radius: 8px;\r\n      pointer-events: none;\r\n      z-index: 3;\r\n    }\r\n  }\r\n\r\n  @keyframes kft18pl-tapHintPulse {\r\n    0%, 100% { opacity: 1; transform: scale(1); }\r\n    50%       { opacity: 0.70; transform: scale(0.97); }\r\n  }\r\n\r\n  \/* \u2500\u2500 Overlay Backdrop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl #chart-overlay {\r\n    display: none;\r\n    position: fixed;\r\n    inset: 0;\r\n    z-index: 9999;\r\n    background: rgba(10,20,40,0.72);\r\n    backdrop-filter: blur(6px);\r\n    -webkit-backdrop-filter: blur(6px);\r\n    align-items: center;\r\n    justify-content: center;\r\n    padding: 16px;\r\n    animation: kft18pl-overlayFadeIn 0.22s ease both;\r\n    overscroll-behavior: contain;\r\n    touch-action: none;\r\n  }\r\n\r\n  .avdemb-t18pl #chart-overlay.open {\r\n    display: flex;\r\n  }\r\n\r\n  @keyframes kft18pl-overlayFadeIn {\r\n    from { opacity: 0; }\r\n    to   { opacity: 1; }\r\n  }\r\n\r\n  \/* \u2500\u2500 Overlay Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .chart-overlay-card {\r\n    background: var(--surface);\r\n    border-radius: 16px;\r\n    box-shadow: 0 16px 48px rgba(38,145,255,0.30);\r\n    width: 100%;\r\n    max-width: 92vw;\r\n    max-height: 88vh;\r\n    display: flex;\r\n    flex-direction: column;\r\n    overflow: hidden;\r\n    animation: kft18pl-overlayCardIn 0.26s cubic-bezier(0.34,1.28,0.64,1) both;\r\n  }\r\n\r\n  @keyframes kft18pl-overlayCardIn {\r\n    from { opacity: 0; transform: scale(0.92) translateY(16px); }\r\n    to   { opacity: 1; transform: scale(1) translateY(0); }\r\n  }\r\n\r\n  .avdemb-t18pl .chart-overlay-header {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: space-between;\r\n    padding: 16px 18px 12px;\r\n    border-bottom: 1px solid var(--border);\r\n    flex-shrink: 0;\r\n  }\r\n\r\n  .avdemb-t18pl .chart-overlay-title {\r\n    font-size: 13px;\r\n    font-weight: 700;\r\n    color: var(--text);\r\n    line-height: 1.3;\r\n  }\r\n\r\n  .avdemb-t18pl .chart-overlay-sub {\r\n    font-size: 11px;\r\n    color: var(--muted);\r\n    margin-top: 2px;\r\n  }\r\n\r\n  .avdemb-t18pl .chart-overlay-close {\r\n    width: 32px;\r\n    height: 32px;\r\n    border-radius: 50%;\r\n    border: 1px solid var(--border);\r\n    background: var(--surface2);\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    cursor: pointer;\r\n    color: var(--text);\r\n    flex-shrink: 0;\r\n    margin-left: 12px;\r\n    transition: background 0.15s;\r\n    -webkit-tap-highlight-color: transparent;\r\n  }\r\n\r\n  .avdemb-t18pl .chart-overlay-close:hover { background: var(--border); }\r\n\r\n  .avdemb-t18pl .chart-overlay-body {\r\n    padding: 16px 16px 20px;\r\n    flex: 1;\r\n    overflow: hidden;\r\n    position: relative;\r\n  }\r\n\r\n  .avdemb-t18pl .chart-overlay-canvas-wrap {\r\n    position: relative;\r\n    width: 100%;\r\n    height: calc(88vh - 110px);\r\n    max-height: 420px;\r\n  }\r\n\r\n  \/* Legende im Overlay f\u00fcr Linien-Chart *\/\r\n  .avdemb-t18pl .chart-overlay-legend {\r\n    display: flex;\r\n    flex-wrap: wrap;\r\n    gap: 10px 14px;\r\n    padding: 0 16px 14px;\r\n    font-size: 11px;\r\n    flex-shrink: 0;\r\n  }\r\n\r\n  .avdemb-t18pl .chart-overlay-legend span {\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 5px;\r\n    color: var(--muted);\r\n  }\r\n\r\n  .avdemb-t18pl .chart-overlay-legend .leg-line {\r\n    width: 20px;\r\n    height: 3px;\r\n    border-radius: 2px;\r\n    display: inline-block;\r\n  }\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     WORDPRESS-DEFENSIVE OVERRIDES\r\n     \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n     Problem: Generische Klassennamen wie .field, .input-wrap, .form-note\r\n     kollidieren in WordPress mit Theme- oder Plugin-CSS (z.B. Contact-\r\n     Form-7, Gravity Forms, viele Themes nutzen .field f\u00fcr Formular\u00adfelder).\r\n     Wenn das Theme-CSS NACH unserem Inline-<style> geladen wird, gewinnt\r\n     es bei gleicher Spezifit\u00e4t und bricht das Layout (Input wird winzig,\r\n     Error-Text bricht daneben um statt darunter).\r\n\r\n     L\u00f6sung: Layout-kritische Regeln werden unter .tool-wrapper geschachtelt\r\n     (h\u00f6here Spezifit\u00e4t als jede einzelne Klasse) und mit !important\r\n     gesichert. Greift NUR innerhalb des Tools, \u00e4ndert sonst nichts.\r\n     \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n\r\n  \/* Konsistentes Box-Modell im gesamten Tool erzwingen *\/\r\n  .avdemb-t18pl .tool-wrapper,\r\n  .avdemb-t18pl .tool-wrapper *,\r\n  .avdemb-t18pl .tool-wrapper *::before,\r\n  .avdemb-t18pl .tool-wrapper *::after {\r\n    box-sizing: border-box;\r\n  }\r\n\r\n  \/* .field MUSS Spalten-Layout sein (Label oben, Input mittig, Note unten) *\/\r\n  .avdemb-t18pl .tool-wrapper .field {\r\n    display: flex !important;\r\n    flex-direction: column !important;\r\n    gap: 8px;\r\n    min-width: 0; \/* erlaubt Schrumpfen in Grid-Spalten, sonst overflow *\/\r\n  }\r\n\r\n  \/* .input-wrap als horizontaler Container f\u00fcr Input + Suffix *\/\r\n  .avdemb-t18pl .tool-wrapper .input-wrap {\r\n    display: flex !important;\r\n    align-items: center;\r\n    width: 100%;\r\n    min-width: 0;\r\n  }\r\n\r\n  \/* Input innerhalb .input-wrap: 100% Breite, transparent (Wrapper liefert Optik) *\/\r\n  .avdemb-t18pl .tool-wrapper .input-wrap .input {\r\n    width: 100% !important;\r\n    min-width: 0 !important;\r\n    flex: 1 1 auto !important;\r\n    background: transparent !important;\r\n    border: none !important;\r\n    border-radius: 0 !important;\r\n    box-shadow: none !important;\r\n    height: auto !important; \/* Styleguide setzt height:2em fix - wir wollen padding-basiert *\/\r\n    padding: 10px 0 !important;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-wrapper .input-wrap .input:focus,\r\n  .avdemb-t18pl .tool-wrapper .input-wrap .input:hover {\r\n    outline: none !important;\r\n    box-shadow: none !important;\r\n    background: transparent !important;\r\n    border: none !important;\r\n  }\r\n\r\n  \/* Validierungs-Icon vom Styleguide unterdr\u00fccken (.input--invalid macht background-image) *\/\r\n  .avdemb-t18pl .tool-wrapper .input-wrap .input.input--invalid,\r\n  .avdemb-t18pl .tool-wrapper .input-wrap .input:invalid {\r\n    background-image: none !important;\r\n    padding-right: 0 !important;\r\n  }\r\n\r\n  \/* .form-note: standardm\u00e4\u00dfig versteckt, nur mit .show sichtbar (block, volle Breite) *\/\r\n  .avdemb-t18pl .tool-wrapper .form-note {\r\n    display: none !important;\r\n    position: static !important; \/* Styleguide setzt position:relative \u2014 hier nicht n\u00f6tig *\/\r\n    width: 100%;\r\n    margin-bottom: 0;\r\n  }\r\n\r\n  .avdemb-t18pl .tool-wrapper .form-note.show {\r\n    display: block !important;\r\n  }\r\n\r\n  \/* Grid-Items d\u00fcrfen schrumpfen (default min-width:auto verhindert das) *\/\r\n  .avdemb-t18pl .tool-wrapper [style*=\"grid-template-columns\"] > * {\r\n    min-width: 0;\r\n  }\r\n\r\n  \/* Tool-Panel als Block sicherstellen (manche Themes machen alles inline) *\/\r\n  .avdemb-t18pl .tool-wrapper .tool-panel {\r\n    display: block !important;\r\n    width: 100%;\r\n  }\r\n\r\n  \/* Desktop: feste H\u00f6he f\u00fcr Bar-Chart Wrapper, damit Balken gut sichtbar sind.\r\n     Ohne diese Regel w\u00fcrde Chart.js mit maintainAspectRatio:false auf die\r\n     Canvas-Default-H\u00f6he (55px) zur\u00fcckfallen und die Balken w\u00e4ren kaum erkennbar. *\/\r\n  @media (min-width: 769px) {\r\n    .avdemb-t18pl #barChartTapWrapper {\r\n      position: relative;\r\n      width: 100%;\r\n      height: 280px;\r\n      min-height: 280px;\r\n    }\r\n  }\r\n\r\n  \/* Mobile: feste H\u00f6he auf Chart-Wrapper-Hierarchie (alle Eltern + Wrapper).\r\n     Chart.js mit responsive:true + maintainAspectRatio:false braucht\r\n     Parent-Hierarchie mit fester H\u00f6he. *\/\r\n  @media (max-width: 768px) {\r\n    .avdemb-t18pl #barChartTapWrapper {\r\n      position: relative !important;\r\n      width: 100% !important;\r\n      height: 280px !important;\r\n      min-height: 280px !important;\r\n      overflow: visible !important;\r\n    }\r\n\r\n    .avdemb-t18pl #verlaufChart-outer {\r\n      position: relative !important;\r\n      width: 100% !important;\r\n      height: 280px !important;\r\n      min-height: 280px !important;\r\n    }\r\n\r\n    .avdemb-t18pl #verlaufChart-outer .chart-tap-wrapper {\r\n      width: 100% !important;\r\n      height: 100% !important;\r\n      position: relative !important;\r\n    }\r\n\r\n    .avdemb-t18pl #rentenBarChart,\r\n    .avdemb-t18pl #verlaufChart {\r\n      display: block !important;\r\n      max-width: 100% !important;\r\n    }\r\n  }\r\n\r\n  \/* Inflation \/ Kaufkraft (real) ----------------------------------- *\/\r\n  .avdemb-t18pl .card-real { font-size: 12px; font-weight: 600; color: var(--muted); margin: 3px 0 8px; }\r\n  .avdemb-t18pl .delta-real { font-size: 12px; color: rgba(255,255,255,0.85); margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(255,255,255,0.25); }\r\n  .avdemb-t18pl .tool-wrapper:not(.kaufkraft-an) .real-zeile { display: none !important; }\r\n  \/* Netto (nach Steuer) \u2013 nur sichtbar, wenn Netto-Toggle aktiv ----- *\/\r\n  .avdemb-t18pl .tool-wrapper:not(.netto-an) .netto-zeile { display: none !important; }\r\n  \/* Brutto\/Netto-Umschalter f\u00fcr die Diagramme (nur im Netto-Modus sichtbar) *\/\r\n  .avdemb-t18pl .chart-bn-toggle { display: flex; gap: 4px; background: var(--surface2); border: 1px solid var(--border); border-radius: 8px; padding: 3px; flex-shrink: 0; }\r\n  .avdemb-t18pl .chart-bn { border: none; background: transparent; border-radius: 6px; padding: 4px 12px; font-size: 11px; font-weight: 600; color: var(--muted); cursor: pointer; font-family: inherit; transition: all .15s; }\r\n  .avdemb-t18pl .chart-bn.sel { background: #2691ff; color: #fff; }\r\n  .avdemb-t18pl .chart-bn:focus-visible { outline: 3px solid #2691ff; outline-offset: 2px; }\r\n  .avdemb-t18pl .card-netto { font-size: 12px; font-weight: 700; color: #1D9E75; margin: 2px 0 8px; }\r\n  \/* Ergebnis-Layout: Netto-Kopf prominent, Brutto zweitrangig *\/\r\n  .avdemb-t18pl .tool-wrapper.netto-an .brutto-full { display: none; }\r\n  .avdemb-t18pl .brutto-card-compact { font-size: 12px; color: var(--muted); font-weight: 400; margin: 2px 0 8px; }\r\n  .avdemb-t18pl .tool-wrapper.netto-an .brutto-only { display: none !important; }\r\n  .avdemb-t18pl .delta-banner .brutto-compact { margin-top: 14px; padding-top: 12px; border-top: 1px solid rgba(255,255,255,.25); font-size: 12.5px; color: #fff; }\r\n  .avdemb-t18pl .delta-banner.gs-mode .netto-zeile { display: none !important; }\r\n  .avdemb-t18pl .delta-banner.gs-mode .brutto-full { display: block !important; }\r\n  \/* Netto: gef\u00fchrte Auswahl-Karten (gesetzl.\/Betriebsrente kennen vs. aus Einkommen sch\u00e4tzen) *\/\r\n  .avdemb-t18pl .netto-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 14px; }\r\n  .avdemb-t18pl .netto-card { position: relative; background: #fff; border: 2px solid var(--border); border-radius: 12px; padding: 16px 14px; cursor: pointer; text-align: center; transition: border-color .15s, box-shadow .15s; }\r\n  .avdemb-t18pl .netto-card:hover { border-color: var(--accent); box-shadow: 0 4px 14px rgba(38,145,255,.12); }\r\n  .avdemb-t18pl .netto-card.sel { border-color: var(--accent); background: #f5faff; box-shadow: 0 4px 16px rgba(38,145,255,.18); }\r\n  .avdemb-t18pl .netto-card.sel::after { content: '\u2713'; position: absolute; top: 6px; right: 9px; color: var(--accent); font-weight: 700; }\r\n  .avdemb-t18pl .netto-card:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }\r\n  .avdemb-t18pl .netto-card .nc-ic { font-size: 26px; line-height: 1; margin-bottom: 6px; }\r\n  .avdemb-t18pl .netto-card .nc-t { font-size: 13px; font-weight: 700; margin-bottom: 3px; color: var(--text); }\r\n  .avdemb-t18pl .netto-card .nc-s { font-size: 11px; color: var(--muted); line-height: 1.4; }\r\n  .avdemb-t18pl .netto-erkl { display: flex; gap: 9px; background: #eaf4ff; border: 1px solid #bcdcff; border-radius: 8px; padding: 11px 13px; margin-bottom: 12px; font-size: 12px; color: #274a6b; line-height: 1.5; }\r\n  .avdemb-t18pl .netto-erkl b { color: #093967; }\r\n  .avdemb-t18pl .netto-ptype { display: flex; gap: 6px; flex-wrap: wrap; }\r\n  .avdemb-t18pl .netto-pt { padding: 6px 12px; border-radius: 20px; font-size: 12px; font-weight: 600; border: 1px solid var(--border); background: #fff; color: var(--muted); cursor: pointer; }\r\n  .avdemb-t18pl .netto-pt.sel { background: var(--accent); border-color: var(--accent); color: #fff; }\r\n  @media (max-width: 520px) { .avdemb-t18pl .netto-cards { grid-template-columns: 1fr; } }\r\n  .avdemb-t18pl .kk-switch { position: relative; display: inline-block; width: 40px; height: 22px; flex-shrink: 0; }\r\n  .avdemb-t18pl .kk-switch input { opacity: 0; width: 0; height: 0; }\r\n  .avdemb-t18pl .kk-slider-track { position: absolute; cursor: pointer; inset: 0; background: var(--border); border-radius: 22px; transition: background .2s; }\r\n  .avdemb-t18pl .kk-slider-track::before { content: ''; position: absolute; height: 16px; width: 16px; left: 3px; bottom: 3px; background: #fff; border-radius: 50%; transition: transform .2s; box-shadow: 0 1px 3px rgba(0,0,0,0.2); }\r\n  .avdemb-t18pl .kk-switch input:checked + .kk-slider-track { background: #E8327A; }\r\n  .avdemb-t18pl .kk-switch input:checked + .kk-slider-track::before { transform: translateX(18px); }\r\n\r\n  \/* \u2500\u2500 Interaktiver Eingabe-Wizard (Tool 1.3 \u00b7 5.2-Muster) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .wiz { background: var(--surface); border: 1px solid var(--border); border-radius: 16px; padding: 28px 28px 22px; box-shadow: 0 4px 20px rgba(38,145,255,0.10); margin-bottom: 16px; }\r\n  .avdemb-t18pl .wiz-progress { height: 6px; border-radius: 99px; background: var(--surface2); overflow: hidden; margin-bottom: 10px; }\r\n  .avdemb-t18pl .wiz-progress-bar { height: 100%; background: linear-gradient(90deg,#2691ff,#56a9ff); border-radius: 99px; transition: width .4s cubic-bezier(.4,0,.2,1); }\r\n  .avdemb-t18pl .wiz-stepinfo { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 18px; }\r\n  .avdemb-t18pl .wiz-step { display: none; animation: kft18pl-wizIn .35s ease both; }\r\n  .avdemb-t18pl .wiz-step.active { display: block; }\r\n  @keyframes kft18pl-wizIn { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: translateX(0); } }\r\n  .avdemb-t18pl .wiz-q { font-size: clamp(20px,3vw,26px); font-weight: 700; color: var(--text); line-height: 1.25; margin-bottom: 6px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }\r\n  .avdemb-t18pl .wiz-help { font-size: 13px; color: var(--muted); line-height: 1.5; margin-bottom: 20px; }\r\n  .avdemb-t18pl .wiz-sub { font-size: 12px; font-weight: 700; color: var(--text); margin: 22px 0 8px; }\r\n  .avdemb-t18pl .wiz-info { display: flex; gap: 9px; background: #eaf4ff; border: 1px solid #bcdcff; border-radius: 8px; padding: 11px 13px; margin: 16px 0 4px; font-size: 12px; color: #274a6b; line-height: 1.55; }\r\n  .avdemb-t18pl .wiz-info b { color: #093967; }\r\n  .avdemb-t18pl .wiz-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }\r\n  .avdemb-t18pl .wiz-tiles-3 { grid-template-columns: repeat(3, 1fr); }\r\n  .avdemb-t18pl .wiz-tile { text-align: left; background: var(--surface2); border: 2px solid var(--border); border-radius: 12px; padding: 16px; cursor: pointer; transition: border-color .15s, box-shadow .15s, transform .12s; font-family: inherit; }\r\n  .avdemb-t18pl .wiz-tile:hover { border-color: #2691ff; transform: translateY(-2px); box-shadow: 0 6px 16px rgba(38,145,255,.12); }\r\n  .avdemb-t18pl .wiz-tile.sel { border-color: #2691ff; background: #f5faff; box-shadow: 0 4px 14px rgba(38,145,255,.16); }\r\n  .avdemb-t18pl .wiz-tile:focus-visible { outline: 3px solid #2691ff; outline-offset: 2px; }\r\n  .avdemb-t18pl .wiz-tile-v { font-size: 18px; font-weight: 700; color: var(--text); }\r\n  .avdemb-t18pl .wiz-tile-s { font-size: 12px; color: var(--muted); margin-top: 2px; }\r\n  .avdemb-t18pl .wiz-nav { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-top: 26px; }\r\n  .avdemb-t18pl .wiz-back { background: transparent; border: 1px solid var(--border); border-radius: 10px; padding: 11px 18px; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; font-family: inherit; transition: all .15s; }\r\n  .avdemb-t18pl .wiz-back:hover { border-color: var(--muted); color: var(--text); }\r\n  .avdemb-t18pl .wiz-next { background: #E8327A; border: none; border-radius: 10px; padding: 13px 26px; font-size: 15px; font-weight: 700; color: #fff; cursor: pointer; font-family: inherit; transition: all .2s; box-shadow: 0 4px 14px rgba(232,50,122,.28); }\r\n  .avdemb-t18pl .wiz-next:hover { background: #C8305A; transform: translateY(-1px); box-shadow: 0 8px 22px rgba(232,50,122,.35); }\r\n  .avdemb-t18pl .wiz-back:focus-visible, .avdemb-t18pl .wiz-next:focus-visible { outline: 3px solid #093967; outline-offset: 2px; }\r\n  @media (max-width: 480px) { .avdemb-t18pl .wiz-tiles, .avdemb-t18pl .wiz-tiles-3 { grid-template-columns: 1fr; } .avdemb-t18pl .wiz { padding: 22px 18px 18px; } .avdemb-t18pl .wiz-next { flex: 1; } }\r\n  \/* Compact-Modus: nach \u201eErgebnis berechnen\" alle Eingaben auf einen Blick *\/\r\n  .avdemb-t18pl .wiz-compact-head { display: none; }\r\n  .avdemb-t18pl .wiz.compact .wiz-compact-head { display: block; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; }\r\n  .avdemb-t18pl .wiz.compact .wiz-progress, .avdemb-t18pl .wiz.compact .wiz-stepinfo, .avdemb-t18pl .wiz.compact .wiz-nav { display: none; }\r\n  .avdemb-t18pl .wiz.compact .wiz-step { display: block; animation: none; }\r\n  .avdemb-t18pl .wiz.compact .wiz-step + .wiz-step { border-top: 1px solid var(--border); padding-top: 14px; margin-top: 14px; }\r\n  .avdemb-t18pl .wiz.compact .wiz-q { font-size: 14px; font-weight: 700; margin-bottom: 10px; }\r\n  .avdemb-t18pl .wiz.compact .wiz-help, .avdemb-t18pl .wiz.compact .wiz-info { display: none; }\r\n<\/style>\r\n\r\n<div class=\"tool-wrapper kaufkraft-an\">\r\n\r\n  <!-- Header (1.8: blaue Box + Chip entfernt; Datum im Vormerken-Button) -->\r\n  <div class=\"header\">\r\n    <div style=\"display:flex;justify-content:space-between;align-items:flex-start;gap:20px;flex-wrap:wrap;\">\r\n      <h1 style=\"flex:1;min-width:240px;margin:0;\">Riester behalten \u2013 oder zum <span>Altersvorsorgedepot<\/span> wechseln?<\/h1>\r\n      <a href=\"#cta-kasten\" onclick=\"var c=document.getElementById('cta-kasten');if(c){event.preventDefault();c.scrollIntoView({behavior:'smooth',block:'start'});}\" style=\"flex-shrink:0;display:inline-flex;flex-direction:column;align-items:flex-start;gap:2px;background:#ffffff;color:#2691ff;border:1.5px solid #2691ff;border-radius:10px;padding:10px 17px;text-decoration:none;cursor:pointer;\">\r\n        <span style=\"font-size:14px;font-weight:700;display:flex;align-items:center;gap:6px;\">\ud83d\udd14 Vormerken<\/span>\r\n        <span style=\"font-size:11.5px;font-weight:600;color:#0d63c4;\">AVD-Start: 01.01.2027<\/span>\r\n      <\/a>\r\n    <\/div>\r\n    <p class=\"subtitle\">Vergleiche dein Riester-Guthaben mit dem Altersvorsorgedepot und einem ETF-Sparplan \u2013 neutral, transparent, ohne Empfehlung.<\/p>\r\n  <\/div>\r\n\r\n  <!-- Eingaben -->\r\n  <div class=\"wiz\" id=\"wiz\">\r\n    <div class=\"wiz-compact-head\">Deine Eingaben \u2013 jederzeit anpassbar<\/div>\r\n    <div class=\"wiz-progress\"><div class=\"wiz-progress-bar\" id=\"wiz-bar\" style=\"width:20%;\"><\/div><\/div>\r\n    <div class=\"wiz-stepinfo\"><span id=\"wiz-stepnum\">Schritt 1<\/span> von 5<\/div>\r\n\r\n    <!-- Schritt 1: Zu dir -->\r\n    <div class=\"wiz-step active\" data-step=\"1\">\r\n      <div class=\"wiz-q\">Wie alt bist du, und wann m\u00f6chtest du in Rente gehen?<\/div>\r\n      <div class=\"wiz-help\">Daraus ergibt sich deine Ansparphase. Renteneintritt fr\u00fchestens mit 65, sp\u00e4testens mit 70.<\/div>\r\n\r\n      <div class=\"wiz-sub\">Dein Alter\r\n        <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 G\u00fcltige Eingabe: 16\u201366 Jahre<br>\u2022 Renteneintrittsalter einstellbar (65 bis 70)<\/span><\/span>\r\n      <\/div>\r\n      <div class=\"input-wrap\" style=\"max-width:220px;\">\r\n        <input type=\"number\" id=\"alter\" min=\"16\" max=\"66\" value=\"30\" placeholder=\"z.B. 35\"\r\n          class=\"input\"\r\n          oninput=\"const raw=(this.value||'').trim();const v=parseInt(this.value);const e=document.getElementById('alter-error');if(raw!==''&#038;&#038;(isNaN(v)||v<16||v>parseInt(this.max))){this.classList.add('input--invalid');e.classList.add('show');}else{this.classList.remove('input--invalid');e.classList.remove('show');}\">\r\n      <\/div>\r\n      <span class=\"form-note form-note--error\" id=\"alter-error\">Bitte gib ein Alter unter dem Renteneintrittsalter ein<\/span>\r\n\r\n      <div class=\"wiz-sub\">Renteneintrittsalter\r\n        <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Alter, ab dem die Auszahlung beginnt (Ende der Ansparphase)<br>\u2022 Fr\u00fchestens mit 65, sp\u00e4testens mit 70<br>\u2022 Standard: 67 (Regelaltersgrenze)<\/span><\/span>\r\n      <\/div>\r\n      <div style=\"display:flex;align-items:center;gap:12px;margin-top:8px;\">\r\n        <input type=\"range\" id=\"renteneintritt\" min=\"65\" max=\"70\" value=\"67\" step=\"1\" oninput=\"updateRenteneintritt(this.value)\" aria-label=\"Renteneintrittsalter\" aria-valuetext=\"67 Jahre\" style=\"flex:1;\">\r\n        <span style=\"font-size:14px;font-weight:700;color:var(--accent);min-width:64px;text-align:right;\" id=\"renteneintrittDisplay\">67 Jahre<\/span>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- Schritt 2: Riester \u00fcbertragen? -->\r\n    <div class=\"wiz-step\" data-step=\"2\">\r\n      <div class=\"wiz-q\">Hast du eine Riester-Rente, und m\u00f6chtest du die F\u00f6rderung wechseln?<\/div>\r\n      <div class=\"wiz-help\">Bestehendes Riester-Guthaben kann per freiwilligem Wechsel ins Altersvorsorgedepot \u00fcberf\u00fchrt werden. Es geht dann in allen Varianten als Startkapital in den Vergleich ein und wird mitverzinst. Ein Wechsel ins Altersvorsorgedepot ist f\u00f6rderunsch\u00e4dlich \u2013 deine Zulagen bleiben erhalten. Anders als ein Riester-Vertrag mit Beitragsgarantie ist das Altersvorsorgedepot ohne Garantie (mehr Renditechance, aber Kapitalmarktrisiko); ob ein Wechsel f\u00fcr dich passt, h\u00e4ngt von deinem Vertrag ab.<\/div>\r\n      <div class=\"wiz-tiles\">\r\n        <button type=\"button\" class=\"wiz-tile\" data-wiz=\"riester\" data-val=\"ja\"><div class=\"wiz-tile-v\">Ja, F\u00f6rderung wechseln<\/div><div class=\"wiz-tile-s\">Riester-Guthaben einbringen<\/div><\/button>\r\n        <button type=\"button\" class=\"wiz-tile sel\" data-wiz=\"riester\" data-val=\"nein\"><div class=\"wiz-tile-v\">Nein \/ kein Riester<\/div><div class=\"wiz-tile-s\">ohne Startkapital starten<\/div><\/button>\r\n      <\/div>\r\n      <div id=\"riester-betrag\" style=\"display:none;margin-top:18px;\">\r\n        <div class=\"wiz-sub\">\u00dcbertragbares Verm\u00f6gen\r\n          <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Vorhandenes Kapital, das du mitbringst \u2013 z. B. dein bestehendes Riester-Guthaben<br>\u2022 Kann per freiwilligem Wechsel ins Altersvorsorgedepot \u00fcberf\u00fchrt werden<br>\u2022 Geht in allen Varianten als Startkapital in den Vergleich ein und wird mitverzinst<\/span><\/span>\r\n        <\/div>\r\n        <div class=\"input-wrap\" style=\"max-width:260px;\">\r\n          <input type=\"text\" inputmode=\"numeric\" id=\"guthaben\" value=\"0\" placeholder=\"z.B. 15000\" class=\"input\">\r\n          <span class=\"currency-suffix\">\u20ac<\/span>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- Schritt 3: Monatliche Einzahlung -->\r\n    <div class=\"wiz-step\" data-step=\"3\">\r\n      <div class=\"wiz-q\">Wie viel zahlst du monatlich ein?\r\n        <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 50% auf erste 360 \u20ac\/Jahr \u2192 max. 180 \u20ac Grundzulage<br>\u2022 25% auf weitere 1.440 \u20ac\/Jahr \u2192 max. 360 \u20ac Grundzulage<br>\u2022 Max. Einzahlung: 570 \u20ac\/Monat<\/span><\/span>\r\n      <\/div>\r\n      <div class=\"wiz-help\">W\u00e4hle einen Richtwert oder stelle den Regler frei ein.<\/div>\r\n      <div class=\"wiz-tiles wiz-tiles-3\">\r\n        <button type=\"button\" class=\"wiz-tile\" data-wiz=\"einz\" data-val=\"50\"><div class=\"wiz-tile-v\">50 \u20ac<\/div><div class=\"wiz-tile-s\">Einstieg<\/div><\/button>\r\n        <button type=\"button\" class=\"wiz-tile sel\" data-wiz=\"einz\" data-val=\"150\"><div class=\"wiz-tile-v\">150 \u20ac<\/div><div class=\"wiz-tile-s\">volle F\u00f6rderung<\/div><\/button>\r\n        <button type=\"button\" class=\"wiz-tile\" data-wiz=\"einz\" data-val=\"570\"><div class=\"wiz-tile-v\">570 \u20ac<\/div><div class=\"wiz-tile-s\">Maximalbetrag<\/div><\/button>\r\n      <\/div>\r\n      <div style=\"display:flex;justify-content:flex-end;align-items:center;margin-top:14px;\">\r\n        <div style=\"display:flex;align-items:center;background:var(--surface2);border:1px solid var(--border);border-radius:8px;padding:0 8px;min-width:96px;\">\r\n          <input type=\"number\" id=\"einzahlung\" min=\"0\" max=\"570\" value=\"150\" placeholder=\"150\"\r\n            class=\"input\"\r\n            oninput=\"syncEinzahlung('input', this.value)\"\r\n            style=\"background:transparent;border:none;padding:6px 0;width:100%;font-size:13px;font-weight:600;color:var(--text);text-align:right;\">\r\n          <span class=\"currency-suffix\" style=\"font-size:13px;font-weight:600;\">\u20ac<\/span>\r\n        <\/div>\r\n      <\/div>\r\n      <input type=\"range\" id=\"einzahlung-slider\" min=\"0\" max=\"570\" value=\"150\" step=\"5\"\r\n        oninput=\"syncEinzahlung('slider', this.value)\" aria-label=\"Monatliche Einzahlung in Euro (Schieberegler)\"\r\n        style=\"width:100%;margin-top:8px;\">\r\n      <div style=\"position:relative;height:14px;font-size:10px;color:var(--muted);margin-top:2px;\">\r\n        <span style=\"position:absolute;left:0;\">0 \u20ac<\/span><span style=\"position:absolute;left:26.3%;transform:translateX(-50%);\">150 \u20ac<\/span><span style=\"position:absolute;right:0;\">570 \u20ac max.<\/span>\r\n      <\/div>\r\n      <span class=\"form-note form-note--warning\" id=\"einzahlung-warning\" style=\"font-size:10px;\">Unter 10 \u20ac\/Monat beim Altersvorsorgedepot: keine Zulagen und kein Berufseinsteigerbonus (eine wieder eingezahlte Steuererstattung z\u00e4hlt bei den Zulagen mit)<\/span>\r\n      <span class=\"form-note form-note--info\"    id=\"einzahlung-info\"    style=\"font-size:10px;\">Max. F\u00f6rderung ab 150 \u20ac\/Monat<\/span>\r\n      <span class=\"form-note form-note--error\"   id=\"einzahlung-max\"     style=\"font-size:10px;\">Max. 570 \u20ac\/Monat<\/span>\r\n      <div class=\"wiz-info\"><span aria-hidden=\"true\">\ud83d\udca1<\/span><span><b>So funktioniert die F\u00f6rderung:<\/b> Der Staat gibt auf die ersten 360 \u20ac\/Jahr 50 % dazu, auf die n\u00e4chsten 1.440 \u20ac\/Jahr 25 %. Ab <b>150 \u20ac\/Monat (1.800 \u20ac\/Jahr)<\/b> nutzt du die volle Grundzulage. Unter 10 \u20ac\/Monat gibt es beim Altersvorsorgedepot keine Zulagen und keinen Berufseinsteigerbonus (eine wieder eingezahlte Steuererstattung z\u00e4hlt bei den Zulagen mit). Einzahlen kannst du bis 570 \u20ac\/Monat \u2013 gef\u00f6rdert wird allerdings nur bis 1.800 \u20ac\/Jahr.<\/span><\/div>\r\n    <\/div>\r\n\r\n    <!-- Schritt 4: Kinder -->\r\n    <div class=\"wiz-step\" data-step=\"4\">\r\n      <div class=\"wiz-q\">Hast du Kinder \u2013 oder planst du welche?\r\n        <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 300 \u20ac\/Kind\/Jahr Kinderzulage<br>\u2022 Ab 25 \u20ac\/Monat voll erreichbar<br>\u2022 Voraussetzung: Kindergeldberechtigung<\/span><\/span>\r\n      <\/div>\r\n      <div class=\"wiz-help\">F\u00fcr jedes kindergeldberechtigte Kind gibt es eine zus\u00e4tzliche Zulage. Gib die Geburtsjahre ein (auch geplante) \u2013 daraus ergibt sich, wie lange die Zulage l\u00e4uft.<\/div>\r\n      <div style=\"margin-top:16px;padding-top:14px;border-top:1px solid var(--border);display:flex;align-items:center;gap:16px;flex-wrap:wrap;\">\r\n        <span style=\"font-size:13px;color:var(--muted);white-space:nowrap;\">Anzahl Kinder<\/span>\r\n        <div style=\"display:flex;gap:6px;flex-wrap:wrap;\">\r\n          <button type=\"button\" onclick=\"setChildren(0)\" class=\"kinder-btn active\" id=\"kBtn0\">0<\/button>\r\n          <button type=\"button\" onclick=\"setChildren(1)\" class=\"kinder-btn\" id=\"kBtn1\">1<\/button>\r\n          <button type=\"button\" onclick=\"setChildren(2)\" class=\"kinder-btn\" id=\"kBtn2\">2<\/button>\r\n          <button type=\"button\" onclick=\"setChildren(3)\" class=\"kinder-btn\" id=\"kBtn3\">3<\/button>\r\n          <button type=\"button\" onclick=\"setChildren(4)\" class=\"kinder-btn\" id=\"kBtn4\">4<\/button>\r\n          <button type=\"button\" onclick=\"setChildren(5)\" class=\"kinder-btn\" id=\"kBtn5\">5<\/button>\r\n        <\/div>\r\n        <div id=\"children-fields\" style=\"display:flex;flex-wrap:wrap;gap:10px;margin-top:8px;width:100%;\"><\/div>\r\n      <\/div>\r\n      <div class=\"wiz-info\"><span aria-hidden=\"true\">\ud83d\udca1<\/span><span><b>Kinderzulage:<\/b> Im Altersvorsorgedepot gibt es einheitlich <b>300 \u20ac\/Jahr pro Kind<\/b> \u2013 unabh\u00e4ngig vom Geburtsjahr. (Bei Riester sind es 300 \u20ac\/Jahr f\u00fcr ab 2008 geborene und 185 \u20ac\/Jahr f\u00fcr vorher geborene Kinder.) Voraussetzung ist die Kindergeldberechtigung \u2013 sie kann i. d. R. bis zum 25. Geburtstag laufen.<\/span><\/div>\r\n    <\/div>\r\n\r\n    <!-- Schritt 5 (Renditeszenario) entfernt:\r\n         Der Szenario-Picker (Buttons + Regler) lebt jetzt im Ergebnis \u00fcber dem Hero,\r\n         damit er keine Pflicht-Entscheidung mehr vor der Berechnung ist (Marketing-Feedback).\r\n         Der Inflation-\/Kaufkraft-Toggle ist ins Netto-Panel nach dem Wizard gewandert. -->\r\n\r\n    <!-- Navigation -->\r\n    <div class=\"wiz-nav\">\r\n      <button type=\"button\" class=\"wiz-back\" id=\"wiz-back\" style=\"visibility:hidden;\">\u2190 Zur\u00fcck<\/button>\r\n      <button type=\"button\" class=\"wiz-next\" id=\"wiz-next\">Weiter \u2192<\/button>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Netto-Toggle (nach Steuer) \u2013 Struktur wie Tool 1.2, als eigener Block nach dem Wizard -->\r\n  <div class=\"tool-panel\" style=\"margin-bottom:16px;\">\r\n    <div>\r\n      <!-- Inflation-\/Kaufkraft-Toggle (aus Wizard-Schritt 5 hierher verschoben) -->\r\n      <div style=\"display:flex;align-items:center;gap:10px;\">\r\n        <label class=\"kk-switch\"><input type=\"checkbox\" id=\"kaufkraft-toggle\" checked onchange=\"toggleKaufkraft(this)\" aria-label=\"Inflation ber\u00fccksichtigen (Kaufkraft in heutigem Wert)\"><span class=\"kk-slider-track\"><\/span><\/label>\r\n        <span style=\"font-size:13px;font-weight:600;color:var(--text);line-height:1.4;\">Inflation ber\u00fccksichtigen <span style=\"font-weight:400;color:var(--muted);\">(2 % p. a.)<\/span><span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Zeigt zus\u00e4tzlich, was die zuk\u00fcnftigen Betr\u00e4ge in heutiger Kaufkraft wert sind<br>\u2022 Annahme: 2 % Inflation pro Jahr (langfristiges Ziel der EZB)<br>\u2022 Abgezinst auf den Renteneintritt \u2013 die Rangfolge der Produkte \u00e4ndert sich dadurch nicht<\/span><\/span><\/span>\r\n      <\/div>\r\n      <div style=\"border-top:1px solid var(--border);margin:14px 0;\"><\/div>\r\n      <div style=\"display:flex;align-items:center;gap:10px;\">\r\n        <label class=\"kk-switch\"><input type=\"checkbox\" id=\"netto-toggle\" onchange=\"toggleNetto(this)\" aria-label=\"Nettobetrag nach Steuer berechnen\"><span class=\"kk-slider-track\"><\/span><\/label>\r\n        <span style=\"font-size:13px;font-weight:600;color:var(--text);line-height:1.4;\">Nettobetrag berechnen <span style=\"font-weight:400;color:var(--muted);\">(vereinfachte Rechnung)<\/span><span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Riester &amp; AVD: nachgelagerte Besteuerung \u2013 die volle Rente wird im Alter mit deinem pers\u00f6nlichen Steuersatz versteuert<br>\u2022 ETF\/Fonds: Abgeltungsteuer (effektiv ~18,5 %) nur auf die Gewinne (inkl. 30 % Teilfreistellung), abz\u00fcglich Sparer-Pauschbetrag (1.000 \u20ac\/Jahr, 2.000 \u20ac bei Zusammenveranlagung)<br>\u2022 Vereinfachte Annahme \u2013 ersetzt keine Steuerberatung<\/span><\/span><\/span>\r\n      <\/div>\r\n      <div id=\"netto-optionen\" style=\"display:none;margin-top:14px;padding:14px;background:var(--surface2);border:1px solid var(--border);border-radius:10px;\">\r\n        <div style=\"font-size:12px;font-weight:700;color:var(--text);margin-bottom:6px;\">Weitere Alterseink\u00fcnfte <span id=\"steuer-stand\" style=\"font-weight:400;color:var(--muted);font-size:11px;\"><\/span><\/div>\r\n        <div style=\"font-size:11px;color:var(--muted);line-height:1.5;margin-bottom:12px;\">Riester &amp; AVD werden im Alter nachgelagert besteuert. Damit wir deinen Steuersatz realistisch sch\u00e4tzen, brauchen wir deine voraussichtlichen weiteren Alterseink\u00fcnfte. Wie m\u00f6chtest du sie angeben?<\/div>\r\n        <div class=\"netto-cards\">\r\n          <div class=\"netto-card\" id=\"netto-card-kenne\" tabindex=\"0\" role=\"button\" onclick=\"setNettoPfad('kenne')\" onkeypress=\"if(event.key==='Enter'||event.key===' ')setNettoPfad('kenne')\">\r\n            <div class=\"nc-ic\" aria-hidden=\"true\">\ud83d\udcc4<\/div>\r\n            <div class=\"nc-t\">Rentenbetr\u00e4ge bekannt<\/div>\r\n            <div class=\"nc-s\">Gesetzliche &amp; Betriebsrente eingeben<\/div>\r\n          <\/div>\r\n          <div class=\"netto-card\" id=\"netto-card-schaetz\" tabindex=\"0\" role=\"button\" onclick=\"setNettoPfad('schaetzen')\" onkeypress=\"if(event.key==='Enter'||event.key===' ')setNettoPfad('schaetzen')\">\r\n            <div class=\"nc-ic\" aria-hidden=\"true\">\ud83e\uddee<\/div>\r\n            <div class=\"nc-t\">Rentenbetr\u00e4ge unbekannt<\/div>\r\n            <div class=\"nc-s\">Aus Einkommen &amp; Beitragsjahren sch\u00e4tzen<\/div>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <div id=\"netto-felder\" style=\"display:none;\">\r\n          <!-- Sch\u00e4tz-Block (nur Pfad \u201esch\u00e4tzen\") -->\r\n          <div id=\"netto-schaetz-block\" style=\"display:none;\">\r\n            <div class=\"netto-erkl\"><span aria-hidden=\"true\">\ud83d\udca1<\/span><span><b>Warum dein Bruttojahreseinkommen?<\/b> Deine sp\u00e4tere gesetzliche Rente h\u00e4ngt vor allem davon ab, wie viel du im Vergleich zum Durchschnittsverdienst einzahlst. Aus deinem heutigen Einkommen und den Beitragsjahren sch\u00e4tzen wir deine Rentenpunkte \u2013 und daraus die voraussichtliche Rente.<\/span><\/div>\r\n            <div style=\"font-size:11px;color:#6c7a8a;margin-top:4px;margin-bottom:8px;\">Deine Angaben werden nicht gespeichert oder weitergegeben \u2013 die Berechnung l\u00e4uft nur in deinem Browser.<\/div>\r\n            <div style=\"display:flex;gap:12px;flex-wrap:wrap;\">\r\n              <div class=\"field\" style=\"margin-bottom:0;flex:1;min-width:150px;\">\r\n                <label style=\"font-size:12px;\">Brutto-Jahreseinkommen (heute)<\/label>\r\n                <div class=\"input-wrap\">\r\n                  <input type=\"text\" inputmode=\"numeric\" id=\"brutto-jahr\" value=\"45000\" placeholder=\"z.B. 45000\" class=\"input\" oninput=\"schaetzAusEinkommen()\" aria-label=\"Brutto-Jahreseinkommen in Euro\">\r\n                  <span class=\"currency-suffix\">\u20ac\/Jahr<\/span>\r\n                <\/div>\r\n              <\/div>\r\n              <div class=\"field\" id=\"erstattung-anlegen-feld\" style=\"margin-bottom:0;flex:1 1 100%;min-width:220px;\">\r\n                <label style=\"font-size:12px;display:flex;align-items:center;gap:10px;cursor:pointer;\">\r\n                  <input type=\"checkbox\" id=\"erstattung-anlegen\" checked onchange=\"toggleErstattungAnlegen(this)\" style=\"width:16px;height:16px;flex-shrink:0;\" aria-label=\"Steuererstattung wieder anlegen\">\r\n                  <span style=\"white-space:normal;\">Steuererstattung wieder anlegen<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 In den gef\u00f6rderten Vertrag darf die Erstattung nur flie\u00dfen, soweit die Einzahlungsgrenze von 6.840 \u20ac\/Jahr noch nicht ausgesch\u00f6pft ist<br>\u2022 Der Rest kann in einem normalen Fonds-\/ETF-Depot angelegt werden \u2013 dann werden nur die Gewinne besteuert<br>\u2022 Ohne Haken bleibt der Betrag unverzinst liegen; er z\u00e4hlt weiterhin zum Gesamtkapital, wirft aber keine Ertr\u00e4ge ab<\/span><\/span><\/span>\r\n                <\/label>\r\n              <\/div>\r\n              <div class=\"field\" style=\"margin-bottom:0;flex:1;min-width:130px;\">\r\n                <label style=\"font-size:12px;\">Beitragsjahre\r\n                  <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Jahre, in denen du voraussichtlich in die gesetzliche Rente einzahlst<br>\u2022 Vorbelegt aus deinem Alter bis zum Renteneintritt (Annahme: durchgehend gearbeitet ab ca. 20)<br>\u2022 Frei anpassbar<\/span><\/span>\r\n                <\/label>\r\n                <div class=\"input-wrap\">\r\n                  <input type=\"number\" id=\"beitragsjahre\" min=\"0\" max=\"50\" value=\"45\" class=\"input\" oninput=\"onBeitragsjahre()\" aria-label=\"Beitragsjahre\">\r\n                  <span class=\"currency-suffix\">Jahre<\/span>\r\n                <\/div>\r\n              <\/div>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <!-- Renten-Felder (beide Pfade) -->\r\n          <div style=\"display:flex;gap:12px;flex-wrap:wrap;margin-top:12px;\">\r\n            <div class=\"field\" style=\"margin-bottom:0;flex:1;min-width:150px;\">\r\n              <label style=\"font-size:12px;\">Gesetzliche Rente <span id=\"ges-rente-badge\" style=\"display:none;color:var(--etf);font-weight:600;font-size:11px;\">\u270e gesch\u00e4tzt \u00b7 anpassbar<\/span>\r\n                <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Voraussichtliche gesetzliche Bruttorente pro Monat<br>\u2022 Es z\u00e4hlt nur der steuerpflichtige Anteil (Besteuerungsanteil je nach Renteneintrittsjahr, 2026 \u2248 84 %, steigend auf 100 %)<\/span><\/span>\r\n              <\/label>\r\n              <div class=\"input-wrap\">\r\n                <input type=\"text\" inputmode=\"numeric\" id=\"ges-rente\" value=\"0\" placeholder=\"z.B. 1500\" class=\"input\" oninput=\"leseRenten()\" aria-label=\"Gesetzliche Rente pro Monat in Euro\">\r\n                <span class=\"currency-suffix\">\u20ac\/Mo.<\/span>\r\n              <\/div>\r\n            <\/div>\r\n            <div class=\"field\" style=\"margin-bottom:0;flex:1;min-width:150px;\">\r\n              <label style=\"font-size:12px;\">Betriebsrente <span style=\"font-weight:400;color:var(--muted);\">(optional)<\/span>\r\n                <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Voraussichtliche Betriebsrente pro Monat<br>\u2022 Wird zu 100 % als steuerpflichtiges Einkommen angesetzt<\/span><\/span>\r\n              <\/label>\r\n              <div class=\"input-wrap\">\r\n                <input type=\"text\" inputmode=\"numeric\" id=\"betriebs-rente\" value=\"0\" placeholder=\"z.B. 300\" class=\"input\" oninput=\"leseRenten()\" aria-label=\"Betriebsrente pro Monat in Euro\">\r\n                <span class=\"currency-suffix\">\u20ac\/Mo.<\/span>\r\n              <\/div>\r\n            <\/div>\r\n          <\/div>\r\n          <div id=\"schaetz-ann\" style=\"font-size:11px;color:var(--muted);line-height:1.5;margin-top:8px;display:none;\"><\/div>\r\n\r\n          <!-- Ehegattensplitting -->\r\n          <div style=\"margin-top:16px;padding-top:14px;border-top:1px solid var(--border);\">\r\n            <div style=\"display:flex;align-items:flex-start;gap:10px;\">\r\n              <label class=\"kk-switch\" style=\"margin-top:1px;\"><input type=\"checkbox\" id=\"split-toggle\" onchange=\"toggleSplitting(this)\" aria-label=\"Ehegattensplitting anwenden\"><span class=\"kk-slider-track\"><\/span><\/label>\r\n              <div style=\"flex:1;\">\r\n                <span style=\"font-size:13px;font-weight:600;color:var(--text);line-height:1.4;\">Verheiratet \/ zusammenveranlagt <span style=\"font-weight:400;color:var(--muted);\">\u2013 Ehegattensplitting<\/span><span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Bei Zusammenveranlagung gilt: Steuer = 2 \u00d7 Tarif(zvE \u00f7 2)<br>\u2022 Senkt die Steuer im Alter sp\u00fcrbar<br>\u2022 Was der Partner steuerlich mitbringt, z\u00e4hlt mit: Rente (nur steuerpflichtiger Anteil) oder Erwerbseinkommen (voll)<\/span><\/span><\/span>\r\n                <div id=\"partner-wrap\" style=\"display:none;margin-top:10px;\">\r\n                  <div style=\"font-size:12px;color:var(--muted);margin-bottom:6px;\">Was bringt dein Partner steuerlich mit?<\/div>\r\n                  <div class=\"netto-ptype\">\r\n                    <button type=\"button\" class=\"netto-pt sel\" id=\"pt-rente\" onclick=\"setPartnerTyp('rente')\">Bezieht Rente<\/button>\r\n                    <button type=\"button\" class=\"netto-pt\" id=\"pt-job\" onclick=\"setPartnerTyp('job')\">Noch berufst\u00e4tig<\/button>\r\n                  <\/div>\r\n                  <div class=\"field\" style=\"margin-bottom:0;max-width:280px;margin-top:10px;\">\r\n                    <label style=\"font-size:12px;\" id=\"partner-label\">Rente des Partners<\/label>\r\n                    <div class=\"input-wrap\">\r\n                      <input type=\"text\" inputmode=\"numeric\" id=\"partner-rente\" value=\"0\" placeholder=\"z.B. 1200\" class=\"input\" oninput=\"leseRenten()\" aria-label=\"Einkommen des Partners\">\r\n                      <span class=\"currency-suffix\" id=\"partner-suffix\">\u20ac\/Mo.<\/span>\r\n                    <\/div>\r\n                  <\/div>\r\n                  <div style=\"font-size:11px;color:var(--muted);line-height:1.5;margin-top:8px;\">Leer\/0 \u20ac = Partner ohne eigenes steuerpflichtiges Einkommen (maximaler Splitting-Vorteil). Rente z\u00e4hlt nur mit Besteuerungsanteil (~84 %), Erwerbseinkommen voll.<\/div>\r\n                <\/div>\r\n              <\/div>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Rendite-Szenario lebt jetzt im Ergebnis (\u00fcber dem Hero) \u2013 nicht mehr im Wizard -->\r\n\r\n\r\n  <!-- MIGRIERT: .cta-btn \u2192 .button .button--primary + .button--stretch (Styleguide) -->\r\n  <button type=\"button\" class=\"button button--primary button--stretch\" id=\"berechnenBtn\" onclick=\"if(window.avdStartBerechnung)window.avdStartBerechnung(event)\" style=\"display:none;align-items:center;justify-content:center;margin:24px auto 32px;padding:16px 24px;font-size:16px;font-weight:700;line-height:1.4;border-radius:12px;letter-spacing:0.02em;background:#E8327A;border-color:#E8327A;color:#ffffff;width:100%;box-sizing:border-box;\">\r\n    Jetzt berechnen \u2192\r\n  <\/button>\r\n\r\n  <!-- CTA Vormerkung (1.8: aus #results herausgezogen \u2192 vor der Berechnung sichtbar) -->\r\n  <div id=\"cta-kasten\" style=\"display:block;margin-bottom:24px;scroll-margin-top:16px;\">\r\n    <div style=\"background:#2691ff;border-radius:12px;padding:28px;box-shadow:0 4px 20px rgba(38,145,255,0.25);\">\r\n      <div id=\"cta-vormerk-titel\" style=\"font-size:18px;font-weight:700;margin-bottom:4px;color:#ffffff;\">AVD vormerken<\/div>\r\n      <div style=\"font-size:14px;font-weight:600;color:#ffffff;margin-bottom:4px;\">Kostenlos f\u00fcr das Altersvorsorgedepot vormerken<\/div>\r\n      <div style=\"font-size:12px;color:#ffffff;margin-bottom:20px;line-height:1.5;\">Wir speichern deine E-Mail-Adresse, um dich \u00fcber den Start des Altersvorsorgedepots zu informieren. N\u00e4heres in der <a href=\"https:\/\/www.finanzen.net\/datenschutz\" target=\"_blank\" style=\"color:#ffffff;text-decoration:underline;\">Datenschutzerkl\u00e4rung<\/a>.<\/div>\r\n      <form id=\"vormerkForm1\" onsubmit=\"submitVormerkung(event,'vormerkForm1')\" style=\"display:flex;flex-direction:column;gap:12px;\">\r\n        <div aria-hidden=\"true\" style=\"position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;\"><label>Bitte frei lassen<\/label><input type=\"text\" name=\"avd_hp\" tabindex=\"-1\" autocomplete=\"off\" value=\"\"><\/div>\r\n        <div>\r\n          <label style=\"font-size:12px;font-weight:600;color:#ffffff;display:block;margin-bottom:6px;text-transform:uppercase;letter-spacing:0.05em;\">E-Mail Adresse <span style=\"color:#E8327A;\">*<\/span><\/label>\r\n          <input type=\"email\" required placeholder=\"deine@email.de\"\r\n            style=\"width:100%;background:#ffffff;border:1px solid #dce3ea;border-radius:8px;padding:12px 16px;color:#1a2332;font-size:14px;outline:none;box-sizing:border-box;\"\r\n            onfocus=\"this.style.borderColor='#E8327A'\"\r\n            onblur=\"this.style.borderColor='#dce3ea'\">\r\n        <\/div>\r\n        <!-- LEGAL P3\/P4: \u00a77-UWG-Einwilligung (Pflicht) \u2013 \u00fcber dem Button -->\r\n        <label style=\"display:flex;align-items:flex-start;gap:10px;cursor:pointer;font-size:13px;color:#ffffff;line-height:1.5;\">\r\n          <input type=\"checkbox\" required style=\"margin-top:2px;accent-color:#E8327A;width:16px;height:16px;flex-shrink:0;\">\r\n          <span>Ich m\u00f6chte per E-Mail benachrichtigt werden, sobald das Altersvorsorgedepot der finanzen.net zero GmbH verf\u00fcgbar ist. Diese Einwilligung kann ich jederzeit mit Wirkung f\u00fcr die Zukunft widerrufen. <span style=\"color:#E8327A;\">*<\/span><\/span>\r\n        <\/label>\r\n        <!-- Riester (optional) \u2013 im K\u00e4stchen abgesetzt -->\r\n        <label style=\"display:flex;align-items:flex-start;gap:10px;cursor:pointer;font-size:13px;color:#ffffff;line-height:1.5;background:rgba(255,255,255,0.2);border:1px solid rgba(255,255,255,0.55);border-radius:8px;padding:12px;\">\r\n          <input type=\"checkbox\" id=\"riesterCheck1\" style=\"margin-top:2px;accent-color:#E8327A;width:16px;height:16px;flex-shrink:0;\">\r\n          <span>Ich interessiere mich f\u00fcr einen Wechsel meiner Riester-F\u00f6rderung in das Altersvorsorgedepot und willige ein, dass die finanzen.net zero GmbH meine Angabe speichert und mich hierzu per E-Mail kontaktiert. <span style=\"font-weight:400;opacity:0.7;\">(optional)<\/span><\/span>\r\n        <\/label>\r\n        <button type=\"submit\" class=\"button button--primary button--stretch\" style=\"display:flex;align-items:center;justify-content:center;padding:16px;font-size:15px;font-weight:700;line-height:1.4;border-radius:8px;letter-spacing:0.02em;background:#E8327A;border-color:#E8327A;color:#ffffff;width:100%;box-sizing:border-box;\">\r\n          <span class=\"cta-btn-desktop\">Kostenlos f\u00fcr das Altersvorsorgedepot vormerken \u2192<\/span><span class=\"cta-btn-mobile\">Kostenlos vormerken \u2192<\/span>\r\n        <\/button>\r\n        <!-- LEGAL P3: DOI-Hinweis -->\r\n        <div style=\"font-size:11px;color:#ffffff;opacity:0.85;line-height:1.5;text-align:center;\">Kostenlos und unverbindlich.<\/div>\r\n      <\/form>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Ergebnisse -->\r\n  <div class=\"results\" id=\"results\">\r\n\r\n    <div class=\"results-header\">Ergebnis<\/div>\r\n    <!-- BFSG: Ergebnis-Ank\u00fcndigung f\u00fcr Screenreader (nur bei \u201eJetzt berechnen\") -->\r\n    <div id=\"sr-result\" class=\"sr-only\" aria-live=\"polite\"><\/div>\r\n\r\n    <!-- Szenario-Auswahl (aus Wizard herausgel\u00f6st \u2192 \u00fcber dem Hero, Buttons + Regler) -->\r\n    <div class=\"szenario-panel\">\r\n      <div class=\"sz-frage\">Welche Renditeerwartung legst du zugrunde?\r\n        <span style=\"font-size:10px;font-weight:600;background:#fff3cd;color:#856404;border:1px solid #ffc107;padding:2px 8px;border-radius:20px;letter-spacing:0.02em;text-transform:none;\">Historische Renditeannahmen<\/span>\r\n        <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Aktien-\/AVD-Renditen abgeleitet aus dem langfristigen DAX-Durchschnitt (Deutsches Aktieninstitut, DAX-Rendite-Dreieck: ~7\u20139 % p.a. \u00fcber 30 Jahre)<br>\u2022 Riester: je nach Studie ~0,8 % (Finanzwende\/Kleinlein) bis ~2,5 % (IVFP) \u2013 nach Kosten und Garantieabz\u00fcgen<br>\u2022 Altersvorsorgedepot\/ETF\/Fonds: Nettorendite nach TER<br>\u2022 Defensiv: konservativ (Anleihen-lastig) \u00b7 Neutral: ausgewogen (60\/40) \u00b7 Offensiv: aktienstark (max. 7,5 % p.a.)<br>\u2022 Die vergangene Wertentwicklung ist kein verl\u00e4sslicher Indikator f\u00fcr die k\u00fcnftige Wertentwicklung<\/span><\/span>\r\n      <\/div>\r\n      <span id=\"scenario-name\" class=\"sr-only\">Neutral<\/span>\r\n      <div class=\"szenario-buttons\" role=\"group\" aria-label=\"Renditeszenario w\u00e4hlen\">\r\n        <button type=\"button\" class=\"sz-btn\" id=\"label-0\" data-sz=\"0\">Defensiv<\/button>\r\n        <button type=\"button\" class=\"sz-btn active\" id=\"label-1\" data-sz=\"1\">Neutral<\/button>\r\n        <button type=\"button\" class=\"sz-btn\" id=\"label-2\" data-sz=\"2\">Offensiv<\/button>\r\n      <\/div>\r\n      <input type=\"range\" id=\"szenario\" min=\"0\" max=\"2\" value=\"1\" step=\"0.01\" oninput=\"updateSzenario(this.value)\" aria-label=\"Renditeszenario fein einstellen\" aria-valuetext=\"Neutral \u2013 Riester 1,0 %, Altersvorsorgedepot 5,5 %, ETF\/Fonds 5,5 %\">\r\n      <div class=\"scenario-rates\" id=\"scenario-rates\">Riester 1,0% \u00b7 Altersvorsorgedepot 5,5% \u00b7 ETF\/Fonds 5,5%<\/div>\r\n    <\/div>\r\n\r\n    <!-- Delta Banner (custom \u2013 tool-spezifisch) -->\r\n    <div class=\"delta-banner\" id=\"delta-banner\">\r\n      <!-- Netto-Delta (prim\u00e4r, nur Netto an; im Grundsicherungs-Fall ausgeblendet) -->\r\n      <div class=\"netto-zeile\">\r\n        <div class=\"delta-label\" id=\"delta-label-netto\">In dieser Beispielrechnung liegt das AVD Flex-Depot vorn<\/div>\r\n        <div class=\"delta-amount\" id=\"delta-amount-netto\">+0 \u20ac<\/div>\r\n        <div class=\"delta-real real-zeile\" id=\"delta-real-netto\">in heutiger Kaufkraft: +0 \u20ac<\/div>\r\n      <\/div>\r\n      <!-- Brutto voll (Netto aus oder Grundsicherungs-Fall) -->\r\n      <div class=\"brutto-full\">\r\n        <div class=\"delta-label\" id=\"delta-label\">Vergleich Altersvorsorgedepot vs. Riester<\/div>\r\n        <div class=\"delta-amount\" id=\"delta-amount\">+0 \u20ac<\/div>\r\n        <div class=\"delta-sub\" id=\"delta-sub\">voraussichtlich mehr mit dem Altersvorsorgedepot<\/div>\r\n        <div class=\"delta-real real-zeile\" id=\"delta-real\">in heutiger Kaufkraft: +0 \u20ac<\/div>\r\n      <\/div>\r\n      <!-- Brutto kompakt\/zweitrangig (nur Netto an) -->\r\n      <div class=\"brutto-compact netto-zeile\"><span id=\"delta-brutto-compact\">Brutto-Vergleich: +0 \u20ac<\/span><span class=\"real-zeile\" id=\"delta-brutto-compact-real\"> \u00b7 in heutiger Kaufkraft +0 \u20ac<\/span><\/div>\r\n      <!-- Risiko-Callout (Legal P3: Risiko auf gleicher Sichtebene wie die Chance) -->\r\n      <div id=\"delta-hint\" style=\"display:flex;gap:10px;align-items:flex-start;margin-top:16px;background:#B02653;border-radius:8px;padding:12px 14px;text-align:left;\">\r\n        <span aria-hidden=\"true\" style=\"font-size:18px;line-height:1.35;flex-shrink:0;\">\u26a0\ufe0f<\/span>\r\n        <span style=\"font-size:14px;font-weight:600;color:#ffffff;line-height:1.45;-webkit-hyphens:auto;hyphens:auto;\">Hinweis: Bei Entnahme in schwachen B\u00f6rsenjahren oder bei geringem Anlagehorizont kann das Ergebnis geringer ausfallen. Die Werte sind Sch\u00e4tzungen mit Durchschnittsannahmen \u2013 keine Anlageempfehlung, keine Prognose.<\/span>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- Netto-Hinweis: warum der ETF-Sparplan netto vorn liegen kann (nur Netto an) -->\r\n    <div class=\"netto-erkl netto-zeile\" style=\"margin-top:12px;\">\r\n      <span aria-hidden=\"true\">\ud83d\udca1<\/span>\r\n      <span style=\"-webkit-hyphens:auto;hyphens:auto;\"><b>Warum kann der ETF-Sparplan netto vorn liegen?<\/b> Riester und das Altersvorsorgedepot werden <b>nachgelagert besteuert<\/b>: Im Alter wird die gesamte Auszahlung (Einzahlungen + F\u00f6rderung + Ertr\u00e4ge) mit deinem pers\u00f6nlichen Einkommensteuersatz versteuert. Beim ETF-Sparplan f\u00e4llt dagegen nur auf die <b>Ertr\u00e4ge<\/b> Abgeltungsteuer an (effektiv ca. 18,5&nbsp;% nach Teilfreistellung, zus\u00e4tzlich gemindert um den j\u00e4hrlichen Sparer-Pauschbetrag) \u2013 die Einzahlungen selbst bleiben steuerfrei, da bereits versteuert. Je h\u00f6her dein Steuersatz im Alter (z.&nbsp;B. durch eine hohe gesetzliche Rente oder weitere Eink\u00fcnfte), desto st\u00e4rker schmilzt der F\u00f6rdervorteil \u2013 netto kann der ETF-Sparplan dann trotz F\u00f6rderung vorn liegen.<\/span>\r\n    <\/div>\r\n\r\n    <!-- Ergebnis-Karten (custom \u2013 kein Card-Component im Styleguide) -->\r\n    <div class=\"cards-grid\">\r\n      <div class=\"card riester\" id=\"card-riester\">\r\n        <div class=\"card-label\"><span aria-hidden=\"true\">\ud83d\udd35<\/span> Riester<\/div>\r\n        <!-- Netto-Kopf (nur Netto an) -->\r\n        <div class=\"netto-zeile\">\r\n          <div class=\"card-amount\" id=\"r-endkapital-netto\">0 \u20ac<\/div>\r\n          <div class=\"card-sub\">Kapital netto (nach Steuer)<\/div>\r\n          <div class=\"card-real real-zeile\" id=\"r-endkapital-netto-real\" style=\"color:#1D9E75;\">= heute 0 \u20ac<\/div>\r\n        <\/div>\r\n        <!-- Brutto-Kopf voll (nur Netto aus) -->\r\n        <div class=\"brutto-full\">\r\n          <div class=\"card-amount\" id=\"r-endkapital\">0 \u20ac<\/div>\r\n          <div class=\"card-sub\">Kapital zum Renteneintritt (Brutto)<\/div>\r\n          <div class=\"card-real real-zeile\" id=\"r-endkapital-real\">= heute 0 \u20ac<\/div>\r\n        <\/div>\r\n        <!-- Brutto kompakt (nur Netto an) -->\r\n        <div class=\"brutto-card-compact netto-zeile\"><span id=\"r-brutto-compact\">Brutto: 0 \u20ac<\/span><span class=\"real-zeile\" id=\"r-brutto-compact-real\" style=\"display:block;\">(heute 0 \u20ac)<\/span><\/div>\r\n        <div class=\"card-detail\"><span style=\"white-space:normal;flex-shrink:1;min-width:0;\">Automatische Sicherheitsumschichtung vor Renteneintritt<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Ziel ist es, das Risiko vor Renteneintritt zu reduzieren<br>\u2022 4\u20135 Jahre vor Renteneintritt: Aktienanteil wird auf 50 % reduziert<br>\u2022 1\u20133 Jahre vor Renteneintritt: Aktienanteil sinkt weiter auf 30 %<\/span><\/span><\/span><span style=\"color:var(--muted);\">Nein<\/span><\/div>\r\n        <div class=\"card-detail\"><span>Eigenbeitrag gesamt<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Startguthaben + monatliche Einzahlungen bis Renteneintritt<br>\u2022 In allen vier Varianten identisch<\/span><\/span><\/span><span id=\"r-eingezahlt\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\"><span>F\u00f6rderung Gesamt<\/span><span id=\"r-foerderung\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\"><span>Wertzuwachs<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Endkapital abz\u00fcglich Eigenbeitrag und F\u00f6rderung<br>\u2022 Kurs-\/Zinsgewinne vor Steuern<\/span><\/span><\/span><span id=\"r-wertzuwachs\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"r-neben-row\" style=\"display:none;\"><span><span id=\"r-neben-label\">+ Fonds-Nebendepot<\/span><span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Der Teil der Steuererstattung, der die gesetzliche Einzahlungsgrenze von 6.840 \u20ac\/Jahr \u00fcbersteigt, darf nicht in den gef\u00f6rderten Vertrag<br>\u2022 Er wird stattdessen in einem normalen Fonds-\/ETF-Depot angelegt<br>\u2022 Die Erstattung selbst ist kein steuerbarer Zufluss \u2013 besteuert werden nur ihre Gewinne (Abgeltungsteuer, 30 % Teilfreistellung, Sparer-Pauschbetrag)<\/span><\/span><\/span><span id=\"r-neben\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"r-gesamt-row\" style=\"display:none;\"><span style=\"font-weight:700;\">= Gesamtkapital<\/span><span id=\"r-gesamt\" style=\"font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail brutto-only\"><span>Monatsrente<\/span><span id=\"r-rente\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail real-zeile brutto-only\"><span>Monatsrente (heute)<\/span><span id=\"r-rente-real\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail netto-zeile\"><span>Monatsrente (netto)<\/span><span id=\"r-rente-netto\" style=\"color:#1D9E75;font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail netto-zeile real-zeile\"><span>Monatsrente (netto, heute)<\/span><span id=\"r-rente-netto-real\" style=\"color:#1D9E75;font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"r-gs-row\" style=\"display:none;\"><span>Grundsicherungsberechtigt<\/span><span style=\"color:#0d6efd;font-size:11px;\">\u00a782 SGB XII greift<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"r-gs-anrech-row\" style=\"display:none;\"><span>Anrechnungsfrei (\u00a782 SGB XII)<\/span><span id=\"r-gs-val\" style=\"color:#0d6efd;font-weight:600;\">0 \u20ac\/Mo.<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"r-gs-gesamt-row\" style=\"display:none;\"><span>Monatsrente mit Grundsicherung<\/span><span id=\"r-gs-gesamt-val\" style=\"color:#0d6efd;font-weight:600;\">0 \u20ac\/Mo.<\/span><\/div>\r\n      <\/div>\r\n\r\n      <div class=\"card depot\" id=\"card-depot\">\r\n        <div class=\"card-label\"><span aria-hidden=\"true\">\ud83d\udd34<\/span> AVD Standarddepot<\/div>\r\n        <!-- Netto-Kopf (nur Netto an) -->\r\n        <div class=\"netto-zeile\">\r\n          <div class=\"card-amount\" id=\"d-endkapital-netto\">0 \u20ac<\/div>\r\n          <div class=\"card-sub\">Kapital netto (nach Steuer)<\/div>\r\n          <div class=\"card-real real-zeile\" id=\"d-endkapital-netto-real\" style=\"color:#1D9E75;\">= heute 0 \u20ac<\/div>\r\n        <\/div>\r\n        <!-- Brutto-Kopf voll (nur Netto aus) -->\r\n        <div class=\"brutto-full\">\r\n          <div class=\"card-amount\" id=\"d-endkapital\">0 \u20ac<\/div>\r\n          <div class=\"card-sub\">Kapital zum Renteneintritt (Brutto)<\/div>\r\n          <div class=\"card-real real-zeile\" id=\"d-endkapital-real\">= heute 0 \u20ac<\/div>\r\n        <\/div>\r\n        <!-- Brutto kompakt (nur Netto an) -->\r\n        <div class=\"brutto-card-compact netto-zeile\"><span id=\"d-brutto-compact\">Brutto: 0 \u20ac<\/span><span class=\"real-zeile\" id=\"d-brutto-compact-real\" style=\"display:block;\">(heute 0 \u20ac)<\/span><\/div>\r\n        <div class=\"card-detail\"><span style=\"white-space:normal;flex-shrink:1;min-width:0;\">Automatische Sicherheitsumschichtung vor Renteneintritt<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Ziel ist es, das Risiko vor Renteneintritt zu reduzieren<br>\u2022 4\u20135 Jahre vor Renteneintritt: Aktienanteil wird auf 50 % reduziert<br>\u2022 1\u20133 Jahre vor Renteneintritt: Aktienanteil sinkt weiter auf 30 %<\/span><\/span><\/span><span style=\"color:#1D9E75;\">Ja \u2713<\/span><\/div>\r\n        <div class=\"card-detail\"><span>Eigenbeitrag gesamt<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Startguthaben + monatliche Einzahlungen bis Renteneintritt<br>\u2022 In allen vier Varianten identisch<\/span><\/span><\/span><span id=\"d-eingezahlt\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\"><span>F\u00f6rderung Gesamt<\/span><span id=\"d-foerderung\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\"><span>Wertzuwachs<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Endkapital abz\u00fcglich Eigenbeitrag und F\u00f6rderung<br>\u2022 Kurs-\/Zinsgewinne vor Steuern<\/span><\/span><\/span><span id=\"d-wertzuwachs\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"d-neben-row\" style=\"display:none;\"><span><span id=\"d-neben-label\">+ Fonds-Nebendepot<\/span><span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Der Teil der Steuererstattung, der die gesetzliche Einzahlungsgrenze von 6.840 \u20ac\/Jahr \u00fcbersteigt, darf nicht in den gef\u00f6rderten Vertrag<br>\u2022 Er wird stattdessen in einem normalen Fonds-\/ETF-Depot angelegt<br>\u2022 Die Erstattung selbst ist kein steuerbarer Zufluss \u2013 besteuert werden nur ihre Gewinne (Abgeltungsteuer, 30 % Teilfreistellung, Sparer-Pauschbetrag)<\/span><\/span><\/span><span id=\"d-neben\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"d-gesamt-row\" style=\"display:none;\"><span style=\"font-weight:700;\">= Gesamtkapital<\/span><span id=\"d-gesamt\" style=\"font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail brutto-only\"><span>Monatsrente<\/span><span id=\"d-rente\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail real-zeile brutto-only\"><span>Monatsrente (heute)<\/span><span id=\"d-rente-real\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail netto-zeile\"><span>Monatsrente (netto)<\/span><span id=\"d-rente-netto\" style=\"color:#1D9E75;font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail netto-zeile real-zeile\"><span>Monatsrente (netto, heute)<\/span><span id=\"d-rente-netto-real\" style=\"color:#1D9E75;font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"d-gs-row\" style=\"display:none;\"><span>Grundsicherungsberechtigt<\/span><span style=\"color:var(--muted);font-size:11px;\">\u00a782 noch nicht geregelt<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"d-gs-anrech-row\" style=\"display:none;\"><span>Anrechnungsfrei (\u00a782 SGB XII)<\/span><span id=\"d-gs-val\" style=\"color:var(--muted);\">noch nicht geregelt<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"d-gs-gesamt-row\" style=\"display:none;\"><span>Monatsrente mit Grundsicherung<\/span><span id=\"d-gs-gesamt-val\" style=\"color:var(--muted);\">0 \u20ac\/Mo.<\/span><\/div>\r\n      <\/div>\r\n\r\n      <div class=\"card etf\" id=\"card-etf\">\r\n        <div class=\"card-label\"><span aria-hidden=\"true\">\ud83d\udfe2<\/span> ETF-Sparplan (ohne F\u00f6rderung)<\/div>\r\n        <!-- Netto-Kopf (nur Netto an) -->\r\n        <div class=\"netto-zeile\">\r\n          <div class=\"card-amount\" id=\"e-endkapital-netto\">0 \u20ac<\/div>\r\n          <div class=\"card-sub\">Kapital netto (nach Steuer)<\/div>\r\n          <div style=\"font-size:10px;color:var(--muted);line-height:1.4;\">inkl. 30 % Teilfreistellung &amp; Sparer-Pauschbetrag (1.000 \u20ac\/Jahr)<\/div>\r\n          <div class=\"card-real real-zeile\" id=\"e-endkapital-netto-real\" style=\"color:#1D9E75;\">= heute 0 \u20ac<\/div>\r\n        <\/div>\r\n        <!-- Brutto-Kopf voll (nur Netto aus) -->\r\n        <div class=\"brutto-full\">\r\n          <div class=\"card-amount\" id=\"e-endkapital\">0 \u20ac<\/div>\r\n          <div class=\"card-sub\">Kapital zum Renteneintritt (Brutto)<\/div>\r\n          <div class=\"card-real real-zeile\" id=\"e-endkapital-real\">= heute 0 \u20ac<\/div>\r\n        <\/div>\r\n        <!-- Brutto kompakt (nur Netto an) -->\r\n        <div class=\"brutto-card-compact netto-zeile\"><span id=\"e-brutto-compact\">Brutto: 0 \u20ac<\/span><span class=\"real-zeile\" id=\"e-brutto-compact-real\" style=\"display:block;\">(heute 0 \u20ac)<\/span><\/div>\r\n        <div class=\"card-detail\"><span style=\"white-space:normal;flex-shrink:1;min-width:0;\">Automatische Sicherheitsumschichtung vor Renteneintritt<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Ziel ist es, das Risiko vor Renteneintritt zu reduzieren<br>\u2022 4\u20135 Jahre vor Renteneintritt: Aktienanteil wird auf 50 % reduziert<br>\u2022 1\u20133 Jahre vor Renteneintritt: Aktienanteil sinkt weiter auf 30 %<\/span><\/span><\/span><span style=\"color:var(--muted);\">Nein<\/span><\/div>\r\n        <div class=\"card-detail\"><span>Eigenbeitrag gesamt<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Startguthaben + monatliche Einzahlungen bis Renteneintritt<br>\u2022 In allen vier Varianten identisch<\/span><\/span><\/span><span id=\"e-eingezahlt\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\"><span>F\u00f6rderung Gesamt<\/span><span>\u2013<\/span><\/div>\r\n        <div class=\"card-detail\"><span>Wertzuwachs<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Endkapital abz\u00fcglich Eigenbeitrag<br>\u2022 Kurs-\/Zinsgewinne vor Steuern (Abgeltungsteuer f\u00e4llt nur hierauf an)<\/span><\/span><\/span><span id=\"e-wertzuwachs\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail brutto-only\"><span>Monatsrente<\/span><span id=\"e-rente\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail real-zeile brutto-only\"><span>Monatsrente (heute)<\/span><span id=\"e-rente-real\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail netto-zeile\"><span>Monatsrente (netto)<\/span><span id=\"e-rente-netto\" style=\"color:#1D9E75;font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail netto-zeile real-zeile\"><span>Monatsrente (netto, heute)<\/span><span id=\"e-rente-netto-real\" style=\"color:#1D9E75;font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"e-gs-row\" style=\"display:none;\"><span>Grundsicherungsberechtigt<\/span><span style=\"color:var(--muted);\">Nein<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"e-gs-anrech-row\" style=\"display:none;\"><span>Anrechnungsfrei (\u00a782 SGB XII)<\/span><span style=\"color:var(--muted);\">\u2013<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"e-gs-gesamt-row\" style=\"display:none;\"><span>Monatsrente mit Grundsicherung<\/span><span style=\"color:var(--muted);\">\u2013<\/span><\/div>\r\n      <\/div>\r\n\r\n      <div class=\"card individual\" id=\"card-individual\">\r\n        <div class=\"card-label\"><span aria-hidden=\"true\">\ud83d\udfe3<\/span> AVD Flex-Depot<\/div>\r\n        <!-- Netto-Kopf (nur Netto an) -->\r\n        <div class=\"netto-zeile\">\r\n          <div class=\"card-amount\" id=\"i-endkapital-netto\">0 \u20ac<\/div>\r\n          <div class=\"card-sub\">Kapital netto (nach Steuer)<\/div>\r\n          <div class=\"card-real real-zeile\" id=\"i-endkapital-netto-real\" style=\"color:#1D9E75;\">= heute 0 \u20ac<\/div>\r\n        <\/div>\r\n        <!-- Brutto-Kopf voll (nur Netto aus) -->\r\n        <div class=\"brutto-full\">\r\n          <div class=\"card-amount\" id=\"i-endkapital\">0 \u20ac<\/div>\r\n          <div class=\"card-sub\">Kapital zum Renteneintritt (Brutto)<\/div>\r\n          <div class=\"card-real real-zeile\" id=\"i-endkapital-real\">= heute 0 \u20ac<\/div>\r\n        <\/div>\r\n        <!-- Brutto kompakt (nur Netto an) -->\r\n        <div class=\"brutto-card-compact netto-zeile\"><span id=\"i-brutto-compact\">Brutto: 0 \u20ac<\/span><span class=\"real-zeile\" id=\"i-brutto-compact-real\" style=\"display:block;\">(heute 0 \u20ac)<\/span><\/div>\r\n        <div class=\"card-detail\"><span style=\"white-space:normal;flex-shrink:1;min-width:0;\">Automatische Sicherheitsumschichtung vor Renteneintritt<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Ziel ist es, das Risiko vor Renteneintritt zu reduzieren<br>\u2022 4\u20135 Jahre vor Renteneintritt: Aktienanteil wird auf 50 % reduziert<br>\u2022 1\u20133 Jahre vor Renteneintritt: Aktienanteil sinkt weiter auf 30 %<\/span><\/span><\/span><span style=\"color:var(--muted);\">Nein<\/span><\/div>\r\n        <div class=\"card-detail\"><span>Eigenbeitrag gesamt<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Startguthaben + monatliche Einzahlungen bis Renteneintritt<br>\u2022 In allen vier Varianten identisch<\/span><\/span><\/span><span id=\"i-eingezahlt\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\"><span>F\u00f6rderung Gesamt<\/span><span id=\"i-foerderung\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\"><span>Wertzuwachs<span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Endkapital abz\u00fcglich Eigenbeitrag und F\u00f6rderung<br>\u2022 Kurs-\/Zinsgewinne vor Steuern<\/span><\/span><\/span><span id=\"i-wertzuwachs\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"i-neben-row\" style=\"display:none;\"><span><span id=\"i-neben-label\">+ Fonds-Nebendepot<\/span><span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Der Teil der Steuererstattung, der die gesetzliche Einzahlungsgrenze von 6.840 \u20ac\/Jahr \u00fcbersteigt, darf nicht in den gef\u00f6rderten Vertrag<br>\u2022 Er wird stattdessen in einem normalen Fonds-\/ETF-Depot angelegt<br>\u2022 Die Erstattung selbst ist kein steuerbarer Zufluss \u2013 besteuert werden nur ihre Gewinne (Abgeltungsteuer, 30 % Teilfreistellung, Sparer-Pauschbetrag)<\/span><\/span><\/span><span id=\"i-neben\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"i-gesamt-row\" style=\"display:none;\"><span style=\"font-weight:700;\">= Gesamtkapital<\/span><span id=\"i-gesamt\" style=\"font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail brutto-only\"><span>Monatsrente<\/span><span id=\"i-rente\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail real-zeile brutto-only\"><span>Monatsrente (heute)<\/span><span id=\"i-rente-real\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail netto-zeile\"><span>Monatsrente (netto)<\/span><span id=\"i-rente-netto\" style=\"color:#1D9E75;font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail netto-zeile real-zeile\"><span>Monatsrente (netto, heute)<\/span><span id=\"i-rente-netto-real\" style=\"color:#1D9E75;font-weight:700;\">0 \u20ac<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"i-gs-row\" style=\"display:none;\"><span>Grundsicherungsberechtigt<\/span><span style=\"color:var(--muted);font-size:11px;\">\u00a782 noch nicht geregelt<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"i-gs-anrech-row\" style=\"display:none;\"><span>Anrechnungsfrei (\u00a782 SGB XII)<\/span><span style=\"color:var(--muted);\">noch nicht geregelt<\/span><\/div>\r\n        <div class=\"card-detail\" id=\"i-gs-gesamt-row\" style=\"display:none;\"><span>Monatsrente mit Grundsicherung<\/span><span id=\"i-gs-gesamt-val\" style=\"color:var(--muted);\">0 \u20ac\/Mo.<\/span><\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- Ziel-Slot: #cta-kasten wird beim ersten Berechnen hierher (Originalposition) verschoben -->\r\n    <div id=\"cta-slot\"><\/div>\r\n\r\n    <!-- Auszahlungsdauer Slider -->\r\n    <div style=\"background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:20px 24px;margin-top:20px;box-shadow:0 2px 8px rgba(38,145,255,0.08);\">\r\n      <div style=\"display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;\">\r\n        <div>\r\n          <div style=\"font-size:14px;font-weight:700;margin-bottom:4px;\">\r\n            Auszahlungsdauer\r\n            <!-- MIGRIERT: .tooltip-icon \u2192 data-sg-tooltip -->\r\n            <span class=\"tip\" tabindex=\"0\">i<span class=\"tip-text\">\u2022 Mann: \u00d8 78 Jahre (Statistisches Bundesamt 2024)<br>\u2022 Frau: \u00d8 83 Jahre (Statistisches Bundesamt 2024)<br>\u2022 Empfehlung: l\u00e4nger ansetzen f\u00fcr Langlebigkeitsschutz<br>\u2022 Default: 18 Jahre nach Rente (entspricht Alter 85)<\/span><\/span>\r\n          <\/div>\r\n          <div style=\"font-size:12px;color:var(--muted);\">Passe den Zeitraum an und sieh sofort, wie sich deine Monatsrate \u00e4ndert<\/div>\r\n        <\/div>\r\n        <div style=\"display:flex;align-items:center;gap:12px;min-width:220px;\">\r\n          <input type=\"range\" id=\"lebenserwartung\" min=\"1\" max=\"33\" value=\"18\" oninput=\"updateLE(this.value)\" aria-label=\"Auszahlungsdauer in Jahren\" aria-valuetext=\"18 Jahre\" style=\"flex:1;\">\r\n          <span style=\"font-size:16px;font-weight:700;color:var(--accent);min-width:80px;text-align:right;\" id=\"leDisplay\">18 Jahre<\/span>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"form-note form-note--warning\" id=\"le-85-warn\">Die Auszahlung endet mit <span id=\"le-85-alter\">85<\/span> Jahren. Das Altersvorsorgedepot muss Leistungen mindestens bis zum 85. Lebensjahr erbringen.<\/div>\r\n    <\/div>\r\n\r\n    <!-- Balkendiagramm Monatsrente -->\r\n    <div style=\"background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:16px 20px;margin-top:16px;box-shadow:0 2px 8px rgba(38,145,255,0.08);\">\r\n      <div style=\"display:flex;align-items:flex-start;justify-content:space-between;gap:10px;flex-wrap:wrap;\">\r\n        <div>\r\n          <div style=\"font-size:12px;font-weight:700;color:var(--text);margin-bottom:2px;\" id=\"barChartTitle\">Monatsrente im Vergleich<\/div>\r\n          <div style=\"font-size:11px;color:var(--muted);margin-bottom:12px;\" id=\"barChartSub\">Brutto \u00b7 ohne Steuer<\/div>\r\n        <\/div>\r\n        <div class=\"chart-bn-toggle netto-zeile\" role=\"group\" aria-label=\"Diagramm-Ansicht: Netto oder Brutto\">\r\n          <button type=\"button\" class=\"chart-bn chart-bn-netto sel\" onclick=\"setChartAnsicht('netto')\">Netto<\/button>\r\n          <button type=\"button\" class=\"chart-bn chart-bn-brutto\" onclick=\"setChartAnsicht('brutto')\">Brutto<\/button>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"chart-tap-wrapper\" id=\"barChartTapWrapper\" onclick=\"openChartOverlay('bar')\">\r\n        <canvas id=\"rentenBarChart\" height=\"55\"><\/canvas>\r\n        <div class=\"chart-tap-hint\">\r\n          <svg width=\"11\" height=\"14\" viewBox=\"0 0 11 14\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M5.5 1C5.5 1 3 2.5 3 5.5V8L2 8.5V10.5C2 11.9 3.6 13 5.5 13C7.4 13 9 11.9 9 10.5V8.5L8 8V5.5C8 2.5 5.5 1 5.5 1Z\" stroke=\"white\" stroke-width=\"1.3\" stroke-linejoin=\"round\"\/><\/svg>\r\n          Antippen zum Vergr\u00f6\u00dfern\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- Liniendiagramm -->\r\n    <div style=\"background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:24px;margin-top:24px;box-shadow:0 2px 8px rgba(38,145,255,0.08);\">\r\n      <div style=\"display:flex;align-items:flex-start;justify-content:space-between;gap:10px;flex-wrap:wrap;\">\r\n        <div>\r\n          <div style=\"font-size:13px;font-weight:700;color:var(--text);margin-bottom:4px;\">Kapitalentwicklung im Vergleich<\/div>\r\n          <div style=\"font-size:12px;color:var(--muted);margin-bottom:16px;\" id=\"lineChartSub\">Verm\u00f6gensentwicklung von heute bis zum Renteneintritt<\/div>\r\n        <\/div>\r\n        <div class=\"chart-bn-toggle netto-zeile\" role=\"group\" aria-label=\"Diagramm-Ansicht: Netto oder Brutto\">\r\n          <button type=\"button\" class=\"chart-bn chart-bn-netto sel\" onclick=\"setChartAnsicht('netto')\">Netto<\/button>\r\n          <button type=\"button\" class=\"chart-bn chart-bn-brutto\" onclick=\"setChartAnsicht('brutto')\">Brutto<\/button>\r\n        <\/div>\r\n      <\/div>\r\n      <div style=\"display:flex;flex-wrap:wrap;gap:12px;margin-bottom:16px;font-size:12px;\">\r\n        <span style=\"display:flex;align-items:center;gap:6px;color:var(--muted);\"><span style=\"width:24px;height:3px;background:#0d6efd;display:inline-block;border-radius:2px;\"><\/span>Riester<\/span>\r\n        <span style=\"display:flex;align-items:center;gap:6px;color:var(--muted);\"><span style=\"width:24px;height:3px;background:#e85d1a;display:inline-block;border-radius:2px;\"><\/span>Standarddepot<\/span>\r\n        <span style=\"display:flex;align-items:center;gap:6px;color:var(--muted);\"><span style=\"width:24px;height:3px;background:#7c3aed;display:inline-block;border-radius:2px;\"><\/span>Flex-Depot<\/span>\r\n        <span style=\"display:flex;align-items:center;gap:6px;color:var(--muted);\"><span style=\"width:24px;height:3px;background:#1D9E75;display:inline-block;border-radius:2px;border-style:dashed;\"><\/span>ETF-Sparplan<\/span>\r\n      <\/div>\r\n      <div id=\"verlaufChart-outer\" style=\"position:relative;width:100%;height:260px;\">\r\n        <div class=\"chart-tap-wrapper\" onclick=\"openChartOverlay('line')\" style=\"width:100%;height:100%;\">\r\n          <canvas id=\"verlaufChart\"><\/canvas>\r\n          <div class=\"chart-tap-hint\">\r\n            <svg width=\"11\" height=\"14\" viewBox=\"0 0 11 14\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M5.5 1C5.5 1 3 2.5 3 5.5V8L2 8.5V10.5C2 11.9 3.6 13 5.5 13C7.4 13 9 11.9 9 10.5V8.5L8 8V5.5C8 2.5 5.5 1 5.5 1Z\" stroke=\"white\" stroke-width=\"1.3\" stroke-linejoin=\"round\"\/><\/svg>\r\n            Antippen zum Vergr\u00f6\u00dfern\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- F\u00f6rderung -->\r\n    <div class=\"foerderung-box\" id=\"foerderung-box\">\r\n      <div class=\"foerderung-item\">\r\n        <div class=\"foerderung-amount\" id=\"f-grundzulage\">0 \u20ac<\/div>\r\n        <div class=\"foerderung-label\">Grundzulage im 1. Jahr<\/div>\r\n      <\/div>\r\n      <div class=\"foerderung-item\">\r\n        <div class=\"foerderung-amount\" id=\"f-kinderzulage\">0 \u20ac<\/div>\r\n        <div class=\"foerderung-label\">Kinderzulage im 1. Jahr<\/div>\r\n      <\/div>\r\n      <div class=\"foerderung-item\" id=\"f-steuer-item\" style=\"display:none;\">\r\n        <div class=\"foerderung-amount\" id=\"f-steuerersparnis\">0 \u20ac<\/div>\r\n        <div id=\"f-steuer-neben\" style=\"display:none;font-size:11px;color:var(--muted);margin-top:2px;\"><\/div>\r\n        <div class=\"foerderung-label\">Steuerersparnis (\u00fcber Laufzeit)<\/div>\r\n      <\/div>\r\n      <div class=\"foerderung-item\">\r\n        <div class=\"foerderung-amount\" id=\"f-gesamt\">0 \u20ac<\/div>\r\n        <div class=\"foerderung-label\">Staatliche F\u00f6rderung gesamt (\u00fcber Laufzeit)<\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <!-- Regul\u00e4res Depot (Preview) \u00b7 Legal P1 Produktidentit\u00e4t -->\r\n    <div style=\"background:#093967;border-radius:12px;padding:28px;margin-bottom:16px;box-shadow:0 4px 20px rgba(9,57,103,0.25);\">\r\n      <div style=\"font-size:18px;font-weight:700;color:#ffffff;margin-bottom:12px;\">Schon heute investieren?<\/div>\r\n      <div style=\"display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:800;background:#ffffff;color:#093967;padding:4px 10px;border-radius:999px;margin-bottom:12px;\">ab 0&nbsp;\u20ac Ordergeb\u00fchren<\/div>\r\n      <p style=\"font-size:13px;color:#ffffff;line-height:1.55;margin:0 0 14px 0;\">Investiere bei finanzen.net zero <strong>ab 0&nbsp;\u20ac Ordergeb\u00fchren<\/strong> (zzgl. Spreads) in Aktien, ETFs, Kryptos oder Sparpl\u00e4ne.<\/p>\r\n      <!-- Sichtbarer Hinweis im Haupttext (statt Kleingedrucktes) -->\r\n      <div style=\"background:rgba(255,255,255,0.12);border:1px solid rgba(255,255,255,0.22);border-radius:8px;padding:12px 14px;font-size:13px;color:#ffffff;line-height:1.55;margin-bottom:16px;\">\r\n        Das <strong>Altersvorsorgedepot kommt erst ab 1.&nbsp;Januar&nbsp;2027.<\/strong> Unabh\u00e4ngig davon kannst du schon heute ein <strong>regul\u00e4res Wertpapierdepot<\/strong> bei finanzen.net zero er\u00f6ffnen \u2013 <strong>ohne<\/strong> AVD-F\u00f6rderung (keine Zulagen, keine Steuervorteile).\r\n      <\/div>\r\n      <p style=\"font-size:13px;color:#ffffff;line-height:1.6;margin:0 0 16px 0;\">\r\n        M\u00f6chtest du auf das gef\u00f6rderte AVD warten? Dann trag dich oben zur <strong style=\"color:#ffffff;\">Vormerkung<\/strong> ein \u2013 wir informieren dich rechtzeitig zum Start.\r\n      <\/p>\r\n      <button class=\"button button--primary button--stretch\" onclick=\"window.open('https:\/\/g.finanzen.net\/zero-fnet_331q-ratgeber-avd-riester-rechner','_blank','noopener')\" style=\"display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;padding:13px 18px;line-height:1.4;border-radius:8px;background:#E8327A;border-color:#E8327A;color:#ffffff;width:100%;box-sizing:border-box;\">\r\n        Regul\u00e4res finanzen.net zero Depot er\u00f6ffnen \u2192\r\n      <\/button>\r\n      <div style=\"font-size:11px;color:#ffd9e6;margin-top:8px;text-align:center;\">Regul\u00e4res Depot \u2013 nicht das gef\u00f6rderte AVD<\/div>\r\n      <div style=\"font-size:10px;color:rgba(255,255,255,0.78);line-height:1.45;text-align:center;margin-top:8px;\">ab 0&nbsp;\u20ac Ordergeb\u00fchren an ausgew\u00e4hlten Handelspl\u00e4tzen unter Bedingungen; zzgl. Spreads. Es gelten die Konditionen im Preis- und Leistungsverzeichnis von finanzen.net zero.<\/div>\r\n      <div style=\"font-size:9px;color:rgba(255,255,255,0.8);line-height:1.4;text-align:center;margin-top:5px;\">finanzen.net zero ist vertraglich gebundener Vermittler der DonauCapital Wertpapier GmbH. Depotbank ist die Baader Bank AG.<\/div>\r\n    <\/div>\r\n\r\n    <!-- Disclaimer -->\r\n    <div class=\"disclaimer\">\r\n      <details class=\"avd-hin\"><summary class=\"avd-hin-sum\"><strong>Hinweise<\/strong><span class=\"avd-hin-chev\" aria-hidden=\"true\">&#9662;<\/span><span class=\"avd-hin-hint\">Keine Anlage- oder Handlungsempfehlung &#8211; nur zur ersten Orientierung<\/span><\/summary>\r\n      <ul style=\"list-style:disc;padding-left:20px;display:flex;flex-direction:column;gap:5px;margin-top:8px;\">\r\n        <li>Kaufkraft heute: zuk\u00fcnftige Betr\u00e4ge mit 2 % Inflation p. a. auf den Renteneintritt abgezinst (Realwert). Die Rangfolge der Produkte bleibt unver\u00e4ndert \u2013 reale Werte zeigen den Kaufkraftverlust; Riester liegt real teils im Minus.<\/li>\r\n        <li>Der Vergleich beim Altersvorsorgedepot bezieht sich ausschlie\u00dflich auf das Standarddepot (max. 1,0% Effektivkosten, Lifecycle automatisch gesteuert) \u2013 individuelle Depots k\u00f6nnen abweichen<\/li>\r\n        <li>Monatliche Renten sind Bruttobetr\u00e4ge vor Steuern \u2013 Verzinsung in der Auszahlungsphase nicht ber\u00fccksichtigt (lineare Entnahme)<\/li>\r\n        <li>Nettobetrag: stark vereinfachte Sch\u00e4tzung nach Steuer. <em>Riester &amp; Altersvorsorgedepot<\/em> werden in zwei T\u00f6pfen besteuert: Der <strong>gef\u00f6rderte Teil<\/strong> (Eigenbeitr\u00e4ge bis zum F\u00f6rderh\u00f6chstbetrag \u2013 AVD 1.800 \u20ac\/Jahr zzgl. Zulagen, Riester 2.100 \u20ac\/Jahr inkl. Zulagen \u2013 samt deren Ertr\u00e4gen sowie ein eingebrachtes Guthaben) wird im Alter voll nachgelagert \u00fcber den Einkommensteuertarif (\u00a732a EStG, Steuertarif 2026, inkl. Grundfreibetrag) versteuert. Der <strong>ungef\u00f6rderte Teil<\/strong> (Beitr\u00e4ge dar\u00fcber) wird g\u00fcnstiger besteuert \u2013 die eingezahlte Substanz bleibt steuerfrei, von den Ertr\u00e4gen ist bei der hier unterstellten linearen Entnahme (Auszahlplan) nur die H\u00e4lfte steuerpflichtig (\u00a7 20 Abs. 1 Nr. 6 Satz 2 EStG: f\u00fcr Auszahlungen nach dem 62. Lebensjahr, sobald der Vertrag 12 Jahre besteht \u2013 gerechnet ab heute; liegen bis zum Rentenbeginn weniger als 12 Jahre, sind die Auszahlungen bis dahin auf den vollen Ertrag steuerpflichtig; bei lebenslanger Leibrente stattdessen nur der Ertragsanteil). Deine weiteren Alterseink\u00fcnfte werden steuerlich \u201eunter\" die nachgelagert besteuerte Riester-\/AVD-Rente gelegt, sodass diese mit dem darauf entfallenden (h\u00f6heren) Satz besteuert wird: angegebene gesetzliche Rente nur mit ihrem steuerpflichtigen Anteil (Besteuerungsanteil gestaffelt nach Renteneintrittsjahr, ~84 % in 2026 bis 100 % ab 2058), Betriebsrente voll steuerpflichtig. <em>Kennst du deine gesetzliche Rente nicht<\/em>, wird sie aus deinem heutigen Bruttojahreseinkommen und den Beitragsjahren grob gesch\u00e4tzt (Entgeltpunkte = Einkommen, gedeckelt auf die Beitragsbemessungsgrenze, \u00f7 Durchschnittsentgelt \u00d7 Beitragsjahre \u00d7 Rentenwert; Annahme: durchgehend gearbeitet, Einkommen konstant) \u2013 dieser Sch\u00e4tzwert ist anpassbar und ersetzt keine Renteninformation der DRV. Der Steuertarif des laufenden Jahres dient als N\u00e4herung auch f\u00fcr k\u00fcnftige Renteneintritte. <em>ETF\/Fonds<\/em> werden mit Abgeltungsteuer (effektiv ~18,5 % = 26,375 % abz\u00fcglich 30 % Teilfreistellung f\u00fcr Aktienfonds) nur auf den Gewinn angesetzt; zus\u00e4tzlich wird der Sparer-Pauschbetrag (1.000 \u20ac\/Jahr, 2.000 \u20ac bei Zusammenveranlagung) f\u00fcr jedes Ansparjahr vom steuerpflichtigen Gewinn abgezogen \u2013 Annahme: der Freibetrag wird j\u00e4hrlich genutzt (z. B. \u00fcber die Vorabpauschale oder rollierende Gewinnrealisierung); die tats\u00e4chliche Nutzung kann abweichen. <em>Einzahlphase (Riester &amp; AVD):<\/em> Eigenbeitr\u00e4ge und Zulagen sind als Sonderausgaben absetzbar (Riester gedeckelt auf 2.100 \u20ac\/Jahr gesamt, AVD bis 1.800 \u20ac\/Jahr Eigenbeitrag zzgl. Zulagen \u2013 der dar\u00fcber hinausgehende Teil des Eigenbeitrags ist nicht absetzbar); das Finanzamt nimmt per G\u00fcnstigerpr\u00fcfung den h\u00f6heren Vorteil aus Zulage oder Steuerersparnis. Die so gesch\u00e4tzte j\u00e4hrliche Steuererstattung wird reinvestiert. In den gef\u00f6rderten Vertrag darf sie allerdings nur flie\u00dfen, soweit die gesetzliche Einzahlungsgrenze von 6.840 \u20ac\/Jahr (\u00a7 1 Abs. 1 Satz 1 Nr. 5 AltZertG) noch nicht ausgesch\u00f6pft ist; ein dar\u00fcber hinausgehender Betrag wird als <em>Fonds-Nebendepot<\/em> abgebildet und dort wie ein normales Fondsdepot besteuert \u2013 die Erstattung selbst ist kein steuerbarer Zufluss, versteuert werden nur ihre Gewinne (Abgeltungsteuer, 30 % Teilfreistellung, Sparer-Pauschbetrag). Bei der Standardrate von 150 \u20ac\/Monat entsteht kein Nebendepot; der Erwerbs-Steuersatz wird vereinfacht \u00fcber eine Vorsorgepauschale aus dem Bruttojahreseinkommen abgeleitet (Werbungskostenpauschale 1.230 \u20ac + Arbeitnehmer-Vorsorgeaufwendungen RV\/KV\/PV, 2026) \u2013 ohne Einkommensangabe werden nur die Zulagen ber\u00fccksichtigt. <em>Verheiratete<\/em> k\u00f6nnen das Ehegattensplitting aktivieren (Steuer = 2 \u00d7 Tarif(zvE \u00f7 2)); der Partner geht je nach Angabe als Rente (nur steuerpflichtiger Anteil) oder als Erwerbseinkommen (voll) ein \u2013 bleibt das Feld leer, wird ein Partner ohne eigenes steuerpflichtiges Einkommen unterstellt. <em>Nicht ber\u00fccksichtigt<\/em> sind Kranken-\/Pflegeversicherungsbeitr\u00e4ge (fallen v. a. auf gesetzliche und Betriebsrente an, kaum auf die Riester-\/AVD-Auszahlung), Kirchensteuer sowie steuermindernde Pauschalen auf die Renteneink\u00fcnfte (Werbungskosten, Vorsorgeaufwendungen) \u2013 die ausgewiesene Rentensteuer ist dadurch eher konservativ (tendenziell etwas zu hoch). Kein Ersatz f\u00fcr eine steuerliche Beratung; tats\u00e4chliche Steuers\u00e4tze und -regeln k\u00f6nnen erheblich abweichen.<\/li>\r\n        <li>Max. Einzahlung: 570 \u20ac\/Monat (6.840 \u20ac\/Jahr) \u2013 davon werden bis zu 1.800 \u20ac\/Jahr staatlich gef\u00f6rdert. Die Grenze gilt f\u00fcr Eigenbeitr\u00e4ge inklusive einer reinvestierten Steuererstattung; Zulagen und Ertr\u00e4ge z\u00e4hlen nicht mit.<\/li>\r\n        <li>Automatische Sicherheitsumschichtung vor Renteneintritt (nur Standarddepot): automatische Umschichtung in risiko\u00e4rmere Anlagen vor Renteneintritt \u2013 sch\u00fctzt vor Kurseinbr\u00fcchen, reduziert aber die Rendite in den letzten Jahren<\/li>\r\n        <li>Rendite-Szenarien: Aktien-\/AVD-Renditen abgeleitet aus dem langfristigen DAX-Durchschnitt (Deutsches Aktieninstitut, DAX-Rendite-Dreieck); Riester-Renditen in Anlehnung an Studien (Finanzwende\/Kleinlein ~0,8 %, IVFP ~2,5 %). Alle Werte nach Kosten. Die vergangene Wertentwicklung ist kein verl\u00e4sslicher Indikator f\u00fcr die k\u00fcnftige Wertentwicklung \u2013 tats\u00e4chliche Marktrenditen k\u00f6nnen erheblich abweichen<\/li>\r\n        <li>Riester-Mindesteigenbeitrag: Liegt der Eigenbeitrag unter dem Mindesteigenbeitrag (4 % des rentenversicherungspflichtigen Vorjahreseinkommens, max. 2.100 \u20ac\/Jahr, abz\u00fcglich Zulagen; mindestens Sockelbetrag 60 \u20ac\/Jahr), k\u00fcrzt die ZfA die Zulagen im Verh\u00e4ltnis Eigenbeitrag zu Mindesteigenbeitrag (\u00a7 86 EStG in der bis Ende 2026 geltenden Fassung, gilt f\u00fcr bestehende Riester-Vertr\u00e4ge weiter). Das Tool bildet diese K\u00fcrzung ab, wenn ein Brutto-Jahreseinkommen angegeben ist (Nettobetrag berechnen, Rentenbetr\u00e4ge unbekannt); es gilt vereinfacht als Vorjahreseinkommen. Ohne diese Angabe wird nur der Sockelbetrag von 60 \u20ac\/Jahr angesetzt.<\/li>\r\n        <li>Kinderzulage vereinfacht bis 25. Geburtstag \u2013 tats\u00e4chlich an Kindergeldberechtigung gekn\u00fcpft<\/li>\r\n        <li>Grundsicherung 2026: Regelsatz 563 \u20ac\/Mo. + durchschnittliche Warmmiete ca. 304 \u20ac\/Mo. = ca. 867 \u20ac\/Mo. gesamt \u00b7 Riester-Rente: bis 100 \u20ac\/Mo. zu 100% anrechnungsfrei, 100\u2013200 \u20ac\/Mo. zu 30% anrechnungsfrei (\u00a782 SGB XII) \u00b7 F\u00fcr das Altersvorsorgedepot ist diese Schutzregelung gesetzlich noch nicht verankert (Stand April 2026) \u00b7 Ein Depot\/AVD m\u00fcsste vor Grundsicherung zudem erst bis auf das Schonverm\u00f6gen (~10.000 \u20ac) verbraucht werden<\/li>\r\n        <li>Individuelle Faktoren (Steuerklasse, bestehende Vertr\u00e4ge, pers\u00f6nliche Situation) nicht ber\u00fccksichtigt<\/li>\r\n        <li>F\u00fcr individuelle Beratung bitte zugelassenen Finanzberater hinzuziehen<\/li>\r\n        <li>Wer weniger als 10 Jahre bis zur Rente hat, sollte den Wechsel sorgf\u00e4ltig abw\u00e4gen, da Marktr\u00fcckg\u00e4nge kurz vor Renteneintritt das angesparte Kapital dauerhaft schm\u00e4lern k\u00f6nnen<\/li>\r\n      <\/ul>\r\n      <\/details>\r\n    <\/div>\r\n\r\n  <\/div><!-- \/results -->\r\n<\/div><!-- \/container -->\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     CHART OVERLAY \u2013 Mobile Tap-to-Expand\r\n     Kein Pinch-Zoom. Stabiler f\u00fcr WordPress + Mobile Browser.\r\n     Tap auf Chart \u2192 Overlay \u2192 Chart neu gerendert \u2192 X \/ au\u00dfen schlie\u00dfen.\r\n     \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<div id=\"chart-overlay\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Chart Vollansicht\">\r\n  <div class=\"chart-overlay-card\" id=\"chart-overlay-card\">\r\n    <div class=\"chart-overlay-header\">\r\n      <div>\r\n        <div class=\"chart-overlay-title\" id=\"overlay-title\">Chart<\/div>\r\n        <div class=\"chart-overlay-sub\" id=\"overlay-sub\"><\/div>\r\n      <\/div>\r\n      <button class=\"chart-overlay-close\" onclick=\"closeChartOverlay()\" aria-label=\"Schlie\u00dfen\">\r\n        <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\"><path d=\"M1 1l12 12M13 1L1 13\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\/><\/svg>\r\n      <\/button>\r\n    <\/div>\r\n    <!-- Legende (nur f\u00fcr Linien-Chart) -->\r\n    <div class=\"chart-overlay-legend\" id=\"overlay-legend\" style=\"display:none;\">\r\n      <span><span class=\"leg-line\" style=\"background:#0d6efd;\"><\/span>Riester<\/span>\r\n      <span><span class=\"leg-line\" style=\"background:#e85d1a;\"><\/span>Standarddepot<\/span>\r\n      <span><span class=\"leg-line\" style=\"background:#7c3aed;\"><\/span>Flex-Depot<\/span>\r\n      <span><span class=\"leg-line\" style=\"background:#1D9E75;border-style:dashed;border-width:0 0 2px;\"><\/span>ETF-Sparplan<\/span>\r\n    <\/div>\r\n    <div class=\"chart-overlay-body\">\r\n      <div class=\"chart-overlay-canvas-wrap\">\r\n        <canvas id=\"overlayChart\"><\/canvas>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- Kein separates JS-Bundle n\u00f6tig \u2013 Tooltip-Fallback via CSS hover -->\r\n<!-- Falls script-net.js verf\u00fcgbar: hier einbinden f\u00fcr volle Tooltip-Funktionalit\u00e4t -->\r\n\r\n<template id=\"avd-code-tpl\">\r\n  \/\/ \u2500\u2500 Liniendiagramm \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  var verlaufChartInstance = null;\r\n  var rentenBarChartInstance = null;\r\n  var lastBarRenten = null;   \/\/ letzte Brutto-Monatsrenten (fuer Netto\/Brutto-Umschalter)\r\n  var verlaufCache = null;    \/\/ Brutto-Jahresserien des Linienchart (fuer Netto\/Brutto-Umschalter)\r\n\r\n  function updateRentenBarChart(rRente, dRente, eRente, iRente) {\r\n    if (typeof Chart === \"undefined\") {\r\n      console.warn(\"[AVD-Tool] Chart.js noch nicht geladen \u2013 updateRentenBarChart abgebrochen\");\r\n      return;\r\n    }\r\n    const ctx = document.getElementById('rentenBarChart');\r\n    if (!ctx) return;\r\n    if (rentenBarChartInstance) rentenBarChartInstance.destroy();\r\n    lastBarRenten = { r: rRente, d: dRente, e: eRente, i: iRente };\r\n\r\n    const gsAktivBar = rRente > 0 && rRente < 200;\r\n    const rGsFreiBar = gsAktivBar ? gsFreibetrag(rRente) : 0;\r\n\r\n    let entries, title, sub;\r\n    if (gsAktivBar) {\r\n      title = 'Monatsrente im Vergleich \u2013 Grundsicherungsfall';\r\n      sub = 'Riester inkl. GS-Schutz (\u00a782 SGB XII) \u00b7 AVD\/ETF: normale Monatsrente';\r\n      entries = [\r\n        { label: 'Riester',       val: Math.round(GS_BEDARF +rGsFreiBar), color: '#0d6efd' },\r\n        { label: 'ETF\/Fonds',     val: Math.round(eRente),            color: '#1D9E75' },\r\n        { label: 'AVD Individual',val: Math.round(iRente),            color: '#7c3aed' },\r\n        { label: 'AVD Standard',  val: Math.round(dRente),            color: '#e85d1a' },\r\n      ];\r\n    } else if (chartNettoAktiv()) {\r\n      \/\/ Netto-Ansicht: gleiche Zwei-T\u00f6pfe-Steuerlogik wie die Ergebniskarten (gef\u00f6rdert voll nachgelagert, ungef\u00f6rdert nur Ertrag)\r\n      const monateBar = leJahre * 12;\r\n      const ajBar = nettoAndereJahr();\r\n      const eEingBar = parseFloat(document.getElementById('e-endkapital').dataset.eingezahlt || 0);\r\n      const jahresbeitragBar = (parseFloat(document.getElementById('einzahlung').value) || 0) * 12;\r\n      const guthabenBar = parseFloat((document.getElementById('guthaben').value || '').replace(\/[^0-9]\/g, '')) || 0;\r\n      const nettoMoZwei = (prefix, rente) => {\r\n        const ds = document.getElementById(prefix + '-endkapital').dataset;\r\n        \/\/ E-059 (Nebenbefund): das Fonds-Nebendepot wie auf der Karte abtrennen (angelegt: Abgeltungsteuer nur auf den Gewinn,\r\n        \/\/ nicht angelegt: bereits versteuerter Barbetrag), statt es zwei-t\u00f6pfig nachgelagert zu versteuern\r\n        \/\/ Der Vertrag kommt wie auf der Karte direkt aus data-raw und nicht aus rente mal Monate: berechnen \u00fcbergibt Vertrag plus\r\n        \/\/ Nebendepot, aktualisiereRenten (Auszahldauer-Regler) nur den Vertrag; so passt der Balken in beiden Wegen zur Karte.\r\n        const nb = parseFloat(ds.neben || 0), nbEing = parseFloat(ds.nebenEingezahlt || 0);\r\n        const nbNetto = nb > 0 ? (erstattungAnlegen ? nettoKapitalETF(nb, nbEing, aktuelleLaufzeit) : nb) : 0;\r\n        const endk = parseFloat(ds.raw || 0);\r\n        const zulageGes = parseFloat(ds.zulage || 0);\r\n        const steuerErsp = parseFloat(ds.steuererstattung || 0), steuerErspUng = parseFloat(ds.steuererstattungUng || 0);\r\n        const foerderGrenze = (prefix === 'r')\r\n          ? Math.max(0, 2100 - (aktuelleLaufzeit > 0 ? zulageGes \/ aktuelleLaufzeit : 0))\r\n          : 1800;\r\n        return Math.round((nettoZweiToepfe(endk, jahresbeitragBar, zulageGes, guthabenBar, aktuelleLaufzeit, ajBar, monateBar, foerderGrenze, 'plan', rentenalter, steuerErsp, steuerErspUng) + nbNetto) \/ monateBar);\r\n      };\r\n      title = 'Monatsrente im Vergleich';\r\n      sub = 'Netto \u00b7 nach Steuern (Sch\u00e4tzung)';\r\n      entries = [\r\n        { label: 'Riester',      val: nettoMoZwei('r', rRente), color: '#0d6efd' },\r\n        { label: 'AVD Standard', val: nettoMoZwei('d', dRente), color: '#e85d1a' },\r\n        { label: 'AVD Individual',val: nettoMoZwei('i', iRente), color: '#7c3aed' },\r\n        { label: 'ETF\/Fonds',    val: Math.round(nettoKapitalETF(eRente * monateBar, eEingBar, aktuelleLaufzeit) \/ monateBar), color: '#1D9E75' },\r\n      ];\r\n    } else {\r\n      title = 'Monatsrente im Vergleich';\r\n      sub = 'Brutto \u00b7 ohne Steuer';\r\n      entries = [\r\n        { label: 'Riester',      val: Math.round(rRente), color: '#0d6efd' },\r\n        { label: 'AVD Standard', val: Math.round(dRente), color: '#e85d1a' },\r\n        { label: 'AVD Individual',val: Math.round(iRente), color: '#7c3aed' },\r\n        { label: 'ETF\/Fonds',    val: Math.round(eRente), color: '#1D9E75' },\r\n      ];\r\n    }\r\n    entries.sort((a,b) => b.val - a.val);\r\n\r\n    document.getElementById('barChartTitle').textContent = title;\r\n    document.getElementById('barChartSub').textContent = sub;\r\n\r\n    var barLabelsPlugin = {\r\n      id: 'barLabels',\r\n      afterDraw(chart) {\r\n        const ctx2 = chart.ctx;\r\n        ctx2.save();\r\n        const isMobile = window.innerWidth <= 768;\r\n        ctx2.font = (isMobile ? '600 10px OpenSans, Arial, sans-serif' : '600 11px OpenSans, Arial, sans-serif');\r\n        ctx2.textAlign = 'center';\r\n        ctx2.textBaseline = 'bottom';\r\n        chart.data.datasets.forEach((dataset, i) => {\r\n          chart.getDatasetMeta(i).data.forEach((bar, j) => {\r\n            const val = dataset.data[j];\r\n            ctx2.fillStyle = Array.isArray(dataset.borderColor) ? dataset.borderColor[j] : dataset.borderColor;\r\n            ctx2.fillText(Math.round(val).toLocaleString('de-DE') + ' \u20ac', bar.x, bar.y - (isMobile ? 8 : 4));\r\n          });\r\n        });\r\n        ctx2.restore();\r\n      }\r\n    };\r\n\r\n    rentenBarChartInstance = new Chart(ctx, {\r\n      type: 'bar',\r\n      plugins: [barLabelsPlugin],\r\n      data: {\r\n        labels: entries.map(e => e.label),\r\n        datasets: [{\r\n          data: entries.map(e => e.val),\r\n          backgroundColor: entries.map(e => e.color + '33'),\r\n          borderColor: entries.map(e => e.color),\r\n          borderWidth: 2,\r\n          borderRadius: 6,\r\n        }]\r\n      },\r\n      options: {\r\n        responsive: true,\r\n        maintainAspectRatio: false,\r\n        layout: { padding: { top: 32, left: 4, right: 4, bottom: 4 } },\r\n        animation: false,\r\n        plugins: {\r\n          legend: { display: false },\r\n          tooltip: { callbacks: { label: ctx => Math.round(ctx.raw).toLocaleString('de-DE') + ' \u20ac\/Mo.' } },\r\n          datalabels: { display: false }\r\n        },\r\n        scales: {\r\n          y: {\r\n            beginAtZero: true,\r\n            ticks: { callback: v => v.toLocaleString('de-DE') + ' \u20ac', color: '#6c7a8a', font: { size: 11 } },\r\n            grid: { color: 'rgba(38,145,255,0.06)' }\r\n          },\r\n          x: { ticks: { color: '#6c7a8a', font: { size: 11 } }, grid: { display: false } }\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  function renderVerlaufChart(guthaben, einzahlung, s, alter, ra, childAges) {\r\n    if (typeof Chart === \"undefined\") {\r\n      console.warn(\"[AVD-Tool] Chart.js noch nicht geladen \u2013 renderVerlaufChart abgebrochen\");\r\n      return;\r\n    }\r\n    const laufzeit = ra - alter;\r\n    const labels = [];\r\n    const riesterData = [], depotData = [], etfData = [], individualData = [], eingezahltData = [];\r\n    const riesterFoerder = [], depotFoerder = [], individualFoerder = [];\r\n    const riesterSteuer = [], depotSteuer = [], individualSteuer = [], riesterSteuerUng = [], depotSteuerUng = [], individualSteuerUng = [];   \/\/ E-059: Erstattung gef\u00f6rdert \/ ungef\u00f6rdert\r\n    const riesterNeben = [], depotNeben = [], individualNeben = [];\r\n    const riesterNebenEing = [], depotNebenEing = [], individualNebenEing = [];\r\n\r\n    for (let t = 0; t <= laufzeit; t++) {\r\n      labels.push(alter + t);\r\n      \/\/ Haupt-Rechenfunktionen liefern {kapital, foerderungGesamt, steuererstattungGesamt} \u2013 Kapital wie zuvor, plus F\u00f6rderung+Steuerersparnis je Punkt (Zwei-T\u00f6pfe-Netto)\r\n      const rRes = berechneRiester(guthaben, einzahlung, s.riester, alter, alter + t, childAges, s.etf);\r\n      const dRes = berechneDepot(guthaben, einzahlung, s.depot, alter, alter + t, childAges, ra, s.etf);\r\n      const iRes = berechneIndividual(guthaben, einzahlung, s.depot, alter, alter + t, childAges, s.etf);\r\n      riesterData.push(Math.round(rRes.kapital + (rRes.nebenKapital || 0)));\r\n      depotData.push(Math.round(dRes.kapital + (dRes.nebenKapital || 0)));\r\n      etfData.push(Math.round(berechneETFBis(guthaben, einzahlung, s.etf, alter, alter + t)));\r\n      individualData.push(Math.round(iRes.kapital + (iRes.nebenKapital || 0)));\r\n      riesterFoerder.push(rRes.foerderungGesamt);\r\n      depotFoerder.push(dRes.foerderungGesamt);\r\n      individualFoerder.push(iRes.foerderungGesamt);\r\n      riesterSteuer.push(rRes.steuererstattungGef || 0); riesterSteuerUng.push(rRes.steuererstattungUng || 0);   \/\/ E-059: gef\u00f6rdert \/ ungef\u00f6rdert\r\n      depotSteuer.push(dRes.steuererstattungGef || 0); depotSteuerUng.push(dRes.steuererstattungUng || 0);\r\n      individualSteuer.push(iRes.steuererstattungGef || 0); individualSteuerUng.push(iRes.steuererstattungUng || 0);\r\n      riesterNeben.push(rRes.nebenKapital || 0);\r\n      depotNeben.push(dRes.nebenKapital || 0);\r\n      individualNeben.push(iRes.nebenKapital || 0);\r\n      riesterNebenEing.push(rRes.nebenEingezahlt || 0);\r\n      depotNebenEing.push(dRes.nebenEingezahlt || 0);\r\n      individualNebenEing.push(iRes.nebenEingezahlt || 0);\r\n      eingezahltData.push(guthaben + einzahlung * 12 * t);\r\n    }\r\n\r\n    verlaufCache = { labels, riesterData, depotData, etfData, individualData, eingezahltData, riesterFoerder, depotFoerder, individualFoerder, riesterSteuer, depotSteuer, individualSteuer, riesterSteuerUng, depotSteuerUng, individualSteuerUng, riesterNeben, depotNeben, individualNeben, riesterNebenEing, depotNebenEing, individualNebenEing, guthaben, jahresbeitrag: einzahlung * 12 };\r\n    drawVerlaufChart();\r\n  }\r\n\r\n  \/\/ Zeichnet das Linienchart aus dem Cache \u2013 je nach Umschalter brutto oder netto (nach Steuern bei Auszahlung)\r\n  function drawVerlaufChart() {\r\n    if (!verlaufCache) return;\r\n    if (typeof Chart === \"undefined\") return;\r\n    const c = verlaufCache;\r\n    const nettoAn = chartNettoAktiv();\r\n    let rD = c.riesterData, dD = c.depotData, eD = c.etfData, iD = c.individualData;\r\n    if (nettoAn) {\r\n      const monate = leJahre * 12;\r\n      const aj = nettoAndereJahr();\r\n      \/\/ Zwei-T\u00f6pfe-Netto je Jahrespunkt \u2013 gleiche Logik wie Karten &#038; Balkenchart (gef\u00f6rdert voll nachgelagert, ungef\u00f6rdert nur Ertrag)\r\n      \/\/ kap ist hier das GESAMTvermoegen; der Nebendepot-Anteil wird herausgerechnet und\r\n      \/\/ separat mit Abgeltungsteuer belastet (nur der Gewinn), der Rest zwei-toepfig.\r\n      const zweiToNetto = (kap, foerder, steuer, jahre, prefix, neben, nebenEing, steuerUng) => {\r\n        const foerderGrenze = (prefix === 'r')\r\n          ? Math.max(0, 2100 - (jahre > 0 ? foerder \/ jahre : 0))\r\n          : 1800;\r\n        const nb = neben || 0;\r\n        const avdTeil = Math.max(0, kap - nb);\r\n        return Math.round(nettoZweiToepfe(avdTeil, c.jahresbeitrag, foerder, c.guthaben, jahre, aj, monate, foerderGrenze, 'plan', rentenalter, steuer, steuerUng))\r\n             + (nb > 0 ? Math.round(erstattungAnlegen ? nettoKapitalETF(nb, nebenEing || 0, jahre) : nb) : 0);\r\n      };\r\n      rD = c.riesterData.map((k, idx) => zweiToNetto(k, c.riesterFoerder[idx], c.riesterSteuer[idx], idx, 'r', (c.riesterNeben||[])[idx], (c.riesterNebenEing||[])[idx], (c.riesterSteuerUng||[])[idx]));\r\n      dD = c.depotData.map((k, idx) => zweiToNetto(k, c.depotFoerder[idx], c.depotSteuer[idx], idx, 'd', (c.depotNeben||[])[idx], (c.depotNebenEing||[])[idx], (c.depotSteuerUng||[])[idx]));\r\n      iD = c.individualData.map((k, idx) => zweiToNetto(k, c.individualFoerder[idx], c.individualSteuer[idx], idx, 'i', (c.individualNeben||[])[idx], (c.individualNebenEing||[])[idx], (c.individualSteuerUng||[])[idx]));\r\n      eD = c.etfData.map((k, idx) => Math.round(nettoKapitalETF(k, c.eingezahltData[idx], idx)));\r\n    }\r\n    const subEl = document.getElementById('lineChartSub');\r\n    if (subEl) subEl.textContent = nettoAn\r\n      ? 'Netto nach Steuern \u2013 was bei Auszahlung \u00fcber die gew\u00e4hlte Dauer \u00fcbrig bliebe'\r\n      : 'Verm\u00f6gensentwicklung von heute bis zum Renteneintritt';\r\n\r\n    if (verlaufChartInstance) verlaufChartInstance.destroy();\r\n    verlaufChartInstance = new Chart(document.getElementById('verlaufChart'), {\r\n      type: 'line',\r\n      data: {\r\n        labels: c.labels,\r\n        datasets: [\r\n          { label: 'Riester',               data: rD,    borderColor: '#0d6efd', backgroundColor: 'rgba(13,110,253,0.06)',  fill: false, tension: 0.3, pointRadius: 2, borderWidth: 2 },\r\n          { label: 'Altersvorsorgedepot',    data: dD,      borderColor: '#e85d1a', backgroundColor: 'rgba(232,93,26,0.06)',   fill: false, tension: 0.3, pointRadius: 2, borderWidth: 2.5 },\r\n          { label: 'ETF-Sparplan',           data: eD,        borderColor: '#1D9E75', backgroundColor: 'rgba(29,158,117,0.04)',  fill: false, tension: 0.3, pointRadius: 2, borderWidth: 2, borderDash: [5,4] },\r\n          { label: 'AVD Flex-Depot', data: iD, borderColor: '#7c3aed', backgroundColor: 'rgba(124,58,237,0.04)', fill: false, tension: 0.3, pointRadius: 2, borderWidth: 2.5 }\r\n        ]\r\n      },\r\n      options: {\r\n        responsive: true,\r\n        maintainAspectRatio: false,\r\n        plugins: { legend: { display: false } },\r\n        scales: {\r\n          x: { title: { display: true, text: 'Alter', color: '#6c7a8a', font: { size: 12 } }, ticks: { color: '#6c7a8a' }, grid: { color: 'rgba(38,145,255,0.06)' } },\r\n          y: { ticks: { color: '#6c7a8a', callback: v => v >= 1000000 ? (v\/1000000).toFixed(1) + ' Mio. \u20ac' : v >= 1000 ? (v\/1000).toFixed(0) + ' T\u20ac' : v + ' \u20ac' }, grid: { color: 'rgba(38,145,255,0.06)' } }\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  \/\/ \u2500\u2500 Hilfsfunktionen f\u00fcr j\u00e4hrliche Zwischenwerte \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  function berechneRiesterBis(guthaben, e, r, alterStart, alterZiel, startChildAges) {\r\n    const monatsrendite = Math.pow(1 + r, 1\/12) - 1;\r\n    let kapital = guthaben;\r\n    const kinder = [...startChildAges];\r\n    const laufzeit = alterZiel - alterStart;\r\n    for (let jahr = 1; jahr <= laufzeit; jahr++) {\r\n      for (let m = 0; m < 12; m++) kapital = kapital * (1 + monatsrendite) + e;\r\n      const jb = e * 12;\r\n      if (jb >= 60) {\r\n        let z = 175;\r\n        for (let k = 0; k < kinder.length; k++) {\r\n          if (kinder[k] >= 0 && kinder[k] < 25) {\r\n            z += (AKTUELLES_JAHR - startChildAges[k] >= 2008 ? 300 : 185);\r\n          }\r\n        }\r\n        kapital += z;\r\n        var _rf = sonderausgabenErstattung(jb, z, getErwerbsBrutto(), 'riester');\r\n        if (_rf > 0) kapital += _rf;\r\n      }\r\n      for (let k = 0; k < kinder.length; k++) kinder[k]++;\r\n    }\r\n    return kapital;\r\n  }\r\n\r\n  function berechneDepotBis(guthaben, e, r, alterStart, alterZiel, startChildAges) {\r\n    const laufzeit = alterZiel - alterStart;\r\n    const kinder = [...startChildAges];\r\n    let kapital = guthaben + (alterStart < 25 ? (e * 12 >= 120 ? 200 : 0) : 0);\r\n    for (let jahr = 1; jahr <= laufzeit; jahr++) {\r\n      const jahreVorRente = laufzeit - jahr;\r\n      let rendite = jahreVorRente > 5 ? r : jahreVorRente > 2 ? r * 0.5 : r * 0.3;\r\n      const mz = Math.pow(1 + rendite, 1\/12) - 1;\r\n      for (let m = 0; m < 12; m++) kapital = kapital * (1 + mz) + e;\r\n      const jb = e * 12;\r\n      let fj = 0;\r\n      if (jb >= 120) { fj = Math.min(jb, 360) * 0.50 + Math.max(0, Math.min(jb, 1800) - 360) * 0.25; }\r\n      if (jb >= 120) { for (let k = 0; k < kinder.length; k++) { if (kinder[k] >= 0 && kinder[k] < 25) fj += Math.min(jb, 300); } }\r\n      if (fj > 0) kapital += fj;\r\n      var _refund = sonderausgabenErstattung(Math.min(jb, AVD_ABZUG_MAX), fj, getErwerbsBrutto());\r\n      if (_refund > 0) kapital += _refund;\r\n      for (let k = 0; k < kinder.length; k++) kinder[k]++;\r\n    }\r\n    return kapital;\r\n  }\r\n\r\n  function berechneIndividualBis(guthaben, e, r, alterStart, alterZiel, startChildAges) {\r\n    const laufzeit = alterZiel - alterStart;\r\n    const kinder = [...startChildAges];\r\n    let kapital = guthaben + (alterStart < 25 ? (e * 12 >= 120 ? 200 : 0) : 0);\r\n    const monatsrendite = Math.pow(1 + r, 1\/12) - 1;\r\n    for (let jahr = 1; jahr <= laufzeit; jahr++) {\r\n      for (let monat = 0; monat < 12; monat++) kapital = kapital * (1 + monatsrendite) + e;\r\n      const jb = e * 12;\r\n      let fj = 0;\r\n      if (jb >= 120) { fj = Math.min(jb, 360) * 0.50 + Math.max(0, Math.min(jb, 1800) - 360) * 0.25; }\r\n      if (jb >= 120) { for (let k = 0; k < kinder.length; k++) { if (kinder[k] >= 0 && kinder[k] < 25) fj += Math.min(jb, 300); } }\r\n      if (fj > 0) kapital += fj;\r\n      var _refund = sonderausgabenErstattung(Math.min(jb, AVD_ABZUG_MAX), fj, getErwerbsBrutto());\r\n      if (_refund > 0) kapital += _refund;\r\n      for (let k = 0; k < kinder.length; k++) kinder[k]++;\r\n    }\r\n    return kapital;\r\n  }\r\n\r\n  function berechneETFBis(guthaben, e, r, alterStart, alterZiel) {\r\n    const monatsrendite = Math.pow(1 + r, 1\/12) - 1;\r\n    let kapital = guthaben;\r\n    const laufzeit = alterZiel - alterStart;\r\n    for (let jahr = 1; jahr <= laufzeit; jahr++) {\r\n      for (let m = 0; m < 12; m++) kapital = kapital * (1 + monatsrendite) + e;\r\n    }\r\n    return kapital;\r\n  }\r\n\r\n  var childAges = [];\r\n  var numChildren = 0;\r\n  var szenarioVal = 1.0;\r\n  var rentenalter = 67;\r\n  function updateRenteneintritt(val) {\r\n    rentenalter = parseInt(val);\r\n    document.getElementById('renteneintrittDisplay').textContent = rentenalter + ' Jahre';\r\n    var rtEl = document.getElementById('renteneintritt'); if (rtEl) rtEl.setAttribute('aria-valuetext', rentenalter + ' Jahre');\r\n    var a = document.getElementById('alter');\r\n    if (a) { a.max = rentenalter - 1; if (parseInt(a.value) > rentenalter - 1) a.value = rentenalter - 1; }\r\n    updateLE85Warn();\r\n    berechnenLive();\r\n  }\r\n\r\n  \/\/ === \u00a782 SGB XII \u2013 Grundsicherungs-Schutz gef\u00f6rderter Altersvorsorge (Riester) ===\r\n  var GS_REGELBEDARF = 563;                           \/\/ Regelbedarfsstufe 1 (2026)\r\n  var GS_WARMMIETE   = 304;                            \/\/ \u00d8 Warmmiete (Annahme)\r\n  var GS_BEDARF      = GS_REGELBEDARF + GS_WARMMIETE;  \/\/ 867 \u20ac Grundsicherungs-Bedarf\r\n  var GS_FREI_CAP    = 0.5 * GS_REGELBEDARF;           \/\/ 281,50 \u20ac H\u00f6chst-Freibetrag (\u00a782 Abs. 4)\r\n  function gsFreibetrag(rRente) {\r\n    \/\/ 100 % der ersten 100 \u20ac + 30 % des Einkommens \u00fcber 100 \u20ac, gedeckelt bei 50 % Regelbedarf\r\n    return Math.min(Math.min(rRente, 100) + Math.max(0, rRente - 100) * 0.30, GS_FREI_CAP);\r\n  }\r\n\r\n  var szenarien = [\r\n    { name: 'Defensiv', riester: 0.005, depot: 0.035, etf: 0.035 },\r\n    { name: 'Neutral',  riester: 0.010, depot: 0.055, etf: 0.055 },\r\n    { name: 'Offensiv', riester: 0.025, depot: 0.075, etf: 0.075 }\r\n  ];\r\n\r\n  function interpolateSzenario(val) {\r\n    if (val <= 1) {\r\n      const t = val;\r\n      return {\r\n        riester: szenarien[0].riester + (szenarien[1].riester - szenarien[0].riester) * t,\r\n        depot:   szenarien[0].depot   + (szenarien[1].depot   - szenarien[0].depot)   * t,\r\n        etf:     szenarien[0].etf     + (szenarien[1].etf     - szenarien[0].etf)     * t,\r\n      };\r\n    } else {\r\n      const t = val - 1;\r\n      return {\r\n        riester: szenarien[1].riester + (szenarien[2].riester - szenarien[1].riester) * t,\r\n        depot:   szenarien[1].depot   + (szenarien[2].depot   - szenarien[1].depot)   * t,\r\n        etf:     szenarien[1].etf     + (szenarien[2].etf     - szenarien[1].etf)     * t,\r\n      };\r\n    }\r\n  }\r\n\r\n  function getSzenarioName(val) {\r\n    if (val < 0.67) return 'Defensiv';\r\n    if (val <= 1.33) return 'Neutral';\r\n    return 'Offensiv';\r\n  }\r\n\r\n  function updateSzenario(val) {\r\n    szenarioVal = parseFloat(val);\r\n    const s = interpolateSzenario(szenarioVal);\r\n    document.getElementById('scenario-name').textContent = getSzenarioName(szenarioVal);\r\n    document.getElementById('scenario-rates').textContent =\r\n      `Riester ${(s.riester*100).toFixed(1)}% \u00b7 Altersvorsorgedepot ${(s.depot*100).toFixed(1)}% \u00b7 ETF\/Fonds ${(s.etf*100).toFixed(1)}%`;\r\n    var szEl = document.getElementById('szenario'); if (szEl) szEl.setAttribute('aria-valuetext', `${getSzenarioName(szenarioVal)} \u2013 Riester ${(s.riester*100).toFixed(1)} %, Altersvorsorgedepot ${(s.depot*100).toFixed(1)} %, ETF\/Fonds ${(s.etf*100).toFixed(1)} %`);\r\n    var szAktiv = Math.max(0, Math.min(2, Math.round(szenarioVal)));\r\n    [0,1,2].forEach(i => {\r\n      var b = document.getElementById('label-'+i);\r\n      if (b) { b.className = 'sz-btn' + (i === szAktiv ? ' active' : ''); b.setAttribute('aria-pressed', i === szAktiv ? 'true' : 'false'); }\r\n    });\r\n    berechnenLive();\r\n  }\r\n\r\n  \/\/ Szenario-Button \u2192 Slider auf feste Stufe snappen + neu rechnen\r\n  function setSzenario(i) {\r\n    var sl = document.getElementById('szenario');\r\n    if (sl) sl.value = i;\r\n    updateSzenario(i);\r\n  }\r\n\r\n  var leJahre = 18;\r\n  var INFLATION = 0.02;\r\n  var aktuelleLaufzeit = 0;\r\n  function realwert(nominal, jahre){ return nominal \/ Math.pow(1 + INFLATION, jahre); }\r\n  function toggleKaufkraft(cb){ var w = document.querySelector('.tool-wrapper'); if (w) w.classList.toggle('kaufkraft-an', cb.checked); }\r\n\r\n  \/\/ \u2500\u2500 Netto \/ Steuer (vereinfacht) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  var nettoAktiv = false;\r\n  var nettoPfad = null;              \/\/ null | 'kenne' | 'schaetzen'\r\n  var beitragsjahreTouched = false; var gesRenteGeschaetzt = false;  \/\/ Beitragsjahre manuell ge\u00e4ndert? (dann nicht mehr vorbelegen)\r\n  var gesetzlRenteMo = 0;            \/\/ gesetzliche Rente \u20ac\/Monat (steuerpflichtige Basis vor Besteuerungsanteil)\r\n  var betriebsRenteMo = 0;           \/\/ Betriebsrente \u20ac\/Monat\r\n  var splittingAktiv = false;        \/\/ Ehegattensplitting (Zusammenveranlagung)\r\n  var partnerTyp = 'rente';          \/\/ 'rente' (\u20ac\/Mo, anteilig) | 'job' (\u20ac\/Jahr, voll)\r\n  var partnerWert = 0;               \/\/ Roh-Eingabewert Partner (Bedeutung je nach partnerTyp) (nur Modus 'weitere')\r\n\r\n  \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n  \/\/ STEUER-PARAMETER \u00b7 Stand: Steuerjahr 2026 (\u00a732a EStG, BMF Lohnsteuer-Handbuch 2026)\r\n  \/\/ \u25bc\u25bc\u25bc EINMAL PRO JAHR HIER AKTUALISIEREN \u2013 diese Werte sind die einzige Quelle \u25bc\u25bc\u25bc\r\n  \/\/ Quelle: bundesfinanzministerium.de (Amtliches Lohnsteuer-Handbuch, \u00a732a)\r\n  \/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n  var STEUER = {\r\n    jahr: 2026,\r\n    grundfreibetrag: 12348,\r\n    \/\/ \u00a732a-Tarifzonen (progressive Zonen als Polynom, obere Zonen linear)\r\n    z2_bis: 17799,  z2_a: 914.51, z2_b: 1400,                   \/\/ Zone 2: (a\u00b7y + b)\u00b7y,        y = (E \u2212 Grundfreibetrag)\/10000\r\n    z3_bis: 69878,  z3_a: 173.10, z3_b: 2397, z3_c: 1034.87,    \/\/ Zone 3: (a\u00b7z + b)\u00b7z + c,    z = (E \u2212 z2_bis)\/10000\r\n    z4_bis: 277825, z4_satz: 0.42, z4_abzug: 11135.63,          \/\/ Zone 4: satz\u00b7E \u2212 abzug\r\n    z5_satz: 0.45,  z5_abzug: 19470.38,                          \/\/ Zone 5: satz\u00b7E \u2212 abzug\r\n    \/\/ Kapitalertr\u00e4ge ETF\/Fonds\r\n    abgeltungsteuer: 0.26375,   \/\/ 25 % Abgeltungsteuer + 5,5 % Soli\r\n    teilfreistellung: 0.30,     \/\/ 30 % steuerfrei bei Aktienfonds (\u00a720 InvStG)\r\n    sparerpauschbetrag: 1000,   \/\/ Sparer-Pauschbetrag \u00a720 Abs. 9 EStG (\u20ac\/Jahr; 2.000 \u20ac bei Zusammenveranlagung)\r\n    \/\/ Besteuerungsanteil gesetzliche Rente: Staffel nach Renteneintrittsjahr (82,5 % in 2023, +0,5 %-Pkt\/Jahr, max 100 % ab 2058)\r\n    rente_ba_basisjahr: 2023, rente_ba_basiswert: 0.825, rente_ba_proJahr: 0.005,\r\n    \/\/ Sch\u00e4tzung gesetzliche Rente aus Bruttojahreseinkommen (grobe N\u00e4herung, Werte j\u00e4hrlich pflegen)\r\n    durchschnittsentgelt: 50493,   \/\/ vorl\u00e4ufiges Durchschnittsentgelt der GRV (\u20ac\/Jahr)\r\n    rentenwert: 42.52,             \/\/ aktueller Rentenwert (\u20ac je Entgeltpunkt \/ Monat; ab 01.07.2026)\r\n    bbg_jahr: 96600,               \/\/ Beitragsbemessungsgrenze Rente (\u20ac\/Jahr)\r\n    annahme_berufsstart: 20        \/\/ angenommener Berufseinstieg (f\u00fcr Beitragsjahre-Vorbelegung)\r\n  };\r\n  \/\/ \u25b2\u25b2\u25b2 Ende j\u00e4hrlich zu pflegender Block \u25b2\u25b2\u25b2\r\n\r\n  \/\/ Einkommensteuer nach \u00a732a EStG auf ein zu versteuerndes Einkommen (Tarif aus STEUER)\r\n  function einkommensteuer(zvE){\r\n    var gfb = STEUER.grundfreibetrag;\r\n    if (zvE <= gfb)         return 0;\r\n    if (zvE <= STEUER.z2_bis) { var y = (zvE - gfb) \/ 10000;        return (STEUER.z2_a * y + STEUER.z2_b) * y; }\r\n    if (zvE <= STEUER.z3_bis) { var z = (zvE - STEUER.z2_bis) \/ 10000; return (STEUER.z3_a * z + STEUER.z3_b) * z + STEUER.z3_c; }\r\n    if (zvE <= STEUER.z4_bis) return STEUER.z4_satz * zvE - STEUER.z4_abzug;\r\n    return STEUER.z5_satz * zvE - STEUER.z5_abzug;\r\n  }\r\n  \/\/ Besteuerungsanteil der gesetzlichen Rente, gestaffelt nach Renteneintrittsjahr\r\n  \/\/ \u2500\u2500 Einzahlphase: Sonderausgabenabzug (G\u00fcnstigerpr\u00fcfung) f\u00fcr AVD &#038; Riester \u2500\u2500\r\n  \/\/ Erwerbs-zvE via vereinfachter Vorsorgepauschale (AN-Anteile 2026: RV 9,3 % bis BBG\r\n  \/\/ 101.400 \u20ac, KV 8,75 %\u00d70,96 + PV 1,8 % bis BBG 69.750 \u20ac, Werbungskosten 1.230 \u20ac).\r\n  \/\/ Abzugsf\u00e4hig: AVD = Eigenbeitrag (max 1.800 \u20ac) + Zulagen ohne Berufseinsteigerbonus; Riester = Eigenbeitrag + Zulagen,\r\n  \/\/ gedeckelt auf 2.100 \u20ac\/Jahr gesamt. Erstattung = Steuerersparnis \u2212 bereits erhaltene Zulage.\r\n  function zvErwerb(brutto){\r\n    if (brutto <= 0) return 0;\r\n    var rv = Math.min(brutto, 101400) * 0.093;\r\n    var kv = Math.min(brutto, 69750) * 0.0875 * 0.96;\r\n    var pv = Math.min(brutto, 69750) * 0.018;\r\n    return Math.max(0, brutto - 1230 - rv - kv - pv);\r\n  }\r\n  \/\/ AVD-Abzug \u00a7 10a Abs. 1 Satz 1 EStG (ab 2027): Eigenbeitrag bis 1.800 \u20ac zzgl. zustehender Zulage (ohne Berufseinsteigerbonus).\r\n  \/\/ Eigene Grenze, nicht die Einzahlungsgrenze AVD_EIGEN_MAX (6.840 \u20ac, \u00a7 1 AltZertG).\r\n  var AVD_ABZUG_MAX = 1800;\r\n  function sonderausgabenErstattung(eigenJahr, zulageJahr, brutto, modus){\r\n    if (brutto <= 0) return 0;\r\n    var zvE = zvErwerb(brutto);\r\n    var abzug = (modus === 'riester') ? Math.min(eigenJahr + zulageJahr, 2100) : (Math.min(eigenJahr, AVD_ABZUG_MAX) + zulageJahr);\r\n    var ersparnis = einkommensteuer(zvE) - einkommensteuer(Math.max(0, zvE - abzug));\r\n    return Math.max(0, ersparnis - zulageJahr);\r\n  }\r\n  \/\/ \u2500\u2500 B1: Einzahlungsgrenze \u00a7 1 Abs. 1 Satz 1 Nr. 5 AltZertG \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  \/\/ In den Vertrag duerfen pro Kalenderjahr hoechstens 6.840 EUR Altersvorsorge-\r\n  \/\/ beitraege fliessen; Zulagen, Ertraege und (kuenftig) die Fruehstartrente\r\n  \/\/ zaehlen nicht an. Eine reinvestierte Steuererstattung ist dagegen eigenes Geld\r\n  \/\/ und damit ein normaler Beitrag - sie passt nur noch in die Restluft. Der\r\n  \/\/ Ueberhang wandert in ein ungefoerdertes ETF-Nebendepot: die Erstattung selbst\r\n  \/\/ ist kein steuerbarer Zufluss, nur ihre Ertraege werden dort mit Abgeltungsteuer\r\n  \/\/ belastet (nettoKapitalETF).\r\n  var AVD_EIGEN_MAX = 6840;\r\n  \/\/ Default bewusst konservativ: der Ueberhang wird NICHT angelegt, sondern nur ausgewiesen.\r\n  var erstattungAnlegen = true;\r\n  function toggleErstattungAnlegen(el){\r\n    erstattungAnlegen = !!(el &#038;&#038; el.checked);\r\n    if (typeof berechnenLive === 'function') berechnenLive();   \/\/ gleiches Muster wie toggleNetto\r\n  }\r\n  function erstattungSplit(refund, jahresbeitrag){\r\n    var r    = Math.max(0, refund || 0);\r\n    var luft = Math.max(0, AVD_EIGEN_MAX - Math.max(0, jahresbeitrag || 0));\r\n    var rein = Math.min(r, luft);\r\n    return { avd: rein, neben: r - rein };\r\n  }\r\n\r\n  \/\/ E-059b (Entscheidung D1): Einkommen f\u00fcr die Riester-K\u00fcrzung nach \u00a7 86 Abs. 1 EStG a. F. (berechneRiester). Es z\u00e4hlt nur,\r\n  \/\/ wenn das Feld Brutto-Jahreseinkommen (heute) im aktuellen Zustand sichtbar und wirksam ist (Nettobetrag berechnen an und\r\n  \/\/ Weg Rentenbetr\u00e4ge unbekannt) oder wenn es selbst eingegeben oder ge\u00e4ndert wurde (input-Ereignis, bleibt danach wirksam).\r\n  \/\/ Sonst 0: Mindesteigenbeitrag ist dann der Sockelbetrag von 60 \u20ac (BMF 05.10.2023 Rn. 65), ab 60 \u20ac Beitrag im Jahr ist die\r\n  \/\/ Zulage ungek\u00fcrzt wie vor E-059. Die Steuererstattung (Sonderausgabenabzug, E-055) liest das Feld weiter immer \u00fcber\r\n  \/\/ getErwerbsBrutto (bekannte Modellannahme: das Feld ist mit 45.000 \u20ac vorbelegt, auch wenn es verdeckt ist).\r\n  var bruttoSelbstGeaendert = false;\r\n  document.addEventListener(`input`, function (e) {\r\n    if (e.target ? e.target.id === `brutto-jahr` : false) bruttoSelbstGeaendert = true;\r\n  }, true);   \/\/ Capture-Phase: gesetzt, bevor der Inline-Handler schaetzAusEinkommen neu rechnen l\u00e4sst\r\n  function einkommenFuerRiesterKuerzung(){\r\n    var sichtbar = nettoAktiv ? nettoPfad === `schaetzen` : false;\r\n    return (sichtbar || bruttoSelbstGeaendert) ? getErwerbsBrutto() : 0;\r\n  }\r\n  function getErwerbsBrutto(){\r\n    var el = document.getElementById('brutto-jahr');\r\n    return el ? (parseFloat((el.value || '').replace(\/[^0-9]\/g, '')) || 0) : 0;\r\n  }\r\n  function besteuerungsanteilGesRente(rentenjahr){\r\n    return Math.min(1, STEUER.rente_ba_basiswert + Math.max(0, rentenjahr - STEUER.rente_ba_basisjahr) * STEUER.rente_ba_proJahr);\r\n  }\r\n  \/\/ Tarif inkl. optionalem Ehegattensplitting: Steuer = 2 \u00d7 \u00a732a(zvE \u00f7 2)\r\n  function tarifNetto(zvE){ return splittingAktiv ? 2 * einkommensteuer(zvE \/ 2) : einkommensteuer(zvE); }\r\n  \/\/ Effektiver Satz auf die nachgelagert besteuerte AVD\/Riester-Rente (Differenzmethode):\r\n  \/\/ andere Eink\u00fcnfte liegen \u201edarunter\", die AVD-Rente wird mit dem darauf entfallenden Satz besteuert\r\n  function nachgelagertSatz(avdJahr, andereJahr){\r\n    if (avdJahr <= 0) return 0;\r\n    return (tarifNetto(andereJahr + avdJahr) - tarifNetto(andereJahr)) \/ avdJahr;\r\n  }\r\n  \/\/ Ertragsanteil (\u00a722 Nr.1 EStG, gek\u00fcrzte Tabelle) f\u00fcr ungef\u00f6rderte Leibrente nach Beginnalter\r\n  function ertragsanteil(a){ if (a>=67) return 0.17; if (a>=65) return 0.18; if (a>=60) return 0.22; return 0.26; }\r\n  \/\/ AVD-\/Riester-Auszahlbesteuerung in zwei T\u00f6pfen (offizielle Logik, Reform 2027):\r\n  \/\/  \u2022 gef\u00f6rderter Teil (Eigenbeitrag bis foerderGrenze + Zulagen + Guthaben + deren Ertr\u00e4ge) \u2192 voll nachgelagert\r\n  \/\/  \u2022 ungef\u00f6rderter Teil (Beitrag \u00fcber foerderGrenze) \u2192 nur die Ertr\u00e4ge; Substanz steuerfrei\r\n  \/\/      form 'plan' (Auszahlplan\/Kapital): \u00bd des Ertrags steuerpflichtig, aber nur in Auszahljahren nach Ablauf\r\n  \/\/        von 12 Jahren seit Vertragsabschluss (\u00a7 20 Abs. 1 Nr. 6 Satz 2 EStG, E-059); davor der volle Ertrag\r\n  \/\/      form 'rente' (lebenslange Leibrente): Ertragsanteil \u00d7 Rente steuerpflichtig\r\n  function nettoZweiToepfe(endk, jahresbeitrag, zulageGesamt, guthaben, jahre, andereJahr, monate, foerderGrenze, form, alterBeginn, steuerersparnis, steuerersparnisUng){\r\n    if (endk <= 0 || monate <= 0) return endk;\r\n    var ungJahr     = Math.max(0, Math.min(jahresbeitrag, 6840) - foerderGrenze);\r\n    \/\/ E-059: Die wieder eingezahlte Erstattung ist ein Beitrag des Folgejahres (\u00a7 82 Abs. 1, \u00a7 88 EStG). steuerersparnis ist nur\r\n    \/\/ ihr gef\u00f6rderter Teil (bis zur F\u00f6rderh\u00f6chstgrenze) und z\u00e4hlt zum gef\u00f6rderten Topf, erh\u00f6ht aber NICHT die Eigenbeitrag-Grenze.\r\n    \/\/ steuerersparnisUng ist die \u00dcberzahlung dar\u00fcber und z\u00e4hlt als Substanz zum ungef\u00f6rderten Topf (\u00a7 22 Nr. 5 Satz 2 EStG;\r\n    \/\/ BMF 05.10.2023 Rn. 133 und 136). Ohne das 12. Argument rechnet die Funktion wie bisher.\r\n    var ungSubstanz = ungJahr * Math.max(0, jahre) + Math.max(0, steuerersparnisUng || 0);\r\n    var gefBeitr    = (guthaben || 0) + Math.min(jahresbeitrag, foerderGrenze) * Math.max(0, jahre) + (zulageGesamt || 0) + (steuerersparnis || 0);\r\n    var sumBeitr    = gefBeitr + ungSubstanz;\r\n    if (sumBeitr <= 0) return endk * (1 - nachgelagertSatz((endk \/ monate) * 12, andereJahr));\r\n    var ungEndk   = endk * ungSubstanz \/ sumBeitr;\r\n    var gefEndk   = endk - ungEndk;\r\n    var gefRenteJ = (gefEndk \/ monate) * 12;\r\n    var nettoGef  = gefEndk * (1 - nachgelagertSatz(gefRenteJ, andereJahr));\r\n    if (ungEndk <= 0) return nettoGef;\r\n    var ungErtrag = Math.max(0, ungEndk - ungSubstanz);\r\n    \/\/ 12-Jahres-Frist (\u00a7 20 Abs. 1 Nr. 6 Satz 2 EStG, entsprechend \u00fcber \u00a7 22 Nr. 5 Satz 2 Buchst. c; E-059, gleiche Regel wie\r\n    \/\/ 7.9\/E-057): h\u00e4lftig nur f\u00fcr Auszahlungen nach dem 62. Lebensjahr (Rentenbeginn ab 65: immer erf\u00fcllt) UND nach Ablauf von\r\n    \/\/ 12 Jahren seit Vertragsabschluss (= heute; ein Abschluss erst ab 2027 in PreLaunch ist nicht eingerechnet).\r\n    \/\/ Auszahljahr j (ab 0) ist h\u00e4lftig, wenn jahre + j >= 12. Unterstellt sind Monatsraten am Monatsende: die erste Rate eines\r\n    \/\/ solchen Jahres flie\u00dft nach mehr als 12 Jahren Laufzeit (BMF 05.10.2023 Rn. 148: Laufzeit von mehr als zw\u00f6lf Jahren),\r\n    \/\/ die letzte Rate davor genau nach 12 Jahren und damit noch voll. Die Auszahljahre davor tragen den vollen Ertrag.\r\n    \/\/ Jeder Abschnitt wird mit seinem eigenen Jahressatz besteuert (Progression), die Netto-Monatsrente ist der Mittelwert\r\n    \/\/ \u00fcber die Auszahldauer. Ab jahre >= 12 ist anteilVoll = 0 und das Ergebnis identisch mit der bisherigen Rechnung.\r\n    var istRente   = (form === 'rente');\r\n    var anteilVoll = istRente ? 0 : Math.min(monate, Math.max(0, 12-jahre) * 12) \/ monate;   \/\/ Anteil der Auszahlzeit vor Fristablauf\r\n    var stpfl      = istRente ? ertragsanteil(alterBeginn) * ungEndk : 0.5 * ungErtrag;\r\n    var sUng       = nachgelagertSatz((stpfl \/ monate) * 12, andereJahr + gefRenteJ);\r\n    var steuerUng  = (1-anteilVoll) * stpfl * sUng;                                                   \/\/ Jahre nach Fristablauf\r\n    if (anteilVoll > 0) steuerUng += anteilVoll * ungErtrag * nachgelagertSatz((ungErtrag \/ monate) * 12, andereJahr + gefRenteJ);   \/\/ Jahre davor, voller Ertrag\r\n    return nettoGef + ungEndk - steuerUng;\r\n  }\r\n\r\n  \/\/ \u2500\u2500 Diagramm-Ansicht: Netto\/Brutto-Umschalter (nur im Netto-Modus relevant) \u2500\u2500\r\n  var chartAnsicht = 'netto';   \/\/ Default: Diagramme zeigen Netto, sobald der Netto-Modus aktiv ist\r\n  function chartNettoAktiv(){ return nettoAktiv && chartAnsicht === 'netto'; }\r\n  function setChartAnsicht(a){\r\n    chartAnsicht = a;\r\n    document.querySelectorAll('.chart-bn-netto').forEach(function(b){ b.classList.toggle('sel', a === 'netto'); });\r\n    document.querySelectorAll('.chart-bn-brutto').forEach(function(b){ b.classList.toggle('sel', a === 'brutto'); });\r\n    refreshCharts();\r\n  }\r\n  \/\/ Steuerpflichtige weitere Alterseinkuenfte (Jahreswert), gemeinsame Basis fuer Karten & Diagramme\r\n  function nettoAndereJahr(){\r\n    var alterNow = parseInt(document.getElementById('alter').value) || 0;\r\n    var rentenjahr = AKTUELLES_JAHR + Math.max(0, rentenalter-alterNow);\r\n    var ba = besteuerungsanteilGesRente(rentenjahr);\r\n    var aj = gesetzlRenteMo * 12 * ba + betriebsRenteMo * 12;\r\n    if (splittingAktiv) aj += (partnerTyp === 'rente' ? partnerWert * 12 * ba : partnerWert);\r\n    return aj;\r\n  }\r\n  \/\/ Netto-Kapital: nachgelagerte Besteuerung (Riester\/AVD, Differenzmethode auf die Jahresrente)\r\n  function nettoKapitalNachgelagert(kapital, monate, andereJahr){\r\n    if (kapital <= 0 || monate <= 0) return kapital;\r\n    var s = nachgelagertSatz((kapital \/ monate) * 12, andereJahr);\r\n    return kapital * (1-s);\r\n  }\r\n  \/\/ Netto-Kapital: ETF, Abgeltungsteuer (26,375 %) auf den Gewinn nach 30 % Teilfreistellung,\r\n  \/\/ abz\u00fcglich Sparer-Pauschbetrag (1.000 \u20ac\/Jahr, 2.000 \u20ac bei Zusammenveranlagung) je Ansparjahr.\r\n  \/\/ Annahme: Der j\u00e4hrliche Freibetrag wird genutzt (z. B. Vorabpauschale \/ rollierende Gewinnrealisierung).\r\n  function nettoKapitalETF(kapital, eingezahlt, jahre){\r\n    var gewinn = Math.max(0, kapital-eingezahlt);\r\n    var freibetrag = STEUER.sparerpauschbetrag * (splittingAktiv ? 2 : 1) * Math.max(0, jahre || 0);\r\n    var steuerpflichtig = Math.max(0, gewinn * (1 - STEUER.teilfreistellung) - freibetrag);\r\n    return kapital - steuerpflichtig * STEUER.abgeltungsteuer;\r\n  }\r\n  \/\/ Beide Diagramme aus den gecachten Brutto-Daten neu zeichnen (aktuelle Ansicht)\r\n  function refreshCharts(){\r\n    if (lastBarRenten) updateRentenBarChart(lastBarRenten.r, lastBarRenten.d, lastBarRenten.e, lastBarRenten.i);\r\n    drawVerlaufChart();\r\n  }\r\n\r\n  function toggleNetto(cb){\r\n    nettoAktiv = cb.checked;\r\n    var opt = document.getElementById('netto-optionen');\r\n    if (opt) opt.style.display = cb.checked ? 'block' : 'none';\r\n    var stand = document.getElementById('steuer-stand'); if (stand) stand.textContent = '\u00b7 Stand: Steuertarif ' + STEUER.jahr;\r\n    var w = document.querySelector('.tool-wrapper'); if (w) w.classList.toggle('netto-an', cb.checked);\r\n    updateNettoAnzeige();\r\n    refreshCharts();   \/\/ Diagramme der neuen Ansicht anpassen (auch beim Ausschalten zurueck auf Brutto)\r\n      if (typeof berechnenLive === 'function') berechnenLive(); \/\/ nach Umschalten Karten nach angezeigtem Wert neu sortieren\r\n  }\r\n  \/\/ Grobe Sch\u00e4tzung der gesetzlichen Brutto-Monatsrente aus Bruttojahreseinkommen + Beitragsjahren\r\n  \/\/ Entgeltpunkte\/Jahr = Einkommen (gedeckelt auf BBG) \/ Durchschnittsentgelt \u2192 \u00d7 Beitragsjahre \u00d7 Rentenwert\r\n  function schaetzeGesetzlicheRente(bruttoJahr, jahre){\r\n    if (bruttoJahr <= 0 || jahre <= 0) return 0;\r\n    var epJahr = Math.min(bruttoJahr, STEUER.bbg_jahr) \/ STEUER.durchschnittsentgelt;\r\n    return epJahr * jahre * STEUER.rentenwert;   \/\/ \u20ac\/Monat brutto\r\n  }\r\n\r\n  \/\/ Karten-Auswahl: 'kenne' (Renten direkt eingeben) | 'schaetzen' (aus Einkommen sch\u00e4tzen)\r\n  function setNettoPfad(p){\r\n    nettoPfad = p;\r\n    var ck = document.getElementById('netto-card-kenne'), cs = document.getElementById('netto-card-schaetz');\r\n    if (ck) ck.classList.toggle('sel', p === 'kenne');\r\n    if (cs) cs.classList.toggle('sel', p === 'schaetzen');\r\n    var felder = document.getElementById('netto-felder'); if (felder) felder.style.display = 'block';\r\n    var sb = document.getElementById('netto-schaetz-block'); if (sb) sb.style.display = p === 'schaetzen' ? 'block' : 'none';\r\n    var badge = document.getElementById('ges-rente-badge'); if (badge) badge.style.display = p === 'schaetzen' ? 'inline' : 'none';\r\n    var ann = document.getElementById('schaetz-ann'); if (ann) ann.style.display = p === 'schaetzen' ? 'block' : 'none';\r\n    if (p === 'schaetzen') {\r\n      if (!beitragsjahreTouched) {\r\n        var bj = document.getElementById('beitragsjahre');\r\n        if (bj) bj.value = Math.max(0, rentenalter - STEUER.annahme_berufsstart);\r\n      }\r\n      schaetzAusEinkommen();\r\n    } else {\r\n      if (gesRenteGeschaetzt) { var ges = document.getElementById('ges-rente'); if (ges) ges.value = ''; gesRenteGeschaetzt = false; }\r\n      leseRenten();\r\n    }\r\n  }\r\n\r\n  function onBeitragsjahre(){ beitragsjahreTouched = true; schaetzAusEinkommen(); }\r\n\r\n  \/\/ Einkommens-Pfad: sch\u00e4tzt die gesetzliche Rente und f\u00fcllt das (\u00fcberschreibbare) Feld vor\r\n  function schaetzAusEinkommen(){\r\n    var b = parseFloat((document.getElementById('brutto-jahr').value || '').replace(\/[^0-9]\/g, '')) || 0;\r\n    var j = parseInt(document.getElementById('beitragsjahre').value) || 0;\r\n    var r = schaetzeGesetzlicheRente(b, j);\r\n    var ges = document.getElementById('ges-rente'); if (ges) ges.value = Math.round(r).toLocaleString('de-DE'); gesRenteGeschaetzt = true;\r\n    var ann = document.getElementById('schaetz-ann');\r\n    if (ann) {\r\n      var epJ = b > 0 ? Math.min(b, STEUER.bbg_jahr) \/ STEUER.durchschnittsentgelt : 0;\r\n      ann.textContent = 'Gesch\u00e4tzt: ' + epJ.toFixed(2).replace('.', ',') + ' Entgeltpunkte\/Jahr \u00d7 ' + j +\r\n        ' Beitragsjahre \u00d7 Rentenwert ' + STEUER.rentenwert.toFixed(2).replace('.', ',') + ' \u20ac \u2248 ' +\r\n        Math.round(r).toLocaleString('de-DE') + ' \u20ac\/Mo. (brutto). Grobe N\u00e4herung \u2013 ersetzt keine Renteninformation der DRV.';\r\n    }\r\n    leseRenten();\r\n  }\r\n\r\n  \/\/ Liest die (ggf. \u00fcberschriebenen) Renten-Felder + Partner und st\u00f6\u00dft die Netto-Berechnung an\r\n  \/\/ \u2500\u2500 Zahleneingaben: Buchstaben blocken + Live-Tausenderpunkte (de-DE) \u2500\u2500\r\n(function () {\r\n  var NUM_FELDER = ['guthaben', 'brutto-jahr', 'ges-rente', 'betriebs-rente', 'partner-rente'];\r\n  function fmtFeld(el) {\r\n    var raw = (el.value || '').replace(\/[^0-9]\/g, '');\r\n    var txt = raw ? parseInt(raw, 10).toLocaleString('de-DE') : '';\r\n    if (el.value !== txt) el.value = txt;\r\n  }\r\n  function initFmt() {\r\n    NUM_FELDER.forEach(function (id) {\r\n      var el = document.getElementById(id);\r\n      if (!el) return;\r\n      el.addEventListener('input', function () { fmtFeld(this); });\r\n      fmtFeld(el);\r\n    });\r\n  }\r\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initFmt); } else { initFmt(); }\r\n  \/\/ Buchstaben in allen Zahlenfeldern verhindern (auch dynamisch erzeugte Felder)\r\n  document.addEventListener('keydown', function (e) {\r\n    var t = e.target;\r\n    if (!t || t.tagName !== 'INPUT') return;\r\n    var im = t.getAttribute('inputmode');\r\n    if (t.type !== 'number' && im !== 'numeric' && im !== 'decimal') return;\r\n    if (e.ctrlKey || e.metaKey || e.altKey) return;\r\n    if (e.key && e.key.length === 1 && !\/[0-9.,]\/.test(e.key)) e.preventDefault();\r\n  });\r\n})();\r\nfunction leseRenten(){\r\n    var g = parseFloat((document.getElementById('ges-rente').value || '').replace(\/[^0-9]\/g, ''));     gesetzlRenteMo  = isNaN(g) || g < 0 ? 0 : g;\r\n    var b = parseFloat((document.getElementById('betriebs-rente').value || '').replace(\/[^0-9]\/g, '')); betriebsRenteMo = isNaN(b) || b < 0 ? 0 : b;\r\n    var pEl = document.getElementById('partner-rente'); var p = pEl ? parseFloat((pEl.value || '').replace(\/[^0-9]\/g, '')) : 0; partnerWert = isNaN(p) || p < 0 ? 0 : p;\r\n    updateNettoAnzeige();\r\n    if (typeof berechnenLive === `function`) berechnenLive();   \/\/ E-059: Stern, Reihenfolge, Banner und Werbe-Box auch nach Netto-Eingaben (wie toggleNetto)\r\n  }\r\n  \/\/ Ehegattensplitting an\/aus\r\n  function toggleSplitting(cb){\r\n    splittingAktiv = cb.checked;\r\n    var pw = document.getElementById('partner-wrap'); if (pw) pw.style.display = cb.checked ? 'block' : 'none';\r\n    leseRenten();\r\n  }\r\n  \/\/ Partner-Typ: 'rente' (\u20ac\/Mo, anteilig steuerpflichtig) | 'job' (\u20ac\/Jahr, voll)\r\n  function setPartnerTyp(t){\r\n    partnerTyp = t;\r\n    var pr = document.getElementById('pt-rente'), pj = document.getElementById('pt-job');\r\n    if (pr) pr.classList.toggle('sel', t === 'rente');\r\n    if (pj) pj.classList.toggle('sel', t === 'job');\r\n    var lab = document.getElementById('partner-label'); if (lab) lab.textContent = t === 'rente' ? 'Rente des Partners' : 'Brutto-Jahreseinkommen des Partners';\r\n    var suf = document.getElementById('partner-suffix'); if (suf) suf.textContent = t === 'rente' ? '\u20ac\/Mo.' : '\u20ac\/Jahr';\r\n    leseRenten();\r\n  }\r\n\r\n  \/\/ Netto-Kopf (prominent) + Kaufkraft + zweitrangige Brutto-Zeile + Netto-Monatsrenten je Karte\r\n  function setNetto(prefix, nettoEnd, nettoRente, bruttoEnd){\r\n    function s(id, txt){ var el = document.getElementById(prefix + id); if (el) el.textContent = txt; }\r\n    s('-endkapital-netto', fmt(nettoEnd));\r\n      var eknRawEl = document.getElementById(prefix + '-endkapital-netto'); if (eknRawEl) eknRawEl.dataset.raw = nettoEnd;\r\n    s('-endkapital-netto-real', '= heute ' + fmt(realwert(nettoEnd, aktuelleLaufzeit)));\r\n    s('-brutto-compact', 'Brutto: ' + fmt(bruttoEnd));\r\n    s('-brutto-compact-real', '(heute ' + fmt(realwert(bruttoEnd, aktuelleLaufzeit)) + ')');\r\n    s('-rente-netto', fmt(nettoRente));\r\n    s('-rente-netto-real', fmt(realwert(nettoRente, aktuelleLaufzeit)));\r\n  }\r\n  function updateNettoAnzeige(){\r\n    if (!nettoAktiv) return;\r\n    var monate = leJahre * 12; if (monate <= 0) return;\r\n    var rEnd = parseFloat(document.getElementById('r-endkapital').dataset.raw || 0);\r\n    var dEnd = parseFloat(document.getElementById('d-endkapital').dataset.raw || 0);\r\n    var eEnd = parseFloat(document.getElementById('e-endkapital').dataset.raw || 0);\r\n    var iEnd = parseFloat(document.getElementById('i-endkapital').dataset.raw || 0);\r\n    if (isNaN(rEnd) || isNaN(dEnd) || isNaN(eEnd) || isNaN(iEnd)) return;   \/\/ E-056b: data-raw NaN ist kein Ergebnis, dann wie vor E-056 abbrechen (keine NaN in den Netto-Feldern); echte Nullen rechnen weiter\r\n    if (!rEnd &#038;&#038; !dEnd &#038;&#038; !eEnd &#038;&#038; !iEnd) { if (!aktuelleLaufzeit) return; }   \/\/ E-056: alle Endkapitale 0 ist ein g\u00fcltiges Ergebnis (z. B. 0 \u20ac\/Monat); abbrechen nur, solange noch nicht gerechnet wurde (aktuelleLaufzeit setzt erst berechnen)\r\n\r\n    \/\/ Weitere Alterseink\u00fcnfte: gesetzliche Rente nur mit steuerpflichtigem Anteil, Betriebsrente voll.\r\n    \/\/ Liegen (noch) keine vor, ist andereJahr = 0 \u2192 die AVD\/Riester-Rente wird allein besteuert.\r\n    var andereJahr = nettoAndereJahr();\r\n\r\n    \/\/ Riester \/ AVD Standard \/ AVD Flex \u2192 nachgelagerte Besteuerung in zwei T\u00f6pfen (gef\u00f6rdert voll, ungef\u00f6rdert nur Ertrag)\r\n    var monatlichNetto = parseFloat(document.getElementById('einzahlung').value) || 0;\r\n    var jahresbeitragN = monatlichNetto * 12;\r\n    var guthabenNetto  = parseFloat((document.getElementById('guthaben').value || '').replace(\/[^0-9]\/g, '')) || 0;\r\n    var nettoEndk = {};\r\n    var nachgelagert = [['r', rEnd], ['d', dEnd], ['i', iEnd]];\r\n    for (var n = 0; n < nachgelagert.length; n++) {\r\n      var prefix = nachgelagert[n][0], endk = nachgelagert[n][1];\r\n      var zulageGes = parseFloat(document.getElementById(prefix + '-endkapital').dataset.zulage || 0);\r\n      var erstDs = document.getElementById(prefix + '-endkapital').dataset;   \/\/ E-059: Vertragsanteil der Erstattung, gef\u00f6rdert \/ ungef\u00f6rdert\r\n      var steuerErsp = parseFloat(erstDs.steuererstattung || 0), steuerErspUng = parseFloat(erstDs.steuererstattungUng || 0);\r\n      \/\/ Riester: gef\u00f6rderter H\u00f6chstbetrag 2.100 \u20ac\/Jahr inkl. Zulagen \u2192 Eigenbeitrag-Grenze 2.100 \u2212 Zulage\/Jahr (nur Zulagen, NICHT die Steuerersparnis)\r\n      \/\/ AVD: gef\u00f6rderter Eigenbeitrag bis 1.800 \u20ac\/Jahr (Zulagen zus\u00e4tzlich)\r\n      var foerderGrenze = (prefix === 'r')\r\n        ? Math.max(0, 2100 - (aktuelleLaufzeit > 0 ? zulageGes \/ aktuelleLaufzeit : 0))\r\n        : 1800;\r\n      \/\/ Auszahlplan (lineare Entnahme \u00fcber die Auszahlungsdauer): ungef\u00f6rderter Teil nur mit dem Ertrag, h\u00e4lftig nach Ablauf der\r\n      \/\/ 12-Jahres-Frist; gef\u00f6rderter Teil der Erstattung im gef\u00f6rderten, \u00dcberzahlung im ungef\u00f6rderten Topf (E-059)\r\n      var ne = nettoZweiToepfe(endk, jahresbeitragN, zulageGes, guthabenNetto, aktuelleLaufzeit, andereJahr, monate, foerderGrenze, 'plan', rentenalter, steuerErsp, steuerErspUng);\r\n      \/\/ B1: Nebendepot aus dem Erstattungs-\u00dcberhang \u2013 Abgeltungsteuer nur auf den Gewinn\r\n      var nbEl        = document.getElementById(prefix + '-endkapital');\r\n      var nbKapital   = parseFloat(nbEl.dataset.neben || 0);\r\n      var nbEingez    = parseFloat(nbEl.dataset.nebenEingezahlt || 0);\r\n      \/\/ Angelegt: Abgeltungsteuer nur auf den Gewinn. Nicht angelegt: bereits versteuertes\r\n      \/\/ Geld, das unverzinst liegt - es faellt keine weitere Steuer an.\r\n      if (nbKapital > 0) ne += erstattungAnlegen ? nettoKapitalETF(nbKapital, nbEingez, aktuelleLaufzeit) : nbKapital;\r\n      var bruttoGesamt = endk + nbKapital;\r\n      nettoEndk[prefix] = ne; nettoEndk[prefix + `Brutto`] = bruttoGesamt;   \/\/ E-059: Brutto inkl. Nebendepot fuer den Banner\r\n      setNetto(prefix, ne, ne \/ monate, bruttoGesamt);\r\n    }\r\n\r\n    \/\/ ETF \u2192 Abgeltungsteuer nur auf den Gewinn (30 % Teilfreistellung + j\u00e4hrlicher Sparer-Pauschbetrag)\r\n    var eEingezahlt = parseFloat(document.getElementById('e-endkapital').dataset.eingezahlt || 0);\r\n    var etfNettoEnd = nettoKapitalETF(eEnd, eEingezahlt, aktuelleLaufzeit);\r\n    setNetto('e', etfNettoEnd, etfNettoEnd \/ monate, eEnd);\r\n\r\n    \/\/ Delta-Banner: Netto-Delta prim\u00e4r, Brutto-Vergleich zweitrangig (Grundsicherungs-Fall ausgenommen)\r\n    var rRenteMo = (nettoEndk.rBrutto || 0) \/ monate;   \/\/ E-059 (Nebenbefund): Grundsicherungsfall wie berechnen mit Vertrag + Nebendepot\r\n    var gsAktiv = rRenteMo > 0 && rRenteMo < 200;\r\n    var banner = document.getElementById('delta-banner');\r\n    if (banner) banner.classList.toggle('gs-mode', gsAktiv);\r\n    if (!gsAktiv) {\r\n      var nettoDiff = (nettoEndk['i'] || 0) - (nettoEndk['r'] || 0);\r\n      var bruttoDiff = (nettoEndk.iBrutto || 0) - (nettoEndk.rBrutto || 0);   \/\/ E-059 (Nebenbefund): wie Karten und Brutto-Banner inkl. Nebendepot\r\n      var setT = function(id, txt){ var el = document.getElementById(id); if (el) el.textContent = txt; };\r\n      setT('delta-label-netto', nettoDiff >= 0\r\n        ? 'In dieser Beispielrechnung liegt das AVD Flex-Depot vorn'\r\n        : 'In dieser Beispielrechnung liegt Riester vorn');\r\n      setT('delta-amount-netto', '+' + fmt(Math.abs(nettoDiff)));\r\n      setT('delta-real-netto', 'in heutiger Kaufkraft: +' + fmt(realwert(Math.abs(nettoDiff), aktuelleLaufzeit)));\r\n      setT('delta-brutto-compact', 'Brutto-Vergleich: +' + fmt(Math.abs(bruttoDiff)));\r\n      setT('delta-brutto-compact-real', ' \u00b7 in heutiger Kaufkraft +' + fmt(realwert(Math.abs(bruttoDiff), aktuelleLaufzeit)));\r\n    }\r\n\r\n    \/\/ Diagramme an geaenderte Netto-Eingaben anpassen (gesetzl. Rente, Splitting usw.)\r\n    refreshCharts();\r\n  }\r\n\r\n  \/\/ B5: Hinweis, wenn Renteneintritt + Auszahlungsdauer das 85. Lebensjahr nicht erreicht\r\n  \/\/ (Vertrag nach \u00a7 1 Abs. 1c AltZertG muss bis mind. 85 leisten). Nur Anzeige, blockiert nichts.\r\n  function updateLE85Warn() {\r\n    var warnEl = document.getElementById('le-85-warn');\r\n    if (!warnEl) return;\r\n    var reEl = document.getElementById('renteneintritt');\r\n    var re = reEl ? parseInt(reEl.value, 10) : NaN;\r\n    if (!isFinite(re)) re = (typeof rentenalter === 'number' && isFinite(rentenalter)) ? rentenalter : 67;\r\n    if (!isFinite(re)) re = 67;\r\n    var dauer = parseInt(leJahre, 10);\r\n    if (!isFinite(dauer)) return;\r\n    var endalter = re + dauer;\r\n    var alterEl = document.getElementById('le-85-alter');\r\n    if (alterEl) alterEl.textContent = String(endalter);\r\n    warnEl.classList.toggle('show', endalter < 85);\r\n  }\r\n\r\n  function updateLE(val) {\r\n    leJahre = parseInt(val);\r\n    updateLE85Warn();\r\n    document.getElementById('leDisplay').textContent = val + (val == 1 ? ' Jahr' : ' Jahre');\r\n    var leEl = document.getElementById('lebenserwartung'); if (leEl) leEl.setAttribute('aria-valuetext', val + (val == 1 ? ' Jahr' : ' Jahre'));\r\n    aktualisiereRenten();\r\n  }\r\n\r\n  function aktualisiereRenten() {\r\n    \/\/ E-059b (D3): Brutto-Renten, Balken und Grundsicherungs-Zeilen wie berechnen aus Vertrag plus Fonds-Nebendepot (data-gesamt;\r\n    \/\/ ETF ohne Nebendepot: data-raw). Bisher nur der Vertrag (data-raw); in PreLaunch blieb das nach dem Regler Auszahlungsdauer\r\n    \/\/ stehen, weil die Steuerelemente-Delegation updateLE nach berechnenLive aufruft.\r\n    const riesterEndkapital = parseFloat(document.getElementById('r-endkapital').dataset.gesamt || 0);\r\n    const depotEndkapital   = parseFloat(document.getElementById('d-endkapital').dataset.gesamt || 0);\r\n    const etfEndkapital     = parseFloat(document.getElementById('e-endkapital').dataset.raw || 0);\r\n    if (!riesterEndkapital) return;\r\n    const monate = leJahre * 12;\r\n    if (monate <= 0) return;\r\n    document.getElementById('r-rente').textContent = fmt(riesterEndkapital \/ monate);\r\n    document.getElementById('d-rente').textContent = fmt(depotEndkapital   \/ monate);\r\n    document.getElementById('e-rente').textContent = fmt(etfEndkapital     \/ monate);   \/\/ E-059b (D3): ohne Zusatz, wie berechnen\r\n    const iRenteSlider = parseFloat(document.getElementById('i-endkapital').dataset.gesamt || 0) \/ monate;\r\n    document.getElementById(`i-rente`).textContent = fmt(iRenteSlider);   \/\/ E-059b (D3): wie berechnen\r\n    document.getElementById('r-rente-real').textContent = fmt(realwert(riesterEndkapital \/ monate, aktuelleLaufzeit));\r\n    document.getElementById('d-rente-real').textContent = fmt(realwert(depotEndkapital   \/ monate, aktuelleLaufzeit));\r\n    document.getElementById('e-rente-real').textContent = fmt(realwert(etfEndkapital     \/ monate, aktuelleLaufzeit));\r\n    document.getElementById('i-rente-real').textContent = fmt(realwert(iRenteSlider, aktuelleLaufzeit));\r\n    updateRentenBarChart(riesterEndkapital\/monate, depotEndkapital\/monate, etfEndkapital\/monate, iRenteSlider);\r\n    updateNettoAnzeige();\r\n    var rRenteMoSlider = riesterEndkapital \/ monate;\r\n    if (rRenteMoSlider > 0 && rRenteMoSlider < 200) {\r\n      const rGsFrei = gsFreibetrag(rRenteMoSlider);\r\n      const rGsGesamt = GS_BEDARF +Math.round(rGsFrei);\r\n      const showIds = ['r-gs-row','r-gs-anrech-row','r-gs-gesamt-row','d-gs-row','d-gs-anrech-row','d-gs-gesamt-row','i-gs-row','i-gs-anrech-row','i-gs-gesamt-row','e-gs-row','e-gs-anrech-row','e-gs-gesamt-row'];\r\n      showIds.forEach(id => { const el = document.getElementById(id); if (el) el.style.display = 'flex'; });\r\n      const rGsValEl = document.getElementById('r-gs-val'); if (rGsValEl) rGsValEl.textContent = Math.round(rGsFrei) + ' \u20ac\/Mo.';\r\n      const rGsGesamtValEl = document.getElementById('r-gs-gesamt-val'); if (rGsGesamtValEl) rGsGesamtValEl.textContent = rGsGesamt.toLocaleString('de-DE') + ' \u20ac\/Mo.';\r\n      const dGsGesamtValEl = document.getElementById('d-gs-gesamt-val'); if (dGsGesamtValEl) dGsGesamtValEl.textContent = GS_BEDARF.toLocaleString('de-DE') + ' \u20ac\/Mo.';\r\n      const iGsGesamtValEl = document.getElementById('i-gs-gesamt-val'); if (iGsGesamtValEl) iGsGesamtValEl.textContent = GS_BEDARF.toLocaleString('de-DE') + ' \u20ac\/Mo.';\r\n    } else {\r\n      ['r-gs-row','r-gs-anrech-row','r-gs-gesamt-row','d-gs-row','d-gs-anrech-row','d-gs-gesamt-row','i-gs-row','i-gs-anrech-row','i-gs-gesamt-row','e-gs-row','e-gs-anrech-row','e-gs-gesamt-row'].forEach(id => {\r\n        const el = document.getElementById(id); if (el) el.style.display = 'none';\r\n      });\r\n    }\r\n  }\r\n\r\n  var AKTUELLES_JAHR = new Date().getFullYear();\r\n  var MIN_GEBURTSJAHR = AKTUELLES_JAHR - 24;\r\n  var MAX_GEBURTSJAHR = AKTUELLES_JAHR + 30;\r\n\r\n  function syncEinzahlung(source, val) {\r\n    let v = parseFloat(val) || 0;\r\n    if (v > 570) v = 570;\r\n    if (v < 0) v = 0;\r\n    document.getElementById('einzahlung').value = v;\r\n    document.getElementById('einzahlung-slider').value = v;\r\n    document.getElementById('einzahlung-warning').classList.toggle('show', v > 0 && v < 10);\r\n    document.getElementById('einzahlung-info').classList.toggle('show', v >= 150 && v <= 570);\r\n    document.getElementById('einzahlung-max').classList.toggle('show', parseFloat(val) > 570);\r\n    berechnenLive();\r\n  }\r\n\r\n  function setChildren(n) {\r\n    numChildren = n;\r\n    \/\/ Vorbelegung wie in Tool 7.7: ein 5-jaehriges Kind. Der frueher genutzte Wert 24\r\n    \/\/ war zugleich das Feldminimum - das Kind fiel im Folgejahr aus der Zulage und die\r\n    \/\/ Foerderung wurde ohne Zutun des Nutzers deutlich zu niedrig ausgewiesen.\r\n    childAges = new Array(n).fill(5);\r\n    for (let i = 0; i <= 5; i++) {\r\n      const btn = document.getElementById('kBtn' + i);\r\n      \/\/ Optik aus Tool 7.7: .button \/ .kinder-active \u2192 .kinder-btn \/ .active\r\n      if (btn) btn.className = 'kinder-btn' + (i === n ? ' active' : '');\r\n    }\r\n    renderChildFields();\r\n    berechnenLive();\r\n  }\r\n\r\n  function renderChildFields() {\r\n    const cf = document.getElementById('children-fields');\r\n    cf.innerHTML = '';\r\n    for (let i = 0; i < numChildren; i++) {\r\n      const geburtsjahr = AKTUELLES_JAHR - childAges[i];\r\n      const div = document.createElement('div');\r\n      div.style.cssText = 'display:flex;flex-direction:column;gap:6px;min-width:160px;';\r\n      div.innerHTML = `\r\n        \\u003Clabel style=\"font-size:12px;color:var(--muted);\">Kind ${i+1} \u2013 Geburtsjahr\\u003C\/label>\r\n        \\u003Cdiv style=\"position:relative;\">\r\n          \\u003Cinput type=\"number\" min=\"${MIN_GEBURTSJAHR}\" max=\"${MAX_GEBURTSJAHR}\"\r\n            value=\"${geburtsjahr}\"\r\n            placeholder=\"${MIN_GEBURTSJAHR}\"\r\n            class=\"input input--stretch input--childbirth\"\r\n            data-ci=\"${i}\"\r\n            oninput=\"updateChildBirthYear(${i}, this)\"\r\n            style=\"font-size:14px;font-weight:500;padding:10px 14px;\">\r\n          \\u003Cspan id=\"childErr${i}\" style=\"font-size:11px;color:var(--error);display:none;margin-top:3px;\">\\u003C\/span>\r\n        \\u003C\/div>`;\r\n      cf.appendChild(div);\r\n    }\r\n  }\r\n\r\n  function updateChildBirthYear(i, input) {\r\n    const val = parseInt(input.value);\r\n    const errEl = document.getElementById('childErr' + i);\r\n    input.classList.remove('input--invalid');\r\n    if (errEl) errEl.style.display = 'none';\r\n    \/\/ Ung\u00fcltiges\/leeres Geburtsjahr: Kind z\u00e4hlt nicht (Sentinel 999 \u2192 keine Zulage), statt einen stale Wert weiterzurechnen\r\n    if (isNaN(val)) { input.classList.add('input--invalid'); if (errEl) { errEl.textContent = 'Bitte Geburtsjahr eingeben'; errEl.style.display = 'block'; } childAges[i] = 999; berechnenLive(); return; }\r\n    if (val < MIN_GEBURTSJAHR) {\r\n      input.classList.add('input--invalid');\r\n      if (errEl) { errEl.textContent = `Fr\u00fchestes Geburtsjahr: ${MIN_GEBURTSJAHR}`; errEl.style.display = 'block'; }\r\n      childAges[i] = 999; berechnenLive(); return;\r\n    }\r\n    if (val > MAX_GEBURTSJAHR) {\r\n      input.classList.add('input--invalid');\r\n      if (errEl) { errEl.textContent = `Bitte realistisches Geburtsjahr eingeben`; errEl.style.display = 'block'; }\r\n      childAges[i] = 999; berechnenLive(); return;\r\n    }\r\n    childAges[i] = AKTUELLES_JAHR - val;\r\n    berechnenLive();\r\n  }\r\n\r\n  function fmt(n) {\r\n    return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR', maximumFractionDigits: 0 }).format(n);\r\n  }\r\n\r\n  function validate() {\r\n    let valid = true;\r\n    const alter = parseInt(document.getElementById('alter').value);\r\n    const alterInput = document.getElementById('alter');\r\n    const alterError = document.getElementById('alter-error');\r\n    if ((alterInput.value||'').trim()==='') {\r\n      alterInput.classList.remove('input--invalid');\r\n      alterError.classList.remove('show');\r\n      valid = false;\r\n    } else if (isNaN(alter) || alter < 16 || alter >= rentenalter) {\r\n      alterInput.classList.add('input--invalid');\r\n      alterError.classList.add('show');\r\n      valid = false;\r\n    } else {\r\n      alterInput.classList.remove('input--invalid');\r\n      alterError.classList.remove('show');\r\n    }\r\n    return valid;\r\n  }\r\n\r\n  \/\/ \u2500\u2500 Berechnungsfunktionen (unver\u00e4ndert) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  function berechneRiester(guthaben, monatlicheEinzahlung, r, alter, ra, startChildAges, rNeben) {\r\n    const monatsrendite = Math.pow(1 + r, 1\/12) - 1;\r\n    let kapital = guthaben;\r\n    let foerderungGesamt = 0;\r\n    let steuererstattungGesamt = 0;\r\n    let steuererstattungAVD = 0;\r\n    let nebenKapital = 0, nebenEingezahlt = 0, erstGef = 0, erstUng = 0, erstGefVorjahr = 0;   \/\/ E-059: Vertragsanteil der Erstattung, gef\u00f6rdert \/ ungef\u00f6rdert\r\n    const laufzeit = ra - alter;\r\n    const kinder = [...startChildAges];\r\n    for (let jahr = 1; jahr <= laufzeit; jahr++) {\r\n      if (erstattungAnlegen) nebenKapital = nebenKapital * (1 + (rNeben == null ? r : rNeben));\r\n      for (let monat = 0; monat < 12; monat++) kapital = kapital * (1 + monatsrendite) + monatlicheEinzahlung;\r\n      const jahresbeitrag = monatlicheEinzahlung * 12;\r\n      \/\/ E-059b (Stufe 2): Beitrag des Jahres f\u00fcr Zulagen, Mindesteigenbeitrag und Sonderausgabenabzug ist der regul\u00e4re\r\n      \/\/ Jahresbeitrag plus der gef\u00f6rderte Teil der Vorjahreserstattung, die in diesem Jahr eingezahlt wird (\u00a7 82 Abs. 1, \u00a7 88 EStG;\r\n      \/\/ AVD \u00a7\u00a7 84 bis 86 und \u00a7 10a n. F., Riester in der bis 2026 geltenden Fassung). Einzahlungsgrenze (6.840 \u20ac), Restluft und\r\n      \/\/ Berufseinsteigerbonus rechnen weiter mit dem regul\u00e4ren Jahresbeitrag.\r\n      const beitragJahr = jahresbeitrag + erstGefVorjahr;\r\n      erstGefVorjahr = 0;   \/\/ unten neu gesetzt, wenn in diesem Jahr ein gef\u00f6rderter Erstattungsteil in den Vertrag flie\u00dft\r\n      if (beitragJahr > 0) {   \/\/ E-059: statt fester 60-\u20ac-Schwelle K\u00fcrzung nach \u00a7 86 Abs. 1 EStG a. F. (unten)\r\n        let zulageJahr = 175;\r\n        for (let k = 0; k < kinder.length; k++) {\r\n          const ka = kinder[k];\r\n          if (ka >= 0 && ka < 25) {\r\n            zulageJahr += (AKTUELLES_JAHR - startChildAges[k] >= 2008 ? 300 : 185);\r\n          }\r\n        }\r\n        \/\/ E-059 \u00b7 Mindesteigenbeitrag nach \u00a7 86 Abs. 1 EStG in der bis 31.12.2026 geltenden Fassung (f\u00fcr Riester-Bestandsvertr\u00e4ge\r\n        \/\/ weiter anzuwenden, \u00a7 52 Abs. 50a EStG): 4 % der beitragspflichtigen Einnahmen des Vorjahres, h\u00f6chstens 2.100 \u20ac (\u00a7 10a\r\n        \/\/ Abs. 1 Satz 1 a. F.), vermindert um die Zulagen (Satz 2), mindestens der Sockelbetrag von 60 \u20ac (Satz 4 und 5). Wird er\r\n        \/\/ nicht erreicht, wird die Zulage im Verh\u00e4ltnis Eigenbeitrag zu Mindesteigenbeitrag gek\u00fcrzt (Satz 6; BMF 05.10.2023\r\n        \/\/ Rn. 63 bis 68). Modell: Vorjahreseinnahmen = heutiges Bruttojahreseinkommen (konstant, nicht auf volle Euro abgerundet;\r\n        \/\/ die BBG-Kappung wirkt wegen der 2.100-\u20ac-Grenze nicht). E-059b (D1): das Einkommen z\u00e4hlt nur, wenn es sichtbar ist oder\r\n        \/\/ selbst eingegeben wurde (einkommenFuerRiesterKuerzung); sonst gilt nur der Sockelbetrag (Rn. 65). E-059b (Stufe 2):\r\n        \/\/ Eigenbeitrag ist beitragJahr, also inklusive der eingezahlten gef\u00f6rderten Vorjahreserstattung (\u00a7 82 Abs. 1, \u00a7 88 EStG).\r\n        \/\/ Die gek\u00fcrzte Zulage gilt auch f\u00fcr Sonderausgabenabzug und F\u00f6rderh\u00f6chstgrenze.\r\n        var _mindestEigen = Math.max(60, Math.min(0.04 * einkommenFuerRiesterKuerzung(), 2100)-zulageJahr);\r\n        if (_mindestEigen > beitragJahr) zulageJahr = zulageJahr * beitragJahr \/ _mindestEigen;\r\n        kapital += zulageJahr;\r\n        foerderungGesamt += zulageJahr;\r\n        var _rf = sonderausgabenErstattung(beitragJahr, zulageJahr, getErwerbsBrutto(), 'riester');   \/\/ E-059b: Abzug min(beitragJahr + Zulage, 2.100)\r\n        if (_rf > 0) {\r\n          var _sp = erstattungSplit(_rf, jahresbeitrag);\r\n          if (_sp.avd   > 0) { kapital      += _sp.avd;   steuererstattungAVD += _sp.avd; }   \/\/ bis zur Einzahlungsgrenze in den Vertrag\r\n          \/\/ E-059: Die eingezahlte Erstattung ist Beitrag des Folgejahres (\u00a7 88 EStG). Gef\u00f6rdert nur bis 2.100 \u20ac minus Zulage minus\r\n          \/\/ regul\u00e4rer Jahresbeitrag (\u00a7 10a Abs. 1 EStG a. F.), der Rest ist \u00dcberzahlung und ungef\u00f6rdert (BMF 05.10.2023 Rn. 136).\r\n          \/\/ Die Erstattung des letzten Ansparjahres flie\u00dft erst in der Auszahlphase zu und z\u00e4hlt ungef\u00f6rdert (Vereinfachung:\r\n          \/\/ sie bleibt im Vertragskapital gebucht).\r\n          var _erstGef = (laufzeit > jahr) ? Math.min(_sp.avd, Math.max(0, 2100-zulageJahr-jahresbeitrag)) : 0;\r\n          erstGef += _erstGef; erstUng += _sp.avd-_erstGef; erstGefVorjahr = _erstGef;   \/\/ E-059b: im Folgejahr Teil von beitragJahr\r\n          if (_sp.neben > 0) { nebenKapital += _sp.neben; nebenEingezahlt     += _sp.neben; } \/\/ \u00dcberhang: ungef\u00f6rdertes ETF-Nebendepot\r\n          steuererstattungGesamt += _rf;   \/\/ Gesamtbetrag bleibt f\u00fcr die F\u00f6rder-Anzeige erhalten\r\n        }\r\n      }\r\n      for (let k = 0; k < kinder.length; k++) kinder[k]++;\r\n    }\r\n    return { kapital, foerderungGesamt, steuererstattungGesamt, steuererstattungAVD, nebenKapital, nebenEingezahlt, steuererstattungGef: erstGef, steuererstattungUng: erstUng };\r\n  }\r\n\r\n  function berechneDepot(guthaben, monatlicheEinzahlung, r, alter, ra, startChildAges, glideRa, rNeben) {\r\n    const laufzeit = ra - alter;\r\n    const glideLaufzeit = (glideRa != null ? glideRa : ra) - alter;   \/\/ Lifecycle-Reduktion am echten Renteneintritt, nicht am Chart-Zwischenpunkt\r\n    const kinder = [...startChildAges];\r\n    \/\/ \u00a7 86 EStG: Starterbonus (\u00a7 84 Satz 2) wie Grund- und Kinderzulage nur ab 120 \u20ac\/Jahr Eigenbeitrag\r\n    const starterbonus = alter < 25 ? (monatlicheEinzahlung * 12 >= 120 ? 200 : 0) : 0;   \/\/ Starterbonus zaehlt zur Foerderung (sonst stimmt die Aufschluesselung Eigenbeitrag\/Foerderung\/Wertzuwachs nicht)\r\n    let kapital = guthaben + starterbonus;\r\n    let foerderungGesamt = starterbonus;\r\n    let steuererstattungGesamt = 0;\r\n    let steuererstattungAVD = 0;\r\n    let nebenKapital = 0, nebenEingezahlt = 0, erstGef = 0, erstUng = 0, erstGefVorjahr = 0;   \/\/ E-059: Vertragsanteil der Erstattung, gef\u00f6rdert \/ ungef\u00f6rdert\r\n    for (let jahr = 1; jahr <= laufzeit; jahr++) {\r\n      const jahreVorRente = glideLaufzeit - jahr;\r\n      let rendite = jahreVorRente > 5 ? r : jahreVorRente > 2 ? r * 0.5 : r * 0.3;\r\n      const monatsrendite = Math.pow(1 + rendite, 1\/12) - 1;\r\n      \/\/ Nebendepot: eigenes, ungefoerdertes Depot ohne Lifecycle-Umschichtung\r\n      if (erstattungAnlegen) nebenKapital = nebenKapital * (1 + (rNeben == null ? rendite : rNeben));\r\n      for (let monat = 0; monat < 12; monat++) kapital = kapital * (1 + monatsrendite) + monatlicheEinzahlung;\r\n      const jahresbeitrag = monatlicheEinzahlung * 12;\r\n      \/\/ E-059b (Stufe 2): Beitrag des Jahres f\u00fcr Zulagen, Mindesteigenbeitrag und Sonderausgabenabzug ist der regul\u00e4re\r\n      \/\/ Jahresbeitrag plus der gef\u00f6rderte Teil der Vorjahreserstattung, die in diesem Jahr eingezahlt wird (\u00a7 82 Abs. 1, \u00a7 88 EStG;\r\n      \/\/ AVD \u00a7\u00a7 84 bis 86 und \u00a7 10a n. F., Riester in der bis 2026 geltenden Fassung). Einzahlungsgrenze (6.840 \u20ac), Restluft und\r\n      \/\/ Berufseinsteigerbonus rechnen weiter mit dem regul\u00e4ren Jahresbeitrag.\r\n      const beitragJahr = jahresbeitrag + erstGefVorjahr;\r\n      erstGefVorjahr = 0;   \/\/ unten neu gesetzt, wenn in diesem Jahr ein gef\u00f6rderter Erstattungsteil in den Vertrag flie\u00dft\r\n      let foerderungJahr = 0;\r\n      if (beitragJahr >= 120) {\r\n        foerderungJahr = Math.min(beitragJahr, 360) * 0.50 + Math.max(0, Math.min(beitragJahr, 1800) - 360) * 0.25;\r\n      }\r\n      if (beitragJahr >= 120) {   \/\/ \u00a7 86 EStG: Kinderzulage wie Grundzulage nur ab 120 \u20ac\/Jahr Eigenbeitrag\r\n        for (let k = 0; k < kinder.length; k++) { if (kinder[k] >= 0 && kinder[k] < 25) foerderungJahr += Math.min(beitragJahr, 300); }\r\n      }\r\n      if (foerderungJahr > 0) { kapital += foerderungJahr; foerderungGesamt += foerderungJahr; }\r\n      var _refund = sonderausgabenErstattung(Math.min(beitragJahr, AVD_ABZUG_MAX), foerderungJahr, getErwerbsBrutto());\r\n      if (_refund > 0) {\r\n        var _sp = erstattungSplit(_refund, jahresbeitrag);\r\n        if (_sp.avd   > 0) { kapital      += _sp.avd;   steuererstattungAVD += _sp.avd; }   \/\/ bis zur Einzahlungsgrenze in den Vertrag\r\n        \/\/ E-059: Die eingezahlte Erstattung ist Beitrag des Folgejahres (\u00a7 88 EStG). Gef\u00f6rdert nur bis 1.800 \u20ac minus regul\u00e4rer\r\n        \/\/ Jahresbeitrag (\u00a7 10a Abs. 1, \u00a7 82 Abs. 1 EStG), der Rest ist \u00dcberzahlung und ungef\u00f6rdert (BMF 05.10.2023 Rn. 136).\r\n        \/\/ Die Erstattung des letzten Ansparjahres flie\u00dft erst in der Auszahlphase zu und z\u00e4hlt ungef\u00f6rdert (Vereinfachung:\r\n        \/\/ sie bleibt im Vertragskapital gebucht).\r\n        var _erstGef = (laufzeit > jahr) ? Math.min(_sp.avd, Math.max(0, AVD_ABZUG_MAX-jahresbeitrag)) : 0;\r\n        erstGef += _erstGef; erstUng += _sp.avd-_erstGef; erstGefVorjahr = _erstGef;   \/\/ E-059b: im Folgejahr Teil von beitragJahr\r\n        if (_sp.neben > 0) { nebenKapital += _sp.neben; nebenEingezahlt     += _sp.neben; }\r\n        steuererstattungGesamt += _refund;\r\n      }\r\n      for (let k = 0; k < kinder.length; k++) kinder[k]++;\r\n    }\r\n    return { kapital, foerderungGesamt, steuererstattungGesamt, steuererstattungAVD, nebenKapital, nebenEingezahlt, steuererstattungGef: erstGef, steuererstattungUng: erstUng };\r\n  }\r\n\r\n  function berechneETF(guthaben, monatlicheEinzahlung, r, alter, ra) {\r\n    const monatsrendite = Math.pow(1 + r, 1\/12) - 1;\r\n    let kapital = guthaben;\r\n    const laufzeit = ra - alter;\r\n    for (let jahr = 1; jahr <= laufzeit; jahr++) {\r\n      for (let monat = 0; monat < 12; monat++) kapital = kapital * (1 + monatsrendite) + monatlicheEinzahlung;\r\n    }\r\n    return kapital;\r\n  }\r\n\r\n  function berechneIndividual(guthaben, monatlicheEinzahlung, r, alter, ra, startChildAges, rNeben) {\r\n    const laufzeit = ra - alter;\r\n    const kinder = [...startChildAges];\r\n    \/\/ \u00a7 86 EStG: Starterbonus (\u00a7 84 Satz 2) wie Grund- und Kinderzulage nur ab 120 \u20ac\/Jahr Eigenbeitrag\r\n    const starterbonus = alter < 25 ? (monatlicheEinzahlung * 12 >= 120 ? 200 : 0) : 0;   \/\/ Starterbonus zaehlt zur Foerderung (sonst stimmt die Aufschluesselung Eigenbeitrag\/Foerderung\/Wertzuwachs nicht)\r\n    let kapital = guthaben + starterbonus;\r\n    let foerderungGesamt = starterbonus;\r\n    let steuererstattungGesamt = 0;\r\n    let steuererstattungAVD = 0;\r\n    let nebenKapital = 0, nebenEingezahlt = 0, erstGef = 0, erstUng = 0, erstGefVorjahr = 0;   \/\/ E-059: Vertragsanteil der Erstattung, gef\u00f6rdert \/ ungef\u00f6rdert\r\n    const monatsrendite = Math.pow(1 + r, 1\/12) - 1;\r\n    for (let jahr = 1; jahr <= laufzeit; jahr++) {\r\n      if (erstattungAnlegen) nebenKapital = nebenKapital * (1 + (rNeben == null ? r : rNeben));\r\n      for (let monat = 0; monat < 12; monat++) kapital = kapital * (1 + monatsrendite) + monatlicheEinzahlung;\r\n      const jahresbeitrag = monatlicheEinzahlung * 12;\r\n      \/\/ E-059b (Stufe 2): Beitrag des Jahres f\u00fcr Zulagen, Mindesteigenbeitrag und Sonderausgabenabzug ist der regul\u00e4re\r\n      \/\/ Jahresbeitrag plus der gef\u00f6rderte Teil der Vorjahreserstattung, die in diesem Jahr eingezahlt wird (\u00a7 82 Abs. 1, \u00a7 88 EStG;\r\n      \/\/ AVD \u00a7\u00a7 84 bis 86 und \u00a7 10a n. F., Riester in der bis 2026 geltenden Fassung). Einzahlungsgrenze (6.840 \u20ac), Restluft und\r\n      \/\/ Berufseinsteigerbonus rechnen weiter mit dem regul\u00e4ren Jahresbeitrag.\r\n      const beitragJahr = jahresbeitrag + erstGefVorjahr;\r\n      erstGefVorjahr = 0;   \/\/ unten neu gesetzt, wenn in diesem Jahr ein gef\u00f6rderter Erstattungsteil in den Vertrag flie\u00dft\r\n      let foerderungJahr = 0;\r\n      if (beitragJahr >= 120) {\r\n        foerderungJahr = Math.min(beitragJahr, 360) * 0.50 + Math.max(0, Math.min(beitragJahr, 1800) - 360) * 0.25;\r\n      }\r\n      if (beitragJahr >= 120) {   \/\/ \u00a7 86 EStG: Kinderzulage wie Grundzulage nur ab 120 \u20ac\/Jahr Eigenbeitrag\r\n        for (let k = 0; k < kinder.length; k++) { if (kinder[k] >= 0 && kinder[k] < 25) foerderungJahr += Math.min(beitragJahr, 300); }\r\n      }\r\n      if (foerderungJahr > 0) { kapital += foerderungJahr; foerderungGesamt += foerderungJahr; }\r\n      var _refund = sonderausgabenErstattung(Math.min(beitragJahr, AVD_ABZUG_MAX), foerderungJahr, getErwerbsBrutto());\r\n      if (_refund > 0) {\r\n        var _sp = erstattungSplit(_refund, jahresbeitrag);\r\n        if (_sp.avd   > 0) { kapital      += _sp.avd;   steuererstattungAVD += _sp.avd; }   \/\/ bis zur Einzahlungsgrenze in den Vertrag\r\n        \/\/ E-059: Die eingezahlte Erstattung ist Beitrag des Folgejahres (\u00a7 88 EStG). Gef\u00f6rdert nur bis 1.800 \u20ac minus regul\u00e4rer\r\n        \/\/ Jahresbeitrag (\u00a7 10a Abs. 1, \u00a7 82 Abs. 1 EStG), der Rest ist \u00dcberzahlung und ungef\u00f6rdert (BMF 05.10.2023 Rn. 136).\r\n        \/\/ Die Erstattung des letzten Ansparjahres flie\u00dft erst in der Auszahlphase zu und z\u00e4hlt ungef\u00f6rdert (Vereinfachung:\r\n        \/\/ sie bleibt im Vertragskapital gebucht).\r\n        var _erstGef = (laufzeit > jahr) ? Math.min(_sp.avd, Math.max(0, AVD_ABZUG_MAX-jahresbeitrag)) : 0;\r\n        erstGef += _erstGef; erstUng += _sp.avd-_erstGef; erstGefVorjahr = _erstGef;   \/\/ E-059b: im Folgejahr Teil von beitragJahr\r\n        if (_sp.neben > 0) { nebenKapital += _sp.neben; nebenEingezahlt     += _sp.neben; }\r\n        steuererstattungGesamt += _refund;\r\n      }\r\n      for (let k = 0; k < kinder.length; k++) kinder[k]++;\r\n    }\r\n    return { kapital, foerderungGesamt, steuererstattungGesamt, steuererstattungAVD, nebenKapital, nebenEingezahlt, steuererstattungGef: erstGef, steuererstattungUng: erstUng };\r\n  }\r\n\r\n  function berechneZulageAnzeige(monatlich, kinder, alter, ra) {\r\n    const jahresbeitrag = monatlich * 12;\r\n    let grundzulage = 0;\r\n    if (jahresbeitrag >= 120) {\r\n      grundzulage = Math.min(jahresbeitrag, 360) * 0.50 + Math.max(0, Math.min(jahresbeitrag, 1800) - 360) * 0.25;\r\n    }\r\n    const kinderUnter25 = kinder.filter(a => a >= 0 && a < 25).length;\r\n    const kinderzulage = jahresbeitrag >= 120 ? kinderUnter25 * Math.min(jahresbeitrag, 300) : 0;\r\n    return { grundzulage, kinderzulage, gesamt: grundzulage + kinderzulage };\r\n  }\r\n\r\n  \/\/ \u2500\u2500 Hauptberechnung \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  function berechnen() {\r\n    if (!validate()) { return; }\r\n\r\n    const alter      = parseInt(document.getElementById('alter').value);\r\n    const guthaben   = parseFloat((document.getElementById('guthaben').value || '').replace(\/[^0-9]\/g, '')) || 0;\r\n    let einzahlung   = parseFloat(document.getElementById('einzahlung').value) || 0;\r\n    const laufzeit   = rentenalter - alter;\r\n    aktuelleLaufzeit = laufzeit;\r\n    const s = interpolateSzenario(szenarioVal);\r\n\r\n    document.getElementById('einzahlung-warning').classList.toggle('show', einzahlung > 0 && einzahlung < 10);\r\n    document.getElementById('einzahlung-info').classList.toggle('show', einzahlung >= 150 && einzahlung <= 570);\r\n    document.getElementById('einzahlung-max').classList.toggle('show', einzahlung > 570);\r\n    if (einzahlung > 570) { einzahlung = 570; document.getElementById('einzahlung').value = 570; }\r\n\r\n    const riesterResult    = berechneRiester(guthaben, einzahlung, s.riester, alter, rentenalter, childAges, s.etf);\r\n    const depotResult      = berechneDepot(guthaben, einzahlung, s.depot, alter, rentenalter, childAges, rentenalter, s.etf);\r\n    const etfEndkapital    = berechneETF(guthaben, einzahlung, s.etf, alter, rentenalter);\r\n    const individualResult = berechneIndividual(guthaben, einzahlung, s.depot, alter, rentenalter, childAges, s.etf);\r\n\r\n    const riesterEndkapital         = riesterResult.kapital;\r\n    const depotEndkapital           = depotResult.kapital;\r\n    const individualEndkapital      = individualResult.kapital;\r\n    const foerderungRiesterGesamt   = riesterResult.foerderungGesamt;\r\n    const foerderungDepotGesamt     = depotResult.foerderungGesamt;\r\n    const foerderungIndividualGesamt = individualResult.foerderungGesamt;\r\n    const steuererstattungRiesterGesamt    = riesterResult.steuererstattungGesamt || 0;\r\n    const steuererstattungDepotGesamt      = depotResult.steuererstattungGesamt || 0;\r\n    const steuererstattungIndividualGesamt = individualResult.steuererstattungGesamt || 0;\r\n    \/\/ B1: nur der Teil der Erstattung, der in die 6.840-EUR-Grenze passte, sitzt im\r\n    \/\/ gefoerderten Vertrag. Der Ueberhang bildet ein eigenes ETF-Nebendepot.\r\n    const steuererstattungRiesterAVD    = riesterResult.steuererstattungAVD    != null ? riesterResult.steuererstattungAVD    : steuererstattungRiesterGesamt;\r\n    const steuererstattungDepotAVD      = depotResult.steuererstattungAVD      != null ? depotResult.steuererstattungAVD      : steuererstattungDepotGesamt;\r\n    const steuererstattungIndividualAVD = individualResult.steuererstattungAVD != null ? individualResult.steuererstattungAVD : steuererstattungIndividualGesamt;\r\n    const nebenRiester    = riesterResult.nebenKapital    || 0;\r\n    const nebenDepot      = depotResult.nebenKapital      || 0;\r\n    const nebenIndividual = individualResult.nebenKapital || 0;\r\n    const nebenEingRiester    = riesterResult.nebenEingezahlt    || 0;\r\n    const nebenEingDepot      = depotResult.nebenEingezahlt      || 0;\r\n    const nebenEingIndividual = individualResult.nebenEingezahlt || 0;\r\n    \/\/ Nur wenn der Ueberhang tatsaechlich angelegt wird, gehoert er zum Vermoegen bei\r\n    \/\/ Renteneintritt. Sonst ist er waehrend der Ansparzeit frei verwendet worden.\r\n    const gesamtRiester    = riesterEndkapital    + nebenRiester;\r\n    const gesamtDepot      = depotEndkapital      + nebenDepot;\r\n    const gesamtIndividual = individualEndkapital + nebenIndividual;\r\n    \/\/ Angezeigte Foerderung: im Anlege-Modus zaehlt die volle Erstattung zum Vermoegen,\r\n    \/\/ sonst nur der Teil, der tatsaechlich in den Vertrag geflossen ist. Damit schliesst\r\n    \/\/ Eigenbeitrag + Foerderung + Wertzuwachs = Bezugsgroesse in beiden Modi.\r\n    const foerderAnzeigeRiester    = foerderungRiesterGesamt    + steuererstattungRiesterGesamt;\r\n    const foerderAnzeigeDepot      = foerderungDepotGesamt      + steuererstattungDepotGesamt;\r\n    const foerderAnzeigeIndividual = foerderungIndividualGesamt + steuererstattungIndividualGesamt;\r\n\r\n    document.getElementById('r-endkapital').dataset.raw = riesterEndkapital;\r\n    document.getElementById('d-endkapital').dataset.raw = depotEndkapital;\r\n    document.getElementById('e-endkapital').dataset.raw = etfEndkapital;\r\n    document.getElementById('i-endkapital').dataset.raw = individualEndkapital;\r\n    \/\/ Eingezahlte Summe ETF (f\u00fcr Gewinn-\/Abgeltungsteuer-Berechnung im Netto-Modus)\r\n    const eingezahltGesamt = guthaben + einzahlung * 12 * laufzeit;\r\n    document.getElementById('e-endkapital').dataset.eingezahlt = eingezahltGesamt;\r\n    \/\/ Gesamte F\u00f6rderung je nachgelagert besteuertem Topf (f\u00fcr Zwei-T\u00f6pfe-Auszahlbesteuerung im Netto-Modus)\r\n    document.getElementById('r-endkapital').dataset.zulage = foerderungRiesterGesamt;\r\n    document.getElementById('d-endkapital').dataset.zulage = foerderungDepotGesamt;\r\n    document.getElementById('i-endkapital').dataset.zulage = foerderungIndividualGesamt;\r\n    \/\/ Steuerersparnis getrennt (nur Vertragsanteil): E-059 gef\u00f6rderter Teil in den gef\u00f6rderten Topf (gefBeitr), \u00dcberzahlung in den ungef\u00f6rderten; nie in die Eigenbeitrag-Grenze.\r\n    \/\/ B1: nur der AVD-Anteil; der \u00dcberhang wird als Nebendepot separat mit Abgeltungsteuer besteuert.\r\n    Object.assign(document.getElementById('r-endkapital').dataset, { steuererstattung: riesterResult.steuererstattungGef, steuererstattungUng: riesterResult.steuererstattungUng });\r\n    Object.assign(document.getElementById('d-endkapital').dataset, { steuererstattung: depotResult.steuererstattungGef, steuererstattungUng: depotResult.steuererstattungUng });\r\n    Object.assign(document.getElementById('i-endkapital').dataset, { steuererstattung: individualResult.steuererstattungGef, steuererstattungUng: individualResult.steuererstattungUng });\r\n    document.getElementById('r-endkapital').dataset.neben = nebenRiester;\r\n    document.getElementById('d-endkapital').dataset.neben = nebenDepot;\r\n    document.getElementById('i-endkapital').dataset.neben = nebenIndividual;\r\n    document.getElementById('r-endkapital').dataset.nebenEingezahlt = nebenEingRiester;\r\n    document.getElementById('d-endkapital').dataset.nebenEingezahlt = nebenEingDepot;\r\n    document.getElementById('i-endkapital').dataset.nebenEingezahlt = nebenEingIndividual;\r\n    document.getElementById('r-endkapital').dataset.gesamt = gesamtRiester;\r\n    document.getElementById('d-endkapital').dataset.gesamt = gesamtDepot;\r\n    document.getElementById('i-endkapital').dataset.gesamt = gesamtIndividual;\r\n\r\n    const entnahmeMonate = leJahre * 12;\r\n    const rRente = gesamtRiester    \/ entnahmeMonate;\r\n    const dRente = gesamtDepot      \/ entnahmeMonate;\r\n    const eRente = etfEndkapital    \/ entnahmeMonate;\r\n    const iRente = gesamtIndividual \/ entnahmeMonate;\r\n\r\n    const foerderung = berechneZulageAnzeige(einzahlung, childAges, alter, rentenalter);\r\n\r\n    const hinweis2029El = document.getElementById('hinweis-2029');\r\n    if (hinweis2029El) hinweis2029El.style.display = 'none';\r\n\r\n    const delta = gesamtIndividual - gesamtRiester;\r\n\r\n    \/\/ Grundsicherung\r\n    const gsAktiv = rRente > 0 && rRente < 200;\r\n    if (gsAktiv) {\r\n      const rGsFrei = gsFreibetrag(rRente);\r\n      const rMitGs = Math.round(GS_BEDARF +rGsFrei);\r\n      const diff = rMitGs - Math.round(dRente);\r\n      document.getElementById('delta-label').textContent = 'In dieser Beispielrechnung liegt Riester vorn';\r\n      document.getElementById('delta-real').textContent = 'in heutiger Kaufkraft: +' + fmt(realwert(diff, laufzeit)) + '\/Mo.';\r\n      document.getElementById('delta-amount').textContent = '+' + diff.toLocaleString('de-DE') + ' \u20ac\/Mo.';\r\n      document.getElementById('delta-sub').textContent = 'voraussichtlich mehr im Alter \u2013 Riester: ' + rMitGs.toLocaleString('de-DE') + ' \u20ac\/Mo. \u00b7 AVD: ' + Math.round(dRente).toLocaleString('de-DE') + ' \u20ac\/Mo.';\r\n    } else {\r\n      const absDelta = Math.abs(delta);\r\n      document.getElementById('delta-amount').textContent = '+' + fmt(absDelta);\r\n      document.getElementById('delta-label').textContent = delta >= 0\r\n        ? 'In dieser Beispielrechnung liegt das AVD Flex-Depot vorn'\r\n        : 'In dieser Beispielrechnung liegt Riester vorn';\r\n      document.getElementById('delta-sub').textContent = delta >= 0\r\n        ? 'voraussichtlich mehr als mit Riester'\r\n        : 'voraussichtlich mehr als mit dem AVD Flex-Depot';\r\n      document.getElementById('delta-real').textContent = 'in heutiger Kaufkraft: +' + fmt(realwert(absDelta, laufzeit));\r\n    }\r\n\r\n    document.getElementById('r-endkapital').textContent = fmt(riesterEndkapital);\r\n    document.getElementById('r-rente').textContent      = fmt(rRente);\r\n    document.getElementById('r-foerderung').textContent = fmt(foerderAnzeigeRiester);\r\n\r\n    document.getElementById('d-endkapital').textContent = fmt(depotEndkapital);\r\n    document.getElementById('d-rente').textContent      = fmt(dRente);\r\n    document.getElementById('d-foerderung').textContent = fmt(foerderAnzeigeDepot);\r\n\r\n    document.getElementById('e-endkapital').textContent = fmt(etfEndkapital);\r\n    document.getElementById('e-rente').textContent      = fmt(eRente);\r\n\r\n    document.getElementById('i-endkapital').textContent = fmt(individualEndkapital);\r\n    document.getElementById('i-rente').textContent      = fmt(iRente);\r\n    document.getElementById('i-foerderung').textContent = fmt(foerderAnzeigeIndividual);\r\n\r\n    \/\/ Aufschluesselung je Karte: Eigenbeitrag \/ Foerderung \/ Wertzuwachs (brutto)\r\n    ['r', 'd', 'e', 'i'].forEach(p => { document.getElementById(p + '-eingezahlt').textContent = fmt(eingezahltGesamt); });\r\n    \/\/ B1: Bezugsgroesse ist das Gesamtkapital (Vertrag + Nebendepot), damit die Bilanz\r\n    \/\/ Eigenbeitrag + Foerderung + Wertzuwachs = Gesamtkapital weiter aufgeht. \"Foerderung\"\r\n    \/\/ bleibt der volle Betrag inkl. Steuererstattung - gewaehrt wurde sie ja in voller Hoehe.\r\n    \/\/ Wertzuwachs = Bezugsgroesse minus Eigenbeitrag minus angezeigte Foerderung.\r\n    \/\/ Die angezeigte Foerderung ist modusabhaengig (siehe foerderAnzeige oben): im Anlege-Modus\r\n    \/\/ gehoert die komplette Erstattung zum Vermoegen, sonst nur ihr Vertragsanteil.\r\n    document.getElementById('r-wertzuwachs').textContent = fmt(gesamtRiester-eingezahltGesamt-foerderAnzeigeRiester);\r\n    document.getElementById('d-wertzuwachs').textContent = fmt(gesamtDepot-eingezahltGesamt-foerderAnzeigeDepot);\r\n    document.getElementById('e-wertzuwachs').textContent = fmt(etfEndkapital-eingezahltGesamt);\r\n    document.getElementById('i-wertzuwachs').textContent = fmt(gesamtIndividual-eingezahltGesamt-foerderAnzeigeIndividual);\r\n    \/\/ Zeile fuer den Ueberhang: je nach Modus Nebendepot (zaehlt mit) oder frei verfuegbar (zaehlt nicht mit)\r\n    [['r', nebenRiester, gesamtRiester], ['d', nebenDepot, gesamtDepot], ['i', nebenIndividual, gesamtIndividual]].forEach(function(x){\r\n      var pre = x[0], nb = x[1], ges = x[2];\r\n      var rowN = document.getElementById(pre + '-neben-row'), rowG = document.getElementById(pre + '-gesamt-row');\r\n      if (rowN) rowN.style.display = nb > 0 ? '' : 'none';\r\n      if (rowG) rowG.style.display = nb > 0 ? '' : 'none';\r\n      var lblN = document.getElementById(pre + '-neben-label');\r\n      if (lblN) lblN.textContent = erstattungAnlegen ? '+ Fonds-Nebendepot' : '+ Steuererstattung (nicht angelegt)';\r\n      var elN = document.getElementById(pre + '-neben'); if (elN) elN.textContent = fmt(nb);\r\n      var elG = document.getElementById(pre + '-gesamt'); if (elG) elG.textContent = fmt(ges);\r\n    });\r\n\r\n    \/\/ Kaufkraft heute (real, auf Renteneintritt abgezinst, 2% Inflation)\r\n    document.getElementById('r-endkapital-real').textContent = '= heute ' + fmt(realwert(riesterEndkapital, laufzeit));\r\n    document.getElementById('d-endkapital-real').textContent = '= heute ' + fmt(realwert(depotEndkapital, laufzeit));\r\n    document.getElementById('e-endkapital-real').textContent = '= heute ' + fmt(realwert(etfEndkapital, laufzeit));\r\n    document.getElementById('i-endkapital-real').textContent = '= heute ' + fmt(realwert(individualEndkapital, laufzeit));\r\n    document.getElementById('r-rente-real').textContent = fmt(realwert(rRente, laufzeit));\r\n    document.getElementById('d-rente-real').textContent = fmt(realwert(dRente, laufzeit));\r\n    document.getElementById('e-rente-real').textContent = fmt(realwert(eRente, laufzeit));\r\n    document.getElementById('i-rente-real').textContent = fmt(realwert(iRente, laufzeit));\r\n\r\n    \/\/ Netto-Werte (nach Steuer) aktualisieren \u2013 greift nur, wenn Netto-Toggle aktiv\r\n    updateNettoAnzeige();\r\n\r\n    \/\/ #results sichtbar machen BEVOR Chart-Rendering (Mobile-Fix f\u00fcr 0-Dimensionen)\r\n    const resultsEl = document.getElementById('results');\r\n    if (resultsEl) {\r\n      resultsEl.className = 'results show';\r\n      resultsEl.style.display = 'block';\r\n    }\r\n\r\n    updateRentenBarChart(rRente, dRente, eRente, iRente);\r\n\r\n    \/\/ GS-Zeilen\r\n    if (gsAktiv) {\r\n      const rGsFrei = gsFreibetrag(rRente);\r\n      const rGsGesamt = GS_BEDARF +Math.round(rGsFrei);\r\n      ['r-gs-row','r-gs-anrech-row','r-gs-gesamt-row','d-gs-row','d-gs-anrech-row','d-gs-gesamt-row','i-gs-row','i-gs-anrech-row','i-gs-gesamt-row','e-gs-row','e-gs-anrech-row','e-gs-gesamt-row'].forEach(id => {\r\n        const el = document.getElementById(id); if (el) el.style.display = 'flex';\r\n      });\r\n      const rGsValEl = document.getElementById('r-gs-val'); if (rGsValEl) rGsValEl.textContent = Math.round(rGsFrei) + ' \u20ac\/Mo.';\r\n      const rGsGesamtValEl = document.getElementById('r-gs-gesamt-val'); if (rGsGesamtValEl) rGsGesamtValEl.textContent = rGsGesamt.toLocaleString('de-DE') + ' \u20ac\/Mo.';\r\n      const dGsGesamtValEl = document.getElementById('d-gs-gesamt-val'); if (dGsGesamtValEl) dGsGesamtValEl.textContent = GS_BEDARF.toLocaleString('de-DE') + ' \u20ac\/Mo.';\r\n      const iGsGesamtValEl = document.getElementById('i-gs-gesamt-val'); if (iGsGesamtValEl) iGsGesamtValEl.textContent = GS_BEDARF.toLocaleString('de-DE') + ' \u20ac\/Mo.';\r\n    } else {\r\n      ['r-gs-row','r-gs-anrech-row','r-gs-gesamt-row','d-gs-row','d-gs-anrech-row','d-gs-gesamt-row','i-gs-row','i-gs-anrech-row','i-gs-gesamt-row','e-gs-row','e-gs-anrech-row','e-gs-gesamt-row'].forEach(id => {\r\n        const el = document.getElementById(id); if (el) el.style.display = 'none';\r\n      });\r\n    }\r\n\r\n    \/\/ Karten sortieren: nach dem angezeigten Hauptwert (Netto-Modus an: Netto-Endkapital, sonst Brutto)\r\n    const sortWert = (prefix, brutto) => {\r\n      if (typeof nettoAktiv === 'undefined' || !nettoAktiv) return brutto;\r\n      const eknEl = document.getElementById(prefix + '-endkapital-netto');\r\n      const v = eknEl ? parseFloat(eknEl.dataset.raw) : NaN;\r\n      return isNaN(v) ? brutto : v;\r\n    };\r\n    const kartenDaten = [\r\n      { id: 'card-riester',    wert: gsAktiv ? (GS_BEDARF +gsFreibetrag(rRente)) : sortWert('r', gesamtRiester) },\r\n      { id: 'card-depot',      wert: gsAktiv ? GS_BEDARF : sortWert('d', gesamtDepot) },\r\n      { id: 'card-etf',        wert: gsAktiv ? GS_BEDARF : sortWert('e', etfEndkapital) },\r\n      { id: 'card-individual', wert: gsAktiv ? GS_BEDARF : sortWert('i', gesamtIndividual) },\r\n    ];\r\n    kartenDaten.sort((a, b) => b.wert - a.wert);\r\n    const grid = document.querySelector('.cards-grid');\r\n    kartenDaten.forEach((k, i) => {\r\n      const el = document.getElementById(k.id);\r\n      if (el) { el.classList.toggle('winner', i === 0); grid.appendChild(el); }\r\n    });\r\n    setWerbeWeg(kartenDaten);   \/\/ E-059: Banner passend zur Rangfolge (PreLaunch: keine Box-Umschaltung)\r\n\r\n    document.getElementById('f-grundzulage').textContent = fmt(foerderung.grundzulage);\r\n    document.getElementById('f-kinderzulage').textContent = fmt(foerderung.kinderzulage);\r\n    document.getElementById('f-steuerersparnis').textContent = fmt(steuererstattungDepotGesamt);\r\n    document.getElementById('f-steuer-item').style.display = steuererstattungDepotGesamt > 0 ? '' : 'none';\r\n    var fNebenEl = document.getElementById('f-steuer-neben');\r\n    if (fNebenEl) {\r\n      fNebenEl.textContent = nebenDepot > 0 ? (erstattungAnlegen ? 'davon ' + fmt(nebenEingDepot) + ' ins Fonds-Nebendepot' : 'davon ' + fmt(nebenEingDepot) + ' nicht angelegt') : '';\r\n      fNebenEl.style.display = nebenDepot > 0 ? '' : 'none';\r\n    }\r\n    document.getElementById('f-gesamt').textContent = fmt(foerderungDepotGesamt + steuererstattungDepotGesamt);\r\n\r\n    const ctaTitel = document.getElementById('cta-vormerk-titel');\r\n    if (ctaTitel) {\r\n      ctaTitel.textContent = 'AVD vormerken';\r\n    }\r\n\r\n    document.getElementById('results').className = 'results show';\r\n\r\n    clearTimeout(chartDebounceTimer);\r\n    chartDebounceTimer = setTimeout(() => {\r\n      renderVerlaufChart(guthaben, einzahlung, s, alter, rentenalter, childAges);\r\n    }, 200);\r\n  }\r\n\r\n  \/\/ \u2500\u2500 Werbe-Weg nach angezeigter Rangfolge (E-059) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  \/\/ Sieger = erste Karte nach der Sortierung (angezeigter Wert: Netto an = netto, sonst brutto; Grundsicherungsfall wie die\r\n  \/\/ Sortierung). ETF-Sparplan vorn und mindestens 1 \u20ac vor dem besten AVD-Weg: Box regul\u00e4res Depot. Riester vorn (mit echtem\r\n  \/\/ Vorsprung): Riester-Box. Sonst, auch bei etwa gleich oder Gleichstand (z. B. alle Werte 0): AVD-Box. Umgeschaltet wird nur,\r\n  \/\/ wenn die Depot-Box im Markup existiert (PreLaunch: nur der Banner). Neue Texte in diesem Kern-Teil stehen in Backticks,\r\n  \/\/ damit der Template-Kern keine neuen einfachen oder doppelten Anf\u00fchrungszeichen bekommt (WordPress-Texturize-Regel).\r\n  function setWerbeWeg(kartenDaten) {\r\n    var wertVon = function (id) { for (var i = 0; kartenDaten.length > i; i++) { if (kartenDaten[i].id === id) return kartenDaten[i].wert; } return -Infinity; };\r\n    var sieger = kartenDaten.length ? kartenDaten[0].id : null;\r\n    var avdBest = Math.max(wertVon(`card-depot`), wertVon(`card-individual`));\r\n    var weg = `avd`;\r\n    if (sieger === `card-riester`) { if (wertVon(`card-riester`) > Math.max(avdBest, wertVon(`card-etf`))) weg = `riester`; }\r\n    else if (sieger === `card-etf`) { if (wertVon(`card-etf`)-avdBest >= 1) weg = `depot`; }\r\n    if (document.getElementById(`cta-depot`)) {\r\n      var box = { avd: `cta-kasten`, riester: `cta-kein-wechsel`, depot: `cta-depot` };\r\n      Object.keys(box).forEach(function (w) { var el = document.getElementById(box[w]); if (el) el.style.display = (w === weg) ? `block` : `none`; });\r\n    }\r\n    \/\/ Banner (vergleicht nur Flex-Depot und Riester): kein Siegertext f\u00fcr das Flex-Depot, wenn eine andere Karte den Stern tr\u00e4gt.\r\n    \/\/ Gepr\u00fcft werden die Zeilen, die dieser Rechenlauf gerade geschrieben hat (die Netto-Zeile nur bei Netto an, sonst bliebe dort\r\n    \/\/ ein veralteter, ausgeblendeter Text zur\u00fcck).\r\n    if (sieger !== `card-individual`) {\r\n      (nettoAktiv ? [`delta-label`, `delta-label-netto`] : [`delta-label`]).forEach(function (id) {\r\n        var el = document.getElementById(id);\r\n        if (el) { if (el.textContent === `In dieser Beispielrechnung liegt das AVD Flex-Depot vorn`) el.textContent = `Vergleich Altersvorsorgedepot vs. Riester`; }\r\n      });\r\n    }\r\n    return weg;\r\n  }\r\n  \/\/ WordPress-sicher: Depot-CTA ohne Inline-Handler, per Delegation (einmalig, mit noopener)\r\n  if (!window.__AVD_ZERO_CTA__) {\r\n    window.__AVD_ZERO_CTA__ = true;\r\n    document.addEventListener(`click`, function (e) {\r\n      var cta = (e.target ? e.target.closest : null) ? e.target.closest(`[data-zero-cta]`) : null;\r\n      if (cta) window.open(cta.getAttribute(`data-zero-cta`), `_blank`, `noopener`);\r\n    });\r\n  }\r\n  \/\/ \u2500\u2500 Live-Berechnung \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  var chartDebounceTimer = null;\r\n  var hasCalculated = false;\r\n\r\n  function ersteBerechnung() {\r\n    hasCalculated = true;\r\n    document.getElementById('berechnenBtn').style.display = 'none';\r\n    \/\/ 1.8: Vormerk-Kasten beim ersten Berechnen an Originalposition (innerhalb der Ergebnisse) verschieben\r\n    var ctaSlot = document.getElementById('cta-slot');\r\n    var ctaKasten = document.getElementById('cta-kasten');\r\n    if (ctaSlot && ctaKasten && ctaKasten.parentNode !== ctaSlot) {\r\n      ctaSlot.appendChild(ctaKasten);\r\n    }\r\n  }\r\n\r\n  function berechnenLive() {\r\n    if (!hasCalculated) return;\r\n    const alter      = parseInt(document.getElementById('alter').value);\r\n    const einzahlung = parseFloat(document.getElementById('einzahlung').value) || 0;\r\n    if (!alter || alter < 16 || alter >= rentenalter || einzahlung < 0) return;\r\n    berechnen();\r\n  }\r\n\r\n  document.getElementById('alter').addEventListener('input', berechnenLive);\r\n  document.getElementById('guthaben').addEventListener('input', function() {\r\n    berechnenLive();\r\n  });\r\n  document.getElementById('einzahlung').addEventListener('input', function() {\r\n    const val = parseFloat(this.value) || 0;\r\n    document.getElementById('einzahlung-warning').classList.toggle('show', val > 0 && val < 10);\r\n    document.getElementById('einzahlung-info').classList.toggle('show', val >= 150 && val <= 570);\r\n    document.getElementById('einzahlung-max').classList.toggle('show', val > 570);\r\n    berechnenLive();\r\n  });\r\n  document.getElementById('lebenserwartung').addEventListener('input', berechnenLive);\r\n\r\n  document.querySelectorAll('input[type=\"number\"]').forEach(input => {\r\n    input.addEventListener('keypress', function(e) {\r\n      if (!\/[0-9.]\/.test(e.key) && e.key !== 'Backspace') e.preventDefault();\r\n    });\r\n  });\r\n\r\n  \/\/ \u2500\u2500 Vormerkung Submit \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  \/\/ LIVE-MODUS: Echter Brevo DOI-Call \u00fcber WordPress Backend-Proxy.\r\n  \/\/ Proxy-Endpunkt: \/wp-json\/avd\/v1\/subscribe (Schritt 2 \u2013 noch zu bauen)\r\n  \/\/ Brevo: Liste #62 \u00b7 Template #82 \u00b7 Redirect \u2192 ...\/newsletter-altersvorsorge-danke\/\r\n  async function submitVormerkung(event, formId) {\r\n    event.preventDefault();\r\n    const form           = document.getElementById(formId);\r\n    const riesterCheck   = form.querySelector('input[id^=\"riesterCheck\"]');\r\n    const riesterWechsel = riesterCheck ? riesterCheck.checked : false;\r\n    const submitBtn      = form.querySelector('button[type=\"submit\"]');\r\n    const originalHTML   = submitBtn.innerHTML;\r\n\r\n    if (!form.checkValidity()) {\r\n      form.reportValidity();\r\n      return;\r\n    }\r\n\r\n    const email = form.querySelector('input[type=\"email\"]').value.trim();\r\n    const avdHp = form.querySelector('input[name=\"avd_hp\"]');\r\n    const avdHpVal = avdHp ? avdHp.value : '';\r\n\r\n    submitBtn.disabled    = true;\r\n    submitBtn.textContent = 'Wird gesendet...';\r\n\r\n    try {\r\n      const response = await fetch((location.pathname.indexOf('\/ratgeber\/') === 0 ? '\/ratgeber' : '') + '\/wp-json\/avd\/v1\/subscribe', {\r\n        method:  'POST',\r\n        headers: { 'Content-Type': 'application\/json' },\r\n        body: JSON.stringify({\r\n          email,\r\n          hp: avdHpVal,\r\n          attributes:     { TOOL: 'AVD_RIESTER_VERGLEICH', RIESTER_WECHSEL: riesterWechsel },\r\n          includeListIds: [62],\r\n          templateId:     82,\r\n          redirectionUrl: 'https:\/\/www.finanzen.net\/zero\/newsletter-altersvorsorge-danke\/'\r\n        })\r\n      });\r\n\r\n      if (!response.ok) throw new Error('HTTP ' + response.status);\r\n      const data = await response.json();\r\n\r\n      if (data.success) {\r\n        var okBox = document.createElement('div');\r\n        okBox.setAttribute('role', 'status');\r\n        okBox.setAttribute('aria-live', 'polite');\r\n        okBox.style.cssText = 'background:#eafaf1;border:1px solid #0a8a3f;border-radius:8px;padding:20px;text-align:center;color:#0a3d1f;font-size:15px;font-weight:700;line-height:1.5;';\r\n        okBox.textContent = (typeof window !== 'undefined' && window.AVD_DOI)\r\n          ? '\ud83d\udce7 Fast geschafft! Bitte pr\u00fcfe dein Postfach und best\u00e4tige deine Anmeldung.'\r\n          : '\u2713 Du bist vorgemerkt! Wir informieren dich zum Start.';\r\n        form.innerHTML = '';\r\n        form.appendChild(okBox);\r\n      } else {\r\n        alert('Es ist ein Fehler aufgetreten. Bitte versuche es erneut.');\r\n        submitBtn.disabled    = false;\r\n        submitBtn.innerHTML = originalHTML;\r\n      }\r\n    } catch (err) {\r\n      alert('Verbindungsfehler. Bitte pr\u00fcfe deine Internetverbindung.');\r\n      submitBtn.disabled    = false;\r\n      submitBtn.innerHTML = originalHTML;\r\n    }\r\n  }\r\n\r\n\/\/ \u2500\u2500 WordPress \/ Mobile Preview Fix f\u00fcr Chart.js mit Rebuild \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n(function () {\r\n  var avdChartResizeTimer = null;\r\n  function rebuildAvdCharts() {\r\n    clearTimeout(avdChartResizeTimer);\r\n    avdChartResizeTimer = setTimeout(function () {\r\n      try {\r\n        if (typeof verlaufChartInstance !== 'undefined' && verlaufChartInstance) {\r\n          verlaufChartInstance.resize();\r\n          verlaufChartInstance.update('none');\r\n        }\r\n        if (typeof rentenBarChartInstance !== 'undefined' && rentenBarChartInstance) {\r\n          rentenBarChartInstance.resize();\r\n          rentenBarChartInstance.update('none');\r\n        }\r\n        const results = document.getElementById('results');\r\n        if (results && results.classList.contains('show') && typeof berechnenLive === 'function') {\r\n          berechnenLive();\r\n        }\r\n      } catch (e) {\r\n        console.warn('AVD Chart rebuild failed:', e);\r\n      }\r\n    }, 350);\r\n  }\r\n  window.addEventListener('resize', rebuildAvdCharts);\r\n  window.addEventListener('orientationchange', rebuildAvdCharts);\r\n  document.addEventListener('visibilitychange', function () {\r\n    if (!document.hidden) {\r\n      rebuildAvdCharts();\r\n    }\r\n  });\r\n  window.addEventListener('load', function () {\r\n    setTimeout(rebuildAvdCharts, 500);\r\n  });\r\n})();\r\n\r\n\/\/ \u2500\u2500 Mobile Chart Overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\/\/ Tap auf Chart \u2192 Overlay \u00f6ffnen \u2192 Chart neu rendern im Overlay.\r\n\/\/ Kein Pinch-Zoom. Stabiler f\u00fcr WordPress + Mobile Browser.\r\n(function () {\r\n  var overlayChartInstance = null;\r\n\r\n  window.openChartOverlay = function (type) {\r\n    \/\/ Nur auf Touch-Ger\u00e4ten aktiv (optional: auf Desktop ebenfalls erlaubt)\r\n    const overlay   = document.getElementById('chart-overlay');\r\n    const titleEl   = document.getElementById('overlay-title');\r\n    const subEl     = document.getElementById('overlay-sub');\r\n    const legendEl  = document.getElementById('overlay-legend');\r\n    const canvasEl  = document.getElementById('overlayChart');\r\n\r\n    if (!overlay || !canvasEl) return;\r\n\r\n    \/\/ Vorheriges Overlay-Chart zerst\u00f6ren\r\n    if (overlayChartInstance) {\r\n      overlayChartInstance.destroy();\r\n      overlayChartInstance = null;\r\n    }\r\n\r\n    \/\/ Canvas zur\u00fccksetzen (wichtig f\u00fcr sauberes Re-Render)\r\n    const parent = canvasEl.parentNode;\r\n    const newCanvas = document.createElement('canvas');\r\n    newCanvas.id = 'overlayChart';\r\n    parent.replaceChild(newCanvas, canvasEl);\r\n\r\n    \/\/ Overlay \u00f6ffnen\r\n    overlay.classList.add('open');\r\n    document.body.style.overflow = 'hidden';\r\n\r\n    \/\/ Leichtes Delay damit DOM\/Layout stabil ist vor Chart-Render\r\n    setTimeout(function () {\r\n      const ctx = document.getElementById('overlayChart');\r\n      if (!ctx) return;\r\n\r\n      if (type === 'bar' && rentenBarChartInstance) {\r\n        \/\/ Titel + Sub aus dem Original \u00fcbernehmen\r\n        titleEl.textContent  = document.getElementById('barChartTitle').textContent;\r\n        subEl.textContent    = document.getElementById('barChartSub').textContent;\r\n        legendEl.style.display = 'none';\r\n\r\n        \/\/ Chart-Konfiguration aus der laufenden Instanz klonen\r\n        const src = rentenBarChartInstance;\r\n\r\n        \/\/ Gleicher barLabels-Plugin wie im Original\r\n        const barLabelsPlugin = {\r\n          id: 'barLabelsOverlay',\r\n          afterDraw(chart) {\r\n            const ctx2 = chart.ctx;\r\n            ctx2.save();\r\n            ctx2.font = '600 12px OpenSans, Arial, sans-serif';\r\n            ctx2.textAlign = 'center';\r\n            ctx2.textBaseline = 'bottom';\r\n            chart.data.datasets.forEach((dataset, i) => {\r\n              chart.getDatasetMeta(i).data.forEach((bar, j) => {\r\n                const val = dataset.data[j];\r\n                ctx2.fillStyle = Array.isArray(dataset.borderColor)\r\n                  ? dataset.borderColor[j]\r\n                  : dataset.borderColor;\r\n                ctx2.fillText(\r\n                  Math.round(val).toLocaleString('de-DE') + ' \u20ac',\r\n                  bar.x, bar.y - 5\r\n                );\r\n              });\r\n            });\r\n            ctx2.restore();\r\n          }\r\n        };\r\n\r\n        overlayChartInstance = new Chart(ctx, {\r\n          type: 'bar',\r\n          plugins: [barLabelsPlugin],\r\n          data: JSON.parse(JSON.stringify(src.data)),\r\n          options: {\r\n            responsive: true,\r\n            maintainAspectRatio: false,\r\n            layout: { padding: { top: 28 } },\r\n            animation: { duration: 300 },\r\n            plugins: {\r\n              legend: { display: false },\r\n              tooltip: {\r\n                callbacks: {\r\n                  label: c => Math.round(c.raw).toLocaleString('de-DE') + ' \u20ac\/Mo.'\r\n                }\r\n              },\r\n              datalabels: { display: false }\r\n            },\r\n            scales: {\r\n              y: {\r\n                beginAtZero: true,\r\n                ticks: {\r\n                  callback: v => v.toLocaleString('de-DE') + ' \u20ac',\r\n                  color: '#6c7a8a',\r\n                  font: { size: 12 }\r\n                },\r\n                grid: { color: 'rgba(38,145,255,0.06)' }\r\n              },\r\n              x: {\r\n                ticks: { color: '#6c7a8a', font: { size: 12 } },\r\n                grid: { display: false }\r\n              }\r\n            }\r\n          }\r\n        });\r\n\r\n      } else if (type === 'line' && verlaufChartInstance) {\r\n        titleEl.textContent  = 'Kapitalentwicklung im Vergleich';\r\n        subEl.textContent    = (document.getElementById('lineChartSub') || {}).textContent || 'Verm\u00f6gensentwicklung von heute bis zum Renteneintritt';\r\n        legendEl.style.display = 'flex';\r\n\r\n        const src = verlaufChartInstance;\r\n\r\n        overlayChartInstance = new Chart(ctx, {\r\n          type: 'line',\r\n          data: JSON.parse(JSON.stringify(src.data)),\r\n          options: {\r\n            responsive: true,\r\n            maintainAspectRatio: false,\r\n            animation: { duration: 300 },\r\n            plugins: {\r\n              legend: { display: false },\r\n              tooltip: {\r\n                mode: 'index',\r\n                intersect: false,\r\n                callbacks: {\r\n                  label: c => c.dataset.label + ': ' +\r\n                    (c.raw >= 1000000\r\n                      ? (c.raw\/1000000).toFixed(2) + ' Mio. \u20ac'\r\n                      : c.raw >= 1000\r\n                        ? (c.raw\/1000).toFixed(0) + ' T\u20ac'\r\n                        : c.raw + ' \u20ac')\r\n                }\r\n              }\r\n            },\r\n            scales: {\r\n              x: {\r\n                title: { display: true, text: 'Alter', color: '#6c7a8a', font: { size: 12 } },\r\n                ticks: { color: '#6c7a8a', font: { size: 11 }, maxTicksLimit: 10 },\r\n                grid: { color: 'rgba(38,145,255,0.06)' }\r\n              },\r\n              y: {\r\n                ticks: {\r\n                  color: '#6c7a8a',\r\n                  font: { size: 11 },\r\n                  callback: v =>\r\n                    v >= 1000000 ? (v\/1000000).toFixed(1) + ' Mio. \u20ac' :\r\n                    v >= 1000    ? (v\/1000).toFixed(0) + ' T\u20ac' : v + ' \u20ac'\r\n                },\r\n                grid: { color: 'rgba(38,145,255,0.06)' }\r\n              }\r\n            }\r\n          }\r\n        });\r\n      }\r\n    }, 80);\r\n  };\r\n\r\n  window.closeChartOverlay = function () {\r\n    const overlay = document.getElementById('chart-overlay');\r\n    if (!overlay) return;\r\n    overlay.classList.remove('open');\r\n    document.body.style.overflow = '';\r\n    if (overlayChartInstance) {\r\n      overlayChartInstance.destroy();\r\n      overlayChartInstance = null;\r\n    }\r\n  };\r\n\r\n  \/\/ Tap au\u00dferhalb der Card schlie\u00dft das Overlay\r\n  document.addEventListener('click', function (e) {\r\n    const overlay = document.getElementById('chart-overlay');\r\n    const card    = document.getElementById('chart-overlay-card');\r\n    if (overlay && overlay.classList.contains('open') && card && !card.contains(e.target) && !(e.target.closest && e.target.closest('.chart-tap-wrapper'))) {\r\n      closeChartOverlay();\r\n    }\r\n  });\r\n\r\n  \/\/ ESC-Taste schlie\u00dft Overlay (Desktop-Komfort)\r\n  document.addEventListener('keydown', function (e) {\r\n    if (e.key === 'Escape') closeChartOverlay();\r\n  });\r\n})();\r\n\r\n<\/template>\r\n<script>\r\n(function() {\r\n  if (window.__AVD_TOOL_LOADED__) return;\r\n  window.__AVD_TOOL_LOADED__ = true;\r\n  \r\n  var tmpl = document.getElementById(\"avd-code-tpl\");\r\n  if (!tmpl) {\r\n    console.error(\"[AVD-Tool] Code-Template nicht gefunden\");\r\n    return;\r\n  }\r\n  \r\n  \/\/ textContent ist automatisch HTML-decoded \u2192 kein && \u2192 &amp;&amp; Problem mehr\r\n  var code = tmpl.content ? tmpl.content.textContent : tmpl.textContent; try { new Function(code); } catch (avdEmbTex) { code = code.replace(\/[\u2013\u2014]\/g,\"-\").replace(\/\u2026\/g,\"...\").replace(\/[\u2018\u2019]\/g,\"'\").replace(\/[\u201c\u201d]\/g,'\"').replace(\/\\u00A0\/g,\" \"); }\r\n  \r\n  try {\r\n    \/\/ Mit new Function ausf\u00fchren + globale Exports\r\n    new Function(code + \"\\n; if(typeof window!==\\\"undefined\\\"){window.berechnen=berechnen;window.berechnenLive=berechnenLive;window.ersteBerechnung=ersteBerechnung;window.validate=validate;window.updateSzenario=updateSzenario;window.setSzenario=setSzenario;window.updateLE=updateLE;window.updateRenteneintritt=updateRenteneintritt;window.syncEinzahlung=syncEinzahlung;window.setChildren=setChildren;window.updateChildBirthYear=updateChildBirthYear;window.submitVormerkung=submitVormerkung;window.aktualisiereRenten=aktualisiereRenten;window.updateRentenBarChart=updateRentenBarChart;window.renderVerlaufChart=renderVerlaufChart;window.toggleKaufkraft=toggleKaufkraft;window.toggleNetto=toggleNetto;window.toggleErstattungAnlegen=toggleErstattungAnlegen;window.setChartAnsicht=setChartAnsicht;window.setNettoPfad=setNettoPfad;window.schaetzAusEinkommen=schaetzAusEinkommen;window.onBeitragsjahre=onBeitragsjahre;window.leseRenten=leseRenten;window.toggleSplitting=toggleSplitting;window.setPartnerTyp=setPartnerTyp;}\")();\r\n  } catch (err) {\r\n    console.error(\"[AVD-Tool] Fehler beim Laden:\", err);\r\n  }\r\n})();\r\n<\/script>\r\n<template id=\"avd-code-tpl-2\">\r\nfunction ensureChartReady(callback) {\r\n  if (typeof Chart !== \"undefined\") {\r\n    callback();\r\n    return;\r\n  }\r\n\r\n  console.warn(\"[AVD-Tool] Chart.js noch nicht verf\u00fcgbar \u2013 lade nach\");\r\n\r\n  var existingScript = document.querySelector('script[src*=\"chart.js\"]');\r\n\r\n  if (existingScript) {\r\n    var tries = 0;\r\n    var timer = setInterval(function () {\r\n      tries++;\r\n      if (typeof Chart !== \"undefined\") {\r\n        clearInterval(timer);\r\n        callback();\r\n      }\r\n      if (tries > 60) {\r\n        clearInterval(timer);\r\n        console.error(\"[AVD-Tool] Chart.js konnte nicht geladen werden\");\r\n      }\r\n    }, 150);\r\n    return;\r\n  }\r\n\r\n  var script = document.createElement(\"script\");\r\n  script.src = \"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/themes\/fnet-ratgeber\/js\/libs\/chart.js\";\r\n  script.onload = function () {\r\n    if (typeof Chart !== \"undefined\") {\r\n      callback();\r\n    } else {\r\n      console.error(\"[AVD-Tool] Chart.js Script geladen, aber Chart ist undefined\");\r\n    }\r\n  };\r\n  script.onerror = function () {\r\n    console.error(\"[AVD-Tool] Chart.js konnte nicht nachgeladen werden\");\r\n  };\r\n\r\n  document.head.appendChild(script);\r\n}\r\n\r\nfunction avdStartBerechnung(event) {\r\n  try {\r\n    \/\/ 1. Erst validieren\r\n    if (typeof validate === \"function\" && !validate()) {\r\n      return;\r\n    }\r\n\r\n    \/\/ 2. results sichtbar machen NACH erfolgreicher Validierung\r\n    var results = document.getElementById(\"results\");\r\n    if (results) {\r\n      results.className = \"results show\";\r\n      results.style.display = \"block\";\r\n    }\r\n\r\n    \/\/ 3a. Mobile: Container-H\u00f6hen inline forcieren (\u00fcberschreibt WP-Theme-CSS)\r\n    if (window.innerWidth <= 768) {\r\n      var barWrap = document.getElementById(\"barChartTapWrapper\");\r\n      if (barWrap) {\r\n        barWrap.style.cssText += \";position:relative;width:100%;height:280px;min-height:280px;display:block;\";\r\n      }\r\n      var lineOuter = document.getElementById(\"verlaufChart-outer\");\r\n      if (lineOuter) {\r\n        lineOuter.style.cssText += \";position:relative;width:100%;height:280px;min-height:280px;display:block;\";\r\n      }\r\n      \/\/ Inner chart-tap-wrapper auch\r\n      document.querySelectorAll(\".chart-tap-wrapper\").forEach(function(el) {\r\n        if (el.id !== \"barChartTapWrapper\") {\r\n          el.style.cssText += \";width:100%;height:100%;position:relative;display:block;\";\r\n        }\r\n      });\r\n    }\r\n\r\n    \/\/ 3b. Berechnung direkt ausf\u00fchren (unabh\u00e4ngig von Chart.js)\r\n    if (typeof berechnen === \"function\") berechnen();\r\n\r\n    \/\/ 3c. BFSG: Ergebnis einmalig f\u00fcr Screenreader ank\u00fcndigen (nur hier, nicht bei Live-Updates)\r\n    try {\r\n      var srEl = document.getElementById(\"sr-result\");\r\n      if (srEl) {\r\n        var dlEl = document.getElementById(\"delta-label\");\r\n        var daEl = document.getElementById(\"delta-amount\");\r\n        var dsEl = document.getElementById(\"delta-sub\");\r\n        srEl.textContent = \"Ergebnis: \" + (dlEl ? dlEl.textContent : \"\") + \": \" +\r\n          (daEl ? daEl.textContent : \"\") + \" \" + (dsEl ? dsEl.textContent : \"\");\r\n      }\r\n    } catch (e) {}\r\n\r\n    \/\/ 4. Pr\u00fcfen ob Berechnung erfolgreich war (Endkapital von berechnen gesetzt; 0 ist ein g\u00fcltiges Ergebnis, z. B. 0 \u20ac\/Monat ohne Guthaben, E-056)\r\n    var ids = [\"r-endkapital\", \"d-endkapital\", \"e-endkapital\", \"i-endkapital\"];\r\n    var hasResult = false;\r\n    for (var i = 0; i < ids.length; i++) {\r\n      var el = document.getElementById(ids[i]);\r\n      if (el &#038;&#038; el.dataset &#038;&#038; parseFloat(el.dataset.raw) >= 0) {\r\n        hasResult = true;\r\n        break;\r\n      }\r\n    }\r\n\r\n    \/\/ 5. ersteBerechnung() nur wenn Werte tats\u00e4chlich gesetzt wurden\r\n    if (hasResult) {\r\n      if (typeof ersteBerechnung === \"function\") ersteBerechnung();\r\n    } else {\r\n      console.warn(\"[AVD-Tool] Keine Ergebnisse erkannt \u2013 Button bleibt sichtbar\");\r\n    }\r\n\r\n    \/\/ Charts resize\/update + Smooth Scroll\r\n    setTimeout(function () {\r\n      if (typeof rentenBarChartInstance !== \"undefined\" && rentenBarChartInstance) {\r\n        rentenBarChartInstance.resize();\r\n        rentenBarChartInstance.update(\"none\");\r\n      }\r\n      if (typeof verlaufChartInstance !== \"undefined\" && verlaufChartInstance) {\r\n        verlaufChartInstance.resize();\r\n        verlaufChartInstance.update(\"none\");\r\n      }\r\n      if (results && results.classList.contains(\"show\")) {\r\n        results.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n      }\r\n    }, 350);\r\n\r\n    \/\/ Nachsicherung: Charts k\u00f6nnten fehlen weil Chart.js zu sp\u00e4t geladen wurde\r\n    setTimeout(function () {\r\n      \/\/ Wenn Chart.js noch nicht geladen \u2192 nachladen + berechnen() nochmal\r\n      if (typeof Chart === \"undefined\") {\r\n        if (typeof ensureChartReady === \"function\") {\r\n          ensureChartReady(function () {\r\n            if (typeof window.berechnen === \"function\") window.berechnen();\r\n          });\r\n        }\r\n        return;\r\n      }\r\n\r\n      \/\/ Chart.js ist da \u2013 check ob Canvas wirklich gerendert wurde\r\n      var barCanvas = document.getElementById(\"rentenBarChart\");\r\n      var lineCanvas = document.getElementById(\"verlaufChart\");\r\n      var barEmpty = !barCanvas || barCanvas.width < 50;\r\n      var lineEmpty = !lineCanvas || lineCanvas.width < 50;\r\n\r\n      if (barEmpty || lineEmpty) {\r\n        if (typeof window.berechnen === \"function\") window.berechnen();\r\n      } else {\r\n      }\r\n    }, 600);\r\n\r\n    \/\/ Zus\u00e4tzliche Sicherheit: Nach 1.5s nochmal forcieren falls immer noch leer\r\n    setTimeout(function () {\r\n      var lineCanvas = document.getElementById(\"verlaufChart\");\r\n      if (!lineCanvas || lineCanvas.width < 50) {\r\n        if (typeof Chart !== \"undefined\" &#038;&#038; typeof window.berechnen === \"function\") {\r\n          window.berechnen();\r\n        }\r\n      }\r\n    }, 1500);\r\n\r\n  } catch (err) {\r\n    console.error(\"[AVD-Tool] Fehler bei Berechnung:\", err);\r\n  }\r\n}\r\n\r\n<\/template>\r\n<script>\r\n(function() {\r\n  if (window.__AVD_AVD_LOADED__) return;\r\n  window.__AVD_AVD_LOADED__ = true;\r\n  \r\n  var tmpl = document.getElementById(\"avd-code-tpl-2\");\r\n  if (!tmpl) return;\r\n  \r\n  var code = tmpl.content ? tmpl.content.textContent : tmpl.textContent; try { new Function(code); } catch (avdEmbTex) { code = code.replace(\/[\u2013\u2014]\/g,\"-\").replace(\/\u2026\/g,\"...\").replace(\/[\u2018\u2019]\/g,\"'\").replace(\/[\u201c\u201d]\/g,'\"').replace(\/\\u00A0\/g,\" \"); }\r\n  \r\n  try {\r\n    new Function(code + \"\\n; window.ensureChartReady=ensureChartReady; window.avdStartBerechnung=avdStartBerechnung;\")();\r\n  } catch (err) {\r\n    console.error(\"[AVD-Tool] Click-Code Fehler:\", err);\r\n  }\r\n})();\r\n<\/script>\r\n\r\n<template id=\"avd-tip-tpl\">\r\n(function () {\r\n  var MOBILE_MAX = 640;\r\n  function isMobile() { return window.innerWidth <= MOBILE_MAX; }\r\n  \/\/ Hover NUR an echte Maus-\/Stift-Ger\u00e4te binden \u2013 NICHT an die Fensterbreite.\r\n  \/\/ (Sonst bleibt Desktop-Hover aus, sobald das Vorschaufenster \u2264640px ist.)\r\n  \/\/ Touch-Ger\u00e4te (hover:none) nutzen weiterhin Tap zum Umschalten.\r\n  function canHover() {\r\n    return !(window.matchMedia &#038;&#038; window.matchMedia(\"(hover: none)\").matches);\r\n  }\r\n\r\n  \/\/ Verschobenen Tooltip-Text an seinen Ursprungsort zur\u00fcckstellen\r\n  function restore(tip) {\r\n    tip.classList.remove(\"open\");\r\n    var text = tip.__tipText;\r\n    if (text &#038;&#038; tip.__home) {\r\n      text.classList.remove(\"tip-portal\", \"tip-portal-desktop\");\r\n      text.removeAttribute(\"style\");\r\n      tip.__home.parent.insertBefore(text, tip.__home.next || null);\r\n      tip.__home = null;\r\n    }\r\n  }\r\n\r\n  function closeAllTips(exceptTip) {\r\n    document.querySelectorAll(\".tip.open\").forEach(function (tip) {\r\n      if (tip !== exceptTip) restore(tip);\r\n    });\r\n  }\r\n\r\n  \/\/ Position des portalierten (an <body> geh\u00e4ngten) Tooltips berechnen\r\n  function positionPortal(tip, text, mobile) {\r\n    var r = tip.getBoundingClientRect();\r\n    var vw = window.innerWidth, vh = window.innerHeight || document.documentElement.clientHeight;\r\n    var m = 12;\r\n    if (mobile) {\r\n      text.style.left = \"16px\";\r\n      text.style.right = \"16px\";\r\n    } else {\r\n      text.style.right = \"auto\";\r\n      text.style.left = \"0px\";\r\n    }\r\n    var tr = text.getBoundingClientRect();\r\n    var top = r.top - tr.height - 10;            \/\/ bevorzugt \u00dcBER dem Icon\r\n    if (top < m) top = r.bottom + 10;            \/\/ sonst darunter\r\n    top = Math.max(m, Math.min(top, vh - tr.height - m));\r\n    text.style.top = top + \"px\";\r\n    if (!mobile) {\r\n      var left = r.left + r.width \/ 2 - tr.width \/ 2;   \/\/ mittig zum Icon\r\n      left = Math.max(m, Math.min(left, vw - tr.width - m));\r\n      text.style.left = left + \"px\";\r\n    }\r\n  }\r\n\r\n  \/\/ Tooltip-Text an <body> h\u00e4ngen \u2192 Wurzel-Stacking-Context, nichts verdeckt ihn\r\n  function openTip(tip) {\r\n    if (tip.classList.contains(\"open\")) return;\r\n    var text = tip.__tipText || tip.querySelector(\".tip-text\");\r\n    if (!text) return;\r\n    tip.__tipText = text;\r\n    tip.classList.add(\"open\");\r\n    var mobile = isMobile();\r\n    if (text.parentNode !== (document.querySelector('.avdemb-t18pl')||document.body)) {\r\n      tip.__home = { parent: text.parentNode, next: text.nextSibling };\r\n      (document.querySelector('.avdemb-t18pl')||document.body).appendChild(text);\r\n    }\r\n    text.classList.add(\"tip-portal\");\r\n    if (!mobile) text.classList.add(\"tip-portal-desktop\");\r\n    positionPortal(tip, text, mobile);\r\n  }\r\n\r\n  \/\/ CLICK \/ TAP: umschalten (funktioniert f\u00fcr Touch UND Maus, auch in WordPress)\r\n  document.addEventListener(\"click\", function (event) {\r\n    var tip = event.target.closest ? event.target.closest(\".tip\") : null;\r\n    if (tip) {\r\n      var isOpen = tip.classList.contains(\"open\");\r\n      closeAllTips(tip);\r\n      if (isOpen) restore(tip); else openTip(tip);\r\n      return;\r\n    }\r\n    \/\/ Klick in den bereits ge\u00f6ffneten (portalierten) Text: offen lassen (Scrollen erlauben)\r\n    if (event.target.closest && event.target.closest(\".tip-text.tip-portal\")) return;\r\n    closeAllTips(null);\r\n  });\r\n\r\n  \/\/ DESKTOP-Maus: Hover \u00f6ffnet\/schlie\u00dft (Portal-Text hat pointer-events:none, daher zuverl\u00e4ssiges Schlie\u00dfen)\r\n  document.addEventListener(\"mouseover\", function (event) {\r\n    if (!canHover()) return;\r\n    var tip = event.target.closest ? event.target.closest(\".tip\") : null;\r\n    if (tip) openTip(tip);\r\n  });\r\n  document.addEventListener(\"mouseout\", function (event) {\r\n    if (!canHover()) return;\r\n    var tip = event.target.closest ? event.target.closest(\".tip\") : null;\r\n    if (!tip) return;\r\n    var to = event.relatedTarget;\r\n    if (to && tip.contains(to)) return;   \/\/ Bewegung innerhalb des Icons ignorieren\r\n    restore(tip);\r\n  });\r\n\r\n  \/\/ Tastatur (BFSG): Fokus \u00f6ffnet, Verlassen schlie\u00dft\r\n  document.addEventListener(\"focusin\", function (event) {\r\n    var tip = event.target.closest ? event.target.closest(\".tip\") : null;\r\n    if (tip) openTip(tip);\r\n  });\r\n  document.addEventListener(\"focusout\", function (event) {\r\n    var tip = event.target.closest ? event.target.closest(\".tip\") : null;\r\n    if (tip) restore(tip);\r\n  });\r\n\r\n  window.addEventListener(\"resize\", function () { closeAllTips(null); });\r\n  window.addEventListener(\"scroll\", function () { closeAllTips(null); }, true);\r\n})();\r\n<\/template>\r\n<script>\r\n(function() {\r\n  \/\/ Event-Delegation auf document \u2192 funktioniert immer,\r\n  \/\/ egal wann der Button im DOM erscheint (auch in Mobile-Editor-Iframes)\r\n  if (window.__AVD_CLICK_DELEGATED__) return;\r\n  window.__AVD_CLICK_DELEGATED__ = true;\r\n\r\n  document.addEventListener(\"click\", function(e) {\r\n    var btn = e.target.closest && e.target.closest(\"#berechnenBtn\");\r\n    if (!btn) return;\r\n\r\n    if (typeof window.avdStartBerechnung === \"function\") {\r\n      window.avdStartBerechnung(e);\r\n    } else if (typeof avdStartBerechnung === \"function\") {\r\n      avdStartBerechnung(e);\r\n    } else {\r\n    }\r\n  }, true);\r\n})();\r\n<\/script>\r\n\r\n<script>\r\n(function() {\r\n  \/\/ Mobile-Heights direkt beim Init setzen - bevor Chart.js irgendwas tut\r\n  function forceMobileHeights() {\r\n    if (window.innerWidth > 768) return;\r\n    var barWrap = document.getElementById(\"barChartTapWrapper\");\r\n    if (barWrap) {\r\n      barWrap.style.cssText += \";position:relative;width:100%;height:280px;min-height:280px;display:block;\";\r\n    }\r\n    var lineOuter = document.getElementById(\"verlaufChart-outer\");\r\n    if (lineOuter) {\r\n      lineOuter.style.cssText += \";position:relative;width:100%;height:280px;min-height:280px;display:block;\";\r\n    }\r\n  }\r\n  if (document.readyState === \"loading\") {\r\n    document.addEventListener(\"DOMContentLoaded\", forceMobileHeights);\r\n  } else {\r\n    forceMobileHeights();\r\n  }\r\n  window.addEventListener(\"resize\", forceMobileHeights);\r\n})();\r\n<\/script>\r\n\r\n<!-- BFSG: Tooltips automatisch f\u00fcr Screenreader beschriften (aria-label aus dem Tooltip-Text) -->\r\n<script>\r\n(function () {\r\n  function labelTips() {\r\n    document.querySelectorAll('.tip').forEach(function (tip) {\r\n      if (tip.getAttribute('aria-label')) return;\r\n      var txt = tip.querySelector('.tip-text');\r\n      if (!txt) return;\r\n      var raw = txt.innerHTML.replace(\/<br\\s*\\\/?>\/gi, '. ').replace(\/<[^>]+>\/g, '');\r\n      raw = raw.replace(\/\u2022\/g, '').replace(\/\\s+\/g, ' ').trim();\r\n      tip.setAttribute('role', 'img');\r\n      if (raw) tip.setAttribute('aria-label', 'Information: ' + raw);\r\n      txt.setAttribute('aria-hidden', 'true');\r\n    });\r\n  }\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', labelTips);\r\n  } else {\r\n    labelTips();\r\n  }\r\n})();\r\n<\/script>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     WORDPRESS-KOMPATIBILIT\u00c4T \u00b7 Event-Delegation f\u00fcr ALLE Steuerelemente\r\n     \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n     WordPress (KSES \/ Security-Plugins) entfernt inline on*-Handler\r\n     (onchange\/oninput\/onclick) aus dem Post-Content. Deshalb funktionierten\r\n     z. B. der Netto-Toggle und die Slider in WordPress nicht \u2013 die inline\r\n     Handler waren weg, ohne Fallback. Hier h\u00e4ngen wir alle Aktionen \u00fcber\r\n     document-Delegation an. Funktioniert auch dann, wenn die inline-Handler\r\n     gestrippt wurden. Alle Zielfunktionen sind idempotent, deshalb schadet\r\n     ein evtl. doppeltes Feuern (inline + delegiert) nicht.\r\n     \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<script>\r\n(function () {\r\n  if (window.__AVD_CONTROLS_DELEGATED__) return;\r\n  window.__AVD_CONTROLS_DELEGATED__ = true;\r\n\r\n  function run(name) {\r\n    var f = window[name];\r\n    if (typeof f !== \"function\") return;\r\n    try { f.apply(null, Array.prototype.slice.call(arguments, 1)); }\r\n    catch (e) { console.warn(\"[AVD-Tool] \" + name + \" Fehler:\", e); }\r\n  }\r\n\r\n  \/\/ CHANGE \u2192 Checkbox-Toggles (inline onchange wird in WP gestrippt)\r\n  document.addEventListener(\"change\", function (e) {\r\n    var t = e.target;\r\n    if (!t || !t.id) return;\r\n    if (t.id === \"netto-toggle\")          run(\"toggleNetto\", t);\r\n    else if (t.id === \"kaufkraft-toggle\") run(\"toggleKaufkraft\", t);\r\n    else if (t.id === \"erstattung-anlegen\") run(\"toggleErstattungAnlegen\", t);\r\n    else if (t.id === \"split-toggle\")     run(\"toggleSplitting\", t);\r\n  });\r\n\r\n  \/\/ INPUT \u2192 Slider & Zahlenfelder (inline oninput wird in WP gestrippt)\r\n  document.addEventListener(\"input\", function (e) {\r\n    var t = e.target;\r\n    if (!t) return;\r\n    switch (t.id) {\r\n      case \"renteneintritt\":    run(\"updateRenteneintritt\", t.value); break;\r\n      case \"szenario\":          run(\"updateSzenario\", t.value); break;\r\n      case \"lebenserwartung\":   run(\"updateLE\", t.value); run(\"berechnenLive\"); break;   \/\/ E-059b (N1): nach updateLE neu rechnen, sonst bleiben Stern, Reihenfolge und Banner vom Stand davor\r\n      case \"einzahlung-slider\": run(\"syncEinzahlung\", \"slider\", t.value); break;\r\n      case \"einzahlung\":        run(\"syncEinzahlung\", \"input\", t.value); break;\r\n      case \"brutto-jahr\":       run(\"schaetzAusEinkommen\"); break;\r\n      case \"beitragsjahre\":     run(\"onBeitragsjahre\"); break;\r\n      case \"ges-rente\":\r\n      case \"betriebs-rente\":\r\n      case \"partner-rente\":     run(\"leseRenten\"); break;\r\n    }\r\n    \/\/ Dynamisch erzeugte Kinder-Geburtsjahr-Felder (Index via data-ci)\r\n    if (t.classList && t.classList.contains(\"input--childbirth\")) {\r\n      var ci = parseInt(t.getAttribute(\"data-ci\"), 10);\r\n      if (!isNaN(ci)) run(\"updateChildBirthYear\", ci, t);\r\n    }\r\n  });\r\n\r\n  \/\/ CLICK \u2192 Buttons & Karten (inline onclick wird in WP gestrippt)\r\n  document.addEventListener(\"click\", function (e) {\r\n    if (!e.target.closest) return;\r\n\r\n    \/\/ Charts vergr\u00f6\u00dfern (Overlay) \u2013 nur \u00f6ffnen, wenn noch nicht offen (kein Doppel-Open)\r\n    var tapWrap = e.target.closest(\".chart-tap-wrapper\");\r\n    if (tapWrap) {\r\n      var ov = document.getElementById(\"chart-overlay\");\r\n      if (!ov || !ov.classList.contains(\"open\")) {\r\n        run(\"openChartOverlay\", tapWrap.id === \"barChartTapWrapper\" ? \"bar\" : \"line\");\r\n      }\r\n      return;\r\n    }\r\n    if (e.target.closest(\".chart-overlay-close\")) { run(\"closeChartOverlay\"); return; }\r\n\r\n    var el = e.target.closest(\"[id], .netto-pt\");\r\n    if (!el) return;\r\n    var id = el.id || \"\";\r\n    if (\/^kBtn[0-5]$\/.test(id))            { run(\"setChildren\", parseInt(id.slice(4), 10)); return; }\r\n    if (\/^label-[012]$\/.test(id))          { run(\"setSzenario\", parseInt(id.slice(6), 10)); return; }\r\n    if (id === \"netto-card-kenne\")         { run(\"setNettoPfad\", \"kenne\"); return; }\r\n    if (id === \"netto-card-schaetz\")       { run(\"setNettoPfad\", \"schaetzen\"); return; }\r\n    if (id === \"pt-rente\")                 { run(\"setPartnerTyp\", \"rente\"); return; }\r\n    if (id === \"pt-job\")                   { run(\"setPartnerTyp\", \"job\"); return; }\r\n  });\r\n\r\n  \/\/ KEYDOWN \u2192 Netto-Pfad-Karten per Tastatur (Enter\/Space) \u00b7 BFSG\r\n  document.addEventListener(\"keydown\", function (e) {\r\n    if (e.key !== \"Enter\" && e.key !== \" \") return;\r\n    if (!e.target.closest) return;\r\n    var card = e.target.closest(\"#netto-card-kenne, #netto-card-schaetz\");\r\n    if (!card) return;\r\n    e.preventDefault();\r\n    run(\"setNettoPfad\", card.id === \"netto-card-kenne\" ? \"kenne\" : \"schaetzen\");\r\n  });\r\n})();\r\n<\/script>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     EINGABE-WIZARD (Tool 1.3) \u00b7 Schritt-Navigation + Kacheln\r\n     Plain-IIFE mit eigener document-Delegation \u2192 WP-sicher (kein Inline-on*).\r\n     Treibt die bestehenden 1.2-Inputs (gleiche IDs) \u2013 die Rechenlogik bleibt\r\n     unver\u00e4ndert; der letzte Schritt klickt den vorhandenen #berechnenBtn.\r\n     \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<template id=\"avd-wiz-tpl\">\r\n(function () {\r\n  if (window.__AVD_WIZ_LOADED__) return;\r\n  window.__AVD_WIZ_LOADED__ = true;\r\n\r\n  var WIZ_TOTAL = 4;\r\n  var step = 1;\r\n  function $(id) { return document.getElementById(id); }\r\n\r\n  function show(n) {\r\n    step = Math.max(1, Math.min(WIZ_TOTAL, n));\r\n    document.querySelectorAll(\".wiz-step\").forEach(function (s) {\r\n      s.classList.toggle(\"active\", parseInt(s.getAttribute(\"data-step\"), 10) === step);\r\n    });\r\n    var bar = $(\"wiz-bar\"); if (bar) bar.style.width = (step \/ WIZ_TOTAL * 100) + \"%\";\r\n    var num = $(\"wiz-stepnum\"); if (num) num.textContent = \"Schritt \" + step;\r\n    var back = $(\"wiz-back\"); if (back) back.style.visibility = step === 1 ? \"hidden\" : \"visible\";\r\n    var next = $(\"wiz-next\"); if (next) next.textContent = step === WIZ_TOTAL ? \"Ergebnis berechnen \u2192\" : \"Weiter \u2192\";\r\n  }\r\n\r\n  function validStep1() {\r\n    var el = $(\"alter\"); if (!el) return true;\r\n    var v = parseInt(el.value, 10);\r\n    var ok = !(isNaN(v) || v < 16 || v > 66);\r\n    var e = $(\"alter-error\"); if (e) e.classList.toggle(\"show\", !ok);\r\n    el.classList.toggle(\"input--invalid\", !ok);\r\n    return ok;\r\n  }\r\n\r\n  function goNext() {\r\n    if (step === 1 && !validStep1()) return;\r\n    if (step < WIZ_TOTAL) { show(step + 1); return; }\r\n    \/\/ Letzter Schritt \u2192 vorhandenen Berechnen-Button ausl\u00f6sen (gleicher Pfad wie 1.2)\r\n    var wz = $(\"wiz\"); if (wz) wz.classList.add(\"compact\");\r\n    var btn = $(\"berechnenBtn\");\r\n    if (btn) { btn.click(); }\r\n    else if (window.avdStartBerechnung) { try { window.avdStartBerechnung(); } catch (e) {} }\r\n    var r = $(\"results\"); if (r &#038;&#038; r.classList.contains(\"show\")) r.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n  }\r\n  function goPrev() { show(step - 1); }\r\n\r\n  function selectTile(tile) {\r\n    var box = tile.closest(\".wiz-tiles\");\r\n    if (box) box.querySelectorAll(\".wiz-tile\").forEach(function (t) { t.classList.remove(\"sel\"); });\r\n    tile.classList.add(\"sel\");\r\n  }\r\n\r\n  document.addEventListener(\"click\", function (e) {\r\n    if (!e.target.closest) return;\r\n    if (e.target.closest(\"#wiz-next\")) { goNext(); return; }\r\n    if (e.target.closest(\"#wiz-back\")) { goPrev(); return; }\r\n    var tile = e.target.closest(\".wiz-tile\"); if (!tile) return;\r\n    var kind = tile.getAttribute(\"data-wiz\");\r\n    var val = tile.getAttribute(\"data-val\");\r\n    selectTile(tile);\r\n    if (kind === \"riester\") {\r\n      var box = $(\"riester-betrag\"); if (box) box.style.display = (val === \"ja\") ? \"block\" : \"none\";\r\n      if (val !== \"ja\") { var g = $(\"guthaben\"); if (g) g.value = \"0\"; }\r\n    } else if (kind === \"einz\") {\r\n      var inp = $(\"einzahlung\"); if (inp) inp.value = val;\r\n      var sl = $(\"einzahlung-slider\"); if (sl) sl.value = val;\r\n      try { if (window.syncEinzahlung) window.syncEinzahlung(\"input\", val); } catch (e2) {}\r\n    }\r\n  });\r\n\r\n  \/\/ Slider\/Feld bewegt \u2192 passende Kachel markieren (oder abw\u00e4hlen bei individuellem Wert)\r\n  document.addEventListener(\"input\", function (e) {\r\n    var t = e.target; if (!t || !t.id) return;\r\n    if (t.id === \"einzahlung\" || t.id === \"einzahlung-slider\") {\r\n      var v = String(t.value);\r\n      document.querySelectorAll('[data-wiz=\"einz\"]').forEach(function (tile) {\r\n        tile.classList.toggle(\"sel\", tile.getAttribute(\"data-val\") === v);\r\n      });\r\n    }\r\n  });\r\n\r\n  function init() { show(1); }\r\n  document.readyState === \"loading\" ? document.addEventListener(\"DOMContentLoaded\", init) : init();\r\n})();\r\n<\/template>\r\n\r\n<!-- WP-sicherer Template-Loader: liest Tooltip- und Wizard-Template, macht wptexturize-Schaeden im JS rueckgaengig (Gedankenstrich, Ellipse, krumme Quotes, NBSP) und fuehrt es per new Function aus. Der Loader selbst enthaelt KEIN \" - \" (Leerzeichen-Minus-Leerzeichen) und ist daher texturize-fest. -->\r\n<script>\r\n(function () {\r\n  if (window.__AVD_TPL_REPAIR_LOADED__) return;\r\n  window.__AVD_TPL_REPAIR_LOADED__ = true;\r\n  var ids = [\"avd-tip-tpl\", \"avd-wiz-tpl\"];\r\n  for (var i = 0; i < ids.length; i++) {\r\n    var t = document.getElementById(ids[i]);\r\n    if (!t) continue;\r\n    var code = (t.content ? t.content.textContent : t.textContent); try { new Function(code); } catch (avdEmbTex) { code = code.replace(\/[\u2013\u2014]\/g,\"-\").replace(\/\u2026\/g,\"...\").replace(\/[\u2018\u2019]\/g,\"'\").replace(\/[\u201c\u201d]\/g,'\"').replace(\/\\u00A0\/g,\" \"); }\r\n    code = code\r\n      .replace(\/[\u2013\u2014]\/g, \"-\")\r\n      .replace(\/\u2026\/g, \"...\")\r\n      .replace(\/[\u2018\u2019]\/g, \"'\")\r\n      .replace(\/[\u201c\u201d]\/g, '\"')\r\n      .replace(\/ \/g, \" \");\r\n    try { new Function(code)(); } catch (e) { console.error(\"[AVD-Tool] Template-Loader \" + ids[i] + \":\", e); }\r\n  }\r\n})();\r\n<\/script>\r\n\r\n<!-- AVD Leerfeld-Guard: leere Pflichtfelder blockieren Berechnung\/Weiter still (keine Warnung); Bereichs-Checks fuer nicht-leere Werte bleiben. WP-safe, idempotent. -->\r\n<style id=\"avd-reqguard-css\">\r\n.avdemb-t18pl .tool-wrapper .avd-reqwarn{display:none;margin-top:4px;font-size:12px;line-height:1.35;color:#b91c1c;max-width:100%;overflow-wrap:break-word;word-break:break-word;}\r\n.avdemb-t18pl .tool-wrapper .avd-reqwarn.avd-show{display:block;}\r\n.avdemb-t18pl .tool-wrapper .avd-field-invalid{border-color:#b91c1c !important;}\r\n<\/style>\r\n<script id=\"avd-reqguard-js\">\r\n(function(){\r\n  if(window.__AVD_REQGUARD__)return; window.__AVD_REQGUARD__=true;\r\n  var REQ=[\"alter\",\"einzahlung\",\"brutto-jahr\"];\r\n  var MSG={\"alter\":\"Bitte dein Alter eingeben\",\"brutto\":\"Bitte dein Bruttoeinkommen eingeben\",\"brutto-jahr\":\"Bitte dein Bruttoeinkommen eingeben\",\"einzahlung\":\"Bitte einen Sparbetrag eingeben\",\"rentenpunkte\":\"Bitte deine Rentenpunkte eingeben\"};\r\n  var ANCHOR={\"einzahlung\":\"einzahlung-max\"};\r\n  function byId(id){return document.getElementById(id);}\r\n  function isEmpty(el){ if(!el)return false; var v=(el.value==null?\"\":String(el.value)); return v.replace(\/[^0-9]\/g,\"\").length===0; }\r\n  function visible(el){ return !!(el && el.offsetParent!==null); }\r\n  function spanFor(id){\r\n    var sid=\"avd-warn-\"+id; var sp=byId(sid); if(sp)return sp;\r\n    var el=byId(id); if(!el)return null;\r\n    sp=document.createElement(\"span\"); sp.id=sid; sp.className=\"avd-reqwarn\"; sp.setAttribute(\"role\",\"alert\"); sp.textContent=(MSG[id]||\"Bitte dieses Feld ausf\\u00fcllen\");\r\n    var anchor=null;\r\n    if(ANCHOR[id]) anchor=byId(ANCHOR[id]);\r\n    if(!anchor && el.closest) anchor=el.closest(\".input-wrap\");\r\n    if(!anchor) anchor=el.parentElement;\r\n    if(anchor && anchor.parentNode){ anchor.parentNode.insertBefore(sp, anchor.nextSibling); }\r\n    else if(el.parentNode){ el.parentNode.insertBefore(sp, el.nextSibling); }\r\n    return sp;\r\n  }\r\n  function fieldBad(id){ var el=byId(id); return !!(el && visible(el) && isEmpty(el)); }\r\n  function mark(id){ var el=byId(id); if(!el)return; var bad=fieldBad(id); var sp=spanFor(id); el.classList.toggle(\"avd-field-invalid\", bad); if(sp) sp.classList.toggle(\"avd-show\", bad); }\r\n  function anyEmpty(){ for(var i=0;i<REQ.length;i++){ if(fieldBad(REQ[i])) return true; } return false; }\r\n  function flagAll(){ for(var i=0;i<REQ.length;i++) mark(REQ[i]); }\r\n  function wire(){ for(var i=0;i<REQ.length;i++){ (function(id){ var el=byId(id); if(!el)return; var f=function(){ mark(id); }; el.addEventListener(\"input\",f); el.addEventListener(\"blur\",f); })(REQ[i]); } }\r\n  document.addEventListener(\"click\",function(e){\r\n    var t=e.target; if(!t||!t.closest)return;\r\n    if(!t.closest(\".tool-wrapper\"))return;\r\n    if(!t.closest(\"#berechnenBtn,#wiz-next,[onclick*=\\\"wizNext\\\"],[onclick*=\\\"wizGoNext\\\"],[onclick*=\\\"goNext\\\"],[onclick*=\\\"berechne\\\"],[onclick*=\\\"avdStartBerechnung\\\"],[onclick*=\\\"startBerechnung\\\"]\"))return;\r\n    if(anyEmpty()){ flagAll(); e.preventDefault(); e.stopImmediatePropagation(); e.stopPropagation(); }\r\n  },true);\r\n  if(document.readyState===\"loading\") document.addEventListener(\"DOMContentLoaded\", wire); else wire();\r\n})();\r\n<\/script>\r\n<!-- AVD BFSG-A11y-Modul: Labels(\u2460)+Radiogroups\/Tastatur(\u2461)+Tooltip-Fokus(\u2462)+Chart-Zoom-Dialog(\u2464). WP-safe, .tool-wrapper-scoped, idempotent. -->\r\n<style id=\"avd-a11y-css\">\r\n.avdemb-t18pl .tool-wrapper .tooltip-icon:focus .tooltip-text,\r\n.avdemb-t18pl .tool-wrapper .tooltip-icon:focus-within .tooltip-text,\r\n.avdemb-t18pl .tool-wrapper .tip:focus .tip-text,\r\n.avdemb-t18pl .tool-wrapper .tip:focus-within .tip-text,\r\n.avdemb-t18pl .tool-wrapper .tooltip-wrap:focus-within .tooltip-img{visibility:visible!important;opacity:1!important;}\r\n.avdemb-t18pl .tool-wrapper [data-a11y-focus]:focus-visible,\r\n.avdemb-t18pl .tool-wrapper .avd7-tap-wrap:focus-visible,\r\n.avdemb-t18pl .tool-wrapper .chart-tap-wrapper:focus-visible{outline:3px solid #2691ff!important;outline-offset:2px;border-radius:8px;}\r\n<\/style>\r\n<script id=\"avd-a11y-js\">\r\n(function(){\r\n  if(window.__AVD_A11Y__)return; window.__AVD_A11Y__=true;\r\n  function ready(fn){ if(document.readyState===\"loading\")document.addEventListener(\"DOMContentLoaded\",fn); else fn(); }\r\n  function cssEsc(s){ return (window.CSS&&CSS.escape)?CSS.escape(s):String(s).replace(\/[^a-zA-Z0-9_-]\/g,\"\\\\$&\"); }\r\n  ready(function(){\r\n    var root=document.querySelector(\".tool-wrapper\"); if(!root) return;   \/\/ Nie auf die ganze WP-Seite ausweichen (kein document.body-Fallback)\r\n    var ACCENT=\"rgb(38, 145, 255)\";\r\n\r\n    \/\/ ---------- \u2462 TOOLTIPS: fokussierbar + benannt, Fokus zeigt Inhalt (CSS), Esc schlie\u00dft ----------\r\n    \/\/ Kein role=button (Enter\/Space l\u00f6sen keine Aktion aus, w\u00fcrde SR-Nutzer irref\u00fchren): fokussierbar + aria-label tr\u00e4gt den Hinweis; CSS zeigt bei Fokus.\r\n    root.querySelectorAll(\".tooltip-icon,.tip,.tooltip-wrap\").forEach(function(t){\r\n      if(t.getAttribute(\"tabindex\")===null) t.setAttribute(\"tabindex\",\"0\");\r\n      var rl=t.getAttribute(\"role\"); if(rl===\"img\"||rl===\"button\") t.removeAttribute(\"role\"); \/\/ irref\u00fchrende Rolle f\u00fcr ein fokussierbares Hinweis-Element entfernen\r\n      t.setAttribute(\"data-a11y-focus\",\"\");\r\n      if(!t.getAttribute(\"aria-label\")){\r\n        var tx=t.querySelector(\".tooltip-text,.tip-text,.tooltip-img-text\");\r\n        t.setAttribute(\"aria-label\", tx ? (\"Hinweis: \"+tx.textContent.replace(\/\\s+\/g,\" \").trim().slice(0,200)) : \"Mehr Informationen\");\r\n      }\r\n      t.addEventListener(\"keydown\",function(e){ if(e.key===\"Escape\") t.blur(); });\r\n    });\r\n\r\n    \/\/ ---------- \u2460 LABELS: fehlenden zug\u00e4nglichen Namen aus sichtbarem Label erg\u00e4nzen ----------\r\n    root.querySelectorAll(\"input,select,textarea\").forEach(function(inp){\r\n      if(inp.type===\"hidden\") return;\r\n      if(inp.closest(\"label\")) return;                                                    \/\/ umschlie\u00dfendes <label> liefert bereits den VOLLEN Namen -> nicht mit gek\u00fcrztem aria-label \u00fcberschreiben (z.B. Consent-Checkboxen)\r\n      if(inp.closest('[aria-hidden=\"true\"]') || inp.getAttribute(\"tabindex\")===\"-1\") return; \/\/ versteckte\/Honeypot-Felder nicht benennen\r\n      if(inp.getAttribute(\"aria-label\")||inp.getAttribute(\"aria-labelledby\")) return;\r\n      if(inp.id && root.querySelector('label[for=\"'+cssEsc(inp.id)+'\"]')) return;\r\n      var name=labelFor(inp);\r\n      if(name) inp.setAttribute(\"aria-label\",name);\r\n    });\r\n\r\n    \/\/ ---------- \u2461 AUSWAHL-GRUPPEN: role=radiogroup\/radio, aria-checked, Roving-Tabindex, Pfeiltasten ----------\r\n    \/\/ sel=Initial-\/Backstop-Erkennung; observe=true nur f\u00fcr KLASSEN-basierte Gruppen (sofort & zuverl\u00e4ssig; z.B. Slider \u00e4ndert Kachel).\r\n    \/\/ Modus-Buttons f\u00e4rben ihren Rand VERZ\u00d6GERT (getComputedStyle w\u00e4re racy) -> rein klickgesteuert, kein Observer.\r\n    var DEFS=[\r\n      {q:'[id^=\"optBtn-\"]', sel:function(b){ return getComputedStyle(b).borderTopColor===ACCENT; }, label:\"Rechenmethode\", observe:false},\r\n      {q:\".ra-kachel\",      sel:function(b){ return b.classList.contains(\"ra-sel\"); },              label:\"Auswahl\",        observe:true},\r\n      {q:\".wiz-tile\",       sel:function(b){ return b.classList.contains(\"sel\"); },                 label:\"Auswahl\",        observe:true},\r\n      {q:\".kinder-btn\",     sel:function(b){ return b.classList.contains(\"active\"); },              label:\"Anzahl Kinder\",  observe:true},\r\n      {q:'[id^=\"kBtn\"]',    sel:function(b){ return b.classList.contains(\"kinder-active\"); },       label:\"Anzahl Kinder\",  observe:true}, \/\/ Tool 6.6-Variante der Kinder-Buttons\r\n      {q:\".netto-pt\",       sel:function(b){ return b.classList.contains(\"sel\"); },                 label:\"Einkommensart Partner\", observe:true}, \/\/ Tool 5.x Partner-Typ (vorher nicht angesagt)\r\n      {q:\".toggle-btn\",     sel:function(b){ return b.classList.contains(\"active\"); },              label:\"Auswahl\",        observe:true}\r\n    ];\r\n    DEFS.forEach(function(d){\r\n      var all=Array.prototype.slice.call(root.querySelectorAll(d.q));\r\n      if(!all.length) return;\r\n      var groups=[];\r\n      all.forEach(function(b){ var p=b.parentElement; var g=null; for(var i=0;i<groups.length;i++){ if(groups[i].p===p){g=groups[i];break;} } if(!g){g={p:p,m:[]};groups.push(g);} g.m.push(b); });\r\n      groups.forEach(function(g){\r\n        if(g.m.length<2) return;\r\n        var parent=g.p, members=g.m;\r\n        if(parent.getAttribute(\"role\")===\"radiogroup\") return; \/\/ idempotent\r\n        parent.setAttribute(\"role\",\"radiogroup\");\r\n        if(!parent.getAttribute(\"aria-label\")) parent.setAttribute(\"aria-label\",d.label);\r\n        members.forEach(function(b){ b.setAttribute(\"role\",\"radio\"); b.setAttribute(\"data-a11y-focus\",\"\"); });\r\n        function setChecked(idx){ members.forEach(function(b,i){ b.setAttribute(\"aria-checked\", i===idx?\"true\":\"false\"); b.setAttribute(\"tabindex\", i===idx?\"0\":\"-1\"); }); }\r\n        function detect(){ var idx=-1; members.forEach(function(b,i){ try{ if(d.sel(b)) idx=i; }catch(e){} }); return idx; }\r\n        var di=detect(); setChecked(di<0?0:di);\r\n        \/\/ Klick auf ein Mitglied (Maus ODER via Pfeiltaste ausgel\u00f6st) = dieses Mitglied ausgew\u00e4hlt (deterministisch, ohne Tool-State zu lesen)\r\n        members.forEach(function(b,i){ b.addEventListener(\"click\",function(){ setChecked(i); }); });\r\n        \/\/ Backstop nur f\u00fcr Klassen-Gruppen (z.B. Slider \u00e4ndert Auswahl ohne Klick) \u2013 Klasse ist sofort\/zuverl\u00e4ssig lesbar\r\n        if(d.observe){ var mo=new MutationObserver(function(){ var idx=detect(); if(idx>=0) setChecked(idx); }); members.forEach(function(b){ mo.observe(b,{attributes:true,attributeFilter:[\"class\"]}); }); }\r\n        parent.addEventListener(\"keydown\",function(e){\r\n          var i=members.indexOf(document.activeElement); if(i<0) return;\r\n          var n=-1;\r\n          if(e.key===\"ArrowRight\"||e.key===\"ArrowDown\") n=(i+1)%members.length;\r\n          else if(e.key===\"ArrowLeft\"||e.key===\"ArrowUp\") n=(i-1+members.length)%members.length;\r\n          else return;\r\n          e.preventDefault(); members[n].focus(); members[n].click(); \/\/ click -> setChecked(n)\r\n        });\r\n      });\r\n    });\r\n\r\n    \/\/ ---------- \u2464 CHART-ZOOM: Fl\u00e4che als Button + Dialog-Fokusf\u00fchrung ----------\r\n    root.querySelectorAll(\".avd7-tap-wrap,.chart-tap-wrapper\").forEach(function(w){\r\n      if(w.getAttribute(\"tabindex\")===null) w.setAttribute(\"tabindex\",\"0\");\r\n      w.setAttribute(\"role\",\"button\");\r\n      w.setAttribute(\"aria-haspopup\",\"dialog\");\r\n      if(!w.getAttribute(\"aria-label\")) w.setAttribute(\"aria-label\",\"Diagramm vergr\u00f6\u00dfern\");\r\n      w.addEventListener(\"keydown\",function(e){ if(e.key===\"Enter\"||e.key===\" \"){ e.preventDefault(); w.click(); } });\r\n    });\r\n    var lastTrigger=null;\r\n    document.addEventListener(\"click\",function(e){ var t=e.target&&e.target.closest?e.target.closest(\".avd7-tap-wrap,.chart-tap-wrapper\"):null; if(t) lastTrigger=t; },true);\r\n    \/\/ Chart-Vollbild-Overlay liegt AUSSERHALB .tool-wrapper (an <body>) -> document-weit, aber NUR \u00fcber tool-eigene IDs (7.6: #avd7-overlay; 1.8\/1.9\/6.6: #chart-overlay). KEINE generischen .chart-* Klassen (die fremde WP-Seiten-Elemente treffen k\u00f6nnten).\r\n    document.querySelectorAll('#avd7-overlay,.avd7-overlay,#chart-overlay').forEach(setupDialog);\r\n    function setupDialog(ov){\r\n      if(!ov||ov.__a11yDlg) return; ov.__a11yDlg=true;\r\n      ov.setAttribute(\"role\",\"dialog\"); ov.setAttribute(\"aria-modal\",\"true\");\r\n      function foc(){ return Array.prototype.slice.call(ov.querySelectorAll('button,a[href],[tabindex]:not([tabindex=\"-1\"])')).filter(function(el){return el.offsetParent!==null;}); }\r\n      function isOpen(){ return ov.classList.contains(\"open\") || (ov.offsetParent!==null && getComputedStyle(ov).visibility!==\"hidden\" && parseFloat(getComputedStyle(ov).opacity||\"1\")>0.01); }\r\n      var mo=new MutationObserver(function(){\r\n        var o=isOpen();\r\n        if(o&&!ov.__open){ ov.__open=true;\r\n          var c=ov.querySelector('.avd7-close,.chart-close,.chart-overlay-close,[aria-label*=\"chlie\"]')||foc()[0];\r\n          if(c){ [30,160,340].forEach(function(ms){ setTimeout(function(){ if(ov.__open && document.activeElement!==c){ try{c.focus();}catch(e){} } },ms); }); } }\r\n        else if(!o&&ov.__open){ ov.__open=false; if(lastTrigger) setTimeout(function(){try{lastTrigger.focus();}catch(e){}},40); }\r\n      });\r\n      mo.observe(ov,{attributes:true,attributeFilter:[\"class\",\"style\"]});\r\n      ov.addEventListener(\"keydown\",function(e){\r\n        if(e.key===\"Escape\"){ var c=ov.querySelector(\".avd7-close,.chart-close\"); if(c) c.click(); }\r\n        else if(e.key===\"Tab\"){ var f=foc(); if(!f.length) return; var first=f[0],last=f[f.length-1];\r\n          if(e.shiftKey&&document.activeElement===first){ e.preventDefault(); last.focus(); }\r\n          else if(!e.shiftKey&&document.activeElement===last){ e.preventDefault(); first.focus(); } }\r\n      });\r\n    }\r\n\r\n    \/\/ ---------- Helpers ----------\r\n    function labelFor(inp){\r\n      var lab=inp.closest(\"label\"); if(lab) return clean(lab);\r\n      var field=inp.closest(\".field\"); if(field){ var l=field.querySelector(\"label,.wiz-sub\"); if(l) return clean(l); }\r\n      var wrap=inp.closest(\".input-wrap\")||inp; var pv=wrap.previousElementSibling;\r\n      while(pv){ if(\/^(LABEL|DIV|SPAN|P)$\/.test(pv.tagName)){ var c=clean(pv); if(c) return c; } pv=pv.previousElementSibling; }\r\n      var step=inp.closest(\".wiz-step,.fields-row,.field-row\"); if(step){ var s=step.querySelector(\"label,.wiz-sub,.wiz-q\"); if(s) return clean(s); }\r\n      return inp.getAttribute(\"placeholder\")||\"\";\r\n    }\r\n    function clean(el){ var c=el.cloneNode(true); c.querySelectorAll(\".tooltip-icon,.tip,.tooltip-wrap,.tooltip-text,.tip-text\").forEach(function(x){x.remove();}); return c.textContent.replace(\/\\s+\/g,\" \").trim().slice(0,120); }\r\n  });\r\n})();\r\n<\/script>\r\n\r\n\r\n<!-- AVD Hinweis-Aufklapp-Modul (avd-hin): \"Hinweise\"-Disclaimerbox als natives Aufklappfeld (details\/summary, kein JS, collapsed by default). WP-safe, .tool-wrapper-scoped, idempotent. -->\r\n<style id=\"avd-hin-css\">\r\n.avdemb-t18pl .tool-wrapper details.avd-hin{display:block;margin:0;padding:0;border:0;background:transparent;}\r\n.avdemb-t18pl .tool-wrapper .avd-hin-sum{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin:0;padding:4px 0;border:0;background:transparent;cursor:pointer;list-style:none;user-select:none;-webkit-user-select:none;-webkit-tap-highlight-color:transparent;scroll-margin-top:64px;}\r\n.avdemb-t18pl .tool-wrapper .avd-hin-sum::-webkit-details-marker{display:none;}\r\n.avdemb-t18pl .tool-wrapper .avd-hin-sum::marker{content:none;}\r\n.avdemb-t18pl .tool-wrapper .avd-hin-sum::before,.avdemb-t18pl .tool-wrapper .avd-hin-sum::after{content:none;}\r\n.avdemb-t18pl .tool-wrapper .avd-hin-sum:focus-visible{outline:3px solid #093967;outline-offset:2px;border-radius:6px;}\r\n.avdemb-t18pl .tool-wrapper .avd-hin-chev{margin-left:auto;color:#093967;font-size:13px;line-height:1;transition:transform .2s ease;}\r\n.avdemb-t18pl .tool-wrapper details.avd-hin[open] .avd-hin-chev{transform:rotate(180deg);}\r\n.avdemb-t18pl .tool-wrapper .avd-hin-hint{display:block;flex-basis:100%;font-size:11px;font-weight:400;color:#4a5563;user-select:text;-webkit-user-select:text;}\r\n@media (prefers-reduced-motion:reduce){.avdemb-t18pl .tool-wrapper .avd-hin-chev{transition:none;}}\r\n\/* Print: zugeklappte Hinweise im Ausdruck vollstaendig ausgeben (Browser mit ::details-content; aeltere drucken nur die Summary-Zeile) *\/\r\n@media print{.avdemb-t18pl .tool-wrapper details.avd-hin::details-content{content-visibility:visible;}}\r\n<\/style>\r\n\r\n<\/div>\r\n\n<h2>Vier Wege f\u00fcr deinen bestehenden Vertrag<\/h2>\n<p>K\u00fcndigen ist keiner davon. Diese vier M\u00f6glichkeiten hast du.<\/p>\n<h3>Weg 1: Vertrag ruhen lassen<\/h3>\n<p>Du stellst den Vertrag beitragsfrei. Es flie\u00dfen keine neuen Beitr\u00e4ge und keine neuen Zulagen mehr, das vorhandene Guthaben bleibt investiert, die bisherigen Zulagen bleiben erhalten. Die laufenden Verwaltungskosten sinken in der Regel, verschwinden aber nicht.<\/p>\n<div class=\"highlightbox box box--small-padding box--tiny-margin-y\" style=\"--color-background:#fff4ef;\"><strong class=\"headline headline--h3 headline--small-margin\">\u26a0\ufe0f Wichtig<\/strong><div class=\"box__content\"><p>Beachte dabei: Mit dem Abschluss eines neuen Altersvorsorgevertrags endet der Bestandsschutz des Altvertrags. Die Kombination aus &#8222;Riester ruhen lassen und daneben ein Altersvorsorgedepot er\u00f6ffnen&#8220; ist deshalb nicht automatisch das Beste aus beiden Welten. Kl\u00e4re vorher mit deinem Anbieter, welche Folgen der Neuabschluss f\u00fcr deinen Altvertrag hat.<\/p><\/div><\/div>\n<h3>Weg 2: Beim selben Anbieter in die neue F\u00f6rdersystematik wechseln<\/h3>\n<p>Du beh\u00e4ltst deinen Vertrag und erkl\u00e4rst gegen\u00fcber deinem Anbieter, dass du k\u00fcnftig nach den neuen Regeln gef\u00f6rdert werden m\u00f6chtest. Die Konditionen des Vertrags bleiben sonst unver\u00e4ndert. Das ist der einfachste Weg f\u00fcr alle, deren Vertrag g\u00fcnstig ist und die nur die h\u00f6here Zulage mitnehmen wollen, ohne einen Anbieterwechsel anzusto\u00dfen. Voraussetzung ist, dass der Anbieter das anbietet.<\/p>\n<h3>Weg 3: Guthaben in ein Altersvorsorgedepot \u00fcbertragen<\/h3>\n<p>Du \u00fcbertr\u00e4gst das gesamte Guthaben zu einem neuen Anbieter, etwa von einer Rentenversicherung zu einem Broker mit reinem Depot. Alle bisher erhaltenen Zulagen und Steuervorteile wandern mit, nichts wird zur\u00fcckgefordert. Nach dem Wechsel gilt die neue F\u00f6rdersystematik, und die Kosten sinken auf das Niveau der selbst gew\u00e4hlten ETFs.<\/p>\n<p>Das ist f\u00fcr die meisten Sparer mit teuren Altvertr\u00e4gen die wirtschaftlich beste Wahl, vor allem f\u00fcr Singles und Gutverdiener ohne Kinder, die von den festen Riester-Zulagen ohnehin wenig hatten.<\/p>\n<h3>Weg 4: Alles unver\u00e4ndert weiterlaufen lassen<\/h3>\n<p>Die bisherige F\u00f6rderung mit festen Zulagen und Beitragsgarantie gilt f\u00fcr Bestandsvertr\u00e4ge unver\u00e4ndert weiter. Sinnvoll ist das f\u00fcr eine kleine, aber klar umrissene Gruppe, die weiter unten beschrieben wird.<\/p>\n<h2>Warum eine K\u00fcndigung fast immer der teuerste Weg ist<\/h2>\n<p>Wer seinen Riester-Vertrag k\u00fcndigt, l\u00f6st eine sch\u00e4dliche Verwendung aus. S\u00e4mtliche erhaltenen Zulagen und Steuervorteile sind an den Staat zur\u00fcckzuzahlen. Bei einem Vertrag, der seit 2005 l\u00e4uft, summieren sich allein die Grundzulagen auf rund 3.500 Euro. Dazu kommen m\u00f6gliche Stornokosten des Anbieters.<\/p>\n<p>Es gibt kaum eine Konstellation, in der sich das rechnet. Selbst ein teurer, schlecht laufender Vertrag ist beitragsfrei gestellt besser aufgehoben als gek\u00fcndigt.<\/p>\n<style>\r\n  .tp-review-card {\r\n    width: 100%;\r\n    background: #F4F1EA;\r\n    border-radius: 14px;\r\n    padding: 32px 40px;\r\n    box-sizing: border-box;\r\n    text-align: center;\r\n    margin: 0 0 32px;\r\n    hyphens: none;\r\n    -webkit-hyphens: none;\r\n    -ms-hyphens: none;\r\n    overflow-wrap: normal;\r\n    word-break: normal;\r\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Arial, sans-serif;\r\n  }\r\n\r\n  .tp-stars {\r\n    display: flex;\r\n    justify-content: center;\r\n    gap: 8px;\r\n    margin-bottom: 14px;\r\n  }\r\n\r\n  .tp-stars span {\r\n    display: inline-flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    width: 40px;\r\n    height: 40px;\r\n    background: #52D9A6;\r\n    border-radius: 8px;\r\n    opacity: 0;\r\n    transform: scale(0.4) rotate(-15deg);\r\n    animation: tp-pop 0.45s cubic-bezier(.34,1.56,.64,1) forwards;\r\n  }\r\n\r\n  .tp-stars svg {\r\n    width: 24px;\r\n    height: 24px;\r\n  }\r\n\r\n  .tp-stars span:nth-child(1) { animation-delay: 0.05s; }\r\n  .tp-stars span:nth-child(2) { animation-delay: 0.15s; }\r\n  .tp-stars span:nth-child(3) { animation-delay: 0.25s; }\r\n  .tp-stars span:nth-child(4) { animation-delay: 0.35s; }\r\n  .tp-stars span:nth-child(5) { animation-delay: 0.45s; }\r\n\r\n  @keyframes tp-pop {\r\n    to { opacity: 1; transform: scale(1) rotate(0deg); }\r\n  }\r\n\r\n  @media (prefers-reduced-motion: reduce) {\r\n    .tp-stars span { animation: none; opacity: 1; transform: none; }\r\n  }\r\n\r\n  .tp-heading {\r\n    font-size: 28px;\r\n    line-height: 1.25;\r\n    margin: 0 0 16px;\r\n    color: #10241E;\r\n    font-weight: 800;\r\n  }\r\n\r\n  .tp-body-text {\r\n    font-size: 17px;\r\n    line-height: 1.5;\r\n    margin: 0 auto 24px;\r\n    max-width: 520px;\r\n    color: #10241E;\r\n  }\r\n\r\n  .tp-body-text strong {\r\n    font-weight: 700;\r\n  }\r\n\r\n  .tp-cta {\r\n    display: inline-block;\r\n    background: #1F4176;\r\n    color: #fff;\r\n    text-decoration: none;\r\n    font-weight: 700;\r\n    font-size: 17px;\r\n    padding: 14px 34px;\r\n    border-radius: 10px;\r\n    transition: background 0.15s ease, transform 0.1s ease;\r\n  }\r\n\r\n  .tp-cta:hover {\r\n    background: #163258;\r\n    transform: translateY(-1px);\r\n  }\r\n\r\n  .tp-cta:active {\r\n    transform: translateY(0);\r\n  }\r\n\r\n  .tp-thanks {\r\n    margin: 16px 0 0;\r\n    font-size: 14px;\r\n    color: rgba(16, 36, 30, 0.6);\r\n  }\r\n\r\n  @media (max-width: 480px) {\r\n    .tp-review-card {\r\n      padding: 28px 24px;\r\n    }\r\n\r\n    .tp-heading {\r\n      font-size: 23px;\r\n    }\r\n\r\n    .tp-body-text {\r\n      font-size: 16px;\r\n    }\r\n\r\n    .tp-cta {\r\n      font-size: 16px;\r\n      padding: 14px 24px;\r\n      width: 100%;\r\n      box-sizing: border-box;\r\n    }\r\n  }\r\n<\/style>\r\n\r\n<div class=\"tp-review-card\">\r\n  <div class=\"tp-stars\" aria-hidden=\"true\">\r\n    <span><svg viewBox=\"0 0 24 24\"><path fill=\"#FFC94D\" d=\"M12 .9l3.2 6.9 7.5.9-5.6 5.2 1.5 7.5L12 17.9 5.4 21.4l1.5-7.5L1.3 8.7l7.5-.9z\"\/><\/svg><\/span>\r\n    <span><svg viewBox=\"0 0 24 24\"><path fill=\"#FFC94D\" d=\"M12 .9l3.2 6.9 7.5.9-5.6 5.2 1.5 7.5L12 17.9 5.4 21.4l1.5-7.5L1.3 8.7l7.5-.9z\"\/><\/svg><\/span>\r\n    <span><svg viewBox=\"0 0 24 24\"><path fill=\"#FFC94D\" d=\"M12 .9l3.2 6.9 7.5.9-5.6 5.2 1.5 7.5L12 17.9 5.4 21.4l1.5-7.5L1.3 8.7l7.5-.9z\"\/><\/svg><\/span>\r\n    <span><svg viewBox=\"0 0 24 24\"><path fill=\"#FFC94D\" d=\"M12 .9l3.2 6.9 7.5.9-5.6 5.2 1.5 7.5L12 17.9 5.4 21.4l1.5-7.5L1.3 8.7l7.5-.9z\"\/><\/svg><\/span>\r\n    <span><svg viewBox=\"0 0 24 24\"><path fill=\"#FFC94D\" d=\"M12 .9l3.2 6.9 7.5.9-5.6 5.2 1.5 7.5L12 17.9 5.4 21.4l1.5-7.5L1.3 8.7l7.5-.9z\"\/><\/svg><\/span>\r\n  <\/div>\r\n\r\n  <p class=\"tp-heading\">Wir brauchen deine Sterne!<\/p>\r\n\r\n  <p class=\"tp-body-text\">\r\n    Dir gefallen unsere Texte und Tools? Dann lass es uns und die Community wissen. Eine Bewertung bei <strong>Trustpilot<\/strong> dauert keine zwei Minuten \u2013 hilft uns aber enorm.\r\n  <\/p>\r\n\r\n  <a class=\"tp-cta\" href=\"https:\/\/de.trustpilot.com\/evaluate\/finanzen.net\" target=\"_blank\" rel=\"noopener\">\r\n    finanzen.net bei Trustpilot bewerten\r\n  <\/a>\r\n\r\n  <p class=\"tp-thanks\">Vielen Dank f\u00fcr deine Hilfe \ud83d\ude4f<\/p>\r\n<\/div>\n<h2>Was ein Riester-Vertrag gekostet hat<\/h2>\n<p>Ein Vergleich mit Zahlen, der zeigt, worum es geht. Wer 2002 begonnen hat, monatlich 100 Euro einzuzahlen, steht nach 25 Jahren bei rund 47.000 Euro. H\u00e4tte es das Altersvorsorgedepot damals schon gegeben, mit demselben Eigenbeitrag, den heutigen Zulagen und einem breit gestreuten Aktien-ETF, w\u00e4ren daraus rund 90.000 Euro geworden.<\/p>\n<div class=\"sc-table table-container table-container--small-margin \"><table class=\"table sc-table table--aligned-left\" style=\"min-width:880px\"><thead><tr><th>Laufzeit<\/th><th>Riester<\/th><th>Altersvorsorgedepot<\/th><th>Differenz<\/th><\/tr><\/thead><tbody><tr><td>10 Jahre (Start 2015)<\/td><td>rund 15.600 \u20ac<\/td><td>rund 22.000 \u20ac<\/td><td>rund 6.400 \u20ac<\/td><\/tr><tr><td>15 Jahre (Start 2010)<\/td><td>rund 24.900 \u20ac<\/td><td>rund 38.600 \u20ac<\/td><td>rund 13.700 \u20ac<\/td><\/tr><tr><td>25 Jahre (Start 2002)<\/td><td>rund 46.800 \u20ac<\/td><td>rund 89.700 \u20ac<\/td><td>rund 42.900 \u20ac<\/td><\/tr><\/thead><\/tbody><\/table><\/div>\n<p><small><strong>Annahmen:<\/strong> 1.200 Euro Eigenbeitrag im Jahr, Einzahlung zu Jahresbeginn. Riester mit 175 Euro Grundzulage und 2,3 Prozent Rendite nach Kosten, Altersvorsorgedepot mit 390 Euro Grundzulage und 5,8 Prozent Rendite nach Kosten, also 6 Prozent Bruttorendite abz\u00fcglich 0,2 Prozent Depotkosten. Ohne Kinderzulagen, ohne Steuereffekte. Eine Modellrechnung, keine historische Wertentwicklung.<\/small><\/p>\n<p>Die Differenz hat drei Ursachen. Erstens die Produktkosten von typischerweise 1,5 bis 2,5 Prozent pro Jahr. Zweitens die Beitragsgarantie, die Anbieter in der Niedrigzinsphase in Anleihen zwang und die Aktienquote begrenzte. Drittens die niedrigere Zulage. Wie stark die drei Ursachen jeweils wirken, zeigt das Rechenbeispiel weiter unten. So viel vorweg: Die Zulage ist der kleinste der drei Hebel.<\/p>\n<h2>Riester und Altersvorsorgedepot im Vergleich<\/h2>\n<p><img decoding=\"async\" class=\"alignnone wp-image-36998 size-full\" src=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/03\/riester-rente-alternative-infografik.png\" alt=\"Vergleich Riester-Rente und Altersvorsorgedepot\" width=\"1424\" srcset=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/03\/riester-rente-alternative-infografik.png 1424w, https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/03\/riester-rente-alternative-infografik-300x158.png 300w, https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/03\/riester-rente-alternative-infografik-1024x541.png 1024w, https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/03\/riester-rente-alternative-infografik-768x406.png 768w\" sizes=\"(max-width: 1424px) 100vw, 1424px\" \/><\/p>\n<div class=\"sc-table table-container table-container--small-margin \"><table class=\"table sc-table table--aligned-left\" style=\"min-width:880px\"><thead><tr><th>Merkmal<\/th><th>Riester-Rente<\/th><th>Altersvorsorgedepot ab 2027<\/th><\/tr><\/thead><tbody><tr><td>Grundzulage<\/td><td>Fest 175 \u20ac im Jahr<\/td><td>Beitragsproportional, bis zu 540 \u20ac<\/td><\/tr><tr><td>Mindesteigenbeitrag<\/td><td>4 % des Vorjahresbruttos abz\u00fcglich Zulagen, mindestens 60 \u20ac<\/td><td>Fest 120 \u20ac im Jahr<\/td><\/tr><tr><td>Kinderzulage<\/td><td>185 \u20ac oder 300 \u20ac, gek\u00fcrzt bei zu kleinem Eigenbeitrag<\/td><td>Bis zu 300 \u20ac, voll ab 300 \u20ac Eigenbeitrag<\/td><\/tr><tr><td>Sonderausgabenabzug<\/td><td>Bis 2.100 \u20ac je Person<\/td><td>Eigenbeitrag bis 1.800 \u20ac zuz\u00fcglich Zulageanspruch<\/td><\/tr><tr><td>Typische Kosten<\/td><td>1,5 bis 2,5 % pro Jahr<\/td><td>0,1 bis 0,2 % bei selbst gew\u00e4hltem ETF, h\u00f6chstens 1,0 % beim Standarddepot<\/td><\/tr><tr><td>Beitragsgarantie<\/td><td>100 % verpflichtend<\/td><td>Keine, optional 80 oder 100 % im Garantieprodukt<\/td><\/tr><tr><td>Aktienquote<\/td><td>Durch die Garantie begrenzt<\/td><td>Bis zu 100 %<\/td><\/tr><tr><td>Besteuerung Ansparphase<\/td><td>Steuerfrei<\/td><td>Steuerfrei<\/td><\/tr><tr><td>Selbstst\u00e4ndige<\/td><td>Nur bei Rentenversicherungspflicht oder mittelbar<\/td><td>Unmittelbar f\u00f6rderberechtigt<\/td><\/tr><tr><td>Auszahlung<\/td><td>Mindestens 70 % m\u00fcssen verrentet werden<\/td><td>Auszahlungsplan oder Leibrente frei w\u00e4hlbar<\/td><\/tr><tr><td>Anbieterwechsel<\/td><td>M\u00f6glich, Kosten je nach Vertrag<\/td><td>Abgebender Anbieter nach 5 Jahren kostenfrei, aufnehmender h\u00f6chstens 150 \u20ac<\/td><\/tr><\/thead><\/tbody><\/table><\/div>\n<p>In der Ansparphase sind beide Systeme steuerfrei und Umschichtungen in beiden steuerfrei m\u00f6glich. Der Unterschied liegt nicht in der Steuer, sondern darin, dass im Riester-Vertrag wegen der Garantie kaum Gewinne entstanden, die von der Steuerfreiheit h\u00e4tten profitieren k\u00f6nnen.<\/p>\n<h2>Die Vorteile im Detail<\/h2>\n<h3>Die Kosten sinken deutlich<\/h3>\n<p>Das ist der st\u00e4rkste Grund f\u00fcr einen Wechsel. Typische Riester-Produkte kosten 1,5 bis 2,5 Prozent pro Jahr, zusammengesetzt aus Abschluss-, Verwaltungs- und Garantiekosten. Im Altersvorsorgedepot mit selbst gew\u00e4hltem ETF liegen die Kosten bei 0,1 bis 0,2 Prozent. Beim Standardprodukt, das jeder Anbieter f\u00fchren muss, sind die Effektivkosten auf 1,0 Prozent gedeckelt.<\/p>\n<p>Was das ausmacht: 25.000 Euro Guthaben, 20 Jahre Restlaufzeit, 6 Prozent Bruttorendite. Bei 2,0 Prozent Kosten werden daraus rund 54.800 Euro, bei 0,2 Prozent rund 77.200 Euro. Der Unterschied liegt bei rund 22.400 Euro, und zwar allein aus dem Kostensatz, ohne jede weitere \u00c4nderung.<\/p>\n<h3>Die Zulage steigt, ab einem bestimmten Beitrag<\/h3>\n<p>Im alten System gibt es feste 175 Euro Grundzulage, unabh\u00e4ngig von der H\u00f6he der Einzahlung, sofern der Mindesteigenbeitrag erreicht ist. Im neuen System h\u00e4ngt die Zulage direkt am Eigenbeitrag.<\/p>\n<div class=\"sc-table table-container table-container--small-margin \"><table class=\"table table--aligned-left\" style=\"min-width:880px\"><thead><tr><th>Eigenbeitrag pro Jahr<\/th><th>Grundzulage Riester<\/th><th>Grundzulage Altersvorsorgedepot<\/th><\/tr><\/thead><tbody><tr><td>300 \u20ac<\/td><td>175 \u20ac<\/td><td>150 \u20ac<\/td><\/tr><tr><td>350 \u20ac<\/td><td>175 \u20ac<\/td><td>175 \u20ac<\/td><\/tr><tr><td>700 \u20ac<\/td><td>175 \u20ac<\/td><td>265 \u20ac<\/td><\/tr><tr><td>1.200 \u20ac<\/td><td>175 \u20ac<\/td><td>390 \u20ac<\/td><\/tr><tr><td>1.800 \u20ac<\/td><td>175 \u20ac<\/td><td>540 \u20ac<\/td><\/tr><\/thead><\/tbody><\/table><\/div>\n<p>Der Kipppunkt liegt bei 350 Euro im Jahr, also rund 29 Euro im Monat. Wer weniger spart, bekommt im alten System mehr Grundzulage. Wer mehr spart, im neuen.<\/p>\n<p>Beim Sonderausgabenabzug ist das Bild \u00e4hnlich. Riester erlaubt bis zu 2.100 Euro je Person. Im Altersvorsorgedepot sind es 1.800 Euro Eigenbeitrag zuz\u00fcglich Zulageanspruch, ohne Kinder also bis zu 2.340 Euro, mit zwei Kindern bis zu 2.940 Euro.<\/p>\n<h3>Volle Aktienquote statt Garantie<\/h3>\n<p>Die verpflichtende Beitragsgarantie war der folgenreichste Konstruktionsfehler. Anbieter mussten zusichern, dass zum Rentenbeginn mindestens die eingezahlten Beitr\u00e4ge zur Verf\u00fcgung stehen. In der Niedrigzinsphase bedeutete das, einen Gro\u00dfteil des Kapitals in niedrig verzinste Anlagen zu stecken. An der Entwicklung der Aktienm\u00e4rkte nahmen Riester-Sparer entsprechend wenig teil.<\/p>\n<p>Im Altersvorsorgedepot gibt es keine Garantiepflicht. Bis zu 100 Prozent Aktienquote sind m\u00f6glich. Wer Sicherheit will, kann freiwillig ein Garantieprodukt mit 80 oder 100 Prozent Beitragserhalt w\u00e4hlen. Es ist eine Wahl, kein Zwang.<\/p>\n<h3>Steuerfreie Ansparphase, die diesmal etwas bringt<\/h3>\n<p>Im Altersvorsorgedepot fallen in der Ansparphase keine Steuern an: keine Abgeltungsteuer auf Kursgewinne, keine Vorabpauschale, keine Steuer beim Umschichten zwischen Fonds. Wer f\u00fcnf Jahre vor der Rente von Aktien in Anleihen wechselt, zahlt darauf keinen Cent.<\/p>\n<p>Diesen Vorteil bot der Riester-Vertrag rechtlich ebenfalls. Er lief nur ins Leere, weil das Geld \u00fcberwiegend in garantiegebundenen Anlagen steckte und kaum steuerpflichtige Gewinne entstanden. Erst mit voller Aktienquote wird aus der Steuerfreiheit ein echter Renditehebel.<\/p>\n<h3>Alle bisherigen Zulagen bleiben erhalten<\/h3>\n<p>Die h\u00e4ufigste Sorge beim Wechsel ist der Verlust der F\u00f6rderung. Bei einer \u00dcbertragung passiert das nicht. Das komplette Guthaben inklusive aller erhaltenen Zulagen und Steuervorteile wandert ins neue System, es wird nichts zur\u00fcckgefordert.<\/p>\n<p>Ein zus\u00e4tzlicher Schutz steht im Gesetz: Das \u00fcbertragene, bereits gef\u00f6rderte Kapital darf der aufnehmende Anbieter bei der Berechnung seiner Abschluss- und Vertriebskosten nicht ber\u00fccksichtigen. Eine zweite Runde Abschlusskosten auf dasselbe Geld ist damit ausgeschlossen.<\/p>\n<h3>Flexible Auszahlung statt Verrentungspflicht<\/h3>\n<p>Bei Riester m\u00fcssen mindestens 70 Prozent des Guthabens in eine lebenslange Rente flie\u00dfen. Wie viel dabei herauskommt, h\u00e4ngt am Rentenfaktor. Bei einem Faktor von 25 bis 30 ergeben 50.000 Euro Guthaben rund 125 bis 150 Euro monatliche Rente.<\/p>\n<p>Im Altersvorsorgedepot hast du die Wahl zwischen einem Auszahlungsplan, der mindestens bis zum vollendeten 85. Lebensjahr l\u00e4uft, und einer lebenslangen Leibrente. Bis zu 30 Prozent des Kapitals lassen sich zu Beginn auf einen Schlag entnehmen. Beim Auszahlungsplan bleibt das Kapital investiert und ist, soweit noch nicht ausgezahlt, vererbbar.<\/p>\n<h3>Kein Versicherungsmantel<\/h3>\n<p>Viele Riester-Vertr\u00e4ge sind keine Depots, sondern fondsgebundene Rentenversicherungen. Der Versicherungsmantel verursacht Abschluss- und Verwaltungskosten, ohne dass ihnen beim Altersvorsorgedepot ein Nutzen gegen\u00fcbersteht, denn eine Beitragsgarantie gibt es dort ohnehin nicht. Auch Versicherer d\u00fcrfen Altersvorsorgedepots anbieten. Achte in dem Fall auf die ausgewiesenen Effektivkosten, dort wird der Unterschied sichtbar.<\/p>\n<!-- ZERO Ratgeber Newsletter \u2013 WordPress Snippet (Brevo-Script) -->\r\n<!-- Variante: Riester-\u00dcbertrag \u00b7 Volle Content-Breite \u00b7 Einfach in Shortcode-\/Snippet-Plugin einf\u00fcgen -->\r\n\r\n<style>\r\n  .zero-nl {\r\n    --zero-red: #E3002B;\r\n    --zero-red-hover: #c80025;\r\n    --zero-red-glow: rgba(227, 0, 43, 0.18);\r\n    --zero-card: #ffffff;\r\n    --zero-text: #0c0c0d;\r\n    --zero-muted: #6b6974;\r\n    --zero-border: #e2e0e4;\r\n    --zero-error-bg: #ffeded;\r\n    --zero-error-text: #661d1d;\r\n    --zero-error-border: #ff4949;\r\n    --zero-success-bg: #e7faf0;\r\n    --zero-success-text: #085229;\r\n    --zero-success-border: #13ce66;\r\n    --zero-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\r\n\r\n    font-family: var(--zero-font);\r\n    width: 100%;\r\n    margin-bottom: 40px;\r\n    background: #f0f0f0;\r\n    padding: 20px;\r\n    border-radius: 16px;\r\n  }\r\n\r\n  .zero-nl * { box-sizing: border-box; margin: 0; padding: 0; }\r\n\r\n  .zero-nl-card {\r\n    background: var(--zero-card);\r\n    border: 1px solid var(--zero-border);\r\n    border-radius: 12px;\r\n    width: 100%;\r\n    box-shadow: 0 2px 4px rgba(0,0,0,0.07), 0 8px 20px rgba(0,0,0,0.12), 0 16px 40px rgba(0,0,0,0.08);\r\n    overflow: hidden;\r\n  }\r\n\r\n  \/* Banner *\/\r\n  .zero-nl-banner {\r\n    background: #242424;\r\n    padding: 14px 28px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: space-between;\r\n    gap: 12px;\r\n  }\r\n\r\n  .zero-nl-banner-text {\r\n    color: #fff;\r\n    font-size: 15px;\r\n    font-weight: 700;\r\n    letter-spacing: 0.04em;\r\n    text-transform: uppercase;\r\n    white-space: nowrap;\r\n  }\r\n\r\n  .zero-nl-banner img {\r\n    height: 32px;\r\n    width: auto;\r\n    flex-shrink: 0;\r\n    display: block;\r\n  }\r\n\r\n  \/* Body \u2013 zweispaltig auf Desktop *\/\r\n  .zero-nl-body {\r\n    padding: 28px;\r\n    display: grid;\r\n    grid-template-columns: 1fr 1fr;\r\n    gap: 8px 36px;\r\n    align-items: start;\r\n  }\r\n\r\n  .zero-nl-left { grid-column: 1; }\r\n  .zero-nl-right { grid-column: 2; }\r\n\r\n  .zero-nl-title {\r\n    font-size: 26px;\r\n    font-weight: 800;\r\n    color: var(--zero-text);\r\n    line-height: 1.35;\r\n    margin-bottom: 6px;\r\n  }\r\n\r\n  .zero-nl-title em {\r\n    font-style: normal;\r\n    color: var(--zero-red);\r\n  }\r\n\r\n  .zero-nl-subtitle {\r\n    font-size: 13px;\r\n    color: var(--zero-muted);\r\n    line-height: 1.55;\r\n  }\r\n\r\n  \/* Brevo-Meldungen *\/\r\n  .zero-nl .sib-form-message-panel {\r\n    display: none;\r\n    padding: 10px 14px !important;\r\n    border-radius: 8px !important;\r\n    font-size: 13px !important;\r\n    line-height: 1.5 !important;\r\n    margin-bottom: 12px !important;\r\n    font-family: var(--zero-font) !important;\r\n    max-width: none !important;\r\n    text-align: center !important;\r\n  }\r\n\r\n  .zero-nl #error-message {\r\n    background: var(--zero-error-bg) !important;\r\n    color: var(--zero-error-text) !important;\r\n    border: 1px solid var(--zero-error-border) !important;\r\n  }\r\n\r\n  .zero-nl #success-message {\r\n    background: var(--zero-success-bg) !important;\r\n    color: var(--zero-success-text) !important;\r\n    border: 1px solid var(--zero-success-border) !important;\r\n  }\r\n\r\n  .zero-nl .sib-form-message-panel__text { justify-content: center; }\r\n  .zero-nl .sib-icon { display: none !important; }\r\n\r\n  .zero-nl #sib-container {\r\n    background: transparent !important;\r\n    border: none !important;\r\n    padding: 0 !important;\r\n    max-width: none !important;\r\n  }\r\n\r\n  \/* Label *\/\r\n  .zero-nl .zero-nl-label {\r\n    display: block;\r\n    font-size: 13px;\r\n    font-weight: 600;\r\n    color: var(--zero-muted);\r\n    margin-bottom: 5px;\r\n  }\r\n\r\n  .zero-nl .zero-nl-required {\r\n    color: var(--zero-red);\r\n    margin-left: 2px;\r\n  }\r\n\r\n  \/* Input *\/\r\n  .zero-nl .zero-nl-input {\r\n    width: 100%;\r\n    padding: 12px 14px;\r\n    font-size: 14px;\r\n    font-family: var(--zero-font);\r\n    color: var(--zero-text);\r\n    border: 1.5px solid var(--zero-border);\r\n    border-radius: 8px;\r\n    outline: none;\r\n    transition: border-color 0.2s ease, box-shadow 0.2s ease;\r\n    background: #faf9fb;\r\n  }\r\n\r\n  .zero-nl .zero-nl-input::placeholder { color: #b5b3ba; }\r\n  .zero-nl .zero-nl-input:focus {\r\n    border-color: var(--zero-red);\r\n    box-shadow: 0 0 0 3px var(--zero-red-glow);\r\n    background: #fff;\r\n  }\r\n\r\n  \/* Checkboxen *\/\r\n  .zero-nl .zero-nl-checks {\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 5px;\r\n    margin-top: 12px;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check {\r\n    display: flex;\r\n    align-items: flex-start;\r\n    gap: 8px;\r\n    cursor: pointer;\r\n    position: relative;\r\n    padding: 0;\r\n    margin: 0;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check input[type=\"checkbox\"] {\r\n    position: absolute;\r\n    opacity: 0;\r\n    width: 0;\r\n    height: 0;\r\n  }\r\n\r\n  .zero-nl .zero-nl-checkmark {\r\n    flex-shrink: 0;\r\n    width: 17px;\r\n    height: 17px;\r\n    border: 1.5px solid #ccc;\r\n    border-radius: 3px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    transition: all 0.15s ease;\r\n    margin-top: 1px;\r\n    background: #faf9fb;\r\n  }\r\n\r\n  .zero-nl .zero-nl-checkmark svg {\r\n    width: 10px;\r\n    height: 10px;\r\n    opacity: 0;\r\n    transform: scale(0.5);\r\n    transition: all 0.15s ease;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check input:checked + .zero-nl-checkmark {\r\n    background: var(--zero-red);\r\n    border-color: var(--zero-red);\r\n  }\r\n\r\n  .zero-nl .zero-nl-check input:checked + .zero-nl-checkmark svg {\r\n    opacity: 1;\r\n    transform: scale(1);\r\n  }\r\n\r\n  .zero-nl .zero-nl-check-text {\r\n    font-size: 12.5px;\r\n    line-height: 1.4;\r\n    color: var(--zero-text);\r\n  }\r\n\r\n  .zero-nl .zero-nl-check-text a {\r\n    color: var(--zero-red);\r\n    text-decoration: underline;\r\n    text-underline-offset: 2px;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check-text a:hover { text-decoration-thickness: 2px; }\r\n\r\n  .zero-nl .zero-nl-optional {\r\n    font-size: 11px;\r\n    color: var(--zero-muted);\r\n    font-weight: 400;\r\n  }\r\n\r\n  \/* CTA-Button *\/\r\n  .zero-nl .sib-form-block__button {\r\n    display: flex !important;\r\n    align-items: center !important;\r\n    justify-content: center !important;\r\n    gap: 8px !important;\r\n    width: 100% !important;\r\n    padding: 14px 24px !important;\r\n    font-size: 16px !important;\r\n    font-weight: 800 !important;\r\n    font-family: var(--zero-font) !important;\r\n    color: #fff !important;\r\n    background: #e0146a !important;\r\n    border: none !important;\r\n    border-radius: 60px !important;\r\n    cursor: pointer;\r\n    transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;\r\n    margin-top: 16px;\r\n    letter-spacing: 0.01em;\r\n    border-width: 0 !important;\r\n    box-shadow: 0 4px 16px rgba(224,20,106,0.18), 0 1px 3px rgba(0,0,0,0.08) !important;\r\n    line-height: 1.2 !important;\r\n  }\r\n\r\n  .zero-nl .sib-form-block__button:hover {\r\n    background: #c9115d !important;\r\n    box-shadow: 0 6px 24px rgba(224,20,106,0.28), 0 2px 6px rgba(0,0,0,0.1) !important;\r\n    transform: translateY(-1px);\r\n  }\r\n\r\n  .zero-nl .sib-form-block__button:active { transform: translateY(0) scale(0.985); }\r\n\r\n  .zero-nl .sib-hide-loader-icon { display: none; }\r\n\r\n  .zero-nl .entry__error {\r\n    display: block;\r\n    font-size: 12px !important;\r\n    font-family: var(--zero-font) !important;\r\n    color: var(--zero-error-text) !important;\r\n    background: transparent !important;\r\n    border: none !important;\r\n    padding: 3px 0 0 0 !important;\r\n    margin: 0 !important;\r\n    border-radius: 0 !important;\r\n  }\r\n\r\n  .zero-nl .input--hidden { position: absolute; left: -9999px; }\r\n\r\n  .zero-nl-trust {\r\n    font-size: 11px;\r\n    color: #a09da6;\r\n    text-align: center;\r\n    margin-top: 12px;\r\n    line-height: 1.4;\r\n    grid-column: 1 \/ -1;\r\n  }\r\n\r\n  \/* Mobile: einspaltig *\/\r\n  @media (max-width: 600px) {\r\n    .zero-nl {\r\n      padding: 16px;\r\n      border-radius: 12px;\r\n    }\r\n    .zero-nl-body {\r\n      grid-template-columns: 1fr;\r\n      gap: 20px;\r\n      padding: 24px 20px;\r\n    }\r\n    .zero-nl-left, .zero-nl-right { grid-column: 1; }\r\n    .zero-nl-banner {\r\n      padding: 12px 12px 12px 20px;\r\n      gap: 8px;\r\n    }\r\n    .zero-nl-banner-text {\r\n      font-size: 12px;\r\n      min-width: 0;\r\n    }\r\n    .zero-nl-banner img { height: 26px; }\r\n    .zero-nl-title { font-size: 22px; }\r\n    .zero-nl .sib-form-block__button { font-size: 15px !important; padding: 13px 20px !important; }\r\n  }\r\n<\/style>\r\n\r\n<div class=\"zero-nl\">\r\n  <div class=\"zero-nl-card\">\r\n\r\n    <!-- Banner -->\r\n    <div class=\"zero-nl-banner\">\r\n      <span class=\"zero-nl-banner-text\">\u2728 Kostenlos &amp; unverbindlich<\/span>\r\n      <img decoding=\"async\"\r\n        src=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/03\/zero_logo_26_light-1.png\"\r\n        alt=\"finanzen.net zero\"\r\n        loading=\"lazy\"\r\n      \/>\r\n    <\/div>\r\n\r\n    <div class=\"zero-nl-body\">\r\n\r\n      <!-- Linke Spalte: Text -->\r\n      <div class=\"zero-nl-left\">\r\n        <h2 class=\"zero-nl-title\">Riester-Vertrag \u00fcbertragen und bis zu <em>540&nbsp;\u20ac F\u00f6rderung<\/em> sichern.<\/h2>\r\n        <p class=\"zero-nl-subtitle\">Dein Riester-Guthaben kann ab 2027 in ein Altersvorsorgedepot bei unserem Broker finanzen.net ZERO wechseln \u2013 <strong>alle bisherigen Zulagen bleiben erhalten<\/strong>. Melde dich jetzt an, damit du am 1.&nbsp;Januar startklar bist.<\/p>\r\n      <\/div>\r\n\r\n      <!-- Rechte Spalte: Formular -->\r\n      <div class=\"zero-nl-right\">\r\n        <div class=\"sib-form\" style=\"text-align:center;background-color:transparent;\">\r\n          <div id=\"sib-form-container\" class=\"sib-form-container\">\r\n\r\n            <div id=\"error-message\" class=\"sib-form-message-panel\" style=\"font-size:16px;text-align:left;font-family:'Plus Jakarta Sans',sans-serif;color:#661d1d;background-color:#ffeded;border-radius:3px;border-color:#ff4949;max-width:540px;\">\r\n              <div class=\"sib-form-message-panel__text sib-form-message-panel__text--center\">\r\n                <span class=\"sib-form-message-panel__inner-text\">Deine Anmeldung konnte nicht gespeichert werden.<\/span>\r\n              <\/div>\r\n            <\/div>\r\n            <div><\/div>\r\n\r\n            <div id=\"success-message\" class=\"sib-form-message-panel\" style=\"font-size:16px;text-align:left;font-family:'Plus Jakarta Sans',sans-serif;color:#085229;background-color:#e7faf0;border-radius:3px;border-color:#13ce66;max-width:540px;\">\r\n              <div class=\"sib-form-message-panel__text sib-form-message-panel__text--center\">\r\n                <span class=\"sib-form-message-panel__inner-text\">Deine Anmeldung war erfolgreich! Wir melden uns bei dir.<\/span>\r\n              <\/div>\r\n            <\/div>\r\n            <div><\/div>\r\n\r\n            <div id=\"sib-container\" class=\"sib-container--large sib-container--vertical\" style=\"text-align:center;background-color:transparent;max-width:540px;border:none;direction:ltr;\">\r\n              <form id=\"sib-form\" method=\"POST\"\r\n                action=\"https:\/\/84e6d0bd.sibforms.com\/serve\/MUIFAO9KhSoKgWoRN7RzRjBQn4jIW8Scte-84jA5y2MsO70gYp35oUKg7GoJmrV2W_625cYuR4FRLB5t-JEn_xnd8XDBR_GezVkuzaDDHD44A4h0Aq9Ef5vo88q-L0XTr9WholZ2rL-JXx3sGaDFNkmtKgCdnDHxKEPdrSUJIZRkQ2KRI7WDuXm5bQRPghu5iiLwpYojVSzcJGiY\"\r\n                data-type=\"subscription\">\r\n\r\n                <!-- E-Mail -->\r\n                <div style=\"padding:0 0 4px;\">\r\n                  <div class=\"sib-input sib-form-block\">\r\n                    <div class=\"form__entry entry_block\">\r\n                      <div class=\"form__label-row\">\r\n                        <label class=\"zero-nl-label\" for=\"EMAIL\" data-required=\"*\">\r\n                          Deine E-Mail-Adresse<span class=\"zero-nl-required\">*<\/span>\r\n                        <\/label>\r\n                        <div class=\"entry__field\">\r\n                          <input class=\"zero-nl-input input\" type=\"text\" id=\"EMAIL\" name=\"EMAIL\" autocomplete=\"off\" placeholder=\"max@beispiel.de\" data-required=\"true\" required \/>\r\n                        <\/div>\r\n                      <\/div>\r\n                      <label class=\"entry__error entry__error--primary\"><\/label>\r\n                    <\/div>\r\n                  <\/div>\r\n                <\/div>\r\n\r\n                <!-- Checkboxen -->\r\n                <div class=\"zero-nl-checks\">\r\n                  <div class=\"sib-optin sib-form-block\">\r\n                    <div class=\"form__entry entry_mcq\">\r\n                      <div class=\"form__label-row\">\r\n                        <div class=\"entry__choice\">\r\n                          <label class=\"zero-nl-check\">\r\n                            <input type=\"checkbox\" class=\"input_replaced\" value=\"1\" id=\"JANEIN\" name=\"JANEIN\" \/>\r\n                            <span class=\"zero-nl-checkmark\">\r\n                              <svg viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M2 6l3 3 5-5\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>\r\n                            <\/span>\r\n                            <span class=\"zero-nl-check-text\">\r\n                              Ich habe einen Riester-Vertrag und m\u00f6chte ihn \u00fcbertragen\r\n                              <span class=\"zero-nl-optional\">(optional)<\/span>\r\n                            <\/span>\r\n                          <\/label>\r\n                        <\/div>\r\n                      <\/div>\r\n                      <label class=\"entry__error entry__error--primary\"><\/label>\r\n                    <\/div>\r\n                  <\/div>\r\n\r\n                <\/div>\r\n\r\n                <!-- CTA -->\r\n                <div style=\"padding:0;\">\r\n                  <div class=\"sib-form-block\" style=\"text-align:center;\">\r\n                    <button class=\"sib-form-block__button sib-form-block__button-with-loader\" style=\"font-size:16px;text-align:center;font-weight:800;font-family:'Plus Jakarta Sans',sans-serif;color:#FFFFFF;background-color:#e0146a;border-width:0px;\" form=\"sib-form\" type=\"submit\">\r\n                      <svg class=\"icon clickable__icon progress-indicator__icon sib-hide-loader-icon\" viewBox=\"0 0 512 512\">\r\n                        <path d=\"M460.116 373.846l-20.823-12.022c-5.541-3.199-7.54-10.159-4.663-15.874 30.137-59.886 28.343-131.652-5.386-189.946-33.641-58.394-94.896-95.833-161.827-99.676C261.028 55.961 256 50.751 256 44.352V20.309c0-6.904 5.808-12.337 12.703-11.982 83.556 4.306 160.163 50.864 202.11 123.677 42.063 72.696 44.079 162.316 6.031 236.832-3.14 6.148-10.75 8.461-16.728 5.01z\"\/>\r\n                      <\/svg>\r\n                      Jetzt Wechsel vorbereiten\r\n                    <\/button>\r\n                  <\/div>\r\n                <\/div>\r\n\r\n                <input type=\"text\" name=\"email_address_check\" value=\"\" class=\"input--hidden\">\r\n                <input type=\"hidden\" name=\"locale\" value=\"de\">\r\n              <\/form>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <p class=\"zero-nl-trust\">\ud83d\udd12 Kein Spam \u00b7 Jederzeit abmeldbar \u00b7 Deine Daten sind sicher<\/p>\r\n\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\n  window.REQUIRED_CODE_ERROR_MESSAGE = 'Bitte w\u00e4hle einen L\u00e4ndercode';\r\n  window.LOCALE = 'de';\r\n  window.EMAIL_INVALID_MESSAGE = window.SMS_INVALID_MESSAGE = \"Die angegebene E-Mail-Adresse ist ung\u00fcltig.\";\r\n  window.REQUIRED_ERROR_MESSAGE = \"Das ist ein Pflichtfeld.\";\r\n  window.GENERIC_INVALID_MESSAGE = \"Die angegebenen Daten sind ung\u00fcltig.\";\r\n  window.translation = {\r\n    common: {\r\n      selectedList: '{quantity} Liste ausgew\u00e4hlt',\r\n      selectedLists: '{quantity} Listen ausgew\u00e4hlt',\r\n      selectedOption: '{quantity} ausgew\u00e4hlt',\r\n      selectedOptions: '{quantity} ausgew\u00e4hlt'\r\n    }\r\n  };\r\n  var AUTOHIDE = Boolean(0);\r\n<\/script>\r\n<script defer src=\"https:\/\/sibforms.com\/forms\/end-form\/build\/main.js\"><\/script>\n<h2>Was der Wechsel in Euro bringt<\/h2>\n<p>Sabine, 45, hat einen Riester-Fondssparplan mit 25.000 Euro Guthaben und zahlt 100 Euro im Monat ein. Bis zur Rente sind es noch 20 Jahre.<\/p>\n<div class=\"sc-table table-container table-container--small-margin \"><table class=\"table sc-table table--aligned-left\" style=\"min-width:880px\"><thead><tr><th><\/th><th>Riester behalten<\/th><th>Ins Altersvorsorgedepot \u00fcbertragen<\/th><\/tr><\/thead><tbody><tr><td>Effektivkosten pro Jahr<\/td><td>2,0 %<\/td><td>0,2 %<\/td><\/tr><tr><td>Grundzulage pro Jahr<\/td><td>175 \u20ac<\/td><td>390 \u20ac<\/td><\/tr><tr><td>Rendite nach Kosten<\/td><td>1,0 %<\/td><td>5,8 %<\/td><\/tr><tr><td>Depotwert nach 20 Jahren<\/td><td>rund 61.100 \u20ac<\/td><td>rund 137.800 \u20ac<\/td><\/tr><\/thead><\/tbody><\/table><\/div>\n<p><small><strong>Annahmen:<\/strong> 25.000 Euro Startguthaben, 1.200 Euro Eigenbeitrag im Jahr, Einzahlung zu Jahresbeginn, 6 Prozent Bruttorendite abz\u00fcglich der genannten Kosten, keine Kinderzulagen, ohne Steuern in der Auszahlungsphase.<\/small><\/p>\n<p>Die Differenz liegt bei rund 76.700 Euro. Interessanter als die Summe ist ihre Aufteilung:<\/p>\n<p><strong>Die h\u00f6here Zulage bringt rund 4.800 Euro.<\/strong> Rechnet man nur die F\u00f6rderung um, von 175 auf 390 Euro im Jahr, und l\u00e4sst Kosten und Aktienquote unver\u00e4ndert, steigt der Endwert von 61.100 auf 65.900 Euro.<\/p>\n<p><strong>Kosten und Aktienquote bringen rund 71.900 Euro.<\/strong> Erst wenn zus\u00e4tzlich die Rendite von 1,0 auf 5,8 Prozent steigt, kommt der Endwert bei 137.800 Euro heraus.<\/p>\n<p>Das ist die eigentliche Botschaft, und sie steht quer zu dem, womit f\u00fcr das neue System geworben wird. Die Zulage ist gut sichtbar und leicht zu erkl\u00e4ren, aber sie ist der kleinste der drei Hebel. Entscheidend sind die Kosten und die Frage, ob das Geld \u00fcberhaupt am Aktienmarkt arbeiten darf. Wer einen Riester-Fondssparplan mit hoher Aktienquote und niedrigen Kosten hat, gewinnt durch einen Wechsel entsprechend wenig.<\/p>\n<h2>F\u00fcr wen der Wechsel nicht sinnvoll ist<\/h2>\n<p>Vier Gruppen sollten ihren Vertrag behalten oder den Wechsel zumindest genau pr\u00fcfen.<\/p>\n<p><strong>Altvertr\u00e4ge aus den Jahren 2002 bis 2004.<\/strong> Dort steht ein Garantiezins von 3,25 Prozent im Vertrag, bei Vertr\u00e4gen bis 2006 immerhin 2,75 Prozent. Verglichen mit dem H\u00f6chstrechnungszins von 1,0 Prozent, der seit 2025 f\u00fcr Neuvertr\u00e4ge gilt, ist das eine Zusage, die sich nicht zur\u00fcckholen l\u00e4sst. Sie geht mit der \u00dcbertragung verloren.<\/p>\n<p><strong>Vertr\u00e4ge mit garantiertem Rentenfaktor.<\/strong> \u00c4ltere Rentenversicherungen sichern oft einen Rentenfaktor zu, der deutlich \u00fcber dem liegt, was heute angeboten wird. Auch diese Zusage f\u00e4llt bei einer \u00dcbertragung weg. Pr\u00fcfe die Police, bevor du wechselst.<\/p>\n<p><strong>Sparer mit mehreren Kindern und kleinem Beitrag.<\/strong> Wer dauerhaft weniger als 25 Euro im Monat aufbringen kann, bekommt im alten System feste Kinderzulagen, die nicht am Eigenbeitrag h\u00e4ngen. Das kann vorteilhafter bleiben.<\/p>\n<p><strong>Wer bereits in der Auszahlungsphase ist.<\/strong> Eine \u00dcbertragung ist dann nicht mehr m\u00f6glich.<\/p>\n<h2>Der Wechsel in f\u00fcnf Schritten<\/h2>\n<p><strong>Schritt 1: Vertrag durchleuchten.<\/strong> Fordere die j\u00e4hrliche Kosteninformation an. Entscheidend ist die Zeile mit den Effektivkosten. Alles \u00fcber 1 Prozent ist ein Warnsignal, alles \u00fcber 2 Prozent ein Grund zum Handeln. Notiere zus\u00e4tzlich den Garantiezins, einen etwaigen garantierten Rentenfaktor, das aktuelle Guthaben und die Summe der erhaltenen Zulagen.<\/p>\n<p><strong>Schritt 2: Pr\u00fcfen, ob ein Anbieterwechsel \u00fcberhaupt n\u00f6tig ist.<\/strong> Wenn dein bisheriger Anbieter ein Altersvorsorgedepot anbietet oder den Wechsel in die neue F\u00f6rdersystematik erm\u00f6glicht, ist das der k\u00fcrzere Weg. Ein Anbieterwechsel lohnt sich vor allem dann, wenn die Kosten hoch sind.<\/p>\n<p><strong>Schritt 3: Neues Depot er\u00f6ffnen.<\/strong> Ab 2027 bieten Banken, <a href=\"https:\/\/www.finanzen.net\/ratgeber\/broker\/produkte-vergleiche\/neobroker-vergleich\/\" data-ilm-light=\"50\" title=\"Neobroker Vergleich\">Neobroker<\/a> und Fondsgesellschaften Altersvorsorgedepots an. Achte auf niedrige Depotkosten und eine breite Fondsauswahl innerhalb der gesetzlichen Positivliste.<\/p>\n<p><strong>Schritt 4: \u00dcbertragung ansto\u00dfen.<\/strong> Rechtlich l\u00e4uft der Wechsel \u00fcber eine K\u00fcndigung des Altvertrags mit dem Verlangen, das gebildete Kapital auf den neuen Vertrag zu \u00fcbertragen. Die Frist betr\u00e4gt drei Monate zum Ende eines Kalendervierteljahres. Wer im Februar k\u00fcndigt, wechselt zum 30. Juni. Die Zustimmung des bisherigen Anbieters ist nicht erforderlich, die Frist aber einzuhalten. Die meisten Anbieter stellen daf\u00fcr ein Formular bereit.<\/p>\n<p><strong>Schritt 5: Kosten einplanen.<\/strong> Liegt der Vertragsschluss weniger als f\u00fcnf Jahre zur\u00fcck, darf der abgebende Anbieter bis zu 150 Euro berechnen. Danach muss er kostenfrei \u00fcbertragen. Unabh\u00e4ngig davon darf der aufnehmende Anbieter eine einmalige Verwaltungspauschale von bis zu 150 Euro verlangen. Rechne also im Zweifel mit 150 Euro, nicht mit null.<\/p>\n<div class=\"highlightbox box box--small-padding box--tiny-margin-y\" style=\"--color-background:#fefcef;\"><strong class=\"headline headline--h3 headline--small-margin\">\ud83d\udca1 Gut zu wissen<\/strong><div class=\"box__content\"><p>Am 1. Januar 2027 werden sehr viele Sparer gleichzeitig ein Depot er\u00f6ffnen wollen. Identit\u00e4tspr\u00fcfung und Freischaltung brauchen Zeit, und f\u00fcr die \u00dcbertragung kommt die K\u00fcndigungsfrist von drei Monaten zum Quartalsende hinzu. <a href=\"https:\/\/g.finanzen.net\/zero-fnet_017o-ratgeber-altersvorsorgedepot-gut-zu-wissen\"><strong>Wer sich jetzt bei finanzen.net ZERO kostenlos vormerkt<\/strong><\/a>, hat diesen Schritt hinter sich und kann den \u00dcbertrag direkt zum Start ansto\u00dfen. F\u00fcr die Zulage selbst z\u00e4hlt \u00fcbrigens nur, wie viel du im Beitragsjahr insgesamt einzahlst, nicht wann.<\/p><\/div><\/div>\n<h2>Was bleibt und was wegf\u00e4llt<\/h2>\n<p><strong>Was bleibt:<\/strong> alle bisherigen Zulagen, alle Steuervorteile, das komplette Guthaben. Die \u00dcbertragung ist f\u00f6rderunsch\u00e4dlich, anders als eine K\u00fcndigung.<\/p>\n<p><strong>Was wegf\u00e4llt:<\/strong> die Beitragsgarantie und, bei \u00e4lteren Vertr\u00e4gen, der darin zugesagte Garantiezins sowie ein etwaiger garantierter Rentenfaktor. Der Verzicht auf die Garantie ist der Zweck der \u00dcbung, denn sie hat die Aktienquote begrenzt. Die beiden anderen Zusagen sind dagegen ein echter Verlust, der sich nur bei alten Vertr\u00e4gen stellt und dort genau gepr\u00fcft geh\u00f6rt.<\/p>\n<h2>Fazit<\/h2>\n<p>F\u00fcr die meisten Riester-Sparer mit einem teuren Vertrag und mehr als zehn Jahren Restlaufzeit ist der Wechsel wirtschaftlich klar vorteilhaft. Der b\u00fcrokratische Aufwand ist \u00fcberschaubar: ein Formular, eine Frist von drei Monaten zum Quartalsende, h\u00f6chstens 150 Euro Geb\u00fchr.<\/p>\n<p>Der Hebel liegt dabei nicht dort, wo er meistens vermutet wird. Die h\u00f6here Zulage macht im Beispiel oben rund 6 Prozent der Differenz aus, Kosten und Aktienquote den Rest. Wer schon heute einen g\u00fcnstigen Riester-Fondssparplan mit hoher Aktienquote hat, gewinnt entsprechend wenig und kann sich auf den Wechsel der F\u00f6rdersystematik beschr\u00e4nken.<\/p>\n<p>Zwei Konstellationen sprechen gegen den Wechsel: ein Garantiezins von 2,75 oder 3,25 Prozent aus einem Altvertrag und ein garantierter Rentenfaktor. Beides steht in deinen Unterlagen. Sieh nach, bevor du k\u00fcndigst.<\/p>\n<!-- ZERO Ratgeber Newsletter \u2013 WordPress Snippet (Brevo-Script) -->\r\n<!-- Variante: Riester-\u00dcbertrag \u00b7 Volle Content-Breite \u00b7 Einfach in Shortcode-\/Snippet-Plugin einf\u00fcgen -->\r\n\r\n<style>\r\n  .zero-nl {\r\n    --zero-red: #E3002B;\r\n    --zero-red-hover: #c80025;\r\n    --zero-red-glow: rgba(227, 0, 43, 0.18);\r\n    --zero-card: #ffffff;\r\n    --zero-text: #0c0c0d;\r\n    --zero-muted: #6b6974;\r\n    --zero-border: #e2e0e4;\r\n    --zero-error-bg: #ffeded;\r\n    --zero-error-text: #661d1d;\r\n    --zero-error-border: #ff4949;\r\n    --zero-success-bg: #e7faf0;\r\n    --zero-success-text: #085229;\r\n    --zero-success-border: #13ce66;\r\n    --zero-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\r\n\r\n    font-family: var(--zero-font);\r\n    width: 100%;\r\n    margin-bottom: 40px;\r\n    background: #f0f0f0;\r\n    padding: 20px;\r\n    border-radius: 16px;\r\n  }\r\n\r\n  .zero-nl * { box-sizing: border-box; margin: 0; padding: 0; }\r\n\r\n  .zero-nl-card {\r\n    background: var(--zero-card);\r\n    border: 1px solid var(--zero-border);\r\n    border-radius: 12px;\r\n    width: 100%;\r\n    box-shadow: 0 2px 4px rgba(0,0,0,0.07), 0 8px 20px rgba(0,0,0,0.12), 0 16px 40px rgba(0,0,0,0.08);\r\n    overflow: hidden;\r\n  }\r\n\r\n  \/* Banner *\/\r\n  .zero-nl-banner {\r\n    background: #242424;\r\n    padding: 14px 28px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: space-between;\r\n    gap: 12px;\r\n  }\r\n\r\n  .zero-nl-banner-text {\r\n    color: #fff;\r\n    font-size: 15px;\r\n    font-weight: 700;\r\n    letter-spacing: 0.04em;\r\n    text-transform: uppercase;\r\n    white-space: nowrap;\r\n  }\r\n\r\n  .zero-nl-banner img {\r\n    height: 32px;\r\n    width: auto;\r\n    flex-shrink: 0;\r\n    display: block;\r\n  }\r\n\r\n  \/* Body \u2013 zweispaltig auf Desktop *\/\r\n  .zero-nl-body {\r\n    padding: 28px;\r\n    display: grid;\r\n    grid-template-columns: 1fr 1fr;\r\n    gap: 8px 36px;\r\n    align-items: start;\r\n  }\r\n\r\n  .zero-nl-left { grid-column: 1; }\r\n  .zero-nl-right { grid-column: 2; }\r\n\r\n  .zero-nl-title {\r\n    font-size: 26px;\r\n    font-weight: 800;\r\n    color: var(--zero-text);\r\n    line-height: 1.35;\r\n    margin-bottom: 6px;\r\n  }\r\n\r\n  .zero-nl-title em {\r\n    font-style: normal;\r\n    color: var(--zero-red);\r\n  }\r\n\r\n  .zero-nl-subtitle {\r\n    font-size: 13px;\r\n    color: var(--zero-muted);\r\n    line-height: 1.55;\r\n  }\r\n\r\n  \/* Brevo-Meldungen *\/\r\n  .zero-nl .sib-form-message-panel {\r\n    display: none;\r\n    padding: 10px 14px !important;\r\n    border-radius: 8px !important;\r\n    font-size: 13px !important;\r\n    line-height: 1.5 !important;\r\n    margin-bottom: 12px !important;\r\n    font-family: var(--zero-font) !important;\r\n    max-width: none !important;\r\n    text-align: center !important;\r\n  }\r\n\r\n  .zero-nl #error-message {\r\n    background: var(--zero-error-bg) !important;\r\n    color: var(--zero-error-text) !important;\r\n    border: 1px solid var(--zero-error-border) !important;\r\n  }\r\n\r\n  .zero-nl #success-message {\r\n    background: var(--zero-success-bg) !important;\r\n    color: var(--zero-success-text) !important;\r\n    border: 1px solid var(--zero-success-border) !important;\r\n  }\r\n\r\n  .zero-nl .sib-form-message-panel__text { justify-content: center; }\r\n  .zero-nl .sib-icon { display: none !important; }\r\n\r\n  .zero-nl #sib-container {\r\n    background: transparent !important;\r\n    border: none !important;\r\n    padding: 0 !important;\r\n    max-width: none !important;\r\n  }\r\n\r\n  \/* Label *\/\r\n  .zero-nl .zero-nl-label {\r\n    display: block;\r\n    font-size: 13px;\r\n    font-weight: 600;\r\n    color: var(--zero-muted);\r\n    margin-bottom: 5px;\r\n  }\r\n\r\n  .zero-nl .zero-nl-required {\r\n    color: var(--zero-red);\r\n    margin-left: 2px;\r\n  }\r\n\r\n  \/* Input *\/\r\n  .zero-nl .zero-nl-input {\r\n    width: 100%;\r\n    padding: 12px 14px;\r\n    font-size: 14px;\r\n    font-family: var(--zero-font);\r\n    color: var(--zero-text);\r\n    border: 1.5px solid var(--zero-border);\r\n    border-radius: 8px;\r\n    outline: none;\r\n    transition: border-color 0.2s ease, box-shadow 0.2s ease;\r\n    background: #faf9fb;\r\n  }\r\n\r\n  .zero-nl .zero-nl-input::placeholder { color: #b5b3ba; }\r\n  .zero-nl .zero-nl-input:focus {\r\n    border-color: var(--zero-red);\r\n    box-shadow: 0 0 0 3px var(--zero-red-glow);\r\n    background: #fff;\r\n  }\r\n\r\n  \/* Checkboxen *\/\r\n  .zero-nl .zero-nl-checks {\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 5px;\r\n    margin-top: 12px;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check {\r\n    display: flex;\r\n    align-items: flex-start;\r\n    gap: 8px;\r\n    cursor: pointer;\r\n    position: relative;\r\n    padding: 0;\r\n    margin: 0;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check input[type=\"checkbox\"] {\r\n    position: absolute;\r\n    opacity: 0;\r\n    width: 0;\r\n    height: 0;\r\n  }\r\n\r\n  .zero-nl .zero-nl-checkmark {\r\n    flex-shrink: 0;\r\n    width: 17px;\r\n    height: 17px;\r\n    border: 1.5px solid #ccc;\r\n    border-radius: 3px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    transition: all 0.15s ease;\r\n    margin-top: 1px;\r\n    background: #faf9fb;\r\n  }\r\n\r\n  .zero-nl .zero-nl-checkmark svg {\r\n    width: 10px;\r\n    height: 10px;\r\n    opacity: 0;\r\n    transform: scale(0.5);\r\n    transition: all 0.15s ease;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check input:checked + .zero-nl-checkmark {\r\n    background: var(--zero-red);\r\n    border-color: var(--zero-red);\r\n  }\r\n\r\n  .zero-nl .zero-nl-check input:checked + .zero-nl-checkmark svg {\r\n    opacity: 1;\r\n    transform: scale(1);\r\n  }\r\n\r\n  .zero-nl .zero-nl-check-text {\r\n    font-size: 12.5px;\r\n    line-height: 1.4;\r\n    color: var(--zero-text);\r\n  }\r\n\r\n  .zero-nl .zero-nl-check-text a {\r\n    color: var(--zero-red);\r\n    text-decoration: underline;\r\n    text-underline-offset: 2px;\r\n  }\r\n\r\n  .zero-nl .zero-nl-check-text a:hover { text-decoration-thickness: 2px; }\r\n\r\n  .zero-nl .zero-nl-optional {\r\n    font-size: 11px;\r\n    color: var(--zero-muted);\r\n    font-weight: 400;\r\n  }\r\n\r\n  \/* CTA-Button *\/\r\n  .zero-nl .sib-form-block__button {\r\n    display: flex !important;\r\n    align-items: center !important;\r\n    justify-content: center !important;\r\n    gap: 8px !important;\r\n    width: 100% !important;\r\n    padding: 14px 24px !important;\r\n    font-size: 16px !important;\r\n    font-weight: 800 !important;\r\n    font-family: var(--zero-font) !important;\r\n    color: #fff !important;\r\n    background: #e0146a !important;\r\n    border: none !important;\r\n    border-radius: 60px !important;\r\n    cursor: pointer;\r\n    transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;\r\n    margin-top: 16px;\r\n    letter-spacing: 0.01em;\r\n    border-width: 0 !important;\r\n    box-shadow: 0 4px 16px rgba(224,20,106,0.18), 0 1px 3px rgba(0,0,0,0.08) !important;\r\n    line-height: 1.2 !important;\r\n  }\r\n\r\n  .zero-nl .sib-form-block__button:hover {\r\n    background: #c9115d !important;\r\n    box-shadow: 0 6px 24px rgba(224,20,106,0.28), 0 2px 6px rgba(0,0,0,0.1) !important;\r\n    transform: translateY(-1px);\r\n  }\r\n\r\n  .zero-nl .sib-form-block__button:active { transform: translateY(0) scale(0.985); }\r\n\r\n  .zero-nl .sib-hide-loader-icon { display: none; }\r\n\r\n  .zero-nl .entry__error {\r\n    display: block;\r\n    font-size: 12px !important;\r\n    font-family: var(--zero-font) !important;\r\n    color: var(--zero-error-text) !important;\r\n    background: transparent !important;\r\n    border: none !important;\r\n    padding: 3px 0 0 0 !important;\r\n    margin: 0 !important;\r\n    border-radius: 0 !important;\r\n  }\r\n\r\n  .zero-nl .input--hidden { position: absolute; left: -9999px; }\r\n\r\n  .zero-nl-trust {\r\n    font-size: 11px;\r\n    color: #a09da6;\r\n    text-align: center;\r\n    margin-top: 12px;\r\n    line-height: 1.4;\r\n    grid-column: 1 \/ -1;\r\n  }\r\n\r\n  \/* Mobile: einspaltig *\/\r\n  @media (max-width: 600px) {\r\n    .zero-nl {\r\n      padding: 16px;\r\n      border-radius: 12px;\r\n    }\r\n    .zero-nl-body {\r\n      grid-template-columns: 1fr;\r\n      gap: 20px;\r\n      padding: 24px 20px;\r\n    }\r\n    .zero-nl-left, .zero-nl-right { grid-column: 1; }\r\n    .zero-nl-banner {\r\n      padding: 12px 12px 12px 20px;\r\n      gap: 8px;\r\n    }\r\n    .zero-nl-banner-text {\r\n      font-size: 12px;\r\n      min-width: 0;\r\n    }\r\n    .zero-nl-banner img { height: 26px; }\r\n    .zero-nl-title { font-size: 22px; }\r\n    .zero-nl .sib-form-block__button { font-size: 15px !important; padding: 13px 20px !important; }\r\n  }\r\n<\/style>\r\n\r\n<div class=\"zero-nl\">\r\n  <div class=\"zero-nl-card\">\r\n\r\n    <!-- Banner -->\r\n    <div class=\"zero-nl-banner\">\r\n      <span class=\"zero-nl-banner-text\">\u2728 Kostenlos &amp; unverbindlich<\/span>\r\n      <img decoding=\"async\"\r\n        src=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/03\/zero_logo_26_light-1.png\"\r\n        alt=\"finanzen.net zero\"\r\n        loading=\"lazy\"\r\n      \/>\r\n    <\/div>\r\n\r\n    <div class=\"zero-nl-body\">\r\n\r\n      <!-- Linke Spalte: Text -->\r\n      <div class=\"zero-nl-left\">\r\n        <h2 class=\"zero-nl-title\">Riester-Vertrag \u00fcbertragen und bis zu <em>540&nbsp;\u20ac F\u00f6rderung<\/em> sichern.<\/h2>\r\n        <p class=\"zero-nl-subtitle\">Dein Riester-Guthaben kann ab 2027 in ein Altersvorsorgedepot bei unserem Broker finanzen.net ZERO wechseln \u2013 <strong>alle bisherigen Zulagen bleiben erhalten<\/strong>. Melde dich jetzt an, damit du am 1.&nbsp;Januar startklar bist.<\/p>\r\n      <\/div>\r\n\r\n      <!-- Rechte Spalte: Formular -->\r\n      <div class=\"zero-nl-right\">\r\n        <div class=\"sib-form\" style=\"text-align:center;background-color:transparent;\">\r\n          <div id=\"sib-form-container\" class=\"sib-form-container\">\r\n\r\n            <div id=\"error-message\" class=\"sib-form-message-panel\" style=\"font-size:16px;text-align:left;font-family:'Plus Jakarta Sans',sans-serif;color:#661d1d;background-color:#ffeded;border-radius:3px;border-color:#ff4949;max-width:540px;\">\r\n              <div class=\"sib-form-message-panel__text sib-form-message-panel__text--center\">\r\n                <span class=\"sib-form-message-panel__inner-text\">Deine Anmeldung konnte nicht gespeichert werden.<\/span>\r\n              <\/div>\r\n            <\/div>\r\n            <div><\/div>\r\n\r\n            <div id=\"success-message\" class=\"sib-form-message-panel\" style=\"font-size:16px;text-align:left;font-family:'Plus Jakarta Sans',sans-serif;color:#085229;background-color:#e7faf0;border-radius:3px;border-color:#13ce66;max-width:540px;\">\r\n              <div class=\"sib-form-message-panel__text sib-form-message-panel__text--center\">\r\n                <span class=\"sib-form-message-panel__inner-text\">Deine Anmeldung war erfolgreich! Wir melden uns bei dir.<\/span>\r\n              <\/div>\r\n            <\/div>\r\n            <div><\/div>\r\n\r\n            <div id=\"sib-container\" class=\"sib-container--large sib-container--vertical\" style=\"text-align:center;background-color:transparent;max-width:540px;border:none;direction:ltr;\">\r\n              <form id=\"sib-form\" method=\"POST\"\r\n                action=\"https:\/\/84e6d0bd.sibforms.com\/serve\/MUIFAO9KhSoKgWoRN7RzRjBQn4jIW8Scte-84jA5y2MsO70gYp35oUKg7GoJmrV2W_625cYuR4FRLB5t-JEn_xnd8XDBR_GezVkuzaDDHD44A4h0Aq9Ef5vo88q-L0XTr9WholZ2rL-JXx3sGaDFNkmtKgCdnDHxKEPdrSUJIZRkQ2KRI7WDuXm5bQRPghu5iiLwpYojVSzcJGiY\"\r\n                data-type=\"subscription\">\r\n\r\n                <!-- E-Mail -->\r\n                <div style=\"padding:0 0 4px;\">\r\n                  <div class=\"sib-input sib-form-block\">\r\n                    <div class=\"form__entry entry_block\">\r\n                      <div class=\"form__label-row\">\r\n                        <label class=\"zero-nl-label\" for=\"EMAIL\" data-required=\"*\">\r\n                          Deine E-Mail-Adresse<span class=\"zero-nl-required\">*<\/span>\r\n                        <\/label>\r\n                        <div class=\"entry__field\">\r\n                          <input class=\"zero-nl-input input\" type=\"text\" id=\"EMAIL\" name=\"EMAIL\" autocomplete=\"off\" placeholder=\"max@beispiel.de\" data-required=\"true\" required \/>\r\n                        <\/div>\r\n                      <\/div>\r\n                      <label class=\"entry__error entry__error--primary\"><\/label>\r\n                    <\/div>\r\n                  <\/div>\r\n                <\/div>\r\n\r\n                <!-- Checkboxen -->\r\n                <div class=\"zero-nl-checks\">\r\n                  <div class=\"sib-optin sib-form-block\">\r\n                    <div class=\"form__entry entry_mcq\">\r\n                      <div class=\"form__label-row\">\r\n                        <div class=\"entry__choice\">\r\n                          <label class=\"zero-nl-check\">\r\n                            <input type=\"checkbox\" class=\"input_replaced\" value=\"1\" id=\"JANEIN\" name=\"JANEIN\" \/>\r\n                            <span class=\"zero-nl-checkmark\">\r\n                              <svg viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M2 6l3 3 5-5\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>\r\n                            <\/span>\r\n                            <span class=\"zero-nl-check-text\">\r\n                              Ich habe einen Riester-Vertrag und m\u00f6chte ihn \u00fcbertragen\r\n                              <span class=\"zero-nl-optional\">(optional)<\/span>\r\n                            <\/span>\r\n                          <\/label>\r\n                        <\/div>\r\n                      <\/div>\r\n                      <label class=\"entry__error entry__error--primary\"><\/label>\r\n                    <\/div>\r\n                  <\/div>\r\n\r\n                <\/div>\r\n\r\n                <!-- CTA -->\r\n                <div style=\"padding:0;\">\r\n                  <div class=\"sib-form-block\" style=\"text-align:center;\">\r\n                    <button class=\"sib-form-block__button sib-form-block__button-with-loader\" style=\"font-size:16px;text-align:center;font-weight:800;font-family:'Plus Jakarta Sans',sans-serif;color:#FFFFFF;background-color:#e0146a;border-width:0px;\" form=\"sib-form\" type=\"submit\">\r\n                      <svg class=\"icon clickable__icon progress-indicator__icon sib-hide-loader-icon\" viewBox=\"0 0 512 512\">\r\n                        <path d=\"M460.116 373.846l-20.823-12.022c-5.541-3.199-7.54-10.159-4.663-15.874 30.137-59.886 28.343-131.652-5.386-189.946-33.641-58.394-94.896-95.833-161.827-99.676C261.028 55.961 256 50.751 256 44.352V20.309c0-6.904 5.808-12.337 12.703-11.982 83.556 4.306 160.163 50.864 202.11 123.677 42.063 72.696 44.079 162.316 6.031 236.832-3.14 6.148-10.75 8.461-16.728 5.01z\"\/>\r\n                      <\/svg>\r\n                      Jetzt Wechsel vorbereiten\r\n                    <\/button>\r\n                  <\/div>\r\n                <\/div>\r\n\r\n                <input type=\"text\" name=\"email_address_check\" value=\"\" class=\"input--hidden\">\r\n                <input type=\"hidden\" name=\"locale\" value=\"de\">\r\n              <\/form>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <p class=\"zero-nl-trust\">\ud83d\udd12 Kein Spam \u00b7 Jederzeit abmeldbar \u00b7 Deine Daten sind sicher<\/p>\r\n\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\n  window.REQUIRED_CODE_ERROR_MESSAGE = 'Bitte w\u00e4hle einen L\u00e4ndercode';\r\n  window.LOCALE = 'de';\r\n  window.EMAIL_INVALID_MESSAGE = window.SMS_INVALID_MESSAGE = \"Die angegebene E-Mail-Adresse ist ung\u00fcltig.\";\r\n  window.REQUIRED_ERROR_MESSAGE = \"Das ist ein Pflichtfeld.\";\r\n  window.GENERIC_INVALID_MESSAGE = \"Die angegebenen Daten sind ung\u00fcltig.\";\r\n  window.translation = {\r\n    common: {\r\n      selectedList: '{quantity} Liste ausgew\u00e4hlt',\r\n      selectedLists: '{quantity} Listen ausgew\u00e4hlt',\r\n      selectedOption: '{quantity} ausgew\u00e4hlt',\r\n      selectedOptions: '{quantity} ausgew\u00e4hlt'\r\n    }\r\n  };\r\n  var AUTOHIDE = Boolean(0);\r\n<\/script>\r\n<script defer src=\"https:\/\/sibforms.com\/forms\/end-form\/build\/main.js\"><\/script>\n<h2>H\u00e4ufige Fragen<\/h2>\n<h3>Ist die Riester-Rente abgeschafft?<\/h3>\n<p>F\u00fcr Neuabschl\u00fcsse ja. Ab dem 1. Januar 2027 werden keine neuen Vertr\u00e4ge mehr geschlossen. Bestehende Vertr\u00e4ge haben Bestandsschutz, alle bisher erhaltenen Zulagen und Steuervorteile bleiben bestehen.<\/p>\n<h3>Warum sollte ich meinen Riester-Vertrag nicht k\u00fcndigen?<\/h3>\n<p>Weil eine K\u00fcndigung als sch\u00e4dliche Verwendung gilt und alle Zulagen und Steuervorteile zur\u00fcckzuzahlen sind. Bei einem 15 Jahre alten Vertrag sind das mehrere tausend Euro, dazu kommen m\u00f6gliche Stornokosten. Ruhen lassen oder \u00fcbertragen ist praktisch immer besser.<\/p>\n<h3>Wie l\u00e4uft die \u00dcbertragung ab?<\/h3>\n<p>\u00dcber eine K\u00fcndigung des Altvertrags mit dem Verlangen, das Kapital auf den neuen Vertrag zu \u00fcbertragen. Die Frist betr\u00e4gt drei Monate zum Ende eines Kalendervierteljahres. Die Zustimmung des bisherigen Anbieters ist nicht erforderlich.<\/p>\n<h3>Was kostet der Wechsel?<\/h3>\n<p>Innerhalb der ersten f\u00fcnf Vertragsjahre darf der abgebende Anbieter bis zu 150 Euro berechnen, danach muss er kostenfrei \u00fcbertragen. Der aufnehmende Anbieter darf unabh\u00e4ngig davon einmalig bis zu 150 Euro Verwaltungspauschale verlangen.<\/p>\n<h3>Gibt es einen Geringverdiener-Bonus von 175 Euro?<\/h3>\n<p>Nein. Das verk\u00fcndete Gesetz kennt keinen solchen Bonus, der Betrag stammt aus einem fr\u00fcheren Reformentwurf. Die 175 Euro im Gesetz sind die Obergrenze der Grundzulage f\u00fcr mittelbar zulageberechtigte Ehegatten.<\/p>\n<h3>Kann ich Riester ruhen lassen und trotzdem ein Altersvorsorgedepot er\u00f6ffnen?<\/h3>\n<p>Technisch ja. Mit dem Abschluss eines neuen Altersvorsorgevertrags endet allerdings der Bestandsschutz des Altvertrags. Kl\u00e4re vorher mit deinem Anbieter, was das f\u00fcr deinen konkreten Vertrag bedeutet.<\/p>\n<h3>F\u00fcr wen lohnt sich Riester nach der Reform noch?<\/h3>\n<p>F\u00fcr Sparer mit mehreren Kindern, die dauerhaft weniger als 25 Euro im Monat aufbringen k\u00f6nnen, und f\u00fcr Altvertr\u00e4ge mit hohem Garantiezins oder garantiertem Rentenfaktor. F\u00fcr alle anderen ist das Altersvorsorgedepot in der Regel besser.<\/p>\n<h3>Ab welchem Beitrag ist die neue Zulage h\u00f6her?<\/h3>\n<p>Ab 350 Euro Eigenbeitrag im Jahr, also rund 29 Euro im Monat. Genau dort erreicht die beitragsproportionale Grundzulage die festen 175 Euro des alten Systems.<\/p>\n<h3>Wann ist der letzte Termin f\u00fcr einen Riester-Neuabschluss?<\/h3>\n<p>Der 31. Dezember 2026. F\u00fcr die Mehrheit der Sparer lohnt sich ein Abschluss kurz vor Torschluss nicht. Sinnvoll kann er f\u00fcr Familien mit mehreren Kindern und sehr kleinem Sparbeitrag sein.<\/p>\n<h2>\u00dcber diesen Artikel<\/h2>\n<p>Der Artikel gibt den Rechtsstand des Altersvorsorgereformgesetzes wieder, verk\u00fcndet am 29. Mai 2026 im Bundesgesetzblatt (BGBl. I 2026 Nr. 156). Die Regeln zu Zulagen, Mindesteigenbeitrag und F\u00f6rderh\u00f6chstgrenze folgen den \u00a7\u00a7 10a und 79 bis 86 EStG in der ab 2027 geltenden Fassung, die Regeln zu K\u00fcndigungsfrist und Wechselkosten dem Altersvorsorgevertr\u00e4ge-Zertifizierungsgesetz. Alle Rechenbeispiele nennen ihre Annahmen und sind nachrechenbar. Es handelt sich um Modellrechnungen mit konstanter Rendite, nicht um historische Wertentwicklungen.<\/p>\n<p>Eine steuerrechtliche Begutachtung durch Dritte hat nicht stattgefunden. Der Artikel ersetzt keine individuelle Beratung. Ob ein Wechsel f\u00fcr dich sinnvoll ist, h\u00e4ngt von deinem konkreten Vertrag ab, insbesondere von Garantiezins, Rentenfaktor und Effektivkosten.<\/p>\n<p><strong>Quellen<\/strong><\/p>\n<p><a href=\"https:\/\/www.recht.bund.de\/bgbl\/1\/2026\/156\/regelungstext.pdf?__blob=publicationFile&amp;v=1\" target=\"_blank\" rel=\"noopener\">Altersvorsorgereformgesetz, Regelungstext im Bundesgesetzblatt (BGBl. I 2026 Nr. 156)<\/a><\/p>\n<p><a href=\"https:\/\/www.bundesfinanzministerium.de\/Content\/DE\/FAQ\/reform-der-privaten-altersvorsorge.html\" target=\"_blank\" rel=\"noopener\">Bundesministerium der Finanzen: Fragen und Antworten zur Reform der gef\u00f6rderten privaten Altersvorsorge<\/a><\/p>\n<p><a href=\"https:\/\/www.bundesfinanzministerium.de\/Content\/DE\/Downloads\/Broschueren_Bestellservice\/reform-der-privaten-altersvorsorge.pdf?__blob=publicationFile&amp;v=5\" target=\"_blank\" rel=\"noopener\">Bundesministerium der Finanzen: Brosch\u00fcre zur Reform der privaten Altersvorsorge (PDF)<\/a><\/p>\n<p><a href=\"https:\/\/aktuar.de\/de\/newsroom\/detail\/deutsche-aktuarvereinigung-empfiehlt-auch-fuer-2026-einen-hoechstrechnungszins-in-hoehe-von-1-prozent\/\" target=\"_blank\" rel=\"noopener\">Deutsche Aktuarvereinigung: H\u00f6chstrechnungszins f\u00fcr Neuvertr\u00e4ge<\/a><\/p>\n<p><a href=\"https:\/\/www.verbraucherzentrale.de\/wissen\/geld-versicherungen\/altersvorsorge\/neues-altersvorsorgedepot-rentenchance-oder-teure-verkaufsfalle-118178\" target=\"_blank\" rel=\"noopener\">Verbraucherzentrale: Einordnung der neuen Altersvorsorgeangebote<\/a><\/p>\n                    <\/div>\n    <\/div>\n<\/div>\n\n\n\n<div class=\"container container--narrow\">\n    <\/div>\n\n\n<div class=\"container container--narrow\" >\n    <div class=\"disclaimer flow-content\">\n                    <small>\n                <p style=\"font-size: 11pt\">Disclaimer: Die in diesem Artikel enthaltenen Inhalte dienen ausschlie\u00dflich allgemeinen Informations-, Bildungs- und Marketingzwecken ohne Gew\u00e4hr auf Vollst\u00e4ndigkeit, Richtigkeit und Aktualit\u00e4t. Die Inhalte stellen keine Anlageberatung, Anlagestrategieempfehlung oder Aufforderung zum Kauf oder Verkauf von Wertpapieren oder sonstigen Finanzinstrumenten dar. Die Informationen ber\u00fccksichtigen nicht die individuellen Anlageziele und finanzielle Situation des Lesers. Jede Anlageentscheidung sollte eigenverantwortlich getroffen und sorgf\u00e4ltig gepr\u00fcft werden. Vor einer Anlageentscheidung sollte der Rat eines Anlage- und Steuerberaters eingeholt werden. Der Handel mit Wertpapieren oder sonstigen Finanzinstrumenten ist mit hohen Risiken verbunden, bis hin zum Totalverlust des eingesetzten Kapitals. Die in der Vergangenheit erzielte Performance ist kein Indikator f\u00fcr zuk\u00fcnftige Wertentwicklungen. Aussagen \u00fcber zuk\u00fcnftige wirtschaftliche Entwicklungen basieren grunds\u00e4tzlich auf Annahmen und Einsch\u00e4tzungen, die sich im Zeitablauf als nicht zutreffend erweisen k\u00f6nnen. Wir \u00fcbernehmen keine Haftung f\u00fcr Verluste, die durch die Umsetzung der in diesem Artikel genannten Informationen entstehen.<\/p>\n<p style=\"font-size: 11pt\"><sup>1<\/sup>Hinweis zu ZERO: <a href=\"https:\/\/www.finanzen.net\/zero\/?utm_source=finnet-ratgeber&amp;utm_medium=web&amp;utm_term=fnet_017m&amp;utm_campaign=content&amp;utm_content=[current_slug]\" target=\"_blank\" rel=\"noopener\">finanzen.net zero<\/a> ist ein Angebot der <a href=\"https:\/\/www.finanzen.net\/zero\/impressum\/?utm_source=finnet-ratgeber&amp;utm_medium=web&amp;utm_term=fnet_017m&amp;utm_campaign=content&amp;utm_content=[current_slug]\" target=\"_blank\" rel=\"noopener\">finanzen.net zero GmbH<\/a>, einer Tochter der <a href=\"https:\/\/www.finanzen.net\/impressum\">finanzen.net GmbH<\/a>.<\/p>\n<p style=\"font-size: 11pt\"><sup>*<\/sup>Hinweis zu Affiliate-Links: Unsere Ratgeber-Artikel sind objektiv und unabh\u00e4ngig erstellt, wobei mit Sternchen gekennzeichnete Links zur Finanzierung der kostenlosen Inhalte dienen. Die Verg\u00fctung aus diesen Links hat keinen Einfluss auf unsere Inhalte.<\/p>\n            <\/small>\n                    <\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>15.000 Euro weniger Geb\u00fchren, dreimal so viel F\u00f6rderung, volle Aktienquote \u2013 wer seinen Riester-Vertrag ins neue Altersvorsorgedepot \u00fcbertr\u00e4gt, gewinnt auf ganzer Linie.<\/p>\n","protected":false},"author":6,"featured_media":39231,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":"","_members_access_role":[],"_members_access_error":""},"categories":[1466,1101,1430,1467,359],"tags":[],"class_list":["post-37275","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-altersvorsorgedepot","category-geld","category-praxis-strategien","category-riester","category-vorsorge"],"acf":[],"yoast_head":"<title>Riester Rente umwandeln: 7 Gr\u00fcnde f\u00fcr eine \u00dcbertragung ins Altersvorsorgedepot<\/title>\n<meta name=\"description\" content=\"Riester-Vertrag ins Altersvorsorgedepot \u00fcbertragen: vier Wege, echte Wechselkosten und die F\u00e4lle, in denen sich der Umstieg nicht lohnt.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Riester Rente umwandeln: 7 Gr\u00fcnde f\u00fcr eine \u00dcbertragung ins Altersvorsorgedepot\" \/>\n<meta property=\"og:description\" content=\"Riester-Vertrag ins Altersvorsorgedepot \u00fcbertragen: vier Wege, echte Wechselkosten und die F\u00e4lle, in denen sich der Umstieg nicht lohnt.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/\" \/>\n<meta property=\"og:site_name\" content=\"Finanzen.net Ratgeber: Finanzwissen, das dich weiterbringt\" \/>\n<meta property=\"article:published_time\" content=\"2026-04-01T09:43:02+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-30T12:16:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1408\" \/>\n\t<meta property=\"og:image:height\" content=\"768\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Roland Kuse\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Geschrieben von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Roland Kuse\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"24\u00a0Minuten\" \/>","yoast_head_json":{"title":"Riester Rente umwandeln: 7 Gr\u00fcnde f\u00fcr eine \u00dcbertragung ins Altersvorsorgedepot","description":"Riester-Vertrag ins Altersvorsorgedepot \u00fcbertragen: vier Wege, echte Wechselkosten und die F\u00e4lle, in denen sich der Umstieg nicht lohnt.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/","og_locale":"de_DE","og_type":"article","og_title":"Riester Rente umwandeln: 7 Gr\u00fcnde f\u00fcr eine \u00dcbertragung ins Altersvorsorgedepot","og_description":"Riester-Vertrag ins Altersvorsorgedepot \u00fcbertragen: vier Wege, echte Wechselkosten und die F\u00e4lle, in denen sich der Umstieg nicht lohnt.","og_url":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/","og_site_name":"Finanzen.net Ratgeber: Finanzwissen, das dich weiterbringt","article_published_time":"2026-04-01T09:43:02+00:00","article_modified_time":"2026-09-30T12:16:55+00:00","og_image":[{"width":1408,"height":768,"url":"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln.png","type":"image\/png"}],"author":"Roland Kuse","twitter_card":"summary_large_image","twitter_misc":{"Geschrieben von":"Roland Kuse","Gesch\u00e4tzte Lesezeit":"24\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/#article","isPartOf":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/"},"author":{"name":"Roland Kuse","@id":"https:\/\/www.finanzen.net\/ratgeber\/#\/schema\/person\/751e702863ee767bd02fc5016b3d10e6"},"headline":"Riester Rente umwandeln","datePublished":"2026-04-01T09:43:02+00:00","dateModified":"2026-09-30T12:16:55+00:00","mainEntityOfPage":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/"},"wordCount":4699,"image":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/#primaryimage"},"thumbnailUrl":"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln.png","articleSection":["Altersvorsorgedepot","Geld","Praxis &amp; Strategien","Riester","Vorsorge"],"inLanguage":"de"},{"@type":["WebPage","ItemPage"],"@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/","url":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/","name":"Riester Rente umwandeln: 7 Gr\u00fcnde f\u00fcr eine \u00dcbertragung ins Altersvorsorgedepot","isPartOf":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/#primaryimage"},"image":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/#primaryimage"},"thumbnailUrl":"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln.png","datePublished":"2026-04-01T09:43:02+00:00","dateModified":"2026-09-30T12:16:55+00:00","author":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/#\/schema\/person\/751e702863ee767bd02fc5016b3d10e6"},"description":"Riester-Vertrag ins Altersvorsorgedepot \u00fcbertragen: vier Wege, echte Wechselkosten und die F\u00e4lle, in denen sich der Umstieg nicht lohnt.","breadcrumb":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/#primaryimage","url":"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln.png","contentUrl":"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/04\/riester-rente-umwandeln.png","width":1408,"height":768},{"@type":"BreadcrumbList","@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/www.finanzen.net\/ratgeber\/"},{"@type":"ListItem","position":2,"name":"Altersvorsorgedepot","item":"https:\/\/www.finanzen.net\/ratgeber\/.\/altersvorsorgedepot\/"},{"@type":"ListItem","position":3,"name":"Riester Rente umwandeln"}]},{"@type":"WebSite","@id":"https:\/\/www.finanzen.net\/ratgeber\/#website","url":"https:\/\/www.finanzen.net\/ratgeber\/","name":"Finanzen.net Ratgeber - Die Ganze Welt der Finanzen","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.finanzen.net\/ratgeber\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/www.finanzen.net\/ratgeber\/#\/schema\/person\/751e702863ee767bd02fc5016b3d10e6","name":"Roland Kuse","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2025\/10\/Roland_Kuse-1-150x150.jpg","url":"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2025\/10\/Roland_Kuse-1-150x150.jpg","contentUrl":"https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2025\/10\/Roland_Kuse-1-150x150.jpg","caption":"Roland Kuse"},"description":"Roland Kuse leitet den Finanzratgeber gemeinsam mit Volker Altvater. Mit \u00fcber 25 Jahren Erfahrung im digitalen Publishing verantwortet der Experte die inhaltliche Strategie und redaktionelle Qualit\u00e4t. Zudem treibt er die Entwicklung interaktiver Formate voran \u2013 vom Altersvorsorgedepot-Rechner bis hin zu anschaulichen Infografiken. Sein Ziel ist es, Finanzen verst\u00e4ndlich, fundiert und verl\u00e4sslich aufzubereiten.","sameAs":["https:\/\/www.linkedin.com\/in\/roland-kuse-959574103\/"],"url":"https:\/\/www.finanzen.net\/ratgeber\/author\/roland-kruse\/"}]}},"_links":{"self":[{"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/posts\/37275","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/comments?post=37275"}],"version-history":[{"count":34,"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/posts\/37275\/revisions"}],"predecessor-version":[{"id":43963,"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/posts\/37275\/revisions\/43963"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/media\/39231"}],"wp:attachment":[{"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/media?parent=37275"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/categories?post=37275"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/tags?post=37275"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}