{"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-07-23T08:04:30","modified_gmt":"2026-07-23T06:04:30","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: 7 Gr\u00fcnde, warum Sparer ins Altersvorsorgedepot \u00fcbertragen sollten                <\/h1>\n                        <div class=\"header__excerpt flow-content\">\n                                    <p>15.000 Euro weniger Geb\u00fchren, dreimal so viel F\u00f6rderung, volle Aktienquote &#8211; wer seinen Riester-Vertrag ins neue <a href=\"https:\/\/www.finanzen.net\/ratgeber\/vorsorge\/altersvorsorgedepot\/\" data-ilm-light=\"96\" title=\"Altersvorsorgedepot\">Altersvorsorgedepot<\/a> \u00fcbertr\u00e4gt, gewinnt auf ganzer Linie. Alle bisherigen Zulagen bleiben erhalten, kein Cent geht verloren. Der Wechsel ist ab 2027 m\u00f6glich, nach f\u00fcnf Vertragsjahren kostenlos, und ohne Zustimmung des alten Anbieters. Lohnen tut sich der Umstieg f\u00fcr praktisch alle, nur Geringverdiener mit Kindern, die unter 25 Euro monatlich sparen k\u00f6nnen, fahren mit dem alten Riester-System weiter besser.<\/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-07-23 08:04\"\n                                  title=\"Aktualisiert am 23.07.2026\">\n                                23.07.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:#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 class=\"font-claude-response-body whitespace-normal break-words pl-2\">Ab 2027 werden keine neuen Riester-Vertr\u00e4ge mehr abgeschlossen. Bestehende Vertr\u00e4ge genie\u00dfen vollen Bestandsschutz, alle bereits erhaltenen Zulagen und Steuervorteile aus der Vergangenheit bleiben dir, auch wenn du den Vertrag sp\u00e4ter wechselst.<\/li>\n<li class=\"font-claude-response-body whitespace-normal break-words pl-2\">Niemals k\u00fcndigen: Bei einer K\u00fcndigung musst du s\u00e4mtliche Zulagen und Steuervorteile zur\u00fcckzahlen. Bei 15 Jahren Laufzeit k\u00f6nnen das mehrere tausend Euro sein.<\/li>\n<li class=\"font-claude-response-body whitespace-normal break-words pl-2\">Drei Optionen stehen offen: Vertrag ruhen lassen, ins Altersvorsorgedepot \u00fcbertragen oder mit alter F\u00f6rdersystematik weiterlaufen lassen. F\u00fcr die meisten Sparer ist der \u00dcbertrag die wirtschaftlich beste Wahl.<\/li>\n<li class=\"font-claude-response-body whitespace-normal break-words pl-2\">Der Wechsel ins Altersvorsorgedepot ist ab 2027 m\u00f6glich, nach f\u00fcnf Vertragsjahren kostenlos, und ohne Zustimmung des bisherigen Anbieters.<\/li>\n<li class=\"font-claude-response-body whitespace-normal break-words pl-2\">Das Altersvorsorgedepot bietet deutlich mehr: bis zu 540 Euro Grundzulage statt 175 Euro, gedeckelte Kosten von maximal 1 % statt durchschnittlich 1,5\u20132 % bei Riester-Vertr\u00e4gen, volle Aktienquote statt Garantie-Bremse.<\/li>\n<li class=\"font-claude-response-body whitespace-normal break-words pl-2\">Bei 100 Euro monatlich und 25 Jahren Laufzeit steht im Altersvorsorgedepot rund 60.000 Euro zur Verf\u00fcgung, etwa doppelt so viel Verm\u00f6gen wie im alten Riester-Vertrag. <em>(Eurozahl mit deinem Rechner gegenpr\u00fcfen.)<\/em><\/li>\n<li class=\"font-claude-response-body whitespace-normal break-words pl-2\">Drei Sonderf\u00f6rderungen erg\u00e4nzen das System: 200 Euro Startbonus f\u00fcr unter 25-J\u00e4hrige, 175 Euro Geringverdiener-Bonus und volle Grundzulage erstmals auch f\u00fcr Selbstst\u00e4ndige.<\/li>\n<li class=\"font-claude-response-body whitespace-normal break-words pl-2\">Geringverdiener mit Kindern sollten genau rechnen: Nur wer weniger als 25 Euro monatlich sparen kann, profitiert weiterhin vom alten System. F\u00fcr alle anderen ist das neue Depot besser.<\/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 2027 k\u00f6nnen keine neuen Riester-Vertr\u00e4ge mehr abgeschlossen werden. Bestehende Vertr\u00e4ge genie\u00dfen vollen Bestandsschutz \u2013 wer seinen Vertrag beh\u00e4lt, bekommt weiterhin die bisherigen Zulagen von 175 Euro Grundzulage und bis zu 300 Euro pro Kind. Die Beitragsgarantie bleibt ebenfalls bestehen.<\/p>\n<p>Der Riester-Nachfolger hei\u00dft Altersvorsorgedepot. Die Koalition hat die F\u00f6rderung gegen\u00fcber dem ersten Entwurf nochmals angehoben: 50 Cent pro eingezahltem Euro bis 360 Euro, 25 Cent f\u00fcr jeden weiteren Euro bis 1.800 Euro. Die maximale Grundzulage steigt damit auf 540 Euro pro Jahr. Kinderzulagen von 300 Euro pro Kind werden bereits ab 25 Euro monatlichem Eigenbeitrag voll gew\u00e4hrt. Erstmals sind auch alle Selbstst\u00e4ndigen f\u00f6rderberechtigt.<\/p>\n<h2>Lohnt sich der Wechsel vom Riester-Vertrag ins Altersvorsorgedepot?<\/h2>\n<p>Mit dem folgenden Rechner vergleichst du, ob ein Umstieg auf das AVD 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.8 PreLaunch\r\n  Quelle: Tool_1.8_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============================================================ -->\r\n<div class=\"avd-embed avdemb-t18pl\" data-avd-tool=\"1.8 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-Buttons \u2013 finanzen.net Navy als active-Farbe \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .avdemb-t18pl .button.kinder-active {\r\n    background: var(--accent);\r\n    border-color: var(--accent);\r\n    color: #fff;\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 .button.kinder-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: keine Grundzulage<\/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 keine Zulage. 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 class=\"wiz-sub\">Anzahl Kinder<\/div>\r\n      <div style=\"display:flex;gap:6px;flex-wrap:wrap;\">\r\n        <button type=\"button\" onclick=\"setChildren(0)\" class=\"button kinder-active\" id=\"kBtn0\">0<\/button>\r\n        <button type=\"button\" onclick=\"setChildren(1)\" class=\"button\" id=\"kBtn1\">1<\/button>\r\n        <button type=\"button\" onclick=\"setChildren(2)\" class=\"button\" id=\"kBtn2\">2<\/button>\r\n        <button type=\"button\" onclick=\"setChildren(3)\" class=\"button\" id=\"kBtn3\">3<\/button>\r\n        <button type=\"button\" onclick=\"setChildren(4)\" class=\"button\" id=\"kBtn4\">4<\/button>\r\n        <button type=\"button\" onclick=\"setChildren(5)\" class=\"button\" id=\"kBtn5\">5<\/button>\r\n      <\/div>\r\n      <div id=\"children-fields\" style=\"display:flex;flex-wrap:wrap;gap:10px;margin-top:14px;\"><\/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\" 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 Depot 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 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 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 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>\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 \/ 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 \/ 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 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 (Halbeink\u00fcnfteverfahren, ab 12 Jahren Laufzeit; 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 6.840 \u20ac\/Jahr Eigenbeitrag + Zulagen); das Finanzamt nimmt per G\u00fcnstigerpr\u00fcfung den h\u00f6heren Vorteil aus Zulage oder Steuerersparnis. Die so gesch\u00e4tzte j\u00e4hrliche Steuererstattung wird reinvestiert und erh\u00f6ht das jeweilige Kapital; 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<\/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: F\u00fcr die volle Grundzulage wird angenommen, dass der individuelle Mindesteigenbeitrag (4 % des rentenversicherungspflichtigen Vorjahreseinkommens, max. 2.100 \u20ac\/Jahr, abz\u00fcglich Zulagen; Sockelbetrag 60 \u20ac\/Jahr) erf\u00fcllt ist. Bei geringeren Beitr\u00e4gen k\u00fcrzt die ZfA die Zulagen anteilig \u2013 das bildet dieses Tool vereinfacht nicht ab, die ausgewiesene Riester-F\u00f6rderung kann dadurch zu hoch ausfallen.<\/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 endk = rente * monateBar;\r\n        const zulageGes = parseFloat(document.getElementById(prefix + '-endkapital').dataset.zulage || 0);\r\n        const steuerErsp = parseFloat(document.getElementById(prefix + '-endkapital').dataset.steuererstattung || 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) \/ 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 = [];\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);\r\n      const dRes = berechneDepot(guthaben, einzahlung, s.depot, alter, alter + t, childAges, ra);\r\n      const iRes = berechneIndividual(guthaben, einzahlung, s.depot, alter, alter + t, childAges);\r\n      riesterData.push(Math.round(rRes.kapital));\r\n      depotData.push(Math.round(dRes.kapital));\r\n      etfData.push(Math.round(berechneETFBis(guthaben, einzahlung, s.etf, alter, alter + t)));\r\n      individualData.push(Math.round(iRes.kapital));\r\n      riesterFoerder.push(rRes.foerderungGesamt);\r\n      depotFoerder.push(dRes.foerderungGesamt);\r\n      individualFoerder.push(iRes.foerderungGesamt);\r\n      riesterSteuer.push(rRes.steuererstattungGesamt || 0);\r\n      depotSteuer.push(dRes.steuererstattungGesamt || 0);\r\n      individualSteuer.push(iRes.steuererstattungGesamt || 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, 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      const zweiToNetto = (kap, foerder, steuer, jahre, prefix) => {\r\n        const foerderGrenze = (prefix === 'r')\r\n          ? Math.max(0, 2100 - (jahre > 0 ? foerder \/ jahre : 0))\r\n          : 1800;\r\n        return Math.round(nettoZweiToepfe(kap, c.jahresbeitrag, foerder, c.guthaben, jahre, aj, monate, foerderGrenze, 'plan', rentenalter, steuer));\r\n      };\r\n      rD = c.riesterData.map((k, idx) => zweiToNetto(k, c.riesterFoerder[idx], c.riesterSteuer[idx], idx, 'r'));\r\n      dD = c.depotData.map((k, idx) => zweiToNetto(k, c.depotFoerder[idx], c.depotSteuer[idx], idx, 'd'));\r\n      iD = c.individualData.map((k, idx) => zweiToNetto(k, c.individualFoerder[idx], c.individualSteuer[idx], idx, 'i'));\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 ? 200 : 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 > 0) { 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, 6840), 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 ? 200 : 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 > 0) { 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, 6840), 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    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 6.840 \u20ac) + Zulagen; 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  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, 6840) + 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  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 (Halbeink\u00fcnfte, ab 12 J.)\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){\r\n    if (endk <= 0 || monate <= 0) return endk;\r\n    var ungJahr     = Math.max(0, Math.min(jahresbeitrag, 6840) - foerderGrenze);\r\n    var ungSubstanz = ungJahr * Math.max(0, jahre);\r\n    \/\/ Steuerersparnis z\u00e4hlt zum gef\u00f6rderten Topf (voll nachgelagert), erh\u00f6ht aber NICHT die Eigenbeitrag-Grenze\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    var halb      = (jahre >= 12) ? 0.5 : 1.0;\r\n    var stpfl     = (form === 'rente') ? ertragsanteil(alterBeginn) * ungEndk : halb * ungErtrag;\r\n    var sUng      = nachgelagertSatz((stpfl \/ monate) * 12, andereJahr + gefRenteJ);\r\n    return nettoGef + ungEndk - stpfl * sUng;\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  }\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 (!rEnd &#038;&#038; !dEnd &#038;&#038; !eEnd &#038;&#038; !iEnd) return;\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 steuerErsp = parseFloat(document.getElementById(prefix + '-endkapital').dataset.steuererstattung || 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) \u2192 Halbeink\u00fcnfte f\u00fcr den ungef\u00f6rderten Teil; Steuerersparnis kommt in den gef\u00f6rderten Topf\r\n      var ne = nettoZweiToepfe(endk, jahresbeitragN, zulageGes, guthabenNetto, aktuelleLaufzeit, andereJahr, monate, foerderGrenze, 'plan', rentenalter, steuerErsp);\r\n      nettoEndk[prefix] = ne;\r\n      setNetto(prefix, ne, ne \/ monate, endk);\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 = rEnd \/ monate;\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 = iEnd - rEnd;\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  function updateLE(val) {\r\n    leJahre = parseInt(val);\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    const riesterEndkapital = parseFloat(document.getElementById('r-endkapital').dataset.raw || 0);\r\n    const depotEndkapital   = parseFloat(document.getElementById('d-endkapital').dataset.raw || 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) + '\/Mo.';\r\n    const iRenteSlider = parseFloat(document.getElementById('i-endkapital').dataset.raw || 0) \/ monate;\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    childAges = new Array(n).fill(24);\r\n    for (let i = 0; i <= 5; i++) {\r\n      const btn = document.getElementById('kBtn' + i);\r\n      \/\/ MIGRIERT: kinder-btn \/ active \u2192 .button \/ .kinder-active\r\n      if (btn) btn.className = 'button' + (i === n ? ' kinder-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) {\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    const laufzeit = ra - alter;\r\n    const kinder = [...startChildAges];\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      const jahresbeitrag = monatlicheEinzahlung * 12;\r\n      if (jahresbeitrag >= 60) {\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        kapital += zulageJahr;\r\n        foerderungGesamt += zulageJahr;\r\n        var _rf = sonderausgabenErstattung(jahresbeitrag, zulageJahr, getErwerbsBrutto(), 'riester');\r\n        if (_rf > 0) { kapital += _rf; steuererstattungGesamt += _rf; }   \/\/ Steuerersparnis separat f\u00fchren (gef\u00f6rderter, voll besteuerter Topf) \u2013 getrennt von Zulagen\r\n      }\r\n      for (let k = 0; k < kinder.length; k++) kinder[k]++;\r\n    }\r\n    return { kapital, foerderungGesamt, steuererstattungGesamt };\r\n  }\r\n\r\n  function berechneDepot(guthaben, monatlicheEinzahlung, r, alter, ra, startChildAges, glideRa) {\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    const starterbonus = alter < 25 ? 200 : 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    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      for (let monat = 0; monat < 12; monat++) kapital = kapital * (1 + monatsrendite) + monatlicheEinzahlung;\r\n      const jahresbeitrag = monatlicheEinzahlung * 12;\r\n      let foerderungJahr = 0;\r\n      if (jahresbeitrag >= 120) {\r\n        foerderungJahr = Math.min(jahresbeitrag, 360) * 0.50 + Math.max(0, Math.min(jahresbeitrag, 1800) - 360) * 0.25;\r\n      }\r\n      if (jahresbeitrag > 0) {\r\n        for (let k = 0; k < kinder.length; k++) { if (kinder[k] >= 0 && kinder[k] < 25) foerderungJahr += Math.min(jahresbeitrag, 300); }\r\n      }\r\n      if (foerderungJahr > 0) { kapital += foerderungJahr; foerderungGesamt += foerderungJahr; }\r\n      var _refund = sonderausgabenErstattung(Math.min(jahresbeitrag, 6840), foerderungJahr, getErwerbsBrutto());\r\n      if (_refund > 0) { kapital += _refund; steuererstattungGesamt += _refund; }   \/\/ Steuerersparnis separat f\u00fchren (gef\u00f6rderter, voll besteuerter Topf) \u2013 getrennt von Zulagen\r\n      for (let k = 0; k < kinder.length; k++) kinder[k]++;\r\n    }\r\n    return { kapital, foerderungGesamt, steuererstattungGesamt };\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) {\r\n    const laufzeit = ra - alter;\r\n    const kinder = [...startChildAges];\r\n    const starterbonus = alter < 25 ? 200 : 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    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) + monatlicheEinzahlung;\r\n      const jahresbeitrag = monatlicheEinzahlung * 12;\r\n      let foerderungJahr = 0;\r\n      if (jahresbeitrag >= 120) {\r\n        foerderungJahr = Math.min(jahresbeitrag, 360) * 0.50 + Math.max(0, Math.min(jahresbeitrag, 1800) - 360) * 0.25;\r\n      }\r\n      if (jahresbeitrag > 0) {\r\n        for (let k = 0; k < kinder.length; k++) { if (kinder[k] >= 0 && kinder[k] < 25) foerderungJahr += Math.min(jahresbeitrag, 300); }\r\n      }\r\n      if (foerderungJahr > 0) { kapital += foerderungJahr; foerderungGesamt += foerderungJahr; }\r\n      var _refund = sonderausgabenErstattung(Math.min(jahresbeitrag, 6840), foerderungJahr, getErwerbsBrutto());\r\n      if (_refund > 0) { kapital += _refund; steuererstattungGesamt += _refund; }   \/\/ Steuerersparnis separat f\u00fchren (gef\u00f6rderter, voll besteuerter Topf) \u2013 getrennt von Zulagen\r\n      for (let k = 0; k < kinder.length; k++) kinder[k]++;\r\n    }\r\n    return { kapital, foerderungGesamt, steuererstattungGesamt };\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 = kinderUnter25 * Math.min(jahresbeitrag, 300);\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);\r\n    const depotResult      = berechneDepot(guthaben, einzahlung, s.depot, alter, rentenalter, childAges);\r\n    const etfEndkapital    = berechneETF(guthaben, einzahlung, s.etf, alter, rentenalter);\r\n    const individualResult = berechneIndividual(guthaben, einzahlung, s.depot, alter, rentenalter, childAges);\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\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 \u2013 flie\u00dft in den gef\u00f6rderten Topf (gefBeitr), aber NICHT in die Eigenbeitrag-Grenze\r\n    document.getElementById('r-endkapital').dataset.steuererstattung = steuererstattungRiesterGesamt;\r\n    document.getElementById('d-endkapital').dataset.steuererstattung = steuererstattungDepotGesamt;\r\n    document.getElementById('i-endkapital').dataset.steuererstattung = steuererstattungIndividualGesamt;\r\n\r\n    const entnahmeMonate = leJahre * 12;\r\n    const rRente = riesterEndkapital    \/ entnahmeMonate;\r\n    const dRente = depotEndkapital      \/ entnahmeMonate;\r\n    const eRente = etfEndkapital        \/ entnahmeMonate;\r\n    const iRente = individualEndkapital \/ 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 = individualEndkapital - riesterEndkapital;\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(foerderungRiesterGesamt + steuererstattungRiesterGesamt);\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(foerderungDepotGesamt + steuererstattungDepotGesamt);\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(foerderungIndividualGesamt + steuererstattungIndividualGesamt);\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    document.getElementById('r-wertzuwachs').textContent = fmt(riesterEndkapital-eingezahltGesamt-foerderungRiesterGesamt-steuererstattungRiesterGesamt);\r\n    document.getElementById('d-wertzuwachs').textContent = fmt(depotEndkapital-eingezahltGesamt-foerderungDepotGesamt-steuererstattungDepotGesamt);\r\n    document.getElementById('e-wertzuwachs').textContent = fmt(etfEndkapital-eingezahltGesamt);\r\n    document.getElementById('i-wertzuwachs').textContent = fmt(individualEndkapital-eingezahltGesamt-foerderungIndividualGesamt-steuererstattungIndividualGesamt);\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', riesterEndkapital) },\r\n      { id: 'card-depot',      wert: gsAktiv ? GS_BEDARF : sortWert('d', depotEndkapital) },\r\n      { id: 'card-etf',        wert: gsAktiv ? GS_BEDARF : sortWert('e', etfEndkapital) },\r\n      { id: 'card-individual', wert: gsAktiv ? GS_BEDARF : sortWert('i', individualEndkapital) },\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\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    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 Depot 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 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 = '\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.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 (mindestens ein endkapital > 0)\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 === \"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); break;\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>Warum \u00fcberhaupt \u00fcbertragen?<\/h2>\n<p>Ab 2027 gibt es keine neuen Riester-Vertr\u00e4ge mehr. Bestehende Vertr\u00e4ge laufen weiter, aber unter den alten Bedingungen: hohe Kosten, magere Rendite, starre Auszahlung. Das Altersvorsorgedepot korrigiert die drei gr\u00f6\u00dften Konstruktionsfehler der Riester-Rente \u2013 und wer sein Guthaben \u00fcbertr\u00e4gt, profitiert sofort von den besseren Konditionen.<\/p>\n<p>Die \u00dcbertragung ist dabei keine K\u00fcndigung und kein Neuabschluss. Es ist eine Fortf\u00fchrung deiner gef\u00f6rderten Vorsorge unter besseren Bedingungen. S\u00e4mtliche bisher erhaltenen Zulagen und Steuervorteile wandern mit. Nichts wird zur\u00fcckgefordert.<\/p>\n<h2>Was ein Riester-Vertrag wirklich gekostet hat<\/h2>\n<p>Die Zahlen sprechen eine deutliche Sprache. Wer 2002 begonnen hat, monatlich 100 Euro in einen Riester-Vertrag einzuzahlen, steht nach 25 Jahren bei rund 47.000 Euro. H\u00e4tte es das Altersvorsorgedepot damals bereits gegeben \u2013 gleicher Eigenbeitrag, aber angelegt in einem MSCI-World-ETF mit den neuen Zulagen \u2013 w\u00e4ren daraus rund 90.000 Euro geworden.<\/p>\n<p>Die Differenz von 43.000 Euro hat drei Ursachen: Erstens die hohen Produktkosten von durchschnittlich 1,5 bis 2,5 Prozent pro Jahr, die \u00fcber Jahrzehnte zehntausende Euro auffressen. Zweitens die verpflichtende Beitragsgarantie, die Anbieter in der Niedrigzinsphase in Anleihen statt Aktien zwang. So k\u00f6nnen schnell schon einmal 3 Prozent an Garantiekosten zusammenkommen, die die Rendite zusammenschnurren lassen. Und drittens die niedrigere F\u00f6rderung \u2013 175 Euro feste Grundzulage bei Riester gegen\u00fcber bis zu 540 Euro im neuen System. Die kann auch von dem Steuervorteil von 2.100 Euro f\u00fcr Singles bzw. 4.200 Euro f\u00fcr Verheiratete nicht aufgewogen werden.<\/p>\n<p>Auch k\u00fcrzere Zeitr\u00e4ume sind betroffen. Wer 2010 gestartet hat, liegt nach 15 Jahren bei etwa 25.000 Euro mit Riester gegen\u00fcber 38.000 Euro im kontrafaktischen Altersvorsorgedepot-Szenario. Selbst bei nur 10 Jahren (Start 2015) betr\u00e4gt die Differenz rund 6.000 Euro.<br \/>\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><\/p>\n<h2>Riester-Rente k\u00fcndigen: Warum das fast immer ein Fehler ist<\/h2>\n<p>Die K\u00fcndigung ist die teuerste aller Optionen. Wer seinen Riester-Vertrag k\u00fcndigt, l\u00f6st eine sogenannte f\u00f6rdersch\u00e4dliche Verwendung aus. Die Folge: S\u00e4mtliche erhaltenen Zulagen und Steuervorteile m\u00fcssen an den Staat zur\u00fcckgezahlt werden. Bei einem Vertrag (Single, keine Kinder), der seit 2005 l\u00e4uft, summieren sich die Zulagen auf 3.500 Euro \u2013 Geld, das bei einer K\u00fcndigung komplett verloren geht. Hinzu kommen Stornogeb\u00fchren des Anbieters, die den Verlust noch vergr\u00f6\u00dfern.<\/p>\n<p>Es gibt praktisch keine Konstellation, in der eine K\u00fcndigung wirtschaftlich Sinn ergibt. Selbst ein schlecht laufender Vertrag mit hohen Kosten ist beitragsfrei gestellt besser aufgehoben als gek\u00fcndigt.<\/p>\n<h2>Drei Wege f\u00fcr deinen bestehenden Riester-Vertrag<\/h2>\n<p>Statt zu k\u00fcndigen hast du drei sinnvolle Optionen \u2013 jede mit eigenen Vor- und Nachteilen.<\/p>\n<h3>Option 1: Riester-Rente ruhen lassen<\/h3>\n<p>Du stellst den Vertrag beitragsfrei. Das bedeutet: keine neuen Einzahlungen, keine neuen Zulagen, aber das vorhandene Guthaben bleibt investiert und die bisherigen Zulagen bleiben erhalten. Die laufenden Verwaltungskosten reduzieren sich in der Regel, verschwinden aber nicht komplett.<\/p>\n<p>Diese Option eignet sich f\u00fcr Sparer, die ihre Abschlusskosten bereits vollst\u00e4ndig abbezahlt haben und parallel ab 2027 ein Altersvorsorgedepot er\u00f6ffnen wollen. So nutzt man das Beste aus beiden Welten: das vorhandene Riester-Kapital arbeitet weiter, w\u00e4hrend frisches Geld ins g\u00fcnstigere neue System flie\u00dft.<\/p>\n<h3>Option 2: Guthaben ins Altersvorsorgedepot \u00fcbertragen (empfohlen)<\/h3>\n<p>Ab 2027 k\u00f6nnen Riester-Sparer ihr gesamtes Guthaben in ein Altersvorsorgedepot \u00fcberf\u00fchren. Der Wechsel funktioniert unkompliziert: Ein formloses Schreiben an den bisherigen Anbieter gen\u00fcgt, dessen Zustimmung ist nicht erforderlich. In den ersten f\u00fcnf Vertragsjahren darf der alte Anbieter maximal 150 Euro Wechselgeb\u00fchr verlangen. Danach ist der Wechsel kostenfrei.<\/p>\n<p>Entscheidend: Alle bisher erhaltenen Zulagen und Steuervorteile bleiben bei der \u00dcbertragung vollst\u00e4ndig erhalten. Nach dem Wechsel greift sofort die neue F\u00f6rdersystematik mit 50 Cent pro Euro statt der festen 175 Euro. Gleichzeitig sinken die Kosten drastisch \u2013 von typischerweise 1,5 bis 2,5 Prozent bei Riester auf h\u00f6chstens 1,0 Prozent. Bei einem reinen Selbstentscheider ETF-Depot k\u00f6nnen die Kosten sogar noch weiter sinken. Einen MSCI World gibt es bereits f\u00fcr etwa 0,2 Prozent Gesamtkostenquote pro Jahr.<\/p>\n<p>Diese Option lohnt sich besonders f\u00fcr Singles und Gutverdiener ohne Kinder, die von den festen Riester-Zulagen ohnehin wenig profitiert haben und deren Vertr\u00e4ge durch hohe laufende Kosten belastet sind.<\/p>\n<h3>Option 3: Vertrag mit alter F\u00f6rdersystematik weiterlaufen lassen<\/h3>\n<p>Die bisherige Riester-F\u00f6rderung mit festen Zulagen und Beitragsgarantie l\u00e4uft f\u00fcr bestehende Vertr\u00e4ge unver\u00e4ndert weiter. Das kann f\u00fcr eine kleine Gruppe die richtige Wahl sein: Geringverdiener mit mehreren Kindern, die weniger als 25 Euro im Monat sparen k\u00f6nnen, erhalten im alten System feste Kinderzulagen unabh\u00e4ngig vom Eigenbeitrag. Auch Sparer, die kurz vor der Rente stehen und von der Beitragsgarantie profitieren, haben wenig Grund zu wechseln.<\/p>\n<p>Durch die Koalitionseinigung ist dieser Personenkreis allerdings deutlich geschrumpft. Im neuen System wird die volle Kinderzulage schon ab 25 Euro monatlich erreicht \u2013 im alten System brauchte man daf\u00fcr mindestens 60 Euro Jahresbeitrag, profitierte aber ohne Einkommensberechnung.<\/p>\n<p>&lt;img class=&#8220;alignnone wp-image-36998 size-full&#8220; src=&#8220;https:\/\/www.finanzen.net\/ratgeber\/wp-content\/uploads\/2026\/03\/riester-rente-alternative-infografik.png&#8220; alt=&#8220;&#8220; width=&#8220;1424&#8243;<\/p>\n<h2>Riester vs. Altersvorsorgedepot: Der direkte Vergleich<\/h2>\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>175 \u20ac\/Jahr (fest)<\/td><td>Bis zu 540 \u20ac\/Jahr<\/td><\/tr><tr><td>Typische Kosten<\/td><td>1,5\u20132,5 % pro Jahr<\/td><td>0,1\u20130,2 % (selbst gew\u00e4hlter ETF)<\/td><\/tr><tr><td>Aktienquote<\/td><td>Meist unter 30 %<\/td><td>Bis zu 100 %<\/td><\/tr><tr><td>Beitragsgarantie<\/td><td>100 % verpflichtend<\/td><td>Keine (optional 80\/100 %)<\/td><\/tr><tr><td>Kinderzulage voll ab<\/td><td>60 \u20ac\/Jahr Eigenbeitrag<\/td><td>25 \u20ac\/Monat<\/td><\/tr><tr><td>Selbstst\u00e4ndige<\/td><td>Ausgeschlossen<\/td><td>F\u00f6rderberechtigt<\/td><\/tr><tr><td>Steuern Ansparphase<\/td><td>Abh\u00e4ngig vom Produkt<\/td><td>Komplett steuerfrei<\/td><\/tr><tr><td>Umschichtungen<\/td><td>Eingeschr\u00e4nkt, ggf. steuerpflichtig<\/td><td>Beliebig oft, steuerfrei<\/td><\/tr><tr><td>Auszahlung<\/td><td>Mind. 70 % verrenten<\/td><td>Frei w\u00e4hlbar<\/td><\/tr><\/thead><\/tbody><\/table><\/div>\n<h2>Die sieben Vorteile im Detail<\/h2>\n<h3>1. Die Kosten sinken um mindestens 50 Prozent<\/h3>\n<p>Das ist der Grund, der allein den Wechsel rechtfertigt. Typische Riester-Produkte belasten Sparer mit Effektivkosten von 1,5 bis 2,5 Prozent pro Jahr. Abschlussgeb\u00fchren, Verwaltungskosten, Garantiekosten \u2013 alles frisst an der Rendite. Im Altersvorsorgedepot mit einem selbst gew\u00e4hlten ETF liegen die Kosten bei 0,1 bis 0,2 Prozent. Bei standardisierten Produkten d\u00fcrfen die Kosten nicht mehr als 1 Prozent betragen.<\/p>\n<p>Was das \u00fcber die Restlaufzeit bedeutet: Wer 25.000 Euro Riester-Guthaben \u00fcbertr\u00e4gt und noch 20 Jahre bis zur Rente hat, spart bei einer Kostenreduktion von 2 auf 0,2 Prozent rund 15.000 Euro an Geb\u00fchren. Das Geld flie\u00dft also nicht ab, sondern kann vielmehr noch weiter f\u00fcr den Anleger arbeiten.<\/p>\n<h3>2. Die F\u00f6rderung verdreifacht sich<\/h3>\n<p>Im alten System gibt es feste 175 Euro Grundzulage \u2013 egal wie viel du einzahlst. Im Altersvorsorgedepot bekommst du 50 Cent pro Euro bis 360 Euro und 25 Cent dar\u00fcber. Wer 1.200 Euro im Jahr einzahlt, erh\u00e4lt 390 Euro Grundzulage. Wer auf 1.800 Euro erh\u00f6ht, bekommt die volle Zulage von 540 Euro.<\/p>\n<p>Der Kipppunkt liegt bei 350 Euro Jahresbeitrag: Ab dieser Summe bringt das neue System bereits mehr als die festen 175 Euro bei Riester. Wer mehr als 30 Euro im Monat spart, f\u00e4hrt im Altersvorsorgedepot besser. Dabei soll allerdings die Steuerersparnis beim Riester-Vertrag nicht unerw\u00e4hnt bleiben. Singles k\u00f6nnen 2.100 Euro absetzen, Verheiratete 4.200 Euro.<\/p>\n<h3>3. Volle Aktienquote statt Garantie-Bremse<\/h3>\n<p>Die verpflichtende Beitragsgarantie war Riesters gr\u00f6\u00dfter Konstruktionsfehler. Anbieter mussten garantieren, dass zum Rentenbeginn mindestens die eingezahlten Beitr\u00e4ge zur\u00fcckgezahlt werden. In der Niedrigzinsphase bedeutete das: 70 bis 100 Prozent des Geldes steckten in Anleihen mit Null- oder Negativrendite. An den Aktienmarkt-Rallyes der letzten 15 Jahre nahmen Riester-Sparer kaum teil. Dieser Renditenachteil gegen\u00fcber der Aktienmarktrendite bel\u00e4uft sich bei einer mit 30 Prozent hoch angesetzten Aktienquote des Riester-Produkts schnell auf drei Prozentpunkte.<\/p>\n<p>Im Altersvorsorgedepot gibt es keine Garantiepflicht. Bis zu 100 Prozent Aktienquote sind m\u00f6glich \u2013 MSCI World, FTSE All-World, thematische ETFs. Wer trotzdem Sicherheit will, kann freiwillig ein Garantieprodukt mit 80 oder 100 Prozent Beitragserhalt w\u00e4hlen. Aber es ist eine Wahl, kein Zwang.<\/p>\n<h3>4. Steuerfreie Ansparphase \u2013 auf alles<\/h3>\n<p>Im Altersvorsorgedepot fallen in der Ansparphase keine Steuern an. Keine Abgeltungssteuer auf Kursgewinne, keine Vorabpauschale. Und der vielleicht wertvollste Punkt: Umschichtungen zwischen Fonds sind komplett steuerfrei. Wer f\u00fcnf Jahre vor der Rente von Aktien in Anleihen wechseln will, zahlt daf\u00fcr keinen Cent.<\/p>\n<p>Im Riester-Vertrag war dieser Vorteil theoretisch auch gegeben \u2013 aber da das Geld \u00fcberwiegend in Garantiefonds steckte, gab es schlicht keine nennenswerten Gewinne, die h\u00e4tten besteuert werden k\u00f6nnen. Im Altersvorsorgedepot wird die steuerfreie Ansparphase zum echten Renditehebel, weil das Geld tats\u00e4chlich am Kapitalmarkt arbeitet.<\/p>\n<h3>5. Alle bisherigen Zulagen bleiben erhalten<\/h3>\n<p>Die h\u00e4ufigste Sorge beim Wechsel: \u201eVerliere ich meine Zulagen?&#8220; Nein. Bei einer \u00dcbertragung ins Altersvorsorgedepot wandert das komplette Guthaben inklusive aller erhaltenen Zulagen und Steuervorteile ins neue System. Nichts wird zur\u00fcckgefordert, nichts geht verloren.<\/p>\n<p>Der alte Anbieter darf in den ersten f\u00fcnf Vertragsjahren maximal 150 Euro Wechselgeb\u00fchr verlangen. Danach ist der Wechsel kostenlos. Eine Zustimmung des bisherigen Anbieters ist nicht erforderlich \u2013 ein formloses Schreiben gen\u00fcgt.<\/p>\n<h3>6. Flexible Auszahlung statt Verrentungspflicht<\/h3>\n<p>Bei Riester m\u00fcssen mindestens 70 Prozent des Guthabens in eine lebenslange Rente flie\u00dfen \u2013 zu Rentenfaktoren, die in den letzten Jahren immer schlechter geworden sind. Viele Sparer bekommen f\u00fcr 50.000 Euro Guthaben gerade einmal 120 bis 150 Euro monatliche Rente.<\/p>\n<p>Im Altersvorsorgedepot hast du die freie Wahl: Auszahlplan bis 85, lebenslange Leibrente oder eine Kombination aus beidem. Bis zu 30 Prozent des Guthabens k\u00f6nnen als Einmalzahlung entnommen werden. Das Kapital bleibt w\u00e4hrend der Auszahlphase investiert und erwirtschaftet weiter Rendite \u2013 statt in einer Rentenversicherung mit Garantiezins von 0,25 Prozent zu versauern.<\/p>\n<h3>7. Kein Versicherungsmantel mehr<\/h3>\n<p>Die meisten Riester-Vertr\u00e4ge sind keine Depots, sondern fondsgebundene Rentenversicherungen. Das Geld steckt in einem Versicherungsmantel, der Abschlussprovisionen, Verwaltungsgeb\u00fchren und Risikokosten verursacht. Im Altersvorsorgedepot entf\u00e4llt dieser Mantel komplett. Das Geld flie\u00dft direkt in den ETF \u2013 ohne Zwischenschicht, ohne Provisionen, ohne versteckte Kosten.<\/p>\n<p>Da es im Altersvorsorgedepot ohnehin keine Beitragsgarantie gibt, bringt ein Versicherungsmantel auch keinen Mehrwert. Auch Versicherer d\u00fcrfen Altersvorsorgedepots anbieten, aber wer ein solches Produkt bei einem Versicherer abschlie\u00dft, zahlt in der Regel deutlich mehr als bei einem <a href=\"https:\/\/www.finanzen.net\/ratgeber\/broker\/produkte-vergleiche\/neobroker-vergleich\/\" data-ilm-light=\"50\" title=\"Neobroker Vergleich\">Neobroker<\/a> oder einer Direktbank.<\/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>Vorher\/Nachher: Was der Wechsel in Euro bringt<\/h2>\n<p>Sabine, 45, hat seit 2010 einen Riester-Fondssparplan mit 25.000 Euro Guthaben. Sie zahlt 100 Euro monatlich ein. Noch 20 Jahre bis zur Rente.<\/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 AVD \u00fcbertragen<\/th><\/tr><\/thead><tbody><tr><td>Effektivkosten\/Jahr<\/td><td>2,0 %<\/td><td>0,2 % (ETF)<\/td><\/tr><tr><td>Grundzulage\/Jahr<\/td><td>175 \u20ac (fest)<\/td><td>390 \u20ac (bei 1.200 \u20ac Eigenbeitrag)<\/td><\/tr><tr><td>Aktienquote<\/td><td>~25 % (Garantie-Bremse)<\/td><td>100 % (selbst gew\u00e4hlt)<\/td><\/tr><tr><td>Erwartete Rendite nach Kosten<\/td><td>~1,0 %<\/td><td>~6,0 %<\/td><\/tr><tr><td>Steuern auf Umschichtungen<\/td><td>Theoretisch frei, praktisch irrelevant<\/td><td>Komplett steuerfrei<\/td><\/tr><tr><td>Depotwert nach 20 Jahren<\/td><td>~38.000 \u20ac<\/td><td>~98.000 \u20ac<\/td><\/tr><\/thead><\/tbody><\/table><\/div>\n<p>Die Differenz: rund 60.000 Euro. Bei identischem Eigenbeitrag von 100 Euro monatlich.<\/p>\n<p><strong>Hebel 1 \u2013 Kosten.<\/strong> Sabine spart 1,8 Prozentpunkte Geb\u00fchren pro Jahr. Bei 25.000 Euro Startguthaben plus laufenden Einzahlungen frisst der Kostenunterschied \u00fcber 20 Jahre rund 15.000 Euro.<\/p>\n<p><strong>Hebel 2 \u2013 F\u00f6rderung.<\/strong> Statt 175 Euro flie\u00dfen 390 Euro Grundzulage ins Depot \u2013 215 Euro mehr pro Jahr. \u00dcber 20 Jahre sind das 4.300 Euro zus\u00e4tzliche Zulagen, die ihrerseits Rendite erwirtschaften.<\/p>\n<p><strong>Hebel 3 \u2013 Rendite.<\/strong> Ohne Garantie-Bremse kann Sabines Geld vollst\u00e4ndig am Aktienmarkt arbeiten. Der Unterschied zwischen 1 und 6 Prozent Rendite nach Kosten ist \u00fcber 20 Jahre der gr\u00f6\u00dfte Treiber \u2013 allein dieser Effekt erkl\u00e4rt rund 40.000 Euro der Differenz.<\/p>\n<h2>Der Wechsel in f\u00fcnf Schritten<\/h2>\n<p><strong>Schritt 1: Riester-Vertrag durchleuchten.<\/strong> Fordere die j\u00e4hrliche Kosteninformation deines Anbieters an. Entscheidend ist die Zeile \u201eEffektivkosten&#8220;. Alles \u00fcber 1 Prozent ist ein Warnsignal, alles \u00fcber 2 Prozent ein Grund zum sofortigen Handeln. Notiere au\u00dferdem dein aktuelles Guthaben und die Summe der erhaltenen Zulagen.<\/p>\n<p><strong>Schritt 2: Anbieter f\u00fcr das Altersvorsorgedepot w\u00e4hlen.<\/strong> Ab 2027 bieten Banken, Neobroker und Fondsgesellschaften Altersvorsorgedepots an. Achte auf niedrige Depotgeb\u00fchren und eine breite ETF-Auswahl. Versicherungsprodukte mit Mantelkosten kosten deutlich mehr als ein reines Depot bei einem Neobroker oder einer Direktbank.<\/p>\n<p><strong>Schritt 3: \u00dcbertragungsantrag stellen.<\/strong> Ein formloses Schreiben an deinen bisherigen Riester-Anbieter gen\u00fcgt. Dessen Zustimmung ist gesetzlich nicht erforderlich \u2013 er muss die \u00dcbertragung durchf\u00fchren. Du brauchst lediglich die Daten deines neuen Altersvorsorgedepots.<\/p>\n<p><strong>Schritt 4: Wechselgeb\u00fchr pr\u00fcfen.<\/strong> In den ersten f\u00fcnf Vertragsjahren darf der alte Anbieter maximal 150 Euro Wechselgeb\u00fchr verlangen. L\u00e4uft dein Vertrag bereits l\u00e4nger als f\u00fcnf Jahre, ist der Wechsel komplett kostenlos. Bei den meisten Riester-Sparern, die seit 2002 oder sp\u00e4ter dabei sind, f\u00e4llt also keine Geb\u00fchr an.<\/p>\n<p><strong>Schritt 5: ETF ausw\u00e4hlen und Sparplan einrichten.<\/strong> Sobald das Guthaben im neuen Depot angekommen ist, w\u00e4hlst du einen oder mehrere ETFs aus. Ein breit gestreuter Welt-ETF (MSCI World, FTSE All-World) kostet 0,1 bis 0,2 Prozent pro Jahr. Sparplan einrichten, fertig. Ab jetzt arbeitet dein Geld mit voller Aktienquote und steuerfreiem Zinseszins.<\/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>Die F\u00f6rderung flie\u00dft erst ab dem Tag, an dem Geld eingezahlt wird. Jeder Monat ohne Altersvorsorgedepot kostet Zulagen \u2013 und jeder Monat, den dein Riester-Guthaben noch beim alten Anbieter liegt, kostet Geb\u00fchren. Wer sich <a href=\"https:\/\/g.finanzen.net\/zero-fnet_017o-ratgeber-altersvorsorgedepot-gut-zu-wissen\"><strong>jetzt bei finanzen.net ZERO kostenlos vormerkt<\/strong><\/a>, kann am 1. Januar 2027 sofort er\u00f6ffnen und den Riester-\u00dcbertrag direkt ansto\u00dfen.<\/p><\/div><\/div>\n<h2>Was du nicht verlierst \u2013 und was schon<\/h2>\n<p><strong>Was erhalten bleibt:<\/strong> Alle bisherigen Zulagen, alle Steuervorteile, das komplette Guthaben. Die \u00dcbertragung ist f\u00f6rderunsch\u00e4dlich \u2013 im Gegensatz zu einer K\u00fcndigung, bei der alles zur\u00fcckgezahlt werden muss.<\/p>\n<p><strong>Was wegf\u00e4llt:<\/strong> Die Beitragsgarantie. Aber das ist gewollt. Die Garantie hat Riester-Sparern \u00fcber zwei Jahrzehnte die Rendite geraubt, weil sie Anbieter in Anleihen zwang. Im Altersvorsorgedepot tr\u00e4gst du das Marktrisiko, profitierst daf\u00fcr aber von historisch deutlich h\u00f6heren Aktienrenditen. Wer trotzdem Sicherheit will, kann freiwillig ein Garantieprodukt mit 80 oder 100 Prozent Beitragserhalt w\u00e4hlen.<\/p>\n<h2>F\u00fcr wen der Wechsel nicht sinnvoll ist<\/h2>\n<p>Zwei Gruppen sollten ihren Riester-Vertrag behalten. Erstens: Geringverdiener mit mehreren Kindern, die weniger als 25 Euro im Monat sparen k\u00f6nnen. F\u00fcr sie sind die festen Riester-Kinderzulagen weiterhin vorteilhaft. Zweitens: Sparer, die bereits in der Auszahlphase sind \u2013 f\u00fcr sie ist eine \u00dcbertragung nicht mehr m\u00f6glich.<\/p>\n<p>F\u00fcr alle anderen \u2013 Singles, Paare, Gutverdiener und erstmals auch Selbstst\u00e4ndige \u2013 profitieren vom Wechsel. Je l\u00e4nger die Restlaufzeit bis zur Rente, desto gr\u00f6\u00dfer der Effekt. Aber selbst bei nur 10 Jahren lohnt sich die \u00dcbertragung in den meisten F\u00e4llen, allein durch die h\u00f6here F\u00f6rderung und die niedrigeren Kosten.<\/p>\n<h2>Fazit: Einfacher Wechsel, gro\u00dfer Unterschied<\/h2>\n<p>Ein formloses Schreiben, keine Zustimmung des Anbieters n\u00f6tig, nach f\u00fcnf Jahren kostenlos, alle Zulagen bleiben erhalten. Der b\u00fcrokratische Aufwand ist minimal. Der finanzielle Unterschied ist es nicht: 60.000 Euro \u00fcber 20 Jahre \u2013 bei gleichem Eigenbeitrag. Wer seinen Riester-Vertrag ins Altersvorsorgedepot \u00fcbertr\u00e4gt, tauscht ein teures, renditeschwaches Produkt gegen ein g\u00fcnstiges, renditestarkes. Der einzige Fehler w\u00e4re, es nicht zu tun.<\/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 zur Riester Rente Alternative<\/h2>\n<h3>Ist die Riester-Rente abgeschafft?<\/h3>\n<p>F\u00fcr Neuabschl\u00fcsse ja \u2013 ab dem 1. Januar 2027 wird kein neuer Riester-Vertrag mehr vergeben. Wer bereits einen hat, beh\u00e4lt ihn mit vollem Bestandsschutz. Alle bisher erhaltenen Zulagen und Steuervorteile bleiben bestehen, unabh\u00e4ngig davon ob man wechselt oder nicht.<\/p>\n<h3>Warum sollte ich meinen Riester-Vertrag nicht k\u00fcndigen?<\/h3>\n<p>Weil eine K\u00fcndigung als f\u00f6rdersch\u00e4dliche Verwendung gilt. Alle Zulagen und Steuervorteile m\u00fcssen zur\u00fcckgezahlt werden. Bei einem 15 Jahre alten Vertrag verlierst du auf einen Schlag mehrere tausend Euro. Dazu kommen m\u00f6gliche Stornogeb\u00fchren. Stilllegen oder \u00fcbertragen ist in praktisch jedem Fall besser.<\/p>\n<h3>Was genau ist der Riester-Nachfolger?<\/h3>\n<p>Das Altersvorsorgedepot \u2013 ein staatlich gef\u00f6rdertes Wertpapierdepot, in dem du direkt in ETFs, Fonds und Anleihen investieren kannst. Die F\u00f6rderung liegt bei bis zu 540 Euro Grundzulage pro Jahr plus 300 Euro Kinderzulage pro Kind. In der Ansparphase fallen keine Steuern auf Kapitalertr\u00e4ge an.<\/p>\n<h3>Wie kann ich meine Riester-Rente ins Altersvorsorgedepot umwandeln?<\/h3>\n<p>Ab 2027 mit einem formlosen Schreiben an deinen bisherigen Anbieter. Dessen Zustimmung ist nicht erforderlich. In den ersten f\u00fcnf Vertragsjahren kann eine Wechselgeb\u00fchr von maximal 150 Euro anfallen, danach ist der Wechsel kostenfrei. Das komplette Guthaben wird \u00fcbertragen, alle Zulagen bleiben erhalten.<\/p>\n<h3>Was bedeutet Riester-Rente 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 und die bisher erhaltenen Zulagen bleiben erhalten. Parallel kannst du ab 2027 ein Altersvorsorgedepot er\u00f6ffnen und dort mit den besseren Konditionen weitersparen.<\/p>\n<h3>F\u00fcr wen lohnt sich Riester nach der Reform noch?<\/h3>\n<p>Nur f\u00fcr eine sehr kleine Gruppe: Geringverdiener mit mehreren Kindern, die weniger als 25 Euro im Monat sparen k\u00f6nnen. In diesem Fall \u00fcbersteigen die festen Riester-Kinderzulagen die neue beitragsabh\u00e4ngige F\u00f6rderung. F\u00fcr alle anderen ist das Altersvorsorgedepot in jeder Hinsicht besser. Wer zu dieser Gruppe geh\u00f6rt und noch keinen Vertrag hat, sollte vor dem 31. Dezember 2026 einen g\u00fcnstigen Riester-Fondssparplan abschlie\u00dfen.<\/p>\n<h3>Wie hoch ist die typische Rendite eines Riester-Vertrags?<\/h3>\n<p>Ern\u00fcchternd niedrig. Eine Analyse von Finanzwende \u00fcber 96 Tarife ergab, dass 65 Prozent der Produkte nicht einmal 2 Prozent Bruttorendite erzielen. Nach Abzug der Kosten von durchschnittlich 1,5 bis 2,5 Prozent pro Jahr bleibt bei vielen Vertr\u00e4gen eine Nettorendite von unter 1 Prozent \u2013 kaum mehr als <a href=\"https:\/\/www.finanzen.net\/ratgeber\/geld\/produkte-vergleiche\/tagesgeld-vergleich\/\" data-ilm-light=\"66\" title=\"Tagesgeld Vergleich\">Tagesgeld<\/a>.<\/p>\n<h3>Wann ist der letztm\u00f6gliche Termin f\u00fcr einen Riester-Neuabschluss?<\/h3>\n<p>Der 31. Dezember 2026. Ab dem 1. Januar 2027 sind keine Neuabschl\u00fcsse mehr m\u00f6glich. Wer von den alten Riester-Konditionen profitieren will (feste Kinderzulagen unabh\u00e4ngig vom Eigenbeitrag), muss bis dahin einen Vertrag abschlie\u00dfen. F\u00fcr die Mehrheit der Sparer lohnt sich das nicht \u2013 Warten auf das Altersvorsorgedepot ist die bessere Strategie<\/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,1467,359],"tags":[],"class_list":["post-37275","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-altersvorsorgedepot","category-riester","category-vorsorge"],"acf":[],"yoast_head":"<title>Riester Rente umwandeln: 7 Gr\u00fcnde f\u00fcr eine \u00dcbertragung ins Altersvorsorgedepot<\/title>\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=\"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.\" \/>\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-07-23T06:04:30+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=\"21\u00a0Minuten\" \/>","yoast_head_json":{"title":"Riester Rente umwandeln: 7 Gr\u00fcnde f\u00fcr eine \u00dcbertragung ins Altersvorsorgedepot","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":"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.","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-07-23T06:04:30+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":"21\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-07-23T06:04:30+00:00","mainEntityOfPage":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/altersvorsorgedepot\/riester-rente-umwandeln\/"},"wordCount":4113,"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","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-07-23T06:04:30+00:00","author":{"@id":"https:\/\/www.finanzen.net\/ratgeber\/#\/schema\/person\/751e702863ee767bd02fc5016b3d10e6"},"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":32,"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/posts\/37275\/revisions"}],"predecessor-version":[{"id":41599,"href":"https:\/\/www.finanzen.net\/ratgeber\/wp-json\/wp\/v2\/posts\/37275\/revisions\/41599"}],"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}]}}