diff --git a/assets/sass/main.scss b/assets/sass/main.scss index 639c39d7..73bd963b 100644 --- a/assets/sass/main.scss +++ b/assets/sass/main.scss @@ -17,3 +17,4 @@ @import "startpage.scss"; @import "interactiveMap.scss"; @import "dropdown.scss"; +@import "trainCategory.scss"; diff --git a/assets/sass/trainCategory.scss b/assets/sass/trainCategory.scss new file mode 100644 index 00000000..0afffb09 --- /dev/null +++ b/assets/sass/trainCategory.scss @@ -0,0 +1,150 @@ +.o-train-category__header { + width: 100%; + + &-content { + display: flex; + flex-direction: column; + gap: 0.8rem; + width: 100%; + } +} + +.o-train-category__title-wrapper { + width: 100%; +} + +.o-train-category__title { + display: flex; + align-items: center; + gap: 0.5rem; + font-weight: 600; + font-size: 1.6rem; + + &-text { + flex: 1; + } +} + +.o-train-category__tags { + display: flex; + flex-wrap: wrap; + gap: 0.6rem; +} + +.o-train-category__tag { + display: flex; + align-items: center; + gap: 0.4rem; + padding: 0.4rem 0.8rem; + border-radius: var(--border-radius-s); + font-size: 1.2rem; + font-weight: 500; + white-space: nowrap; + + &--accepted { + background: #d4edda; + color: #155724; + border: 0.1rem solid #c3e6cb; + } + + &--rejected { + background: #f8d7da; + color: #721c24; + border: 0.1rem solid #f5c6cb; + } + + &--required { + background: #fff3cd; + color: #856404; + border: 0.1rem solid #ffeaa7; + } + + &--possible { + background: #cce7ff; + color: #004085; + border: 0.1rem solid #b3d9ff; + } + + &--none { + background: #e2e3e5; + color: #383d41; + border: 0.1rem solid #d6d8db; + } + + &--info { + background: #e7f3ff; + color: #0c5460; + border: 0.1rem solid #bee5eb; + } +} + +.o-train-category__content { + margin-top: 1rem; +} + +.o-train-category__info { + padding: 0.8rem; + margin-bottom: 1rem; + background: #e7f3ff; + border: 0.1rem solid #bee5eb; + border-radius: var(--border-radius-s); + color: #0c5460; + font-style: italic; +} + +.o-expander__summary--train-category { + &:hover, + &:focus { + .o-train-category__title-text { + text-decoration: underline; + } + } +} + +html[data-theme="dark"] { + .o-train-category { + &__info { + background: #0c3544; + border-color: #17a2b8; + color: #bee5eb; + } + + &__tag { + &--accepted { + background: #2d5a3d; + color: #a3d5ab; + border-color: #4a7c59; + } + + &--rejected { + background: #5a2d32; + color: #f5a3ab; + border-color: #7c4a52; + } + + &--required { + background: #5a4d2d; + color: #f5e6a3; + border-color: #7c6a4a; + } + + &--possible { + background: #2d4a5a; + color: #a3d5f5; + border-color: #4a6a7c; + } + + &--none { + background: #3d3d3d; + color: #d0d0d0; + border-color: #5a5a5a; + } + + &--info { + background: #0c3544; + color: #bee5eb; + border-color: #17a2b8; + } + } + } +} diff --git a/content/operator/sncf/index.en.md b/content/operator/sncf/index.en.md index c973b448..38d8fd0a 100644 --- a/content/operator/sncf/index.en.md +++ b/content/operator/sncf/index.en.md @@ -37,78 +37,84 @@ Reservations are mandatory on all `TGV`, almost all `IC` trains, and some region ### Long-distance -{{% expander "Train à grande vitesse inOui (TGV inOui) ⚠️ℹ️" traincategory "long-distance" %}} -**Description:** \ +{{% train-category + title="Train à grande vitesse inOui (TGV inOui)" + fip_accepted=true + reservation_required=true + info_available=true +%}} The `TGV` inOui is SNCF's high-speed train, connecting many cities in France and international destinations (e.g. Munich, Frankfurt am Main, Barcelona, Luxembourg, Brussels, Zurich, Milan). [Route overview](https://www.sncf-connect.com/assets/media/2021-05/2014_axes-tgv_0.pdf). Each seat number exists twice in the carriage; the reserved seat is the one with the illuminated number. -ℹ️ SNCF also operates low-cost `TGV` trains under the name OuiGo, which are not valid with FIP. +{{% highlight inofficial %}} +SNCF also operates low-cost `TGV` trains under the name OuiGo, which are not valid with FIP. +{{% /highlight %}} + +{{% highlight important %}} +Special conditions apply for international connections, see International TGV inOui / ICE trains section below. +{{% /highlight %}} -⚠️ Special conditions apply for international connections, see [International TGV inOui / ICE trains](#international-tgv-inoui--ice-trains). \ -**Reservation possible:** yes \ -**Reservation required:** yes ⚠️ \ **Reservation cost:** \ Prices differ between peak and off-peak trains. Off-peak: €1.70 (1st/2nd class); peak: €15 (1st class), €10 (2nd class). The classification is not publicly available. -{{% /expander %}} +{{% /train-category %}} -{{% expander "Train à grande vitesse OuiGo (TGV OuiGo) / OuiGo Train Classique ⛔⚠️ℹ️" traincategory "long-distance" %}} -**Description:** \ +{{% train-category + title="Train à grande vitesse OuiGo (TGV OuiGo) / OuiGo Train Classique" + fip_accepted=false + reservation_required=true +%}} The `TGV` OuiGo is SNCF's low-cost high-speed train, serving many cities in France and some international destinations. +{{% /train-category %}} -ℹ️ SNCF also operates `TGV` trains under the inOui brand, which are valid with FIP. \ -**Reservation possible:** yes \ -**Reservation required:** yes ⚠️ \ -**FIP:** ⛔ FIP not accepted -{{% /expander %}} - -{{% expander "Intercity-Express (ICE) ⚠️" traincategory "long-distance" %}} -**Description:** \ +{{% train-category + title="Intercity-Express (ICE)" + fip_accepted=true + reservation_required=true +%}} International high-speed trains operated by SNCF in cooperation with Deutsche Bahn, running between France (Paris Est, Strasbourg) and Germany (Karlsruhe, Mannheim, Frankfurt am Main, Stuttgart, Munich). -⚠️ Special conditions apply for international connections, see [International TGV inOui / ICE trains](#international-tgv-inoui--ice-trains). \ -**Reservation possible:** yes \ -**Reservation required:** yes ⚠️ \ **Reservation cost:** \ Prices differ between peak and off-peak trains. Off-peak: €1.70 (1st/2nd class); peak: €15 (1st class), €10 (2nd class). The classification is not publicly available. -{{% /expander %}} +{{% /train-category %}} -{{% expander "Intercité (IC) ⚠️" traincategory "long-distance" %}} -**Description:** \ +{{% train-category + title="Intercité (IC)" + fip_accepted=true + reservation_required=true +%}} Intercity trains operated by SNCF, connecting various cities in France, mostly requiring reservations. -SNCF does not provide public information on which `IC` trains require reservations. If in doubt, check with SNCF or purchase a reservation. \ -**Reservation possible:** yes \ -**Reservation required:** mostly ⚠️ \ +SNCF does not provide public information on which `IC` trains require reservations. If in doubt, check with SNCF or purchase a reservation. + **Reservation cost:** \ Prices differ between peak and off-peak trains. Off-peak: €1.70 (1st/2nd class); peak: €15 (1st class), €10 (2nd class). The classification is not publicly available. -{{% /expander %}} +{{% /train-category %}} + +{{% train-category + title="Intercité de nuit" + fip_accepted=true + reservation_required=true +%}} +SNCF night trains within France. International Nightjet connections ended in December 2025. -{{% expander "Intercité de nuit ⚠️" traincategory "long-distance" %}} -**Description:** \ -SNCF night trains within France. International Nightjet connections ended in December 2025. \ -**Reservation possible:** yes \ -**Reservation required:** yes ⚠️ \ **Reservation cost:** depends on route and occupancy -{{% /expander %}} +{{% /train-category %}} ### Regional -{{% expander "Train express régional (TER) ⚠️ℹ️" traincategory "regional" %}} -**Description:** \ +{{% train-category + title="Train express régional (TER)" + fip_accepted=true + reservation_possible=true +%}} `TER` is SNCF's regional train, connecting various cities in France. +{{% /train-category %}} -ℹ️ On the Marseille – Toulon – Nice route, FIP is not valid as `TER` trains are operated by Transdev. \ -**Reservation possible:** sometimes \ -**Reservation required:** sometimes ⚠️ \ -Some lines from Paris require reservations, see [Reservation requirement in regional trains](#reservation-requirement-in-regional-trains) -{{% /expander %}} - -{{% expander "Réseau Express Régional (RER) ⚠️" traincategory "regional" %}} -**Description:** \ +{{% train-category + title="Réseau Express Régional (RER)" + fip_accepted=true +%}} RER is a suburban train operated by SNCF in Île de France (Greater Paris) and surrounding cities. - -⚠️ FIP is only valid on certain RER lines, see [Trains in Greater Paris](#trains-in-greater-paris) \ -**Reservation possible:** no -{{% /expander %}} +{{% /train-category %}} ## Ticket and Reservation Purchase diff --git a/layouts/partials/train-category.html b/layouts/partials/train-category.html new file mode 100644 index 00000000..38f1c81e --- /dev/null +++ b/layouts/partials/train-category.html @@ -0,0 +1,61 @@ + +
+
+
+
+ {{- partial "icon" "train" -}} + {{- .title -}} +
+
+
+ {{- if eq .fip_accepted true -}} + + {{ partial "icon" "check_circle" }} + FIP Accepted + + {{- else -}} + + {{ partial "icon" "dangerous" }} + FIP Not Accepted + + {{- end -}} + + {{- if eq .reservation_required true -}} + + {{ partial "icon" "calendar_month" }} + Reservation Required + + {{- else if eq .reservation_possible true -}} + + {{ partial "icon" "free_cancellation" }} + Reservation Possible + + {{- else -}} + + {{ partial "icon" "close" }} + No Reservation Possible + + {{- end -}} + + {{- if .info_available -}} + + {{ partial "icon" "info" }} + Information Available + + {{- end -}} +
+
+
+ {{- partial "icon" "keyboard_arrow_down" -}} +
+ +
+ {{- if .content -}} +
+ {{- .content -}} +
+ {{- end -}} + {{- if not (eq .fip_accepted true) -}} + FIP is not accepted for this train category! + {{- end -}} +
diff --git a/layouts/shortcodes/train-category.html b/layouts/shortcodes/train-category.html new file mode 100644 index 00000000..62bf7e81 --- /dev/null +++ b/layouts/shortcodes/train-category.html @@ -0,0 +1,17 @@ +{{- $data := dict + "title" (.Get "title") + "fip_accepted" (default true (.Get "fip_accepted")) + "reservation_required" (default false (.Get "reservation_required")) + "reservation_possible" (default false (.Get "reservation_possible")) + "info_available" (default false (.Get "info_available")) + "content" (.Inner | .Page.RenderString) +-}} + + +
+ {{- partial "train-category" $data -}} +
+ +
+ {{- partial "train-category" $data -}} +