@@ -0,0 +1,529 @@
<!DOCTYPE html>
< html lang = "de" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1, viewport-fit=cover" >
< meta name = "theme-color" content = "#0b3a54" >
< meta name = "apple-mobile-web-app-capable" content = "yes" >
< meta name = "apple-mobile-web-app-status-bar-style" content = "black-translucent" >
< meta name = "apple-mobile-web-app-title" content = "AIDA Drinks" >
< title > AIDA Getränkepaket – Break-even-Rechner< / title >
< link rel = "icon" href = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%230b3a54'/%3E%3Cpath d='M15 19h34l-14 16v9h6v4H23v-4h6v-9z' fill='%23e2673d'/%3E%3Ccircle cx='42' cy='15' r='3' fill='%23eaf1f5'/%3E%3Cpath d='M12 50c5 0 5-3 10-3s5 3 10 3 5-3 10-3 5 3 10 3' fill='none' stroke='%2312556f' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E" >
< link rel = "apple-touch-icon" href = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%230b3a54'/%3E%3Cpath d='M15 19h34l-14 16v9h6v4H23v-4h6v-9z' fill='%23e2673d'/%3E%3Ccircle cx='42' cy='15' r='3' fill='%23eaf1f5'/%3E%3C/svg%3E" >
< style >
: root {
--sea : #0b3a54 ; --sea2 : #12556f ; --sky : #eaf1f5 ; --coral : #e2673d ; --coral2 : #c9542e ;
--red : #c2352a ; --green : #1f9257 ; --amber : #c0801e ; --ink : #151b1f ; --mut : #5f7480 ; --line : #dbe5eb ;
--card : #ffffff ; --bg : #edf2f5 ;
--sans : - apple-system , BlinkMacSystemFont , "Segoe UI" , Roboto , Helvetica , Arial , "Helvetica Neue" , sans-serif ;
--mono : ui-monospace , "SF Mono" , Menlo , Consolas , "Roboto Mono" , monospace ;
}
* { box-sizing : border-box }
html , body { margin : 0 }
body { font-family : var ( - - sans ) ; background : var ( - - bg ) ; color : var ( - - ink ) ; line-height : 1.45 ;
-webkit- text-size-adjust : 100 % ; -webkit- font-smoothing : antialiased }
@ keyframes fadeUp { from { opacity : 0 ; transform : translateY ( 6 px ) } to { opacity : 1 ; transform : none } }
@ keyframes grow { from { transform : scaleY ( 0 ) } to { transform : scaleY ( 1 ) } }
@ media ( prefers-reduced-motion : reduce ) { * { animation : none !important ; transition : none !important } }
. wrap { max-width : 640 px ; margin : 0 auto ; padding : 0 14 px 96 px }
header { background : linear-gradient ( 140 deg , var ( - - sea ) , var ( - - sea2 ) ) ; color : #fff ;
padding : calc ( 18 px + env ( safe - area - inset - top ) ) 16 px 16 px }
header . wrap { padding : 0 ; max-width : 612 px }
. brand { display : flex ; align-items : center ; gap : 12 px }
. brand svg { flex : none ; filter : drop-shadow ( 0 2 px 5 px rgba ( 0 , 0 , 0 , .28 ) ) }
h1 { font-size : 20 px ; margin : 0 ; letter-spacing : -.3 px ; font-weight : 700 ; line-height : 1.05 }
. sub { font-size : 12.5 px ; opacity : .82 ; margin : 6 px 0 0 ; max-width : 54 ch }
. pstamp { display : inline-flex ; align-items : center ; gap : 5 px ; margin-top : 9 px ; font-size : 11 px ;
background : rgba ( 255 , 255 , 255 , .14 ) ; padding : 3 px 9 px ; border-radius : 20 px }
. pstamp b { font-weight : 600 }
. card { background : var ( - - card ) ; border : 1 px solid var ( - - line ) ; border-radius : 16 px ; padding : 15 px ; margin : 14 px 0 ;
box-shadow : 0 1 px 2 px rgba ( 11 , 58 , 84 , .05 ) , 0 8 px 24 px -18 px rgba ( 11 , 58 , 84 , .35 ) ; animation : fadeUp .4 s ease both }
h2 { font-size : 11.5 px ; text-transform : uppercase ; letter-spacing : 1.2 px ; color : var ( - - sea2 ) ; margin : 0 0 11 px ; font-weight : 700 ;
display : flex ; justify-content : space-between ; align-items : center }
h2 . tag { font-size : 10.5 px ; letter-spacing : .3 px ; color : var ( - - mut ) ; text-transform : none ; font-weight : 500 }
label { font-size : 12 px ; color : var ( - - mut ) ; display : block ; margin : 0 0 5 px }
. row { display : flex ; gap : 10 px ; flex-wrap : wrap }
. row > div { flex : 1 ; min-width : 120 px }
input , select { width : 100 % ; font-size : 16 px ; padding : 9 px 10 px ; border : 1 px solid var ( - - line ) ; border-radius : 10 px ;
background : #fbfdff ; color : var ( - - ink ) ; font-family : inherit }
input : focus , select : focus { outline : 2 px solid var ( - - sea2 ) ; border-color : var ( - - sea2 ) }
. hint { font-size : 11.5 px ; color : var ( - - mut ) ; margin : 6 px 0 0 }
# status { border-radius : 18 px ; padding : 17 px ; color : #fff ; text-align : center ; margin : 14 px 0 ; transition : background .3 s }
# status . no { background : linear-gradient ( 140 deg , #9c352b , #c2352a ) }
# status . close { background : linear-gradient ( 140 deg , #b1701a , #c9821f ) }
# status . yes { background : linear-gradient ( 140 deg , #166b42 , #1f9257 ) }
# statusMain { font-size : 18 px ; font-weight : 700 ; margin : 0 0 4 px ; letter-spacing : -.2 px }
# statusSub { font-size : 13 px ; opacity : .95 ; margin : 0 }
. bignum { font-family : var ( - - mono ) ; font-size : 32 px ; font-weight : 700 ; line-height : 1.05 ; margin : 8 px 0 2 px ; letter-spacing : -1 px }
. bar { height : 14 px ; background : rgba ( 255 , 255 , 255 , .28 ) ; border-radius : 8 px ; overflow : hidden ; margin : 12 px 0 2 px }
# status . bar { background : rgba ( 255 , 255 , 255 , .25 ) }
. bar > span { display : block ; height : 100 % ; background : #fff ; width : 0 ; transition : width .35 s cubic-bezier ( .16 , 1 , .3 , 1 ) }
. today { border : 1 px solid var ( - - line ) ; border-radius : 14 px ; padding : 13 px ; background : linear-gradient ( 180 deg , #fff , #f7fafc ) }
. today . tbar { height : 12 px ; background : #e3edf2 ; border-radius : 7 px ; overflow : hidden ; margin : 9 px 0 8 px }
. today . tbar > span { display : block ; height : 100 % ; width : 0 ; background : linear-gradient ( 90 deg , var ( - - sea2 ) , var ( - - coral ) ) ; transition : width .35 s cubic-bezier ( .16 , 1 , .3 , 1 ) }
. today . done . tbar > span { background : linear-gradient ( 90 deg , var ( - - green ) , #40c584 ) }
. todayMsg { font-size : 13.5 px ; font-weight : 600 }
. todayMsg small { display : block ; font-weight : 400 ; color : var ( - - mut ) ; font-size : 12 px ; margin-top : 2 px }
. grid2 { display : grid ; grid-template-columns : 1 fr 1 fr ; gap : 10 px ; margin-top : 12 px }
. stat { background : var ( - - sky ) ; border-radius : 11 px ; padding : 11 px }
. stat b { display : block ; font-size : 19 px ; font-family : var ( - - mono ) ; letter-spacing : -.5 px }
. stat span { font-size : 11 px ; color : var ( - - mut ) }
. stat . extra { background : #fdeee9 } . stat . extra b { color : var ( - - coral2 ) }
/* chart */
. chart { position : relative ; height : 132 px ; display : flex ; align-items : flex-end ; gap : 4 px ; padding-top : 6 px ; margin-top : 4 px }
. col { flex : 1 ; display : flex ; flex-direction : column ; align-items : center ; justify-content : flex-end ; height : 100 % ; gap : 4 px }
. col . b { width : 100 % ; max-width : 26 px ; border-radius : 5 px 5 px 2 px 2 px ; background : var ( - - sea2 ) ; transform-origin : bottom ; animation : grow .4 s ease both }
. col . b . hit { background : var ( - - green ) }
. col . b . today { outline : 2 px solid var ( - - coral ) ; outline-offset : 1 px }
. col . b . future { background : #dbe5eb }
. col small { font-size : 9.5 px ; color : var ( - - mut ) ; font-family : var ( - - mono ) }
. tline { position : absolute ; left : 0 ; right : 0 ; border-top : 2 px dashed var ( - - coral ) ; opacity : .75 }
. tlabel { position : absolute ; right : 0 ; font-size : 9.5 px ; color : var ( - - coral2 ) ; background : var ( - - card ) ; padding : 0 3 px ; transform : translateY ( -50 % ) }
. clegend { font-size : 11 px ; color : var ( - - mut ) ; margin-top : 8 px ; display : flex ; gap : 12 px ; flex-wrap : wrap }
. dot { display : inline-block ; width : 9 px ; height : 9 px ; border-radius : 3 px ; vertical-align : -1 px ; margin-right : 4 px }
. seg { display : grid ; grid-template-columns : 1 fr 1 fr ; gap : 8 px }
. seg button { font : inherit ; font-size : 13 px ; font-weight : 600 ; padding : 11 px 8 px ; border-radius : 12 px ; border : 1.5 px solid var ( - - line ) ;
background : #fff ; color : var ( - - sea ) ; cursor : pointer ; text-align : center ; transition : transform .08 s , background .15 s , border-color .15 s }
. seg button : active { transform : translateY ( 1 px ) }
. seg button small { display : block ; font-weight : 400 ; font-size : 10.5 px ; color : var ( - - mut ) ; margin-top : 2 px }
. seg button . active { background : var ( - - sea ) ; color : #fff ; border-color : var ( - - sea ) ; box-shadow : 0 6 px 16 px -10 px var ( - - sea ) }
. seg button . active small { color : #cfe3ef }
. cat h3 { font-size : 13 px ; margin : 16 px 0 4 px ; color : var ( - - ink ) ; font-weight : 700 }
. drink { display : flex ; align-items : center ; gap : 10 px ; padding : 9 px 0 ; border-bottom : 1 px solid #eef3f6 }
. drink : last-child { border-bottom : 0 }
. dinfo { flex : 1 ; min-width : 0 }
. dname { font-size : 14 px ; display : flex ; align-items : center ; gap : 6 px ; flex-wrap : wrap }
. dmeta { font-size : 11.5 px ; color : var ( - - mut ) ; font-family : var ( - - mono ) }
. badge { font-size : 10 px ; padding : 1 px 6 px ; border-radius : 20 px ; font-weight : 600 ; white-space : nowrap }
. b-in { background : #e0f2e9 ; color : #177049 }
. b-out { background : #fdece7 ; color : #b5461f }
. b-alc { background : #fbeecf ; color : #8a5c10 }
. stepper { display : flex ; align-items : center ; gap : 0 }
. stepper button { width : 34 px ; height : 34 px ; border : 1 px solid var ( - - line ) ; background : #fff ; border-radius : 10 px ; font-size : 19 px ; line-height : 1 ;
color : var ( - - sea ) ; cursor : pointer ; font-family : inherit ; transition : transform .08 s , background .15 s }
. stepper button : active { background : var ( - - sky ) ; transform : scale ( .9 ) }
. qty { min-width : 28 px ; text-align : center ; font-size : 15 px ; font-weight : 700 ; font-family : var ( - - mono ) }
. drink . dim { opacity : .5 }
. warn { border-radius : 12 px ; padding : 12 px ; font-size : 13 px ; margin : 10 px 0 }
. warn . red { background : #fdecea ; border : 1 px solid #f0c1bb ; color : #8f2018 }
. warn . amber { background : #fdf3e3 ; border : 1 px solid #eed49a ; color : #7a4d12 }
. warn . info { background : #eaf3fa ; border : 1 px solid #c3ddf1 ; color : #1c4a6e }
. warn b { display : block ; margin-bottom : 2 px }
. pill { display : inline-block ; background : var ( - - sky ) ; color : var ( - - sea ) ; font-size : 11 px ; padding : 3 px 9 px ; border-radius : 20 px ; margin : 2 px 4 px 2 px 0 ; font-weight : 500 }
. btnbar { display : flex ; gap : 8 px ; margin-top : 12 px }
. btnbar button { flex : 1 ; font : inherit ; font-size : 13 px ; font-weight : 600 ; padding : 11 px ; border-radius : 11 px ; border : 1 px solid var ( - - line ) ;
background : #fff ; color : var ( - - sea ) ; cursor : pointer ; transition : transform .08 s , background .15 s }
. btnbar button : active { transform : translateY ( 1 px ) ; background : var ( - - sky ) }
. btnbar button . warned { color : var ( - - red ) ; border-color : #eec4c0 }
. dayband { font-size : 12 px ; color : var ( - - sea ) ; background : var ( - - sky ) ; border-radius : 10 px ; padding : 8 px 11 px ; margin : -2 px 0 6 px ; font-weight : 600 }
details { margin-top : 8 px }
summary { font-size : 12.5 px ; color : var ( - - sea2 ) ; cursor : pointer ; padding : 4 px 0 }
. fine { font-size : 11.5 px ; color : var ( - - mut ) }
. fine p { margin : 8 px 0 }
. foot { font-size : 11 px ; color : var ( - - mut ) ; text-align : center ; margin : 18 px 0 0 }
< / style >
< / head >
< body >
< header >
< div class = "wrap" >
< div class = "brand" >
< svg width = "38" height = "38" viewBox = "0 0 64 64" aria-hidden = "true" >
< rect width = "64" height = "64" rx = "14" fill = "rgba(255,255,255,.10)" / >
< path d = "M15 19h34l-14 16v9h6v4H23v-4h6v-9z" fill = "#e2673d" / >
< circle cx = "42" cy = "15" r = "3" fill = "#eaf1f5" / >
< path d = "M12 50c5 0 5-3 10-3s5 3 10 3 5-3 10-3 5 3 10 3" fill = "none" stroke = "#9fd0e6" stroke-width = "3" stroke-linecap = "round" / >
< / svg >
< div >
< h1 > Getränkepaket · Break-even< / h1 >
< p class = "sub" > Lohnt sich dein AIDA-Paket schon – heute und über die ganze Reise?< / p >
< / div >
< / div >
< span class = "pstamp" > Preisstand: AIDA-Barkarte < b > 01.11.2025< / b > · geprüft Juli 2026< / span >
< / div >
< / header >
< div class = "wrap" >
< div id = "status" class = "no" >
< div id = "statusMain" > – < / div >
< div class = "bignum" id = "statusNum" > – < / div >
< div id = "statusSub" > – < / div >
< div class = "bar" > < span id = "bar" > < / span > < / div >
< / div >
< div class = "card" >
< h2 > Dein Paket< / h2 >
< div class = "seg" id = "pkgPick" >
< button data-pkg = "fun" class = "active" > FUN < small > alkoholfrei · ab 16 J.< / small > < / button >
< button data-pkg = "allin" > ALL IN < small > mit Alkohol · ab 18 J.< / small > < / button >
< button data-pkg = "kfun" > Kids & Teens FUN < small > 4– 17 J.< / small > < / button >
< button data-pkg = "kallin" > Kids & Teens ALL IN < small > alkoholfrei · 4– 17 J.< / small > < / button >
< / div >
< div class = "row" style = "margin-top:12px" >
< div > < label > Preis pro Person & Paket (€)< / label >
< input id = "price" type = "number" inputmode = "decimal" min = "0" step = "0.01" value = "159" > < / div >
< div > < label > Personen mit Paket< / label >
< input id = "persons" type = "number" inputmode = "numeric" min = "1" step = "1" value = "2" > < / div >
< / div >
< div class = "row" style = "margin-top:10px" >
< div > < label > Reisedauer (Tage)< / label >
< input id = "days" type = "number" inputmode = "numeric" min = "1" step = "1" value = "7" > < / div >
< div > < label > Heute = Reisetag Nr.< / label >
< input id = "curday" type = "number" inputmode = "numeric" min = "1" step = "1" value = "1" > < / div >
< / div >
< p class = "hint" id = "priceHint" > Der Paketpreis < b > variiert je nach Reise, Zeitraum & Fahrtgebiet< / b > – die 159 € sind nur ein Vorschlag. Trag deinen echten myAIDA-Preis ein; der zählt.< / p >
< / div >
< div class = "card today" id = "todayCard" >
< h2 > Heute < span class = "tag" id = "todayTag" > Tag 1< / span > < / h2 >
< div class = "todayMsg" id = "todayMsg" > – < / div >
< div class = "tbar" > < span id = "tbar" > < / span > < / div >
< div class = "hint" id = "todayExtra" > < / div >
< / div >
< div class = "card" >
< h2 > Über die ganze Reise< / h2 >
< div class = "grid2" >
< div class = "stat" > < b id = "sPkg" > – < / b > < span > Paketkosten gesamt< / span > < / div >
< div class = "stat" > < b id = "sCons" > – < / b > < span > Angerechneter Wert bisher< / span > < / div >
< div class = "stat" > < b id = "sPerDay" > – < / b > < span > Break-even pro Tag< / span > < / div >
< div class = "stat extra" > < b id = "sExtra" > – < / b > < span > Zusatzkosten (nicht im Paket)< / span > < / div >
< / div >
< div id = "projLine" class = "warn info" style = "display:none;margin-bottom:0" > < / div >
< / div >
< div class = "card" >
< h2 > Tag für Tag < span class = "tag" > angerechneter Wert je Tag< / span > < / h2 >
< div class = "chart" id = "chart" > < / div >
< div class = "clegend" >
< span > < i class = "dot" style = "background:var(--green)" > < / i > Tagesziel erreicht< / span >
< span > < i class = "dot" style = "background:var(--sea2)" > < / i > drunter< / span >
< span > < i class = "dot" style = "background:#dbe5eb" > < / i > kommt noch< / span >
< span > < i class = "dot" style = "background:var(--coral)" > < / i > heute< / span >
< / div >
< / div >
< div class = "card" id = "panel" > < / div >
< div class = "card" >
< h2 > Getränke wählen< / h2 >
< div class = "dayband" id = "dayband" > Du erfasst gerade < b > Tag 1< / b > . Tippe < b > +< / b > für jedes Getränk.< / div >
< p class = "hint" style = "margin-top:0" > Grün = im Paket (zählt zum Break-even). Orange = nicht im Paket → wird < b > on top< / b > als Zusatzkosten berechnet. Alles wird lokal gespeichert und läuft offline.< / p >
< div id = "drinks" > < / div >
< div class = "btnbar" >
< button id = "nextDay" > Tag abschließen → nächster Tag< / button >
< / div >
< div class = "btnbar" >
< button id = "resetDay" > Diesen Tag leeren< / button >
< button id = "resetAll" class = "warned" > Alles zurücksetzen< / button >
< / div >
< / div >
< div class = "card" id = "kidCard" >
< h2 > Kind unter 4 · gratis dabei< / h2 >
< p class = "hint" style = "margin-top:0" > Kinder unter 4 bekommen über das Paket der Eltern das < b > Kids & Teens FUN gratis< / b > (ohne eigene Karte). Was das Kind trinkt, kostet nichts – zählt aber als geschenkter Wert obendrauf, < b > separat< / b > vom Break-even. Bei euch: Felix.< / p >
< div id = "kidDrinks" > < / div >
< div class = "warn info" id = "kidLine" style = "margin-bottom:0" > Noch nichts fürs Kind erfasst.< / div >
< / div >
< details >
< summary > Kleingedrucktes & Regeln (AGB-Auszug, ehrlich)< / summary >
< div class = "fine" id = "rules" > < / div >
< / details >
< p class = "foot" > Inoffizieller Helfer · Preise & Paketinhalte laut AIDA-Barkarte/AGB (Stand 01.11.2025, geprüft Juli 2026). Auswahl kann je nach Fahrtgebiet, Zeitraum & Bar leicht variieren – im Zweifel gilt die Barkarte an Bord.< / p >
< / div >
< script >
"use strict" ;
/* ---- Getränke-DB (echte Barkarten-Preise €) ----
tag: base=alle Pakete | mock=alkfr. Cocktails (alle Pakete) | coffee=Kaffeespez. (FUN & ALL IN)
prem=Premium-Softdrink/alkfr. Bier (nur ALL IN) | alc=alkoholisch (nur ALL IN) | none=kein Paket */
const CAT = [
[ "Alkoholfrei · Basics" , [
[ "Coca-Cola" , "0,2 l" , 2.6 , "base" ] , [ "Coca-Cola Zero" , "0,2 l" , 2.6 , "base" ] , [ "Fanta" , "0,2 l" , 2.6 , "base" ] ,
[ "Sprite" , "0,2 l" , 2.6 , "base" ] , [ "Saft / Schorle" , "0,2 l" , 2.6 , "base" ] , [ "Sodawasser" , "0,2 l" , 2.0 , "base" ] ,
[ "AIDA Lemonade" , "" , 5.5 , "base" ] , [ "AIDA Iced Tea" , "" , 5.5 , "base" ] ] ] ,
[ "Heißgetränke" , [
[ "Kakao" , "Kinder" , 1.5 , "base" ] , [ "Eilles Tee" , "" , 3.4 , "base" ] , [ "Heiße Schokolade" , "" , 2.9 , "base" ] ,
[ "Espresso" , "" , 2.2 , "coffee" ] , [ "Kaffee" , "" , 2.9 , "coffee" ] , [ "Espresso Macchiato" , "" , 2.9 , "coffee" ] ,
[ "Doppelter Espresso" , "" , 3.6 , "coffee" ] , [ "Cappuccino" , "" , 4.1 , "coffee" ] , [ "Milchkaffee" , "" , 4.1 , "coffee" ] ,
[ "Latte Macchiato" , "" , 4.1 , "coffee" ] ] ] ,
[ "Alkoholfreie Cocktails, Mocktails & Shakes" , [
[ "Aquarium (alkoholfrei)" , "" , 7.5 , "mock" ] , [ "Cherry Bomb (alkoholfrei)" , "" , 7.5 , "mock" ] ,
[ "Erdbeer Colada (alkoholfrei)" , "" , 7.5 , "mock" ] , [ "Ipanema (alkoholfrei)" , "" , 7.5 , "mock" ] ,
[ "Palm Beach (alkoholfrei)" , "" , 6.5 , "mock" ] , [ "Banana Split (alkoholfrei)" , "" , 6.5 , "mock" ] ,
[ "Sunrise (alkoholfrei)" , "" , 6.5 , "mock" ] , [ "Coco Choco Loco (alkoholfrei)" , "" , 5.5 , "mock" ] ,
[ "Apple Crumble (alkoholfrei)" , "" , 5.5 , "mock" ] , [ "AIDA Virgin Sprizz" , "" , 7.9 , "mock" ] ,
[ "Virgin Hugo" , "" , 7.9 , "mock" ] , [ "Aperitivo Sprizz (alkoholfrei)" , "" , 8.9 , "mock" ] ,
[ "Little Berry (alkoholfrei)" , "" , 8.9 , "mock" ] , [ "Milchshake" , "" , 5.5 , "base" ] ,
[ "Kids & Teens Cocktail (Dodo & Co.)" , "" , 5.5 , "base" ] ] ] ,
[ "Premium-Softdrinks & alkoholfreies Bier" , [
[ "BioZisch Limonade (Voelkel)" , "0,33 l" , 3.9 , "prem" ] , [ "Kombucha" , "0,33 l" , 3.9 , "prem" ] ,
[ "ChariTea" , "0,33 l" , 3.9 , "prem" ] , [ "Fever-Tree Tonic & Co." , "0,2 l" , 3.9 , "prem" ] ,
[ "Red Bull" , "0,25 l" , 3.9 , "prem" ] , [ "Alkoholfreies Bier (Jever Fun u.a.)" , "0,33 l" , 4.6 , "prem" ] ] ] ,
[ "Bier" , [
[ "Radeberger Pilsner" , "0,3 l" , 4.0 , "alc" , true ] , [ "Radeberger Pilsner" , "0,5 l" , 5.5 , "alc" , true ] ,
[ "Schöfferhofer Hefeweizen" , "0,5 l" , 5.5 , "alc" , true ] , [ "Corona" , "0,355 l" , 4.8 , "alc" , true ] ,
[ "Salitos" , "0,33 l" , 4.6 , "alc" , true ] , [ "Heineken" , "0,33 l" , 4.6 , "alc" , true ] ,
[ "Schöfferhofer Grapefruit" , "0,33 l" , 4.6 , "alc" , true ] ] ] ,
[ "Wein & Sekt (im Glas)" , [
[ "Wein im Glas (Edition AIDA)" , "0,2 l" , 8.0 , "alc" , true ] , [ "Primitivo / Cabernet" , "0,2 l" , 10.0 , "alc" , true ] ,
[ "Sekt / Prosecco" , "0,1 l" , 4.9 , "alc" , true ] , [ "Sekt / Prosecco auf Eis" , "0,15 l" , 6.6 , "alc" , true ] ] ] ,
[ "Cocktails" , [
[ "AIDA Honey Mule" , "" , 10.2 , "alc" , true ] , [ "Dark & Stormy" , "" , 9.2 , "alc" , true ] ,
[ "Deep Purple Magic Sour" , "" , 11.2 , "alc" , true ] , [ "Coconut Mai Tai" , "" , 10.2 , "alc" , true ] ,
[ "White Basil" , "" , 8.2 , "alc" , true ] , [ "AIDA Icebreaker" , "" , 10.2 , "alc" , true ] ,
[ "AIDA Mai Tai" , "" , 10.2 , "alc" , true ] , [ "Mojito" , "" , 9.2 , "alc" , true ] , [ "Sex on the Beach" , "" , 9.2 , "alc" , true ] ,
[ "Caipirinha" , "" , 9.2 , "alc" , true ] , [ "Piña Colada" , "" , 9.9 , "alc" , true ] , [ "Hurricane" , "" , 10.2 , "alc" , true ] ,
[ "Swimming Pool" , "" , 10.2 , "alc" , true ] , [ "Long Island Iced Tea" , "" , 11.9 , "alc" , true ] ,
[ "Margarita" , "" , 8.2 , "alc" , true ] , [ "Negroni" , "" , 10.2 , "alc" , true ] , [ "Whiskey Sour" , "" , 8.2 , "alc" , true ] ,
[ "Cosmopolitan" , "" , 7.9 , "alc" , true ] , [ "Espresso Martini" , "" , 8.2 , "alc" , true ] ] ] ,
[ "Longdrinks & Gin Tonics" , [
[ "Gin Tonic" , "" , 10.6 , "alc" , true ] , [ "Vodka Red Bull" , "" , 9.6 , "alc" , true ] , [ "Vodka Cranberry" , "" , 8.3 , "alc" , true ] ,
[ "Whiskey Cola" , "" , 9.3 , "alc" , true ] , [ "Campari Orange" , "" , 8.3 , "alc" , true ] , [ "Rum Cola" , "" , 8.3 , "alc" , true ] ,
[ "Cuba Libre" , "" , 7.9 , "alc" , true ] , [ "Deep & Purple G&T" , "" , 11.6 , "alc" , true ] ,
[ "AIDA Guilty Pleasure" , "" , 11.2 , "alc" , true ] , [ "Garden & Tonic" , "" , 10.2 , "alc" , true ] ,
[ "Italian G&T" , "" , 12.0 , "alc" , true ] ] ] ,
[ "Sprizz & Shots" , [
[ "Aperol Sprizz" , "" , 9.2 , "alc" , true ] , [ "AIDA Sprizz" , "" , 8.2 , "alc" , true ] , [ "Lillet Berry" , "" , 9.2 , "alc" , true ] ,
[ "Hugo" , "" , 8.2 , "alc" , true ] , [ "Shot (B-52, Hellfire …)" , "4 cl" , 4.9 , "alc" , true ] ] ] ,
[ "Spirituosen, Aperitifs & Liköre" , [
[ "Spirituose Standard (Gin, Rum, Vodka …)" , "4 cl" , 5.7 , "alc" , true ] ,
[ "Premium-Spirituose (Monkey 47, Grey Goose Altius …)" , "4 cl" , 9.5 , "alc" , true ] ,
[ "Aperitif / Likör / Bitter (Aperol, Baileys, Jägermeister …)" , "4 cl" , 4.9 , "alc" , true ] ,
[ "Grappa" , "4 cl" , 6.7 , "alc" , true ] ] ] ,
[ "Nicht im Paket (immer extra)" , [
[ "Mineralwasser Flasche" , "0,75 l" , 6.9 , "none" ] , [ "Champagner (Glas)" , "0,1 l" , 9.6 , "none" ] ,
[ "Weinflasche" , "0,75 l" , 27.9 , "none" ] , [ "Champagner-Flasche" , "0,75 l" , 149.0 , "none" ] ,
[ "Starbucks (ca.)" , "" , 5.0 , "none" ] ] ]
] ;
const KID = [ [ "Milchshake" , 5.5 ] , [ "Kids & Teens Cocktail (Dodo & Co.)" , 5.5 ] , [ "Mocktail (Coco Choco Loco)" , 5.5 ] ,
[ "Saft / Schorle" , 2.6 ] , [ "Softdrink (Cola, Fanta …)" , 2.6 ] , [ "Kakao" , 1.5 ] , [ "Eilles Tee" , 3.4 ] ] ;
function inPkg ( tag , pkg ) { switch ( pkg ) {
case "fun" : return tag === "base" || tag === "mock" || tag === "coffee" ;
case "allin" : return tag !== "none" ;
case "kfun" : case "kallin" : return tag === "base" || tag === "mock" ; } return false ; }
const PKGNAME = { fun : "FUN" , allin : "ALL IN" , kfun : "Kids & Teens FUN" , kallin : "Kids & Teens ALL IN" } ;
const DRINKS = [ ] ;
CAT . forEach ( ( c , ci ) => c [ 1 ] . forEach ( ( d , di ) => DRINKS . push (
{ id : "d" + ci + "_" + di , name : d [ 0 ] , size : d [ 1 ] , price : d [ 2 ] , tag : d [ 3 ] , alc : ! ! d [ 4 ] , cat : c [ 0 ] } ) ) ) ;
const PRICE = { } ; DRINKS . forEach ( d => PRICE [ d . id ] = { price : d . price , tag : d . tag , alc : d . alc } ) ;
/* ---- state (Konsum je Reisetag) ---- */
const KEY = "aidaBreakeven_v3" ;
let S = { pkg : "fun" , price : 159 , persons : 2 , days : 7 , curday : 1 , byday : { } , kid : { } } ;
try { const r = localStorage . getItem ( KEY ) ; if ( r ) S = Object . assign ( S , JSON . parse ( r ) ) ; } catch ( e ) { }
function save ( ) { try { localStorage . setItem ( KEY , JSON . stringify ( S ) ) ; } catch ( e ) { } }
function today ( ) { return S . byday [ S . curday ] || ( S . byday [ S . curday ] = { } ) ; }
const eur = x => x . toLocaleString ( "de-DE" , { minimumFractionDigits : 2 , maximumFractionDigits : 2 } ) + " €" ;
const $ = s => document . querySelector ( s ) ;
const num = ( v , f ) => { v = parseFloat ( ( "" + v ) . replace ( "," , "." ) ) ; return isFinite ( v ) && v >= 0 ? v : f ; } ;
/* value of a counts-object */
function valOf ( counts ) { let incl = 0 , extra = 0 , alcV = 0 , alcN = 0 ;
for ( const id in counts ) { const q = counts [ id ] , p = PRICE [ id ] ; if ( ! p ) continue ;
if ( inPkg ( p . tag , S . pkg ) ) { incl += p . price * q ; if ( p . alc ) { alcV += p . price * q ; alcN += q ; } } else extra += p . price * q ; }
return { incl , extra , alcV , alcN } ; }
function totals ( ) { let incl = 0 , extra = 0 , alcV = 0 , alcN = 0 ;
for ( const d in S . byday ) { const v = valOf ( S . byday [ d ] ) ; incl += v . incl ; extra += v . extra ; alcV += v . alcV ; alcN += v . alcN ; }
return { incl , extra , alcV , alcN } ; }
/* ---- render drinks (edit current day) ---- */
function renderDrinks ( ) {
const host = $ ( "#drinks" ) ; host . innerHTML = "" ; const tc = today ( ) ;
CAT . forEach ( ( c , ci ) => {
const wrap = document . createElement ( "div" ) ; wrap . className = "cat" ;
wrap . innerHTML = '<h3>' + c [ 0 ] + '</h3>' ;
c [ 1 ] . forEach ( ( d , di ) => {
const id = "d" + ci + "_" + di , tag = d [ 3 ] , alc = ! ! d [ 4 ] , incl = inPkg ( tag , S . pkg ) ;
let badge = incl ? '<span class="badge b-in">im Paket</span>'
: ( tag === "none" ? '<span class="badge b-out">nie im Paket</span>' : '<span class="badge b-out">extra +' + eur ( d [ 2 ] ) + '</span>' ) ;
if ( incl && alc ) badge += ' <span class="badge b-alc">Alkohol</span>' ;
const meta = [ d [ 1 ] , eur ( d [ 2 ] ) ] . filter ( Boolean ) . join ( " · " ) ;
const row = document . createElement ( "div" ) ; row . className = "drink" + ( incl ? "" : " dim" ) ;
row . innerHTML = '<div class="dinfo"><div class="dname">' + d [ 0 ] + ' ' + badge + '</div><div class="dmeta">' + meta + '</div></div>' +
'<div class="stepper"><button data-m="' + id + '" aria-label="minus">– </button>' +
'<span class="qty" id="q_' + id + '">' + ( tc [ id ] || 0 ) + '</span>' +
'<button data-p="' + id + '" aria-label="plus">+</button></div>' ;
wrap . appendChild ( row ) ;
} ) ; host . appendChild ( wrap ) ;
} ) ;
}
function renderKid ( ) {
const host = $ ( "#kidDrinks" ) ; host . innerHTML = "" ;
KID . forEach ( ( d , i ) => { const id = "k" + i , q = S . kid [ id ] || 0 ;
const row = document . createElement ( "div" ) ; row . className = "drink" ;
row . innerHTML = '<div class="dinfo"><div class="dname">' + d [ 0 ] + ' <span class="badge b-in">gratis</span></div>' +
'<div class="dmeta">Wert ' + eur ( d [ 1 ] ) + '</div></div>' +
'<div class="stepper"><button data-km="' + id + '" aria-label="minus">– </button>' +
'<span class="qty" id="qk_' + id + '">' + q + '</span><button data-kp="' + id + '" aria-label="plus">+</button></div>' ;
host . appendChild ( row ) ; } ) ;
}
/* ---- chart ---- */
function renderChart ( perDay ) {
const host = $ ( "#chart" ) ; host . innerHTML = "" ;
const vals = [ ] ; for ( let d = 1 ; d <= S . days ; d ++ ) vals . push ( valOf ( S . byday [ d ] || { } ) . incl ) ;
const scale = Math . max ( perDay * 1.25 , Math . max . apply ( null , vals . concat ( [ 1 ] ) ) * 1.1 , 1 ) ;
// target line
const tl = document . createElement ( "div" ) ; tl . className = "tline" ;
tl . style . bottom = ( perDay / scale * 100 ) + "%" ; host . appendChild ( tl ) ;
const lab = document . createElement ( "div" ) ; lab . className = "tlabel" ;
lab . style . bottom = ( perDay / scale * 100 ) + "%" ; lab . textContent = "Ziel " + eur ( perDay ) ; host . appendChild ( lab ) ;
for ( let d = 1 ; d <= S . days ; d ++ ) {
const v = vals [ d - 1 ] , col = document . createElement ( "div" ) ; col . className = "col" ;
const b = document . createElement ( "div" ) ; b . className = "b" ;
const future = d > S . curday && v === 0 ;
if ( future ) b . classList . add ( "future" ) ; else if ( v >= perDay && v > 0 ) b . classList . add ( "hit" ) ;
if ( d === S . curday ) b . classList . add ( "today" ) ;
b . style . height = Math . max ( v / scale * 100 , v > 0 ? 3 : 0 ) + "%" ;
col . appendChild ( b ) ;
const s = document . createElement ( "small" ) ; s . textContent = d ; col . appendChild ( s ) ;
host . appendChild ( col ) ;
}
}
/* ---- compute + render ---- */
function compute ( ) {
S . price = num ( $ ( "#price" ) . value , 0 ) ;
S . persons = Math . max ( 1 , Math . round ( num ( $ ( "#persons" ) . value , 1 ) ) ) ;
S . days = Math . max ( 1 , Math . round ( num ( $ ( "#days" ) . value , 1 ) ) ) ;
S . curday = Math . max ( 1 , Math . min ( S . days , Math . round ( num ( $ ( "#curday" ) . value , 1 ) ) ) ) ;
const pkgTotal = S . price * S . persons , perDay = pkgTotal / S . days ;
const T = totals ( ) , tv = valOf ( today ( ) ) ;
const remaining = pkgTotal - T . incl ;
/* overall status */
const st = $ ( "#status" ) ;
if ( remaining > 0.001 ) { const ratio = pkgTotal > 0 ? T . incl / pkgTotal : 0 ;
st . className = ratio >= 0.75 ? "close" : "no" ;
$ ( "#statusMain" ) . textContent = ratio >= 0.75 ? "Fast am Break-even" : "Lohnt sich noch nicht" ;
$ ( "#statusNum" ) . textContent = "noch " + eur ( remaining ) ;
$ ( "#statusSub" ) . textContent = "bis sich dein " + PKGNAME [ S . pkg ] + "-Paket über die Reise rechnet" ;
} else { st . className = "yes" ;
$ ( "#statusMain" ) . textContent = "Break-even erreicht" ;
$ ( "#statusNum" ) . textContent = "+" + eur ( - remaining ) + " Plus" ;
$ ( "#statusSub" ) . textContent = "Jeder weitere Drink im Paket ist ab jetzt geschenkt" ; }
$ ( "#bar" ) . style . width = Math . min ( 100 , pkgTotal > 0 ? T . incl / pkgTotal * 100 : 0 ) + "%" ;
/* today */
const tcard = $ ( "#todayCard" ) ;
$ ( "#todayTag" ) . textContent = "Tag " + S . curday ;
const tpct = Math . min ( 100 , perDay > 0 ? tv . incl / perDay * 100 : 0 ) ;
$ ( "#tbar" ) . style . width = tpct + "%" ;
tcard . classList . toggle ( "done" , tv . incl >= perDay && perDay > 0 ) ;
if ( tv . incl >= perDay && perDay > 0 ) {
$ ( "#todayMsg" ) . innerHTML = "Für heute ausgereizt – " + eur ( tv . incl ) + " von " + eur ( perDay ) +
"<small>Tagesziel geknackt. Alles Weitere heute ist reiner Gewinn.</small>" ;
} else {
$ ( "#todayMsg" ) . innerHTML = "Noch nicht ausgereizt für heute" +
"<small>" + eur ( tv . incl ) + " von " + eur ( perDay ) + " – noch <b>" + eur ( perDay - tv . incl ) + "</b> bis dein Paket sich für heute rechnet.</small>" ;
}
$ ( "#todayExtra" ) . innerHTML = tv . extra > 0 ? "Heute zusätzlich außerhalb des Pakets: <b>" + eur ( tv . extra ) + "</b>" : "" ;
/* overall stats */
$ ( "#sPkg" ) . textContent = eur ( pkgTotal ) ;
$ ( "#sCons" ) . textContent = eur ( T . incl ) ;
$ ( "#sPerDay" ) . textContent = eur ( perDay ) ;
$ ( "#sExtra" ) . textContent = eur ( T . extra ) ;
const pj = $ ( "#projLine" ) ;
if ( T . incl > 0 && S . curday < S . days ) {
const paceDay = T . incl / S . curday , proj = paceDay * S . days , onTrack = proj >= pkgTotal ;
pj . style . display = "block" ; pj . className = "warn " + ( onTrack ? "info" : "amber" ) ;
pj . innerHTML = "<b>Hochrechnung</b>Dein Schnitt: " + eur ( paceDay ) + "/Tag → bis Reiseende ca. <b>" + eur ( proj ) + "</b> von " + eur ( pkgTotal ) + ". " +
( onTrack ? "Du liegst über dem Break-even." : "Das ist <b>unter</b> Break-even – ca. " + eur ( Math . max ( 0 , remaining ) / Math . max ( 1 , S . days - S . curday + 1 ) ) + " pro Resttag nötig." ) ;
} else pj . style . display = "none" ;
renderChart ( perDay ) ;
/* panel: alcohol (allin) / value tips */
const p = $ ( "#panel" ) ;
if ( S . pkg === "allin" ) {
const alcPerDay = T . alcN / S . curday , needAlc = perDay / 8.5 ;
let body = '<h2>Fairer Alkohol-Check</h2><p class="hint" style="margin-top:0">Vom angerechneten Wert entfallen <b>' + eur ( T . alcV ) +
'</b> auf Alkohol (' + T . alcN + ' Drink' + ( T . alcN !== 1 ? 's' : '' ) + ', Ø ' + alcPerDay . toFixed ( 1 ) + '/Tag).</p>' ;
if ( alcPerDay >= 5 ) { body += '<div class="warn red" style="margin-bottom:0"><b>Bitte aufpassen.</b>Das sind Ø ' + alcPerDay . toFixed ( 1 ) +
' alkoholische Getränke pro Tag. Ein Paket rechnet sich <b>nie</b>, indem man mehr trinkt, als einem guttut. Der Break-even ist kein Trinkziel – Wasser, Kaffee & Mocktails zählen genauso.</div>' ; }
else { body += '<div class="warn amber" style="margin-bottom:0"><b>Denk dran:</b> Rein über Alkohol bräuchtest du ~' + needAlc . toFixed ( 1 ) +
' Drinks/Tag für den Break-even. Muss nicht sein – Kaffeespezialitäten, Softdrinks & alkoholfreie Cocktails zählen voll mit. Verantwortungsvoll genießen.</div>' ; }
p . innerHTML = body ;
} else {
const incl = DRINKS . filter ( d => inPkg ( d . tag , S . pkg ) ) ;
const top = incl . slice ( ) . sort ( ( a , b ) => b . price - a . price )
. filter ( ( d , i , a ) => a . findIndex ( x => x . name . replace ( /\s*\(alkoholfrei\)/ , "" ) === d . name . replace ( /\s*\(alkoholfrei\)/ , "" ) ) === i ) . slice ( 0 , 6 ) ;
let h = '<h2>So holst du am meisten raus</h2><p class="hint" style="margin-top:0">Break-even = <b>' + eur ( perDay ) +
' pro Tag</b>. Das sind z.B. ~' + ( perDay / 4.1 ) . toFixed ( 1 ) + ' Latte Macchiato <i>oder</i> ~' + ( perDay / 7.5 ) . toFixed ( 1 ) + ' Mocktails am Tag.</p>' ;
h += '<div style="font-size:12px;color:var(--mut);margin:8px 0 3px">Teuerste inkludierte Drinks (bringen Wert am schnellsten):</div><div>' +
top . map ( d => '<span class="pill">' + d . name . replace ( /\s*\(alkoholfrei\)/ , '' ) + ' · ' + eur ( d . price ) + '</span>' ) . join ( '' ) + '</div>' ;
h += '<div class="warn info" style="margin:10px 0 0">Tipp: Kaffeespezialitäten (' + eur ( 4.1 ) + ') zählen im FUN voll mit – Latte zum Frühstück, Cappuccino nachmittags, Mocktail abends bringen dich Richtung Break-even, ganz ohne Alkohol.</div>' ;
p . innerHTML = h ;
}
/* kid bonus */
let kidVal = 0 , kidN = 0 ; KID . forEach ( ( d , i ) => { const q = S . kid [ "k" + i ] || 0 ; kidVal += d [ 1 ] * q ; kidN += q ; } ) ;
const kl = $ ( "#kidLine" ) ;
kl . innerHTML = kidN > 0 ? "Das Kind hat für <b>" + eur ( kidVal ) + "</b> getrunken – komplett <b>gratis</b> über euer Paket. Reiner Bonus, unabhängig vom Break-even oben." : "Noch nichts fürs Kind erfasst." ;
$ ( "#dayband" ) . innerHTML = "Du erfasst gerade <b>Tag " + S . curday + "</b> von " + S . days + ". Tippe <b>+</b> für jedes Getränk." ;
save ( ) ;
}
/* ---- events ---- */
$ ( "#drinks" ) . addEventListener ( "click" , e => {
const plus = e . target . getAttribute ( "data-p" ) , minus = e . target . getAttribute ( "data-m" ) , id = plus || minus ; if ( ! id ) return ;
const tc = today ( ) ; let q = tc [ id ] || 0 ; q += plus ? 1 : - 1 ; if ( q < 0 ) q = 0 ;
if ( q === 0 ) delete tc [ id ] ; else tc [ id ] = q ;
const el = document . getElementById ( "q_" + id ) ; if ( el ) el . textContent = q ; compute ( ) ; } ) ;
$ ( "#kidDrinks" ) . addEventListener ( "click" , e => {
const kp = e . target . getAttribute ( "data-kp" ) , km = e . target . getAttribute ( "data-km" ) , id = kp || km ; if ( ! id ) return ;
let q = S . kid [ id ] || 0 ; q += kp ? 1 : - 1 ; if ( q < 0 ) q = 0 ; if ( q === 0 ) delete S . kid [ id ] ; else S . kid [ id ] = q ;
const el = document . getElementById ( "qk_" + id ) ; if ( el ) el . textContent = q ; compute ( ) ; } ) ;
$ ( "#pkgPick" ) . addEventListener ( "click" , e => { const b = e . target . closest ( "button" ) ; if ( ! b ) return ;
S . pkg = b . getAttribute ( "data-pkg" ) ;
[ ... $ ( "#pkgPick" ) . children ] . forEach ( x => x . classList . toggle ( "active" , x === b ) ) ;
$ ( "#priceHint" ) . innerHTML = S . pkg === "allin"
? "ALL IN ist ab 5 Reisetagen buchbar und in den ALL-IN-Tarifen ab 25 J. im Reisepreis. Preis variiert je Reise – trag deinen echten myAIDA-Preis ein."
: "Der Paketpreis <b>variiert je nach Reise, Zeitraum & Fahrtgebiet</b> – die Vorgabe ist nur ein Vorschlag. Trag deinen echten myAIDA-Preis ein." ;
renderDrinks ( ) ; compute ( ) ; } ) ;
[ "price" , "persons" , "days" , "curday" ] . forEach ( f => $ ( "#" + f ) . addEventListener ( "input" , ( ) => { renderDrinks ( ) ; compute ( ) ; } ) ) ;
$ ( "#nextDay" ) . addEventListener ( "click" , ( ) => {
if ( S . curday < S . days ) { S . curday ++ ; $ ( "#curday" ) . value = S . curday ; renderDrinks ( ) ; compute ( ) ;
window . scrollTo ( { top : 0 , behavior : "smooth" } ) ; }
else alert ( "Das ist bereits dein letzter Reisetag (" + S . days + ")." ) ; } ) ;
$ ( "#resetDay" ) . addEventListener ( "click" , ( ) => { if ( confirm ( "Tag " + S . curday + " leeren?" ) ) { S . byday [ S . curday ] = { } ; renderDrinks ( ) ; compute ( ) ; } } ) ;
$ ( "#resetAll" ) . addEventListener ( "click" , ( ) => { if ( confirm ( "Wirklich alles zurücksetzen (alle Tage + Einstellungen)?" ) ) {
try { localStorage . removeItem ( KEY ) ; } catch ( e ) { }
S = { pkg : "fun" , price : 159 , persons : 2 , days : 7 , curday : 1 , byday : { } , kid : { } } ; initForm ( ) ; renderDrinks ( ) ; renderKid ( ) ; compute ( ) ; } } ) ;
$ ( "#rules" ) . innerHTML = [
"<b>Kabinen-Regel:</b> Alle Reisenden ab 16 J. in einer Kabine müssen dasselbe Paket buchen (FUN) bzw. alle Volljährigen dasselbe (ALL IN). Deshalb haben Lea & du beide FUN – Tante Astrid in eigener Kabine ist frei." ,
"<b>Mythos aufgeklärt:</b> Nein, es müssen <b>nicht alle Mitreisenden</b> ein Paket buchen – nur alle ab 16 J. in <b>derselben Kabine</b>. Andere Kabinen entscheiden frei." ,
"<b>Personengebunden:</b> Paket gilt laut AGB nur für Eigenverzehr, 1 Getränk pro Bestellung, Bordkarte vorzeigen. Jemandem ohne Paket etwas »ausgeben« ist offiziell nicht vorgesehen. Regelkonforme Ausnahme: Kleinkinder unter 4 (siehe oben)." ,
"<b>Buchbarkeit:</b> ALL IN erst ab 5 Reisetagen; FUN & Kids-Pakete ab 1 Tag. Keine tageweise Buchung, keine rückwirkende Umbuchung." ,
"<b>Nicht enthalten:</b> Minibar, Automaten, Spa-Getränke, Flaschen-/Dosenwasser, Starbucks, selbst gebraute Biere, Champagner & Flaschenweine." ,
"<b>Preis:</b> je nach Reise, Zeitraum & Fahrtgebiet unterschiedlich – nur myAIDA zeigt deinen echten Preis. Deshalb ist er hier frei eingebbar." ,
"<i>Datenstand Barkarte/AGB: 01.11.2025, geprüft Juli 2026. Auswahl kann je Fahrtgebiet/Bar leicht abweichen. Kids-Paket-Details in myAIDA gegenprüfen.</i>"
] . map ( t => "<p>" + t + "</p>" ) . join ( "" ) ;
function initForm ( ) {
$ ( "#price" ) . value = S . price ; $ ( "#persons" ) . value = S . persons ; $ ( "#days" ) . value = S . days ; $ ( "#curday" ) . value = S . curday ;
[ ... $ ( "#pkgPick" ) . children ] . forEach ( x => x . classList . toggle ( "active" , x . getAttribute ( "data-pkg" ) === S . pkg ) ) ; }
initForm ( ) ; renderDrinks ( ) ; renderKid ( ) ; compute ( ) ;
< / script >
< / body >
< / html >