`s.
+
+.nav {
+ // scss-docs-start nav-css-vars
+ --#{$prefix}nav-link-padding-x: #{$nav-link-padding-x};
+ --#{$prefix}nav-link-padding-y: #{$nav-link-padding-y};
+ @include rfs($nav-link-font-size, --#{$prefix}nav-link-font-size);
+ --#{$prefix}nav-link-font-weight: #{$nav-link-font-weight};
+ --#{$prefix}nav-link-color: #{$nav-link-color};
+ --#{$prefix}nav-link-hover-color: #{$nav-link-hover-color};
+ --#{$prefix}nav-link-disabled-color: #{$nav-link-disabled-color};
+ // scss-docs-end nav-css-vars
+
+ display: flex;
+ flex-wrap: wrap;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+
+.nav-link {
+ display: block;
+ padding: var(--#{$prefix}nav-link-padding-y) var(--#{$prefix}nav-link-padding-x);
+ @include font-size(var(--#{$prefix}nav-link-font-size));
+ font-weight: var(--#{$prefix}nav-link-font-weight);
+ color: var(--#{$prefix}nav-link-color);
+ text-decoration: if($link-decoration == none, null, none);
+ background: none;
+ border: 0;
+ @include transition($nav-link-transition);
+
+ &:hover,
+ &:focus {
+ color: var(--#{$prefix}nav-link-hover-color);
+ text-decoration: if($link-hover-decoration == underline, none, null);
+ }
+
+ &:focus-visible {
+ outline: 0;
+ box-shadow: $nav-link-focus-box-shadow;
+ }
+
+ // Disabled state lightens text
+ &.disabled,
+ &:disabled {
+ color: var(--#{$prefix}nav-link-disabled-color);
+ pointer-events: none;
+ cursor: default;
+ }
+}
+
+//
+// Tabs
+//
+
+.nav-tabs {
+ // scss-docs-start nav-tabs-css-vars
+ --#{$prefix}nav-tabs-border-width: #{$nav-tabs-border-width};
+ --#{$prefix}nav-tabs-border-color: #{$nav-tabs-border-color};
+ --#{$prefix}nav-tabs-border-radius: #{$nav-tabs-border-radius};
+ --#{$prefix}nav-tabs-link-hover-border-color: #{$nav-tabs-link-hover-border-color};
+ --#{$prefix}nav-tabs-link-active-color: #{$nav-tabs-link-active-color};
+ --#{$prefix}nav-tabs-link-active-bg: #{$nav-tabs-link-active-bg};
+ --#{$prefix}nav-tabs-link-active-border-color: #{$nav-tabs-link-active-border-color};
+ // scss-docs-end nav-tabs-css-vars
+
+ border-bottom: var(--#{$prefix}nav-tabs-border-width) solid var(--#{$prefix}nav-tabs-border-color);
+
+ .nav-link {
+ margin-bottom: calc(-1 * var(--#{$prefix}nav-tabs-border-width)); // stylelint-disable-line function-disallowed-list
+ border: var(--#{$prefix}nav-tabs-border-width) solid transparent;
+ @include border-top-radius(var(--#{$prefix}nav-tabs-border-radius));
+
+ &:hover,
+ &:focus {
+ // Prevents active .nav-link tab overlapping focus outline of previous/next .nav-link
+ isolation: isolate;
+ border-color: var(--#{$prefix}nav-tabs-link-hover-border-color);
+ }
+ }
+
+ .nav-link.active,
+ .nav-item.show .nav-link {
+ color: var(--#{$prefix}nav-tabs-link-active-color);
+ background-color: var(--#{$prefix}nav-tabs-link-active-bg);
+ border-color: var(--#{$prefix}nav-tabs-link-active-border-color);
+ }
+
+ .dropdown-menu {
+ // Make dropdown border overlap tab border
+ margin-top: calc(-1 * var(--#{$prefix}nav-tabs-border-width)); // stylelint-disable-line function-disallowed-list
+ // Remove the top rounded corners here since there is a hard edge above the menu
+ @include border-top-radius(0);
+ }
+}
+
+
+//
+// Pills
+//
+
+.nav-pills {
+ // scss-docs-start nav-pills-css-vars
+ --#{$prefix}nav-pills-border-radius: #{$nav-pills-border-radius};
+ --#{$prefix}nav-pills-link-active-color: #{$nav-pills-link-active-color};
+ --#{$prefix}nav-pills-link-active-bg: #{$nav-pills-link-active-bg};
+ // scss-docs-end nav-pills-css-vars
+
+ .nav-link {
+ @include border-radius(var(--#{$prefix}nav-pills-border-radius));
+ }
+
+ .nav-link.active,
+ .show > .nav-link {
+ color: var(--#{$prefix}nav-pills-link-active-color);
+ @include gradient-bg(var(--#{$prefix}nav-pills-link-active-bg));
+ }
+}
+
+
+//
+// Underline
+//
+
+.nav-underline {
+ // scss-docs-start nav-underline-css-vars
+ --#{$prefix}nav-underline-gap: #{$nav-underline-gap};
+ --#{$prefix}nav-underline-border-width: #{$nav-underline-border-width};
+ --#{$prefix}nav-underline-link-active-color: #{$nav-underline-link-active-color};
+ // scss-docs-end nav-underline-css-vars
+
+ gap: var(--#{$prefix}nav-underline-gap);
+
+ .nav-link {
+ padding-right: 0;
+ padding-left: 0;
+ border-bottom: var(--#{$prefix}nav-underline-border-width) solid transparent;
+
+ &:hover,
+ &:focus {
+ border-bottom-color: currentcolor;
+ }
+ }
+
+ .nav-link.active,
+ .show > .nav-link {
+ font-weight: $font-weight-bold;
+ color: var(--#{$prefix}nav-underline-link-active-color);
+ border-bottom-color: currentcolor;
+ }
+}
+
+
+//
+// Justified variants
+//
+
+.nav-fill {
+ > .nav-link,
+ .nav-item {
+ flex: 1 1 auto;
+ text-align: center;
+ }
+}
+
+.nav-justified {
+ > .nav-link,
+ .nav-item {
+ flex-grow: 1;
+ flex-basis: 0;
+ text-align: center;
+ }
+}
+
+.nav-fill,
+.nav-justified {
+ .nav-item .nav-link {
+ width: 100%; // Make sure button will grow
+ }
+}
+
+
+// Tabbable tabs
+//
+// Hide tabbable panes to start, show them when `.active`
+
+.tab-content {
+ > .tab-pane {
+ display: none;
+ }
+ > .active {
+ display: block;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_navbar.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_navbar.scss
new file mode 100644
index 0000000..86aa441
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_navbar.scss
@@ -0,0 +1,289 @@
+// Navbar
+//
+// Provide a static navbar from which we expand to create full-width, fixed, and
+// other navbar variations.
+
+.navbar {
+ // scss-docs-start navbar-css-vars
+ --#{$prefix}navbar-padding-x: #{if($navbar-padding-x == null, 0, $navbar-padding-x)};
+ --#{$prefix}navbar-padding-y: #{$navbar-padding-y};
+ --#{$prefix}navbar-color: #{$navbar-light-color};
+ --#{$prefix}navbar-hover-color: #{$navbar-light-hover-color};
+ --#{$prefix}navbar-disabled-color: #{$navbar-light-disabled-color};
+ --#{$prefix}navbar-active-color: #{$navbar-light-active-color};
+ --#{$prefix}navbar-brand-padding-y: #{$navbar-brand-padding-y};
+ --#{$prefix}navbar-brand-margin-end: #{$navbar-brand-margin-end};
+ --#{$prefix}navbar-brand-font-size: #{$navbar-brand-font-size};
+ --#{$prefix}navbar-brand-color: #{$navbar-light-brand-color};
+ --#{$prefix}navbar-brand-hover-color: #{$navbar-light-brand-hover-color};
+ --#{$prefix}navbar-nav-link-padding-x: #{$navbar-nav-link-padding-x};
+ --#{$prefix}navbar-toggler-padding-y: #{$navbar-toggler-padding-y};
+ --#{$prefix}navbar-toggler-padding-x: #{$navbar-toggler-padding-x};
+ --#{$prefix}navbar-toggler-font-size: #{$navbar-toggler-font-size};
+ --#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-light-toggler-icon-bg)};
+ --#{$prefix}navbar-toggler-border-color: #{$navbar-light-toggler-border-color};
+ --#{$prefix}navbar-toggler-border-radius: #{$navbar-toggler-border-radius};
+ --#{$prefix}navbar-toggler-focus-width: #{$navbar-toggler-focus-width};
+ --#{$prefix}navbar-toggler-transition: #{$navbar-toggler-transition};
+ // scss-docs-end navbar-css-vars
+
+ position: relative;
+ display: flex;
+ flex-wrap: wrap; // allow us to do the line break for collapsing content
+ align-items: center;
+ justify-content: space-between; // space out brand from logo
+ padding: var(--#{$prefix}navbar-padding-y) var(--#{$prefix}navbar-padding-x);
+ @include gradient-bg();
+
+ // Because flex properties aren't inherited, we need to redeclare these first
+ // few properties so that content nested within behave properly.
+ // The `flex-wrap` property is inherited to simplify the expanded navbars
+ %container-flex-properties {
+ display: flex;
+ flex-wrap: inherit;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ > .container,
+ > .container-fluid {
+ @extend %container-flex-properties;
+ }
+
+ @each $breakpoint, $container-max-width in $container-max-widths {
+ > .container#{breakpoint-infix($breakpoint, $container-max-widths)} {
+ @extend %container-flex-properties;
+ }
+ }
+}
+
+
+// Navbar brand
+//
+// Used for brand, project, or site names.
+
+.navbar-brand {
+ padding-top: var(--#{$prefix}navbar-brand-padding-y);
+ padding-bottom: var(--#{$prefix}navbar-brand-padding-y);
+ margin-right: var(--#{$prefix}navbar-brand-margin-end);
+ @include font-size(var(--#{$prefix}navbar-brand-font-size));
+ color: var(--#{$prefix}navbar-brand-color);
+ text-decoration: if($link-decoration == none, null, none);
+ white-space: nowrap;
+
+ &:hover,
+ &:focus {
+ color: var(--#{$prefix}navbar-brand-hover-color);
+ text-decoration: if($link-hover-decoration == underline, none, null);
+ }
+}
+
+
+// Navbar nav
+//
+// Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`).
+
+.navbar-nav {
+ // scss-docs-start navbar-nav-css-vars
+ --#{$prefix}nav-link-padding-x: 0;
+ --#{$prefix}nav-link-padding-y: #{$nav-link-padding-y};
+ @include rfs($nav-link-font-size, --#{$prefix}nav-link-font-size);
+ --#{$prefix}nav-link-font-weight: #{$nav-link-font-weight};
+ --#{$prefix}nav-link-color: var(--#{$prefix}navbar-color);
+ --#{$prefix}nav-link-hover-color: var(--#{$prefix}navbar-hover-color);
+ --#{$prefix}nav-link-disabled-color: var(--#{$prefix}navbar-disabled-color);
+ // scss-docs-end navbar-nav-css-vars
+
+ display: flex;
+ flex-direction: column; // cannot use `inherit` to get the `.navbar`s value
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+
+ .nav-link {
+ &.active,
+ &.show {
+ color: var(--#{$prefix}navbar-active-color);
+ }
+ }
+
+ .dropdown-menu {
+ position: static;
+ }
+}
+
+
+// Navbar text
+//
+//
+
+.navbar-text {
+ padding-top: $nav-link-padding-y;
+ padding-bottom: $nav-link-padding-y;
+ color: var(--#{$prefix}navbar-color);
+
+ a,
+ a:hover,
+ a:focus {
+ color: var(--#{$prefix}navbar-active-color);
+ }
+}
+
+
+// Responsive navbar
+//
+// Custom styles for responsive collapsing and toggling of navbar contents.
+// Powered by the collapse Bootstrap JavaScript plugin.
+
+// When collapsed, prevent the toggleable navbar contents from appearing in
+// the default flexbox row orientation. Requires the use of `flex-wrap: wrap`
+// on the `.navbar` parent.
+.navbar-collapse {
+ flex-grow: 1;
+ flex-basis: 100%;
+ // For always expanded or extra full navbars, ensure content aligns itself
+ // properly vertically. Can be easily overridden with flex utilities.
+ align-items: center;
+}
+
+// Button for toggling the navbar when in its collapsed state
+.navbar-toggler {
+ padding: var(--#{$prefix}navbar-toggler-padding-y) var(--#{$prefix}navbar-toggler-padding-x);
+ @include font-size(var(--#{$prefix}navbar-toggler-font-size));
+ line-height: 1;
+ color: var(--#{$prefix}navbar-color);
+ background-color: transparent; // remove default button style
+ border: var(--#{$prefix}border-width) solid var(--#{$prefix}navbar-toggler-border-color); // remove default button style
+ @include border-radius(var(--#{$prefix}navbar-toggler-border-radius));
+ @include transition(var(--#{$prefix}navbar-toggler-transition));
+
+ &:hover {
+ text-decoration: none;
+ }
+
+ &:focus {
+ text-decoration: none;
+ outline: 0;
+ box-shadow: 0 0 0 var(--#{$prefix}navbar-toggler-focus-width);
+ }
+}
+
+// Keep as a separate element so folks can easily override it with another icon
+// or image file as needed.
+.navbar-toggler-icon {
+ display: inline-block;
+ width: 1.5em;
+ height: 1.5em;
+ vertical-align: middle;
+ background-image: var(--#{$prefix}navbar-toggler-icon-bg);
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: 100%;
+}
+
+.navbar-nav-scroll {
+ max-height: var(--#{$prefix}scroll-height, 75vh);
+ overflow-y: auto;
+}
+
+// scss-docs-start navbar-expand-loop
+// Generate series of `.navbar-expand-*` responsive classes for configuring
+// where your navbar collapses.
+.navbar-expand {
+ @each $breakpoint in map-keys($grid-breakpoints) {
+ $next: breakpoint-next($breakpoint, $grid-breakpoints);
+ $infix: breakpoint-infix($next, $grid-breakpoints);
+
+ // stylelint-disable-next-line scss/selector-no-union-class-name
+ {$infix} {
+ @include media-breakpoint-up($next) {
+ flex-wrap: nowrap;
+ justify-content: flex-start;
+
+ .navbar-nav {
+ flex-direction: row;
+
+ .dropdown-menu {
+ position: absolute;
+ }
+
+ .nav-link {
+ padding-right: var(--#{$prefix}navbar-nav-link-padding-x);
+ padding-left: var(--#{$prefix}navbar-nav-link-padding-x);
+ }
+ }
+
+ .navbar-nav-scroll {
+ overflow: visible;
+ }
+
+ .navbar-collapse {
+ display: flex !important; // stylelint-disable-line declaration-no-important
+ flex-basis: auto;
+ }
+
+ .navbar-toggler {
+ display: none;
+ }
+
+ .offcanvas {
+ // stylelint-disable declaration-no-important
+ position: static;
+ z-index: auto;
+ flex-grow: 1;
+ width: auto !important;
+ height: auto !important;
+ visibility: visible !important;
+ background-color: transparent !important;
+ border: 0 !important;
+ transform: none !important;
+ @include box-shadow(none);
+ @include transition(none);
+ // stylelint-enable declaration-no-important
+
+ .offcanvas-header {
+ display: none;
+ }
+
+ .offcanvas-body {
+ display: flex;
+ flex-grow: 0;
+ padding: 0;
+ overflow-y: visible;
+ }
+ }
+ }
+ }
+ }
+}
+// scss-docs-end navbar-expand-loop
+
+// Navbar themes
+//
+// Styles for switching between navbars with light or dark background.
+
+.navbar-light {
+ @include deprecate("`.navbar-light`", "v5.2.0", "v6.0.0", true);
+}
+
+.navbar-dark,
+.navbar[data-bs-theme="dark"] {
+ // scss-docs-start navbar-dark-css-vars
+ --#{$prefix}navbar-color: #{$navbar-dark-color};
+ --#{$prefix}navbar-hover-color: #{$navbar-dark-hover-color};
+ --#{$prefix}navbar-disabled-color: #{$navbar-dark-disabled-color};
+ --#{$prefix}navbar-active-color: #{$navbar-dark-active-color};
+ --#{$prefix}navbar-brand-color: #{$navbar-dark-brand-color};
+ --#{$prefix}navbar-brand-hover-color: #{$navbar-dark-brand-hover-color};
+ --#{$prefix}navbar-toggler-border-color: #{$navbar-dark-toggler-border-color};
+ --#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
+ // scss-docs-end navbar-dark-css-vars
+}
+
+@if $enable-dark-mode {
+ @include color-mode(dark) {
+ .navbar-toggler-icon {
+ --#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_offcanvas.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_offcanvas.scss
new file mode 100644
index 0000000..b40b2cd
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_offcanvas.scss
@@ -0,0 +1,147 @@
+// stylelint-disable function-disallowed-list
+
+%offcanvas-css-vars {
+ // scss-docs-start offcanvas-css-vars
+ --#{$prefix}offcanvas-zindex: #{$zindex-offcanvas};
+ --#{$prefix}offcanvas-width: #{$offcanvas-horizontal-width};
+ --#{$prefix}offcanvas-height: #{$offcanvas-vertical-height};
+ --#{$prefix}offcanvas-padding-x: #{$offcanvas-padding-x};
+ --#{$prefix}offcanvas-padding-y: #{$offcanvas-padding-y};
+ --#{$prefix}offcanvas-color: #{$offcanvas-color};
+ --#{$prefix}offcanvas-bg: #{$offcanvas-bg-color};
+ --#{$prefix}offcanvas-border-width: #{$offcanvas-border-width};
+ --#{$prefix}offcanvas-border-color: #{$offcanvas-border-color};
+ --#{$prefix}offcanvas-box-shadow: #{$offcanvas-box-shadow};
+ --#{$prefix}offcanvas-transition: #{transform $offcanvas-transition-duration ease-in-out};
+ --#{$prefix}offcanvas-title-line-height: #{$offcanvas-title-line-height};
+ // scss-docs-end offcanvas-css-vars
+}
+
+@each $breakpoint in map-keys($grid-breakpoints) {
+ $next: breakpoint-next($breakpoint, $grid-breakpoints);
+ $infix: breakpoint-infix($next, $grid-breakpoints);
+
+ .offcanvas#{$infix} {
+ @extend %offcanvas-css-vars;
+ }
+}
+
+@each $breakpoint in map-keys($grid-breakpoints) {
+ $next: breakpoint-next($breakpoint, $grid-breakpoints);
+ $infix: breakpoint-infix($next, $grid-breakpoints);
+
+ .offcanvas#{$infix} {
+ @include media-breakpoint-down($next) {
+ position: fixed;
+ bottom: 0;
+ z-index: var(--#{$prefix}offcanvas-zindex);
+ display: flex;
+ flex-direction: column;
+ max-width: 100%;
+ color: var(--#{$prefix}offcanvas-color);
+ visibility: hidden;
+ background-color: var(--#{$prefix}offcanvas-bg);
+ background-clip: padding-box;
+ outline: 0;
+ @include box-shadow(var(--#{$prefix}offcanvas-box-shadow));
+ @include transition(var(--#{$prefix}offcanvas-transition));
+
+ &.offcanvas-start {
+ top: 0;
+ left: 0;
+ width: var(--#{$prefix}offcanvas-width);
+ border-right: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
+ transform: translateX(-100%);
+ }
+
+ &.offcanvas-end {
+ top: 0;
+ right: 0;
+ width: var(--#{$prefix}offcanvas-width);
+ border-left: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
+ transform: translateX(100%);
+ }
+
+ &.offcanvas-top {
+ top: 0;
+ right: 0;
+ left: 0;
+ height: var(--#{$prefix}offcanvas-height);
+ max-height: 100%;
+ border-bottom: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
+ transform: translateY(-100%);
+ }
+
+ &.offcanvas-bottom {
+ right: 0;
+ left: 0;
+ height: var(--#{$prefix}offcanvas-height);
+ max-height: 100%;
+ border-top: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
+ transform: translateY(100%);
+ }
+
+ &.showing,
+ &.show:not(.hiding) {
+ transform: none;
+ }
+
+ &.showing,
+ &.hiding,
+ &.show {
+ visibility: visible;
+ }
+ }
+
+ @if not ($infix == "") {
+ @include media-breakpoint-up($next) {
+ --#{$prefix}offcanvas-height: auto;
+ --#{$prefix}offcanvas-border-width: 0;
+ background-color: transparent !important; // stylelint-disable-line declaration-no-important
+
+ .offcanvas-header {
+ display: none;
+ }
+
+ .offcanvas-body {
+ display: flex;
+ flex-grow: 0;
+ padding: 0;
+ overflow-y: visible;
+ // Reset `background-color` in case `.bg-*` classes are used in offcanvas
+ background-color: transparent !important; // stylelint-disable-line declaration-no-important
+ }
+ }
+ }
+ }
+}
+
+.offcanvas-backdrop {
+ @include overlay-backdrop($zindex-offcanvas-backdrop, $offcanvas-backdrop-bg, $offcanvas-backdrop-opacity);
+}
+
+.offcanvas-header {
+ display: flex;
+ align-items: center;
+ padding: var(--#{$prefix}offcanvas-padding-y) var(--#{$prefix}offcanvas-padding-x);
+
+ .btn-close {
+ padding: calc(var(--#{$prefix}offcanvas-padding-y) * .5) calc(var(--#{$prefix}offcanvas-padding-x) * .5);
+ // Split properties to avoid invalid calc() function if value is 0
+ margin-top: calc(-.5 * var(--#{$prefix}offcanvas-padding-y));
+ margin-right: calc(-.5 * var(--#{$prefix}offcanvas-padding-x));
+ margin-bottom: calc(-.5 * var(--#{$prefix}offcanvas-padding-y));
+ margin-left: auto;
+ }
+}
+
+.offcanvas-title {
+ margin-bottom: 0;
+ line-height: var(--#{$prefix}offcanvas-title-line-height);
+}
+
+.offcanvas-body {
+ flex-grow: 1;
+ padding: var(--#{$prefix}offcanvas-padding-y) var(--#{$prefix}offcanvas-padding-x);
+ overflow-y: auto;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_pagination.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_pagination.scss
new file mode 100644
index 0000000..9f09694
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_pagination.scss
@@ -0,0 +1,109 @@
+.pagination {
+ // scss-docs-start pagination-css-vars
+ --#{$prefix}pagination-padding-x: #{$pagination-padding-x};
+ --#{$prefix}pagination-padding-y: #{$pagination-padding-y};
+ @include rfs($pagination-font-size, --#{$prefix}pagination-font-size);
+ --#{$prefix}pagination-color: #{$pagination-color};
+ --#{$prefix}pagination-bg: #{$pagination-bg};
+ --#{$prefix}pagination-border-width: #{$pagination-border-width};
+ --#{$prefix}pagination-border-color: #{$pagination-border-color};
+ --#{$prefix}pagination-border-radius: #{$pagination-border-radius};
+ --#{$prefix}pagination-hover-color: #{$pagination-hover-color};
+ --#{$prefix}pagination-hover-bg: #{$pagination-hover-bg};
+ --#{$prefix}pagination-hover-border-color: #{$pagination-hover-border-color};
+ --#{$prefix}pagination-focus-color: #{$pagination-focus-color};
+ --#{$prefix}pagination-focus-bg: #{$pagination-focus-bg};
+ --#{$prefix}pagination-focus-box-shadow: #{$pagination-focus-box-shadow};
+ --#{$prefix}pagination-active-color: #{$pagination-active-color};
+ --#{$prefix}pagination-active-bg: #{$pagination-active-bg};
+ --#{$prefix}pagination-active-border-color: #{$pagination-active-border-color};
+ --#{$prefix}pagination-disabled-color: #{$pagination-disabled-color};
+ --#{$prefix}pagination-disabled-bg: #{$pagination-disabled-bg};
+ --#{$prefix}pagination-disabled-border-color: #{$pagination-disabled-border-color};
+ // scss-docs-end pagination-css-vars
+
+ display: flex;
+ @include list-unstyled();
+}
+
+.page-link {
+ position: relative;
+ display: block;
+ padding: var(--#{$prefix}pagination-padding-y) var(--#{$prefix}pagination-padding-x);
+ @include font-size(var(--#{$prefix}pagination-font-size));
+ color: var(--#{$prefix}pagination-color);
+ text-decoration: if($link-decoration == none, null, none);
+ background-color: var(--#{$prefix}pagination-bg);
+ border: var(--#{$prefix}pagination-border-width) solid var(--#{$prefix}pagination-border-color);
+ @include transition($pagination-transition);
+
+ &:hover {
+ z-index: 2;
+ color: var(--#{$prefix}pagination-hover-color);
+ text-decoration: if($link-hover-decoration == underline, none, null);
+ background-color: var(--#{$prefix}pagination-hover-bg);
+ border-color: var(--#{$prefix}pagination-hover-border-color);
+ }
+
+ &:focus {
+ z-index: 3;
+ color: var(--#{$prefix}pagination-focus-color);
+ background-color: var(--#{$prefix}pagination-focus-bg);
+ outline: $pagination-focus-outline;
+ box-shadow: var(--#{$prefix}pagination-focus-box-shadow);
+ }
+
+ &.active,
+ .active > & {
+ z-index: 3;
+ color: var(--#{$prefix}pagination-active-color);
+ @include gradient-bg(var(--#{$prefix}pagination-active-bg));
+ border-color: var(--#{$prefix}pagination-active-border-color);
+ }
+
+ &.disabled,
+ .disabled > & {
+ color: var(--#{$prefix}pagination-disabled-color);
+ pointer-events: none;
+ background-color: var(--#{$prefix}pagination-disabled-bg);
+ border-color: var(--#{$prefix}pagination-disabled-border-color);
+ }
+}
+
+.page-item {
+ &:not(:first-child) .page-link {
+ margin-left: $pagination-margin-start;
+ }
+
+ @if $pagination-margin-start == calc(-1 * #{$pagination-border-width}) {
+ &:first-child {
+ .page-link {
+ @include border-start-radius(var(--#{$prefix}pagination-border-radius));
+ }
+ }
+
+ &:last-child {
+ .page-link {
+ @include border-end-radius(var(--#{$prefix}pagination-border-radius));
+ }
+ }
+ } @else {
+ // Add border-radius to all pageLinks in case they have left margin
+ .page-link {
+ @include border-radius(var(--#{$prefix}pagination-border-radius));
+ }
+ }
+}
+
+
+//
+// Sizing
+//
+
+.pagination-lg {
+ @include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $pagination-border-radius-lg);
+}
+
+.pagination-sm {
+ @include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $pagination-border-radius-sm);
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_placeholders.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_placeholders.scss
new file mode 100644
index 0000000..6e32e1c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_placeholders.scss
@@ -0,0 +1,51 @@
+.placeholder {
+ display: inline-block;
+ min-height: 1em;
+ vertical-align: middle;
+ cursor: wait;
+ background-color: currentcolor;
+ opacity: $placeholder-opacity-max;
+
+ &.btn::before {
+ display: inline-block;
+ content: "";
+ }
+}
+
+// Sizing
+.placeholder-xs {
+ min-height: .6em;
+}
+
+.placeholder-sm {
+ min-height: .8em;
+}
+
+.placeholder-lg {
+ min-height: 1.2em;
+}
+
+// Animation
+.placeholder-glow {
+ .placeholder {
+ animation: placeholder-glow 2s ease-in-out infinite;
+ }
+}
+
+@keyframes placeholder-glow {
+ 50% {
+ opacity: $placeholder-opacity-min;
+ }
+}
+
+.placeholder-wave {
+ mask-image: linear-gradient(130deg, $black 55%, rgba(0, 0, 0, (1 - $placeholder-opacity-min)) 75%, $black 95%);
+ mask-size: 200% 100%;
+ animation: placeholder-wave 2s linear infinite;
+}
+
+@keyframes placeholder-wave {
+ 100% {
+ mask-position: -200% 0%;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_popover.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_popover.scss
new file mode 100644
index 0000000..7b69f62
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_popover.scss
@@ -0,0 +1,196 @@
+.popover {
+ // scss-docs-start popover-css-vars
+ --#{$prefix}popover-zindex: #{$zindex-popover};
+ --#{$prefix}popover-max-width: #{$popover-max-width};
+ @include rfs($popover-font-size, --#{$prefix}popover-font-size);
+ --#{$prefix}popover-bg: #{$popover-bg};
+ --#{$prefix}popover-border-width: #{$popover-border-width};
+ --#{$prefix}popover-border-color: #{$popover-border-color};
+ --#{$prefix}popover-border-radius: #{$popover-border-radius};
+ --#{$prefix}popover-inner-border-radius: #{$popover-inner-border-radius};
+ --#{$prefix}popover-box-shadow: #{$popover-box-shadow};
+ --#{$prefix}popover-header-padding-x: #{$popover-header-padding-x};
+ --#{$prefix}popover-header-padding-y: #{$popover-header-padding-y};
+ @include rfs($popover-header-font-size, --#{$prefix}popover-header-font-size);
+ --#{$prefix}popover-header-color: #{$popover-header-color};
+ --#{$prefix}popover-header-bg: #{$popover-header-bg};
+ --#{$prefix}popover-body-padding-x: #{$popover-body-padding-x};
+ --#{$prefix}popover-body-padding-y: #{$popover-body-padding-y};
+ --#{$prefix}popover-body-color: #{$popover-body-color};
+ --#{$prefix}popover-arrow-width: #{$popover-arrow-width};
+ --#{$prefix}popover-arrow-height: #{$popover-arrow-height};
+ --#{$prefix}popover-arrow-border: var(--#{$prefix}popover-border-color);
+ // scss-docs-end popover-css-vars
+
+ z-index: var(--#{$prefix}popover-zindex);
+ display: block;
+ max-width: var(--#{$prefix}popover-max-width);
+ // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
+ // So reset our font and text properties to avoid inheriting weird values.
+ @include reset-text();
+ @include font-size(var(--#{$prefix}popover-font-size));
+ // Allow breaking very long words so they don't overflow the popover's bounds
+ word-wrap: break-word;
+ background-color: var(--#{$prefix}popover-bg);
+ background-clip: padding-box;
+ border: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-border-color);
+ @include border-radius(var(--#{$prefix}popover-border-radius));
+ @include box-shadow(var(--#{$prefix}popover-box-shadow));
+
+ .popover-arrow {
+ display: block;
+ width: var(--#{$prefix}popover-arrow-width);
+ height: var(--#{$prefix}popover-arrow-height);
+
+ &::before,
+ &::after {
+ position: absolute;
+ display: block;
+ content: "";
+ border-color: transparent;
+ border-style: solid;
+ border-width: 0;
+ }
+ }
+}
+
+.bs-popover-top {
+ > .popover-arrow {
+ bottom: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
+
+ &::before,
+ &::after {
+ border-width: var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
+ }
+
+ &::before {
+ bottom: 0;
+ border-top-color: var(--#{$prefix}popover-arrow-border);
+ }
+
+ &::after {
+ bottom: var(--#{$prefix}popover-border-width);
+ border-top-color: var(--#{$prefix}popover-bg);
+ }
+ }
+}
+
+/* rtl:begin:ignore */
+.bs-popover-end {
+ > .popover-arrow {
+ left: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
+ width: var(--#{$prefix}popover-arrow-height);
+ height: var(--#{$prefix}popover-arrow-width);
+
+ &::before,
+ &::after {
+ border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
+ }
+
+ &::before {
+ left: 0;
+ border-right-color: var(--#{$prefix}popover-arrow-border);
+ }
+
+ &::after {
+ left: var(--#{$prefix}popover-border-width);
+ border-right-color: var(--#{$prefix}popover-bg);
+ }
+ }
+}
+
+/* rtl:end:ignore */
+
+.bs-popover-bottom {
+ > .popover-arrow {
+ top: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
+
+ &::before,
+ &::after {
+ border-width: 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height); // stylelint-disable-line function-disallowed-list
+ }
+
+ &::before {
+ top: 0;
+ border-bottom-color: var(--#{$prefix}popover-arrow-border);
+ }
+
+ &::after {
+ top: var(--#{$prefix}popover-border-width);
+ border-bottom-color: var(--#{$prefix}popover-bg);
+ }
+ }
+
+ // This will remove the popover-header's border just below the arrow
+ .popover-header::before {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ display: block;
+ width: var(--#{$prefix}popover-arrow-width);
+ margin-left: calc(-.5 * var(--#{$prefix}popover-arrow-width)); // stylelint-disable-line function-disallowed-list
+ content: "";
+ border-bottom: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-header-bg);
+ }
+}
+
+/* rtl:begin:ignore */
+.bs-popover-start {
+ > .popover-arrow {
+ right: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
+ width: var(--#{$prefix}popover-arrow-height);
+ height: var(--#{$prefix}popover-arrow-width);
+
+ &::before,
+ &::after {
+ border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height); // stylelint-disable-line function-disallowed-list
+ }
+
+ &::before {
+ right: 0;
+ border-left-color: var(--#{$prefix}popover-arrow-border);
+ }
+
+ &::after {
+ right: var(--#{$prefix}popover-border-width);
+ border-left-color: var(--#{$prefix}popover-bg);
+ }
+ }
+}
+
+/* rtl:end:ignore */
+
+.bs-popover-auto {
+ &[data-popper-placement^="top"] {
+ @extend .bs-popover-top;
+ }
+ &[data-popper-placement^="right"] {
+ @extend .bs-popover-end;
+ }
+ &[data-popper-placement^="bottom"] {
+ @extend .bs-popover-bottom;
+ }
+ &[data-popper-placement^="left"] {
+ @extend .bs-popover-start;
+ }
+}
+
+// Offset the popover to account for the popover arrow
+.popover-header {
+ padding: var(--#{$prefix}popover-header-padding-y) var(--#{$prefix}popover-header-padding-x);
+ margin-bottom: 0; // Reset the default from Reboot
+ @include font-size(var(--#{$prefix}popover-header-font-size));
+ color: var(--#{$prefix}popover-header-color);
+ background-color: var(--#{$prefix}popover-header-bg);
+ border-bottom: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-border-color);
+ @include border-top-radius(var(--#{$prefix}popover-inner-border-radius));
+
+ &:empty {
+ display: none;
+ }
+}
+
+.popover-body {
+ padding: var(--#{$prefix}popover-body-padding-y) var(--#{$prefix}popover-body-padding-x);
+ color: var(--#{$prefix}popover-body-color);
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_progress.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_progress.scss
new file mode 100644
index 0000000..732365c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_progress.scss
@@ -0,0 +1,68 @@
+// Disable animation if transitions are disabled
+
+// scss-docs-start progress-keyframes
+@if $enable-transitions {
+ @keyframes progress-bar-stripes {
+ 0% { background-position-x: var(--#{$prefix}progress-height); }
+ }
+}
+// scss-docs-end progress-keyframes
+
+.progress,
+.progress-stacked {
+ // scss-docs-start progress-css-vars
+ --#{$prefix}progress-height: #{$progress-height};
+ @include rfs($progress-font-size, --#{$prefix}progress-font-size);
+ --#{$prefix}progress-bg: #{$progress-bg};
+ --#{$prefix}progress-border-radius: #{$progress-border-radius};
+ --#{$prefix}progress-box-shadow: #{$progress-box-shadow};
+ --#{$prefix}progress-bar-color: #{$progress-bar-color};
+ --#{$prefix}progress-bar-bg: #{$progress-bar-bg};
+ --#{$prefix}progress-bar-transition: #{$progress-bar-transition};
+ // scss-docs-end progress-css-vars
+
+ display: flex;
+ height: var(--#{$prefix}progress-height);
+ overflow: hidden; // force rounded corners by cropping it
+ @include font-size(var(--#{$prefix}progress-font-size));
+ background-color: var(--#{$prefix}progress-bg);
+ @include border-radius(var(--#{$prefix}progress-border-radius));
+ @include box-shadow(var(--#{$prefix}progress-box-shadow));
+}
+
+.progress-bar {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ overflow: hidden;
+ color: var(--#{$prefix}progress-bar-color);
+ text-align: center;
+ white-space: nowrap;
+ background-color: var(--#{$prefix}progress-bar-bg);
+ @include transition(var(--#{$prefix}progress-bar-transition));
+}
+
+.progress-bar-striped {
+ @include gradient-striped();
+ background-size: var(--#{$prefix}progress-height) var(--#{$prefix}progress-height);
+}
+
+.progress-stacked > .progress {
+ overflow: visible;
+}
+
+.progress-stacked > .progress > .progress-bar {
+ width: 100%;
+}
+
+@if $enable-transitions {
+ .progress-bar-animated {
+ animation: $progress-bar-animation-timing progress-bar-stripes;
+
+ @if $enable-reduced-motion {
+ @media (prefers-reduced-motion: reduce) {
+ animation: none;
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_reboot.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_reboot.scss
new file mode 100644
index 0000000..524645f
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_reboot.scss
@@ -0,0 +1,617 @@
+// stylelint-disable declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix
+
+
+// Reboot
+//
+// Normalization of HTML elements, manually forked from Normalize.css to remove
+// styles targeting irrelevant browsers while applying new styles.
+//
+// Normalize is licensed MIT. https://github.com/necolas/normalize.css
+
+
+// Document
+//
+// Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+
+// Root
+//
+// Ability to the value of the root font sizes, affecting the value of `rem`.
+// null by default, thus nothing is generated.
+
+:root {
+ @if $font-size-root != null {
+ @include font-size(var(--#{$prefix}root-font-size));
+ }
+
+ @if $enable-smooth-scroll {
+ @media (prefers-reduced-motion: no-preference) {
+ scroll-behavior: smooth;
+ }
+ }
+}
+
+
+// Body
+//
+// 1. Remove the margin in all browsers.
+// 2. As a best practice, apply a default `background-color`.
+// 3. Prevent adjustments of font size after orientation changes in iOS.
+// 4. Change the default tap highlight to be completely transparent in iOS.
+
+// scss-docs-start reboot-body-rules
+body {
+ margin: 0; // 1
+ font-family: var(--#{$prefix}body-font-family);
+ @include font-size(var(--#{$prefix}body-font-size));
+ font-weight: var(--#{$prefix}body-font-weight);
+ line-height: var(--#{$prefix}body-line-height);
+ color: var(--#{$prefix}body-color);
+ text-align: var(--#{$prefix}body-text-align);
+ background-color: var(--#{$prefix}body-bg); // 2
+ -webkit-text-size-adjust: 100%; // 3
+ -webkit-tap-highlight-color: rgba($black, 0); // 4
+}
+// scss-docs-end reboot-body-rules
+
+
+// Content grouping
+//
+// 1. Reset Firefox's gray color
+
+hr {
+ margin: $hr-margin-y 0;
+ color: $hr-color; // 1
+ border: 0;
+ border-top: $hr-border-width solid $hr-border-color;
+ opacity: $hr-opacity;
+}
+
+
+// Typography
+//
+// 1. Remove top margins from headings
+// By default, ``-`` all receive top and bottom margins. We nuke the top
+// margin for easier control within type scales as it avoids margin collapsing.
+
+%heading {
+ margin-top: 0; // 1
+ margin-bottom: $headings-margin-bottom;
+ font-family: $headings-font-family;
+ font-style: $headings-font-style;
+ font-weight: $headings-font-weight;
+ line-height: $headings-line-height;
+ color: var(--#{$prefix}heading-color);
+}
+
+h1 {
+ @extend %heading;
+ @include font-size($h1-font-size);
+}
+
+h2 {
+ @extend %heading;
+ @include font-size($h2-font-size);
+}
+
+h3 {
+ @extend %heading;
+ @include font-size($h3-font-size);
+}
+
+h4 {
+ @extend %heading;
+ @include font-size($h4-font-size);
+}
+
+h5 {
+ @extend %heading;
+ @include font-size($h5-font-size);
+}
+
+h6 {
+ @extend %heading;
+ @include font-size($h6-font-size);
+}
+
+
+// Reset margins on paragraphs
+//
+// Similarly, the top margin on ` `s get reset. However, we also reset the
+// bottom margin to use `rem` units instead of `em`.
+
+p {
+ margin-top: 0;
+ margin-bottom: $paragraph-margin-bottom;
+}
+
+
+// Abbreviations
+//
+// 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari.
+// 2. Add explicit cursor to indicate changed behavior.
+// 3. Prevent the text-decoration to be skipped.
+
+abbr[title] {
+ text-decoration: underline dotted; // 1
+ cursor: help; // 2
+ text-decoration-skip-ink: none; // 3
+}
+
+
+// Address
+
+address {
+ margin-bottom: 1rem;
+ font-style: normal;
+ line-height: inherit;
+}
+
+
+// Lists
+
+ol,
+ul {
+ padding-left: 2rem;
+}
+
+ol,
+ul,
+dl {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+ margin-bottom: 0;
+}
+
+dt {
+ font-weight: $dt-font-weight;
+}
+
+// 1. Undo browser default
+
+dd {
+ margin-bottom: .5rem;
+ margin-left: 0; // 1
+}
+
+
+// Blockquote
+
+blockquote {
+ margin: 0 0 1rem;
+}
+
+
+// Strong
+//
+// Add the correct font weight in Chrome, Edge, and Safari
+
+b,
+strong {
+ font-weight: $font-weight-bolder;
+}
+
+
+// Small
+//
+// Add the correct font size in all browsers
+
+small {
+ @include font-size($small-font-size);
+}
+
+
+// Mark
+
+mark {
+ padding: $mark-padding;
+ color: var(--#{$prefix}highlight-color);
+ background-color: var(--#{$prefix}highlight-bg);
+}
+
+
+// Sub and Sup
+//
+// Prevent `sub` and `sup` elements from affecting the line height in
+// all browsers.
+
+sub,
+sup {
+ position: relative;
+ @include font-size($sub-sup-font-size);
+ line-height: 0;
+ vertical-align: baseline;
+}
+
+sub { bottom: -.25em; }
+sup { top: -.5em; }
+
+
+// Links
+
+a {
+ color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, 1));
+ text-decoration: $link-decoration;
+
+ &:hover {
+ --#{$prefix}link-color-rgb: var(--#{$prefix}link-hover-color-rgb);
+ text-decoration: $link-hover-decoration;
+ }
+}
+
+// And undo these styles for placeholder links/named anchors (without href).
+// It would be more straightforward to just use a[href] in previous block, but that
+// causes specificity issues in many other styles that are too complex to fix.
+// See https://github.com/twbs/bootstrap/issues/19402
+
+a:not([href]):not([class]) {
+ &,
+ &:hover {
+ color: inherit;
+ text-decoration: none;
+ }
+}
+
+
+// Code
+
+pre,
+code,
+kbd,
+samp {
+ font-family: $font-family-code;
+ @include font-size(1em); // Correct the odd `em` font sizing in all browsers.
+}
+
+// 1. Remove browser default top margin
+// 2. Reset browser default of `1em` to use `rem`s
+// 3. Don't allow content to break outside
+
+pre {
+ display: block;
+ margin-top: 0; // 1
+ margin-bottom: 1rem; // 2
+ overflow: auto; // 3
+ @include font-size($code-font-size);
+ color: $pre-color;
+
+ // Account for some code outputs that place code tags in pre tags
+ code {
+ @include font-size(inherit);
+ color: inherit;
+ word-break: normal;
+ }
+}
+
+code {
+ @include font-size($code-font-size);
+ color: var(--#{$prefix}code-color);
+ word-wrap: break-word;
+
+ // Streamline the style when inside anchors to avoid broken underline and more
+ a > & {
+ color: inherit;
+ }
+}
+
+kbd {
+ padding: $kbd-padding-y $kbd-padding-x;
+ @include font-size($kbd-font-size);
+ color: $kbd-color;
+ background-color: $kbd-bg;
+ @include border-radius($border-radius-sm);
+
+ kbd {
+ padding: 0;
+ @include font-size(1em);
+ font-weight: $nested-kbd-font-weight;
+ }
+}
+
+
+// Figures
+//
+// Apply a consistent margin strategy (matches our type styles).
+
+figure {
+ margin: 0 0 1rem;
+}
+
+
+// Images and content
+
+img,
+svg {
+ vertical-align: middle;
+}
+
+
+// Tables
+//
+// Prevent double borders
+
+table {
+ caption-side: bottom;
+ border-collapse: collapse;
+}
+
+caption {
+ padding-top: $table-cell-padding-y;
+ padding-bottom: $table-cell-padding-y;
+ color: $table-caption-color;
+ text-align: left;
+}
+
+// 1. Removes font-weight bold by inheriting
+// 2. Matches default `
` alignment by inheriting `text-align`.
+// 3. Fix alignment for Safari
+
+th {
+ font-weight: $table-th-font-weight; // 1
+ text-align: inherit; // 2
+ text-align: -webkit-match-parent; // 3
+}
+
+thead,
+tbody,
+tfoot,
+tr,
+td,
+th {
+ border-color: inherit;
+ border-style: solid;
+ border-width: 0;
+}
+
+
+// Forms
+//
+// 1. Allow labels to use `margin` for spacing.
+
+label {
+ display: inline-block; // 1
+}
+
+// Remove the default `border-radius` that macOS Chrome adds.
+// See https://github.com/twbs/bootstrap/issues/24093
+
+button {
+ // stylelint-disable-next-line property-disallowed-list
+ border-radius: 0;
+}
+
+// Explicitly remove focus outline in Chromium when it shouldn't be
+// visible (e.g. as result of mouse click or touch tap). It already
+// should be doing this automatically, but seems to currently be
+// confused and applies its very visible two-tone outline anyway.
+
+button:focus:not(:focus-visible) {
+ outline: 0;
+}
+
+// 1. Remove the margin in Firefox and Safari
+
+input,
+button,
+select,
+optgroup,
+textarea {
+ margin: 0; // 1
+ font-family: inherit;
+ @include font-size(inherit);
+ line-height: inherit;
+}
+
+// Remove the inheritance of text transform in Firefox
+button,
+select {
+ text-transform: none;
+}
+// Set the cursor for non-`` buttons
+//
+// Details at https://github.com/twbs/bootstrap/pull/30562
+[role="button"] {
+ cursor: pointer;
+}
+
+select {
+ // Remove the inheritance of word-wrap in Safari.
+ // See https://github.com/twbs/bootstrap/issues/24990
+ word-wrap: normal;
+
+ // Undo the opacity change from Chrome
+ &:disabled {
+ opacity: 1;
+ }
+}
+
+// Remove the dropdown arrow only from text type inputs built with datalists in Chrome.
+// See https://stackoverflow.com/a/54997118
+
+[list]:not([type="date"]):not([type="datetime-local"]):not([type="month"]):not([type="week"]):not([type="time"])::-webkit-calendar-picker-indicator {
+ display: none !important;
+}
+
+// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
+// controls in Android 4.
+// 2. Correct the inability to style clickable types in iOS and Safari.
+// 3. Opinionated: add "hand" cursor to non-disabled button elements.
+
+button,
+[type="button"], // 1
+[type="reset"],
+[type="submit"] {
+ -webkit-appearance: button; // 2
+
+ @if $enable-button-pointers {
+ &:not(:disabled) {
+ cursor: pointer; // 3
+ }
+ }
+}
+
+// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.
+
+::-moz-focus-inner {
+ padding: 0;
+ border-style: none;
+}
+
+// 1. Textareas should really only resize vertically so they don't break their (horizontal) containers.
+
+textarea {
+ resize: vertical; // 1
+}
+
+// 1. Browsers set a default `min-width: min-content;` on fieldsets,
+// unlike e.g. ``s, which have `min-width: 0;` by default.
+// So we reset that to ensure fieldsets behave more like a standard block element.
+// See https://github.com/twbs/bootstrap/issues/12359
+// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
+// 2. Reset the default outline behavior of fieldsets so they don't affect page layout.
+
+fieldset {
+ min-width: 0; // 1
+ padding: 0; // 2
+ margin: 0; // 2
+ border: 0; // 2
+}
+
+// 1. By using `float: left`, the legend will behave like a block element.
+// This way the border of a fieldset wraps around the legend if present.
+// 2. Fix wrapping bug.
+// See https://github.com/twbs/bootstrap/issues/29712
+
+legend {
+ float: left; // 1
+ width: 100%;
+ padding: 0;
+ margin-bottom: $legend-margin-bottom;
+ font-weight: $legend-font-weight;
+ line-height: inherit;
+ @include font-size($legend-font-size);
+
+ + * {
+ clear: left; // 2
+ }
+}
+
+// Fix height of inputs with a type of datetime-local, date, month, week, or time
+// See https://github.com/twbs/bootstrap/issues/18842
+
+::-webkit-datetime-edit-fields-wrapper,
+::-webkit-datetime-edit-text,
+::-webkit-datetime-edit-minute,
+::-webkit-datetime-edit-hour-field,
+::-webkit-datetime-edit-day-field,
+::-webkit-datetime-edit-month-field,
+::-webkit-datetime-edit-year-field {
+ padding: 0;
+}
+
+::-webkit-inner-spin-button {
+ height: auto;
+}
+
+// 1. This overrides the extra rounded corners on search inputs in iOS so that our
+// `.form-control` class can properly style them. Note that this cannot simply
+// be added to `.form-control` as it's not specific enough. For details, see
+// https://github.com/twbs/bootstrap/issues/11586.
+// 2. Correct the outline style in Safari.
+
+[type="search"] {
+ -webkit-appearance: textfield; // 1
+ outline-offset: -2px; // 2
+
+ // 3. Better affordance and consistent appearance for search cancel button
+ &::-webkit-search-cancel-button {
+ cursor: pointer;
+ filter: grayscale(1);
+ }
+}
+
+// 1. A few input types should stay LTR
+// See https://rtlstyling.com/posts/rtl-styling#form-inputs
+// 2. RTL only output
+// See https://rtlcss.com/learn/usage-guide/control-directives/#raw
+
+/* rtl:raw:
+[type="tel"],
+[type="url"],
+[type="email"],
+[type="number"] {
+ direction: ltr;
+}
+*/
+
+// Remove the inner padding in Chrome and Safari on macOS.
+
+::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+// Remove padding around color pickers in webkit browsers
+
+::-webkit-color-swatch-wrapper {
+ padding: 0;
+}
+
+
+// 1. Inherit font family and line height for file input buttons
+// 2. Correct the inability to style clickable types in iOS and Safari.
+
+::file-selector-button {
+ font: inherit; // 1
+ -webkit-appearance: button; // 2
+}
+
+// Correct element displays
+
+output {
+ display: inline-block;
+}
+
+// Remove border from iframe
+
+iframe {
+ border: 0;
+}
+
+// Summary
+//
+// 1. Add the correct display in all browsers
+
+summary {
+ display: list-item; // 1
+ cursor: pointer;
+}
+
+
+// Progress
+//
+// Add the correct vertical alignment in Chrome, Firefox, and Opera.
+
+progress {
+ vertical-align: baseline;
+}
+
+
+// Hidden attribute
+//
+// Always hide an element with the `hidden` HTML attribute.
+
+[hidden] {
+ display: none !important;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_root.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_root.scss
new file mode 100644
index 0000000..becddf1
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_root.scss
@@ -0,0 +1,187 @@
+:root,
+[data-bs-theme="light"] {
+ // Note: Custom variable values only support SassScript inside `#{}`.
+
+ // Colors
+ //
+ // Generate palettes for full colors, grays, and theme colors.
+
+ @each $color, $value in $colors {
+ --#{$prefix}#{$color}: #{$value};
+ }
+
+ @each $color, $value in $grays {
+ --#{$prefix}gray-#{$color}: #{$value};
+ }
+
+ @each $color, $value in $theme-colors {
+ --#{$prefix}#{$color}: #{$value};
+ }
+
+ @each $color, $value in $theme-colors-rgb {
+ --#{$prefix}#{$color}-rgb: #{$value};
+ }
+
+ @each $color, $value in $theme-colors-text {
+ --#{$prefix}#{$color}-text-emphasis: #{$value};
+ }
+
+ @each $color, $value in $theme-colors-bg-subtle {
+ --#{$prefix}#{$color}-bg-subtle: #{$value};
+ }
+
+ @each $color, $value in $theme-colors-border-subtle {
+ --#{$prefix}#{$color}-border-subtle: #{$value};
+ }
+
+ --#{$prefix}white-rgb: #{to-rgb($white)};
+ --#{$prefix}black-rgb: #{to-rgb($black)};
+
+ // Fonts
+
+ // Note: Use `inspect` for lists so that quoted items keep the quotes.
+ // See https://github.com/sass/sass/issues/2383#issuecomment-336349172
+ --#{$prefix}font-sans-serif: #{inspect($font-family-sans-serif)};
+ --#{$prefix}font-monospace: #{inspect($font-family-monospace)};
+ --#{$prefix}gradient: #{$gradient};
+
+ // Root and body
+ // scss-docs-start root-body-variables
+ @if $font-size-root != null {
+ --#{$prefix}root-font-size: #{$font-size-root};
+ }
+ --#{$prefix}body-font-family: #{inspect($font-family-base)};
+ @include rfs($font-size-base, --#{$prefix}body-font-size);
+ --#{$prefix}body-font-weight: #{$font-weight-base};
+ --#{$prefix}body-line-height: #{$line-height-base};
+ @if $body-text-align != null {
+ --#{$prefix}body-text-align: #{$body-text-align};
+ }
+
+ --#{$prefix}body-color: #{$body-color};
+ --#{$prefix}body-color-rgb: #{to-rgb($body-color)};
+ --#{$prefix}body-bg: #{$body-bg};
+ --#{$prefix}body-bg-rgb: #{to-rgb($body-bg)};
+
+ --#{$prefix}emphasis-color: #{$body-emphasis-color};
+ --#{$prefix}emphasis-color-rgb: #{to-rgb($body-emphasis-color)};
+
+ --#{$prefix}secondary-color: #{$body-secondary-color};
+ --#{$prefix}secondary-color-rgb: #{to-rgb($body-secondary-color)};
+ --#{$prefix}secondary-bg: #{$body-secondary-bg};
+ --#{$prefix}secondary-bg-rgb: #{to-rgb($body-secondary-bg)};
+
+ --#{$prefix}tertiary-color: #{$body-tertiary-color};
+ --#{$prefix}tertiary-color-rgb: #{to-rgb($body-tertiary-color)};
+ --#{$prefix}tertiary-bg: #{$body-tertiary-bg};
+ --#{$prefix}tertiary-bg-rgb: #{to-rgb($body-tertiary-bg)};
+ // scss-docs-end root-body-variables
+
+ --#{$prefix}heading-color: #{$headings-color};
+
+ --#{$prefix}link-color: #{$link-color};
+ --#{$prefix}link-color-rgb: #{to-rgb($link-color)};
+ --#{$prefix}link-decoration: #{$link-decoration};
+
+ --#{$prefix}link-hover-color: #{$link-hover-color};
+ --#{$prefix}link-hover-color-rgb: #{to-rgb($link-hover-color)};
+
+ @if $link-hover-decoration != null {
+ --#{$prefix}link-hover-decoration: #{$link-hover-decoration};
+ }
+
+ --#{$prefix}code-color: #{$code-color};
+ --#{$prefix}highlight-color: #{$mark-color};
+ --#{$prefix}highlight-bg: #{$mark-bg};
+
+ // scss-docs-start root-border-var
+ --#{$prefix}border-width: #{$border-width};
+ --#{$prefix}border-style: #{$border-style};
+ --#{$prefix}border-color: #{$border-color};
+ --#{$prefix}border-color-translucent: #{$border-color-translucent};
+
+ --#{$prefix}border-radius: #{$border-radius};
+ --#{$prefix}border-radius-sm: #{$border-radius-sm};
+ --#{$prefix}border-radius-lg: #{$border-radius-lg};
+ --#{$prefix}border-radius-xl: #{$border-radius-xl};
+ --#{$prefix}border-radius-xxl: #{$border-radius-xxl};
+ --#{$prefix}border-radius-2xl: var(--#{$prefix}border-radius-xxl); // Deprecated in v5.3.0 for consistency
+ --#{$prefix}border-radius-pill: #{$border-radius-pill};
+ // scss-docs-end root-border-var
+
+ --#{$prefix}box-shadow: #{$box-shadow};
+ --#{$prefix}box-shadow-sm: #{$box-shadow-sm};
+ --#{$prefix}box-shadow-lg: #{$box-shadow-lg};
+ --#{$prefix}box-shadow-inset: #{$box-shadow-inset};
+
+ // Focus styles
+ // scss-docs-start root-focus-variables
+ --#{$prefix}focus-ring-width: #{$focus-ring-width};
+ --#{$prefix}focus-ring-opacity: #{$focus-ring-opacity};
+ --#{$prefix}focus-ring-color: #{$focus-ring-color};
+ // scss-docs-end root-focus-variables
+
+ // scss-docs-start root-form-validation-variables
+ --#{$prefix}form-valid-color: #{$form-valid-color};
+ --#{$prefix}form-valid-border-color: #{$form-valid-border-color};
+ --#{$prefix}form-invalid-color: #{$form-invalid-color};
+ --#{$prefix}form-invalid-border-color: #{$form-invalid-border-color};
+ // scss-docs-end root-form-validation-variables
+}
+
+@if $enable-dark-mode {
+ @include color-mode(dark, true) {
+ color-scheme: dark;
+
+ // scss-docs-start root-dark-mode-vars
+ --#{$prefix}body-color: #{$body-color-dark};
+ --#{$prefix}body-color-rgb: #{to-rgb($body-color-dark)};
+ --#{$prefix}body-bg: #{$body-bg-dark};
+ --#{$prefix}body-bg-rgb: #{to-rgb($body-bg-dark)};
+
+ --#{$prefix}emphasis-color: #{$body-emphasis-color-dark};
+ --#{$prefix}emphasis-color-rgb: #{to-rgb($body-emphasis-color-dark)};
+
+ --#{$prefix}secondary-color: #{$body-secondary-color-dark};
+ --#{$prefix}secondary-color-rgb: #{to-rgb($body-secondary-color-dark)};
+ --#{$prefix}secondary-bg: #{$body-secondary-bg-dark};
+ --#{$prefix}secondary-bg-rgb: #{to-rgb($body-secondary-bg-dark)};
+
+ --#{$prefix}tertiary-color: #{$body-tertiary-color-dark};
+ --#{$prefix}tertiary-color-rgb: #{to-rgb($body-tertiary-color-dark)};
+ --#{$prefix}tertiary-bg: #{$body-tertiary-bg-dark};
+ --#{$prefix}tertiary-bg-rgb: #{to-rgb($body-tertiary-bg-dark)};
+
+ @each $color, $value in $theme-colors-text-dark {
+ --#{$prefix}#{$color}-text-emphasis: #{$value};
+ }
+
+ @each $color, $value in $theme-colors-bg-subtle-dark {
+ --#{$prefix}#{$color}-bg-subtle: #{$value};
+ }
+
+ @each $color, $value in $theme-colors-border-subtle-dark {
+ --#{$prefix}#{$color}-border-subtle: #{$value};
+ }
+
+ --#{$prefix}heading-color: #{$headings-color-dark};
+
+ --#{$prefix}link-color: #{$link-color-dark};
+ --#{$prefix}link-hover-color: #{$link-hover-color-dark};
+ --#{$prefix}link-color-rgb: #{to-rgb($link-color-dark)};
+ --#{$prefix}link-hover-color-rgb: #{to-rgb($link-hover-color-dark)};
+
+ --#{$prefix}code-color: #{$code-color-dark};
+ --#{$prefix}highlight-color: #{$mark-color-dark};
+ --#{$prefix}highlight-bg: #{$mark-bg-dark};
+
+ --#{$prefix}border-color: #{$border-color-dark};
+ --#{$prefix}border-color-translucent: #{$border-color-translucent-dark};
+
+ --#{$prefix}form-valid-color: #{$form-valid-color-dark};
+ --#{$prefix}form-valid-border-color: #{$form-valid-border-color-dark};
+ --#{$prefix}form-invalid-color: #{$form-invalid-color-dark};
+ --#{$prefix}form-invalid-border-color: #{$form-invalid-border-color-dark};
+ // scss-docs-end root-dark-mode-vars
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_spinners.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_spinners.scss
new file mode 100644
index 0000000..9dff289
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_spinners.scss
@@ -0,0 +1,86 @@
+//
+// Rotating border
+//
+
+.spinner-grow,
+.spinner-border {
+ display: inline-block;
+ flex-shrink: 0;
+ width: var(--#{$prefix}spinner-width);
+ height: var(--#{$prefix}spinner-height);
+ vertical-align: var(--#{$prefix}spinner-vertical-align);
+ // stylelint-disable-next-line property-disallowed-list
+ border-radius: 50%;
+ animation: var(--#{$prefix}spinner-animation-speed) linear infinite var(--#{$prefix}spinner-animation-name);
+}
+
+// scss-docs-start spinner-border-keyframes
+@keyframes spinner-border {
+ to { transform: rotate(360deg) #{"/* rtl:ignore */"}; }
+}
+// scss-docs-end spinner-border-keyframes
+
+.spinner-border {
+ // scss-docs-start spinner-border-css-vars
+ --#{$prefix}spinner-width: #{$spinner-width};
+ --#{$prefix}spinner-height: #{$spinner-height};
+ --#{$prefix}spinner-vertical-align: #{$spinner-vertical-align};
+ --#{$prefix}spinner-border-width: #{$spinner-border-width};
+ --#{$prefix}spinner-animation-speed: #{$spinner-animation-speed};
+ --#{$prefix}spinner-animation-name: spinner-border;
+ // scss-docs-end spinner-border-css-vars
+
+ border: var(--#{$prefix}spinner-border-width) solid currentcolor;
+ border-right-color: transparent;
+}
+
+.spinner-border-sm {
+ // scss-docs-start spinner-border-sm-css-vars
+ --#{$prefix}spinner-width: #{$spinner-width-sm};
+ --#{$prefix}spinner-height: #{$spinner-height-sm};
+ --#{$prefix}spinner-border-width: #{$spinner-border-width-sm};
+ // scss-docs-end spinner-border-sm-css-vars
+}
+
+//
+// Growing circle
+//
+
+// scss-docs-start spinner-grow-keyframes
+@keyframes spinner-grow {
+ 0% {
+ transform: scale(0);
+ }
+ 50% {
+ opacity: 1;
+ transform: none;
+ }
+}
+// scss-docs-end spinner-grow-keyframes
+
+.spinner-grow {
+ // scss-docs-start spinner-grow-css-vars
+ --#{$prefix}spinner-width: #{$spinner-width};
+ --#{$prefix}spinner-height: #{$spinner-height};
+ --#{$prefix}spinner-vertical-align: #{$spinner-vertical-align};
+ --#{$prefix}spinner-animation-speed: #{$spinner-animation-speed};
+ --#{$prefix}spinner-animation-name: spinner-grow;
+ // scss-docs-end spinner-grow-css-vars
+
+ background-color: currentcolor;
+ opacity: 0;
+}
+
+.spinner-grow-sm {
+ --#{$prefix}spinner-width: #{$spinner-width-sm};
+ --#{$prefix}spinner-height: #{$spinner-height-sm};
+}
+
+@if $enable-reduced-motion {
+ @media (prefers-reduced-motion: reduce) {
+ .spinner-border,
+ .spinner-grow {
+ --#{$prefix}spinner-animation-speed: #{$spinner-animation-speed * 2};
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_tables.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_tables.scss
new file mode 100644
index 0000000..276521a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_tables.scss
@@ -0,0 +1,171 @@
+//
+// Basic Bootstrap table
+//
+
+.table {
+ // Reset needed for nesting tables
+ --#{$prefix}table-color-type: initial;
+ --#{$prefix}table-bg-type: initial;
+ --#{$prefix}table-color-state: initial;
+ --#{$prefix}table-bg-state: initial;
+ // End of reset
+ --#{$prefix}table-color: #{$table-color};
+ --#{$prefix}table-bg: #{$table-bg};
+ --#{$prefix}table-border-color: #{$table-border-color};
+ --#{$prefix}table-accent-bg: #{$table-accent-bg};
+ --#{$prefix}table-striped-color: #{$table-striped-color};
+ --#{$prefix}table-striped-bg: #{$table-striped-bg};
+ --#{$prefix}table-active-color: #{$table-active-color};
+ --#{$prefix}table-active-bg: #{$table-active-bg};
+ --#{$prefix}table-hover-color: #{$table-hover-color};
+ --#{$prefix}table-hover-bg: #{$table-hover-bg};
+
+ width: 100%;
+ margin-bottom: $spacer;
+ vertical-align: $table-cell-vertical-align;
+ border-color: var(--#{$prefix}table-border-color);
+
+ // Target th & td
+ // We need the child combinator to prevent styles leaking to nested tables which doesn't have a `.table` class.
+ // We use the universal selectors here to simplify the selector (else we would need 6 different selectors).
+ // Another advantage is that this generates less code and makes the selector less specific making it easier to override.
+ // stylelint-disable-next-line selector-max-universal
+ > :not(caption) > * > * {
+ padding: $table-cell-padding-y $table-cell-padding-x;
+ // Following the precept of cascades: https://codepen.io/miriamsuzanne/full/vYNgodb
+ color: var(--#{$prefix}table-color-state, var(--#{$prefix}table-color-type, var(--#{$prefix}table-color)));
+ background-color: var(--#{$prefix}table-bg);
+ border-bottom-width: $table-border-width;
+ box-shadow: inset 0 0 0 9999px var(--#{$prefix}table-bg-state, var(--#{$prefix}table-bg-type, var(--#{$prefix}table-accent-bg)));
+ }
+
+ > tbody {
+ vertical-align: inherit;
+ }
+
+ > thead {
+ vertical-align: bottom;
+ }
+}
+
+.table-group-divider {
+ border-top: calc(#{$table-border-width} * 2) solid $table-group-separator-color; // stylelint-disable-line function-disallowed-list
+}
+
+//
+// Change placement of captions with a class
+//
+
+.caption-top {
+ caption-side: top;
+}
+
+
+//
+// Condensed table w/ half padding
+//
+
+.table-sm {
+ // stylelint-disable-next-line selector-max-universal
+ > :not(caption) > * > * {
+ padding: $table-cell-padding-y-sm $table-cell-padding-x-sm;
+ }
+}
+
+
+// Border versions
+//
+// Add or remove borders all around the table and between all the columns.
+//
+// When borders are added on all sides of the cells, the corners can render odd when
+// these borders do not have the same color or if they are semi-transparent.
+// Therefore we add top and border bottoms to the `tr`s and left and right borders
+// to the `td`s or `th`s
+
+.table-bordered {
+ > :not(caption) > * {
+ border-width: $table-border-width 0;
+
+ // stylelint-disable-next-line selector-max-universal
+ > * {
+ border-width: 0 $table-border-width;
+ }
+ }
+}
+
+.table-borderless {
+ // stylelint-disable-next-line selector-max-universal
+ > :not(caption) > * > * {
+ border-bottom-width: 0;
+ }
+
+ > :not(:first-child) {
+ border-top-width: 0;
+ }
+}
+
+// Zebra-striping
+//
+// Default zebra-stripe styles (alternating gray and transparent backgrounds)
+
+// For rows
+.table-striped {
+ > tbody > tr:nth-of-type(#{$table-striped-order}) > * {
+ --#{$prefix}table-color-type: var(--#{$prefix}table-striped-color);
+ --#{$prefix}table-bg-type: var(--#{$prefix}table-striped-bg);
+ }
+}
+
+// For columns
+.table-striped-columns {
+ > :not(caption) > tr > :nth-child(#{$table-striped-columns-order}) {
+ --#{$prefix}table-color-type: var(--#{$prefix}table-striped-color);
+ --#{$prefix}table-bg-type: var(--#{$prefix}table-striped-bg);
+ }
+}
+
+// Active table
+//
+// The `.table-active` class can be added to highlight rows or cells
+
+.table-active {
+ --#{$prefix}table-color-state: var(--#{$prefix}table-active-color);
+ --#{$prefix}table-bg-state: var(--#{$prefix}table-active-bg);
+}
+
+// Hover effect
+//
+// Placed here since it has to come after the potential zebra striping
+
+.table-hover {
+ > tbody > tr:hover > * {
+ --#{$prefix}table-color-state: var(--#{$prefix}table-hover-color);
+ --#{$prefix}table-bg-state: var(--#{$prefix}table-hover-bg);
+ }
+}
+
+
+// Table variants
+//
+// Table variants set the table cell backgrounds, border colors
+// and the colors of the striped, hovered & active tables
+
+@each $color, $value in $table-variants {
+ @include table-variant($color, $value);
+}
+
+// Responsive tables
+//
+// Generate series of `.table-responsive-*` classes for configuring the screen
+// size of where your table will overflow.
+
+@each $breakpoint in map-keys($grid-breakpoints) {
+ $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+
+ @include media-breakpoint-down($breakpoint) {
+ .table-responsive#{$infix} {
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_toasts.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_toasts.scss
new file mode 100644
index 0000000..2ce378d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_toasts.scss
@@ -0,0 +1,73 @@
+.toast {
+ // scss-docs-start toast-css-vars
+ --#{$prefix}toast-zindex: #{$zindex-toast};
+ --#{$prefix}toast-padding-x: #{$toast-padding-x};
+ --#{$prefix}toast-padding-y: #{$toast-padding-y};
+ --#{$prefix}toast-spacing: #{$toast-spacing};
+ --#{$prefix}toast-max-width: #{$toast-max-width};
+ @include rfs($toast-font-size, --#{$prefix}toast-font-size);
+ --#{$prefix}toast-color: #{$toast-color};
+ --#{$prefix}toast-bg: #{$toast-background-color};
+ --#{$prefix}toast-border-width: #{$toast-border-width};
+ --#{$prefix}toast-border-color: #{$toast-border-color};
+ --#{$prefix}toast-border-radius: #{$toast-border-radius};
+ --#{$prefix}toast-box-shadow: #{$toast-box-shadow};
+ --#{$prefix}toast-header-color: #{$toast-header-color};
+ --#{$prefix}toast-header-bg: #{$toast-header-background-color};
+ --#{$prefix}toast-header-border-color: #{$toast-header-border-color};
+ // scss-docs-end toast-css-vars
+
+ width: var(--#{$prefix}toast-max-width);
+ max-width: 100%;
+ @include font-size(var(--#{$prefix}toast-font-size));
+ color: var(--#{$prefix}toast-color);
+ pointer-events: auto;
+ background-color: var(--#{$prefix}toast-bg);
+ background-clip: padding-box;
+ border: var(--#{$prefix}toast-border-width) solid var(--#{$prefix}toast-border-color);
+ box-shadow: var(--#{$prefix}toast-box-shadow);
+ @include border-radius(var(--#{$prefix}toast-border-radius));
+
+ &.showing {
+ opacity: 0;
+ }
+
+ &:not(.show) {
+ display: none;
+ }
+}
+
+.toast-container {
+ --#{$prefix}toast-zindex: #{$zindex-toast};
+
+ position: absolute;
+ z-index: var(--#{$prefix}toast-zindex);
+ width: max-content;
+ max-width: 100%;
+ pointer-events: none;
+
+ > :not(:last-child) {
+ margin-bottom: var(--#{$prefix}toast-spacing);
+ }
+}
+
+.toast-header {
+ display: flex;
+ align-items: center;
+ padding: var(--#{$prefix}toast-padding-y) var(--#{$prefix}toast-padding-x);
+ color: var(--#{$prefix}toast-header-color);
+ background-color: var(--#{$prefix}toast-header-bg);
+ background-clip: padding-box;
+ border-bottom: var(--#{$prefix}toast-border-width) solid var(--#{$prefix}toast-header-border-color);
+ @include border-top-radius(calc(var(--#{$prefix}toast-border-radius) - var(--#{$prefix}toast-border-width)));
+
+ .btn-close {
+ margin-right: calc(-.5 * var(--#{$prefix}toast-padding-x)); // stylelint-disable-line function-disallowed-list
+ margin-left: var(--#{$prefix}toast-padding-x);
+ }
+}
+
+.toast-body {
+ padding: var(--#{$prefix}toast-padding-x);
+ word-wrap: break-word;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_tooltip.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_tooltip.scss
new file mode 100644
index 0000000..85de90f
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_tooltip.scss
@@ -0,0 +1,119 @@
+// Base class
+.tooltip {
+ // scss-docs-start tooltip-css-vars
+ --#{$prefix}tooltip-zindex: #{$zindex-tooltip};
+ --#{$prefix}tooltip-max-width: #{$tooltip-max-width};
+ --#{$prefix}tooltip-padding-x: #{$tooltip-padding-x};
+ --#{$prefix}tooltip-padding-y: #{$tooltip-padding-y};
+ --#{$prefix}tooltip-margin: #{$tooltip-margin};
+ @include rfs($tooltip-font-size, --#{$prefix}tooltip-font-size);
+ --#{$prefix}tooltip-color: #{$tooltip-color};
+ --#{$prefix}tooltip-bg: #{$tooltip-bg};
+ --#{$prefix}tooltip-border-radius: #{$tooltip-border-radius};
+ --#{$prefix}tooltip-opacity: #{$tooltip-opacity};
+ --#{$prefix}tooltip-arrow-width: #{$tooltip-arrow-width};
+ --#{$prefix}tooltip-arrow-height: #{$tooltip-arrow-height};
+ // scss-docs-end tooltip-css-vars
+
+ z-index: var(--#{$prefix}tooltip-zindex);
+ display: block;
+ margin: var(--#{$prefix}tooltip-margin);
+ @include deprecate("`$tooltip-margin`", "v5", "v5.x", true);
+ // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
+ // So reset our font and text properties to avoid inheriting weird values.
+ @include reset-text();
+ @include font-size(var(--#{$prefix}tooltip-font-size));
+ // Allow breaking very long words so they don't overflow the tooltip's bounds
+ word-wrap: break-word;
+ opacity: 0;
+
+ &.show { opacity: var(--#{$prefix}tooltip-opacity); }
+
+ .tooltip-arrow {
+ display: block;
+ width: var(--#{$prefix}tooltip-arrow-width);
+ height: var(--#{$prefix}tooltip-arrow-height);
+
+ &::before {
+ position: absolute;
+ content: "";
+ border-color: transparent;
+ border-style: solid;
+ }
+ }
+}
+
+.bs-tooltip-top .tooltip-arrow {
+ bottom: calc(-1 * var(--#{$prefix}tooltip-arrow-height)); // stylelint-disable-line function-disallowed-list
+
+ &::before {
+ top: -1px;
+ border-width: var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
+ border-top-color: var(--#{$prefix}tooltip-bg);
+ }
+}
+
+/* rtl:begin:ignore */
+.bs-tooltip-end .tooltip-arrow {
+ left: calc(-1 * var(--#{$prefix}tooltip-arrow-height)); // stylelint-disable-line function-disallowed-list
+ width: var(--#{$prefix}tooltip-arrow-height);
+ height: var(--#{$prefix}tooltip-arrow-width);
+
+ &::before {
+ right: -1px;
+ border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
+ border-right-color: var(--#{$prefix}tooltip-bg);
+ }
+}
+
+/* rtl:end:ignore */
+
+.bs-tooltip-bottom .tooltip-arrow {
+ top: calc(-1 * var(--#{$prefix}tooltip-arrow-height)); // stylelint-disable-line function-disallowed-list
+
+ &::before {
+ bottom: -1px;
+ border-width: 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height); // stylelint-disable-line function-disallowed-list
+ border-bottom-color: var(--#{$prefix}tooltip-bg);
+ }
+}
+
+/* rtl:begin:ignore */
+.bs-tooltip-start .tooltip-arrow {
+ right: calc(-1 * var(--#{$prefix}tooltip-arrow-height)); // stylelint-disable-line function-disallowed-list
+ width: var(--#{$prefix}tooltip-arrow-height);
+ height: var(--#{$prefix}tooltip-arrow-width);
+
+ &::before {
+ left: -1px;
+ border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height); // stylelint-disable-line function-disallowed-list
+ border-left-color: var(--#{$prefix}tooltip-bg);
+ }
+}
+
+/* rtl:end:ignore */
+
+.bs-tooltip-auto {
+ &[data-popper-placement^="top"] {
+ @extend .bs-tooltip-top;
+ }
+ &[data-popper-placement^="right"] {
+ @extend .bs-tooltip-end;
+ }
+ &[data-popper-placement^="bottom"] {
+ @extend .bs-tooltip-bottom;
+ }
+ &[data-popper-placement^="left"] {
+ @extend .bs-tooltip-start;
+ }
+}
+
+// Wrapper for the tooltip content
+.tooltip-inner {
+ max-width: var(--#{$prefix}tooltip-max-width);
+ padding: var(--#{$prefix}tooltip-padding-y) var(--#{$prefix}tooltip-padding-x);
+ color: var(--#{$prefix}tooltip-color);
+ text-align: center;
+ background-color: var(--#{$prefix}tooltip-bg);
+ @include border-radius(var(--#{$prefix}tooltip-border-radius));
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_transitions.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_transitions.scss
new file mode 100644
index 0000000..bfb26aa
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_transitions.scss
@@ -0,0 +1,27 @@
+.fade {
+ @include transition($transition-fade);
+
+ &:not(.show) {
+ opacity: 0;
+ }
+}
+
+// scss-docs-start collapse-classes
+.collapse {
+ &:not(.show) {
+ display: none;
+ }
+}
+
+.collapsing {
+ height: 0;
+ overflow: hidden;
+ @include transition($transition-collapse);
+
+ &.collapse-horizontal {
+ width: 0;
+ height: auto;
+ @include transition($transition-collapse-width);
+ }
+}
+// scss-docs-end collapse-classes
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_type.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_type.scss
new file mode 100644
index 0000000..6961390
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_type.scss
@@ -0,0 +1,106 @@
+//
+// Headings
+//
+.h1 {
+ @extend h1;
+}
+
+.h2 {
+ @extend h2;
+}
+
+.h3 {
+ @extend h3;
+}
+
+.h4 {
+ @extend h4;
+}
+
+.h5 {
+ @extend h5;
+}
+
+.h6 {
+ @extend h6;
+}
+
+
+.lead {
+ @include font-size($lead-font-size);
+ font-weight: $lead-font-weight;
+}
+
+// Type display classes
+@each $display, $font-size in $display-font-sizes {
+ .display-#{$display} {
+ font-family: $display-font-family;
+ font-style: $display-font-style;
+ font-weight: $display-font-weight;
+ line-height: $display-line-height;
+ @include font-size($font-size);
+ }
+}
+
+//
+// Emphasis
+//
+.small {
+ @extend small;
+}
+
+.mark {
+ @extend mark;
+}
+
+//
+// Lists
+//
+
+.list-unstyled {
+ @include list-unstyled();
+}
+
+// Inline turns list items into inline-block
+.list-inline {
+ @include list-unstyled();
+}
+.list-inline-item {
+ display: inline-block;
+
+ &:not(:last-child) {
+ margin-right: $list-inline-padding;
+ }
+}
+
+
+//
+// Misc
+//
+
+// Builds on `abbr`
+.initialism {
+ @include font-size($initialism-font-size);
+ text-transform: uppercase;
+}
+
+// Blockquotes
+.blockquote {
+ margin-bottom: $blockquote-margin-y;
+ @include font-size($blockquote-font-size);
+
+ > :last-child {
+ margin-bottom: 0;
+ }
+}
+
+.blockquote-footer {
+ margin-top: -$blockquote-margin-y;
+ margin-bottom: $blockquote-margin-y;
+ @include font-size($blockquote-footer-font-size);
+ color: $blockquote-footer-color;
+
+ &::before {
+ content: "\2014\00A0"; // em dash, nbsp
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_utilities.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_utilities.scss
new file mode 100644
index 0000000..696f906
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_utilities.scss
@@ -0,0 +1,806 @@
+// Utilities
+
+$utilities: () !default;
+// stylelint-disable-next-line scss/dollar-variable-default
+$utilities: map-merge(
+ (
+ // scss-docs-start utils-vertical-align
+ "align": (
+ property: vertical-align,
+ class: align,
+ values: baseline top middle bottom text-bottom text-top
+ ),
+ // scss-docs-end utils-vertical-align
+ // scss-docs-start utils-float
+ "float": (
+ responsive: true,
+ property: float,
+ values: (
+ start: left,
+ end: right,
+ none: none,
+ )
+ ),
+ // scss-docs-end utils-float
+ // Object Fit utilities
+ // scss-docs-start utils-object-fit
+ "object-fit": (
+ responsive: true,
+ property: object-fit,
+ values: (
+ contain: contain,
+ cover: cover,
+ fill: fill,
+ scale: scale-down,
+ none: none,
+ )
+ ),
+ // scss-docs-end utils-object-fit
+ // Opacity utilities
+ // scss-docs-start utils-opacity
+ "opacity": (
+ property: opacity,
+ values: (
+ 0: 0,
+ 25: .25,
+ 50: .5,
+ 75: .75,
+ 100: 1,
+ )
+ ),
+ // scss-docs-end utils-opacity
+ // scss-docs-start utils-overflow
+ "overflow": (
+ property: overflow,
+ values: auto hidden visible scroll,
+ ),
+ "overflow-x": (
+ property: overflow-x,
+ values: auto hidden visible scroll,
+ ),
+ "overflow-y": (
+ property: overflow-y,
+ values: auto hidden visible scroll,
+ ),
+ // scss-docs-end utils-overflow
+ // scss-docs-start utils-display
+ "display": (
+ responsive: true,
+ print: true,
+ property: display,
+ class: d,
+ values: inline inline-block block grid inline-grid table table-row table-cell flex inline-flex none
+ ),
+ // scss-docs-end utils-display
+ // scss-docs-start utils-shadow
+ "shadow": (
+ property: box-shadow,
+ class: shadow,
+ values: (
+ null: var(--#{$prefix}box-shadow),
+ sm: var(--#{$prefix}box-shadow-sm),
+ lg: var(--#{$prefix}box-shadow-lg),
+ none: none,
+ )
+ ),
+ // scss-docs-end utils-shadow
+ // scss-docs-start utils-focus-ring
+ "focus-ring": (
+ css-var: true,
+ css-variable-name: focus-ring-color,
+ class: focus-ring,
+ values: map-loop($theme-colors-rgb, rgba-css-var, "$key", "focus-ring")
+ ),
+ // scss-docs-end utils-focus-ring
+ // scss-docs-start utils-position
+ "position": (
+ property: position,
+ values: static relative absolute fixed sticky
+ ),
+ "top": (
+ property: top,
+ values: $position-values
+ ),
+ "bottom": (
+ property: bottom,
+ values: $position-values
+ ),
+ "start": (
+ property: left,
+ class: start,
+ values: $position-values
+ ),
+ "end": (
+ property: right,
+ class: end,
+ values: $position-values
+ ),
+ "translate-middle": (
+ property: transform,
+ class: translate-middle,
+ values: (
+ null: translate(-50%, -50%),
+ x: translateX(-50%),
+ y: translateY(-50%),
+ )
+ ),
+ // scss-docs-end utils-position
+ // scss-docs-start utils-borders
+ "border": (
+ property: border,
+ values: (
+ null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
+ 0: 0,
+ )
+ ),
+ "border-top": (
+ property: border-top,
+ values: (
+ null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
+ 0: 0,
+ )
+ ),
+ "border-end": (
+ property: border-right,
+ class: border-end,
+ values: (
+ null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
+ 0: 0,
+ )
+ ),
+ "border-bottom": (
+ property: border-bottom,
+ values: (
+ null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
+ 0: 0,
+ )
+ ),
+ "border-start": (
+ property: border-left,
+ class: border-start,
+ values: (
+ null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
+ 0: 0,
+ )
+ ),
+ "border-color": (
+ property: border-color,
+ class: border,
+ local-vars: (
+ "border-opacity": 1
+ ),
+ values: $utilities-border-colors
+ ),
+ "subtle-border-color": (
+ property: border-color,
+ class: border,
+ values: $utilities-border-subtle
+ ),
+ "border-width": (
+ property: border-width,
+ class: border,
+ values: $border-widths
+ ),
+ "border-opacity": (
+ css-var: true,
+ class: border-opacity,
+ values: (
+ 10: .1,
+ 25: .25,
+ 50: .5,
+ 75: .75,
+ 100: 1
+ )
+ ),
+ // scss-docs-end utils-borders
+ // Sizing utilities
+ // scss-docs-start utils-sizing
+ "width": (
+ property: width,
+ class: w,
+ values: (
+ 25: 25%,
+ 50: 50%,
+ 75: 75%,
+ 100: 100%,
+ auto: auto
+ )
+ ),
+ "max-width": (
+ property: max-width,
+ class: mw,
+ values: (100: 100%)
+ ),
+ "viewport-width": (
+ property: width,
+ class: vw,
+ values: (100: 100vw)
+ ),
+ "min-viewport-width": (
+ property: min-width,
+ class: min-vw,
+ values: (100: 100vw)
+ ),
+ "height": (
+ property: height,
+ class: h,
+ values: (
+ 25: 25%,
+ 50: 50%,
+ 75: 75%,
+ 100: 100%,
+ auto: auto
+ )
+ ),
+ "max-height": (
+ property: max-height,
+ class: mh,
+ values: (100: 100%)
+ ),
+ "viewport-height": (
+ property: height,
+ class: vh,
+ values: (100: 100vh)
+ ),
+ "min-viewport-height": (
+ property: min-height,
+ class: min-vh,
+ values: (100: 100vh)
+ ),
+ // scss-docs-end utils-sizing
+ // Flex utilities
+ // scss-docs-start utils-flex
+ "flex": (
+ responsive: true,
+ property: flex,
+ values: (fill: 1 1 auto)
+ ),
+ "flex-direction": (
+ responsive: true,
+ property: flex-direction,
+ class: flex,
+ values: row column row-reverse column-reverse
+ ),
+ "flex-grow": (
+ responsive: true,
+ property: flex-grow,
+ class: flex,
+ values: (
+ grow-0: 0,
+ grow-1: 1,
+ )
+ ),
+ "flex-shrink": (
+ responsive: true,
+ property: flex-shrink,
+ class: flex,
+ values: (
+ shrink-0: 0,
+ shrink-1: 1,
+ )
+ ),
+ "flex-wrap": (
+ responsive: true,
+ property: flex-wrap,
+ class: flex,
+ values: wrap nowrap wrap-reverse
+ ),
+ "justify-content": (
+ responsive: true,
+ property: justify-content,
+ values: (
+ start: flex-start,
+ end: flex-end,
+ center: center,
+ between: space-between,
+ around: space-around,
+ evenly: space-evenly,
+ )
+ ),
+ "align-items": (
+ responsive: true,
+ property: align-items,
+ values: (
+ start: flex-start,
+ end: flex-end,
+ center: center,
+ baseline: baseline,
+ stretch: stretch,
+ )
+ ),
+ "align-content": (
+ responsive: true,
+ property: align-content,
+ values: (
+ start: flex-start,
+ end: flex-end,
+ center: center,
+ between: space-between,
+ around: space-around,
+ stretch: stretch,
+ )
+ ),
+ "align-self": (
+ responsive: true,
+ property: align-self,
+ values: (
+ auto: auto,
+ start: flex-start,
+ end: flex-end,
+ center: center,
+ baseline: baseline,
+ stretch: stretch,
+ )
+ ),
+ "order": (
+ responsive: true,
+ property: order,
+ values: (
+ first: -1,
+ 0: 0,
+ 1: 1,
+ 2: 2,
+ 3: 3,
+ 4: 4,
+ 5: 5,
+ last: 6,
+ ),
+ ),
+ // scss-docs-end utils-flex
+ // Margin utilities
+ // scss-docs-start utils-spacing
+ "margin": (
+ responsive: true,
+ property: margin,
+ class: m,
+ values: map-merge($spacers, (auto: auto))
+ ),
+ "margin-x": (
+ responsive: true,
+ property: margin-right margin-left,
+ class: mx,
+ values: map-merge($spacers, (auto: auto))
+ ),
+ "margin-y": (
+ responsive: true,
+ property: margin-top margin-bottom,
+ class: my,
+ values: map-merge($spacers, (auto: auto))
+ ),
+ "margin-top": (
+ responsive: true,
+ property: margin-top,
+ class: mt,
+ values: map-merge($spacers, (auto: auto))
+ ),
+ "margin-end": (
+ responsive: true,
+ property: margin-right,
+ class: me,
+ values: map-merge($spacers, (auto: auto))
+ ),
+ "margin-bottom": (
+ responsive: true,
+ property: margin-bottom,
+ class: mb,
+ values: map-merge($spacers, (auto: auto))
+ ),
+ "margin-start": (
+ responsive: true,
+ property: margin-left,
+ class: ms,
+ values: map-merge($spacers, (auto: auto))
+ ),
+ // Negative margin utilities
+ "negative-margin": (
+ responsive: true,
+ property: margin,
+ class: m,
+ values: $negative-spacers
+ ),
+ "negative-margin-x": (
+ responsive: true,
+ property: margin-right margin-left,
+ class: mx,
+ values: $negative-spacers
+ ),
+ "negative-margin-y": (
+ responsive: true,
+ property: margin-top margin-bottom,
+ class: my,
+ values: $negative-spacers
+ ),
+ "negative-margin-top": (
+ responsive: true,
+ property: margin-top,
+ class: mt,
+ values: $negative-spacers
+ ),
+ "negative-margin-end": (
+ responsive: true,
+ property: margin-right,
+ class: me,
+ values: $negative-spacers
+ ),
+ "negative-margin-bottom": (
+ responsive: true,
+ property: margin-bottom,
+ class: mb,
+ values: $negative-spacers
+ ),
+ "negative-margin-start": (
+ responsive: true,
+ property: margin-left,
+ class: ms,
+ values: $negative-spacers
+ ),
+ // Padding utilities
+ "padding": (
+ responsive: true,
+ property: padding,
+ class: p,
+ values: $spacers
+ ),
+ "padding-x": (
+ responsive: true,
+ property: padding-right padding-left,
+ class: px,
+ values: $spacers
+ ),
+ "padding-y": (
+ responsive: true,
+ property: padding-top padding-bottom,
+ class: py,
+ values: $spacers
+ ),
+ "padding-top": (
+ responsive: true,
+ property: padding-top,
+ class: pt,
+ values: $spacers
+ ),
+ "padding-end": (
+ responsive: true,
+ property: padding-right,
+ class: pe,
+ values: $spacers
+ ),
+ "padding-bottom": (
+ responsive: true,
+ property: padding-bottom,
+ class: pb,
+ values: $spacers
+ ),
+ "padding-start": (
+ responsive: true,
+ property: padding-left,
+ class: ps,
+ values: $spacers
+ ),
+ // Gap utility
+ "gap": (
+ responsive: true,
+ property: gap,
+ class: gap,
+ values: $spacers
+ ),
+ "row-gap": (
+ responsive: true,
+ property: row-gap,
+ class: row-gap,
+ values: $spacers
+ ),
+ "column-gap": (
+ responsive: true,
+ property: column-gap,
+ class: column-gap,
+ values: $spacers
+ ),
+ // scss-docs-end utils-spacing
+ // Text
+ // scss-docs-start utils-text
+ "font-family": (
+ property: font-family,
+ class: font,
+ values: (monospace: var(--#{$prefix}font-monospace))
+ ),
+ "font-size": (
+ rfs: true,
+ property: font-size,
+ class: fs,
+ values: $font-sizes
+ ),
+ "font-style": (
+ property: font-style,
+ class: fst,
+ values: italic normal
+ ),
+ "font-weight": (
+ property: font-weight,
+ class: fw,
+ values: (
+ lighter: $font-weight-lighter,
+ light: $font-weight-light,
+ normal: $font-weight-normal,
+ medium: $font-weight-medium,
+ semibold: $font-weight-semibold,
+ bold: $font-weight-bold,
+ bolder: $font-weight-bolder
+ )
+ ),
+ "line-height": (
+ property: line-height,
+ class: lh,
+ values: (
+ 1: 1,
+ sm: $line-height-sm,
+ base: $line-height-base,
+ lg: $line-height-lg,
+ )
+ ),
+ "text-align": (
+ responsive: true,
+ property: text-align,
+ class: text,
+ values: (
+ start: left,
+ end: right,
+ center: center,
+ )
+ ),
+ "text-decoration": (
+ property: text-decoration,
+ values: none underline line-through
+ ),
+ "text-transform": (
+ property: text-transform,
+ class: text,
+ values: lowercase uppercase capitalize
+ ),
+ "white-space": (
+ property: white-space,
+ class: text,
+ values: (
+ wrap: normal,
+ nowrap: nowrap,
+ )
+ ),
+ "word-wrap": (
+ property: word-wrap word-break,
+ class: text,
+ values: (break: break-word),
+ rtl: false
+ ),
+ // scss-docs-end utils-text
+ // scss-docs-start utils-color
+ "color": (
+ property: color,
+ class: text,
+ local-vars: (
+ "text-opacity": 1
+ ),
+ values: map-merge(
+ $utilities-text-colors,
+ (
+ "muted": var(--#{$prefix}secondary-color), // deprecated
+ "black-50": rgba($black, .5), // deprecated
+ "white-50": rgba($white, .5), // deprecated
+ "body-secondary": var(--#{$prefix}secondary-color),
+ "body-tertiary": var(--#{$prefix}tertiary-color),
+ "body-emphasis": var(--#{$prefix}emphasis-color),
+ "reset": inherit,
+ )
+ )
+ ),
+ "text-opacity": (
+ css-var: true,
+ class: text-opacity,
+ values: (
+ 25: .25,
+ 50: .5,
+ 75: .75,
+ 100: 1
+ )
+ ),
+ "text-color": (
+ property: color,
+ class: text,
+ values: $utilities-text-emphasis-colors
+ ),
+ // scss-docs-end utils-color
+ // scss-docs-start utils-links
+ "link-opacity": (
+ css-var: true,
+ class: link-opacity,
+ state: hover,
+ values: (
+ 10: .1,
+ 25: .25,
+ 50: .5,
+ 75: .75,
+ 100: 1
+ )
+ ),
+ "link-offset": (
+ property: text-underline-offset,
+ class: link-offset,
+ state: hover,
+ values: (
+ 1: .125em,
+ 2: .25em,
+ 3: .375em,
+ )
+ ),
+ "link-underline": (
+ property: text-decoration-color,
+ class: link-underline,
+ local-vars: (
+ "link-underline-opacity": 1
+ ),
+ values: map-merge(
+ $utilities-links-underline,
+ (
+ null: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-underline-opacity, 1)),
+ )
+ )
+ ),
+ "link-underline-opacity": (
+ css-var: true,
+ class: link-underline-opacity,
+ state: hover,
+ values: (
+ 0: 0,
+ 10: .1,
+ 25: .25,
+ 50: .5,
+ 75: .75,
+ 100: 1
+ ),
+ ),
+ // scss-docs-end utils-links
+ // scss-docs-start utils-bg-color
+ "background-color": (
+ property: background-color,
+ class: bg,
+ local-vars: (
+ "bg-opacity": 1
+ ),
+ values: map-merge(
+ $utilities-bg-colors,
+ (
+ "transparent": transparent,
+ "body-secondary": rgba(var(--#{$prefix}secondary-bg-rgb), var(--#{$prefix}bg-opacity)),
+ "body-tertiary": rgba(var(--#{$prefix}tertiary-bg-rgb), var(--#{$prefix}bg-opacity)),
+ )
+ )
+ ),
+ "bg-opacity": (
+ css-var: true,
+ class: bg-opacity,
+ values: (
+ 10: .1,
+ 25: .25,
+ 50: .5,
+ 75: .75,
+ 100: 1
+ )
+ ),
+ "subtle-background-color": (
+ property: background-color,
+ class: bg,
+ values: $utilities-bg-subtle
+ ),
+ // scss-docs-end utils-bg-color
+ "gradient": (
+ property: background-image,
+ class: bg,
+ values: (gradient: var(--#{$prefix}gradient))
+ ),
+ // scss-docs-start utils-interaction
+ "user-select": (
+ property: user-select,
+ values: all auto none
+ ),
+ "pointer-events": (
+ property: pointer-events,
+ class: pe,
+ values: none auto,
+ ),
+ // scss-docs-end utils-interaction
+ // scss-docs-start utils-border-radius
+ "rounded": (
+ property: border-radius,
+ class: rounded,
+ values: (
+ null: var(--#{$prefix}border-radius),
+ 0: 0,
+ 1: var(--#{$prefix}border-radius-sm),
+ 2: var(--#{$prefix}border-radius),
+ 3: var(--#{$prefix}border-radius-lg),
+ 4: var(--#{$prefix}border-radius-xl),
+ 5: var(--#{$prefix}border-radius-xxl),
+ circle: 50%,
+ pill: var(--#{$prefix}border-radius-pill)
+ )
+ ),
+ "rounded-top": (
+ property: border-top-left-radius border-top-right-radius,
+ class: rounded-top,
+ values: (
+ null: var(--#{$prefix}border-radius),
+ 0: 0,
+ 1: var(--#{$prefix}border-radius-sm),
+ 2: var(--#{$prefix}border-radius),
+ 3: var(--#{$prefix}border-radius-lg),
+ 4: var(--#{$prefix}border-radius-xl),
+ 5: var(--#{$prefix}border-radius-xxl),
+ circle: 50%,
+ pill: var(--#{$prefix}border-radius-pill)
+ )
+ ),
+ "rounded-end": (
+ property: border-top-right-radius border-bottom-right-radius,
+ class: rounded-end,
+ values: (
+ null: var(--#{$prefix}border-radius),
+ 0: 0,
+ 1: var(--#{$prefix}border-radius-sm),
+ 2: var(--#{$prefix}border-radius),
+ 3: var(--#{$prefix}border-radius-lg),
+ 4: var(--#{$prefix}border-radius-xl),
+ 5: var(--#{$prefix}border-radius-xxl),
+ circle: 50%,
+ pill: var(--#{$prefix}border-radius-pill)
+ )
+ ),
+ "rounded-bottom": (
+ property: border-bottom-right-radius border-bottom-left-radius,
+ class: rounded-bottom,
+ values: (
+ null: var(--#{$prefix}border-radius),
+ 0: 0,
+ 1: var(--#{$prefix}border-radius-sm),
+ 2: var(--#{$prefix}border-radius),
+ 3: var(--#{$prefix}border-radius-lg),
+ 4: var(--#{$prefix}border-radius-xl),
+ 5: var(--#{$prefix}border-radius-xxl),
+ circle: 50%,
+ pill: var(--#{$prefix}border-radius-pill)
+ )
+ ),
+ "rounded-start": (
+ property: border-bottom-left-radius border-top-left-radius,
+ class: rounded-start,
+ values: (
+ null: var(--#{$prefix}border-radius),
+ 0: 0,
+ 1: var(--#{$prefix}border-radius-sm),
+ 2: var(--#{$prefix}border-radius),
+ 3: var(--#{$prefix}border-radius-lg),
+ 4: var(--#{$prefix}border-radius-xl),
+ 5: var(--#{$prefix}border-radius-xxl),
+ circle: 50%,
+ pill: var(--#{$prefix}border-radius-pill)
+ )
+ ),
+ // scss-docs-end utils-border-radius
+ // scss-docs-start utils-visibility
+ "visibility": (
+ property: visibility,
+ class: null,
+ values: (
+ visible: visible,
+ invisible: hidden,
+ )
+ ),
+ // scss-docs-end utils-visibility
+ // scss-docs-start utils-zindex
+ "z-index": (
+ property: z-index,
+ class: z,
+ values: $zindex-levels,
+ )
+ // scss-docs-end utils-zindex
+ ),
+ $utilities
+);
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_variables-dark.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_variables-dark.scss
new file mode 100644
index 0000000..260f6dc
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_variables-dark.scss
@@ -0,0 +1,102 @@
+// Dark color mode variables
+//
+// Custom variables for the `[data-bs-theme="dark"]` theme. Use this as a starting point for your own custom color modes by creating a new theme-specific file like `_variables-dark.scss` and adding the variables you need.
+
+//
+// Global colors
+//
+
+// scss-docs-start sass-dark-mode-vars
+// scss-docs-start theme-text-dark-variables
+$primary-text-emphasis-dark: tint-color($primary, 40%) !default;
+$secondary-text-emphasis-dark: tint-color($secondary, 40%) !default;
+$success-text-emphasis-dark: tint-color($success, 40%) !default;
+$info-text-emphasis-dark: tint-color($info, 40%) !default;
+$warning-text-emphasis-dark: tint-color($warning, 40%) !default;
+$danger-text-emphasis-dark: tint-color($danger, 40%) !default;
+$light-text-emphasis-dark: $gray-100 !default;
+$dark-text-emphasis-dark: $gray-300 !default;
+// scss-docs-end theme-text-dark-variables
+
+// scss-docs-start theme-bg-subtle-dark-variables
+$primary-bg-subtle-dark: shade-color($primary, 80%) !default;
+$secondary-bg-subtle-dark: shade-color($secondary, 80%) !default;
+$success-bg-subtle-dark: shade-color($success, 80%) !default;
+$info-bg-subtle-dark: shade-color($info, 80%) !default;
+$warning-bg-subtle-dark: shade-color($warning, 80%) !default;
+$danger-bg-subtle-dark: shade-color($danger, 80%) !default;
+$light-bg-subtle-dark: $gray-800 !default;
+$dark-bg-subtle-dark: mix($gray-800, $black) !default;
+// scss-docs-end theme-bg-subtle-dark-variables
+
+// scss-docs-start theme-border-subtle-dark-variables
+$primary-border-subtle-dark: shade-color($primary, 40%) !default;
+$secondary-border-subtle-dark: shade-color($secondary, 40%) !default;
+$success-border-subtle-dark: shade-color($success, 40%) !default;
+$info-border-subtle-dark: shade-color($info, 40%) !default;
+$warning-border-subtle-dark: shade-color($warning, 40%) !default;
+$danger-border-subtle-dark: shade-color($danger, 40%) !default;
+$light-border-subtle-dark: $gray-700 !default;
+$dark-border-subtle-dark: $gray-800 !default;
+// scss-docs-end theme-border-subtle-dark-variables
+
+$body-color-dark: $gray-300 !default;
+$body-bg-dark: $gray-900 !default;
+$body-secondary-color-dark: rgba($body-color-dark, .75) !default;
+$body-secondary-bg-dark: $gray-800 !default;
+$body-tertiary-color-dark: rgba($body-color-dark, .5) !default;
+$body-tertiary-bg-dark: mix($gray-800, $gray-900, 50%) !default;
+$body-emphasis-color-dark: $white !default;
+$border-color-dark: $gray-700 !default;
+$border-color-translucent-dark: rgba($white, .15) !default;
+$headings-color-dark: inherit !default;
+$link-color-dark: tint-color($primary, 40%) !default;
+$link-hover-color-dark: shift-color($link-color-dark, -$link-shade-percentage) !default;
+$code-color-dark: tint-color($code-color, 40%) !default;
+$mark-color-dark: $body-color-dark !default;
+$mark-bg-dark: $yellow-800 !default;
+
+
+//
+// Forms
+//
+
+$form-select-indicator-color-dark: $body-color-dark !default;
+$form-select-indicator-dark: url("data:image/svg+xml,
") !default;
+
+$form-switch-color-dark: rgba($white, .25) !default;
+$form-switch-bg-image-dark: url("data:image/svg+xml,
") !default;
+
+// scss-docs-start form-validation-colors-dark
+$form-valid-color-dark: $green-300 !default;
+$form-valid-border-color-dark: $green-300 !default;
+$form-invalid-color-dark: $red-300 !default;
+$form-invalid-border-color-dark: $red-300 !default;
+// scss-docs-end form-validation-colors-dark
+
+
+//
+// Accordion
+//
+
+$accordion-icon-color-dark: $primary-text-emphasis-dark !default;
+$accordion-icon-active-color-dark: $primary-text-emphasis-dark !default;
+
+$accordion-button-icon-dark: url("data:image/svg+xml,
") !default;
+$accordion-button-active-icon-dark: url("data:image/svg+xml,
") !default;
+// scss-docs-end sass-dark-mode-vars
+
+
+//
+// Carousel
+//
+
+$carousel-indicator-active-bg-dark: $carousel-dark-indicator-active-bg !default;
+$carousel-caption-color-dark: $carousel-dark-caption-color !default;
+$carousel-control-icon-filter-dark: $carousel-dark-control-icon-filter !default;
+
+//
+// Close button
+//
+
+$btn-close-filter-dark: $btn-close-white-filter !default;
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_variables.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_variables.scss
new file mode 100644
index 0000000..1ffa7e7
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/_variables.scss
@@ -0,0 +1,1753 @@
+// Variables
+//
+// Variables should follow the `$component-state-property-size` formula for
+// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.
+
+// Color system
+
+// scss-docs-start gray-color-variables
+$white: #fff !default;
+$gray-100: #f8f9fa !default;
+$gray-200: #e9ecef !default;
+$gray-300: #dee2e6 !default;
+$gray-400: #ced4da !default;
+$gray-500: #adb5bd !default;
+$gray-600: #6c757d !default;
+$gray-700: #495057 !default;
+$gray-800: #343a40 !default;
+$gray-900: #212529 !default;
+$black: #000 !default;
+// scss-docs-end gray-color-variables
+
+// fusv-disable
+// scss-docs-start gray-colors-map
+$grays: (
+ "100": $gray-100,
+ "200": $gray-200,
+ "300": $gray-300,
+ "400": $gray-400,
+ "500": $gray-500,
+ "600": $gray-600,
+ "700": $gray-700,
+ "800": $gray-800,
+ "900": $gray-900
+) !default;
+// scss-docs-end gray-colors-map
+// fusv-enable
+
+// scss-docs-start color-variables
+$blue: #0d6efd !default;
+$indigo: #6610f2 !default;
+$purple: #6f42c1 !default;
+$pink: #d63384 !default;
+$red: #dc3545 !default;
+$orange: #fd7e14 !default;
+$yellow: #ffc107 !default;
+$green: #198754 !default;
+$teal: #20c997 !default;
+$cyan: #0dcaf0 !default;
+// scss-docs-end color-variables
+
+// scss-docs-start colors-map
+$colors: (
+ "blue": $blue,
+ "indigo": $indigo,
+ "purple": $purple,
+ "pink": $pink,
+ "red": $red,
+ "orange": $orange,
+ "yellow": $yellow,
+ "green": $green,
+ "teal": $teal,
+ "cyan": $cyan,
+ "black": $black,
+ "white": $white,
+ "gray": $gray-600,
+ "gray-dark": $gray-800
+) !default;
+// scss-docs-end colors-map
+
+// The contrast ratio to reach against white, to determine if color changes from "light" to "dark". Acceptable values for WCAG 2.2 are 3, 4.5 and 7.
+// See https://www.w3.org/TR/WCAG/#contrast-minimum
+$min-contrast-ratio: 4.5 !default;
+
+// Customize the light and dark text colors for use in our color contrast function.
+$color-contrast-dark: $black !default;
+$color-contrast-light: $white !default;
+
+// fusv-disable
+$blue-100: tint-color($blue, 80%) !default;
+$blue-200: tint-color($blue, 60%) !default;
+$blue-300: tint-color($blue, 40%) !default;
+$blue-400: tint-color($blue, 20%) !default;
+$blue-500: $blue !default;
+$blue-600: shade-color($blue, 20%) !default;
+$blue-700: shade-color($blue, 40%) !default;
+$blue-800: shade-color($blue, 60%) !default;
+$blue-900: shade-color($blue, 80%) !default;
+
+$indigo-100: tint-color($indigo, 80%) !default;
+$indigo-200: tint-color($indigo, 60%) !default;
+$indigo-300: tint-color($indigo, 40%) !default;
+$indigo-400: tint-color($indigo, 20%) !default;
+$indigo-500: $indigo !default;
+$indigo-600: shade-color($indigo, 20%) !default;
+$indigo-700: shade-color($indigo, 40%) !default;
+$indigo-800: shade-color($indigo, 60%) !default;
+$indigo-900: shade-color($indigo, 80%) !default;
+
+$purple-100: tint-color($purple, 80%) !default;
+$purple-200: tint-color($purple, 60%) !default;
+$purple-300: tint-color($purple, 40%) !default;
+$purple-400: tint-color($purple, 20%) !default;
+$purple-500: $purple !default;
+$purple-600: shade-color($purple, 20%) !default;
+$purple-700: shade-color($purple, 40%) !default;
+$purple-800: shade-color($purple, 60%) !default;
+$purple-900: shade-color($purple, 80%) !default;
+
+$pink-100: tint-color($pink, 80%) !default;
+$pink-200: tint-color($pink, 60%) !default;
+$pink-300: tint-color($pink, 40%) !default;
+$pink-400: tint-color($pink, 20%) !default;
+$pink-500: $pink !default;
+$pink-600: shade-color($pink, 20%) !default;
+$pink-700: shade-color($pink, 40%) !default;
+$pink-800: shade-color($pink, 60%) !default;
+$pink-900: shade-color($pink, 80%) !default;
+
+$red-100: tint-color($red, 80%) !default;
+$red-200: tint-color($red, 60%) !default;
+$red-300: tint-color($red, 40%) !default;
+$red-400: tint-color($red, 20%) !default;
+$red-500: $red !default;
+$red-600: shade-color($red, 20%) !default;
+$red-700: shade-color($red, 40%) !default;
+$red-800: shade-color($red, 60%) !default;
+$red-900: shade-color($red, 80%) !default;
+
+$orange-100: tint-color($orange, 80%) !default;
+$orange-200: tint-color($orange, 60%) !default;
+$orange-300: tint-color($orange, 40%) !default;
+$orange-400: tint-color($orange, 20%) !default;
+$orange-500: $orange !default;
+$orange-600: shade-color($orange, 20%) !default;
+$orange-700: shade-color($orange, 40%) !default;
+$orange-800: shade-color($orange, 60%) !default;
+$orange-900: shade-color($orange, 80%) !default;
+
+$yellow-100: tint-color($yellow, 80%) !default;
+$yellow-200: tint-color($yellow, 60%) !default;
+$yellow-300: tint-color($yellow, 40%) !default;
+$yellow-400: tint-color($yellow, 20%) !default;
+$yellow-500: $yellow !default;
+$yellow-600: shade-color($yellow, 20%) !default;
+$yellow-700: shade-color($yellow, 40%) !default;
+$yellow-800: shade-color($yellow, 60%) !default;
+$yellow-900: shade-color($yellow, 80%) !default;
+
+$green-100: tint-color($green, 80%) !default;
+$green-200: tint-color($green, 60%) !default;
+$green-300: tint-color($green, 40%) !default;
+$green-400: tint-color($green, 20%) !default;
+$green-500: $green !default;
+$green-600: shade-color($green, 20%) !default;
+$green-700: shade-color($green, 40%) !default;
+$green-800: shade-color($green, 60%) !default;
+$green-900: shade-color($green, 80%) !default;
+
+$teal-100: tint-color($teal, 80%) !default;
+$teal-200: tint-color($teal, 60%) !default;
+$teal-300: tint-color($teal, 40%) !default;
+$teal-400: tint-color($teal, 20%) !default;
+$teal-500: $teal !default;
+$teal-600: shade-color($teal, 20%) !default;
+$teal-700: shade-color($teal, 40%) !default;
+$teal-800: shade-color($teal, 60%) !default;
+$teal-900: shade-color($teal, 80%) !default;
+
+$cyan-100: tint-color($cyan, 80%) !default;
+$cyan-200: tint-color($cyan, 60%) !default;
+$cyan-300: tint-color($cyan, 40%) !default;
+$cyan-400: tint-color($cyan, 20%) !default;
+$cyan-500: $cyan !default;
+$cyan-600: shade-color($cyan, 20%) !default;
+$cyan-700: shade-color($cyan, 40%) !default;
+$cyan-800: shade-color($cyan, 60%) !default;
+$cyan-900: shade-color($cyan, 80%) !default;
+
+$blues: (
+ "blue-100": $blue-100,
+ "blue-200": $blue-200,
+ "blue-300": $blue-300,
+ "blue-400": $blue-400,
+ "blue-500": $blue-500,
+ "blue-600": $blue-600,
+ "blue-700": $blue-700,
+ "blue-800": $blue-800,
+ "blue-900": $blue-900
+) !default;
+
+$indigos: (
+ "indigo-100": $indigo-100,
+ "indigo-200": $indigo-200,
+ "indigo-300": $indigo-300,
+ "indigo-400": $indigo-400,
+ "indigo-500": $indigo-500,
+ "indigo-600": $indigo-600,
+ "indigo-700": $indigo-700,
+ "indigo-800": $indigo-800,
+ "indigo-900": $indigo-900
+) !default;
+
+$purples: (
+ "purple-100": $purple-100,
+ "purple-200": $purple-200,
+ "purple-300": $purple-300,
+ "purple-400": $purple-400,
+ "purple-500": $purple-500,
+ "purple-600": $purple-600,
+ "purple-700": $purple-700,
+ "purple-800": $purple-800,
+ "purple-900": $purple-900
+) !default;
+
+$pinks: (
+ "pink-100": $pink-100,
+ "pink-200": $pink-200,
+ "pink-300": $pink-300,
+ "pink-400": $pink-400,
+ "pink-500": $pink-500,
+ "pink-600": $pink-600,
+ "pink-700": $pink-700,
+ "pink-800": $pink-800,
+ "pink-900": $pink-900
+) !default;
+
+$reds: (
+ "red-100": $red-100,
+ "red-200": $red-200,
+ "red-300": $red-300,
+ "red-400": $red-400,
+ "red-500": $red-500,
+ "red-600": $red-600,
+ "red-700": $red-700,
+ "red-800": $red-800,
+ "red-900": $red-900
+) !default;
+
+$oranges: (
+ "orange-100": $orange-100,
+ "orange-200": $orange-200,
+ "orange-300": $orange-300,
+ "orange-400": $orange-400,
+ "orange-500": $orange-500,
+ "orange-600": $orange-600,
+ "orange-700": $orange-700,
+ "orange-800": $orange-800,
+ "orange-900": $orange-900
+) !default;
+
+$yellows: (
+ "yellow-100": $yellow-100,
+ "yellow-200": $yellow-200,
+ "yellow-300": $yellow-300,
+ "yellow-400": $yellow-400,
+ "yellow-500": $yellow-500,
+ "yellow-600": $yellow-600,
+ "yellow-700": $yellow-700,
+ "yellow-800": $yellow-800,
+ "yellow-900": $yellow-900
+) !default;
+
+$greens: (
+ "green-100": $green-100,
+ "green-200": $green-200,
+ "green-300": $green-300,
+ "green-400": $green-400,
+ "green-500": $green-500,
+ "green-600": $green-600,
+ "green-700": $green-700,
+ "green-800": $green-800,
+ "green-900": $green-900
+) !default;
+
+$teals: (
+ "teal-100": $teal-100,
+ "teal-200": $teal-200,
+ "teal-300": $teal-300,
+ "teal-400": $teal-400,
+ "teal-500": $teal-500,
+ "teal-600": $teal-600,
+ "teal-700": $teal-700,
+ "teal-800": $teal-800,
+ "teal-900": $teal-900
+) !default;
+
+$cyans: (
+ "cyan-100": $cyan-100,
+ "cyan-200": $cyan-200,
+ "cyan-300": $cyan-300,
+ "cyan-400": $cyan-400,
+ "cyan-500": $cyan-500,
+ "cyan-600": $cyan-600,
+ "cyan-700": $cyan-700,
+ "cyan-800": $cyan-800,
+ "cyan-900": $cyan-900
+) !default;
+// fusv-enable
+
+// scss-docs-start theme-color-variables
+$primary: $blue !default;
+$secondary: $gray-600 !default;
+$success: $green !default;
+$info: $cyan !default;
+$warning: $yellow !default;
+$danger: $red !default;
+$light: $gray-100 !default;
+$dark: $gray-900 !default;
+// scss-docs-end theme-color-variables
+
+// scss-docs-start theme-colors-map
+$theme-colors: (
+ "primary": $primary,
+ "secondary": $secondary,
+ "success": $success,
+ "info": $info,
+ "warning": $warning,
+ "danger": $danger,
+ "light": $light,
+ "dark": $dark
+) !default;
+// scss-docs-end theme-colors-map
+
+// scss-docs-start theme-text-variables
+$primary-text-emphasis: shade-color($primary, 60%) !default;
+$secondary-text-emphasis: shade-color($secondary, 60%) !default;
+$success-text-emphasis: shade-color($success, 60%) !default;
+$info-text-emphasis: shade-color($info, 60%) !default;
+$warning-text-emphasis: shade-color($warning, 60%) !default;
+$danger-text-emphasis: shade-color($danger, 60%) !default;
+$light-text-emphasis: $gray-700 !default;
+$dark-text-emphasis: $gray-700 !default;
+// scss-docs-end theme-text-variables
+
+// scss-docs-start theme-bg-subtle-variables
+$primary-bg-subtle: tint-color($primary, 80%) !default;
+$secondary-bg-subtle: tint-color($secondary, 80%) !default;
+$success-bg-subtle: tint-color($success, 80%) !default;
+$info-bg-subtle: tint-color($info, 80%) !default;
+$warning-bg-subtle: tint-color($warning, 80%) !default;
+$danger-bg-subtle: tint-color($danger, 80%) !default;
+$light-bg-subtle: mix($gray-100, $white) !default;
+$dark-bg-subtle: $gray-400 !default;
+// scss-docs-end theme-bg-subtle-variables
+
+// scss-docs-start theme-border-subtle-variables
+$primary-border-subtle: tint-color($primary, 60%) !default;
+$secondary-border-subtle: tint-color($secondary, 60%) !default;
+$success-border-subtle: tint-color($success, 60%) !default;
+$info-border-subtle: tint-color($info, 60%) !default;
+$warning-border-subtle: tint-color($warning, 60%) !default;
+$danger-border-subtle: tint-color($danger, 60%) !default;
+$light-border-subtle: $gray-200 !default;
+$dark-border-subtle: $gray-500 !default;
+// scss-docs-end theme-border-subtle-variables
+
+// Characters which are escaped by the escape-svg function
+$escaped-characters: (
+ ("<", "%3c"),
+ (">", "%3e"),
+ ("#", "%23"),
+ ("(", "%28"),
+ (")", "%29"),
+) !default;
+
+// Options
+//
+// Quickly modify global styling by enabling or disabling optional features.
+
+$enable-caret: true !default;
+$enable-rounded: true !default;
+$enable-shadows: false !default;
+$enable-gradients: false !default;
+$enable-transitions: true !default;
+$enable-reduced-motion: true !default;
+$enable-smooth-scroll: true !default;
+$enable-grid-classes: true !default;
+$enable-container-classes: true !default;
+$enable-cssgrid: false !default;
+$enable-button-pointers: true !default;
+$enable-rfs: true !default;
+$enable-validation-icons: true !default;
+$enable-negative-margins: false !default;
+$enable-deprecation-messages: true !default;
+$enable-important-utilities: true !default;
+
+$enable-dark-mode: true !default;
+$color-mode-type: data !default; // `data` or `media-query`
+
+// Prefix for :root CSS variables
+
+$variable-prefix: bs- !default; // Deprecated in v5.2.0 for the shorter `$prefix`
+$prefix: $variable-prefix !default;
+
+// Gradient
+//
+// The gradient which is added to components if `$enable-gradients` is `true`
+// This gradient is also added to elements with `.bg-gradient`
+// scss-docs-start variable-gradient
+$gradient: linear-gradient(180deg, rgba($white, .15), rgba($white, 0)) !default;
+// scss-docs-end variable-gradient
+
+// Spacing
+//
+// Control the default styling of most Bootstrap elements by modifying these
+// variables. Mostly focused on spacing.
+// You can add more entries to the $spacers map, should you need more variation.
+
+// scss-docs-start spacer-variables-maps
+$spacer: 1rem !default;
+$spacers: (
+ 0: 0,
+ 1: $spacer * .25,
+ 2: $spacer * .5,
+ 3: $spacer,
+ 4: $spacer * 1.5,
+ 5: $spacer * 3,
+) !default;
+// scss-docs-end spacer-variables-maps
+
+// Position
+//
+// Define the edge positioning anchors of the position utilities.
+
+// scss-docs-start position-map
+$position-values: (
+ 0: 0,
+ 50: 50%,
+ 100: 100%
+) !default;
+// scss-docs-end position-map
+
+// Body
+//
+// Settings for the `` element.
+
+$body-text-align: null !default;
+$body-color: $gray-900 !default;
+$body-bg: $white !default;
+
+$body-secondary-color: rgba($body-color, .75) !default;
+$body-secondary-bg: $gray-200 !default;
+
+$body-tertiary-color: rgba($body-color, .5) !default;
+$body-tertiary-bg: $gray-100 !default;
+
+$body-emphasis-color: $black !default;
+
+// Links
+//
+// Style anchor elements.
+
+$link-color: $primary !default;
+$link-decoration: underline !default;
+$link-shade-percentage: 20% !default;
+$link-hover-color: shift-color($link-color, $link-shade-percentage) !default;
+$link-hover-decoration: null !default;
+
+$stretched-link-pseudo-element: after !default;
+$stretched-link-z-index: 1 !default;
+
+// Icon links
+// scss-docs-start icon-link-variables
+$icon-link-gap: .375rem !default;
+$icon-link-underline-offset: .25em !default;
+$icon-link-icon-size: 1em !default;
+$icon-link-icon-transition: .2s ease-in-out transform !default;
+$icon-link-icon-transform: translate3d(.25em, 0, 0) !default;
+// scss-docs-end icon-link-variables
+
+// Paragraphs
+//
+// Style p element.
+
+$paragraph-margin-bottom: 1rem !default;
+
+
+// Grid breakpoints
+//
+// Define the minimum dimensions at which your layout will change,
+// adapting to different screen sizes, for use in media queries.
+
+// scss-docs-start grid-breakpoints
+$grid-breakpoints: (
+ xs: 0,
+ sm: 576px,
+ md: 768px,
+ lg: 992px,
+ xl: 1200px,
+ xxl: 1400px
+) !default;
+// scss-docs-end grid-breakpoints
+
+@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
+@include _assert-starts-at-zero($grid-breakpoints, "$grid-breakpoints");
+
+
+// Grid containers
+//
+// Define the maximum width of `.container` for different screen sizes.
+
+// scss-docs-start container-max-widths
+$container-max-widths: (
+ sm: 540px,
+ md: 720px,
+ lg: 960px,
+ xl: 1140px,
+ xxl: 1320px
+) !default;
+// scss-docs-end container-max-widths
+
+@include _assert-ascending($container-max-widths, "$container-max-widths");
+
+
+// Grid columns
+//
+// Set the number of columns and specify the width of the gutters.
+
+$grid-columns: 12 !default;
+$grid-gutter-width: 1.5rem !default;
+$grid-row-columns: 6 !default;
+
+// Container padding
+
+$container-padding-x: $grid-gutter-width !default;
+
+
+// Components
+//
+// Define common padding and border radius sizes and more.
+
+// scss-docs-start border-variables
+$border-width: 1px !default;
+$border-widths: (
+ 1: 1px,
+ 2: 2px,
+ 3: 3px,
+ 4: 4px,
+ 5: 5px
+) !default;
+$border-style: solid !default;
+$border-color: $gray-300 !default;
+$border-color-translucent: rgba($black, .175) !default;
+// scss-docs-end border-variables
+
+// scss-docs-start border-radius-variables
+$border-radius: .375rem !default;
+$border-radius-sm: .25rem !default;
+$border-radius-lg: .5rem !default;
+$border-radius-xl: 1rem !default;
+$border-radius-xxl: 2rem !default;
+$border-radius-pill: 50rem !default;
+// scss-docs-end border-radius-variables
+// fusv-disable
+$border-radius-2xl: $border-radius-xxl !default; // Deprecated in v5.3.0
+// fusv-enable
+
+// scss-docs-start box-shadow-variables
+$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;
+$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;
+$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;
+$box-shadow-inset: inset 0 1px 2px rgba($black, .075) !default;
+// scss-docs-end box-shadow-variables
+
+$component-active-color: $white !default;
+$component-active-bg: $primary !default;
+
+// scss-docs-start focus-ring-variables
+$focus-ring-width: .25rem !default;
+$focus-ring-opacity: .25 !default;
+$focus-ring-color: rgba($primary, $focus-ring-opacity) !default;
+$focus-ring-blur: 0 !default;
+$focus-ring-box-shadow: 0 0 $focus-ring-blur $focus-ring-width $focus-ring-color !default;
+// scss-docs-end focus-ring-variables
+
+// scss-docs-start caret-variables
+$caret-width: .3em !default;
+$caret-vertical-align: $caret-width * .85 !default;
+$caret-spacing: $caret-width * .85 !default;
+// scss-docs-end caret-variables
+
+$transition-base: all .2s ease-in-out !default;
+$transition-fade: opacity .15s linear !default;
+// scss-docs-start collapse-transition
+$transition-collapse: height .35s ease !default;
+$transition-collapse-width: width .35s ease !default;
+// scss-docs-end collapse-transition
+
+// stylelint-disable function-disallowed-list
+// scss-docs-start aspect-ratios
+$aspect-ratios: (
+ "1x1": 100%,
+ "4x3": calc(3 / 4 * 100%),
+ "16x9": calc(9 / 16 * 100%),
+ "21x9": calc(9 / 21 * 100%)
+) !default;
+// scss-docs-end aspect-ratios
+// stylelint-enable function-disallowed-list
+
+// Typography
+//
+// Font, line-height, and color for body text, headings, and more.
+
+// scss-docs-start font-variables
+// stylelint-disable value-keyword-case
+$font-family-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default;
+$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default;
+// stylelint-enable value-keyword-case
+$font-family-base: var(--#{$prefix}font-sans-serif) !default;
+$font-family-code: var(--#{$prefix}font-monospace) !default;
+
+// $font-size-root affects the value of `rem`, which is used for as well font sizes, paddings, and margins
+// $font-size-base affects the font size of the body text
+$font-size-root: null !default;
+$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`
+$font-size-sm: $font-size-base * .875 !default;
+$font-size-lg: $font-size-base * 1.25 !default;
+
+$font-weight-lighter: lighter !default;
+$font-weight-light: 300 !default;
+$font-weight-normal: 400 !default;
+$font-weight-medium: 500 !default;
+$font-weight-semibold: 600 !default;
+$font-weight-bold: 700 !default;
+$font-weight-bolder: bolder !default;
+
+$font-weight-base: $font-weight-normal !default;
+
+$line-height-base: 1.5 !default;
+$line-height-sm: 1.25 !default;
+$line-height-lg: 2 !default;
+
+$h1-font-size: $font-size-base * 2.5 !default;
+$h2-font-size: $font-size-base * 2 !default;
+$h3-font-size: $font-size-base * 1.75 !default;
+$h4-font-size: $font-size-base * 1.5 !default;
+$h5-font-size: $font-size-base * 1.25 !default;
+$h6-font-size: $font-size-base !default;
+// scss-docs-end font-variables
+
+// scss-docs-start font-sizes
+$font-sizes: (
+ 1: $h1-font-size,
+ 2: $h2-font-size,
+ 3: $h3-font-size,
+ 4: $h4-font-size,
+ 5: $h5-font-size,
+ 6: $h6-font-size
+) !default;
+// scss-docs-end font-sizes
+
+// scss-docs-start headings-variables
+$headings-margin-bottom: $spacer * .5 !default;
+$headings-font-family: null !default;
+$headings-font-style: null !default;
+$headings-font-weight: 500 !default;
+$headings-line-height: 1.2 !default;
+$headings-color: inherit !default;
+// scss-docs-end headings-variables
+
+// scss-docs-start display-headings
+$display-font-sizes: (
+ 1: 5rem,
+ 2: 4.5rem,
+ 3: 4rem,
+ 4: 3.5rem,
+ 5: 3rem,
+ 6: 2.5rem
+) !default;
+
+$display-font-family: null !default;
+$display-font-style: null !default;
+$display-font-weight: 300 !default;
+$display-line-height: $headings-line-height !default;
+// scss-docs-end display-headings
+
+// scss-docs-start type-variables
+$lead-font-size: $font-size-base * 1.25 !default;
+$lead-font-weight: 300 !default;
+
+$small-font-size: .875em !default;
+
+$sub-sup-font-size: .75em !default;
+
+// fusv-disable
+$text-muted: var(--#{$prefix}secondary-color) !default; // Deprecated in 5.3.0
+// fusv-enable
+
+$initialism-font-size: $small-font-size !default;
+
+$blockquote-margin-y: $spacer !default;
+$blockquote-font-size: $font-size-base * 1.25 !default;
+$blockquote-footer-color: $gray-600 !default;
+$blockquote-footer-font-size: $small-font-size !default;
+
+$hr-margin-y: $spacer !default;
+$hr-color: inherit !default;
+
+// fusv-disable
+$hr-bg-color: null !default; // Deprecated in v5.2.0
+$hr-height: null !default; // Deprecated in v5.2.0
+// fusv-enable
+
+$hr-border-color: null !default; // Allows for inherited colors
+$hr-border-width: var(--#{$prefix}border-width) !default;
+$hr-opacity: .25 !default;
+
+// scss-docs-start vr-variables
+$vr-border-width: var(--#{$prefix}border-width) !default;
+// scss-docs-end vr-variables
+
+$legend-margin-bottom: .5rem !default;
+$legend-font-size: 1.5rem !default;
+$legend-font-weight: null !default;
+
+$dt-font-weight: $font-weight-bold !default;
+
+$list-inline-padding: .5rem !default;
+
+$mark-padding: .1875em !default;
+$mark-color: $body-color !default;
+$mark-bg: $yellow-100 !default;
+// scss-docs-end type-variables
+
+
+// Tables
+//
+// Customizes the `.table` component with basic values, each used across all table variations.
+
+// scss-docs-start table-variables
+$table-cell-padding-y: .5rem !default;
+$table-cell-padding-x: .5rem !default;
+$table-cell-padding-y-sm: .25rem !default;
+$table-cell-padding-x-sm: .25rem !default;
+
+$table-cell-vertical-align: top !default;
+
+$table-color: var(--#{$prefix}emphasis-color) !default;
+$table-bg: var(--#{$prefix}body-bg) !default;
+$table-accent-bg: transparent !default;
+
+$table-th-font-weight: null !default;
+
+$table-striped-color: $table-color !default;
+$table-striped-bg-factor: .05 !default;
+$table-striped-bg: rgba(var(--#{$prefix}emphasis-color-rgb), $table-striped-bg-factor) !default;
+
+$table-active-color: $table-color !default;
+$table-active-bg-factor: .1 !default;
+$table-active-bg: rgba(var(--#{$prefix}emphasis-color-rgb), $table-active-bg-factor) !default;
+
+$table-hover-color: $table-color !default;
+$table-hover-bg-factor: .075 !default;
+$table-hover-bg: rgba(var(--#{$prefix}emphasis-color-rgb), $table-hover-bg-factor) !default;
+
+$table-border-factor: .2 !default;
+$table-border-width: var(--#{$prefix}border-width) !default;
+$table-border-color: var(--#{$prefix}border-color) !default;
+
+$table-striped-order: odd !default;
+$table-striped-columns-order: even !default;
+
+$table-group-separator-color: currentcolor !default;
+
+$table-caption-color: var(--#{$prefix}secondary-color) !default;
+
+$table-bg-scale: -80% !default;
+// scss-docs-end table-variables
+
+// scss-docs-start table-loop
+$table-variants: (
+ "primary": shift-color($primary, $table-bg-scale),
+ "secondary": shift-color($secondary, $table-bg-scale),
+ "success": shift-color($success, $table-bg-scale),
+ "info": shift-color($info, $table-bg-scale),
+ "warning": shift-color($warning, $table-bg-scale),
+ "danger": shift-color($danger, $table-bg-scale),
+ "light": $light,
+ "dark": $dark,
+) !default;
+// scss-docs-end table-loop
+
+
+// Buttons + Forms
+//
+// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.
+
+// scss-docs-start input-btn-variables
+$input-btn-padding-y: .375rem !default;
+$input-btn-padding-x: .75rem !default;
+$input-btn-font-family: null !default;
+$input-btn-font-size: $font-size-base !default;
+$input-btn-line-height: $line-height-base !default;
+
+$input-btn-focus-width: $focus-ring-width !default;
+$input-btn-focus-color-opacity: $focus-ring-opacity !default;
+$input-btn-focus-color: $focus-ring-color !default;
+$input-btn-focus-blur: $focus-ring-blur !default;
+$input-btn-focus-box-shadow: $focus-ring-box-shadow !default;
+
+$input-btn-padding-y-sm: .25rem !default;
+$input-btn-padding-x-sm: .5rem !default;
+$input-btn-font-size-sm: $font-size-sm !default;
+
+$input-btn-padding-y-lg: .5rem !default;
+$input-btn-padding-x-lg: 1rem !default;
+$input-btn-font-size-lg: $font-size-lg !default;
+
+$input-btn-border-width: var(--#{$prefix}border-width) !default;
+// scss-docs-end input-btn-variables
+
+
+// Buttons
+//
+// For each of Bootstrap's buttons, define text, background, and border color.
+
+// scss-docs-start btn-variables
+$btn-color: var(--#{$prefix}body-color) !default;
+$btn-padding-y: $input-btn-padding-y !default;
+$btn-padding-x: $input-btn-padding-x !default;
+$btn-font-family: $input-btn-font-family !default;
+$btn-font-size: $input-btn-font-size !default;
+$btn-line-height: $input-btn-line-height !default;
+$btn-white-space: null !default; // Set to `nowrap` to prevent text wrapping
+
+$btn-padding-y-sm: $input-btn-padding-y-sm !default;
+$btn-padding-x-sm: $input-btn-padding-x-sm !default;
+$btn-font-size-sm: $input-btn-font-size-sm !default;
+
+$btn-padding-y-lg: $input-btn-padding-y-lg !default;
+$btn-padding-x-lg: $input-btn-padding-x-lg !default;
+$btn-font-size-lg: $input-btn-font-size-lg !default;
+
+$btn-border-width: $input-btn-border-width !default;
+
+$btn-font-weight: $font-weight-normal !default;
+$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;
+$btn-focus-width: $input-btn-focus-width !default;
+$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;
+$btn-disabled-opacity: .65 !default;
+$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;
+
+$btn-link-color: var(--#{$prefix}link-color) !default;
+$btn-link-hover-color: var(--#{$prefix}link-hover-color) !default;
+$btn-link-disabled-color: $gray-600 !default;
+$btn-link-focus-shadow-rgb: to-rgb(mix(color-contrast($link-color), $link-color, 15%)) !default;
+
+// Allows for customizing button radius independently from global border radius
+$btn-border-radius: var(--#{$prefix}border-radius) !default;
+$btn-border-radius-sm: var(--#{$prefix}border-radius-sm) !default;
+$btn-border-radius-lg: var(--#{$prefix}border-radius-lg) !default;
+
+$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+
+$btn-hover-bg-shade-amount: 15% !default;
+$btn-hover-bg-tint-amount: 15% !default;
+$btn-hover-border-shade-amount: 20% !default;
+$btn-hover-border-tint-amount: 10% !default;
+$btn-active-bg-shade-amount: 20% !default;
+$btn-active-bg-tint-amount: 20% !default;
+$btn-active-border-shade-amount: 25% !default;
+$btn-active-border-tint-amount: 10% !default;
+// scss-docs-end btn-variables
+
+
+// Forms
+
+// scss-docs-start form-text-variables
+$form-text-margin-top: .25rem !default;
+$form-text-font-size: $small-font-size !default;
+$form-text-font-style: null !default;
+$form-text-font-weight: null !default;
+$form-text-color: var(--#{$prefix}secondary-color) !default;
+// scss-docs-end form-text-variables
+
+// scss-docs-start form-label-variables
+$form-label-margin-bottom: .5rem !default;
+$form-label-font-size: null !default;
+$form-label-font-style: null !default;
+$form-label-font-weight: null !default;
+$form-label-color: null !default;
+// scss-docs-end form-label-variables
+
+// scss-docs-start form-input-variables
+$input-padding-y: $input-btn-padding-y !default;
+$input-padding-x: $input-btn-padding-x !default;
+$input-font-family: $input-btn-font-family !default;
+$input-font-size: $input-btn-font-size !default;
+$input-font-weight: $font-weight-base !default;
+$input-line-height: $input-btn-line-height !default;
+
+$input-padding-y-sm: $input-btn-padding-y-sm !default;
+$input-padding-x-sm: $input-btn-padding-x-sm !default;
+$input-font-size-sm: $input-btn-font-size-sm !default;
+
+$input-padding-y-lg: $input-btn-padding-y-lg !default;
+$input-padding-x-lg: $input-btn-padding-x-lg !default;
+$input-font-size-lg: $input-btn-font-size-lg !default;
+
+$input-bg: var(--#{$prefix}body-bg) !default;
+$input-disabled-color: null !default;
+$input-disabled-bg: var(--#{$prefix}secondary-bg) !default;
+$input-disabled-border-color: null !default;
+
+$input-color: var(--#{$prefix}body-color) !default;
+$input-border-color: var(--#{$prefix}border-color) !default;
+$input-border-width: $input-btn-border-width !default;
+$input-box-shadow: var(--#{$prefix}box-shadow-inset) !default;
+
+$input-border-radius: var(--#{$prefix}border-radius) !default;
+$input-border-radius-sm: var(--#{$prefix}border-radius-sm) !default;
+$input-border-radius-lg: var(--#{$prefix}border-radius-lg) !default;
+
+$input-focus-bg: $input-bg !default;
+$input-focus-border-color: tint-color($component-active-bg, 50%) !default;
+$input-focus-color: $input-color !default;
+$input-focus-width: $input-btn-focus-width !default;
+$input-focus-box-shadow: $input-btn-focus-box-shadow !default;
+
+$input-placeholder-color: var(--#{$prefix}secondary-color) !default;
+$input-plaintext-color: var(--#{$prefix}body-color) !default;
+
+$input-height-border: calc(#{$input-border-width} * 2) !default; // stylelint-disable-line function-disallowed-list
+
+$input-height-inner: add($input-line-height * 1em, $input-padding-y * 2) !default;
+$input-height-inner-half: add($input-line-height * .5em, $input-padding-y) !default;
+$input-height-inner-quarter: add($input-line-height * .25em, $input-padding-y * .5) !default;
+
+$input-height: add($input-line-height * 1em, add($input-padding-y * 2, $input-height-border, false)) !default;
+$input-height-sm: add($input-line-height * 1em, add($input-padding-y-sm * 2, $input-height-border, false)) !default;
+$input-height-lg: add($input-line-height * 1em, add($input-padding-y-lg * 2, $input-height-border, false)) !default;
+
+$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+
+$form-color-width: 3rem !default;
+// scss-docs-end form-input-variables
+
+// scss-docs-start form-check-variables
+$form-check-input-width: 1em !default;
+$form-check-min-height: $font-size-base * $line-height-base !default;
+$form-check-padding-start: $form-check-input-width + .5em !default;
+$form-check-margin-bottom: .125rem !default;
+$form-check-label-color: null !default;
+$form-check-label-cursor: null !default;
+$form-check-transition: null !default;
+
+$form-check-input-active-filter: brightness(90%) !default;
+
+$form-check-input-bg: $input-bg !default;
+$form-check-input-border: var(--#{$prefix}border-width) solid var(--#{$prefix}border-color) !default;
+$form-check-input-border-radius: .25em !default;
+$form-check-radio-border-radius: 50% !default;
+$form-check-input-focus-border: $input-focus-border-color !default;
+$form-check-input-focus-box-shadow: $focus-ring-box-shadow !default;
+
+$form-check-input-checked-color: $component-active-color !default;
+$form-check-input-checked-bg-color: $component-active-bg !default;
+$form-check-input-checked-border-color: $form-check-input-checked-bg-color !default;
+$form-check-input-checked-bg-image: url("data:image/svg+xml,
") !default;
+$form-check-radio-checked-bg-image: url("data:image/svg+xml,
") !default;
+
+$form-check-input-indeterminate-color: $component-active-color !default;
+$form-check-input-indeterminate-bg-color: $component-active-bg !default;
+$form-check-input-indeterminate-border-color: $form-check-input-indeterminate-bg-color !default;
+$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,
") !default;
+
+$form-check-input-disabled-opacity: .5 !default;
+$form-check-label-disabled-opacity: $form-check-input-disabled-opacity !default;
+$form-check-btn-check-disabled-opacity: $btn-disabled-opacity !default;
+
+$form-check-inline-margin-end: 1rem !default;
+// scss-docs-end form-check-variables
+
+// scss-docs-start form-switch-variables
+$form-switch-color: rgba($black, .25) !default;
+$form-switch-width: 2em !default;
+$form-switch-padding-start: $form-switch-width + .5em !default;
+$form-switch-bg-image: url("data:image/svg+xml,
") !default;
+$form-switch-border-radius: $form-switch-width !default;
+$form-switch-transition: background-position .15s ease-in-out !default;
+
+$form-switch-focus-color: $input-focus-border-color !default;
+$form-switch-focus-bg-image: url("data:image/svg+xml,
") !default;
+
+$form-switch-checked-color: $component-active-color !default;
+$form-switch-checked-bg-image: url("data:image/svg+xml,
") !default;
+$form-switch-checked-bg-position: right center !default;
+// scss-docs-end form-switch-variables
+
+// scss-docs-start input-group-variables
+$input-group-addon-padding-y: $input-padding-y !default;
+$input-group-addon-padding-x: $input-padding-x !default;
+$input-group-addon-font-weight: $input-font-weight !default;
+$input-group-addon-color: $input-color !default;
+$input-group-addon-bg: var(--#{$prefix}tertiary-bg) !default;
+$input-group-addon-border-color: $input-border-color !default;
+// scss-docs-end input-group-variables
+
+// scss-docs-start form-select-variables
+$form-select-padding-y: $input-padding-y !default;
+$form-select-padding-x: $input-padding-x !default;
+$form-select-font-family: $input-font-family !default;
+$form-select-font-size: $input-font-size !default;
+$form-select-indicator-padding: $form-select-padding-x * 3 !default; // Extra padding for background-image
+$form-select-font-weight: $input-font-weight !default;
+$form-select-line-height: $input-line-height !default;
+$form-select-color: $input-color !default;
+$form-select-bg: $input-bg !default;
+$form-select-disabled-color: null !default;
+$form-select-disabled-bg: $input-disabled-bg !default;
+$form-select-disabled-border-color: $input-disabled-border-color !default;
+$form-select-bg-position: right $form-select-padding-x center !default;
+$form-select-bg-size: 16px 12px !default; // In pixels because image dimensions
+$form-select-indicator-color: $gray-800 !default;
+$form-select-indicator: url("data:image/svg+xml,
") !default;
+
+$form-select-feedback-icon-padding-end: $form-select-padding-x * 2.5 + $form-select-indicator-padding !default;
+$form-select-feedback-icon-position: center right $form-select-indicator-padding !default;
+$form-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;
+
+$form-select-border-width: $input-border-width !default;
+$form-select-border-color: $input-border-color !default;
+$form-select-border-radius: $input-border-radius !default;
+$form-select-box-shadow: var(--#{$prefix}box-shadow-inset) !default;
+
+$form-select-focus-border-color: $input-focus-border-color !default;
+$form-select-focus-width: $input-focus-width !default;
+$form-select-focus-box-shadow: 0 0 0 $form-select-focus-width $input-btn-focus-color !default;
+
+$form-select-padding-y-sm: $input-padding-y-sm !default;
+$form-select-padding-x-sm: $input-padding-x-sm !default;
+$form-select-font-size-sm: $input-font-size-sm !default;
+$form-select-border-radius-sm: $input-border-radius-sm !default;
+
+$form-select-padding-y-lg: $input-padding-y-lg !default;
+$form-select-padding-x-lg: $input-padding-x-lg !default;
+$form-select-font-size-lg: $input-font-size-lg !default;
+$form-select-border-radius-lg: $input-border-radius-lg !default;
+
+$form-select-transition: $input-transition !default;
+// scss-docs-end form-select-variables
+
+// scss-docs-start form-range-variables
+$form-range-track-width: 100% !default;
+$form-range-track-height: .5rem !default;
+$form-range-track-cursor: pointer !default;
+$form-range-track-bg: var(--#{$prefix}secondary-bg) !default;
+$form-range-track-border-radius: 1rem !default;
+$form-range-track-box-shadow: var(--#{$prefix}box-shadow-inset) !default;
+
+$form-range-thumb-width: 1rem !default;
+$form-range-thumb-height: $form-range-thumb-width !default;
+$form-range-thumb-bg: $component-active-bg !default;
+$form-range-thumb-border: 0 !default;
+$form-range-thumb-border-radius: 1rem !default;
+$form-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;
+$form-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;
+$form-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in Edge
+$form-range-thumb-active-bg: tint-color($component-active-bg, 70%) !default;
+$form-range-thumb-disabled-bg: var(--#{$prefix}secondary-color) !default;
+$form-range-thumb-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+// scss-docs-end form-range-variables
+
+// scss-docs-start form-file-variables
+$form-file-button-color: $input-color !default;
+$form-file-button-bg: var(--#{$prefix}tertiary-bg) !default;
+$form-file-button-hover-bg: var(--#{$prefix}secondary-bg) !default;
+// scss-docs-end form-file-variables
+
+// scss-docs-start form-floating-variables
+$form-floating-height: add(3.5rem, $input-height-border) !default;
+$form-floating-line-height: 1.25 !default;
+$form-floating-padding-x: $input-padding-x !default;
+$form-floating-padding-y: 1rem !default;
+$form-floating-input-padding-t: 1.625rem !default;
+$form-floating-input-padding-b: .625rem !default;
+$form-floating-label-height: 1.5em !default;
+$form-floating-label-opacity: .65 !default;
+$form-floating-label-transform: scale(.85) translateY(-.5rem) translateX(.15rem) !default;
+$form-floating-label-disabled-color: $gray-600 !default;
+$form-floating-transition: opacity .1s ease-in-out, transform .1s ease-in-out !default;
+// scss-docs-end form-floating-variables
+
+// Form validation
+
+// scss-docs-start form-feedback-variables
+$form-feedback-margin-top: $form-text-margin-top !default;
+$form-feedback-font-size: $form-text-font-size !default;
+$form-feedback-font-style: $form-text-font-style !default;
+$form-feedback-valid-color: $success !default;
+$form-feedback-invalid-color: $danger !default;
+
+$form-feedback-icon-valid-color: $form-feedback-valid-color !default;
+$form-feedback-icon-valid: url("data:image/svg+xml,
") !default;
+$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;
+$form-feedback-icon-invalid: url("data:image/svg+xml,
") !default;
+// scss-docs-end form-feedback-variables
+
+// scss-docs-start form-validation-colors
+$form-valid-color: $form-feedback-valid-color !default;
+$form-valid-border-color: $form-feedback-valid-color !default;
+$form-invalid-color: $form-feedback-invalid-color !default;
+$form-invalid-border-color: $form-feedback-invalid-color !default;
+// scss-docs-end form-validation-colors
+
+// scss-docs-start form-validation-states
+$form-validation-states: (
+ "valid": (
+ "color": var(--#{$prefix}form-valid-color),
+ "icon": $form-feedback-icon-valid,
+ "tooltip-color": #fff,
+ "tooltip-bg-color": var(--#{$prefix}success),
+ "focus-box-shadow": 0 0 $input-btn-focus-blur $input-focus-width rgba(var(--#{$prefix}success-rgb), $input-btn-focus-color-opacity),
+ "border-color": var(--#{$prefix}form-valid-border-color),
+ ),
+ "invalid": (
+ "color": var(--#{$prefix}form-invalid-color),
+ "icon": $form-feedback-icon-invalid,
+ "tooltip-color": #fff,
+ "tooltip-bg-color": var(--#{$prefix}danger),
+ "focus-box-shadow": 0 0 $input-btn-focus-blur $input-focus-width rgba(var(--#{$prefix}danger-rgb), $input-btn-focus-color-opacity),
+ "border-color": var(--#{$prefix}form-invalid-border-color),
+ )
+) !default;
+// scss-docs-end form-validation-states
+
+// Z-index master list
+//
+// Warning: Avoid customizing these values. They're used for a bird's eye view
+// of components dependent on the z-axis and are designed to all work together.
+
+// scss-docs-start zindex-stack
+$zindex-dropdown: 1000 !default;
+$zindex-sticky: 1020 !default;
+$zindex-fixed: 1030 !default;
+$zindex-offcanvas-backdrop: 1040 !default;
+$zindex-offcanvas: 1045 !default;
+$zindex-modal-backdrop: 1050 !default;
+$zindex-modal: 1055 !default;
+$zindex-popover: 1070 !default;
+$zindex-tooltip: 1080 !default;
+$zindex-toast: 1090 !default;
+// scss-docs-end zindex-stack
+
+// scss-docs-start zindex-levels-map
+$zindex-levels: (
+ n1: -1,
+ 0: 0,
+ 1: 1,
+ 2: 2,
+ 3: 3
+) !default;
+// scss-docs-end zindex-levels-map
+
+
+// Navs
+
+// scss-docs-start nav-variables
+$nav-link-padding-y: .5rem !default;
+$nav-link-padding-x: 1rem !default;
+$nav-link-font-size: null !default;
+$nav-link-font-weight: null !default;
+$nav-link-color: var(--#{$prefix}link-color) !default;
+$nav-link-hover-color: var(--#{$prefix}link-hover-color) !default;
+$nav-link-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out !default;
+$nav-link-disabled-color: var(--#{$prefix}secondary-color) !default;
+$nav-link-focus-box-shadow: $focus-ring-box-shadow !default;
+
+$nav-tabs-border-color: var(--#{$prefix}border-color) !default;
+$nav-tabs-border-width: var(--#{$prefix}border-width) !default;
+$nav-tabs-border-radius: var(--#{$prefix}border-radius) !default;
+$nav-tabs-link-hover-border-color: var(--#{$prefix}secondary-bg) var(--#{$prefix}secondary-bg) $nav-tabs-border-color !default;
+$nav-tabs-link-active-color: var(--#{$prefix}emphasis-color) !default;
+$nav-tabs-link-active-bg: var(--#{$prefix}body-bg) !default;
+$nav-tabs-link-active-border-color: var(--#{$prefix}border-color) var(--#{$prefix}border-color) $nav-tabs-link-active-bg !default;
+
+$nav-pills-border-radius: var(--#{$prefix}border-radius) !default;
+$nav-pills-link-active-color: $component-active-color !default;
+$nav-pills-link-active-bg: $component-active-bg !default;
+
+$nav-underline-gap: 1rem !default;
+$nav-underline-border-width: .125rem !default;
+$nav-underline-link-active-color: var(--#{$prefix}emphasis-color) !default;
+// scss-docs-end nav-variables
+
+
+// Navbar
+
+// scss-docs-start navbar-variables
+$navbar-padding-y: $spacer * .5 !default;
+$navbar-padding-x: null !default;
+
+$navbar-nav-link-padding-x: .5rem !default;
+
+$navbar-brand-font-size: $font-size-lg !default;
+// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link
+$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;
+$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;
+$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) * .5 !default;
+$navbar-brand-margin-end: 1rem !default;
+
+$navbar-toggler-padding-y: .25rem !default;
+$navbar-toggler-padding-x: .75rem !default;
+$navbar-toggler-font-size: $font-size-lg !default;
+$navbar-toggler-border-radius: $btn-border-radius !default;
+$navbar-toggler-focus-width: $btn-focus-width !default;
+$navbar-toggler-transition: box-shadow .15s ease-in-out !default;
+
+$navbar-light-color: rgba(var(--#{$prefix}emphasis-color-rgb), .65) !default;
+$navbar-light-hover-color: rgba(var(--#{$prefix}emphasis-color-rgb), .8) !default;
+$navbar-light-active-color: rgba(var(--#{$prefix}emphasis-color-rgb), 1) !default;
+$navbar-light-disabled-color: rgba(var(--#{$prefix}emphasis-color-rgb), .3) !default;
+$navbar-light-icon-color: rgba($body-color, .75) !default;
+$navbar-light-toggler-icon-bg: url("data:image/svg+xml,
") !default;
+$navbar-light-toggler-border-color: rgba(var(--#{$prefix}emphasis-color-rgb), .15) !default;
+$navbar-light-brand-color: $navbar-light-active-color !default;
+$navbar-light-brand-hover-color: $navbar-light-active-color !default;
+// scss-docs-end navbar-variables
+
+// scss-docs-start navbar-dark-variables
+$navbar-dark-color: rgba($white, .55) !default;
+$navbar-dark-hover-color: rgba($white, .75) !default;
+$navbar-dark-active-color: $white !default;
+$navbar-dark-disabled-color: rgba($white, .25) !default;
+$navbar-dark-icon-color: $navbar-dark-color !default;
+$navbar-dark-toggler-icon-bg: url("data:image/svg+xml,
") !default;
+$navbar-dark-toggler-border-color: rgba($white, .1) !default;
+$navbar-dark-brand-color: $navbar-dark-active-color !default;
+$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;
+// scss-docs-end navbar-dark-variables
+
+
+// Dropdowns
+//
+// Dropdown menu container and contents.
+
+// scss-docs-start dropdown-variables
+$dropdown-min-width: 10rem !default;
+$dropdown-padding-x: 0 !default;
+$dropdown-padding-y: .5rem !default;
+$dropdown-spacer: .125rem !default;
+$dropdown-font-size: $font-size-base !default;
+$dropdown-color: var(--#{$prefix}body-color) !default;
+$dropdown-bg: var(--#{$prefix}body-bg) !default;
+$dropdown-border-color: var(--#{$prefix}border-color-translucent) !default;
+$dropdown-border-radius: var(--#{$prefix}border-radius) !default;
+$dropdown-border-width: var(--#{$prefix}border-width) !default;
+$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default; // stylelint-disable-line function-disallowed-list
+$dropdown-divider-bg: $dropdown-border-color !default;
+$dropdown-divider-margin-y: $spacer * .5 !default;
+$dropdown-box-shadow: var(--#{$prefix}box-shadow) !default;
+
+$dropdown-link-color: var(--#{$prefix}body-color) !default;
+$dropdown-link-hover-color: $dropdown-link-color !default;
+$dropdown-link-hover-bg: var(--#{$prefix}tertiary-bg) !default;
+
+$dropdown-link-active-color: $component-active-color !default;
+$dropdown-link-active-bg: $component-active-bg !default;
+
+$dropdown-link-disabled-color: var(--#{$prefix}tertiary-color) !default;
+
+$dropdown-item-padding-y: $spacer * .25 !default;
+$dropdown-item-padding-x: $spacer !default;
+
+$dropdown-header-color: $gray-600 !default;
+$dropdown-header-padding-x: $dropdown-item-padding-x !default;
+$dropdown-header-padding-y: $dropdown-padding-y !default;
+// fusv-disable
+$dropdown-header-padding: $dropdown-header-padding-y $dropdown-header-padding-x !default; // Deprecated in v5.2.0
+// fusv-enable
+// scss-docs-end dropdown-variables
+
+// scss-docs-start dropdown-dark-variables
+$dropdown-dark-color: $gray-300 !default;
+$dropdown-dark-bg: $gray-800 !default;
+$dropdown-dark-border-color: $dropdown-border-color !default;
+$dropdown-dark-divider-bg: $dropdown-divider-bg !default;
+$dropdown-dark-box-shadow: null !default;
+$dropdown-dark-link-color: $dropdown-dark-color !default;
+$dropdown-dark-link-hover-color: $white !default;
+$dropdown-dark-link-hover-bg: rgba($white, .15) !default;
+$dropdown-dark-link-active-color: $dropdown-link-active-color !default;
+$dropdown-dark-link-active-bg: $dropdown-link-active-bg !default;
+$dropdown-dark-link-disabled-color: $gray-500 !default;
+$dropdown-dark-header-color: $gray-500 !default;
+// scss-docs-end dropdown-dark-variables
+
+
+// Pagination
+
+// scss-docs-start pagination-variables
+$pagination-padding-y: .375rem !default;
+$pagination-padding-x: .75rem !default;
+$pagination-padding-y-sm: .25rem !default;
+$pagination-padding-x-sm: .5rem !default;
+$pagination-padding-y-lg: .75rem !default;
+$pagination-padding-x-lg: 1.5rem !default;
+
+$pagination-font-size: $font-size-base !default;
+
+$pagination-color: var(--#{$prefix}link-color) !default;
+$pagination-bg: var(--#{$prefix}body-bg) !default;
+$pagination-border-radius: var(--#{$prefix}border-radius) !default;
+$pagination-border-width: var(--#{$prefix}border-width) !default;
+$pagination-margin-start: calc(-1 * #{$pagination-border-width}) !default; // stylelint-disable-line function-disallowed-list
+$pagination-border-color: var(--#{$prefix}border-color) !default;
+
+$pagination-focus-color: var(--#{$prefix}link-hover-color) !default;
+$pagination-focus-bg: var(--#{$prefix}secondary-bg) !default;
+$pagination-focus-box-shadow: $focus-ring-box-shadow !default;
+$pagination-focus-outline: 0 !default;
+
+$pagination-hover-color: var(--#{$prefix}link-hover-color) !default;
+$pagination-hover-bg: var(--#{$prefix}tertiary-bg) !default;
+$pagination-hover-border-color: var(--#{$prefix}border-color) !default; // Todo in v6: remove this?
+
+$pagination-active-color: $component-active-color !default;
+$pagination-active-bg: $component-active-bg !default;
+$pagination-active-border-color: $component-active-bg !default;
+
+$pagination-disabled-color: var(--#{$prefix}secondary-color) !default;
+$pagination-disabled-bg: var(--#{$prefix}secondary-bg) !default;
+$pagination-disabled-border-color: var(--#{$prefix}border-color) !default;
+
+$pagination-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+
+$pagination-border-radius-sm: var(--#{$prefix}border-radius-sm) !default;
+$pagination-border-radius-lg: var(--#{$prefix}border-radius-lg) !default;
+// scss-docs-end pagination-variables
+
+
+// Placeholders
+
+// scss-docs-start placeholders
+$placeholder-opacity-max: .5 !default;
+$placeholder-opacity-min: .2 !default;
+// scss-docs-end placeholders
+
+// Cards
+
+// scss-docs-start card-variables
+$card-spacer-y: $spacer !default;
+$card-spacer-x: $spacer !default;
+$card-title-spacer-y: $spacer * .5 !default;
+$card-title-color: null !default;
+$card-subtitle-color: null !default;
+$card-border-width: var(--#{$prefix}border-width) !default;
+$card-border-color: var(--#{$prefix}border-color-translucent) !default;
+$card-border-radius: var(--#{$prefix}border-radius) !default;
+$card-box-shadow: null !default;
+$card-inner-border-radius: subtract($card-border-radius, $card-border-width) !default;
+$card-cap-padding-y: $card-spacer-y * .5 !default;
+$card-cap-padding-x: $card-spacer-x !default;
+$card-cap-bg: rgba(var(--#{$prefix}body-color-rgb), .03) !default;
+$card-cap-color: null !default;
+$card-height: null !default;
+$card-color: null !default;
+$card-bg: var(--#{$prefix}body-bg) !default;
+$card-img-overlay-padding: $spacer !default;
+$card-group-margin: $grid-gutter-width * .5 !default;
+// scss-docs-end card-variables
+
+// Accordion
+
+// scss-docs-start accordion-variables
+$accordion-padding-y: 1rem !default;
+$accordion-padding-x: 1.25rem !default;
+$accordion-color: var(--#{$prefix}body-color) !default;
+$accordion-bg: var(--#{$prefix}body-bg) !default;
+$accordion-border-width: var(--#{$prefix}border-width) !default;
+$accordion-border-color: var(--#{$prefix}border-color) !default;
+$accordion-border-radius: var(--#{$prefix}border-radius) !default;
+$accordion-inner-border-radius: subtract($accordion-border-radius, $accordion-border-width) !default;
+
+$accordion-body-padding-y: $accordion-padding-y !default;
+$accordion-body-padding-x: $accordion-padding-x !default;
+
+$accordion-button-padding-y: $accordion-padding-y !default;
+$accordion-button-padding-x: $accordion-padding-x !default;
+$accordion-button-color: var(--#{$prefix}body-color) !default;
+$accordion-button-bg: var(--#{$prefix}accordion-bg) !default;
+$accordion-transition: $btn-transition, border-radius .15s ease !default;
+$accordion-button-active-bg: var(--#{$prefix}primary-bg-subtle) !default;
+$accordion-button-active-color: var(--#{$prefix}primary-text-emphasis) !default;
+
+// fusv-disable
+$accordion-button-focus-border-color: $input-focus-border-color !default; // Deprecated in v5.3.3
+// fusv-enable
+$accordion-button-focus-box-shadow: $btn-focus-box-shadow !default;
+
+$accordion-icon-width: 1.25rem !default;
+$accordion-icon-color: $body-color !default;
+$accordion-icon-active-color: $primary-text-emphasis !default;
+$accordion-icon-transition: transform .2s ease-in-out !default;
+$accordion-icon-transform: rotate(-180deg) !default;
+
+$accordion-button-icon: url("data:image/svg+xml,
") !default;
+$accordion-button-active-icon: url("data:image/svg+xml,
") !default;
+// scss-docs-end accordion-variables
+
+// Tooltips
+
+// scss-docs-start tooltip-variables
+$tooltip-font-size: $font-size-sm !default;
+$tooltip-max-width: 200px !default;
+$tooltip-color: var(--#{$prefix}body-bg) !default;
+$tooltip-bg: var(--#{$prefix}emphasis-color) !default;
+$tooltip-border-radius: var(--#{$prefix}border-radius) !default;
+$tooltip-opacity: .9 !default;
+$tooltip-padding-y: $spacer * .25 !default;
+$tooltip-padding-x: $spacer * .5 !default;
+$tooltip-margin: null !default; // TODO: remove this in v6
+
+$tooltip-arrow-width: .8rem !default;
+$tooltip-arrow-height: .4rem !default;
+// fusv-disable
+$tooltip-arrow-color: null !default; // Deprecated in Bootstrap 5.2.0 for CSS variables
+// fusv-enable
+// scss-docs-end tooltip-variables
+
+// Form tooltips must come after regular tooltips
+// scss-docs-start tooltip-feedback-variables
+$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;
+$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;
+$form-feedback-tooltip-font-size: $tooltip-font-size !default;
+$form-feedback-tooltip-line-height: null !default;
+$form-feedback-tooltip-opacity: $tooltip-opacity !default;
+$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;
+// scss-docs-end tooltip-feedback-variables
+
+
+// Popovers
+
+// scss-docs-start popover-variables
+$popover-font-size: $font-size-sm !default;
+$popover-bg: var(--#{$prefix}body-bg) !default;
+$popover-max-width: 276px !default;
+$popover-border-width: var(--#{$prefix}border-width) !default;
+$popover-border-color: var(--#{$prefix}border-color-translucent) !default;
+$popover-border-radius: var(--#{$prefix}border-radius-lg) !default;
+$popover-inner-border-radius: calc(#{$popover-border-radius} - #{$popover-border-width}) !default; // stylelint-disable-line function-disallowed-list
+$popover-box-shadow: var(--#{$prefix}box-shadow) !default;
+
+$popover-header-font-size: $font-size-base !default;
+$popover-header-bg: var(--#{$prefix}secondary-bg) !default;
+$popover-header-color: $headings-color !default;
+$popover-header-padding-y: .5rem !default;
+$popover-header-padding-x: $spacer !default;
+
+$popover-body-color: var(--#{$prefix}body-color) !default;
+$popover-body-padding-y: $spacer !default;
+$popover-body-padding-x: $spacer !default;
+
+$popover-arrow-width: 1rem !default;
+$popover-arrow-height: .5rem !default;
+// scss-docs-end popover-variables
+
+// fusv-disable
+// Deprecated in Bootstrap 5.2.0 for CSS variables
+$popover-arrow-color: $popover-bg !default;
+$popover-arrow-outer-color: var(--#{$prefix}border-color-translucent) !default;
+// fusv-enable
+
+
+// Toasts
+
+// scss-docs-start toast-variables
+$toast-max-width: 350px !default;
+$toast-padding-x: .75rem !default;
+$toast-padding-y: .5rem !default;
+$toast-font-size: .875rem !default;
+$toast-color: null !default;
+$toast-background-color: rgba(var(--#{$prefix}body-bg-rgb), .85) !default;
+$toast-border-width: var(--#{$prefix}border-width) !default;
+$toast-border-color: var(--#{$prefix}border-color-translucent) !default;
+$toast-border-radius: var(--#{$prefix}border-radius) !default;
+$toast-box-shadow: var(--#{$prefix}box-shadow) !default;
+$toast-spacing: $container-padding-x !default;
+
+$toast-header-color: var(--#{$prefix}secondary-color) !default;
+$toast-header-background-color: rgba(var(--#{$prefix}body-bg-rgb), .85) !default;
+$toast-header-border-color: $toast-border-color !default;
+// scss-docs-end toast-variables
+
+
+// Badges
+
+// scss-docs-start badge-variables
+$badge-font-size: .75em !default;
+$badge-font-weight: $font-weight-bold !default;
+$badge-color: $white !default;
+$badge-padding-y: .35em !default;
+$badge-padding-x: .65em !default;
+$badge-border-radius: var(--#{$prefix}border-radius) !default;
+// scss-docs-end badge-variables
+
+
+// Modals
+
+// scss-docs-start modal-variables
+$modal-inner-padding: $spacer !default;
+
+$modal-footer-margin-between: .5rem !default;
+
+$modal-dialog-margin: .5rem !default;
+$modal-dialog-margin-y-sm-up: 1.75rem !default;
+
+$modal-title-line-height: $line-height-base !default;
+
+$modal-content-color: var(--#{$prefix}body-color) !default;
+$modal-content-bg: var(--#{$prefix}body-bg) !default;
+$modal-content-border-color: var(--#{$prefix}border-color-translucent) !default;
+$modal-content-border-width: var(--#{$prefix}border-width) !default;
+$modal-content-border-radius: var(--#{$prefix}border-radius-lg) !default;
+$modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width) !default;
+$modal-content-box-shadow-xs: var(--#{$prefix}box-shadow-sm) !default;
+$modal-content-box-shadow-sm-up: var(--#{$prefix}box-shadow) !default;
+
+$modal-backdrop-bg: $black !default;
+$modal-backdrop-opacity: .5 !default;
+
+$modal-header-border-color: var(--#{$prefix}border-color) !default;
+$modal-header-border-width: $modal-content-border-width !default;
+$modal-header-padding-y: $modal-inner-padding !default;
+$modal-header-padding-x: $modal-inner-padding !default;
+$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility
+
+$modal-footer-bg: null !default;
+$modal-footer-border-color: $modal-header-border-color !default;
+$modal-footer-border-width: $modal-header-border-width !default;
+
+$modal-sm: 300px !default;
+$modal-md: 500px !default;
+$modal-lg: 800px !default;
+$modal-xl: 1140px !default;
+
+$modal-fade-transform: translate(0, -50px) !default;
+$modal-show-transform: none !default;
+$modal-transition: transform .3s ease-out !default;
+$modal-scale-transform: scale(1.02) !default;
+// scss-docs-end modal-variables
+
+
+// Alerts
+//
+// Define alert colors, border radius, and padding.
+
+// scss-docs-start alert-variables
+$alert-padding-y: $spacer !default;
+$alert-padding-x: $spacer !default;
+$alert-margin-bottom: 1rem !default;
+$alert-border-radius: var(--#{$prefix}border-radius) !default;
+$alert-link-font-weight: $font-weight-bold !default;
+$alert-border-width: var(--#{$prefix}border-width) !default;
+$alert-dismissible-padding-r: $alert-padding-x * 3 !default; // 3x covers width of x plus default padding on either side
+// scss-docs-end alert-variables
+
+// fusv-disable
+$alert-bg-scale: -80% !default; // Deprecated in v5.2.0, to be removed in v6
+$alert-border-scale: -70% !default; // Deprecated in v5.2.0, to be removed in v6
+$alert-color-scale: 40% !default; // Deprecated in v5.2.0, to be removed in v6
+// fusv-enable
+
+// Progress bars
+
+// scss-docs-start progress-variables
+$progress-height: 1rem !default;
+$progress-font-size: $font-size-base * .75 !default;
+$progress-bg: var(--#{$prefix}secondary-bg) !default;
+$progress-border-radius: var(--#{$prefix}border-radius) !default;
+$progress-box-shadow: var(--#{$prefix}box-shadow-inset) !default;
+$progress-bar-color: $white !default;
+$progress-bar-bg: $primary !default;
+$progress-bar-animation-timing: 1s linear infinite !default;
+$progress-bar-transition: width .6s ease !default;
+// scss-docs-end progress-variables
+
+
+// List group
+
+// scss-docs-start list-group-variables
+$list-group-color: var(--#{$prefix}body-color) !default;
+$list-group-bg: var(--#{$prefix}body-bg) !default;
+$list-group-border-color: var(--#{$prefix}border-color) !default;
+$list-group-border-width: var(--#{$prefix}border-width) !default;
+$list-group-border-radius: var(--#{$prefix}border-radius) !default;
+
+$list-group-item-padding-y: $spacer * .5 !default;
+$list-group-item-padding-x: $spacer !default;
+// fusv-disable
+$list-group-item-bg-scale: -80% !default; // Deprecated in v5.3.0
+$list-group-item-color-scale: 40% !default; // Deprecated in v5.3.0
+// fusv-enable
+
+$list-group-hover-bg: var(--#{$prefix}tertiary-bg) !default;
+$list-group-active-color: $component-active-color !default;
+$list-group-active-bg: $component-active-bg !default;
+$list-group-active-border-color: $list-group-active-bg !default;
+
+$list-group-disabled-color: var(--#{$prefix}secondary-color) !default;
+$list-group-disabled-bg: $list-group-bg !default;
+
+$list-group-action-color: var(--#{$prefix}secondary-color) !default;
+$list-group-action-hover-color: var(--#{$prefix}emphasis-color) !default;
+
+$list-group-action-active-color: var(--#{$prefix}body-color) !default;
+$list-group-action-active-bg: var(--#{$prefix}secondary-bg) !default;
+// scss-docs-end list-group-variables
+
+
+// Image thumbnails
+
+// scss-docs-start thumbnail-variables
+$thumbnail-padding: .25rem !default;
+$thumbnail-bg: var(--#{$prefix}body-bg) !default;
+$thumbnail-border-width: var(--#{$prefix}border-width) !default;
+$thumbnail-border-color: var(--#{$prefix}border-color) !default;
+$thumbnail-border-radius: var(--#{$prefix}border-radius) !default;
+$thumbnail-box-shadow: var(--#{$prefix}box-shadow-sm) !default;
+// scss-docs-end thumbnail-variables
+
+
+// Figures
+
+// scss-docs-start figure-variables
+$figure-caption-font-size: $small-font-size !default;
+$figure-caption-color: var(--#{$prefix}secondary-color) !default;
+// scss-docs-end figure-variables
+
+
+// Breadcrumbs
+
+// scss-docs-start breadcrumb-variables
+$breadcrumb-font-size: null !default;
+$breadcrumb-padding-y: 0 !default;
+$breadcrumb-padding-x: 0 !default;
+$breadcrumb-item-padding-x: .5rem !default;
+$breadcrumb-margin-bottom: 1rem !default;
+$breadcrumb-bg: null !default;
+$breadcrumb-divider-color: var(--#{$prefix}secondary-color) !default;
+$breadcrumb-active-color: var(--#{$prefix}secondary-color) !default;
+$breadcrumb-divider: quote("/") !default;
+$breadcrumb-divider-flipped: $breadcrumb-divider !default;
+$breadcrumb-border-radius: null !default;
+// scss-docs-end breadcrumb-variables
+
+// Carousel
+
+// scss-docs-start carousel-variables
+$carousel-control-color: $white !default;
+$carousel-control-width: 15% !default;
+$carousel-control-opacity: .5 !default;
+$carousel-control-hover-opacity: .9 !default;
+$carousel-control-transition: opacity .15s ease !default;
+$carousel-control-icon-filter: null !default;
+
+$carousel-indicator-width: 30px !default;
+$carousel-indicator-height: 3px !default;
+$carousel-indicator-hit-area-height: 10px !default;
+$carousel-indicator-spacer: 3px !default;
+$carousel-indicator-opacity: .5 !default;
+$carousel-indicator-active-bg: $white !default;
+$carousel-indicator-active-opacity: 1 !default;
+$carousel-indicator-transition: opacity .6s ease !default;
+
+$carousel-caption-width: 70% !default;
+$carousel-caption-color: $white !default;
+$carousel-caption-padding-y: 1.25rem !default;
+$carousel-caption-spacer: 1.25rem !default;
+
+$carousel-control-icon-width: 2rem !default;
+
+$carousel-control-prev-icon-bg: url("data:image/svg+xml,
") !default;
+$carousel-control-next-icon-bg: url("data:image/svg+xml,
") !default;
+
+$carousel-transition-duration: .6s !default;
+$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)
+// scss-docs-end carousel-variables
+
+// scss-docs-start carousel-dark-variables
+$carousel-dark-indicator-active-bg: $black !default; // Deprecated in v5.3.4
+$carousel-dark-caption-color: $black !default; // Deprecated in v5.3.4
+$carousel-dark-control-icon-filter: invert(1) grayscale(100) !default; // Deprecated in v5.3.4
+// scss-docs-end carousel-dark-variables
+
+
+// Spinners
+
+// scss-docs-start spinner-variables
+$spinner-width: 2rem !default;
+$spinner-height: $spinner-width !default;
+$spinner-vertical-align: -.125em !default;
+$spinner-border-width: .25em !default;
+$spinner-animation-speed: .75s !default;
+
+$spinner-width-sm: 1rem !default;
+$spinner-height-sm: $spinner-width-sm !default;
+$spinner-border-width-sm: .2em !default;
+// scss-docs-end spinner-variables
+
+
+// Close
+
+// scss-docs-start close-variables
+$btn-close-width: 1em !default;
+$btn-close-height: $btn-close-width !default;
+$btn-close-padding-x: .25em !default;
+$btn-close-padding-y: $btn-close-padding-x !default;
+$btn-close-color: $black !default;
+$btn-close-bg: url("data:image/svg+xml,
") !default;
+$btn-close-focus-shadow: $focus-ring-box-shadow !default;
+$btn-close-opacity: .5 !default;
+$btn-close-hover-opacity: .75 !default;
+$btn-close-focus-opacity: 1 !default;
+$btn-close-disabled-opacity: .25 !default;
+$btn-close-filter: null !default;
+$btn-close-white-filter: invert(1) grayscale(100%) brightness(200%) !default; // Deprecated in v5.3.4
+// scss-docs-end close-variables
+
+
+// Offcanvas
+
+// scss-docs-start offcanvas-variables
+$offcanvas-padding-y: $modal-inner-padding !default;
+$offcanvas-padding-x: $modal-inner-padding !default;
+$offcanvas-horizontal-width: 400px !default;
+$offcanvas-vertical-height: 30vh !default;
+$offcanvas-transition-duration: .3s !default;
+$offcanvas-border-color: $modal-content-border-color !default;
+$offcanvas-border-width: $modal-content-border-width !default;
+$offcanvas-title-line-height: $modal-title-line-height !default;
+$offcanvas-bg-color: var(--#{$prefix}body-bg) !default;
+$offcanvas-color: var(--#{$prefix}body-color) !default;
+$offcanvas-box-shadow: $modal-content-box-shadow-xs !default;
+$offcanvas-backdrop-bg: $modal-backdrop-bg !default;
+$offcanvas-backdrop-opacity: $modal-backdrop-opacity !default;
+// scss-docs-end offcanvas-variables
+
+// Code
+
+$code-font-size: $small-font-size !default;
+$code-color: $pink !default;
+
+$kbd-padding-y: .1875rem !default;
+$kbd-padding-x: .375rem !default;
+$kbd-font-size: $code-font-size !default;
+$kbd-color: var(--#{$prefix}body-bg) !default;
+$kbd-bg: var(--#{$prefix}body-color) !default;
+$nested-kbd-font-weight: null !default; // Deprecated in v5.2.0, removing in v6
+
+$pre-color: null !default;
+
+@import "variables-dark"; // TODO: can be removed safely in v6, only here to avoid breaking changes in v5.3
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-grid.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-grid.scss
new file mode 100644
index 0000000..52bd577
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-grid.scss
@@ -0,0 +1,62 @@
+@import "mixins/banner";
+@include bsBanner(Grid);
+
+$include-column-box-sizing: true !default;
+
+@import "functions";
+@import "variables";
+@import "variables-dark";
+@import "maps";
+
+@import "mixins/breakpoints";
+@import "mixins/container";
+@import "mixins/grid";
+@import "mixins/utilities";
+
+@import "vendor/rfs";
+
+@import "containers";
+@import "grid";
+
+@import "utilities";
+// Only use the utilities we need
+// stylelint-disable-next-line scss/dollar-variable-default
+$utilities: map-get-multiple(
+ $utilities,
+ (
+ "display",
+ "order",
+ "flex",
+ "flex-direction",
+ "flex-grow",
+ "flex-shrink",
+ "flex-wrap",
+ "justify-content",
+ "align-items",
+ "align-content",
+ "align-self",
+ "margin",
+ "margin-x",
+ "margin-y",
+ "margin-top",
+ "margin-end",
+ "margin-bottom",
+ "margin-start",
+ "negative-margin",
+ "negative-margin-x",
+ "negative-margin-y",
+ "negative-margin-top",
+ "negative-margin-end",
+ "negative-margin-bottom",
+ "negative-margin-start",
+ "padding",
+ "padding-x",
+ "padding-y",
+ "padding-top",
+ "padding-end",
+ "padding-bottom",
+ "padding-start",
+ )
+);
+
+@import "utilities/api";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-reboot.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-reboot.scss
new file mode 100644
index 0000000..5b69b95
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-reboot.scss
@@ -0,0 +1,10 @@
+@import "mixins/banner";
+@include bsBanner(Reboot);
+
+@import "functions";
+@import "variables";
+@import "variables-dark";
+@import "maps";
+@import "mixins";
+@import "root";
+@import "reboot";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-utilities.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-utilities.scss
new file mode 100644
index 0000000..99c4a35
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap-utilities.scss
@@ -0,0 +1,19 @@
+@import "mixins/banner";
+@include bsBanner(Utilities);
+
+// Configuration
+@import "functions";
+@import "variables";
+@import "variables-dark";
+@import "maps";
+@import "mixins";
+@import "utilities";
+
+// Layout & components
+@import "root";
+
+// Helpers
+@import "helpers";
+
+// Utilities
+@import "utilities/api";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap.scss
new file mode 100644
index 0000000..97dc8ca
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/bootstrap.scss
@@ -0,0 +1,52 @@
+@import 'mixins/banner';
+@include bsBanner('');
+
+// scss-docs-start import-stack
+// Configuration
+@import 'functions';
+@import 'variables';
+@import 'variables-dark';
+@import 'maps';
+@import 'mixins';
+@import 'utilities';
+
+// Layout & components
+@import 'root';
+@import 'reboot';
+@import 'type';
+@import 'images';
+@import 'containers';
+@import 'grid';
+
+@import 'tables';
+@import 'forms';
+@import 'buttons';
+@import 'transitions';
+@import 'dropdown';
+@import 'button-group';
+@import 'nav';
+@import 'navbar';
+@import 'card';
+@import 'accordion';
+@import 'breadcrumb';
+@import 'pagination';
+@import 'badge';
+@import 'alert';
+@import 'progress';
+@import 'list-group';
+@import 'close';
+@import 'toasts';
+@import 'modal';
+@import 'tooltip';
+@import 'popover';
+@import 'carousel';
+@import 'spinners';
+@import 'offcanvas';
+@import 'placeholders';
+
+// Helpers
+@import 'helpers';
+
+// Utilities
+@import 'utilities/api';
+// scss-docs-end import-stack
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_floating-labels.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_floating-labels.scss
new file mode 100644
index 0000000..38df115
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_floating-labels.scss
@@ -0,0 +1,97 @@
+.form-floating {
+ position: relative;
+
+ > .form-control,
+ > .form-control-plaintext,
+ > .form-select {
+ height: $form-floating-height;
+ min-height: $form-floating-height;
+ line-height: $form-floating-line-height;
+ }
+
+ > label {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 2;
+ max-width: 100%;
+ height: 100%; // allow textareas
+ padding: $form-floating-padding-y $form-floating-padding-x;
+ overflow: hidden;
+ color: rgba(var(--#{$prefix}body-color-rgb), #{$form-floating-label-opacity});
+ text-align: start;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ pointer-events: none;
+ border: $input-border-width solid transparent; // Required for aligning label's text with the input as it affects inner box model
+ transform-origin: 0 0;
+ @include transition($form-floating-transition);
+ }
+
+ > .form-control,
+ > .form-control-plaintext {
+ padding: $form-floating-padding-y $form-floating-padding-x;
+
+ &::placeholder {
+ color: transparent;
+ }
+
+ &:focus,
+ &:not(:placeholder-shown) {
+ padding-top: $form-floating-input-padding-t;
+ padding-bottom: $form-floating-input-padding-b;
+ }
+ // Duplicated because `:-webkit-autofill` invalidates other selectors when grouped
+ &:-webkit-autofill {
+ padding-top: $form-floating-input-padding-t;
+ padding-bottom: $form-floating-input-padding-b;
+ }
+ }
+
+ > .form-select {
+ padding-top: $form-floating-input-padding-t;
+ padding-bottom: $form-floating-input-padding-b;
+ padding-left: $form-floating-padding-x;
+ }
+
+ > .form-control:focus,
+ > .form-control:not(:placeholder-shown),
+ > .form-control-plaintext,
+ > .form-select {
+ ~ label {
+ transform: $form-floating-label-transform;
+ }
+ }
+ // Duplicated because `:-webkit-autofill` invalidates other selectors when grouped
+ > .form-control:-webkit-autofill {
+ ~ label {
+ transform: $form-floating-label-transform;
+ }
+ }
+ > textarea:focus,
+ > textarea:not(:placeholder-shown) {
+ ~ label::after {
+ position: absolute;
+ inset: $form-floating-padding-y ($form-floating-padding-x * .5);
+ z-index: -1;
+ height: $form-floating-label-height;
+ content: "";
+ background-color: $input-bg;
+ @include border-radius($input-border-radius);
+ }
+ }
+ > textarea:disabled ~ label::after {
+ background-color: $input-disabled-bg;
+ }
+
+ > .form-control-plaintext {
+ ~ label {
+ border-width: $input-border-width 0; // Required to properly position label text - as explained above
+ }
+ }
+
+ > :disabled ~ label,
+ > .form-control:disabled ~ label { // Required for `.form-control`s because of specificity
+ color: $form-floating-label-disabled-color;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-check.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-check.scss
new file mode 100644
index 0000000..8a1b639
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-check.scss
@@ -0,0 +1,189 @@
+//
+// Check/radio
+//
+
+.form-check {
+ display: block;
+ min-height: $form-check-min-height;
+ padding-left: $form-check-padding-start;
+ margin-bottom: $form-check-margin-bottom;
+
+ .form-check-input {
+ float: left;
+ margin-left: $form-check-padding-start * -1;
+ }
+}
+
+.form-check-reverse {
+ padding-right: $form-check-padding-start;
+ padding-left: 0;
+ text-align: right;
+
+ .form-check-input {
+ float: right;
+ margin-right: $form-check-padding-start * -1;
+ margin-left: 0;
+ }
+}
+
+.form-check-input {
+ --#{$prefix}form-check-bg: #{$form-check-input-bg};
+
+ flex-shrink: 0;
+ width: $form-check-input-width;
+ height: $form-check-input-width;
+ margin-top: ($line-height-base - $form-check-input-width) * .5; // line-height minus check height
+ vertical-align: top;
+ appearance: none;
+ background-color: var(--#{$prefix}form-check-bg);
+ background-image: var(--#{$prefix}form-check-bg-image);
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: contain;
+ border: $form-check-input-border;
+ print-color-adjust: exact; // Keep themed appearance for print
+ @include transition($form-check-transition);
+
+ &[type="checkbox"] {
+ @include border-radius($form-check-input-border-radius);
+ }
+
+ &[type="radio"] {
+ // stylelint-disable-next-line property-disallowed-list
+ border-radius: $form-check-radio-border-radius;
+ }
+
+ &:active {
+ filter: $form-check-input-active-filter;
+ }
+
+ &:focus {
+ border-color: $form-check-input-focus-border;
+ outline: 0;
+ box-shadow: $form-check-input-focus-box-shadow;
+ }
+
+ &:checked {
+ background-color: $form-check-input-checked-bg-color;
+ border-color: $form-check-input-checked-border-color;
+
+ &[type="checkbox"] {
+ @if $enable-gradients {
+ --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-checked-bg-image)}, var(--#{$prefix}gradient);
+ } @else {
+ --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-checked-bg-image)};
+ }
+ }
+
+ &[type="radio"] {
+ @if $enable-gradients {
+ --#{$prefix}form-check-bg-image: #{escape-svg($form-check-radio-checked-bg-image)}, var(--#{$prefix}gradient);
+ } @else {
+ --#{$prefix}form-check-bg-image: #{escape-svg($form-check-radio-checked-bg-image)};
+ }
+ }
+ }
+
+ &[type="checkbox"]:indeterminate {
+ background-color: $form-check-input-indeterminate-bg-color;
+ border-color: $form-check-input-indeterminate-border-color;
+
+ @if $enable-gradients {
+ --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-indeterminate-bg-image)}, var(--#{$prefix}gradient);
+ } @else {
+ --#{$prefix}form-check-bg-image: #{escape-svg($form-check-input-indeterminate-bg-image)};
+ }
+ }
+
+ &:disabled {
+ pointer-events: none;
+ filter: none;
+ opacity: $form-check-input-disabled-opacity;
+ }
+
+ // Use disabled attribute in addition of :disabled pseudo-class
+ // See: https://github.com/twbs/bootstrap/issues/28247
+ &[disabled],
+ &:disabled {
+ ~ .form-check-label {
+ cursor: default;
+ opacity: $form-check-label-disabled-opacity;
+ }
+ }
+}
+
+.form-check-label {
+ color: $form-check-label-color;
+ cursor: $form-check-label-cursor;
+}
+
+//
+// Switch
+//
+
+.form-switch {
+ padding-left: $form-switch-padding-start;
+
+ .form-check-input {
+ --#{$prefix}form-switch-bg: #{escape-svg($form-switch-bg-image)};
+
+ width: $form-switch-width;
+ margin-left: $form-switch-padding-start * -1;
+ background-image: var(--#{$prefix}form-switch-bg);
+ background-position: left center;
+ @include border-radius($form-switch-border-radius, 0);
+ @include transition($form-switch-transition);
+
+ &:focus {
+ --#{$prefix}form-switch-bg: #{escape-svg($form-switch-focus-bg-image)};
+ }
+
+ &:checked {
+ background-position: $form-switch-checked-bg-position;
+
+ @if $enable-gradients {
+ --#{$prefix}form-switch-bg: #{escape-svg($form-switch-checked-bg-image)}, var(--#{$prefix}gradient);
+ } @else {
+ --#{$prefix}form-switch-bg: #{escape-svg($form-switch-checked-bg-image)};
+ }
+ }
+ }
+
+ &.form-check-reverse {
+ padding-right: $form-switch-padding-start;
+ padding-left: 0;
+
+ .form-check-input {
+ margin-right: $form-switch-padding-start * -1;
+ margin-left: 0;
+ }
+ }
+}
+
+.form-check-inline {
+ display: inline-block;
+ margin-right: $form-check-inline-margin-end;
+}
+
+.btn-check {
+ position: absolute;
+ clip: rect(0, 0, 0, 0);
+ pointer-events: none;
+
+ &[disabled],
+ &:disabled {
+ + .btn {
+ pointer-events: none;
+ filter: none;
+ opacity: $form-check-btn-check-disabled-opacity;
+ }
+ }
+}
+
+@if $enable-dark-mode {
+ @include color-mode(dark) {
+ .form-switch .form-check-input:not(:checked):not(:focus) {
+ --#{$prefix}form-switch-bg: #{escape-svg($form-switch-bg-image-dark)};
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-control.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-control.scss
new file mode 100644
index 0000000..67ae5f4
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-control.scss
@@ -0,0 +1,214 @@
+//
+// General form controls (plus a few specific high-level interventions)
+//
+
+.form-control {
+ display: block;
+ width: 100%;
+ padding: $input-padding-y $input-padding-x;
+ font-family: $input-font-family;
+ @include font-size($input-font-size);
+ font-weight: $input-font-weight;
+ line-height: $input-line-height;
+ color: $input-color;
+ appearance: none; // Fix appearance for date inputs in Safari
+ background-color: $input-bg;
+ background-clip: padding-box;
+ border: $input-border-width solid $input-border-color;
+
+ // Note: This has no effect on
s in some browsers, due to the limited stylability of ``s in CSS.
+ @include border-radius($input-border-radius, 0);
+
+ @include box-shadow($input-box-shadow);
+ @include transition($input-transition);
+
+ &[type="file"] {
+ overflow: hidden; // prevent pseudo element button overlap
+
+ &:not(:disabled):not([readonly]) {
+ cursor: pointer;
+ }
+ }
+
+ // Customize the `:focus` state to imitate native WebKit styles.
+ &:focus {
+ color: $input-focus-color;
+ background-color: $input-focus-bg;
+ border-color: $input-focus-border-color;
+ outline: 0;
+ @if $enable-shadows {
+ @include box-shadow($input-box-shadow, $input-focus-box-shadow);
+ } @else {
+ // Avoid using mixin so we can pass custom focus shadow properly
+ box-shadow: $input-focus-box-shadow;
+ }
+ }
+
+ &::-webkit-date-and-time-value {
+ // On Android Chrome, form-control's "width: 100%" makes the input width too small
+ // Tested under Android 11 / Chrome 89, Android 12 / Chrome 100, Android 13 / Chrome 109
+ //
+ // On iOS Safari, form-control's "appearance: none" + "width: 100%" makes the input width too small
+ // Tested under iOS 16.2 / Safari 16.2
+ min-width: 85px; // Seems to be a good minimum safe width
+
+ // Add some height to date inputs on iOS
+ // https://github.com/twbs/bootstrap/issues/23307
+ // TODO: we can remove this workaround once https://bugs.webkit.org/show_bug.cgi?id=198959 is resolved
+ // Multiply line-height by 1em if it has no unit
+ height: if(unit($input-line-height) == "", $input-line-height * 1em, $input-line-height);
+
+ // Android Chrome type="date" is taller than the other inputs
+ // because of "margin: 1px 24px 1px 4px" inside the shadow DOM
+ // Tested under Android 11 / Chrome 89, Android 12 / Chrome 100, Android 13 / Chrome 109
+ margin: 0;
+ }
+
+ // Prevent excessive date input height in Webkit
+ // https://github.com/twbs/bootstrap/issues/34433
+ &::-webkit-datetime-edit {
+ display: block;
+ padding: 0;
+ }
+
+ // Placeholder
+ &::placeholder {
+ color: $input-placeholder-color;
+ // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.
+ opacity: 1;
+ }
+
+ // Disabled inputs
+ //
+ // HTML5 says that controls under a fieldset > legend:first-child won't be
+ // disabled if the fieldset is disabled. Due to implementation difficulty, we
+ // don't honor that edge case; we style them as disabled anyway.
+ &:disabled {
+ color: $input-disabled-color;
+ background-color: $input-disabled-bg;
+ border-color: $input-disabled-border-color;
+ // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.
+ opacity: 1;
+ }
+
+ // File input buttons theming
+ &::file-selector-button {
+ padding: $input-padding-y $input-padding-x;
+ margin: (-$input-padding-y) (-$input-padding-x);
+ margin-inline-end: $input-padding-x;
+ color: $form-file-button-color;
+ @include gradient-bg($form-file-button-bg);
+ pointer-events: none;
+ border-color: inherit;
+ border-style: solid;
+ border-width: 0;
+ border-inline-end-width: $input-border-width;
+ border-radius: 0; // stylelint-disable-line property-disallowed-list
+ @include transition($btn-transition);
+ }
+
+ &:hover:not(:disabled):not([readonly])::file-selector-button {
+ background-color: $form-file-button-hover-bg;
+ }
+}
+
+// Readonly controls as plain text
+//
+// Apply class to a readonly input to make it appear like regular plain
+// text (without any border, background color, focus indicator)
+
+.form-control-plaintext {
+ display: block;
+ width: 100%;
+ padding: $input-padding-y 0;
+ margin-bottom: 0; // match inputs if this class comes on inputs with default margins
+ line-height: $input-line-height;
+ color: $input-plaintext-color;
+ background-color: transparent;
+ border: solid transparent;
+ border-width: $input-border-width 0;
+
+ &:focus {
+ outline: 0;
+ }
+
+ &.form-control-sm,
+ &.form-control-lg {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+
+// Form control sizing
+//
+// Build on `.form-control` with modifier classes to decrease or increase the
+// height and font-size of form controls.
+//
+// Repeated in `_input_group.scss` to avoid Sass extend issues.
+
+.form-control-sm {
+ min-height: $input-height-sm;
+ padding: $input-padding-y-sm $input-padding-x-sm;
+ @include font-size($input-font-size-sm);
+ @include border-radius($input-border-radius-sm);
+
+ &::file-selector-button {
+ padding: $input-padding-y-sm $input-padding-x-sm;
+ margin: (-$input-padding-y-sm) (-$input-padding-x-sm);
+ margin-inline-end: $input-padding-x-sm;
+ }
+}
+
+.form-control-lg {
+ min-height: $input-height-lg;
+ padding: $input-padding-y-lg $input-padding-x-lg;
+ @include font-size($input-font-size-lg);
+ @include border-radius($input-border-radius-lg);
+
+ &::file-selector-button {
+ padding: $input-padding-y-lg $input-padding-x-lg;
+ margin: (-$input-padding-y-lg) (-$input-padding-x-lg);
+ margin-inline-end: $input-padding-x-lg;
+ }
+}
+
+// Make sure textareas don't shrink too much when resized
+// https://github.com/twbs/bootstrap/pull/29124
+// stylelint-disable selector-no-qualifying-type
+textarea {
+ &.form-control {
+ min-height: $input-height;
+ }
+
+ &.form-control-sm {
+ min-height: $input-height-sm;
+ }
+
+ &.form-control-lg {
+ min-height: $input-height-lg;
+ }
+}
+// stylelint-enable selector-no-qualifying-type
+
+.form-control-color {
+ width: $form-color-width;
+ height: $input-height;
+ padding: $input-padding-y;
+
+ &:not(:disabled):not([readonly]) {
+ cursor: pointer;
+ }
+
+ &::-moz-color-swatch {
+ border: 0 !important; // stylelint-disable-line declaration-no-important
+ @include border-radius($input-border-radius);
+ }
+
+ &::-webkit-color-swatch {
+ border: 0 !important; // stylelint-disable-line declaration-no-important
+ @include border-radius($input-border-radius);
+ }
+
+ &.form-control-sm { height: $input-height-sm; }
+ &.form-control-lg { height: $input-height-lg; }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-range.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-range.scss
new file mode 100644
index 0000000..4732213
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-range.scss
@@ -0,0 +1,91 @@
+// Range
+//
+// Style range inputs the same across browsers. Vendor-specific rules for pseudo
+// elements cannot be mixed. As such, there are no shared styles for focus or
+// active states on prefixed selectors.
+
+.form-range {
+ width: 100%;
+ height: add($form-range-thumb-height, $form-range-thumb-focus-box-shadow-width * 2);
+ padding: 0; // Need to reset padding
+ appearance: none;
+ background-color: transparent;
+
+ &:focus {
+ outline: 0;
+
+ // Pseudo-elements must be split across multiple rulesets to have an effect.
+ // No box-shadow() mixin for focus accessibility.
+ &::-webkit-slider-thumb { box-shadow: $form-range-thumb-focus-box-shadow; }
+ &::-moz-range-thumb { box-shadow: $form-range-thumb-focus-box-shadow; }
+ }
+
+ &::-moz-focus-outer {
+ border: 0;
+ }
+
+ &::-webkit-slider-thumb {
+ width: $form-range-thumb-width;
+ height: $form-range-thumb-height;
+ margin-top: ($form-range-track-height - $form-range-thumb-height) * .5; // Webkit specific
+ appearance: none;
+ @include gradient-bg($form-range-thumb-bg);
+ border: $form-range-thumb-border;
+ @include border-radius($form-range-thumb-border-radius);
+ @include box-shadow($form-range-thumb-box-shadow);
+ @include transition($form-range-thumb-transition);
+
+ &:active {
+ @include gradient-bg($form-range-thumb-active-bg);
+ }
+ }
+
+ &::-webkit-slider-runnable-track {
+ width: $form-range-track-width;
+ height: $form-range-track-height;
+ color: transparent; // Why?
+ cursor: $form-range-track-cursor;
+ background-color: $form-range-track-bg;
+ border-color: transparent;
+ @include border-radius($form-range-track-border-radius);
+ @include box-shadow($form-range-track-box-shadow);
+ }
+
+ &::-moz-range-thumb {
+ width: $form-range-thumb-width;
+ height: $form-range-thumb-height;
+ appearance: none;
+ @include gradient-bg($form-range-thumb-bg);
+ border: $form-range-thumb-border;
+ @include border-radius($form-range-thumb-border-radius);
+ @include box-shadow($form-range-thumb-box-shadow);
+ @include transition($form-range-thumb-transition);
+
+ &:active {
+ @include gradient-bg($form-range-thumb-active-bg);
+ }
+ }
+
+ &::-moz-range-track {
+ width: $form-range-track-width;
+ height: $form-range-track-height;
+ color: transparent;
+ cursor: $form-range-track-cursor;
+ background-color: $form-range-track-bg;
+ border-color: transparent; // Firefox specific?
+ @include border-radius($form-range-track-border-radius);
+ @include box-shadow($form-range-track-box-shadow);
+ }
+
+ &:disabled {
+ pointer-events: none;
+
+ &::-webkit-slider-thumb {
+ background-color: $form-range-thumb-disabled-bg;
+ }
+
+ &::-moz-range-thumb {
+ background-color: $form-range-thumb-disabled-bg;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-select.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-select.scss
new file mode 100644
index 0000000..69ace52
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-select.scss
@@ -0,0 +1,80 @@
+// Select
+//
+// Replaces the browser default select with a custom one, mostly pulled from
+// https://primer.github.io/.
+
+.form-select {
+ --#{$prefix}form-select-bg-img: #{escape-svg($form-select-indicator)};
+
+ display: block;
+ width: 100%;
+ padding: $form-select-padding-y $form-select-indicator-padding $form-select-padding-y $form-select-padding-x;
+ font-family: $form-select-font-family;
+ @include font-size($form-select-font-size);
+ font-weight: $form-select-font-weight;
+ line-height: $form-select-line-height;
+ color: $form-select-color;
+ appearance: none;
+ background-color: $form-select-bg;
+ background-image: var(--#{$prefix}form-select-bg-img), var(--#{$prefix}form-select-bg-icon, none);
+ background-repeat: no-repeat;
+ background-position: $form-select-bg-position;
+ background-size: $form-select-bg-size;
+ border: $form-select-border-width solid $form-select-border-color;
+ @include border-radius($form-select-border-radius, 0);
+ @include box-shadow($form-select-box-shadow);
+ @include transition($form-select-transition);
+
+ &:focus {
+ border-color: $form-select-focus-border-color;
+ outline: 0;
+ @if $enable-shadows {
+ @include box-shadow($form-select-box-shadow, $form-select-focus-box-shadow);
+ } @else {
+ // Avoid using mixin so we can pass custom focus shadow properly
+ box-shadow: $form-select-focus-box-shadow;
+ }
+ }
+
+ &[multiple],
+ &[size]:not([size="1"]) {
+ padding-right: $form-select-padding-x;
+ background-image: none;
+ }
+
+ &:disabled {
+ color: $form-select-disabled-color;
+ background-color: $form-select-disabled-bg;
+ border-color: $form-select-disabled-border-color;
+ }
+
+ // Remove outline from select box in FF
+ &:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 $form-select-color;
+ }
+}
+
+.form-select-sm {
+ padding-top: $form-select-padding-y-sm;
+ padding-bottom: $form-select-padding-y-sm;
+ padding-left: $form-select-padding-x-sm;
+ @include font-size($form-select-font-size-sm);
+ @include border-radius($form-select-border-radius-sm);
+}
+
+.form-select-lg {
+ padding-top: $form-select-padding-y-lg;
+ padding-bottom: $form-select-padding-y-lg;
+ padding-left: $form-select-padding-x-lg;
+ @include font-size($form-select-font-size-lg);
+ @include border-radius($form-select-border-radius-lg);
+}
+
+@if $enable-dark-mode {
+ @include color-mode(dark) {
+ .form-select {
+ --#{$prefix}form-select-bg-img: #{escape-svg($form-select-indicator-dark)};
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-text.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-text.scss
new file mode 100644
index 0000000..f080d1a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_form-text.scss
@@ -0,0 +1,11 @@
+//
+// Form text
+//
+
+.form-text {
+ margin-top: $form-text-margin-top;
+ @include font-size($form-text-font-size);
+ font-style: $form-text-font-style;
+ font-weight: $form-text-font-weight;
+ color: $form-text-color;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_input-group.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_input-group.scss
new file mode 100644
index 0000000..8078ebb
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_input-group.scss
@@ -0,0 +1,132 @@
+//
+// Base styles
+//
+
+.input-group {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap; // For form validation feedback
+ align-items: stretch;
+ width: 100%;
+
+ > .form-control,
+ > .form-select,
+ > .form-floating {
+ position: relative; // For focus state's z-index
+ flex: 1 1 auto;
+ width: 1%;
+ min-width: 0; // https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size
+ }
+
+ // Bring the "active" form control to the top of surrounding elements
+ > .form-control:focus,
+ > .form-select:focus,
+ > .form-floating:focus-within {
+ z-index: 5;
+ }
+
+ // Ensure buttons are always above inputs for more visually pleasing borders.
+ // This isn't needed for `.input-group-text` since it shares the same border-color
+ // as our inputs.
+ .btn {
+ position: relative;
+ z-index: 2;
+
+ &:focus {
+ z-index: 5;
+ }
+ }
+}
+
+
+// Textual addons
+//
+// Serves as a catch-all element for any text or radio/checkbox input you wish
+// to prepend or append to an input.
+
+.input-group-text {
+ display: flex;
+ align-items: center;
+ padding: $input-group-addon-padding-y $input-group-addon-padding-x;
+ @include font-size($input-font-size); // Match inputs
+ font-weight: $input-group-addon-font-weight;
+ line-height: $input-line-height;
+ color: $input-group-addon-color;
+ text-align: center;
+ white-space: nowrap;
+ background-color: $input-group-addon-bg;
+ border: $input-border-width solid $input-group-addon-border-color;
+ @include border-radius($input-border-radius);
+}
+
+
+// Sizing
+//
+// Remix the default form control sizing classes into new ones for easier
+// manipulation.
+
+.input-group-lg > .form-control,
+.input-group-lg > .form-select,
+.input-group-lg > .input-group-text,
+.input-group-lg > .btn {
+ padding: $input-padding-y-lg $input-padding-x-lg;
+ @include font-size($input-font-size-lg);
+ @include border-radius($input-border-radius-lg);
+}
+
+.input-group-sm > .form-control,
+.input-group-sm > .form-select,
+.input-group-sm > .input-group-text,
+.input-group-sm > .btn {
+ padding: $input-padding-y-sm $input-padding-x-sm;
+ @include font-size($input-font-size-sm);
+ @include border-radius($input-border-radius-sm);
+}
+
+.input-group-lg > .form-select,
+.input-group-sm > .form-select {
+ padding-right: $form-select-padding-x + $form-select-indicator-padding;
+}
+
+
+// Rounded corners
+//
+// These rulesets must come after the sizing ones to properly override sm and lg
+// border-radius values when extending. They're more specific than we'd like
+// with the `.input-group >` part, but without it, we cannot override the sizing.
+
+// stylelint-disable-next-line no-duplicate-selectors
+.input-group {
+ &:not(.has-validation) {
+ > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),
+ > .dropdown-toggle:nth-last-child(n + 3),
+ > .form-floating:not(:last-child) > .form-control,
+ > .form-floating:not(:last-child) > .form-select {
+ @include border-end-radius(0);
+ }
+ }
+
+ &.has-validation {
+ > :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),
+ > .dropdown-toggle:nth-last-child(n + 4),
+ > .form-floating:nth-last-child(n + 3) > .form-control,
+ > .form-floating:nth-last-child(n + 3) > .form-select {
+ @include border-end-radius(0);
+ }
+ }
+
+ $validation-messages: "";
+ @each $state in map-keys($form-validation-states) {
+ $validation-messages: $validation-messages + ":not(." + unquote($state) + "-tooltip)" + ":not(." + unquote($state) + "-feedback)";
+ }
+
+ > :not(:first-child):not(.dropdown-menu)#{$validation-messages} {
+ margin-left: calc(-1 * #{$input-border-width}); // stylelint-disable-line function-disallowed-list
+ @include border-start-radius(0);
+ }
+
+ > .form-floating:not(:first-child) > .form-control,
+ > .form-floating:not(:first-child) > .form-select {
+ @include border-start-radius(0);
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_labels.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_labels.scss
new file mode 100644
index 0000000..39ecafc
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_labels.scss
@@ -0,0 +1,36 @@
+//
+// Labels
+//
+
+.form-label {
+ margin-bottom: $form-label-margin-bottom;
+ @include font-size($form-label-font-size);
+ font-style: $form-label-font-style;
+ font-weight: $form-label-font-weight;
+ color: $form-label-color;
+}
+
+// For use with horizontal and inline forms, when you need the label (or legend)
+// text to align with the form controls.
+.col-form-label {
+ padding-top: add($input-padding-y, $input-border-width);
+ padding-bottom: add($input-padding-y, $input-border-width);
+ margin-bottom: 0; // Override the `` default
+ @include font-size(inherit); // Override the `` default
+ font-style: $form-label-font-style;
+ font-weight: $form-label-font-weight;
+ line-height: $input-line-height;
+ color: $form-label-color;
+}
+
+.col-form-label-lg {
+ padding-top: add($input-padding-y-lg, $input-border-width);
+ padding-bottom: add($input-padding-y-lg, $input-border-width);
+ @include font-size($input-font-size-lg);
+}
+
+.col-form-label-sm {
+ padding-top: add($input-padding-y-sm, $input-border-width);
+ padding-bottom: add($input-padding-y-sm, $input-border-width);
+ @include font-size($input-font-size-sm);
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_validation.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_validation.scss
new file mode 100644
index 0000000..c48123a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/forms/_validation.scss
@@ -0,0 +1,12 @@
+// Form validation
+//
+// Provide feedback to users when form field values are valid or invalid. Works
+// primarily for client-side validation via scoped `:invalid` and `:valid`
+// pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for
+// server-side validation.
+
+// scss-docs-start form-validation-states-loop
+@each $state, $data in $form-validation-states {
+ @include form-validation-state($state, $data...);
+}
+// scss-docs-end form-validation-states-loop
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_clearfix.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_clearfix.scss
new file mode 100644
index 0000000..e92522a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_clearfix.scss
@@ -0,0 +1,3 @@
+.clearfix {
+ @include clearfix();
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_color-bg.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_color-bg.scss
new file mode 100644
index 0000000..1a3a4cf
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_color-bg.scss
@@ -0,0 +1,7 @@
+// All-caps `RGBA()` function used because of this Sass bug: https://github.com/sass/node-sass/issues/2251
+@each $color, $value in $theme-colors {
+ .text-bg-#{$color} {
+ color: color-contrast($value) if($enable-important-utilities, !important, null);
+ background-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}bg-opacity, 1)) if($enable-important-utilities, !important, null);
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_colored-links.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_colored-links.scss
new file mode 100644
index 0000000..5f86857
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_colored-links.scss
@@ -0,0 +1,30 @@
+// All-caps `RGBA()` function used because of this Sass bug: https://github.com/sass/node-sass/issues/2251
+@each $color, $value in $theme-colors {
+ .link-#{$color} {
+ color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}link-opacity, 1)) if($enable-important-utilities, !important, null);
+ text-decoration-color: RGBA(var(--#{$prefix}#{$color}-rgb), var(--#{$prefix}link-underline-opacity, 1)) if($enable-important-utilities, !important, null);
+
+ @if $link-shade-percentage != 0 {
+ &:hover,
+ &:focus {
+ $hover-color: if(color-contrast($value) == $color-contrast-light, shade-color($value, $link-shade-percentage), tint-color($value, $link-shade-percentage));
+ color: RGBA(#{to-rgb($hover-color)}, var(--#{$prefix}link-opacity, 1)) if($enable-important-utilities, !important, null);
+ text-decoration-color: RGBA(to-rgb($hover-color), var(--#{$prefix}link-underline-opacity, 1)) if($enable-important-utilities, !important, null);
+ }
+ }
+ }
+}
+
+// One-off special link helper as a bridge until v6
+.link-body-emphasis {
+ color: RGBA(var(--#{$prefix}emphasis-color-rgb), var(--#{$prefix}link-opacity, 1)) if($enable-important-utilities, !important, null);
+ text-decoration-color: RGBA(var(--#{$prefix}emphasis-color-rgb), var(--#{$prefix}link-underline-opacity, 1)) if($enable-important-utilities, !important, null);
+
+ @if $link-shade-percentage != 0 {
+ &:hover,
+ &:focus {
+ color: RGBA(var(--#{$prefix}emphasis-color-rgb), var(--#{$prefix}link-opacity, .75)) if($enable-important-utilities, !important, null);
+ text-decoration-color: RGBA(var(--#{$prefix}emphasis-color-rgb), var(--#{$prefix}link-underline-opacity, .75)) if($enable-important-utilities, !important, null);
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_focus-ring.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_focus-ring.scss
new file mode 100644
index 0000000..26508a8
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_focus-ring.scss
@@ -0,0 +1,5 @@
+.focus-ring:focus {
+ outline: 0;
+ // By default, there is no `--bs-focus-ring-x`, `--bs-focus-ring-y`, or `--bs-focus-ring-blur`, but we provide CSS variables with fallbacks to initial `0` values
+ box-shadow: var(--#{$prefix}focus-ring-x, 0) var(--#{$prefix}focus-ring-y, 0) var(--#{$prefix}focus-ring-blur, 0) var(--#{$prefix}focus-ring-width) var(--#{$prefix}focus-ring-color);
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_icon-link.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_icon-link.scss
new file mode 100644
index 0000000..3f8bcb3
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_icon-link.scss
@@ -0,0 +1,25 @@
+.icon-link {
+ display: inline-flex;
+ gap: $icon-link-gap;
+ align-items: center;
+ text-decoration-color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, .5));
+ text-underline-offset: $icon-link-underline-offset;
+ backface-visibility: hidden;
+
+ > .bi {
+ flex-shrink: 0;
+ width: $icon-link-icon-size;
+ height: $icon-link-icon-size;
+ fill: currentcolor;
+ @include transition($icon-link-icon-transition);
+ }
+}
+
+.icon-link-hover {
+ &:hover,
+ &:focus-visible {
+ > .bi {
+ transform: var(--#{$prefix}icon-link-transform, $icon-link-icon-transform);
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_position.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_position.scss
new file mode 100644
index 0000000..59103d9
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_position.scss
@@ -0,0 +1,36 @@
+// Shorthand
+
+.fixed-top {
+ position: fixed;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: $zindex-fixed;
+}
+
+.fixed-bottom {
+ position: fixed;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: $zindex-fixed;
+}
+
+// Responsive sticky top and bottom
+@each $breakpoint in map-keys($grid-breakpoints) {
+ @include media-breakpoint-up($breakpoint) {
+ $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+
+ .sticky#{$infix}-top {
+ position: sticky;
+ top: 0;
+ z-index: $zindex-sticky;
+ }
+
+ .sticky#{$infix}-bottom {
+ position: sticky;
+ bottom: 0;
+ z-index: $zindex-sticky;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_ratio.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_ratio.scss
new file mode 100644
index 0000000..b6a7654
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_ratio.scss
@@ -0,0 +1,26 @@
+// Credit: Nicolas Gallagher and SUIT CSS.
+
+.ratio {
+ position: relative;
+ width: 100%;
+
+ &::before {
+ display: block;
+ padding-top: var(--#{$prefix}aspect-ratio);
+ content: "";
+ }
+
+ > * {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ }
+}
+
+@each $key, $ratio in $aspect-ratios {
+ .ratio-#{$key} {
+ --#{$prefix}aspect-ratio: #{$ratio};
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_stacks.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_stacks.scss
new file mode 100644
index 0000000..6cd237a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_stacks.scss
@@ -0,0 +1,15 @@
+// scss-docs-start stacks
+.hstack {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ align-self: stretch;
+}
+
+.vstack {
+ display: flex;
+ flex: 1 1 auto;
+ flex-direction: column;
+ align-self: stretch;
+}
+// scss-docs-end stacks
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_stretched-link.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_stretched-link.scss
new file mode 100644
index 0000000..71a1c75
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_stretched-link.scss
@@ -0,0 +1,15 @@
+//
+// Stretched link
+//
+
+.stretched-link {
+ &::#{$stretched-link-pseudo-element} {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: $stretched-link-z-index;
+ content: "";
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_text-truncation.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_text-truncation.scss
new file mode 100644
index 0000000..6421dac
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_text-truncation.scss
@@ -0,0 +1,7 @@
+//
+// Text truncation
+//
+
+.text-truncate {
+ @include text-truncate();
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_visually-hidden.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_visually-hidden.scss
new file mode 100644
index 0000000..4760ff0
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_visually-hidden.scss
@@ -0,0 +1,8 @@
+//
+// Visually hidden
+//
+
+.visually-hidden,
+.visually-hidden-focusable:not(:focus):not(:focus-within) {
+ @include visually-hidden();
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_vr.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_vr.scss
new file mode 100644
index 0000000..b6f9d42
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/helpers/_vr.scss
@@ -0,0 +1,8 @@
+.vr {
+ display: inline-block;
+ align-self: stretch;
+ width: $vr-border-width;
+ min-height: 1em;
+ background-color: currentcolor;
+ opacity: $hr-opacity;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_alert.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_alert.scss
new file mode 100644
index 0000000..fb524af
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_alert.scss
@@ -0,0 +1,18 @@
+@include deprecate("`alert-variant()`", "v5.3.0", "v6.0.0");
+
+// scss-docs-start alert-variant-mixin
+@mixin alert-variant($background, $border, $color) {
+ --#{$prefix}alert-color: #{$color};
+ --#{$prefix}alert-bg: #{$background};
+ --#{$prefix}alert-border-color: #{$border};
+ --#{$prefix}alert-link-color: #{shade-color($color, 20%)};
+
+ @if $enable-gradients {
+ background-image: var(--#{$prefix}gradient);
+ }
+
+ .alert-link {
+ color: var(--#{$prefix}alert-link-color);
+ }
+}
+// scss-docs-end alert-variant-mixin
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_backdrop.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_backdrop.scss
new file mode 100644
index 0000000..9705ae9
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_backdrop.scss
@@ -0,0 +1,14 @@
+// Shared between modals and offcanvases
+@mixin overlay-backdrop($zindex, $backdrop-bg, $backdrop-opacity) {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: $zindex;
+ width: 100vw;
+ height: 100vh;
+ background-color: $backdrop-bg;
+
+ // Fade for backdrop
+ &.fade { opacity: 0; }
+ &.show { opacity: $backdrop-opacity; }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_banner.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_banner.scss
new file mode 100644
index 0000000..dd8a510
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_banner.scss
@@ -0,0 +1,7 @@
+@mixin bsBanner($file) {
+ /*!
+ * Bootstrap #{$file} v5.3.8 (https://getbootstrap.com/)
+ * Copyright 2011-2025 The Bootstrap Authors
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ */
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_border-radius.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_border-radius.scss
new file mode 100644
index 0000000..616decb
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_border-radius.scss
@@ -0,0 +1,78 @@
+// stylelint-disable property-disallowed-list
+// Single side border-radius
+
+// Helper function to replace negative values with 0
+@function valid-radius($radius) {
+ $return: ();
+ @each $value in $radius {
+ @if type-of($value) == number {
+ $return: append($return, max($value, 0));
+ } @else {
+ $return: append($return, $value);
+ }
+ }
+ @return $return;
+}
+
+// scss-docs-start border-radius-mixins
+@mixin border-radius($radius: $border-radius, $fallback-border-radius: false) {
+ @if $enable-rounded {
+ border-radius: valid-radius($radius);
+ }
+ @else if $fallback-border-radius != false {
+ border-radius: $fallback-border-radius;
+ }
+}
+
+@mixin border-top-radius($radius: $border-radius) {
+ @if $enable-rounded {
+ border-top-left-radius: valid-radius($radius);
+ border-top-right-radius: valid-radius($radius);
+ }
+}
+
+@mixin border-end-radius($radius: $border-radius) {
+ @if $enable-rounded {
+ border-top-right-radius: valid-radius($radius);
+ border-bottom-right-radius: valid-radius($radius);
+ }
+}
+
+@mixin border-bottom-radius($radius: $border-radius) {
+ @if $enable-rounded {
+ border-bottom-right-radius: valid-radius($radius);
+ border-bottom-left-radius: valid-radius($radius);
+ }
+}
+
+@mixin border-start-radius($radius: $border-radius) {
+ @if $enable-rounded {
+ border-top-left-radius: valid-radius($radius);
+ border-bottom-left-radius: valid-radius($radius);
+ }
+}
+
+@mixin border-top-start-radius($radius: $border-radius) {
+ @if $enable-rounded {
+ border-top-left-radius: valid-radius($radius);
+ }
+}
+
+@mixin border-top-end-radius($radius: $border-radius) {
+ @if $enable-rounded {
+ border-top-right-radius: valid-radius($radius);
+ }
+}
+
+@mixin border-bottom-end-radius($radius: $border-radius) {
+ @if $enable-rounded {
+ border-bottom-right-radius: valid-radius($radius);
+ }
+}
+
+@mixin border-bottom-start-radius($radius: $border-radius) {
+ @if $enable-rounded {
+ border-bottom-left-radius: valid-radius($radius);
+ }
+}
+// scss-docs-end border-radius-mixins
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_box-shadow.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_box-shadow.scss
new file mode 100644
index 0000000..0bb6bf7
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_box-shadow.scss
@@ -0,0 +1,24 @@
+@mixin box-shadow($shadow...) {
+ @if $enable-shadows {
+ $result: ();
+ $has-single-value: false;
+ $single-value: null;
+
+ @each $value in $shadow {
+ @if $value != null {
+ @if $value == none or $value == initial or $value == inherit or $value == unset {
+ $has-single-value: true;
+ $single-value: $value;
+ } @else {
+ $result: append($result, $value, "comma");
+ }
+ }
+ }
+
+ @if $has-single-value {
+ box-shadow: $single-value;
+ } @else if (length($result) > 0) {
+ box-shadow: $result;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_breakpoints.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_breakpoints.scss
new file mode 100644
index 0000000..286be89
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_breakpoints.scss
@@ -0,0 +1,127 @@
+// Breakpoint viewport sizes and media queries.
+//
+// Breakpoints are defined as a map of (name: minimum width), order from small to large:
+//
+// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px)
+//
+// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.
+
+// Name of the next breakpoint, or null for the last breakpoint.
+//
+// >> breakpoint-next(sm)
+// md
+// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
+// md
+// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl xxl))
+// md
+@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
+ $n: index($breakpoint-names, $name);
+ @if not $n {
+ @error "breakpoint `#{$name}` not found in `#{$breakpoints}`";
+ }
+ @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
+}
+
+// Minimum breakpoint width. Null for the smallest (first) breakpoint.
+//
+// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
+// 576px
+@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
+ $min: map-get($breakpoints, $name);
+ @return if($min != 0, $min, null);
+}
+
+// Maximum breakpoint width.
+// The maximum value is reduced by 0.02px to work around the limitations of
+// `min-` and `max-` prefixes and viewports with fractional widths.
+// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max
+// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.
+// See https://bugs.webkit.org/show_bug.cgi?id=178261
+//
+// >> breakpoint-max(md, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
+// 767.98px
+@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
+ $max: map-get($breakpoints, $name);
+ @return if($max and $max > 0, $max - .02, null);
+}
+
+// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.
+// Useful for making responsive utilities.
+//
+// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
+// "" (Returns a blank string)
+// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px))
+// "-sm"
+@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
+ @return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
+}
+
+// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
+// Makes the @content apply to the given breakpoint and wider.
+@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
+ $min: breakpoint-min($name, $breakpoints);
+ @if $min {
+ @media (min-width: $min) {
+ @content;
+ }
+ } @else {
+ @content;
+ }
+}
+
+// Media of at most the maximum breakpoint width. No query for the largest breakpoint.
+// Makes the @content apply to the given breakpoint and narrower.
+@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
+ $max: breakpoint-max($name, $breakpoints);
+ @if $max {
+ @media (max-width: $max) {
+ @content;
+ }
+ } @else {
+ @content;
+ }
+}
+
+// Media that spans multiple breakpoint widths.
+// Makes the @content apply between the min and max breakpoints
+@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {
+ $min: breakpoint-min($lower, $breakpoints);
+ $max: breakpoint-max($upper, $breakpoints);
+
+ @if $min != null and $max != null {
+ @media (min-width: $min) and (max-width: $max) {
+ @content;
+ }
+ } @else if $max == null {
+ @include media-breakpoint-up($lower, $breakpoints) {
+ @content;
+ }
+ } @else if $min == null {
+ @include media-breakpoint-down($upper, $breakpoints) {
+ @content;
+ }
+ }
+}
+
+// Media between the breakpoint's minimum and maximum widths.
+// No minimum for the smallest breakpoint, and no maximum for the largest one.
+// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.
+@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {
+ $min: breakpoint-min($name, $breakpoints);
+ $next: breakpoint-next($name, $breakpoints);
+ $max: breakpoint-max($next, $breakpoints);
+
+ @if $min != null and $max != null {
+ @media (min-width: $min) and (max-width: $max) {
+ @content;
+ }
+ } @else if $max == null {
+ @include media-breakpoint-up($name, $breakpoints) {
+ @content;
+ }
+ } @else if $min == null {
+ @include media-breakpoint-down($next, $breakpoints) {
+ @content;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_buttons.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_buttons.scss
new file mode 100644
index 0000000..cf087fd
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_buttons.scss
@@ -0,0 +1,70 @@
+// Button variants
+//
+// Easily pump out default styles, as well as :hover, :focus, :active,
+// and disabled options for all buttons
+
+// scss-docs-start btn-variant-mixin
+@mixin button-variant(
+ $background,
+ $border,
+ $color: color-contrast($background),
+ $hover-background: if($color == $color-contrast-light, shade-color($background, $btn-hover-bg-shade-amount), tint-color($background, $btn-hover-bg-tint-amount)),
+ $hover-border: if($color == $color-contrast-light, shade-color($border, $btn-hover-border-shade-amount), tint-color($border, $btn-hover-border-tint-amount)),
+ $hover-color: color-contrast($hover-background),
+ $active-background: if($color == $color-contrast-light, shade-color($background, $btn-active-bg-shade-amount), tint-color($background, $btn-active-bg-tint-amount)),
+ $active-border: if($color == $color-contrast-light, shade-color($border, $btn-active-border-shade-amount), tint-color($border, $btn-active-border-tint-amount)),
+ $active-color: color-contrast($active-background),
+ $disabled-background: $background,
+ $disabled-border: $border,
+ $disabled-color: color-contrast($disabled-background)
+) {
+ --#{$prefix}btn-color: #{$color};
+ --#{$prefix}btn-bg: #{$background};
+ --#{$prefix}btn-border-color: #{$border};
+ --#{$prefix}btn-hover-color: #{$hover-color};
+ --#{$prefix}btn-hover-bg: #{$hover-background};
+ --#{$prefix}btn-hover-border-color: #{$hover-border};
+ --#{$prefix}btn-focus-shadow-rgb: #{to-rgb(mix($color, $border, 15%))};
+ --#{$prefix}btn-active-color: #{$active-color};
+ --#{$prefix}btn-active-bg: #{$active-background};
+ --#{$prefix}btn-active-border-color: #{$active-border};
+ --#{$prefix}btn-active-shadow: #{$btn-active-box-shadow};
+ --#{$prefix}btn-disabled-color: #{$disabled-color};
+ --#{$prefix}btn-disabled-bg: #{$disabled-background};
+ --#{$prefix}btn-disabled-border-color: #{$disabled-border};
+}
+// scss-docs-end btn-variant-mixin
+
+// scss-docs-start btn-outline-variant-mixin
+@mixin button-outline-variant(
+ $color,
+ $color-hover: color-contrast($color),
+ $active-background: $color,
+ $active-border: $color,
+ $active-color: color-contrast($active-background)
+) {
+ --#{$prefix}btn-color: #{$color};
+ --#{$prefix}btn-border-color: #{$color};
+ --#{$prefix}btn-hover-color: #{$color-hover};
+ --#{$prefix}btn-hover-bg: #{$active-background};
+ --#{$prefix}btn-hover-border-color: #{$active-border};
+ --#{$prefix}btn-focus-shadow-rgb: #{to-rgb($color)};
+ --#{$prefix}btn-active-color: #{$active-color};
+ --#{$prefix}btn-active-bg: #{$active-background};
+ --#{$prefix}btn-active-border-color: #{$active-border};
+ --#{$prefix}btn-active-shadow: #{$btn-active-box-shadow};
+ --#{$prefix}btn-disabled-color: #{$color};
+ --#{$prefix}btn-disabled-bg: transparent;
+ --#{$prefix}btn-disabled-border-color: #{$color};
+ --#{$prefix}gradient: none;
+}
+// scss-docs-end btn-outline-variant-mixin
+
+// scss-docs-start btn-size-mixin
+@mixin button-size($padding-y, $padding-x, $font-size, $border-radius) {
+ --#{$prefix}btn-padding-y: #{$padding-y};
+ --#{$prefix}btn-padding-x: #{$padding-x};
+ @include rfs($font-size, --#{$prefix}btn-font-size);
+ --#{$prefix}btn-border-radius: #{$border-radius};
+}
+// scss-docs-end btn-size-mixin
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_caret.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_caret.scss
new file mode 100644
index 0000000..be73116
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_caret.scss
@@ -0,0 +1,69 @@
+// scss-docs-start caret-mixins
+@mixin caret-down($width: $caret-width) {
+ border-top: $width solid;
+ border-right: $width solid transparent;
+ border-bottom: 0;
+ border-left: $width solid transparent;
+}
+
+@mixin caret-up($width: $caret-width) {
+ border-top: 0;
+ border-right: $width solid transparent;
+ border-bottom: $width solid;
+ border-left: $width solid transparent;
+}
+
+@mixin caret-end($width: $caret-width) {
+ border-top: $width solid transparent;
+ border-right: 0;
+ border-bottom: $width solid transparent;
+ border-left: $width solid;
+}
+
+@mixin caret-start($width: $caret-width) {
+ border-top: $width solid transparent;
+ border-right: $width solid;
+ border-bottom: $width solid transparent;
+}
+
+@mixin caret(
+ $direction: down,
+ $width: $caret-width,
+ $spacing: $caret-spacing,
+ $vertical-align: $caret-vertical-align
+) {
+ @if $enable-caret {
+ &::after {
+ display: inline-block;
+ margin-left: $spacing;
+ vertical-align: $vertical-align;
+ content: "";
+ @if $direction == down {
+ @include caret-down($width);
+ } @else if $direction == up {
+ @include caret-up($width);
+ } @else if $direction == end {
+ @include caret-end($width);
+ }
+ }
+
+ @if $direction == start {
+ &::after {
+ display: none;
+ }
+
+ &::before {
+ display: inline-block;
+ margin-right: $spacing;
+ vertical-align: $vertical-align;
+ content: "";
+ @include caret-start($width);
+ }
+ }
+
+ &:empty::after {
+ margin-left: 0;
+ }
+ }
+}
+// scss-docs-end caret-mixins
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_clearfix.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_clearfix.scss
new file mode 100644
index 0000000..ffc62bb
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_clearfix.scss
@@ -0,0 +1,9 @@
+// scss-docs-start clearfix
+@mixin clearfix() {
+ &::after {
+ display: block;
+ clear: both;
+ content: "";
+ }
+}
+// scss-docs-end clearfix
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_color-mode.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_color-mode.scss
new file mode 100644
index 0000000..03338b0
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_color-mode.scss
@@ -0,0 +1,21 @@
+// scss-docs-start color-mode-mixin
+@mixin color-mode($mode: light, $root: false) {
+ @if $color-mode-type == "media-query" {
+ @if $root == true {
+ @media (prefers-color-scheme: $mode) {
+ :root {
+ @content;
+ }
+ }
+ } @else {
+ @media (prefers-color-scheme: $mode) {
+ @content;
+ }
+ }
+ } @else {
+ [data-bs-theme="#{$mode}"] {
+ @content;
+ }
+ }
+}
+// scss-docs-end color-mode-mixin
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_color-scheme.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_color-scheme.scss
new file mode 100644
index 0000000..90497aa
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_color-scheme.scss
@@ -0,0 +1,7 @@
+// scss-docs-start mixin-color-scheme
+@mixin color-scheme($name) {
+ @media (prefers-color-scheme: #{$name}) {
+ @content;
+ }
+}
+// scss-docs-end mixin-color-scheme
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_container.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_container.scss
new file mode 100644
index 0000000..b9f3351
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_container.scss
@@ -0,0 +1,11 @@
+// Container mixins
+
+@mixin make-container($gutter: $container-padding-x) {
+ --#{$prefix}gutter-x: #{$gutter};
+ --#{$prefix}gutter-y: 0;
+ width: 100%;
+ padding-right: calc(var(--#{$prefix}gutter-x) * .5); // stylelint-disable-line function-disallowed-list
+ padding-left: calc(var(--#{$prefix}gutter-x) * .5); // stylelint-disable-line function-disallowed-list
+ margin-right: auto;
+ margin-left: auto;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_deprecate.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_deprecate.scss
new file mode 100644
index 0000000..df070bc
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_deprecate.scss
@@ -0,0 +1,10 @@
+// Deprecate mixin
+//
+// This mixin can be used to deprecate mixins or functions.
+// `$enable-deprecation-messages` is a global variable, `$ignore-warning` is a variable that can be passed to
+// some deprecated mixins to suppress the warning (for example if the mixin is still be used in the current version of Bootstrap)
+@mixin deprecate($name, $deprecate-version, $remove-version, $ignore-warning: false) {
+ @if ($enable-deprecation-messages != false and $ignore-warning != true) {
+ @warn "#{$name} has been deprecated as of #{$deprecate-version}. It will be removed entirely in #{$remove-version}.";
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_forms.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_forms.scss
new file mode 100644
index 0000000..00b4764
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_forms.scss
@@ -0,0 +1,163 @@
+// This mixin uses an `if()` technique to be compatible with Dart Sass
+// See https://github.com/sass/sass/issues/1873#issuecomment-152293725 for more details
+
+// scss-docs-start form-validation-mixins
+@mixin form-validation-state-selector($state) {
+ @if ($state == "valid" or $state == "invalid") {
+ .was-validated #{if(&, "&", "")}:#{$state},
+ #{if(&, "&", "")}.is-#{$state} {
+ @content;
+ }
+ } @else {
+ #{if(&, "&", "")}.is-#{$state} {
+ @content;
+ }
+ }
+}
+
+@mixin form-validation-state(
+ $state,
+ $color,
+ $icon,
+ $tooltip-color: color-contrast($color),
+ $tooltip-bg-color: rgba($color, $form-feedback-tooltip-opacity),
+ $focus-box-shadow: 0 0 $input-btn-focus-blur $input-focus-width rgba($color, $input-btn-focus-color-opacity),
+ $border-color: $color
+) {
+ .#{$state}-feedback {
+ display: none;
+ width: 100%;
+ margin-top: $form-feedback-margin-top;
+ @include font-size($form-feedback-font-size);
+ font-style: $form-feedback-font-style;
+ color: $color;
+ }
+
+ .#{$state}-tooltip {
+ position: absolute;
+ top: 100%;
+ z-index: 5;
+ display: none;
+ max-width: 100%; // Contain to parent when possible
+ padding: $form-feedback-tooltip-padding-y $form-feedback-tooltip-padding-x;
+ margin-top: .1rem;
+ @include font-size($form-feedback-tooltip-font-size);
+ line-height: $form-feedback-tooltip-line-height;
+ color: $tooltip-color;
+ background-color: $tooltip-bg-color;
+ @include border-radius($form-feedback-tooltip-border-radius);
+ }
+
+ @include form-validation-state-selector($state) {
+ ~ .#{$state}-feedback,
+ ~ .#{$state}-tooltip {
+ display: block;
+ }
+ }
+
+ .form-control {
+ @include form-validation-state-selector($state) {
+ border-color: $border-color;
+
+ @if $enable-validation-icons {
+ padding-right: $input-height-inner;
+ background-image: escape-svg($icon);
+ background-repeat: no-repeat;
+ background-position: right $input-height-inner-quarter center;
+ background-size: $input-height-inner-half $input-height-inner-half;
+ }
+
+ &:focus {
+ border-color: $border-color;
+ @if $enable-shadows {
+ @include box-shadow($input-box-shadow, $focus-box-shadow);
+ } @else {
+ // Avoid using mixin so we can pass custom focus shadow properly
+ box-shadow: $focus-box-shadow;
+ }
+ }
+ }
+ }
+
+ // stylelint-disable-next-line selector-no-qualifying-type
+ textarea.form-control {
+ @include form-validation-state-selector($state) {
+ @if $enable-validation-icons {
+ padding-right: $input-height-inner;
+ background-position: top $input-height-inner-quarter right $input-height-inner-quarter;
+ }
+ }
+ }
+
+ .form-select {
+ @include form-validation-state-selector($state) {
+ border-color: $border-color;
+
+ @if $enable-validation-icons {
+ &:not([multiple]):not([size]),
+ &:not([multiple])[size="1"] {
+ --#{$prefix}form-select-bg-icon: #{escape-svg($icon)};
+ padding-right: $form-select-feedback-icon-padding-end;
+ background-position: $form-select-bg-position, $form-select-feedback-icon-position;
+ background-size: $form-select-bg-size, $form-select-feedback-icon-size;
+ }
+ }
+
+ &:focus {
+ border-color: $border-color;
+ @if $enable-shadows {
+ @include box-shadow($form-select-box-shadow, $focus-box-shadow);
+ } @else {
+ // Avoid using mixin so we can pass custom focus shadow properly
+ box-shadow: $focus-box-shadow;
+ }
+ }
+ }
+ }
+
+ .form-control-color {
+ @include form-validation-state-selector($state) {
+ @if $enable-validation-icons {
+ width: add($form-color-width, $input-height-inner);
+ }
+ }
+ }
+
+ .form-check-input {
+ @include form-validation-state-selector($state) {
+ border-color: $border-color;
+
+ &:checked {
+ background-color: $color;
+ }
+
+ &:focus {
+ box-shadow: $focus-box-shadow;
+ }
+
+ ~ .form-check-label {
+ color: $color;
+ }
+ }
+ }
+ .form-check-inline .form-check-input {
+ ~ .#{$state}-feedback {
+ margin-left: .5em;
+ }
+ }
+
+ .input-group {
+ > .form-control:not(:focus),
+ > .form-select:not(:focus),
+ > .form-floating:not(:focus-within) {
+ @include form-validation-state-selector($state) {
+ @if $state == "valid" {
+ z-index: 3;
+ } @else if $state == "invalid" {
+ z-index: 4;
+ }
+ }
+ }
+ }
+}
+// scss-docs-end form-validation-mixins
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_gradients.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_gradients.scss
new file mode 100644
index 0000000..608e18d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_gradients.scss
@@ -0,0 +1,47 @@
+// Gradients
+
+// scss-docs-start gradient-bg-mixin
+@mixin gradient-bg($color: null) {
+ background-color: $color;
+
+ @if $enable-gradients {
+ background-image: var(--#{$prefix}gradient);
+ }
+}
+// scss-docs-end gradient-bg-mixin
+
+// scss-docs-start gradient-mixins
+// Horizontal gradient, from left to right
+//
+// Creates two color stops, start and end, by specifying a color and position for each color stop.
+@mixin gradient-x($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) {
+ background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent);
+}
+
+// Vertical gradient, from top to bottom
+//
+// Creates two color stops, start and end, by specifying a color and position for each color stop.
+@mixin gradient-y($start-color: $gray-700, $end-color: $gray-800, $start-percent: null, $end-percent: null) {
+ background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent);
+}
+
+@mixin gradient-directional($start-color: $gray-700, $end-color: $gray-800, $deg: 45deg) {
+ background-image: linear-gradient($deg, $start-color, $end-color);
+}
+
+@mixin gradient-x-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) {
+ background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color);
+}
+
+@mixin gradient-y-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) {
+ background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color);
+}
+
+@mixin gradient-radial($inner-color: $gray-700, $outer-color: $gray-800) {
+ background-image: radial-gradient(circle, $inner-color, $outer-color);
+}
+
+@mixin gradient-striped($color: rgba($white, .15), $angle: 45deg) {
+ background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);
+}
+// scss-docs-end gradient-mixins
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_grid.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_grid.scss
new file mode 100644
index 0000000..db77e07
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_grid.scss
@@ -0,0 +1,151 @@
+// Grid system
+//
+// Generate semantic grid columns with these mixins.
+
+@mixin make-row($gutter: $grid-gutter-width) {
+ --#{$prefix}gutter-x: #{$gutter};
+ --#{$prefix}gutter-y: 0;
+ display: flex;
+ flex-wrap: wrap;
+ // TODO: Revisit calc order after https://github.com/react-bootstrap/react-bootstrap/issues/6039 is fixed
+ margin-top: calc(-1 * var(--#{$prefix}gutter-y)); // stylelint-disable-line function-disallowed-list
+ margin-right: calc(-.5 * var(--#{$prefix}gutter-x)); // stylelint-disable-line function-disallowed-list
+ margin-left: calc(-.5 * var(--#{$prefix}gutter-x)); // stylelint-disable-line function-disallowed-list
+}
+
+@mixin make-col-ready() {
+ // Add box sizing if only the grid is loaded
+ box-sizing: if(variable-exists(include-column-box-sizing) and $include-column-box-sizing, border-box, null);
+ // Prevent columns from becoming too narrow when at smaller grid tiers by
+ // always setting `width: 100%;`. This works because we set the width
+ // later on to override this initial width.
+ flex-shrink: 0;
+ width: 100%;
+ max-width: 100%; // Prevent `.col-auto`, `.col` (& responsive variants) from breaking out the grid
+ padding-right: calc(var(--#{$prefix}gutter-x) * .5); // stylelint-disable-line function-disallowed-list
+ padding-left: calc(var(--#{$prefix}gutter-x) * .5); // stylelint-disable-line function-disallowed-list
+ margin-top: var(--#{$prefix}gutter-y);
+}
+
+@mixin make-col($size: false, $columns: $grid-columns) {
+ @if $size {
+ flex: 0 0 auto;
+ width: percentage(divide($size, $columns));
+
+ } @else {
+ flex: 1 1 0;
+ max-width: 100%;
+ }
+}
+
+@mixin make-col-auto() {
+ flex: 0 0 auto;
+ width: auto;
+}
+
+@mixin make-col-offset($size, $columns: $grid-columns) {
+ $num: divide($size, $columns);
+ margin-left: if($num == 0, 0, percentage($num));
+}
+
+// Row columns
+//
+// Specify on a parent element(e.g., .row) to force immediate children into NN
+// number of columns. Supports wrapping to new lines, but does not do a Masonry
+// style grid.
+@mixin row-cols($count) {
+ > * {
+ flex: 0 0 auto;
+ width: percentage(divide(1, $count));
+ }
+}
+
+// Framework grid generation
+//
+// Used only by Bootstrap to generate the correct number of grid classes given
+// any value of `$grid-columns`.
+
+@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {
+ @each $breakpoint in map-keys($breakpoints) {
+ $infix: breakpoint-infix($breakpoint, $breakpoints);
+
+ @include media-breakpoint-up($breakpoint, $breakpoints) {
+ // Provide basic `.col-{bp}` classes for equal-width flexbox columns
+ .col#{$infix} {
+ flex: 1 0 0;
+ }
+
+ .row-cols#{$infix}-auto > * {
+ @include make-col-auto();
+ }
+
+ @if $grid-row-columns > 0 {
+ @for $i from 1 through $grid-row-columns {
+ .row-cols#{$infix}-#{$i} {
+ @include row-cols($i);
+ }
+ }
+ }
+
+ .col#{$infix}-auto {
+ @include make-col-auto();
+ }
+
+ @if $columns > 0 {
+ @for $i from 1 through $columns {
+ .col#{$infix}-#{$i} {
+ @include make-col($i, $columns);
+ }
+ }
+
+ // `$columns - 1` because offsetting by the width of an entire row isn't possible
+ @for $i from 0 through ($columns - 1) {
+ @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0
+ .offset#{$infix}-#{$i} {
+ @include make-col-offset($i, $columns);
+ }
+ }
+ }
+ }
+
+ // Gutters
+ //
+ // Make use of `.g-*`, `.gx-*` or `.gy-*` utilities to change spacing between the columns.
+ @each $key, $value in $gutters {
+ .g#{$infix}-#{$key},
+ .gx#{$infix}-#{$key} {
+ --#{$prefix}gutter-x: #{$value};
+ }
+
+ .g#{$infix}-#{$key},
+ .gy#{$infix}-#{$key} {
+ --#{$prefix}gutter-y: #{$value};
+ }
+ }
+ }
+ }
+}
+
+@mixin make-cssgrid($columns: $grid-columns, $breakpoints: $grid-breakpoints) {
+ @each $breakpoint in map-keys($breakpoints) {
+ $infix: breakpoint-infix($breakpoint, $breakpoints);
+
+ @include media-breakpoint-up($breakpoint, $breakpoints) {
+ @if $columns > 0 {
+ @for $i from 1 through $columns {
+ .g-col#{$infix}-#{$i} {
+ grid-column: auto / span $i;
+ }
+ }
+
+ // Start with `1` because `0` is an invalid value.
+ // Ends with `$columns - 1` because offsetting by the width of an entire row isn't possible.
+ @for $i from 1 through ($columns - 1) {
+ .g-start#{$infix}-#{$i} {
+ grid-column-start: $i;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_image.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_image.scss
new file mode 100644
index 0000000..e1df779
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_image.scss
@@ -0,0 +1,16 @@
+// Image Mixins
+// - Responsive image
+// - Retina image
+
+
+// Responsive image
+//
+// Keep images from scaling beyond the width of their parents.
+
+@mixin img-fluid {
+ // Part 1: Set a maximum relative to the parent
+ max-width: 100%;
+ // Part 2: Override the height to auto, otherwise images will be stretched
+ // when setting a width and height attribute on the img element.
+ height: auto;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_list-group.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_list-group.scss
new file mode 100644
index 0000000..6274f34
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_list-group.scss
@@ -0,0 +1,26 @@
+@include deprecate("`list-group-item-variant()`", "v5.3.0", "v6.0.0");
+
+// List Groups
+
+// scss-docs-start list-group-mixin
+@mixin list-group-item-variant($state, $background, $color) {
+ .list-group-item-#{$state} {
+ color: $color;
+ background-color: $background;
+
+ &.list-group-item-action {
+ &:hover,
+ &:focus {
+ color: $color;
+ background-color: shade-color($background, 10%);
+ }
+
+ &.active {
+ color: $white;
+ background-color: $color;
+ border-color: $color;
+ }
+ }
+ }
+}
+// scss-docs-end list-group-mixin
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_lists.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_lists.scss
new file mode 100644
index 0000000..2518562
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_lists.scss
@@ -0,0 +1,7 @@
+// Lists
+
+// Unstyled keeps list items block level, just removes default browser padding and list-style
+@mixin list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_pagination.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_pagination.scss
new file mode 100644
index 0000000..0d65796
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_pagination.scss
@@ -0,0 +1,10 @@
+// Pagination
+
+// scss-docs-start pagination-mixin
+@mixin pagination-size($padding-y, $padding-x, $font-size, $border-radius) {
+ --#{$prefix}pagination-padding-x: #{$padding-x};
+ --#{$prefix}pagination-padding-y: #{$padding-y};
+ @include rfs($font-size, --#{$prefix}pagination-font-size);
+ --#{$prefix}pagination-border-radius: #{$border-radius};
+}
+// scss-docs-end pagination-mixin
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_reset-text.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_reset-text.scss
new file mode 100644
index 0000000..f5bd1af
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_reset-text.scss
@@ -0,0 +1,17 @@
+@mixin reset-text {
+ font-family: $font-family-base;
+ // We deliberately do NOT reset font-size or overflow-wrap / word-wrap.
+ font-style: normal;
+ font-weight: $font-weight-normal;
+ line-height: $line-height-base;
+ text-align: left; // Fallback for where `start` is not supported
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ letter-spacing: normal;
+ word-break: normal;
+ white-space: normal;
+ word-spacing: normal;
+ line-break: auto;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_resize.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_resize.scss
new file mode 100644
index 0000000..66f233a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_resize.scss
@@ -0,0 +1,6 @@
+// Resize anything
+
+@mixin resizable($direction) {
+ overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible`
+ resize: $direction; // Options: horizontal, vertical, both
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_table-variants.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_table-variants.scss
new file mode 100644
index 0000000..5fe1b9b
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_table-variants.scss
@@ -0,0 +1,24 @@
+// scss-docs-start table-variant
+@mixin table-variant($state, $background) {
+ .table-#{$state} {
+ $color: color-contrast(opaque($body-bg, $background));
+ $hover-bg: mix($color, $background, percentage($table-hover-bg-factor));
+ $striped-bg: mix($color, $background, percentage($table-striped-bg-factor));
+ $active-bg: mix($color, $background, percentage($table-active-bg-factor));
+ $table-border-color: mix($color, $background, percentage($table-border-factor));
+
+ --#{$prefix}table-color: #{$color};
+ --#{$prefix}table-bg: #{$background};
+ --#{$prefix}table-border-color: #{$table-border-color};
+ --#{$prefix}table-striped-bg: #{$striped-bg};
+ --#{$prefix}table-striped-color: #{color-contrast($striped-bg)};
+ --#{$prefix}table-active-bg: #{$active-bg};
+ --#{$prefix}table-active-color: #{color-contrast($active-bg)};
+ --#{$prefix}table-hover-bg: #{$hover-bg};
+ --#{$prefix}table-hover-color: #{color-contrast($hover-bg)};
+
+ color: var(--#{$prefix}table-color);
+ border-color: var(--#{$prefix}table-border-color);
+ }
+}
+// scss-docs-end table-variant
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_text-truncate.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_text-truncate.scss
new file mode 100644
index 0000000..3504bb1
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_text-truncate.scss
@@ -0,0 +1,8 @@
+// Text truncate
+// Requires inline-block or block for proper styling
+
+@mixin text-truncate() {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_transition.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_transition.scss
new file mode 100644
index 0000000..d437f6d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_transition.scss
@@ -0,0 +1,26 @@
+// stylelint-disable property-disallowed-list
+@mixin transition($transition...) {
+ @if length($transition) == 0 {
+ $transition: $transition-base;
+ }
+
+ @if length($transition) > 1 {
+ @each $value in $transition {
+ @if $value == null or $value == none {
+ @warn "The keyword 'none' or 'null' must be used as a single argument.";
+ }
+ }
+ }
+
+ @if $enable-transitions {
+ @if nth($transition, 1) != null {
+ transition: $transition;
+ }
+
+ @if $enable-reduced-motion and nth($transition, 1) != null and nth($transition, 1) != none {
+ @media (prefers-reduced-motion: reduce) {
+ transition: none;
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_utilities.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_utilities.scss
new file mode 100644
index 0000000..4795e89
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_utilities.scss
@@ -0,0 +1,97 @@
+// Utility generator
+// Used to generate utilities & print utilities
+@mixin generate-utility($utility, $infix: "", $is-rfs-media-query: false) {
+ $values: map-get($utility, values);
+
+ // If the values are a list or string, convert it into a map
+ @if type-of($values) == "string" or type-of(nth($values, 1)) != "list" {
+ $values: zip($values, $values);
+ }
+
+ @each $key, $value in $values {
+ $properties: map-get($utility, property);
+
+ // Multiple properties are possible, for example with vertical or horizontal margins or paddings
+ @if type-of($properties) == "string" {
+ $properties: append((), $properties);
+ }
+
+ // Use custom class if present
+ $property-class: if(map-has-key($utility, class), map-get($utility, class), nth($properties, 1));
+ $property-class: if($property-class == null, "", $property-class);
+
+ // Use custom CSS variable name if present, otherwise default to `class`
+ $css-variable-name: if(map-has-key($utility, css-variable-name), map-get($utility, css-variable-name), map-get($utility, class));
+
+ // State params to generate pseudo-classes
+ $state: if(map-has-key($utility, state), map-get($utility, state), ());
+
+ $infix: if($property-class == "" and str-slice($infix, 1, 1) == "-", str-slice($infix, 2), $infix);
+
+ // Don't prefix if value key is null (e.g. with shadow class)
+ $property-class-modifier: if($key, if($property-class == "" and $infix == "", "", "-") + $key, "");
+
+ @if map-get($utility, rfs) {
+ // Inside the media query
+ @if $is-rfs-media-query {
+ $val: rfs-value($value);
+
+ // Do not render anything if fluid and non fluid values are the same
+ $value: if($val == rfs-fluid-value($value), null, $val);
+ }
+ @else {
+ $value: rfs-fluid-value($value);
+ }
+ }
+
+ $is-css-var: map-get($utility, css-var);
+ $is-local-vars: map-get($utility, local-vars);
+ $is-rtl: map-get($utility, rtl);
+
+ @if $value != null {
+ @if $is-rtl == false {
+ /* rtl:begin:remove */
+ }
+
+ @if $is-css-var {
+ .#{$property-class + $infix + $property-class-modifier} {
+ --#{$prefix}#{$css-variable-name}: #{$value};
+ }
+
+ @each $pseudo in $state {
+ .#{$property-class + $infix + $property-class-modifier}-#{$pseudo}:#{$pseudo} {
+ --#{$prefix}#{$css-variable-name}: #{$value};
+ }
+ }
+ } @else {
+ .#{$property-class + $infix + $property-class-modifier} {
+ @each $property in $properties {
+ @if $is-local-vars {
+ @each $local-var, $variable in $is-local-vars {
+ --#{$prefix}#{$local-var}: #{$variable};
+ }
+ }
+ #{$property}: $value if($enable-important-utilities, !important, null);
+ }
+ }
+
+ @each $pseudo in $state {
+ .#{$property-class + $infix + $property-class-modifier}-#{$pseudo}:#{$pseudo} {
+ @each $property in $properties {
+ @if $is-local-vars {
+ @each $local-var, $variable in $is-local-vars {
+ --#{$prefix}#{$local-var}: #{$variable};
+ }
+ }
+ #{$property}: $value if($enable-important-utilities, !important, null);
+ }
+ }
+ }
+ }
+
+ @if $is-rtl == false {
+ /* rtl:end:remove */
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_visually-hidden.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_visually-hidden.scss
new file mode 100644
index 0000000..9dd0ad3
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/mixins/_visually-hidden.scss
@@ -0,0 +1,38 @@
+// stylelint-disable declaration-no-important
+
+// Hide content visually while keeping it accessible to assistive technologies
+//
+// See: https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/
+// See: https://kittygiraudel.com/2016/10/13/css-hide-and-seek/
+
+@mixin visually-hidden() {
+ width: 1px !important;
+ height: 1px !important;
+ padding: 0 !important;
+ margin: -1px !important; // Fix for https://github.com/twbs/bootstrap/issues/25686
+ overflow: hidden !important;
+ clip: rect(0, 0, 0, 0) !important;
+ white-space: nowrap !important;
+ border: 0 !important;
+
+ // Fix for positioned table caption that could become anonymous cells
+ &:not(caption) {
+ position: absolute !important;
+ }
+
+ // Fix to prevent overflowing children to become focusable
+ * {
+ overflow: hidden !important;
+ }
+}
+
+// Use to only display content when it's focused, or one of its child elements is focused
+// (i.e. when focus is within the element/container that the class was applied to)
+//
+// Useful for "Skip to main content" links; see https://www.w3.org/WAI/WCAG22/Techniques/general/G1.html
+
+@mixin visually-hidden-focusable() {
+ &:not(:focus):not(:focus-within) {
+ @include visually-hidden();
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/jasmine.js b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/jasmine.js
new file mode 100644
index 0000000..25d838c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/jasmine.js
@@ -0,0 +1,16 @@
+/* eslint-disable camelcase */
+
+'use strict'
+
+const path = require('node:path')
+
+module.exports = {
+ spec_dir: 'scss',
+ // Make Jasmine look for `.test.scss` files
+ spec_files: ['**/*.{test,spec}.scss'],
+ // Compile them into JS scripts running `sass-true`
+ requires: [path.join(__dirname, 'sass-true/register')],
+ // Ensure we use `require` so that the require.extensions works
+ // as `import` completely bypasses it
+ jsLoader: 'require'
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_auto-import-of-variables-dark.test.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_auto-import-of-variables-dark.test.scss
new file mode 100644
index 0000000..f08ae58
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_auto-import-of-variables-dark.test.scss
@@ -0,0 +1,7 @@
+// TODO: this file can be removed safely in v6 when `@import "variables-dark"` will be removed at the end of _variables.scss
+
+@import "../../functions";
+@import "../../variables";
+// Voluntarily not importing _variables-dark.scss
+@import "../../maps";
+@import "../../mixins";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_box-shadow.test.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_box-shadow.test.scss
new file mode 100644
index 0000000..f5a0748
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_box-shadow.test.scss
@@ -0,0 +1,188 @@
+@import "../../functions";
+@import "../../variables";
+@import "../../mixins";
+
+// Store original value
+$original-enable-shadows: $enable-shadows;
+
+// Enable shadows for all tests
+$enable-shadows: true !global;
+
+@include describe("box-shadow mixin") {
+ @include it("handles single none value") {
+ @include assert() {
+ @include output() {
+ .test {
+ @include box-shadow(none);
+ }
+ }
+
+ @include expect() {
+ .test {
+ box-shadow: none;
+ }
+ }
+ }
+ }
+
+ @include it("handles multiple none values by consolidating them") {
+ @include assert() {
+ @include output() {
+ .test {
+ @include box-shadow(none, none, none);
+ }
+ }
+
+ @include expect() {
+ .test {
+ box-shadow: none;
+ }
+ }
+ }
+ }
+
+ @include it("handles other single-value keywords (initial, inherit, unset)") {
+ @include assert() {
+ @include output() {
+ .test-initial {
+ @include box-shadow(initial);
+ }
+ .test-inherit {
+ @include box-shadow(inherit);
+ }
+ .test-unset {
+ @include box-shadow(unset);
+ }
+ }
+
+ @include expect() {
+ .test-initial {
+ box-shadow: initial;
+ }
+ .test-inherit {
+ box-shadow: inherit;
+ }
+ .test-unset {
+ box-shadow: unset;
+ }
+ }
+ }
+ }
+
+ @include it("handles multiple single-value keywords by using the last one") {
+ @include assert() {
+ @include output() {
+ .test {
+ @include box-shadow(initial, inherit, unset);
+ }
+ }
+
+ @include expect() {
+ .test {
+ box-shadow: unset;
+ }
+ }
+ }
+ }
+
+ @include it("handles regular box-shadow values") {
+ @include assert() {
+ @include output() {
+ .test {
+ @include box-shadow(0 0 10px rgba(0, 0, 0, .5));
+ }
+ }
+
+ @include expect() {
+ .test {
+ box-shadow: 0 0 10px rgba(0, 0, 0, .5);
+ }
+ }
+ }
+ }
+
+ @include it("handles multiple regular box-shadow values") {
+ @include assert() {
+ @include output() {
+ .test {
+ @include box-shadow(0 0 10px rgba(0, 0, 0, .5), 0 0 20px rgba(0, 0, 0, .3));
+ }
+ }
+
+ @include expect() {
+ .test {
+ box-shadow: 0 0 10px rgba(0, 0, 0, .5), 0 0 20px rgba(0, 0, 0, .3);
+ }
+ }
+ }
+ }
+
+ @include it("handles null values by ignoring them") {
+ @include assert() {
+ @include output() {
+ .test {
+ @include box-shadow(null, 0 0 10px rgba(0, 0, 0, .5), null);
+ }
+ }
+
+ @include expect() {
+ .test {
+ box-shadow: 0 0 10px rgba(0, 0, 0, .5);
+ }
+ }
+ }
+ }
+
+ @include it("handles mixed values with keywords and regular shadows") {
+ @include assert() {
+ @include output() {
+ .test {
+ @include box-shadow(none, 0 0 10px rgba(0, 0, 0, .5));
+ }
+ }
+
+ @include expect() {
+ .test {
+ box-shadow: none;
+ }
+ }
+ }
+ }
+
+ @include it("handles empty input") {
+ @include assert() {
+ @include output() {
+ .test {
+ @include box-shadow();
+ }
+ }
+
+ @include expect() {
+ .test { // stylelint-disable-line block-no-empty
+ }
+ }
+ }
+ }
+
+ @include it("respects $enable-shadows variable") {
+ $enable-shadows: false !global;
+
+ @include assert() {
+ @include output() {
+ .test {
+ @include box-shadow(0 0 10px rgba(0, 0, 0, .5));
+ }
+ }
+
+ @include expect() {
+ .test { // stylelint-disable-line block-no-empty
+ }
+ }
+ }
+
+ $enable-shadows: true !global;
+ }
+}
+
+// Restore original value
+$enable-shadows: $original-enable-shadows !global;
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_color-contrast.test.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_color-contrast.test.scss
new file mode 100644
index 0000000..5b94ac5
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_color-contrast.test.scss
@@ -0,0 +1,139 @@
+@import "../../functions";
+@import "../../variables";
+@import "../../variables-dark";
+@import "../../maps";
+@import "../../mixins";
+
+@include describe("color-contrast function") {
+ @include it("should return a color when contrast ratio equals minimum requirement (WCAG 2.1 compliance)") {
+ // Test case: Background color that produces contrast ratio close to 4.5:1
+ // This tests the WCAG 2.1 requirement that contrast should be "at least 4.5:1" (>= 4.5)
+ // rather than "strictly greater than 4.5:1" (> 4.5)
+
+ // #777777 produces 4.4776:1 contrast ratio with white text
+ // Since this is below the 4.5:1 threshold, it should return the highest available contrast color
+ $test-background: #777;
+ $result: color-contrast($test-background);
+
+ @include assert-equal($result, $black, "Should return black (highest available contrast) for background with 4.4776:1 contrast ratio (below threshold)");
+ }
+
+ @include it("should return a color when contrast ratio is above minimum requirement") {
+ // Test case: Background color that produces contrast ratio above 4.5:1
+ // #767676 produces 4.5415:1 contrast ratio with white text
+ $test-background: #767676;
+ $result: color-contrast($test-background);
+
+ @include assert-equal($result, $white, "Should return white for background with 4.5415:1 contrast ratio (above threshold)");
+ }
+
+ @include it("should return a color when contrast ratio is below minimum requirement") {
+ // Test case: Background color that produces contrast ratio below 4.5:1
+ // #787878 produces 4.4155:1 contrast ratio with white text
+ $test-background: #787878;
+ $result: color-contrast($test-background);
+
+ // Should return the color with the highest available contrast ratio
+ @include assert-equal($result, $black, "Should return black (highest available contrast) for background with 4.4155:1 contrast ratio (below threshold)");
+ }
+
+ @include it("should handle edge case with very light background") {
+ // Test case: Very light background that should return dark text
+ $test-background: #f8f9fa; // Very light gray
+ $result: color-contrast($test-background);
+
+ @include assert-equal($result, $color-contrast-dark, "Should return dark text for very light background");
+ }
+
+ @include it("should handle edge case with very dark background") {
+ // Test case: Very dark background that should return light text
+ $test-background: #212529; // Very dark gray
+ $result: color-contrast($test-background);
+
+ @include assert-equal($result, $color-contrast-light, "Should return light text for very dark background");
+ }
+
+ @include it("should work with custom minimum contrast ratio") {
+ // Test case: Using a custom minimum contrast ratio
+ $test-background: #666;
+ $result: color-contrast($test-background, $color-contrast-dark, $color-contrast-light, 3);
+
+ @include assert-equal($result, $white, "Should return white when using custom minimum contrast ratio of 3.0");
+ }
+
+ @include it("should test contrast ratio calculation accuracy") {
+ // Test case: Verify that contrast-ratio function works correctly
+ $background: #767676;
+ $foreground: $white;
+ $ratio: contrast-ratio($background, $foreground);
+ // Bootstrap's implementation calculates this as ~4.5415, not exactly 4.5, due to its luminance math.
+ // We use 4.54 as the threshold for this test to match the actual implementation.
+ @include assert-true($ratio >= 4.54 and $ratio <= 4.55, "Contrast ratio should be approximately 4.54:1 (Bootstrap's math)");
+ }
+
+ @include it("should test luminance calculation") {
+ // Test case: Verify luminance function works correctly
+ $white-luminance: luminance($white);
+ $black-luminance: luminance($black);
+
+ @include assert-equal($white-luminance, 1, "White should have luminance of 1");
+ @include assert-equal($black-luminance, 0, "Black should have luminance of 0");
+ }
+
+ @include it("should handle rgba colors correctly") {
+ // Test case: Test with rgba colors
+ $test-background: rgba(118, 118, 118, 1); // Same as #767676
+ $result: color-contrast($test-background);
+
+ @include assert-equal($result, $white, "Should handle rgba colors correctly");
+ }
+
+ @include it("should test the WCAG 2.1 boundary condition with color below threshold") {
+ // Test case: Background color that produces contrast ratio below 4.5:1
+ // #787878 produces 4.4155:1 contrast ratio with white
+ $test-background: #787878; // Produces 4.4155:1 contrast ratio
+ $contrast-ratio: contrast-ratio($test-background, $white);
+
+ // Verify the contrast ratio is below 4.5:1
+ @include assert-true($contrast-ratio < 4.5, "Contrast ratio should be below 4.5:1 threshold");
+
+ // The color-contrast function should return the color with highest available contrast
+ $result: color-contrast($test-background);
+ @include assert-equal($result, $black, "color-contrast should return black (highest available contrast) for below-threshold ratio");
+ }
+
+ @include it("should test the WCAG 2.1 boundary condition with color at threshold") {
+ // Test case: Background color that produces contrast ratio close to 4.5:1
+ // #777777 produces 4.4776:1 contrast ratio with white
+ $test-background: #777; // Produces 4.4776:1 contrast ratio
+ $contrast-ratio: contrast-ratio($test-background, $white);
+
+ // Verify the contrast ratio is below 4.5:1 threshold
+ @include assert-true($contrast-ratio < 4.5, "Contrast ratio is below threshold, function should handle gracefully");
+ }
+
+ @include it("should demonstrate the difference between > and >= operators") {
+ // Test case: Demonstrates the difference between > and >= operators
+ // Uses #767676 with a custom minimum contrast ratio that matches its actual ratio (4.5415)
+ // With > 4.5415: should return black (fallback to highest available)
+ // With >= 4.5415: should return white (meets threshold)
+
+ $test-background: #767676; // Produces 4.5415:1 contrast ratio
+ $actual-ratio: contrast-ratio($test-background, $white);
+
+ // Test with a custom minimum that matches the actual ratio
+ $result: color-contrast($test-background, $color-contrast-dark, $color-contrast-light, $actual-ratio);
+
+ // Should return white when using >= implementation
+ @include assert-equal($result, $white, "color-contrast should return white when using exact ratio as threshold (>= implementation)");
+ }
+
+ @include it("should test additional working colors above threshold") {
+ // Test case: Background color that produces contrast ratio well above 4.5:1
+ // #757575 produces 4.6047:1 contrast ratio with white text
+ $test-background: #757575; // Produces 4.6047:1 contrast ratio
+ $result: color-contrast($test-background);
+
+ @include assert-equal($result, $white, "Should return white for background with 4.6047:1 contrast ratio (well above threshold)");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_color-modes.test.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_color-modes.test.scss
new file mode 100644
index 0000000..9ecc628
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_color-modes.test.scss
@@ -0,0 +1,69 @@
+// stylelint-disable selector-attribute-quotes
+
+@import "../../functions";
+@import "../../variables";
+@import "../../variables-dark";
+@import "../../maps";
+@import "../../mixins";
+
+@include describe("global $color-mode-type: data") {
+ @include it("generates data attribute selectors for dark mode") {
+ @include assert() {
+ @include output() {
+ @include color-mode(dark) {
+ .element {
+ color: var(--bs-primary-text-emphasis);
+ background-color: var(--bs-primary-bg-subtle);
+ }
+ }
+ @include color-mode(dark, true) {
+ --custom-color: #{mix($indigo, $blue, 50%)};
+ }
+ }
+ @include expect() {
+ [data-bs-theme=dark] .element {
+ color: var(--bs-primary-text-emphasis);
+ background-color: var(--bs-primary-bg-subtle);
+ }
+ [data-bs-theme=dark] {
+ --custom-color: #3a3ff8;
+ }
+ }
+ }
+ }
+}
+
+@include describe("global $color-mode-type: media-query") {
+ @include it("generates media queries for dark mode") {
+ $color-mode-type: media-query !global;
+
+ @include assert() {
+ @include output() {
+ @include color-mode(dark) {
+ .element {
+ color: var(--bs-primary-text-emphasis);
+ background-color: var(--bs-primary-bg-subtle);
+ }
+ }
+ @include color-mode(dark, true) {
+ --custom-color: #{mix($indigo, $blue, 50%)};
+ }
+ }
+ @include expect() {
+ @media (prefers-color-scheme: dark) {
+ .element {
+ color: var(--bs-primary-text-emphasis);
+ background-color: var(--bs-primary-bg-subtle);
+ }
+ }
+ @media (prefers-color-scheme: dark) {
+ :root {
+ --custom-color: #3a3ff8;
+ }
+ }
+ }
+ }
+
+ $color-mode-type: data !global;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_media-query-color-mode-full.test.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_media-query-color-mode-full.test.scss
new file mode 100644
index 0000000..00ed82d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_media-query-color-mode-full.test.scss
@@ -0,0 +1,8 @@
+$color-mode-type: media-query;
+
+@import "../../bootstrap";
+
+@include describe("global $color-mode-type: media-query") {
+ @include it("compiles entirely Bootstrap CSS with media-query color mode") { // stylelint-disable-line block-no-empty
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_utilities.test.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_utilities.test.scss
new file mode 100644
index 0000000..8140ac4
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/mixins/_utilities.test.scss
@@ -0,0 +1,393 @@
+$prefix: bs-;
+$enable-important-utilities: false;
+
+// Important: Do not import rfs to check that the mixin just calls the appropriate functions from it
+@import "../../mixins/utilities";
+
+@mixin test-generate-utility($params...) {
+ @include assert() {
+ @include output() {
+ @include generate-utility($params...);
+ }
+
+ @include expect() {
+ @content;
+ }
+ }
+}
+
+@include describe(generate-utility) {
+ @include it("generates a utility class for each value") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (small: .5rem, large: 2rem)
+ )
+ ) {
+ .padding-small {
+ padding: .5rem;
+ }
+
+ .padding-large {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include describe("global $enable-important-utilities: true") {
+ @include it("sets !important") {
+ $enable-important-utilities: true !global;
+
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (small: .5rem, large: 2rem)
+ )
+ ) {
+ .padding-small {
+ padding: .5rem !important;
+ }
+
+ .padding-large {
+ padding: 2rem !important;
+ }
+ }
+
+ $enable-important-utilities: false !global;
+ }
+ }
+
+ @include describe("$utility") {
+ @include describe("values") {
+ @include it("supports null keys") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (null: 1rem, small: .5rem, large: 2rem)
+ ),
+ ) {
+ .padding {
+ padding: 1rem;
+ }
+
+ .padding-small {
+ padding: .5rem;
+ }
+
+ .padding-large {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include it("ignores null values") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (small: null, large: 2rem)
+ )
+ ) {
+ .padding-large {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include it("supports lists") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: 1rem 2rem
+ )
+ ) {
+ .padding-1rem {
+ padding: 1rem;
+ }
+
+ .padding-2rem {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include it("supports single values") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem
+ )
+ ) {
+ .padding-1rem {
+ padding: 1rem;
+ }
+ }
+ }
+ }
+
+ @include describe("class & property") {
+ @include it("adds each property to the declaration") {
+ @include test-generate-utility(
+ (
+ class: padding-x,
+ property: padding-inline-start padding-inline-end,
+ values: 1rem
+ )
+ ) {
+ .padding-x-1rem {
+ padding-inline-start: 1rem;
+ padding-inline-end: 1rem;
+ }
+ }
+ }
+
+ @include it("uses the first property as class name") {
+ @include test-generate-utility(
+ (
+ property: padding-inline-start padding-inline-end,
+ values: 1rem
+ )
+ ) {
+ .padding-inline-start-1rem {
+ padding-inline-start: 1rem;
+ padding-inline-end: 1rem;
+ }
+ }
+ }
+
+ @include it("supports a null class to create classes straight from the values") {
+ @include test-generate-utility(
+ (
+ property: visibility,
+ class: null,
+ values: (
+ visible: visible,
+ invisible: hidden,
+ )
+ )
+ ) {
+ .visible {
+ visibility: visible;
+ }
+
+ .invisible {
+ visibility: hidden;
+ }
+ }
+ }
+ }
+
+ @include describe("state") {
+ @include it("Generates selectors for each states") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem,
+ state: hover focus,
+ )
+ ) {
+ .padding-1rem {
+ padding: 1rem;
+ }
+
+ .padding-1rem-hover:hover {
+ padding: 1rem;
+ }
+
+ .padding-1rem-focus:focus {
+ padding: 1rem;
+ }
+ }
+ }
+ }
+
+ @include describe("css-var"){
+ @include it("sets a CSS variable instead of the property") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ css-variable-name: padding,
+ css-var: true,
+ values: 1rem 2rem
+ )
+ ) {
+ .padding-1rem {
+ --bs-padding: 1rem;
+ }
+
+ .padding-2rem {
+ --bs-padding: 2rem;
+ }
+ }
+ }
+
+ @include it("defaults to class") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ class: padding,
+ css-var: true,
+ values: 1rem 2rem
+ )
+ ) {
+ .padding-1rem {
+ --bs-padding: 1rem;
+ }
+
+ .padding-2rem {
+ --bs-padding: 2rem;
+ }
+ }
+ }
+ }
+
+ @include describe("local-vars") {
+ @include it("generates the listed variables") {
+ @include test-generate-utility(
+ (
+ property: color,
+ class: desaturated-color,
+ local-vars: (
+ color-opacity: 1,
+ color-saturation: .25
+ ),
+ values: (
+ blue: hsla(192deg, var(--bs-color-saturation), 0, var(--bs-color-opacity))
+ )
+ )
+ ) {
+ .desaturated-color-blue {
+ --bs-color-opacity: 1;
+ // Sass compilation will put a leading zero so we want to keep that one
+ // stylelint-disable-next-line @stylistic/number-leading-zero
+ --bs-color-saturation: 0.25;
+ color: hsla(192deg, var(--bs-color-saturation), 0, var(--bs-color-opacity));
+ }
+ }
+ }
+ }
+
+ @include describe("css-var & state") {
+ @include it("Generates a rule with for each state with a CSS variable") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ css-var: true,
+ css-variable-name: padding,
+ values: 1rem,
+ state: hover focus,
+ )
+ ) {
+ .padding-1rem {
+ --bs-padding: 1rem;
+ }
+
+ .padding-1rem-hover:hover {
+ --bs-padding: 1rem;
+ }
+
+ .padding-1rem-focus:focus {
+ --bs-padding: 1rem;
+ }
+ }
+ }
+ }
+
+ @include describe("rtl") {
+ @include it("sets up RTLCSS for removal when false") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem,
+ rtl: false
+ )
+ ) {
+ /* rtl:begin:remove */
+
+ .padding-1rem {
+ padding: 1rem;
+ }
+
+ /* rtl:end:remove */
+
+ }
+ }
+ }
+
+ @include describe("rfs") {
+ @include it("sets the fluid value when not inside media query") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem,
+ rfs: true
+ )
+ ) {
+ .padding-1rem {
+ padding: rfs-fluid-value(1rem);
+ }
+ }
+ }
+
+ @include it("sets the value when inside the media query") {
+ @include test-generate-utility(
+ (
+ property: padding,
+ values: 1rem,
+ rfs: true
+ ),
+ $is-rfs-media-query: true
+ ) {
+ .padding-1rem {
+ padding: rfs-value(1rem);
+ }
+ }
+ }
+ }
+ }
+
+ @include describe("$infix") {
+ @include it("inserts the given infix") {
+ @include test-generate-utility(
+ (
+ property: "padding",
+ values: (null: 1rem, small: .5rem, large: 2rem)
+ ),
+ $infix: -sm
+ ) {
+ .padding-sm {
+ padding: 1rem;
+ }
+
+ .padding-sm-small {
+ padding: .5rem;
+ }
+
+ .padding-sm-large {
+ padding: 2rem;
+ }
+ }
+ }
+
+ @include it("strips leading - if class is null") {
+ @include test-generate-utility(
+ (
+ property: visibility,
+ class: null,
+ values: (
+ visible: visible,
+ invisible: hidden,
+ )
+ ),
+ -sm
+ ) {
+ .sm-visible {
+ visibility: visible;
+ }
+
+ .sm-invisible {
+ visibility: hidden;
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/sass-true/register.js b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/sass-true/register.js
new file mode 100644
index 0000000..d93e414
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/sass-true/register.js
@@ -0,0 +1,14 @@
+'use strict'
+
+const path = require('node:path')
+
+const runnerPath = path.join(__dirname, 'runner').replace(/\\/g, '/')
+
+require.extensions['.scss'] = (module, filename) => {
+ const normalizedFilename = filename.replace(/\\/g, '/')
+
+ return module._compile(`
+ const runner = require('${runnerPath}')
+ runner('${normalizedFilename}', { describe, it })
+ `, filename)
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/sass-true/runner.js b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/sass-true/runner.js
new file mode 100644
index 0000000..bef870a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/sass-true/runner.js
@@ -0,0 +1,17 @@
+'use strict'
+
+const fs = require('node:fs')
+const path = require('node:path')
+const { runSass } = require('sass-true')
+
+module.exports = (filename, { describe, it }) => {
+ const data = fs.readFileSync(filename, 'utf8')
+ const TRUE_SETUP = '$true-terminal-output: false; @import "true";'
+ const sassString = TRUE_SETUP + data
+
+ runSass(
+ { describe, it, sourceType: 'string' },
+ sassString,
+ { loadPaths: [path.dirname(filename)] }
+ )
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/utilities/_api.test.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/utilities/_api.test.scss
new file mode 100644
index 0000000..304d8d1
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/tests/utilities/_api.test.scss
@@ -0,0 +1,75 @@
+@import "../../functions";
+@import "../../variables";
+@import "../../variables-dark";
+@import "../../maps";
+@import "../../mixins";
+
+$utilities: ();
+
+@include describe("utilities/api") {
+ @include it("generates utilities for each breakpoints") {
+ $utilities: (
+ margin: (
+ property: margin,
+ values: auto
+ ),
+ padding: (
+ property: padding,
+ responsive: true,
+ values: 1rem
+ ),
+ font-size: (
+ property: font-size,
+ values: (large: 1.25rem),
+ print: true
+ )
+ ) !global;
+
+ $grid-breakpoints: (
+ xs: 0,
+ sm: 333px,
+ md: 666px
+ ) !global;
+
+ @include assert() {
+ @include output() {
+ @import "../../utilities/api";
+ }
+
+ @include expect() {
+ // margin is not set to responsive
+ .margin-auto {
+ margin: auto !important;
+ }
+
+ // padding is, though
+ .padding-1rem {
+ padding: 1rem !important;
+ }
+
+ .font-size-large {
+ font-size: 1.25rem !important;
+ }
+
+ @media (min-width: 333px) {
+ .padding-sm-1rem {
+ padding: 1rem !important;
+ }
+ }
+
+ @media (min-width: 666px) {
+ .padding-md-1rem {
+ padding: 1rem !important;
+ }
+ }
+
+ @media print {
+ .font-size-print-large {
+ font-size: 1.25rem !important;
+ }
+ }
+ }
+
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/utilities/_api.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/utilities/_api.scss
new file mode 100644
index 0000000..62e1d39
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/utilities/_api.scss
@@ -0,0 +1,47 @@
+// Loop over each breakpoint
+@each $breakpoint in map-keys($grid-breakpoints) {
+
+ // Generate media query if needed
+ @include media-breakpoint-up($breakpoint) {
+ $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+
+ // Loop over each utility property
+ @each $key, $utility in $utilities {
+ // The utility can be disabled with `false`, thus check if the utility is a map first
+ // Only proceed if responsive media queries are enabled or if it's the base media query
+ @if type-of($utility) == "map" and (map-get($utility, responsive) or $infix == "") {
+ @include generate-utility($utility, $infix);
+ }
+ }
+ }
+}
+
+// RFS rescaling
+@media (min-width: $rfs-mq-value) {
+ @each $breakpoint in map-keys($grid-breakpoints) {
+ $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
+
+ @if (map-get($grid-breakpoints, $breakpoint) < $rfs-breakpoint) {
+ // Loop over each utility property
+ @each $key, $utility in $utilities {
+ // The utility can be disabled with `false`, thus check if the utility is a map first
+ // Only proceed if responsive media queries are enabled or if it's the base media query
+ @if type-of($utility) == "map" and map-get($utility, rfs) and (map-get($utility, responsive) or $infix == "") {
+ @include generate-utility($utility, $infix, true);
+ }
+ }
+ }
+ }
+}
+
+
+// Print utilities
+@media print {
+ @each $key, $utility in $utilities {
+ // The utility can be disabled with `false`, thus check if the utility is a map first
+ // Then check if the utility needs print styles
+ @if type-of($utility) == "map" and map-get($utility, print) == true {
+ @include generate-utility($utility, "-print");
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/vendor/_rfs.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/vendor/_rfs.scss
new file mode 100644
index 0000000..aa1f82b
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bootstrap-5.3.8/vendor/_rfs.scss
@@ -0,0 +1,348 @@
+// stylelint-disable scss/dimension-no-non-numeric-values
+
+// SCSS RFS mixin
+//
+// Automated responsive values for font sizes, paddings, margins and much more
+//
+// Licensed under MIT (https://github.com/twbs/rfs/blob/main/LICENSE)
+
+// Configuration
+
+// Base value
+$rfs-base-value: 1.25rem !default;
+$rfs-unit: rem !default;
+
+@if $rfs-unit != rem and $rfs-unit != px {
+ @error "`#{$rfs-unit}` is not a valid unit for $rfs-unit. Use `px` or `rem`.";
+}
+
+// Breakpoint at where values start decreasing if screen width is smaller
+$rfs-breakpoint: 1200px !default;
+$rfs-breakpoint-unit: px !default;
+
+@if $rfs-breakpoint-unit != px and $rfs-breakpoint-unit != em and $rfs-breakpoint-unit != rem {
+ @error "`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.";
+}
+
+// Resize values based on screen height and width
+$rfs-two-dimensional: false !default;
+
+// Factor of decrease
+$rfs-factor: 10 !default;
+
+@if type-of($rfs-factor) != number or $rfs-factor <= 1 {
+ @error "`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.";
+}
+
+// Mode. Possibilities: "min-media-query", "max-media-query"
+$rfs-mode: min-media-query !default;
+
+// Generate enable or disable classes. Possibilities: false, "enable" or "disable"
+$rfs-class: false !default;
+
+// 1 rem = $rfs-rem-value px
+$rfs-rem-value: 16 !default;
+
+// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14
+$rfs-safari-iframe-resize-bug-fix: false !default;
+
+// Disable RFS by setting $enable-rfs to false
+$enable-rfs: true !default;
+
+// Cache $rfs-base-value unit
+$rfs-base-value-unit: unit($rfs-base-value);
+
+@function divide($dividend, $divisor, $precision: 10) {
+ $sign: if($dividend > 0 and $divisor > 0 or $dividend < 0 and $divisor < 0, 1, -1);
+ $dividend: abs($dividend);
+ $divisor: abs($divisor);
+ @if $dividend == 0 {
+ @return 0;
+ }
+ @if $divisor == 0 {
+ @error "Cannot divide by 0";
+ }
+ $remainder: $dividend;
+ $result: 0;
+ $factor: 10;
+ @while ($remainder > 0 and $precision >= 0) {
+ $quotient: 0;
+ @while ($remainder >= $divisor) {
+ $remainder: $remainder - $divisor;
+ $quotient: $quotient + 1;
+ }
+ $result: $result * 10 + $quotient;
+ $factor: $factor * .1;
+ $remainder: $remainder * 10;
+ $precision: $precision - 1;
+ @if ($precision < 0 and $remainder >= $divisor * 5) {
+ $result: $result + 1;
+ }
+ }
+ $result: $result * $factor * $sign;
+ $dividend-unit: unit($dividend);
+ $divisor-unit: unit($divisor);
+ $unit-map: (
+ "px": 1px,
+ "rem": 1rem,
+ "em": 1em,
+ "%": 1%
+ );
+ @if ($dividend-unit != $divisor-unit and map-has-key($unit-map, $dividend-unit)) {
+ $result: $result * map-get($unit-map, $dividend-unit);
+ }
+ @return $result;
+}
+
+// Remove px-unit from $rfs-base-value for calculations
+@if $rfs-base-value-unit == px {
+ $rfs-base-value: divide($rfs-base-value, $rfs-base-value * 0 + 1);
+}
+@else if $rfs-base-value-unit == rem {
+ $rfs-base-value: divide($rfs-base-value, divide($rfs-base-value * 0 + 1, $rfs-rem-value));
+}
+
+// Cache $rfs-breakpoint unit to prevent multiple calls
+$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);
+
+// Remove unit from $rfs-breakpoint for calculations
+@if $rfs-breakpoint-unit-cache == px {
+ $rfs-breakpoint: divide($rfs-breakpoint, $rfs-breakpoint * 0 + 1);
+}
+@else if $rfs-breakpoint-unit-cache == rem or $rfs-breakpoint-unit-cache == "em" {
+ $rfs-breakpoint: divide($rfs-breakpoint, divide($rfs-breakpoint * 0 + 1, $rfs-rem-value));
+}
+
+// Calculate the media query value
+$rfs-mq-value: if($rfs-breakpoint-unit == px, #{$rfs-breakpoint}px, #{divide($rfs-breakpoint, $rfs-rem-value)}#{$rfs-breakpoint-unit});
+$rfs-mq-property-width: if($rfs-mode == max-media-query, max-width, min-width);
+$rfs-mq-property-height: if($rfs-mode == max-media-query, max-height, min-height);
+
+// Internal mixin used to determine which media query needs to be used
+@mixin _rfs-media-query {
+ @if $rfs-two-dimensional {
+ @if $rfs-mode == max-media-query {
+ @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}), (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {
+ @content;
+ }
+ }
+ @else {
+ @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) and (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {
+ @content;
+ }
+ }
+ }
+ @else {
+ @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) {
+ @content;
+ }
+ }
+}
+
+// Internal mixin that adds disable classes to the selector if needed.
+@mixin _rfs-rule {
+ @if $rfs-class == disable and $rfs-mode == max-media-query {
+ // Adding an extra class increases specificity, which prevents the media query to override the property
+ &,
+ .disable-rfs &,
+ &.disable-rfs {
+ @content;
+ }
+ }
+ @else if $rfs-class == enable and $rfs-mode == min-media-query {
+ .enable-rfs &,
+ &.enable-rfs {
+ @content;
+ }
+ } @else {
+ @content;
+ }
+}
+
+// Internal mixin that adds enable classes to the selector if needed.
+@mixin _rfs-media-query-rule {
+
+ @if $rfs-class == enable {
+ @if $rfs-mode == min-media-query {
+ @content;
+ }
+
+ @include _rfs-media-query () {
+ .enable-rfs &,
+ &.enable-rfs {
+ @content;
+ }
+ }
+ }
+ @else {
+ @if $rfs-class == disable and $rfs-mode == min-media-query {
+ .disable-rfs &,
+ &.disable-rfs {
+ @content;
+ }
+ }
+ @include _rfs-media-query () {
+ @content;
+ }
+ }
+}
+
+// Helper function to get the formatted non-responsive value
+@function rfs-value($values) {
+ // Convert to list
+ $values: if(type-of($values) != list, ($values,), $values);
+
+ $val: "";
+
+ // Loop over each value and calculate value
+ @each $value in $values {
+ @if $value == 0 {
+ $val: $val + " 0";
+ }
+ @else {
+ // Cache $value unit
+ $unit: if(type-of($value) == "number", unit($value), false);
+
+ @if $unit == px {
+ // Convert to rem if needed
+ $val: $val + " " + if($rfs-unit == rem, #{divide($value, $value * 0 + $rfs-rem-value)}rem, $value);
+ }
+ @else if $unit == rem {
+ // Convert to px if needed
+ $val: $val + " " + if($rfs-unit == px, #{divide($value, $value * 0 + 1) * $rfs-rem-value}px, $value);
+ } @else {
+ // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value
+ $val: $val + " " + $value;
+ }
+ }
+ }
+
+ // Remove first space
+ @return unquote(str-slice($val, 2));
+}
+
+// Helper function to get the responsive value calculated by RFS
+@function rfs-fluid-value($values) {
+ // Convert to list
+ $values: if(type-of($values) != list, ($values,), $values);
+
+ $val: "";
+
+ // Loop over each value and calculate value
+ @each $value in $values {
+ @if $value == 0 {
+ $val: $val + " 0";
+ } @else {
+ // Cache $value unit
+ $unit: if(type-of($value) == "number", unit($value), false);
+
+ // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value
+ @if not $unit or $unit != px and $unit != rem {
+ $val: $val + " " + $value;
+ } @else {
+ // Remove unit from $value for calculations
+ $value: divide($value, $value * 0 + if($unit == px, 1, divide(1, $rfs-rem-value)));
+
+ // Only add the media query if the value is greater than the minimum value
+ @if abs($value) <= $rfs-base-value or not $enable-rfs {
+ $val: $val + " " + if($rfs-unit == rem, #{divide($value, $rfs-rem-value)}rem, #{$value}px);
+ }
+ @else {
+ // Calculate the minimum value
+ $value-min: $rfs-base-value + divide(abs($value) - $rfs-base-value, $rfs-factor);
+
+ // Calculate difference between $value and the minimum value
+ $value-diff: abs($value) - $value-min;
+
+ // Base value formatting
+ $min-width: if($rfs-unit == rem, #{divide($value-min, $rfs-rem-value)}rem, #{$value-min}px);
+
+ // Use negative value if needed
+ $min-width: if($value < 0, -$min-width, $min-width);
+
+ // Use `vmin` if two-dimensional is enabled
+ $variable-unit: if($rfs-two-dimensional, vmin, vw);
+
+ // Calculate the variable width between 0 and $rfs-breakpoint
+ $variable-width: #{divide($value-diff * 100, $rfs-breakpoint)}#{$variable-unit};
+
+ // Return the calculated value
+ $val: $val + " calc(" + $min-width + if($value < 0, " - ", " + ") + $variable-width + ")";
+ }
+ }
+ }
+ }
+
+ // Remove first space
+ @return unquote(str-slice($val, 2));
+}
+
+// RFS mixin
+@mixin rfs($values, $property: font-size) {
+ @if $values != null {
+ $val: rfs-value($values);
+ $fluid-val: rfs-fluid-value($values);
+
+ // Do not print the media query if responsive & non-responsive values are the same
+ @if $val == $fluid-val {
+ #{$property}: $val;
+ }
+ @else {
+ @include _rfs-rule () {
+ #{$property}: if($rfs-mode == max-media-query, $val, $fluid-val);
+
+ // Include safari iframe resize fix if needed
+ min-width: if($rfs-safari-iframe-resize-bug-fix, (0 * 1vw), null);
+ }
+
+ @include _rfs-media-query-rule () {
+ #{$property}: if($rfs-mode == max-media-query, $fluid-val, $val);
+ }
+ }
+ }
+}
+
+// Shorthand helper mixins
+@mixin font-size($value) {
+ @include rfs($value);
+}
+
+@mixin padding($value) {
+ @include rfs($value, padding);
+}
+
+@mixin padding-top($value) {
+ @include rfs($value, padding-top);
+}
+
+@mixin padding-right($value) {
+ @include rfs($value, padding-right);
+}
+
+@mixin padding-bottom($value) {
+ @include rfs($value, padding-bottom);
+}
+
+@mixin padding-left($value) {
+ @include rfs($value, padding-left);
+}
+
+@mixin margin($value) {
+ @include rfs($value, margin);
+}
+
+@mixin margin-top($value) {
+ @include rfs($value, margin-top);
+}
+
+@mixin margin-right($value) {
+ @include rfs($value, margin-right);
+}
+
+@mixin margin-bottom($value) {
+ @include rfs($value, margin-bottom);
+}
+
+@mixin margin-left($value) {
+ @include rfs($value, margin-left);
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/_index.scss
new file mode 100644
index 0000000..82310cb
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/_index.scss
@@ -0,0 +1,10 @@
+@forward "utilities";
+@forward "themes";
+@forward "base";
+@forward "elements";
+@forward "form";
+@forward "components";
+@forward "grid";
+@forward "layout";
+@forward "base/skeleton";
+@forward "helpers";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/_index.scss
new file mode 100644
index 0000000..4416b1f
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/_index.scss
@@ -0,0 +1,6 @@
+/* Bulma Base */
+@charset "utf-8";
+
+@forward "minireset";
+@forward "generic";
+@forward "animations";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/animations.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/animations.scss
new file mode 100644
index 0000000..667124c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/animations.scss
@@ -0,0 +1,15 @@
+@keyframes spinAround {
+ from {
+ transform: rotate(0deg);
+ }
+
+ to {
+ transform: rotate(359deg);
+ }
+}
+
+@keyframes pulsate {
+ 50% {
+ opacity: 0.5;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/generic.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/generic.scss
new file mode 100644
index 0000000..b004246
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/generic.scss
@@ -0,0 +1,240 @@
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/css-variables.scss" as cv;
+@use "../utilities/mixins" as mx;
+
+$body-background-color: cv.getVar("scheme-main") !default;
+$body-size: 1em !default;
+$body-min-width: 300px !default;
+$body-rendering: optimizeLegibility !default;
+$body-family: cv.getVar("family-primary") !default;
+$body-overflow-x: hidden !default;
+$body-overflow-y: scroll !default;
+
+$body-color: cv.getVar("text") !default;
+$body-font-size: 1em !default;
+$body-weight: cv.getVar("weight-normal") !default;
+$body-line-height: 1.5 !default;
+
+$code-family: cv.getVar("family-code") !default;
+$code-padding: 0.25em 0.5em 0.25em !default;
+$code-weight: normal !default;
+$code-size: 0.875em !default;
+
+$small-font-size: 0.875em !default;
+
+$hr-background-color: cv.getVar("background") !default;
+$hr-height: 2px !default;
+$hr-margin: 1.5rem 0 !default;
+
+$strong-color: cv.getVar("text-strong") !default;
+$strong-weight: cv.getVar("weight-semibold") !default;
+
+$pre-font-size: 0.875em !default;
+$pre-padding: 1.25rem 1.5rem !default;
+$pre-code-font-size: 1em !default;
+
+#{iv.$variables-host} {
+ @include cv.register-vars(
+ (
+ "body-background-color": #{$body-background-color},
+ "body-size": #{$body-size},
+ "body-min-width": #{$body-min-width},
+ "body-rendering": #{$body-rendering},
+ "body-family": #{$body-family},
+ "body-overflow-x": #{$body-overflow-x},
+ "body-overflow-y": #{$body-overflow-y},
+ "body-color": #{$body-color},
+ "body-font-size": #{$body-font-size},
+ "body-weight": #{$body-weight},
+ "body-line-height": #{$body-line-height},
+ "code-family": #{$code-family},
+ "code-padding": #{$code-padding},
+ "code-weight": #{$code-weight},
+ "code-size": #{$code-size},
+ "small-font-size": #{$small-font-size},
+ "hr-background-color": #{$hr-background-color},
+ "hr-height": #{$hr-height},
+ "hr-margin": #{$hr-margin},
+ "strong-color": #{$strong-color},
+ "strong-weight": #{$strong-weight},
+ "pre-font-size": #{$pre-font-size},
+ "pre-padding": #{$pre-padding},
+ "pre-code-font-size": #{$pre-code-font-size},
+ )
+ );
+}
+
+html {
+ background-color: cv.getVar("body-background-color");
+ font-size: cv.getVar("body-size");
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ min-width: cv.getVar("body-min-width");
+ overflow-x: cv.getVar("body-overflow-x");
+ overflow-y: cv.getVar("body-overflow-y");
+ text-rendering: cv.getVar("body-rendering");
+ text-size-adjust: 100%;
+}
+
+article,
+aside,
+figure,
+footer,
+header,
+hgroup,
+section {
+ display: block;
+}
+
+body,
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: cv.getVar("body-family");
+}
+
+code,
+pre {
+ -moz-osx-font-smoothing: auto;
+ -webkit-font-smoothing: auto;
+ font-family: cv.getVar("code-family");
+}
+
+body {
+ color: cv.getVar("body-color");
+ font-size: cv.getVar("body-font-size");
+ font-weight: cv.getVar("body-weight");
+ line-height: cv.getVar("body-line-height");
+}
+
+// Inline
+
+a,
+button {
+ cursor: pointer;
+
+ &:focus-visible {
+ outline-color: hsl(
+ cv.getVar("focus-h"),
+ cv.getVar("focus-s"),
+ cv.getVar("focus-l")
+ );
+ outline-offset: cv.getVar("focus-offset");
+ outline-style: cv.getVar("focus-style");
+ outline-width: cv.getVar("focus-width");
+
+ &:active {
+ outline-width: 1px;
+ }
+ }
+
+ &:active {
+ outline-width: 1px;
+ }
+}
+
+a {
+ color: cv.getVar("link-text");
+ cursor: pointer;
+ text-decoration: none;
+ transition-duration: cv.getVar("duration");
+ transition-property: background-color, border-color, color;
+
+ strong {
+ color: currentColor;
+ }
+}
+
+button {
+ @include mx.reset;
+ transition-duration: cv.getVar("duration");
+ transition-property: background-color, border-color, color;
+}
+
+code {
+ background-color: cv.getVar("code-background");
+ border-radius: 0.5em;
+ color: cv.getVar("code");
+ font-size: cv.getVar("code-size");
+ font-weight: cv.getVar("code-weight");
+ padding: cv.getVar("code-padding");
+}
+
+hr {
+ background-color: cv.getVar("hr-background-color");
+ border: none;
+ display: block;
+ height: cv.getVar("hr-height");
+ margin: cv.getVar("hr-margin");
+}
+
+img {
+ height: auto;
+ max-width: 100%;
+}
+
+input[type="checkbox"],
+input[type="radio"] {
+ vertical-align: baseline;
+}
+
+small {
+ font-size: cv.getVar("small-font-size");
+}
+
+span {
+ font-style: inherit;
+ font-weight: inherit;
+}
+
+strong {
+ color: cv.getVar("strong-color");
+ font-weight: cv.getVar("strong-weight");
+}
+
+svg {
+ height: auto;
+ width: auto;
+}
+
+// Block
+
+fieldset {
+ border: none;
+}
+
+pre {
+ @include mx.overflow-touch;
+
+ background-color: cv.getVar("pre-background");
+ color: cv.getVar("pre");
+ font-size: cv.getVar("pre-font-size");
+ overflow-x: auto;
+ padding: cv.getVar("pre-padding");
+ white-space: pre;
+ word-wrap: normal;
+
+ code {
+ background-color: transparent;
+ color: currentColor;
+ font-size: cv.getVar("pre-code-font-size");
+ padding: 0;
+ }
+}
+
+table {
+ td,
+ th {
+ vertical-align: top;
+
+ &:not([align]) {
+ text-align: inherit;
+ }
+ }
+
+ th {
+ color: cv.getVar("text-strong");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/minireset.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/minireset.scss
new file mode 100644
index 0000000..5b09693
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/minireset.scss
@@ -0,0 +1,92 @@
+/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */
+// Blocks
+html,
+body,
+p,
+ol,
+ul,
+li,
+dl,
+dt,
+dd,
+blockquote,
+figure,
+fieldset,
+legend,
+textarea,
+pre,
+iframe,
+hr,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ margin: 0;
+ padding: 0;
+}
+
+// Headings
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-size: 100%;
+ font-weight: normal;
+}
+
+// List
+ul {
+ list-style: none;
+}
+
+// Form
+button,
+input,
+select,
+textarea {
+ margin: 0;
+}
+
+// Box sizing
+html {
+ box-sizing: border-box;
+}
+
+* {
+ &,
+ &::before,
+ &::after {
+ box-sizing: inherit;
+ }
+}
+
+// Media
+img,
+video {
+ height: auto;
+ max-width: 100%;
+}
+
+// Iframe
+iframe {
+ border: 0;
+}
+
+// Table
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+
+ &:not([align]) {
+ text-align: inherit;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/skeleton.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/skeleton.scss
new file mode 100644
index 0000000..f5c1d04
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/base/skeleton.scss
@@ -0,0 +1,114 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/mixins" as mx;
+@use "../utilities/extends";
+
+$skeleton-background: cv.getVar("border") !default;
+$skeleton-radius: cv.getVar("radius-small") !default;
+$skeleton-block-min-height: 4.5em !default;
+$skeleton-lines-gap: 0.75em !default;
+$skeleton-line-height: 0.75em !default;
+
+#{iv.$variables-host} {
+ @include cv.register-vars(
+ (
+ "skeleton-background": #{$skeleton-background},
+ "skeleton-radius": #{$skeleton-radius},
+ "skeleton-block-min-height": #{$skeleton-block-min-height},
+ "skeleton-lines-gap": #{$skeleton-lines-gap},
+ "skeleton-line-height": #{$skeleton-line-height},
+ )
+ );
+}
+
+%skeleton-pulsation {
+ animation-duration: 2s;
+ animation-iteration-count: infinite;
+ animation-name: pulsate;
+ animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1);
+ background-color: cv.getVar("skeleton-background");
+ border-radius: cv.getVar("skeleton-radius");
+ box-shadow: none;
+ pointer-events: none;
+}
+
+.#{iv.$class-prefix}is-skeleton {
+ @extend %skeleton-pulsation;
+ color: transparent !important;
+
+ em,
+ strong {
+ color: inherit;
+ }
+
+ img {
+ visibility: hidden;
+ }
+
+ &.#{iv.$class-prefix}checkbox {
+ input {
+ opacity: 0;
+ }
+ }
+
+ &.#{iv.$class-prefix}delete {
+ border-radius: cv.getVar("radius-rounded");
+
+ &::before,
+ &::after {
+ display: none;
+ }
+ }
+}
+
+input.#{iv.$class-prefix}is-skeleton,
+textarea.#{iv.$class-prefix}is-skeleton {
+ resize: none;
+
+ @include mx.placeholder {
+ color: transparent !important;
+ }
+}
+
+.#{iv.$class-prefix}has-skeleton {
+ color: transparent !important;
+ position: relative;
+
+ &::after {
+ @extend %skeleton-pulsation;
+ content: "";
+ display: block;
+ height: 100%;
+ left: 0;
+ max-width: 100%;
+ min-width: 10%;
+ position: absolute;
+ top: 0;
+ width: 7em;
+ }
+}
+
+.#{iv.$class-prefix}skeleton-block {
+ @extend %block;
+ @extend %skeleton-pulsation;
+ color: transparent !important;
+ min-height: cv.getVar("skeleton-block-min-height");
+}
+
+.#{iv.$class-prefix}skeleton-lines {
+ color: transparent !important;
+ display: flex;
+ flex-direction: column;
+ gap: cv.getVar("skeleton-lines-gap");
+ position: relative;
+
+ > div {
+ @extend %skeleton-pulsation;
+ height: cv.getVar("skeleton-line-height");
+
+ &:last-child {
+ min-width: 4em;
+ width: 30%;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/_index.scss
new file mode 100644
index 0000000..2decd67
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/_index.scss
@@ -0,0 +1,13 @@
+/* Bulma Components */
+@charset "utf-8";
+
+@forward "breadcrumb";
+@forward "card";
+@forward "dropdown";
+@forward "menu";
+@forward "message";
+@forward "modal";
+@forward "navbar";
+@forward "pagination";
+@forward "panel";
+@forward "tabs";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/breadcrumb.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/breadcrumb.scss
new file mode 100644
index 0000000..bd261fb
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/breadcrumb.scss
@@ -0,0 +1,139 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins";
+
+$breadcrumb-item-color: cv.getVar("link-text") !default;
+$breadcrumb-item-hover-color: cv.getVar("link-text-hover") !default;
+$breadcrumb-item-active-color: cv.getVar("link-text-active") !default;
+
+$breadcrumb-item-padding-vertical: 0 !default;
+$breadcrumb-item-padding-horizontal: 0.75em !default;
+
+$breadcrumb-item-separator-color: cv.getVar("border") !default;
+
+.#{iv.$class-prefix}breadcrumb {
+ @include cv.register-vars(
+ (
+ "breadcrumb-item-color": #{$breadcrumb-item-color},
+ "breadcrumb-item-hover-color": #{$breadcrumb-item-hover-color},
+ "breadcrumb-item-active-color": #{$breadcrumb-item-active-color},
+ "breadcrumb-item-padding-vertical": #{$breadcrumb-item-padding-vertical},
+ "breadcrumb-item-padding-horizontal": #{$breadcrumb-item-padding-horizontal},
+ "breadcrumb-item-separator-color": #{$breadcrumb-item-separator-color},
+ )
+ );
+}
+
+.#{iv.$class-prefix}breadcrumb {
+ @extend %block;
+ @extend %unselectable;
+ font-size: cv.getVar("size-normal");
+ white-space: nowrap;
+
+ a {
+ align-items: center;
+ color: cv.getVar("breadcrumb-item-color");
+ display: flex;
+ justify-content: center;
+ padding: cv.getVar("breadcrumb-item-padding-vertical")
+ cv.getVar("breadcrumb-item-padding-horizontal");
+
+ &:hover {
+ color: cv.getVar("breadcrumb-item-hover-color");
+ }
+ }
+
+ li {
+ align-items: center;
+ display: flex;
+
+ &:first-child a {
+ padding-inline-start: 0;
+ }
+
+ &.#{iv.$class-prefix}is-active {
+ a {
+ color: cv.getVar("breadcrumb-item-active-color");
+ cursor: default;
+ pointer-events: none;
+ }
+ }
+
+ & + li::before {
+ color: cv.getVar("breadcrumb-item-separator-color");
+ content: "/";
+ }
+ }
+
+ ul,
+ ol {
+ align-items: flex-start;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ }
+
+ .#{iv.$class-prefix}icon {
+ &:first-child {
+ margin-inline-end: 0.5em;
+ }
+
+ &:last-child {
+ margin-inline-start: 0.5em;
+ }
+ }
+
+ // Alignment
+ &.#{iv.$class-prefix}is-centered {
+ ol,
+ ul {
+ justify-content: center;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-right {
+ ol,
+ ul {
+ justify-content: flex-end;
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-large");
+ }
+
+ // Styles
+ &.#{iv.$class-prefix}has-arrow-separator {
+ li + li::before {
+ content: "→";
+ }
+ }
+
+ &.#{iv.$class-prefix}has-bullet-separator {
+ li + li::before {
+ content: "•";
+ }
+ }
+
+ &.#{iv.$class-prefix}has-dot-separator {
+ li + li::before {
+ content: "·";
+ }
+ }
+
+ &.#{iv.$class-prefix}has-succeeds-separator {
+ li + li::before {
+ content: "≻";
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/card.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/card.scss
new file mode 100644
index 0000000..0b3b2c5
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/card.scss
@@ -0,0 +1,162 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$card-color: cv.getVar("text") !default;
+$card-background-color: cv.getVar("scheme-main") !default;
+$card-shadow: cv.getVar("shadow") !default;
+$card-radius: 0.75rem !default;
+
+$card-header-background-color: transparent !default;
+$card-header-color: cv.getVar("text-strong") !default;
+$card-header-padding: 0.75rem 1rem !default;
+$card-header-shadow: 0 0.125em 0.25em
+ hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")},
+ 0.1
+ ) !default;
+$card-header-weight: cv.getVar("weight-bold") !default;
+
+$card-content-background-color: transparent !default;
+$card-content-padding: 1.5rem !default;
+
+$card-footer-background-color: transparent !default;
+$card-footer-border-top: 1px solid cv.getVar("border-weak") !default;
+$card-footer-padding: 0.75rem !default;
+
+$card-media-margin: cv.getVar("block-spacing") !default;
+
+.#{iv.$class-prefix}card {
+ @include cv.register-vars(
+ (
+ "card-color": #{$card-color},
+ "card-background-color": #{$card-background-color},
+ "card-shadow": #{$card-shadow},
+ "card-radius": #{$card-radius},
+ "card-header-background-color": #{$card-header-background-color},
+ "card-header-color": #{$card-header-color},
+ "card-header-padding": #{$card-header-padding},
+ "card-header-shadow": #{$card-header-shadow},
+ "card-header-weight": #{$card-header-weight},
+ "card-content-background-color": #{$card-content-background-color},
+ "card-content-padding": #{$card-content-padding},
+ "card-footer-background-color": #{$card-footer-background-color},
+ "card-footer-border-top": #{$card-footer-border-top},
+ "card-footer-padding": #{$card-footer-padding},
+ "card-media-margin": #{$card-media-margin},
+ )
+ );
+}
+
+.#{iv.$class-prefix}card {
+ @extend %block;
+ background-color: cv.getVar("card-background-color");
+ border-radius: cv.getVar("card-radius");
+ box-shadow: cv.getVar("card-shadow");
+ color: cv.getVar("card-color");
+ max-width: 100%;
+ position: relative;
+}
+
+%card-item {
+ &:first-child {
+ border-start-start-radius: cv.getVar("card-radius");
+ border-start-end-radius: cv.getVar("card-radius");
+ }
+
+ &:last-child {
+ border-end-start-radius: cv.getVar("card-radius");
+ border-end-end-radius: cv.getVar("card-radius");
+ }
+}
+
+.#{iv.$class-prefix}card-header {
+ @extend %card-item;
+ background-color: cv.getVar("card-header-background-color");
+ align-items: stretch;
+ box-shadow: cv.getVar("card-header-shadow");
+ display: flex;
+}
+
+.#{iv.$class-prefix}card-header-title {
+ align-items: center;
+ color: cv.getVar("card-header-color");
+ display: flex;
+ flex-grow: 1;
+ font-weight: cv.getVar("card-header-weight");
+ padding: cv.getVar("card-header-padding");
+
+ &.#{iv.$class-prefix}is-centered {
+ justify-content: center;
+ }
+}
+
+.#{iv.$class-prefix}card-header-icon {
+ @include mx.reset;
+
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+ justify-content: center;
+ padding: cv.getVar("card-header-padding");
+}
+
+.#{iv.$class-prefix}card-image {
+ display: block;
+ position: relative;
+
+ &:first-child {
+ img {
+ border-start-start-radius: cv.getVar("card-radius");
+ border-start-end-radius: cv.getVar("card-radius");
+ }
+ }
+
+ &:last-child {
+ img {
+ border-end-start-radius: cv.getVar("card-radius");
+ border-end-end-radius: cv.getVar("card-radius");
+ }
+ }
+}
+
+.#{iv.$class-prefix}card-content {
+ @extend %card-item;
+
+ background-color: cv.getVar("card-content-background-color");
+ padding: cv.getVar("card-content-padding");
+}
+
+.#{iv.$class-prefix}card-footer {
+ @extend %card-item;
+
+ background-color: cv.getVar("card-footer-background-color");
+ border-top: cv.getVar("card-footer-border-top");
+ align-items: stretch;
+ display: flex;
+}
+
+.#{iv.$class-prefix}card-footer-item {
+ align-items: center;
+ display: flex;
+ flex-basis: 0;
+ flex-grow: 1;
+ flex-shrink: 0;
+ justify-content: center;
+ padding: cv.getVar("card-footer-padding");
+
+ &:not(:last-child) {
+ border-inline-end: cv.getVar("card-footer-border-top");
+ }
+}
+
+// Combinations
+
+.#{iv.$class-prefix}card {
+ .#{iv.$class-prefix}media:not(:last-child) {
+ margin-bottom: cv.getVar("card-media-margin");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/dropdown.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/dropdown.scss
new file mode 100644
index 0000000..415728b
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/dropdown.scss
@@ -0,0 +1,188 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$dropdown-menu-min-width: 12rem !default;
+
+$dropdown-content-background-color: cv.getVar("scheme-main") !default;
+$dropdown-content-offset: 0.25rem !default;
+$dropdown-content-padding-bottom: 0.5rem !default;
+$dropdown-content-padding-top: 0.5rem !default;
+$dropdown-content-radius: cv.getVar("radius") !default;
+$dropdown-content-shadow: cv.getVar("shadow") !default;
+$dropdown-content-z: 20 !default;
+
+$dropdown-item-h: cv.getVar("scheme-h");
+$dropdown-item-s: cv.getVar("scheme-s");
+$dropdown-item-l: cv.getVar("scheme-main-l");
+$dropdown-item-background-l: cv.getVar("scheme-main-l");
+$dropdown-item-background-l-delta: 0%;
+$dropdown-item-hover-background-l-delta: cv.getVar("hover-background-l-delta");
+$dropdown-item-active-background-l-delta: cv.getVar(
+ "active-background-l-delta"
+);
+$dropdown-item-color-l: cv.getVar("text-strong-l");
+$dropdown-item-selected-h: cv.getVar("link-h");
+$dropdown-item-selected-s: cv.getVar("link-s");
+$dropdown-item-selected-l: cv.getVar("link-l");
+$dropdown-item-selected-background-l: cv.getVar("link-l");
+$dropdown-item-selected-color-l: cv.getVar("link-invert-l");
+
+$dropdown-divider-background-color: cv.getVar("border-weak") !default;
+
+.#{iv.$class-prefix}dropdown {
+ // prettier-ignore-start
+ @include cv.register-vars(
+ (
+ "dropdown-menu-min-width": #{$dropdown-menu-min-width},
+ "dropdown-content-background-color": #{$dropdown-content-background-color},
+ "dropdown-content-offset": #{$dropdown-content-offset},
+ "dropdown-content-padding-bottom": #{$dropdown-content-padding-bottom},
+ "dropdown-content-padding-top": #{$dropdown-content-padding-top},
+ "dropdown-content-radius": #{$dropdown-content-radius},
+ "dropdown-content-shadow": #{$dropdown-content-shadow},
+ "dropdown-content-z": #{$dropdown-content-z},
+ "dropdown-item-h": #{$dropdown-item-h},
+ "dropdown-item-s": #{$dropdown-item-s},
+ "dropdown-item-l": #{$dropdown-item-l},
+ "dropdown-item-background-l": #{$dropdown-item-background-l},
+ "dropdown-item-background-l-delta": #{$dropdown-item-background-l-delta},
+ "dropdown-item-hover-background-l-delta": #{$dropdown-item-hover-background-l-delta},
+ "dropdown-item-active-background-l-delta": #{$dropdown-item-active-background-l-delta},
+ "dropdown-item-color-l": #{$dropdown-item-color-l},
+ "dropdown-item-selected-h": #{$dropdown-item-selected-h},
+ "dropdown-item-selected-s": #{$dropdown-item-selected-s},
+ "dropdown-item-selected-l": #{$dropdown-item-selected-l},
+ "dropdown-item-selected-background-l": #{$dropdown-item-selected-background-l},
+ "dropdown-item-selected-color-l": #{$dropdown-item-selected-color-l},
+ "dropdown-divider-background-color": #{$dropdown-divider-background-color},
+ )
+ );
+ // prettier-ignore-end
+}
+
+.#{iv.$class-prefix}dropdown {
+ display: inline-flex;
+ position: relative;
+ vertical-align: top;
+
+ &.#{iv.$class-prefix}is-active,
+ &.#{iv.$class-prefix}is-hoverable:hover {
+ .#{iv.$class-prefix}dropdown-menu {
+ display: block;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-right {
+ .#{iv.$class-prefix}dropdown-menu {
+ left: auto;
+ right: 0;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-up {
+ .#{iv.$class-prefix}dropdown-menu {
+ bottom: 100%;
+ padding-bottom: cv.getVar("dropdown-content-offset");
+ padding-top: initial;
+ top: auto;
+ }
+ }
+}
+
+.#{iv.$class-prefix}dropdown-menu {
+ display: none;
+ @include mx.ltr-position(0, false);
+ min-width: cv.getVar("dropdown-menu-min-width");
+ padding-top: cv.getVar("dropdown-content-offset");
+ position: absolute;
+ top: 100%;
+ z-index: cv.getVar("dropdown-content-z");
+}
+
+.#{iv.$class-prefix}dropdown-content {
+ background-color: cv.getVar("dropdown-content-background-color");
+ border-radius: cv.getVar("dropdown-content-radius");
+ box-shadow: cv.getVar("dropdown-content-shadow");
+ padding-bottom: cv.getVar("dropdown-content-padding-bottom");
+ padding-top: cv.getVar("dropdown-content-padding-top");
+}
+
+.#{iv.$class-prefix}dropdown-item {
+ color: hsl(
+ #{cv.getVar("dropdown-item-h")},
+ #{cv.getVar("dropdown-item-s")},
+ #{cv.getVar("dropdown-item-color-l")}
+ );
+ display: block;
+ font-size: 0.875rem;
+ line-height: 1.5;
+ padding: 0.375rem 1rem;
+}
+
+a.#{iv.$class-prefix}dropdown-item,
+button.#{iv.$class-prefix}dropdown-item {
+ background-color: hsl(
+ #{cv.getVar("dropdown-item-h")},
+ #{cv.getVar("dropdown-item-s")},
+ calc(
+ #{cv.getVar("dropdown-item-background-l")} + #{cv.getVar(
+ "dropdown-item-background-l-delta"
+ )}
+ )
+ );
+ padding-inline-end: 3rem;
+ text-align: inherit;
+ white-space: nowrap;
+ width: 100%;
+
+ &:hover {
+ @include cv.register-vars(
+ (
+ "dropdown-item-background-l-delta": #{cv.getVar(
+ "dropdown-item-hover-background-l-delta"
+ )},
+ "dropdown-item-border-l-delta": #{cv.getVar(
+ "dropdown-item-hover-border-l-delta"
+ )},
+ )
+ );
+ }
+
+ &:active {
+ @include cv.register-vars(
+ (
+ "dropdown-item-background-l-delta": #{cv.getVar(
+ "dropdown-item-active-background-l-delta"
+ )},
+ "dropdown-item-border-l-delta": #{cv.getVar(
+ "dropdown-item-active-border-l-delta"
+ )},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}is-active,
+ &.#{iv.$class-prefix}is-selected {
+ @include cv.register-vars(
+ (
+ "dropdown-item-h": #{cv.getVar("dropdown-item-selected-h")},
+ "dropdown-item-s": #{cv.getVar("dropdown-item-selected-s")},
+ "dropdown-item-l": #{cv.getVar("dropdown-item-selected-l")},
+ "dropdown-item-background-l": #{cv.getVar(
+ "dropdown-item-selected-background-l"
+ )},
+ "dropdown-item-color-l": #{cv.getVar("dropdown-item-selected-color-l")},
+ )
+ );
+ }
+}
+
+.#{iv.$class-prefix}dropdown-divider {
+ background-color: cv.getVar("dropdown-divider-background-color");
+ border: none;
+ display: block;
+ height: 1px;
+ margin: 0.5rem 0;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/menu.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/menu.scss
new file mode 100644
index 0000000..2bee7d5
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/menu.scss
@@ -0,0 +1,165 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$menu-item-h: cv.getVar("scheme-h");
+$menu-item-s: cv.getVar("scheme-s");
+$menu-item-l: cv.getVar("scheme-main-l");
+$menu-item-background-l: cv.getVar("scheme-main-l");
+$menu-item-background-l-delta: 0%;
+$menu-item-hover-background-l-delta: cv.getVar("hover-background-l-delta");
+$menu-item-active-background-l-delta: cv.getVar("active-background-l-delta");
+$menu-item-color-l: cv.getVar("text-l");
+$menu-item-radius: cv.getVar("radius-small") !default;
+$menu-item-selected-h: cv.getVar("link-h");
+$menu-item-selected-s: cv.getVar("link-s");
+$menu-item-selected-l: cv.getVar("link-l");
+$menu-item-selected-background-l: cv.getVar("link-l");
+$menu-item-selected-color-l: cv.getVar("link-invert-l");
+
+$menu-list-border-left: 1px solid cv.getVar("border") !default;
+$menu-list-line-height: 1.25 !default;
+$menu-list-link-padding: 0.5em 0.75em !default;
+$menu-nested-list-margin: 0.75em !default;
+$menu-nested-list-padding-left: 0.75em !default;
+
+$menu-label-color: cv.getVar("text-weak") !default;
+$menu-label-font-size: 0.75em !default;
+$menu-label-letter-spacing: 0.1em !default;
+$menu-label-spacing: 1em !default;
+
+.#{iv.$class-prefix}menu {
+ @include cv.register-vars(
+ (
+ "menu-item-h": #{$menu-item-h},
+ "menu-item-s": #{$menu-item-s},
+ "menu-item-l": #{$menu-item-l},
+ "menu-item-background-l": #{$menu-item-background-l},
+ "menu-item-background-l-delta": #{$menu-item-background-l-delta},
+ "menu-item-hover-background-l-delta": #{$menu-item-hover-background-l-delta},
+ "menu-item-active-background-l-delta": #{$menu-item-active-background-l-delta},
+ "menu-item-color-l": #{$menu-item-color-l},
+ "menu-item-radius": #{$menu-item-radius},
+ "menu-item-selected-h": #{$menu-item-selected-h},
+ "menu-item-selected-s": #{$menu-item-selected-s},
+ "menu-item-selected-l": #{$menu-item-selected-l},
+ "menu-item-selected-background-l": #{$menu-item-selected-background-l},
+ "menu-item-selected-color-l": #{$menu-item-selected-color-l},
+ "menu-list-border-left": #{$menu-list-border-left},
+ "menu-list-line-height": #{$menu-list-line-height},
+ "menu-list-link-padding": #{$menu-list-link-padding},
+ "menu-nested-list-margin": #{$menu-nested-list-margin},
+ "menu-nested-list-padding-left": #{$menu-nested-list-padding-left},
+ "menu-label-color": #{$menu-label-color},
+ "menu-label-font-size": #{$menu-label-font-size},
+ "menu-label-letter-spacing": #{$menu-label-letter-spacing},
+ "menu-label-spacing": #{$menu-label-spacing},
+ )
+ );
+}
+
+.#{iv.$class-prefix}menu {
+ font-size: cv.getVar("size-normal");
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-large");
+ }
+}
+
+.#{iv.$class-prefix}menu-list {
+ line-height: cv.getVar("menu-list-line-height");
+
+ a,
+ button,
+ .#{iv.$class-prefix}menu-item {
+ @extend %reset;
+ background-color: hsl(
+ #{cv.getVar("menu-item-h")},
+ #{cv.getVar("menu-item-s")},
+ calc(
+ #{cv.getVar("menu-item-background-l")} + #{cv.getVar(
+ "menu-item-background-l-delta"
+ )}
+ )
+ );
+ border-radius: cv.getVar("menu-item-radius");
+ color: hsl(
+ #{cv.getVar("menu-item-h")},
+ #{cv.getVar("menu-item-s")},
+ #{cv.getVar("menu-item-color-l")}
+ );
+ display: block;
+ padding: cv.getVar("menu-list-link-padding");
+ text-align: left;
+ width: 100%;
+
+ &:hover {
+ @include cv.register-vars(
+ (
+ "menu-item-background-l-delta": #{cv.getVar(
+ "menu-item-hover-background-l-delta"
+ )},
+ )
+ );
+ }
+
+ &:active {
+ @include cv.register-vars(
+ (
+ "menu-item-background-l-delta": #{cv.getVar(
+ "menu-item-active-background-l-delta"
+ )},
+ )
+ );
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-active,
+ &.#{iv.$class-prefix}is-selected {
+ @include cv.register-vars(
+ (
+ "menu-item-h": #{cv.getVar("menu-item-selected-h")},
+ "menu-item-s": #{cv.getVar("menu-item-selected-s")},
+ "menu-item-l": #{cv.getVar("menu-item-selected-l")},
+ "menu-item-background-l": #{cv.getVar(
+ "menu-item-selected-background-l"
+ )},
+ "menu-item-color-l": #{cv.getVar("menu-item-selected-color-l")},
+ )
+ );
+ }
+ }
+
+ li {
+ ul {
+ border-inline-start: cv.getVar("menu-list-border-left");
+ margin: cv.getVar("menu-nested-list-margin");
+ padding-inline-start: cv.getVar("menu-nested-list-padding-left");
+ }
+ }
+}
+
+.#{iv.$class-prefix}menu-label {
+ color: cv.getVar("menu-label-color");
+ font-size: cv.getVar("menu-label-font-size");
+ letter-spacing: cv.getVar("menu-label-letter-spacing");
+ text-transform: uppercase;
+
+ &:not(:first-child) {
+ margin-top: cv.getVar("menu-label-spacing");
+ }
+
+ &:not(:last-child) {
+ margin-bottom: cv.getVar("menu-label-spacing");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/message.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/message.scss
new file mode 100644
index 0000000..03196fe
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/message.scss
@@ -0,0 +1,183 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$message-h: cv.getVar("scheme-h");
+$message-s: cv.getVar("scheme-s");
+$message-background-l: cv.getVar("background-l");
+$message-border-l: cv.getVar("border-l");
+$message-border-l-delta: -20% !default;
+$message-border-style: solid;
+$message-border-width: 0.25em;
+$message-color-l: cv.getVar("text-l");
+$message-header-background-l: cv.getVar("dark-l");
+$message-header-color-l: cv.getVar("text-dark-invert-l");
+$message-radius: cv.getVar("radius") !default;
+
+$message-header-weight: cv.getVar("weight-semibold") !default;
+$message-header-padding: 1em 1.25em !default;
+$message-header-radius: cv.getVar("radius") !default;
+
+$message-body-border-width: 0 0 0 4px !default;
+$message-body-color: cv.getVar("text") !default;
+$message-body-padding: 1.25em 1.5em !default;
+$message-body-radius: cv.getVar("radius-small") !default;
+
+$message-body-pre-code-background-color: transparent !default;
+
+$message-header-body-border-width: 0 !default;
+$message-colors: dv.$colors !default;
+
+.#{iv.$class-prefix}message {
+ @include cv.register-vars(
+ (
+ "message-border-l-delta": #{$message-border-l-delta},
+ "message-radius": #{$message-radius},
+ "message-header-weight": #{$message-header-weight},
+ "message-header-padding": #{$message-header-padding},
+ "message-header-radius": #{$message-header-radius},
+ "message-body-border-width": #{$message-body-border-width},
+ "message-body-color": #{$message-body-color},
+ "message-body-padding": #{$message-body-padding},
+ "message-body-radius": #{$message-body-radius},
+ "message-body-pre-code-background-color": #{$message-body-pre-code-background-color},
+ "message-header-body-border-width": #{$message-header-body-border-width},
+ "message-h": #{$message-h},
+ "message-s": #{$message-s},
+ "message-background-l": #{$message-background-l},
+ "message-border-l": #{$message-border-l},
+ "message-border-style": #{$message-border-style},
+ "message-border-width": #{$message-border-width},
+ "message-color-l": #{$message-color-l},
+ "message-header-background-l": #{$message-header-background-l},
+ "message-header-color-l": #{$message-header-color-l},
+ )
+ );
+}
+
+.#{iv.$class-prefix}message {
+ @extend %block;
+ border-radius: cv.getVar("message-radius");
+ color: hsl(
+ #{cv.getVar("message-h")},
+ #{cv.getVar("message-s")},
+ #{cv.getVar("message-color-l")}
+ );
+ font-size: cv.getVar("size-normal");
+
+ strong {
+ color: currentColor;
+ }
+
+ a:not(.#{iv.$class-prefix}button):not(.#{iv.$class-prefix}tag):not(
+ .#{iv.$class-prefix}dropdown-item
+ ) {
+ color: currentColor;
+ text-decoration: underline;
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-large");
+ }
+
+ // Colors
+ @each $name, $components in $message-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "message-h": #{cv.getVar($name, "", "-h")},
+ "message-s": #{cv.getVar($name, "", "-s")},
+ "message-border-l":
+ calc(
+ #{cv.getVar($name, "", "-l")} + #{cv.getVar(
+ "message-border-l-delta"
+ )}
+ ),
+ "message-color-l": #{cv.getVar($name, "", "-on-scheme-l")},
+ "message-header-background-l": #{cv.getVar($name, "", "-l")},
+ "message-header-color-l": #{cv.getVar($name, "", "-invert-l")},
+ )
+ );
+ }
+ }
+}
+
+.#{iv.$class-prefix}message-header {
+ align-items: center;
+ background-color: hsl(
+ #{cv.getVar("message-h")},
+ #{cv.getVar("message-s")},
+ #{cv.getVar("message-header-background-l")}
+ );
+ border-start-start-radius: cv.getVar("message-header-radius");
+ border-start-end-radius: cv.getVar("message-header-radius");
+ color: hsl(
+ #{cv.getVar("message-h")},
+ #{cv.getVar("message-s")},
+ #{cv.getVar("message-header-color-l")}
+ );
+ display: flex;
+ font-weight: cv.getVar("message-header-weight");
+ justify-content: space-between;
+ line-height: 1.25;
+ padding: cv.getVar("message-header-padding");
+ position: relative;
+
+ .#{iv.$class-prefix}delete {
+ flex-grow: 0;
+ flex-shrink: 0;
+ margin-inline-start: 0.75em;
+ }
+
+ & + .#{iv.$class-prefix}message-body {
+ border-width: cv.getVar("message-header-body-border-width");
+ border-start-start-radius: 0;
+ border-start-end-radius: 0;
+ }
+}
+
+.#{iv.$class-prefix}message-body {
+ background-color: hsl(
+ #{cv.getVar("message-h")},
+ #{cv.getVar("message-s")},
+ #{cv.getVar("message-background-l")}
+ );
+ border-inline-start-color: hsl(
+ #{cv.getVar("message-h")},
+ #{cv.getVar("message-s")},
+ #{cv.getVar("message-border-l")}
+ );
+ border-inline-start-style: #{cv.getVar("message-border-style")};
+ border-inline-start-width: #{cv.getVar("message-border-width")};
+ border-radius: cv.getVar("message-body-radius");
+ padding: cv.getVar("message-body-padding");
+
+ code,
+ pre {
+ background-color: hsl(
+ #{cv.getVar("message-h")},
+ #{cv.getVar("message-s")},
+ #{cv.getVar("message-header-color-l")}
+ );
+ color: hsl(
+ #{cv.getVar("message-h")},
+ #{cv.getVar("message-s")},
+ #{cv.getVar("message-header-background-l")}
+ );
+ }
+
+ pre code {
+ background-color: cv.getVar("message-body-pre-code-background-color");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/modal.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/modal.scss
new file mode 100644
index 0000000..0a0aa59
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/modal.scss
@@ -0,0 +1,164 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$modal-z: 40 !default;
+
+$modal-background-background-color: hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")},
+ 0.86
+) !default;
+
+$modal-content-width: 40rem !default;
+$modal-content-margin-mobile: 1.25rem !default;
+$modal-content-spacing-mobile: 10rem !default;
+$modal-content-spacing-tablet: 2.5rem !default;
+
+$modal-close-dimensions: 2.5rem !default;
+$modal-close-right: 1.25rem !default;
+$modal-close-top: 1.25rem !default;
+
+$modal-card-spacing: 2.5rem !default;
+
+$modal-card-head-background-color: cv.getVar("scheme-main") !default;
+$modal-card-head-padding: 2rem !default;
+$modal-card-head-radius: cv.getVar("radius-large") !default;
+
+$modal-card-title-color: cv.getVar("text-strong") !default;
+$modal-card-title-line-height: 1 !default;
+$modal-card-title-size: cv.getVar("size-4") !default;
+
+$modal-card-foot-background-color: cv.getVar("scheme-main-bis") !default;
+$modal-card-foot-radius: cv.getVar("radius-large") !default;
+
+$modal-card-body-background-color: cv.getVar("scheme-main") !default;
+$modal-card-body-padding: 2rem !default;
+
+$modal-breakpoint: iv.$tablet !default;
+
+.#{iv.$class-prefix}modal {
+ @include cv.register-vars(
+ (
+ "modal-z": #{$modal-z},
+ "modal-background-background-color": #{$modal-background-background-color},
+ "modal-content-width": #{$modal-content-width},
+ "modal-content-margin-mobile": #{$modal-content-margin-mobile},
+ "modal-content-spacing-mobile": #{$modal-content-spacing-mobile},
+ "modal-content-spacing-tablet": #{$modal-content-spacing-tablet},
+ "modal-close-dimensions": #{$modal-close-dimensions},
+ "modal-close-right": #{$modal-close-right},
+ "modal-close-top": #{$modal-close-top},
+ "modal-card-spacing": #{$modal-card-spacing},
+ "modal-card-head-background-color": #{$modal-card-head-background-color},
+ "modal-card-head-padding": #{$modal-card-head-padding},
+ "modal-card-head-radius": #{$modal-card-head-radius},
+ "modal-card-title-color": #{$modal-card-title-color},
+ "modal-card-title-line-height": #{$modal-card-title-line-height},
+ "modal-card-title-size": #{$modal-card-title-size},
+ "modal-card-foot-background-color": #{$modal-card-foot-background-color},
+ "modal-card-foot-radius": #{$modal-card-foot-radius},
+ "modal-card-body-background-color": #{$modal-card-body-background-color},
+ "modal-card-body-padding": #{$modal-card-body-padding},
+ )
+ );
+}
+
+.#{iv.$class-prefix}modal {
+ @extend %overlay;
+
+ align-items: center;
+ display: none;
+ flex-direction: column;
+ justify-content: center;
+ overflow: hidden;
+ position: fixed;
+ z-index: cv.getVar("modal-z");
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-active {
+ display: flex;
+ }
+}
+
+.#{iv.$class-prefix}modal-background {
+ @extend %overlay;
+ background-color: cv.getVar("modal-background-background-color");
+}
+
+.#{iv.$class-prefix}modal-content,
+.#{iv.$class-prefix}modal-card {
+ margin: 0 cv.getVar("modal-content-margin-mobile");
+ max-height: calc(100vh - #{cv.getVar("modal-content-spacing-mobile")});
+ overflow: auto;
+ position: relative;
+ width: 100%;
+
+ // Responsiveness
+ @include mx.from($modal-breakpoint) {
+ margin: 0 auto;
+ max-height: calc(100vh - #{cv.getVar("modal-content-spacing-tablet")});
+ width: cv.getVar("modal-content-width");
+ }
+}
+
+.#{iv.$class-prefix}modal-close {
+ @extend %delete;
+ background: none;
+ height: cv.getVar("modal-close-dimensions");
+ inset-inline-end: cv.getVar("modal-close-right");
+ position: fixed;
+ top: cv.getVar("modal-close-top");
+ width: cv.getVar("modal-close-dimensions");
+}
+
+.#{iv.$class-prefix}modal-card {
+ display: flex;
+ flex-direction: column;
+ max-height: calc(100vh - #{cv.getVar("modal-card-spacing")});
+ overflow: hidden;
+ overflow-y: visible;
+}
+
+.#{iv.$class-prefix}modal-card-head,
+.#{iv.$class-prefix}modal-card-foot {
+ align-items: center;
+ display: flex;
+ flex-shrink: 0;
+ justify-content: flex-start;
+ padding: cv.getVar("modal-card-head-padding");
+ position: relative;
+}
+
+.#{iv.$class-prefix}modal-card-head {
+ background-color: cv.getVar("modal-card-head-background-color");
+ border-start-start-radius: cv.getVar("modal-card-head-radius");
+ border-start-end-radius: cv.getVar("modal-card-head-radius");
+ box-shadow: cv.getVar("shadow");
+}
+
+.#{iv.$class-prefix}modal-card-title {
+ color: cv.getVar("modal-card-title-color");
+ flex-grow: 1;
+ flex-shrink: 0;
+ font-size: cv.getVar("modal-card-title-size");
+ line-height: cv.getVar("modal-card-title-line-height");
+}
+
+.#{iv.$class-prefix}modal-card-foot {
+ background-color: cv.getVar("modal-card-foot-background-color");
+ border-end-start-radius: cv.getVar("modal-card-foot-radius");
+ border-end-end-radius: cv.getVar("modal-card-foot-radius");
+}
+
+.#{iv.$class-prefix}modal-card-body {
+ @include mx.overflow-touch;
+ background-color: cv.getVar("modal-card-body-background-color");
+ flex-grow: 1;
+ flex-shrink: 1;
+ overflow: auto;
+ padding: cv.getVar("modal-card-body-padding");
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/navbar.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/navbar.scss
new file mode 100644
index 0000000..7ae7e35
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/navbar.scss
@@ -0,0 +1,799 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$navbar-h: cv.getVar("scheme-h") !default;
+$navbar-s: cv.getVar("scheme-s") !default;
+$navbar-l: cv.getVar("scheme-main-l") !default;
+$navbar-background-color: cv.getVar("scheme-main") !default;
+$navbar-box-shadow-size: 0 0.125em 0 0 !default;
+$navbar-box-shadow-color: cv.getVar("background") !default;
+$navbar-height: 3.25rem !default;
+$navbar-padding-vertical: 1rem !default;
+$navbar-padding-horizontal: 2rem !default;
+$navbar-z: 30 !default;
+$navbar-fixed-z: 30 !default;
+
+$navbar-item-background-a: 0 !default;
+$navbar-item-background-l: cv.getVar("scheme-main-l") !default;
+$navbar-item-background-l-delta: 0% !default;
+$navbar-item-hover-background-l-delta: cv.getVar(
+ "hover-background-l-delta"
+) !default;
+$navbar-item-active-background-l-delta: cv.getVar(
+ "active-background-l-delta"
+) !default;
+$navbar-item-color-l: cv.getVar("text-l") !default;
+$navbar-item-color: hsl(
+ #{cv.getVar("navbar-h")},
+ #{cv.getVar("navbar-s")},
+ #{cv.getVar("navbar-item-color-l")}
+) !default;
+$navbar-item-selected-h: cv.getVar("link-h") !default;
+$navbar-item-selected-s: cv.getVar("link-s") !default;
+$navbar-item-selected-l: cv.getVar("link-l") !default;
+$navbar-item-selected-background-l: cv.getVar("link-l") !default;
+$navbar-item-selected-color-l: cv.getVar("link-invert-l") !default;
+$navbar-item-img-max-height: 1.75rem !default;
+
+$navbar-dropdown-item-h: cv.getVar("scheme-h") !default;
+$navbar-dropdown-item-s: cv.getVar("scheme-s") !default;
+$navbar-dropdown-item-l: cv.getVar("scheme-main-l") !default;
+$navbar-dropdown-item-background-l: cv.getVar("scheme-main-l") !default;
+$navbar-dropdown-item-color-l: cv.getVar("text-l") !default;
+
+$navbar-burger-color: cv.getVar("link") !default;
+
+$navbar-tab-hover-background-color: transparent !default;
+$navbar-tab-hover-border-bottom-color: cv.getVar("link") !default;
+$navbar-tab-active-color: cv.getVar("link") !default;
+$navbar-tab-active-background-color: transparent !default;
+$navbar-tab-active-border-bottom-color: cv.getVar("link") !default;
+$navbar-tab-active-border-bottom-style: solid !default;
+$navbar-tab-active-border-bottom-width: 0.1875em !default;
+
+$navbar-dropdown-background-color: cv.getVar("scheme-main") !default;
+$navbar-dropdown-border-l: cv.getVar("border-l") !default;
+$navbar-dropdown-border-color: hsl(
+ cv.getVar("navbar-h"),
+ cv.getVar("navbar-s"),
+ cv.getVar("navbar-dropdown-border-l")
+) !default;
+$navbar-dropdown-border-style: solid !default;
+$navbar-dropdown-border-width: 0.125em !default;
+$navbar-dropdown-offset: -0.25em !default;
+$navbar-dropdown-arrow: cv.getVar("link") !default;
+$navbar-dropdown-radius: cv.getVar("radius-large") !default;
+$navbar-dropdown-z: 20 !default;
+
+$navbar-dropdown-boxed-radius: cv.getVar("radius-large") !default;
+$navbar-dropdown-boxed-shadow:
+ 0 0.5em 0.5em
+ hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")},
+ 0.1
+ ),
+ 0 0 0 1px
+ hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")},
+ 0.1
+ ) !default;
+
+$navbar-divider-background-l: cv.getVar("background-l") !default;
+$navbar-divider-height: 0.125em !default;
+
+$navbar-bottom-box-shadow-size: 0 -0.125em 0 0 !default;
+
+$navbar-breakpoint: iv.$desktop !default;
+
+$navbar-colors: dv.$colors !default;
+
+@mixin navbar-fixed {
+ left: 0;
+ position: fixed;
+ right: 0;
+ z-index: cv.getVar("navbar-fixed-z");
+}
+
+#{iv.$variables-host} {
+ @include cv.register-vars(
+ (
+ "navbar-height": #{$navbar-height},
+ )
+ );
+}
+
+.#{iv.$class-prefix}navbar {
+ @include cv.register-vars(
+ (
+ "navbar-h": #{$navbar-h},
+ "navbar-s": #{$navbar-s},
+ "navbar-l": #{$navbar-l},
+ "navbar-background-color": #{$navbar-background-color},
+ "navbar-box-shadow-size": #{$navbar-box-shadow-size},
+ "navbar-box-shadow-color": #{$navbar-box-shadow-color},
+ "navbar-padding-vertical": #{$navbar-padding-vertical},
+ "navbar-padding-horizontal": #{$navbar-padding-horizontal},
+ "navbar-z": #{$navbar-z},
+ "navbar-fixed-z": #{$navbar-fixed-z},
+ "navbar-item-background-a": #{$navbar-item-background-a},
+ "navbar-item-background-l": #{$navbar-item-background-l},
+ "navbar-item-background-l-delta": #{$navbar-item-background-l-delta},
+ "navbar-item-hover-background-l-delta": #{$navbar-item-hover-background-l-delta},
+ "navbar-item-active-background-l-delta": #{$navbar-item-active-background-l-delta},
+ "navbar-item-color-l": #{$navbar-item-color-l},
+ "navbar-item-color": #{$navbar-item-color},
+ "navbar-item-selected-h": #{$navbar-item-selected-h},
+ "navbar-item-selected-s": #{$navbar-item-selected-s},
+ "navbar-item-selected-l": #{$navbar-item-selected-l},
+ "navbar-item-selected-background-l": #{$navbar-item-selected-background-l},
+ "navbar-item-selected-color-l": #{$navbar-item-selected-color-l},
+ "navbar-item-img-max-height": #{$navbar-item-img-max-height},
+ "navbar-burger-color": #{$navbar-burger-color},
+ "navbar-tab-hover-background-color": #{$navbar-tab-hover-background-color},
+ "navbar-tab-hover-border-bottom-color": #{$navbar-tab-hover-border-bottom-color},
+ "navbar-tab-active-color": #{$navbar-tab-active-color},
+ "navbar-tab-active-background-color": #{$navbar-tab-active-background-color},
+ "navbar-tab-active-border-bottom-color": #{$navbar-tab-active-border-bottom-color},
+ "navbar-tab-active-border-bottom-style": #{$navbar-tab-active-border-bottom-style},
+ "navbar-tab-active-border-bottom-width": #{$navbar-tab-active-border-bottom-width},
+ "navbar-dropdown-background-color": #{$navbar-dropdown-background-color},
+ "navbar-dropdown-border-l": #{$navbar-dropdown-border-l},
+ "navbar-dropdown-border-color": #{$navbar-dropdown-border-color},
+ "navbar-dropdown-border-style": #{$navbar-dropdown-border-style},
+ "navbar-dropdown-border-width": #{$navbar-dropdown-border-width},
+ "navbar-dropdown-offset": #{$navbar-dropdown-offset},
+ "navbar-dropdown-arrow": #{$navbar-dropdown-arrow},
+ "navbar-dropdown-radius": #{$navbar-dropdown-radius},
+ "navbar-dropdown-z": #{$navbar-dropdown-z},
+ "navbar-dropdown-boxed-radius": #{$navbar-dropdown-boxed-radius},
+ "navbar-dropdown-boxed-shadow": #{$navbar-dropdown-boxed-shadow},
+ "navbar-dropdown-item-h": #{$navbar-dropdown-item-h},
+ "navbar-dropdown-item-s": #{$navbar-dropdown-item-s},
+ "navbar-dropdown-item-l": #{$navbar-dropdown-item-l},
+ "navbar-dropdown-item-background-l": #{$navbar-dropdown-item-background-l},
+ "navbar-dropdown-item-color-l": #{$navbar-dropdown-item-color-l},
+ "navbar-divider-background-l": #{$navbar-divider-background-l},
+ "navbar-divider-height": #{$navbar-divider-height},
+ "navbar-bottom-box-shadow-size": #{$navbar-bottom-box-shadow-size},
+ )
+ );
+}
+
+.#{iv.$class-prefix}navbar {
+ background-color: cv.getVar("navbar-background-color");
+ min-height: cv.getVar("navbar-height");
+ position: relative;
+ z-index: cv.getVar("navbar-z");
+
+ @each $name, $pair in $navbar-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "navbar-h": #{cv.getVar($name, "", "-h")},
+ "navbar-s": #{cv.getVar($name, "", "-s")},
+ "navbar-l": #{cv.getVar($name, "", "-l")},
+ "burger-h": #{cv.getVar($name, "", "-h")},
+ "burger-s": #{cv.getVar($name, "", "-s")},
+ "burger-l": #{cv.getVar($name, "", "-invert-l")},
+ "navbar-background-color": #{cv.getVar($name)},
+ "navbar-item-background-l": #{cv.getVar($name, "", "-l")},
+ "navbar-item-color-l": #{cv.getVar($name, "", "-invert-l")},
+ "navbar-item-selected-h": #{cv.getVar($name, "", "-h")},
+ "navbar-item-selected-s": #{cv.getVar($name, "", "-s")},
+ "navbar-item-selected-l": #{cv.getVar($name, "", "-l")},
+ "navbar-item-selected-background-l": #{cv.getVar($name, "", "-l")},
+ "navbar-item-selected-color-l": #{cv.getVar($name, "", "-invert-l")},
+ "navbar-dropdown-arrow": #{cv.getVar($name, "", "-invert-l")},
+ "navbar-dropdown-background-color":
+ hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar("navbar-dropdown-item-background-l")}
+ ),
+ "navbar-dropdown-item-h": #{cv.getVar($name, "", "-h")},
+ "navbar-dropdown-item-s": #{cv.getVar($name, "", "-s")},
+ )
+ );
+ }
+ }
+
+ & > .#{iv.$class-prefix}container {
+ align-items: stretch;
+ display: flex;
+ min-height: cv.getVar("navbar-height");
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}has-shadow {
+ box-shadow: cv.getVar("navbar-box-shadow-size")
+ cv.getVar("navbar-box-shadow-color");
+ }
+
+ &.#{iv.$class-prefix}is-fixed-bottom,
+ &.#{iv.$class-prefix}is-fixed-top {
+ @include navbar-fixed;
+ }
+
+ &.#{iv.$class-prefix}is-fixed-bottom {
+ bottom: 0;
+
+ &.#{iv.$class-prefix}has-shadow {
+ box-shadow: cv.getVar("navbar-bottom-box-shadow-size")
+ cv.getVar("navbar-box-shadow-color");
+ }
+ }
+
+ &.#{iv.$class-prefix}is-fixed-top {
+ top: 0;
+ }
+}
+
+html,
+body {
+ &.#{iv.$class-prefix}has-navbar-fixed-top {
+ padding-top: cv.getVar("navbar-height");
+ }
+
+ &.#{iv.$class-prefix}has-navbar-fixed-bottom {
+ padding-bottom: cv.getVar("navbar-height");
+ }
+}
+
+.#{iv.$class-prefix}navbar-brand,
+.#{iv.$class-prefix}navbar-tabs {
+ align-items: stretch;
+ display: flex;
+ flex-shrink: 0;
+ min-height: cv.getVar("navbar-height");
+}
+
+.#{iv.$class-prefix}navbar-tabs {
+ @include mx.overflow-touch;
+ max-width: 100vw;
+ overflow-x: auto;
+ overflow-y: hidden;
+}
+
+.#{iv.$class-prefix}navbar-burger {
+ @extend %reset;
+ @include mx.burger(2.5rem);
+
+ & {
+ align-self: center;
+ color: cv.getVar("navbar-burger-color");
+ margin-inline-start: auto;
+ margin-inline-end: 0.375rem;
+ }
+}
+
+.#{iv.$class-prefix}navbar-menu {
+ display: none;
+}
+
+.#{iv.$class-prefix}navbar-item,
+.#{iv.$class-prefix}navbar-link {
+ color: cv.getVar("navbar-item-color");
+ display: block;
+ gap: 0.75rem;
+ line-height: 1.5;
+ padding: 0.5rem 0.75rem;
+ position: relative;
+
+ .#{iv.$class-prefix}icon {
+ &:only-child {
+ margin-left: -0.25rem;
+ margin-right: -0.25rem;
+ }
+ }
+}
+
+a.#{iv.$class-prefix}navbar-item,
+.#{iv.$class-prefix}navbar-link {
+ background-color: hsla(
+ #{cv.getVar("navbar-h")},
+ #{cv.getVar("navbar-s")},
+ calc(
+ #{cv.getVar("navbar-item-background-l")} + #{cv.getVar(
+ "navbar-item-background-l-delta"
+ )}
+ ),
+ #{cv.getVar("navbar-item-background-a")}
+ );
+ cursor: pointer;
+
+ &:focus,
+ &:focus-within,
+ &:hover {
+ @include cv.register-vars(
+ (
+ "navbar-item-background-l-delta": #{cv.getVar(
+ "navbar-item-hover-background-l-delta"
+ )},
+ "navbar-item-background-a": 1,
+ )
+ );
+ }
+
+ &:active {
+ @include cv.register-vars(
+ (
+ "navbar-item-background-l-delta": #{cv.getVar(
+ "navbar-item-active-background-l-delta"
+ )},
+ "navbar-item-background-a": 1,
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}is-active,
+ &.#{iv.$class-prefix}is-selected {
+ @include cv.register-vars(
+ (
+ "navbar-h": #{cv.getVar("navbar-item-selected-h")},
+ "navbar-s": #{cv.getVar("navbar-item-selected-s")},
+ "navbar-l": #{cv.getVar("navbar-item-selected-l")},
+ "navbar-item-background-l": #{cv.getVar(
+ "navbar-item-selected-background-l"
+ )},
+ "navbar-item-background-a": 1,
+ "navbar-item-color-l": #{cv.getVar("navbar-item-selected-color-l")},
+ )
+ );
+ }
+}
+
+.#{iv.$class-prefix}navbar-item {
+ flex-grow: 0;
+ flex-shrink: 0;
+
+ img,
+ svg {
+ max-height: cv.getVar("navbar-item-img-max-height");
+ }
+
+ &.#{iv.$class-prefix}has-dropdown {
+ padding: 0;
+ }
+
+ &.#{iv.$class-prefix}is-expanded {
+ flex-grow: 1;
+ flex-shrink: 1;
+ }
+
+ &.#{iv.$class-prefix}is-tab {
+ border-bottom: 1px solid transparent;
+ min-height: cv.getVar("navbar-height");
+ padding-bottom: calc(0.5rem - 1px);
+
+ &:focus,
+ &:hover {
+ background-color: cv.getVar("navbar-tab-hover-background-color");
+ border-bottom-color: cv.getVar("navbar-tab-hover-border-bottom-color");
+ }
+
+ &.#{iv.$class-prefix}is-active {
+ background-color: cv.getVar("navbar-tab-active-background-color");
+ border-bottom-color: cv.getVar("navbar-tab-active-border-bottom-color");
+ border-bottom-style: cv.getVar("navbar-tab-active-border-bottom-style");
+ border-bottom-width: cv.getVar("navbar-tab-active-border-bottom-width");
+ color: cv.getVar("navbar-tab-active-color");
+ padding-bottom: calc(
+ 0.5rem - #{cv.getVar("navbar-tab-active-border-bottom-width")}
+ );
+ }
+ }
+}
+
+.#{iv.$class-prefix}navbar-content {
+ flex-grow: 1;
+ flex-shrink: 1;
+}
+
+.#{iv.$class-prefix}navbar-link:not(.#{iv.$class-prefix}is-arrowless) {
+ padding-inline-end: 2.5em;
+
+ &::after {
+ @extend %arrow;
+ border-color: cv.getVar("navbar-dropdown-arrow");
+ margin-top: -0.375em;
+ inset-inline-end: 1.125em;
+ }
+}
+
+.#{iv.$class-prefix}navbar-dropdown {
+ font-size: 0.875rem;
+ padding-bottom: 0.75rem;
+ padding-top: 0.5rem;
+
+ .#{iv.$class-prefix}navbar-item {
+ padding-left: 1.5rem;
+ padding-right: 1.5rem;
+
+ &:not(.is-active, .is-selected) {
+ background-color: hsl(
+ #{cv.getVar("navbar-dropdown-item-h")},
+ #{cv.getVar("navbar-dropdown-item-s")},
+ calc(
+ #{cv.getVar("navbar-dropdown-item-background-l")} + #{cv.getVar(
+ "navbar-item-background-l-delta"
+ )}
+ )
+ );
+ color: hsl(
+ #{cv.getVar("navbar-dropdown-item-h")},
+ #{cv.getVar("navbar-dropdown-item-s")},
+ #{cv.getVar("navbar-dropdown-item-color-l")}
+ );
+ }
+ }
+}
+
+.#{iv.$class-prefix}navbar-divider {
+ background-color: hsl(
+ #{cv.getVar("navbar-h")},
+ #{cv.getVar("navbar-s")},
+ #{cv.getVar("navbar-divider-background-l")}
+ );
+ border: none;
+ display: none;
+ height: cv.getVar("navbar-divider-height");
+ margin: 0.5rem 0;
+}
+
+@include mx.until($navbar-breakpoint) {
+ .#{iv.$class-prefix}navbar > .#{iv.$class-prefix}container {
+ display: block;
+ }
+
+ .#{iv.$class-prefix}navbar-brand,
+ .#{iv.$class-prefix}navbar-tabs {
+ .#{iv.$class-prefix}navbar-item {
+ align-items: center;
+ display: flex;
+ }
+ }
+
+ .#{iv.$class-prefix}navbar-link {
+ &::after {
+ display: none;
+ }
+ }
+
+ .#{iv.$class-prefix}navbar-menu {
+ background-color: cv.getVar("navbar-background-color");
+ box-shadow: 0 0.5em 1em
+ hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")},
+ 0.1
+ );
+ padding: 0.5rem 0;
+
+ &.#{iv.$class-prefix}is-active {
+ display: block;
+ }
+ }
+
+ // Fixed navbar
+ .#{iv.$class-prefix}navbar {
+ &.#{iv.$class-prefix}is-fixed-bottom-touch,
+ &.#{iv.$class-prefix}is-fixed-top-touch {
+ @include navbar-fixed;
+ }
+
+ &.#{iv.$class-prefix}is-fixed-bottom-touch {
+ bottom: 0;
+
+ &.#{iv.$class-prefix}has-shadow {
+ box-shadow: 0 -0.125em 0.1875em hsla(#{cv.getVar("scheme-h")}, #{cv.getVar(
+ "scheme-s"
+ )}, #{cv.getVar("scheme-invert-l")}, 0.1);
+ }
+ }
+
+ &.#{iv.$class-prefix}is-fixed-top-touch {
+ top: 0;
+ }
+
+ &.#{iv.$class-prefix}is-fixed-top,
+ &.#{iv.$class-prefix}is-fixed-top-touch {
+ .#{iv.$class-prefix}navbar-menu {
+ @include mx.overflow-touch;
+ max-height: calc(100vh - #{cv.getVar("navbar-height")});
+ overflow: auto;
+ }
+ }
+ }
+
+ html,
+ body {
+ &.#{iv.$class-prefix}has-navbar-fixed-top-touch {
+ padding-top: cv.getVar("navbar-height");
+ }
+
+ &.#{iv.$class-prefix}has-navbar-fixed-bottom-touch {
+ padding-bottom: cv.getVar("navbar-height");
+ }
+ }
+}
+
+@include mx.from($navbar-breakpoint) {
+ .#{iv.$class-prefix}navbar,
+ .#{iv.$class-prefix}navbar-menu,
+ .#{iv.$class-prefix}navbar-start,
+ .#{iv.$class-prefix}navbar-end {
+ align-items: stretch;
+ display: flex;
+ }
+
+ .#{iv.$class-prefix}navbar {
+ min-height: cv.getVar("navbar-height");
+
+ &.#{iv.$class-prefix}is-spaced {
+ padding: cv.getVar("navbar-padding-vertical")
+ cv.getVar("navbar-padding-horizontal");
+
+ .#{iv.$class-prefix}navbar-start,
+ .#{iv.$class-prefix}navbar-end {
+ align-items: center;
+ }
+
+ a.#{iv.$class-prefix}navbar-item,
+ .#{iv.$class-prefix}navbar-link {
+ border-radius: cv.getVar("radius");
+ }
+ }
+
+ &.#{iv.$class-prefix}is-transparent {
+ @include cv.register-vars(
+ (
+ "navbar-item-background-a": 0,
+ )
+ );
+
+ .#{iv.$class-prefix}navbar-dropdown {
+ a.#{iv.$class-prefix}navbar-item {
+ background-color: hsl(
+ #{cv.getVar("navbar-h")},
+ #{cv.getVar("navbar-s")},
+ calc(
+ #{cv.getVar("navbar-item-background-l")} + #{cv.getVar(
+ "navbar-item-background-l-delta"
+ )}
+ )
+ );
+
+ &.#{iv.$class-prefix}is-active,
+ &.#{iv.$class-prefix}is-selected {
+ @include cv.register-vars(
+ (
+ "navbar-h": #{cv.getVar("navbar-item-selected-h")},
+ "navbar-s": #{cv.getVar("navbar-item-selected-s")},
+ "navbar-l": #{cv.getVar("navbar-item-selected-l")},
+ "navbar-item-background-l": #{cv.getVar(
+ "navbar-item-selected-background-l"
+ )},
+ "navbar-item-color-l": #{cv.getVar(
+ "navbar-item-selected-color-l"
+ )},
+ )
+ );
+ }
+ }
+ }
+ }
+ }
+
+ .#{iv.$class-prefix}navbar-burger {
+ display: none;
+ }
+
+ .#{iv.$class-prefix}navbar-item,
+ .#{iv.$class-prefix}navbar-link {
+ align-items: center;
+ display: flex;
+ }
+
+ .#{iv.$class-prefix}navbar-item {
+ &.#{iv.$class-prefix}has-dropdown {
+ align-items: stretch;
+ }
+
+ &.#{iv.$class-prefix}has-dropdown-up {
+ .#{iv.$class-prefix}navbar-link::after {
+ transform: rotate(135deg) translate(0.25em, -0.25em);
+ }
+
+ .#{iv.$class-prefix}navbar-dropdown {
+ border-bottom-color: cv.getVar("navbar-dropdown-border-color");
+ border-bottom-style: cv.getVar("navbar-dropdown-border-style");
+ border-bottom-width: cv.getVar("navbar-dropdown-border-width");
+ border-radius: cv.getVar("navbar-dropdown-radius")
+ cv.getVar("navbar-dropdown-radius") 0 0;
+ border-top: none;
+ bottom: 100%;
+ box-shadow: 0 -0.5em 0.5em hsla(#{cv.getVar("scheme-h")}, #{cv.getVar(
+ "scheme-s"
+ )}, #{cv.getVar("scheme-invert-l")}, 0.1);
+ top: auto;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-active,
+ &.#{iv.$class-prefix}is-hoverable:focus,
+ &.#{iv.$class-prefix}is-hoverable:focus-within,
+ &.#{iv.$class-prefix}is-hoverable:hover {
+ .#{iv.$class-prefix}navbar-dropdown {
+ display: block;
+
+ .#{iv.$class-prefix}navbar.#{iv.$class-prefix}is-spaced &,
+ &.#{iv.$class-prefix}is-boxed {
+ opacity: 1;
+ pointer-events: auto;
+ transform: translateY(0);
+ }
+ }
+ }
+ }
+
+ .#{iv.$class-prefix}navbar-menu {
+ flex-grow: 1;
+ flex-shrink: 0;
+ }
+
+ .#{iv.$class-prefix}navbar-start {
+ justify-content: flex-start;
+ margin-inline-end: auto;
+ }
+
+ .#{iv.$class-prefix}navbar-end {
+ justify-content: flex-end;
+ margin-inline-start: auto;
+ }
+
+ .#{iv.$class-prefix}navbar-dropdown {
+ background-color: cv.getVar("navbar-dropdown-background-color");
+ border-end-start-radius: cv.getVar("navbar-dropdown-radius");
+ border-end-end-radius: cv.getVar("navbar-dropdown-radius");
+ border-top-color: cv.getVar("navbar-dropdown-border-color");
+ border-top-style: cv.getVar("navbar-dropdown-border-style");
+ border-top-width: cv.getVar("navbar-dropdown-border-width");
+ box-shadow: 0 0.5em 0.5em
+ hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")},
+ 0.1
+ );
+ display: none;
+ font-size: 0.875rem;
+ inset-inline-start: 0;
+ min-width: 100%;
+ position: absolute;
+ top: 100%;
+ z-index: cv.getVar("navbar-dropdown-z");
+
+ .#{iv.$class-prefix}navbar-item {
+ padding: 0.375rem 1rem;
+ white-space: nowrap;
+ }
+
+ a.#{iv.$class-prefix}navbar-item {
+ padding-inline-end: 3rem;
+
+ &:not(.is-active, .is-selected) {
+ background-color: hsl(
+ #{cv.getVar("navbar-dropdown-item-h")},
+ #{cv.getVar("navbar-dropdown-item-s")},
+ calc(
+ #{cv.getVar("navbar-dropdown-item-background-l")} + #{cv.getVar(
+ "navbar-item-background-l-delta"
+ )}
+ )
+ );
+ color: hsl(
+ #{cv.getVar("navbar-dropdown-item-h")},
+ #{cv.getVar("navbar-dropdown-item-s")},
+ #{cv.getVar("navbar-dropdown-item-color-l")}
+ );
+ }
+ }
+
+ .#{iv.$class-prefix}navbar.#{iv.$class-prefix}is-spaced &,
+ &.#{iv.$class-prefix}is-boxed {
+ border-radius: cv.getVar("navbar-dropdown-boxed-radius");
+ border-top: none;
+ box-shadow: cv.getVar("navbar-dropdown-boxed-shadow");
+ display: block;
+ opacity: 0;
+ pointer-events: none;
+ top: calc(100% + (#{cv.getVar("navbar-dropdown-offset")}));
+ transform: translateY(-5px);
+ transition-duration: cv.getVar("duration");
+ transition-property: opacity, transform;
+ }
+
+ &.#{iv.$class-prefix}is-right {
+ left: auto;
+ right: 0;
+ }
+ }
+
+ .#{iv.$class-prefix}navbar-divider {
+ display: block;
+ }
+
+ .#{iv.$class-prefix}navbar > .#{iv.$class-prefix}container,
+ .#{iv.$class-prefix}container > .#{iv.$class-prefix}navbar {
+ .#{iv.$class-prefix}navbar-brand {
+ margin-inline-start: -0.75rem;
+ }
+
+ .#{iv.$class-prefix}navbar-menu {
+ margin-inline-end: -0.75rem;
+ }
+ }
+
+ // Fixed navbar
+ .#{iv.$class-prefix}navbar {
+ &.#{iv.$class-prefix}is-fixed-bottom-desktop,
+ &.#{iv.$class-prefix}is-fixed-top-desktop {
+ @include navbar-fixed;
+ }
+
+ &.#{iv.$class-prefix}is-fixed-bottom-desktop {
+ bottom: 0;
+
+ &.#{iv.$class-prefix}has-shadow {
+ box-shadow: 0 -0.125em 0.1875em hsla(#{cv.getVar("scheme-h")}, #{cv.getVar(
+ "scheme-s"
+ )}, #{cv.getVar("scheme-invert-l")}, 0.1);
+ }
+ }
+
+ &.#{iv.$class-prefix}is-fixed-top-desktop {
+ top: 0;
+ }
+ }
+
+ html,
+ body {
+ &.#{iv.$class-prefix}has-navbar-fixed-top-desktop {
+ padding-top: cv.getVar("navbar-height");
+ }
+
+ &.#{iv.$class-prefix}has-navbar-fixed-bottom-desktop {
+ padding-bottom: cv.getVar("navbar-height");
+ }
+
+ &.#{iv.$class-prefix}has-spaced-navbar-fixed-top {
+ padding-top: calc(
+ #{cv.getVar("navbar-height")} + #{cv.getVar("navbar-padding-vertical")} *
+ 2
+ );
+ }
+
+ &.#{iv.$class-prefix}has-spaced-navbar-fixed-bottom {
+ padding-bottom: calc(
+ #{cv.getVar("navbar-height")} + #{cv.getVar("navbar-padding-vertical")} *
+ 2
+ );
+ }
+ }
+}
+
+// Combination
+
+.#{iv.$class-prefix}hero {
+ &.#{iv.$class-prefix}is-fullheight-with-navbar {
+ min-height: calc(100vh - #{cv.getVar("navbar-height")});
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/pagination.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/pagination.scss
new file mode 100644
index 0000000..0634653
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/pagination.scss
@@ -0,0 +1,379 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$pagination-margin: -0.25rem !default;
+$pagination-min-width: cv.getVar("control-height") !default;
+
+$pagination-item-h: cv.getVar("scheme-h");
+$pagination-item-s: cv.getVar("scheme-s");
+$pagination-item-l: cv.getVar("scheme-main-l");
+$pagination-item-background-l-delta: 0%;
+$pagination-item-hover-background-l-delta: cv.getVar(
+ "hover-background-l-delta"
+);
+$pagination-item-active-background-l-delta: cv.getVar(
+ "active-background-l-delta"
+);
+$pagination-item-border-l: cv.getVar("border-l");
+$pagination-item-border-l-delta: 0%;
+$pagination-item-border-style: solid !default;
+$pagination-item-border-width: cv.getVar("control-border-width") !default;
+$pagination-item-hover-border-l-delta: cv.getVar("hover-border-l-delta");
+$pagination-item-active-border-l-delta: cv.getVar("active-border-l-delta");
+$pagination-item-focus-border-l-delta: cv.getVar("focus-border-l-delta");
+$pagination-item-color-l: cv.getVar("text-strong-l");
+$pagination-item-font-size: 1em !default;
+$pagination-item-margin: 0.25rem !default;
+$pagination-item-padding-left: 0.5em !default;
+$pagination-item-padding-right: 0.5em !default;
+$pagination-item-outer-shadow-h: 0;
+$pagination-item-outer-shadow-s: 0%;
+$pagination-item-outer-shadow-l: 20%;
+$pagination-item-outer-shadow-a: 0.05;
+
+$pagination-selected-item-h: cv.getVar("link-h");
+$pagination-selected-item-s: cv.getVar("link-s");
+$pagination-selected-item-l: cv.getVar("link-l");
+$pagination-selected-item-background-l: cv.getVar("link-l");
+$pagination-selected-item-border-l: cv.getVar("link-l");
+$pagination-selected-item-color-l: cv.getVar("link-invert-l");
+
+$pagination-nav-padding-left: 0.75em !default;
+$pagination-nav-padding-right: 0.75em !default;
+
+$pagination-disabled-color: cv.getVar("text-weak") !default;
+$pagination-disabled-background-color: cv.getVar("border") !default;
+$pagination-disabled-border-color: cv.getVar("border") !default;
+
+$pagination-current-color: cv.getVar("link-invert") !default;
+$pagination-current-background-color: cv.getVar("link") !default;
+$pagination-current-border-color: cv.getVar("link") !default;
+
+$pagination-ellipsis-color: cv.getVar("text-weak") !default;
+
+$pagination-shadow-inset: inset 0 0.0625em 0.125em
+ hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")},
+ 0.2
+ ) !default;
+
+.#{iv.$class-prefix}pagination {
+ @include cv.register-vars(
+ (
+ "pagination-margin": #{$pagination-margin},
+ "pagination-min-width": #{$pagination-min-width},
+ "pagination-item-h": #{$pagination-item-h},
+ "pagination-item-s": #{$pagination-item-s},
+ "pagination-item-l": #{$pagination-item-l},
+ "pagination-item-background-l-delta": #{$pagination-item-background-l-delta},
+ "pagination-item-hover-background-l-delta": #{$pagination-item-hover-background-l-delta},
+ "pagination-item-active-background-l-delta": #{$pagination-item-active-background-l-delta},
+ "pagination-item-border-style": #{$pagination-item-border-style},
+ "pagination-item-border-width": #{$pagination-item-border-width},
+ "pagination-item-border-l": #{$pagination-item-border-l},
+ "pagination-item-border-l-delta": #{$pagination-item-border-l-delta},
+ "pagination-item-hover-border-l-delta": #{$pagination-item-hover-border-l-delta},
+ "pagination-item-active-border-l-delta": #{$pagination-item-active-border-l-delta},
+ "pagination-item-focus-border-l-delta": #{$pagination-item-focus-border-l-delta},
+ "pagination-item-color-l": #{$pagination-item-color-l},
+ "pagination-item-font-size": #{$pagination-item-font-size},
+ "pagination-item-margin": #{$pagination-item-margin},
+ "pagination-item-padding-left": #{$pagination-item-padding-left},
+ "pagination-item-padding-right": #{$pagination-item-padding-right},
+ "pagination-item-outer-shadow-h": #{$pagination-item-outer-shadow-h},
+ "pagination-item-outer-shadow-s": #{$pagination-item-outer-shadow-s},
+ "pagination-item-outer-shadow-l": #{$pagination-item-outer-shadow-l},
+ "pagination-item-outer-shadow-a": #{$pagination-item-outer-shadow-a},
+ "pagination-nav-padding-left": #{$pagination-nav-padding-left},
+ "pagination-nav-padding-right": #{$pagination-nav-padding-right},
+ "pagination-disabled-color": #{$pagination-disabled-color},
+ "pagination-disabled-background-color": #{$pagination-disabled-background-color},
+ "pagination-disabled-border-color": #{$pagination-disabled-border-color},
+ "pagination-current-color": #{$pagination-current-color},
+ "pagination-current-background-color": #{$pagination-current-background-color},
+ "pagination-current-border-color": #{$pagination-current-border-color},
+ "pagination-ellipsis-color": #{$pagination-ellipsis-color},
+ "pagination-shadow-inset": #{$pagination-shadow-inset},
+ "pagination-selected-item-h": #{$pagination-selected-item-h},
+ "pagination-selected-item-s": #{$pagination-selected-item-s},
+ "pagination-selected-item-l": #{$pagination-selected-item-l},
+ "pagination-selected-item-background-l": #{$pagination-selected-item-background-l},
+ "pagination-selected-item-border-l": #{$pagination-selected-item-border-l},
+ "pagination-selected-item-color-l": #{$pagination-selected-item-color-l},
+ )
+ );
+}
+
+.#{iv.$class-prefix}pagination {
+ @extend %block;
+
+ font-size: cv.getVar("size-normal");
+ margin: cv.getVar("pagination-margin");
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-large");
+ }
+
+ &.#{iv.$class-prefix}is-rounded {
+ .#{iv.$class-prefix}pagination-previous,
+ .#{iv.$class-prefix}pagination-next {
+ padding-left: 1em;
+ padding-right: 1em;
+ border-radius: cv.getVar("radius-rounded");
+ }
+
+ .#{iv.$class-prefix}pagination-link {
+ border-radius: cv.getVar("radius-rounded");
+ }
+ }
+}
+
+.#{iv.$class-prefix}pagination,
+.#{iv.$class-prefix}pagination-list {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ text-align: center;
+}
+
+.#{iv.$class-prefix}pagination-previous,
+.#{iv.$class-prefix}pagination-next,
+.#{iv.$class-prefix}pagination-link,
+.#{iv.$class-prefix}pagination-ellipsis {
+ @extend %control;
+ @extend %unselectable;
+ color: hsl(
+ #{cv.getVar("pagination-item-h")},
+ #{cv.getVar("pagination-item-s")},
+ #{cv.getVar("pagination-item-color-l")}
+ );
+ font-size: cv.getVar("pagination-item-font-size");
+ justify-content: center;
+ margin: cv.getVar("pagination-item-margin");
+ padding-left: cv.getVar("pagination-item-padding-left");
+ padding-right: cv.getVar("pagination-item-padding-right");
+ text-align: center;
+}
+
+.#{iv.$class-prefix}pagination-previous,
+.#{iv.$class-prefix}pagination-next,
+.#{iv.$class-prefix}pagination-link {
+ background-color: hsl(
+ #{cv.getVar("pagination-item-h")},
+ #{cv.getVar("pagination-item-s")},
+ calc(
+ #{cv.getVar("pagination-item-background-l")} + #{cv.getVar(
+ "pagination-item-background-l-delta"
+ )}
+ )
+ );
+ border-color: hsl(
+ #{cv.getVar("pagination-item-h")},
+ #{cv.getVar("pagination-item-s")},
+ calc(
+ #{cv.getVar("pagination-item-border-l")} + #{cv.getVar(
+ "pagination-item-border-l-delta"
+ )}
+ )
+ );
+ border-style: cv.getVar("pagination-item-border-style");
+ border-width: cv.getVar("pagination-item-border-width");
+ box-shadow:
+ 0px 0.0625em 0.125em
+ hsla(
+ cv.getVar("pagination-item-outer-shadow-h"),
+ cv.getVar("pagination-item-outer-shadow-s"),
+ cv.getVar("pagination-item-outer-shadow-l"),
+ cv.getVar("pagination-item-outer-shadow-a")
+ ),
+ 0px 0.125em 0.25em
+ hsla(
+ cv.getVar("pagination-item-outer-shadow-h"),
+ cv.getVar("pagination-item-outer-shadow-s"),
+ cv.getVar("pagination-item-outer-shadow-l"),
+ cv.getVar("pagination-item-outer-shadow-a")
+ );
+ color: hsl(
+ #{cv.getVar("pagination-item-h")},
+ #{cv.getVar("pagination-item-s")},
+ #{cv.getVar("pagination-item-color-l")}
+ );
+ min-width: cv.getVar("pagination-min-width");
+ transition-duration: cv.getVar("duration");
+ transition-property: background-color, border-color, box-shadow, color;
+
+ &:hover {
+ @include cv.register-vars(
+ (
+ "pagination-item-background-l-delta": #{cv.getVar(
+ "pagination-item-hover-background-l-delta"
+ )},
+ "pagination-item-border-l-delta": #{cv.getVar(
+ "pagination-item-hover-border-l-delta"
+ )},
+ )
+ );
+ }
+
+ &:focus {
+ @include cv.register-vars(
+ (
+ "pagination-item-background-l-delta": #{cv.getVar(
+ "pagination-item-hover-background-l-delta"
+ )},
+ "pagination-item-border-l-delta": #{cv.getVar(
+ "pagination-item-hover-border-l-delta"
+ )},
+ )
+ );
+ }
+
+ &:active {
+ box-shadow: cv.getVar("pagination-shadow-inset");
+ }
+
+ &[disabled],
+ &.#{iv.$class-prefix}is-disabled {
+ background-color: cv.getVar("pagination-disabled-background-color");
+ border-color: cv.getVar("pagination-disabled-border-color");
+ box-shadow: none;
+ color: cv.getVar("pagination-disabled-color");
+ opacity: 0.5;
+ }
+}
+
+.#{iv.$class-prefix}pagination-previous,
+.#{iv.$class-prefix}pagination-next {
+ padding-left: cv.getVar("pagination-nav-padding-left");
+ padding-right: cv.getVar("pagination-nav-padding-right");
+ white-space: nowrap;
+}
+
+.#{iv.$class-prefix}pagination-link {
+ &.#{iv.$class-prefix}is-current,
+ &.#{iv.$class-prefix}is-selected {
+ @include cv.register-vars(
+ (
+ "pagination-item-h": #{cv.getVar("pagination-selected-item-h")},
+ "pagination-item-s": #{cv.getVar("pagination-selected-item-s")},
+ "pagination-item-l": #{cv.getVar("pagination-selected-item-l")},
+ "pagination-item-background-l": #{cv.getVar(
+ "pagination-selected-item-background-l"
+ )},
+ "pagination-item-border-l": #{cv.getVar(
+ "pagination-selected-item-border-l"
+ )},
+ "pagination-item-color-l": #{cv.getVar(
+ "pagination-selected-item-color-l"
+ )},
+ )
+ );
+ }
+}
+
+.#{iv.$class-prefix}pagination-ellipsis {
+ color: cv.getVar("pagination-ellipsis-color");
+ pointer-events: none;
+}
+
+.#{iv.$class-prefix}pagination-list {
+ flex-wrap: wrap;
+
+ li {
+ list-style: none;
+ }
+}
+
+@include mx.mobile {
+ .#{iv.$class-prefix}pagination {
+ flex-wrap: wrap;
+ }
+
+ .#{iv.$class-prefix}pagination-previous,
+ .#{iv.$class-prefix}pagination-next {
+ flex-grow: 1;
+ flex-shrink: 1;
+ }
+
+ .#{iv.$class-prefix}pagination-list {
+ li {
+ flex-grow: 1;
+ flex-shrink: 1;
+ }
+ }
+}
+
+@include mx.tablet {
+ .#{iv.$class-prefix}pagination-list {
+ flex-grow: 1;
+ flex-shrink: 1;
+ justify-content: flex-start;
+ order: 1;
+ }
+
+ .#{iv.$class-prefix}pagination-previous,
+ .#{iv.$class-prefix}pagination-next,
+ .#{iv.$class-prefix}pagination-link,
+ .#{iv.$class-prefix}pagination-ellipsis {
+ margin-bottom: 0;
+ margin-top: 0;
+ }
+
+ .#{iv.$class-prefix}pagination-previous {
+ order: 2;
+ }
+
+ .#{iv.$class-prefix}pagination-next {
+ order: 3;
+ }
+
+ .#{iv.$class-prefix}pagination {
+ justify-content: space-between;
+ margin-bottom: 0;
+ margin-top: 0;
+
+ &.#{iv.$class-prefix}is-centered {
+ .#{iv.$class-prefix}pagination-previous {
+ order: 1;
+ }
+
+ .#{iv.$class-prefix}pagination-list {
+ justify-content: center;
+ order: 2;
+ }
+
+ .#{iv.$class-prefix}pagination-next {
+ order: 3;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-right {
+ .#{iv.$class-prefix}pagination-previous {
+ order: 1;
+ }
+
+ .#{iv.$class-prefix}pagination-next {
+ order: 2;
+ }
+
+ .#{iv.$class-prefix}pagination-list {
+ justify-content: flex-end;
+ order: 3;
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/panel.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/panel.scss
new file mode 100644
index 0000000..0926195
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/panel.scss
@@ -0,0 +1,218 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$panel-margin: cv.getVar("block-spacing") !default;
+$panel-item-border: 1px solid cv.getVar("border-weak") !default;
+$panel-radius: cv.getVar("radius-large") !default;
+$panel-shadow: cv.getVar("shadow") !default;
+
+$panel-heading-line-height: 1.25 !default;
+$panel-heading-padding: 1em 1.25em !default;
+$panel-heading-radius: cv.getVar("radius") !default;
+$panel-heading-size: 1.25em !default;
+$panel-heading-weight: cv.getVar("weight-bold") !default;
+
+$panel-tabs-font-size: 1em !default;
+$panel-tab-border-bottom-color: cv.getVar("border") !default;
+$panel-tab-border-bottom-style: solid !default;
+$panel-tab-border-bottom-width: 1px !default;
+$panel-tab-active-color: cv.getVar("link-active") !default;
+
+$panel-list-item-color: cv.getVar("text") !default;
+$panel-list-item-hover-color: cv.getVar("link") !default;
+
+$panel-block-color: cv.getVar("text-strong") !default;
+$panel-block-hover-background-color: cv.getVar("background") !default;
+$panel-block-active-border-left-color: cv.getVar("link") !default;
+$panel-block-active-color: cv.getVar("link-active") !default;
+$panel-block-active-icon-color: cv.getVar("link") !default;
+
+$panel-icon-color: cv.getVar("text-weak") !default;
+$panel-colors: dv.$colors !default;
+
+.#{iv.$class-prefix}panel {
+ @include cv.register-vars(
+ (
+ "panel-margin": #{$panel-margin},
+ "panel-item-border": #{$panel-item-border},
+ "panel-radius": #{$panel-radius},
+ "panel-shadow": #{$panel-shadow},
+ "panel-heading-line-height": #{$panel-heading-line-height},
+ "panel-heading-padding": #{$panel-heading-padding},
+ "panel-heading-radius": #{$panel-heading-radius},
+ "panel-heading-size": #{$panel-heading-size},
+ "panel-heading-weight": #{$panel-heading-weight},
+ "panel-tabs-font-size": #{$panel-tabs-font-size},
+ "panel-tab-border-bottom-color": #{$panel-tab-border-bottom-color},
+ "panel-tab-border-bottom-style": #{$panel-tab-border-bottom-style},
+ "panel-tab-border-bottom-width": #{$panel-tab-border-bottom-width},
+ "panel-tab-active-color": #{$panel-tab-active-color},
+ "panel-list-item-color": #{$panel-list-item-color},
+ "panel-list-item-hover-color": #{$panel-list-item-hover-color},
+ "panel-block-color": #{$panel-block-color},
+ "panel-block-hover-background-color": #{$panel-block-hover-background-color},
+ "panel-block-active-border-left-color": #{$panel-block-active-border-left-color},
+ "panel-block-active-color": #{$panel-block-active-color},
+ "panel-block-active-icon-color": #{$panel-block-active-icon-color},
+ "panel-icon-color": #{$panel-icon-color},
+ )
+ );
+}
+
+.#{iv.$class-prefix}panel {
+ @include cv.register-vars(
+ (
+ "panel-h": #{cv.getVar("scheme-h")},
+ "panel-s": #{cv.getVar("scheme-s")},
+ "panel-color-l": #{cv.getVar("text-l")},
+ "panel-heading-background-l": #{cv.getVar("text-l")},
+ "panel-heading-color-l": #{cv.getVar("text-invert-l")},
+ )
+ );
+
+ border-radius: cv.getVar("panel-radius");
+ box-shadow: cv.getVar("panel-shadow");
+ font-size: cv.getVar("size-normal");
+
+ &:not(:last-child) {
+ margin-bottom: cv.getVar("panel-margin");
+ }
+
+ // Colors
+ @each $name, $components in $panel-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "panel-h": #{cv.getVar($name, "", "-h")},
+ "panel-s": #{cv.getVar($name, "", "-s")},
+ "panel-color-l": #{cv.getVar($name, "", "-l")},
+ "panel-heading-background-l": #{cv.getVar($name, "", "-l")},
+ "panel-heading-color-l": #{cv.getVar($name, "", "-invert-l")},
+ )
+ );
+ }
+ }
+}
+
+.#{iv.$class-prefix}panel-tabs,
+.#{iv.$class-prefix}panel-block {
+ &:not(:last-child) {
+ border-bottom: cv.getVar("panel-item-border");
+ }
+}
+
+.#{iv.$class-prefix}panel-heading {
+ background-color: hsl(
+ cv.getVar("panel-h"),
+ cv.getVar("panel-s"),
+ cv.getVar("panel-heading-background-l")
+ );
+ border-radius: cv.getVar("panel-radius") cv.getVar("panel-radius") 0 0;
+ color: hsl(
+ cv.getVar("panel-h"),
+ cv.getVar("panel-s"),
+ cv.getVar("panel-heading-color-l")
+ );
+ font-size: cv.getVar("panel-heading-size");
+ font-weight: cv.getVar("panel-heading-weight");
+ line-height: cv.getVar("panel-heading-line-height");
+ padding: cv.getVar("panel-heading-padding");
+}
+
+.#{iv.$class-prefix}panel-tabs {
+ align-items: flex-end;
+ display: flex;
+ font-size: cv.getVar("panel-tabs-font-size");
+ justify-content: center;
+
+ a {
+ border-bottom-color: cv.getVar("panel-tab-border-bottom-color");
+ border-bottom-style: cv.getVar("panel-tab-border-bottom-style");
+ border-bottom-width: cv.getVar("panel-tab-border-bottom-width");
+ margin-bottom: calc(-1 * #{$panel-tab-border-bottom-width});
+ padding: 0.75em;
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-active {
+ border-bottom-color: hsl(
+ cv.getVar("panel-h"),
+ cv.getVar("panel-s"),
+ cv.getVar("panel-color-l")
+ );
+ color: cv.getVar("panel-tab-active-color");
+ }
+ }
+}
+
+.#{iv.$class-prefix}panel-list {
+ a {
+ color: cv.getVar("panel-list-item-color");
+
+ &:hover {
+ color: cv.getVar("panel-list-item-hover-color");
+ }
+ }
+}
+
+.#{iv.$class-prefix}panel-block {
+ align-items: center;
+ color: cv.getVar("panel-block-color");
+ display: flex;
+ justify-content: flex-start;
+ padding: 0.75em 1em;
+
+ input[type="checkbox"] {
+ margin-inline-end: 0.75em;
+ }
+
+ & > .#{iv.$class-prefix}control {
+ flex-grow: 1;
+ flex-shrink: 1;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-wrapped {
+ flex-wrap: wrap;
+ }
+
+ &.#{iv.$class-prefix}is-active {
+ border-left-color: cv.getVar("panel-block-active-border-left-color");
+ color: cv.getVar("panel-block-active-color");
+
+ .#{iv.$class-prefix}panel-icon {
+ color: hsl(
+ cv.getVar("panel-h"),
+ cv.getVar("panel-s"),
+ cv.getVar("panel-color-l")
+ );
+ }
+ }
+
+ &:last-child {
+ border-end-start-radius: cv.getVar("panel-radius");
+ border-end-end-radius: cv.getVar("panel-radius");
+ }
+}
+
+a.#{iv.$class-prefix}panel-block,
+label.#{iv.$class-prefix}panel-block {
+ cursor: pointer;
+
+ &:hover {
+ background-color: cv.getVar("panel-block-hover-background-color");
+ }
+}
+
+.#{iv.$class-prefix}panel-icon {
+ @include mx.fa(1em, 1em);
+ color: cv.getVar("panel-icon-color");
+ margin-inline-end: 0.75em;
+
+ .#{iv.$class-prefix}fa {
+ font-size: inherit;
+ line-height: inherit;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/tabs.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/tabs.scss
new file mode 100644
index 0000000..072282c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/components/tabs.scss
@@ -0,0 +1,273 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$tabs-border-bottom-color: cv.getVar("border") !default;
+$tabs-border-bottom-style: solid !default;
+$tabs-border-bottom-width: 1px !default;
+$tabs-link-color: cv.getVar("text") !default;
+$tabs-link-hover-border-bottom-color: cv.getVar("text-strong") !default;
+$tabs-link-hover-color: cv.getVar("text-strong") !default;
+$tabs-link-active-border-bottom-color: cv.getVar("link-text") !default;
+$tabs-link-active-color: cv.getVar("link-text") !default;
+$tabs-link-padding: 0.5em 1em !default;
+
+$tabs-boxed-link-radius: cv.getVar("radius") !default;
+$tabs-boxed-link-hover-background-color: cv.getVar("background") !default;
+$tabs-boxed-link-hover-border-bottom-color: cv.getVar("border") !default;
+
+$tabs-boxed-link-active-background-color: cv.getVar("scheme-main") !default;
+$tabs-boxed-link-active-border-color: cv.getVar("border") !default;
+$tabs-boxed-link-active-border-bottom-color: transparent !default;
+
+$tabs-toggle-link-border-color: cv.getVar("border") !default;
+$tabs-toggle-link-border-style: solid !default;
+$tabs-toggle-link-border-width: 1px !default;
+$tabs-toggle-link-hover-background-color: cv.getVar("background") !default;
+$tabs-toggle-link-hover-border-color: cv.getVar("border-hover") !default;
+$tabs-toggle-link-radius: cv.getVar("radius") !default;
+$tabs-toggle-link-active-background-color: cv.getVar("link") !default;
+$tabs-toggle-link-active-border-color: cv.getVar("link") !default;
+$tabs-toggle-link-active-color: cv.getVar("link-invert") !default;
+
+.#{iv.$class-prefix}tabs {
+ @include cv.register-vars(
+ (
+ "tabs-border-bottom-color": #{$tabs-border-bottom-color},
+ "tabs-border-bottom-style": #{$tabs-border-bottom-style},
+ "tabs-border-bottom-width": #{$tabs-border-bottom-width},
+ "tabs-link-color": #{$tabs-link-color},
+ "tabs-link-hover-border-bottom-color": #{$tabs-link-hover-border-bottom-color},
+ "tabs-link-hover-color": #{$tabs-link-hover-color},
+ "tabs-link-active-border-bottom-color": #{$tabs-link-active-border-bottom-color},
+ "tabs-link-active-color": #{$tabs-link-active-color},
+ "tabs-link-padding": #{$tabs-link-padding},
+ "tabs-boxed-link-radius": #{$tabs-boxed-link-radius},
+ "tabs-boxed-link-hover-background-color": #{$tabs-boxed-link-hover-background-color},
+ "tabs-boxed-link-hover-border-bottom-color": #{$tabs-boxed-link-hover-border-bottom-color},
+ "tabs-boxed-link-active-background-color": #{$tabs-boxed-link-active-background-color},
+ "tabs-boxed-link-active-border-color": #{$tabs-boxed-link-active-border-color},
+ "tabs-boxed-link-active-border-bottom-color": #{$tabs-boxed-link-active-border-bottom-color},
+ "tabs-toggle-link-border-color": #{$tabs-toggle-link-border-color},
+ "tabs-toggle-link-border-style": #{$tabs-toggle-link-border-style},
+ "tabs-toggle-link-border-width": #{$tabs-toggle-link-border-width},
+ "tabs-toggle-link-hover-background-color": #{$tabs-toggle-link-hover-background-color},
+ "tabs-toggle-link-hover-border-color": #{$tabs-toggle-link-hover-border-color},
+ "tabs-toggle-link-radius": #{$tabs-toggle-link-radius},
+ "tabs-toggle-link-active-background-color": #{$tabs-toggle-link-active-background-color},
+ "tabs-toggle-link-active-border-color": #{$tabs-toggle-link-active-border-color},
+ "tabs-toggle-link-active-color": #{$tabs-toggle-link-active-color},
+ )
+ );
+}
+
+.#{iv.$class-prefix}tabs {
+ @extend %block;
+ @extend %unselectable;
+ @include mx.overflow-touch;
+ align-items: stretch;
+ display: flex;
+ font-size: cv.getVar("size-normal");
+ justify-content: space-between;
+ overflow: hidden;
+ overflow-x: auto;
+ white-space: nowrap;
+
+ a {
+ align-items: center;
+ border-bottom-color: cv.getVar("tabs-border-bottom-color");
+ border-bottom-style: cv.getVar("tabs-border-bottom-style");
+ border-bottom-width: cv.getVar("tabs-border-bottom-width");
+ color: cv.getVar("tabs-link-color");
+ display: flex;
+ justify-content: center;
+ margin-bottom: calc(-1 * #{cv.getVar("tabs-border-bottom-width")});
+ padding: cv.getVar("tabs-link-padding");
+ transition-duration: cv.getVar("duration");
+ transition-property: background-color, border-color, color;
+ vertical-align: top;
+
+ &:hover {
+ border-bottom-color: cv.getVar("tabs-link-hover-border-bottom-color");
+ color: cv.getVar("tabs-link-hover-color");
+ }
+ }
+
+ li {
+ display: block;
+
+ &.#{iv.$class-prefix}is-active {
+ a {
+ border-bottom-color: cv.getVar("tabs-link-active-border-bottom-color");
+ color: cv.getVar("tabs-link-active-color");
+ }
+ }
+ }
+
+ ul {
+ align-items: center;
+ border-bottom-color: cv.getVar("tabs-border-bottom-color");
+ border-bottom-style: cv.getVar("tabs-border-bottom-style");
+ border-bottom-width: cv.getVar("tabs-border-bottom-width");
+ display: flex;
+ flex-grow: 1;
+ flex-shrink: 0;
+ justify-content: flex-start;
+
+ &.#{iv.$class-prefix}is-left {
+ padding-right: 0.75em;
+ }
+
+ &.#{iv.$class-prefix}is-center {
+ flex: none;
+ justify-content: center;
+ padding-left: 0.75em;
+ padding-right: 0.75em;
+ }
+
+ &.#{iv.$class-prefix}is-right {
+ justify-content: flex-end;
+ padding-left: 0.75em;
+ }
+ }
+
+ .#{iv.$class-prefix}icon {
+ &:first-child {
+ margin-inline-end: 0.5em;
+ }
+
+ &:last-child {
+ margin-inline-start: 0.5em;
+ }
+ }
+
+ // Alignment
+ &.#{iv.$class-prefix}is-centered {
+ ul {
+ justify-content: center;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-right {
+ ul {
+ justify-content: flex-end;
+ }
+ }
+
+ // Styles
+ &.#{iv.$class-prefix}is-boxed {
+ a {
+ border: 1px solid transparent;
+ border-start-start-radius: cv.getVar("tabs-boxed-link-radius");
+ border-start-end-radius: cv.getVar("tabs-boxed-link-radius");
+
+ &:hover {
+ background-color: cv.getVar("tabs-boxed-link-hover-background-color");
+ border-bottom-color: cv.getVar(
+ "tabs-boxed-link-hover-border-bottom-color"
+ );
+ }
+ }
+
+ li {
+ &.#{iv.$class-prefix}is-active {
+ a {
+ background-color: cv.getVar(
+ "tabs-boxed-link-active-background-color"
+ );
+ border-color: cv.getVar("tabs-boxed-link-active-border-color");
+ border-bottom-color: cv.getVar(
+ "tabs-boxed-link-active-border-bottom-color"
+ ) !important;
+ }
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-fullwidth {
+ li {
+ flex-grow: 1;
+ flex-shrink: 0;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-toggle {
+ a {
+ border-color: cv.getVar("tabs-toggle-link-border-color");
+ border-style: cv.getVar("tabs-toggle-link-border-style");
+ border-width: cv.getVar("tabs-toggle-link-border-width");
+ margin-bottom: 0;
+ position: relative;
+
+ &:hover {
+ background-color: cv.getVar("tabs-toggle-link-hover-background-color");
+ border-color: cv.getVar("tabs-toggle-link-hover-border-color");
+ z-index: 2;
+ }
+ }
+
+ li {
+ & + li {
+ margin-inline-start: calc(
+ -1 * #{cv.getVar("tabs-toggle-link-border-width")}
+ );
+ }
+
+ &:first-child a {
+ border-start-start-radius: cv.getVar("tabs-toggle-link-radius");
+ border-end-start-radius: cv.getVar("tabs-toggle-link-radius");
+ }
+
+ &:last-child a {
+ border-start-end-radius: cv.getVar("tabs-toggle-link-radius");
+ border-end-end-radius: cv.getVar("tabs-toggle-link-radius");
+ }
+
+ &.#{iv.$class-prefix}is-active {
+ a {
+ background-color: cv.getVar(
+ "tabs-toggle-link-active-background-color"
+ );
+ border-color: cv.getVar("tabs-toggle-link-active-border-color");
+ color: cv.getVar("tabs-toggle-link-active-color");
+ z-index: 1;
+ }
+ }
+ }
+
+ ul {
+ border-bottom: none;
+ }
+
+ &.#{iv.$class-prefix}is-toggle-rounded {
+ li {
+ &:first-child a {
+ border-start-start-radius: cv.getVar("radius-rounded");
+ border-end-start-radius: cv.getVar("radius-rounded");
+ padding-inline-start: 1.25em;
+ }
+
+ &:last-child a {
+ border-start-end-radius: cv.getVar("radius-rounded");
+ border-end-end-radius: cv.getVar("radius-rounded");
+ padding-inline-end: 1.25em;
+ }
+ }
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-large");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/_index.scss
new file mode 100644
index 0000000..68034bf
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/_index.scss
@@ -0,0 +1,16 @@
+/* Bulma Elements */
+@charset "utf-8";
+
+@forward "block";
+@forward "box";
+@forward "button";
+@forward "content";
+@forward "delete";
+@forward "icon";
+@forward "image";
+@forward "loader";
+@forward "notification";
+@forward "progress";
+@forward "table";
+@forward "tag";
+@forward "title";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/block.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/block.scss
new file mode 100644
index 0000000..34fee01
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/block.scss
@@ -0,0 +1,6 @@
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+
+.#{iv.$class-prefix}block {
+ @extend %block;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/box.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/box.scss
new file mode 100644
index 0000000..060f53a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/box.scss
@@ -0,0 +1,59 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+
+$box-background-color: cv.getVar("scheme-main") !default;
+$box-color: cv.getVar("text") !default;
+$box-radius: cv.getVar("radius-large") !default;
+$box-shadow: cv.getVar("shadow") !default;
+$box-padding: 1.25rem !default;
+
+$box-link-hover-shadow:
+ 0 0.5em 1em -0.125em hsla(#{cv.getVar("scheme-h")}, #{cv.getVar("scheme-s")}, #{cv.getVar(
+ "scheme-invert-l"
+ )}, 0.1),
+ 0 0 0 1px cv.getVar("link") !default;
+$box-link-active-shadow:
+ inset 0 1px 2px
+ hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")},
+ 0.2
+ ),
+ 0 0 0 1px cv.getVar("link") !default;
+
+.#{iv.$class-prefix}box {
+ @include cv.register-vars(
+ (
+ "box-background-color": #{$box-background-color},
+ "box-color": #{$box-color},
+ "box-radius": #{$box-radius},
+ "box-shadow": #{$box-shadow},
+ "box-padding": #{$box-padding},
+ "box-link-hover-shadow": #{$box-link-hover-shadow},
+ "box-link-active-shadow": #{$box-link-active-shadow},
+ )
+ );
+}
+
+.#{iv.$class-prefix}box {
+ @extend %block;
+ background-color: cv.getVar("box-background-color");
+ border-radius: cv.getVar("box-radius");
+ box-shadow: cv.getVar("box-shadow");
+ color: cv.getVar("box-color");
+ display: block;
+ padding: cv.getVar("box-padding");
+}
+
+a.#{iv.$class-prefix}box {
+ &:hover,
+ &:focus {
+ box-shadow: cv.getVar("box-link-hover-shadow");
+ }
+
+ &:active {
+ box-shadow: cv.getVar("box-link-active-shadow");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/button.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/button.scss
new file mode 100644
index 0000000..06ac4b6
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/button.scss
@@ -0,0 +1,659 @@
+@use "sass:list";
+
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$button-h: #{cv.getVar("scheme-h")};
+$button-s: #{cv.getVar("scheme-s")};
+$button-l: #{cv.getVar("scheme-main-l")};
+$button-background-l: #{cv.getVar("scheme-main-l")};
+$button-background-l-delta: 0%;
+$button-hover-background-l-delta: #{cv.getVar("hover-background-l-delta")};
+$button-active-background-l-delta: #{cv.getVar("active-background-l-delta")};
+$button-color-l: #{cv.getVar("text-strong-l")};
+$button-border-l: #{cv.getVar("border-l")};
+$button-border-l-delta: 0%;
+$button-hover-border-l-delta: #{cv.getVar("hover-border-l-delta")};
+$button-active-border-l-delta: #{cv.getVar("active-border-l-delta")};
+$button-focus-border-l-delta: #{cv.getVar("focus-border-l-delta")};
+$button-outer-shadow-h: 0;
+$button-outer-shadow-s: 0%;
+$button-outer-shadow-l: 20%;
+$button-outer-shadow-a: 0.05;
+
+$button-weight: cv.getVar("weight-medium") !default;
+$button-family: false !default;
+
+$button-border-color: cv.getVar("border") !default;
+$button-border-style: solid !default;
+$button-border-width: cv.getVar("control-border-width") !default;
+
+$button-padding-vertical: 0.5em !default;
+$button-padding-horizontal: 1em !default;
+$button-rounded-padding-horizontal-offset: 0.25em !default;
+
+$button-focus-border-color: cv.getVar("link-focus-border") !default;
+$button-focus-box-shadow-size: 0 0 0 0.125em !default;
+$button-focus-box-shadow-color: hsla(
+ #{cv.getVar("link-h")},
+ #{cv.getVar("link-s")},
+ #{cv.getVar("link-on-scheme-l")},
+ 0.25
+) !default;
+
+$button-active-color: cv.getVar("link-active") !default;
+$button-active-border-color: cv.getVar("link-active-border") !default;
+
+$button-text-color: cv.getVar("text") !default;
+$button-text-decoration: underline !default;
+$button-text-hover-background-color: cv.getVar("background") !default;
+$button-text-hover-color: cv.getVar("text-strong") !default;
+
+$button-ghost-background: none !default;
+$button-ghost-border-color: transparent !default;
+$button-ghost-color: cv.getVar("link-text") !default;
+$button-ghost-decoration: none !default;
+$button-ghost-hover-color: cv.getVar("link") !default;
+$button-ghost-hover-decoration: underline !default;
+
+$button-disabled-background-color: cv.getVar("scheme-main") !default;
+$button-disabled-border-color: cv.getVar("border") !default;
+$button-disabled-shadow: none !default;
+$button-disabled-opacity: 0.5 !default;
+
+$button-static-color: cv.getVar("text-weak") !default;
+$button-static-background-color: cv.getVar("scheme-main-ter") !default;
+$button-static-border-color: cv.getVar("border") !default;
+
+$button-colors: dv.$colors !default;
+$button-responsive-sizes: (
+ "mobile": (
+ "small": calc(#{cv.getVar("size-small")} * 0.75),
+ "normal": calc(#{cv.getVar("size-small")} * 0.875),
+ "medium": cv.getVar("size-small"),
+ "large": cv.getVar("size-normal"),
+ ),
+ "tablet-only": (
+ "small": calc(#{cv.getVar("size-small")} * 0.875),
+ "normal": cv.getVar("size-small"),
+ "medium": cv.getVar("size-normal"),
+ "large": cv.getVar("size-medium"),
+ ),
+) !default;
+
+$no-palette: ("white", "black", "light", "dark");
+
+.#{iv.$class-prefix}button {
+ @include cv.register-vars(
+ (
+ "button-family": #{$button-family},
+ "button-weight": #{$button-weight},
+ "button-border-color": #{$button-border-color},
+ "button-border-style": #{$button-border-style},
+ "button-border-width": #{$button-border-width},
+ "button-padding-vertical": #{$button-padding-vertical},
+ "button-padding-horizontal": #{$button-padding-horizontal},
+ "button-focus-border-color": #{$button-focus-border-color},
+ "button-focus-box-shadow-size": #{$button-focus-box-shadow-size},
+ "button-focus-box-shadow-color": #{$button-focus-box-shadow-color},
+ "button-active-color": #{$button-active-color},
+ "button-active-border-color": #{$button-active-border-color},
+ "button-text-color": #{$button-text-color},
+ "button-text-decoration": #{$button-text-decoration},
+ "button-text-hover-background-color": #{$button-text-hover-background-color},
+ "button-text-hover-color": #{$button-text-hover-color},
+ "button-ghost-background": #{$button-ghost-background},
+ "button-ghost-border-color": #{$button-ghost-border-color},
+ "button-ghost-color": #{$button-ghost-color},
+ "button-ghost-decoration": #{$button-ghost-decoration},
+ "button-ghost-hover-color": #{$button-ghost-hover-color},
+ "button-ghost-hover-decoration": #{$button-ghost-hover-decoration},
+ "button-disabled-background-color": #{$button-disabled-background-color},
+ "button-disabled-border-color": #{$button-disabled-border-color},
+ "button-disabled-shadow": #{$button-disabled-shadow},
+ "button-disabled-opacity": #{$button-disabled-opacity},
+ "button-static-color": #{$button-static-color},
+ "button-static-background-color": #{$button-static-background-color},
+ "button-static-border-color": #{$button-static-border-color},
+ )
+ );
+}
+
+.#{iv.$class-prefix}button {
+ @include cv.register-vars(
+ (
+ "button-h": #{$button-h},
+ "button-s": #{$button-s},
+ "button-l": #{$button-l},
+ "button-background-l": #{$button-background-l},
+ "button-background-l-delta": #{$button-background-l-delta},
+ "button-hover-background-l-delta": #{$button-hover-background-l-delta},
+ "button-active-background-l-delta": #{$button-active-background-l-delta},
+ "button-color-l": #{$button-color-l},
+ "button-border-l": #{$button-border-l},
+ "button-border-l-delta": #{$button-border-l-delta},
+ "button-hover-border-l-delta": #{$button-hover-border-l-delta},
+ "button-active-border-l-delta": #{$button-active-border-l-delta},
+ "button-focus-border-l-delta": #{$button-focus-border-l-delta},
+ "button-outer-shadow-h": #{$button-outer-shadow-h},
+ "button-outer-shadow-s": #{$button-outer-shadow-s},
+ "button-outer-shadow-l": #{$button-outer-shadow-l},
+ "button-outer-shadow-a": #{$button-outer-shadow-a},
+ "loading-color":
+ hsl(
+ #{cv.getVar("button-h")},
+ #{cv.getVar("button-s")},
+ #{cv.getVar("button-color-l")}
+ ),
+ )
+ );
+
+ @extend %control;
+ @extend %unselectable;
+
+ background-color: hsl(
+ #{cv.getVar("button-h")},
+ #{cv.getVar("button-s")},
+ calc(
+ #{cv.getVar("button-background-l")} + #{cv.getVar(
+ "button-background-l-delta"
+ )}
+ )
+ );
+ border-color: hsl(
+ #{cv.getVar("button-h")},
+ #{cv.getVar("button-s")},
+ calc(
+ #{cv.getVar("button-border-l")} + #{cv.getVar("button-border-l-delta")}
+ )
+ );
+ border-style: cv.getVar("button-border-style");
+ border-width: cv.getVar("button-border-width");
+ box-shadow:
+ 0px 0.0625em 0.125em
+ hsla(
+ cv.getVar("button-outer-shadow-h"),
+ cv.getVar("button-outer-shadow-s"),
+ cv.getVar("button-outer-shadow-l"),
+ cv.getVar("button-outer-shadow-a")
+ ),
+ 0px 0.125em 0.25em
+ hsla(
+ cv.getVar("button-outer-shadow-h"),
+ cv.getVar("button-outer-shadow-s"),
+ cv.getVar("button-outer-shadow-l"),
+ cv.getVar("button-outer-shadow-a")
+ );
+ color: hsl(
+ #{cv.getVar("button-h")},
+ #{cv.getVar("button-s")},
+ #{cv.getVar("button-color-l")}
+ );
+ cursor: pointer;
+ font-weight: cv.getVar("button-weight");
+ height: auto;
+ justify-content: center;
+ padding-bottom: calc(
+ #{cv.getVar("button-padding-vertical")} - #{cv.getVar(
+ "button-border-width"
+ )}
+ );
+ padding-left: calc(
+ #{cv.getVar("button-padding-horizontal")} - #{cv.getVar(
+ "button-border-width"
+ )}
+ );
+ padding-right: calc(
+ #{cv.getVar("button-padding-horizontal")} - #{cv.getVar(
+ "button-border-width"
+ )}
+ );
+ padding-top: calc(
+ #{cv.getVar("button-padding-vertical")} - #{cv.getVar(
+ "button-border-width"
+ )}
+ );
+ text-align: center;
+ white-space: nowrap;
+
+ @if $button-family {
+ font-family: cv.getVar("button-family");
+ }
+
+ strong {
+ color: inherit;
+ }
+
+ .#{iv.$class-prefix}icon {
+ &,
+ &.#{iv.$class-prefix}is-small,
+ &.#{iv.$class-prefix}is-medium,
+ &.#{iv.$class-prefix}is-large {
+ height: 1.5em;
+ width: 1.5em;
+ }
+
+ &:first-child:not(:last-child) {
+ margin-inline-start: calc(
+ -0.5 * #{cv.getVar("button-padding-horizontal")}
+ );
+ margin-inline-end: calc(#{cv.getVar("button-padding-horizontal")} * 0.25);
+ }
+
+ &:last-child:not(:first-child) {
+ margin-inline-start: calc(
+ #{cv.getVar("button-padding-horizontal")} * 0.25
+ );
+ margin-inline-end: calc(-0.5 * #{cv.getVar("button-padding-horizontal")});
+ }
+
+ &:first-child:last-child {
+ margin-inline-start: calc(
+ -0.5 * #{cv.getVar("button-padding-horizontal")}
+ );
+ margin-inline-end: calc(-0.5 * #{cv.getVar("button-padding-horizontal")});
+ }
+ }
+
+ // States
+ &:hover,
+ &.#{iv.$class-prefix}is-hovered {
+ @include cv.register-vars(
+ (
+ "button-background-l-delta": #{cv.getVar(
+ "button-hover-background-l-delta"
+ )},
+ "button-border-l-delta": #{cv.getVar("button-hover-border-l-delta")},
+ )
+ );
+ }
+
+ &:focus-visible,
+ &.#{iv.$class-prefix}is-focused {
+ @include cv.register-var("button-border-width", 1px);
+
+ border-color: hsl(
+ #{cv.getVar("focus-h")},
+ #{cv.getVar("focus-s")},
+ #{cv.getVar("focus-l")}
+ );
+ box-shadow: cv.getVar("focus-shadow-size")
+ hsla(
+ cv.getVar("focus-h"),
+ cv.getVar("focus-s"),
+ cv.getVar("focus-l"),
+ cv.getVar("focus-shadow-alpha")
+ );
+ }
+
+ &:active,
+ &.#{iv.$class-prefix}is-active {
+ @include cv.register-vars(
+ (
+ "button-background-l-delta": #{cv.getVar(
+ "button-active-background-l-delta"
+ )},
+ "button-border-l-delta": #{cv.getVar("button-active-border-l-delta")},
+ "button-outer-shadow-a": 0,
+ )
+ );
+ }
+
+ &[disabled],
+ fieldset[disabled] & {
+ background-color: cv.getVar("button-disabled-background-color");
+ border-color: cv.getVar("button-disabled-border-color");
+ box-shadow: cv.getVar("button-disabled-shadow");
+ opacity: cv.getVar("button-disabled-opacity");
+ }
+
+ // Colors
+ @each $name, $pair in $button-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "button-h": #{cv.getVar($name, "", "-h")},
+ "button-s": #{cv.getVar($name, "", "-s")},
+ "button-l": #{cv.getVar($name, "", "-l")},
+ "button-background-l": #{cv.getVar($name, "", "-l")},
+ "button-border-l": #{cv.getVar($name, "", "-l")},
+ "button-border-width": 0px,
+ "button-color-l": #{cv.getVar($name, "", "-invert-l")},
+ "button-outer-shadow-a": 0,
+ )
+ );
+
+ &:focus-visible,
+ &.#{iv.$class-prefix}is-focused {
+ @include cv.register-var("button-border-width", 1px);
+ }
+
+ @if not list.index($no-palette, $name) {
+ &.#{iv.$class-prefix}is-light {
+ @include cv.register-vars(
+ (
+ "button-background-l": #{cv.getVar("light-l")},
+ "button-color-l": #{cv.getVar($name, "", "-light-invert-l")},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}is-dark {
+ @include cv.register-vars(
+ (
+ "button-background-l": #{cv.getVar("dark-l")},
+ "button-color-l": #{cv.getVar($name, "", "-dark-invert-l")},
+ )
+ );
+ }
+ }
+
+ &.#{iv.$class-prefix}is-soft {
+ @include cv.register-vars(
+ (
+ "button-background-l": #{cv.getVar("soft-l")},
+ "button-color-l": #{cv.getVar("soft-invert-l")},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}is-bold {
+ @include cv.register-vars(
+ (
+ "button-background-l": #{cv.getVar("bold-l")},
+ "button-color-l": #{cv.getVar("bold-invert-l")},
+ )
+ );
+ }
+
+ &[disabled],
+ fieldset[disabled] & {
+ background-color: cv.getVar($name);
+ border-color: cv.getVar($name);
+ box-shadow: none;
+ }
+ }
+ }
+
+ // Styles
+ &.#{iv.$class-prefix}is-outlined {
+ @include cv.register-vars(
+ (
+ "button-border-width": max(1px, 0.0625em),
+ "loading-color":
+ hsl(
+ #{cv.getVar("button-h")},
+ #{cv.getVar("button-s")},
+ #{cv.getVar("button-l")}
+ ),
+ )
+ );
+
+ background-color: transparent;
+ border-color: hsl(
+ #{cv.getVar("button-h")},
+ #{cv.getVar("button-s")},
+ #{cv.getVar("button-l")}
+ );
+ color: hsl(
+ #{cv.getVar("button-h")},
+ #{cv.getVar("button-s")},
+ #{cv.getVar("button-l")}
+ );
+
+ &:hover {
+ @include cv.register-vars(
+ (
+ "button-border-width": max(2px, 0.125em),
+ "button-outer-shadow-alpha": 1,
+ )
+ );
+ }
+
+ &:active {
+ @include cv.register-vars(());
+ }
+
+ &[disabled],
+ fieldset[disabled] & {
+ background-color: transparent;
+ box-shadow: none;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-inverted {
+ background-color: hsl(
+ #{cv.getVar("button-h")},
+ #{cv.getVar("button-s")},
+ calc(
+ #{cv.getVar("button-color-l")} + #{cv.getVar(
+ "button-background-l-delta"
+ )}
+ )
+ );
+ color: hsl(
+ #{cv.getVar("button-h")},
+ #{cv.getVar("button-s")},
+ #{cv.getVar("button-background-l")}
+ );
+ }
+
+ &.#{iv.$class-prefix}is-text {
+ background-color: transparent;
+ border-color: transparent;
+ color: cv.getVar("button-text-color");
+ text-decoration: cv.getVar("button-text-decoration");
+
+ &:hover,
+ &.#{iv.$class-prefix}is-hovered {
+ background-color: cv.getVar("button-text-hover-background-color");
+ color: cv.getVar("button-text-hover-color");
+ }
+
+ &:active,
+ &.#{iv.$class-prefix}is-active {
+ // background-color: bulmaDarken($button-text-hover-background-color, 5%);
+ color: cv.getVar("button-text-hover-color");
+ }
+
+ &[disabled],
+ fieldset[disabled] & {
+ background-color: transparent;
+ border-color: transparent;
+ box-shadow: none;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-ghost {
+ background: cv.getVar("button-ghost-background");
+ border-color: cv.getVar("button-ghost-border-color");
+ box-shadow: none;
+ color: cv.getVar("button-ghost-color");
+ text-decoration: cv.getVar("button-ghost-decoration");
+
+ &:hover,
+ &.#{iv.$class-prefix}is-hovered {
+ color: cv.getVar("button-ghost-hover-color");
+ text-decoration: cv.getVar("button-ghost-hover-decoration");
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ @include cv.register-vars(
+ (
+ "control-size": #{cv.getVar("size-small")},
+ "control-radius": #{cv.getVar("radius-small")},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}is-normal {
+ @include cv.register-vars(
+ (
+ "control-size": #{cv.getVar("size-normal")},
+ "control-radius": #{cv.getVar("radius")},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ @include cv.register-vars(
+ (
+ "control-size": #{cv.getVar("size-medium")},
+ "control-radius": #{cv.getVar("radius-medium")},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ @include cv.register-vars(
+ (
+ "control-size": #{cv.getVar("size-large")},
+ "control-radius": #{cv.getVar("radius-medium")},
+ )
+ );
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-fullwidth {
+ display: flex;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-loading {
+ box-shadow: none;
+ color: transparent !important;
+ pointer-events: none;
+
+ &::after {
+ @extend %loader;
+ @include mx.center(1em);
+ position: absolute !important;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-static {
+ background-color: cv.getVar("button-static-background-color");
+ border-color: cv.getVar("button-static-border-color");
+ color: cv.getVar("button-static-color");
+ box-shadow: none;
+ pointer-events: none;
+ }
+
+ &.#{iv.$class-prefix}is-rounded {
+ border-radius: cv.getVar("radius-rounded");
+ padding-left: calc(
+ #{cv.getVar("button-padding-horizontal")} + #{$button-rounded-padding-horizontal-offset} -
+ #{cv.getVar("button-border-width")}
+ );
+ padding-right: calc(
+ #{cv.getVar("button-padding-horizontal")} + #{$button-rounded-padding-horizontal-offset} -
+ #{cv.getVar("button-border-width")}
+ );
+ }
+}
+
+.#{iv.$class-prefix}buttons {
+ @extend %block;
+ align-items: center;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+ justify-content: flex-start;
+
+ // Sizes
+ &.#{iv.$class-prefix}are-small {
+ @include cv.register-vars(
+ (
+ "control-size": #{cv.getVar("size-small")},
+ "control-radius": #{cv.getVar("radius-small")},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}are-medium {
+ @include cv.register-vars(
+ (
+ "control-size": #{cv.getVar("size-medium")},
+ "control-radius": #{cv.getVar("radius-medium")},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}are-large {
+ @include cv.register-vars(
+ (
+ "control-size": #{cv.getVar("size-large")},
+ "control-radius": #{cv.getVar("radius-large")},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}has-addons {
+ gap: 0;
+
+ .#{iv.$class-prefix}button {
+ &:not(:first-child) {
+ border-end-start-radius: 0;
+ border-start-start-radius: 0;
+ }
+
+ &:not(:last-child) {
+ border-end-end-radius: 0;
+ border-start-end-radius: 0;
+ margin-inline-end: -1px;
+ }
+
+ &:hover,
+ &.#{iv.$class-prefix}is-hovered {
+ z-index: 2;
+ }
+
+ &:focus,
+ &.#{iv.$class-prefix}is-focused,
+ &:active,
+ &.#{iv.$class-prefix}is-active,
+ &.#{iv.$class-prefix}is-selected {
+ z-index: 3;
+
+ &:hover {
+ z-index: 4;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-expanded {
+ flex-grow: 1;
+ flex-shrink: 1;
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-centered {
+ justify-content: center;
+ }
+
+ &.#{iv.$class-prefix}is-right {
+ justify-content: flex-end;
+ }
+}
+
+@each $bp-name, $bp-sizes in $button-responsive-sizes {
+ @include mx.breakpoint($bp-name) {
+ @each $size, $value in $bp-sizes {
+ @if $size != "normal" {
+ .#{iv.$class-prefix}button.#{iv.$class-prefix}is-responsive.#{iv.$class-prefix}is-#{$size} {
+ font-size: $value;
+ }
+ } @else {
+ .#{iv.$class-prefix}button.#{iv.$class-prefix}is-responsive,
+ .#{iv.$class-prefix}button.#{iv.$class-prefix}is-responsive.#{iv.$class-prefix}is-normal {
+ font-size: $value;
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/content.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/content.scss
new file mode 100644
index 0000000..0890736
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/content.scss
@@ -0,0 +1,289 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$content-heading-color: #{cv.getVar("text-strong")} !default;
+$content-heading-weight: #{cv.getVar("weight-extrabold")} !default;
+$content-heading-line-height: 1.125 !default;
+
+$content-block-margin-bottom: 1em !default;
+
+$content-blockquote-background-color: #{cv.getVar("background")} !default;
+$content-blockquote-border-left: 5px solid #{cv.getVar("border")} !default;
+$content-blockquote-padding: 1.25em 1.5em !default;
+
+$content-pre-padding: 1.25em 1.5em !default;
+
+$content-table-cell-border: 1px solid #{cv.getVar("border")} !default;
+$content-table-cell-border-width: 0 0 1px !default;
+$content-table-cell-padding: 0.5em 0.75em !default;
+$content-table-cell-heading-color: #{cv.getVar("text-strong")} !default;
+$content-table-head-cell-border-width: 0 0 2px !default;
+$content-table-head-cell-color: #{cv.getVar("text-strong")} !default;
+$content-table-body-last-row-cell-border-bottom-width: 0 !default;
+$content-table-foot-cell-border-width: 2px 0 0 !default;
+$content-table-foot-cell-color: #{cv.getVar("text-strong")} !default;
+
+.#{iv.$class-prefix}content {
+ @include cv.register-vars(
+ (
+ "content-heading-color": #{$content-heading-color},
+ "content-heading-weight": #{$content-heading-weight},
+ "content-heading-line-height": #{$content-heading-line-height},
+ "content-block-margin-bottom": #{$content-block-margin-bottom},
+ "content-blockquote-background-color": #{$content-blockquote-background-color},
+ "content-blockquote-border-left": #{$content-blockquote-border-left},
+ "content-blockquote-padding": #{$content-blockquote-padding},
+ "content-pre-padding": #{$content-pre-padding},
+ "content-table-cell-border": #{$content-table-cell-border},
+ "content-table-cell-border-width": #{$content-table-cell-border-width},
+ "content-table-cell-padding": #{$content-table-cell-padding},
+ "content-table-cell-heading-color": #{$content-table-cell-heading-color},
+ "content-table-head-cell-border-width": #{$content-table-head-cell-border-width},
+ "content-table-head-cell-color": #{$content-table-head-cell-color},
+ "content-table-body-last-row-cell-border-bottom-width": #{$content-table-body-last-row-cell-border-bottom-width},
+ "content-table-foot-cell-border-width": #{$content-table-foot-cell-border-width},
+ "content-table-foot-cell-color": #{$content-table-foot-cell-color},
+ )
+ );
+}
+
+.#{iv.$class-prefix}content {
+ @extend %block;
+
+ // Inline
+ li + li {
+ margin-top: 0.25em;
+ }
+
+ // Block
+ p,
+ dl,
+ ol,
+ ul,
+ blockquote,
+ pre,
+ table {
+ &:not(:last-child) {
+ margin-bottom: cv.getVar("content-block-margin-bottom");
+ }
+ }
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ color: cv.getVar("content-heading-color");
+ font-weight: cv.getVar("content-heading-weight");
+ line-height: cv.getVar("content-heading-line-height");
+ }
+
+ h1 {
+ font-size: 2em;
+ margin-bottom: 0.5em;
+
+ &:not(:first-child) {
+ margin-top: 1em;
+ }
+ }
+
+ h2 {
+ font-size: 1.75em;
+ margin-bottom: 0.5714em;
+
+ &:not(:first-child) {
+ margin-top: 1.1428em;
+ }
+ }
+
+ h3 {
+ font-size: 1.5em;
+ margin-bottom: 0.6666em;
+
+ &:not(:first-child) {
+ margin-top: 1.3333em;
+ }
+ }
+
+ h4 {
+ font-size: 1.25em;
+ margin-bottom: 0.8em;
+ }
+
+ h5 {
+ font-size: 1.125em;
+ margin-bottom: 0.8888em;
+ }
+
+ h6 {
+ font-size: 1em;
+ margin-bottom: 1em;
+ }
+
+ blockquote {
+ background-color: cv.getVar("content-blockquote-background-color");
+ border-inline-start: cv.getVar("content-blockquote-border-left");
+ padding: cv.getVar("content-blockquote-padding");
+ }
+
+ ol {
+ list-style-position: outside;
+ margin-inline-start: 2em;
+
+ &:not(:first-child) {
+ margin-top: 1em;
+ }
+
+ &:not([type]) {
+ list-style-type: decimal;
+
+ &.#{iv.$class-prefix}is-lower-alpha {
+ list-style-type: lower-alpha;
+ }
+
+ &.#{iv.$class-prefix}is-lower-roman {
+ list-style-type: lower-roman;
+ }
+
+ &.#{iv.$class-prefix}is-upper-alpha {
+ list-style-type: upper-alpha;
+ }
+
+ &.#{iv.$class-prefix}is-upper-roman {
+ list-style-type: upper-roman;
+ }
+ }
+ }
+
+ ul {
+ list-style: disc outside;
+ margin-inline-start: 2em;
+
+ &:not(:first-child) {
+ margin-top: 1em;
+ }
+
+ ul {
+ list-style-type: circle;
+ margin-bottom: 0.25em;
+ margin-top: 0.25em;
+
+ ul {
+ list-style-type: square;
+ }
+ }
+ }
+
+ dd {
+ margin-inline-start: 2em;
+ }
+
+ figure:not([class]) {
+ margin-left: 2em;
+ margin-right: 2em;
+ text-align: center;
+
+ &:not(:first-child) {
+ margin-top: 2em;
+ }
+
+ &:not(:last-child) {
+ margin-bottom: 2em;
+ }
+
+ img {
+ display: inline-block;
+ }
+
+ figcaption {
+ font-style: italic;
+ }
+ }
+
+ pre {
+ @include mx.overflow-touch;
+ overflow-x: auto;
+ padding: cv.getVar("content-pre-padding");
+ white-space: pre;
+ word-wrap: normal;
+ }
+
+ sup,
+ sub {
+ font-size: 75%;
+ }
+
+ table {
+ td,
+ th {
+ border: cv.getVar("content-table-cell-border");
+ border-width: cv.getVar("content-table-cell-border-width");
+ padding: cv.getVar("content-table-cell-padding");
+ vertical-align: top;
+ }
+
+ th {
+ color: cv.getVar("content-table-cell-heading-color");
+
+ &:not([align]) {
+ text-align: inherit;
+ }
+ }
+
+ thead {
+ td,
+ th {
+ border-width: cv.getVar("content-table-head-cell-border-width");
+ color: cv.getVar("content-table-head-cell-color");
+ }
+ }
+
+ tfoot {
+ td,
+ th {
+ border-width: cv.getVar("content-table-foot-cell-border-width");
+ color: cv.getVar("content-table-foot-cell-color");
+ }
+ }
+
+ tbody {
+ tr {
+ &:last-child {
+ td,
+ th {
+ border-bottom-width: cv.getVar(
+ "content-table-body-last-row-cell-border-bottom-width"
+ );
+ }
+ }
+ }
+ }
+ }
+
+ .#{iv.$class-prefix}tabs {
+ li + li {
+ margin-top: 0;
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-normal {
+ font-size: cv.getVar("size-normal");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-large");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/delete.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/delete.scss
new file mode 100644
index 0000000..fb9cb43
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/delete.scss
@@ -0,0 +1,6 @@
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/mixins" as mx;
+
+.#{iv.$class-prefix}delete {
+ @include mx.delete;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/icon.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/icon.scss
new file mode 100644
index 0000000..2df2638
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/icon.scss
@@ -0,0 +1,67 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+
+$icon-dimensions: 1.5rem !default;
+$icon-dimensions-small: 1rem !default;
+$icon-dimensions-medium: 2rem !default;
+$icon-dimensions-large: 3rem !default;
+$icon-text-spacing: 0.25em !default;
+
+.#{iv.$class-prefix}icon,
+.#{iv.$class-prefix}icon-text {
+ @include cv.register-vars(
+ (
+ "icon-dimensions": #{$icon-dimensions},
+ "icon-dimensions-small": #{$icon-dimensions-small},
+ "icon-dimensions-medium": #{$icon-dimensions-medium},
+ "icon-dimensions-large": #{$icon-dimensions-large},
+ "icon-text-spacing": #{$icon-text-spacing},
+ )
+ );
+}
+
+.#{iv.$class-prefix}icon {
+ align-items: center;
+ display: inline-flex;
+ flex-shrink: 0;
+ justify-content: center;
+ height: cv.getVar("icon-dimensions");
+ transition-duration: cv.getVar("duration");
+ transition-property: color;
+ width: cv.getVar("icon-dimensions");
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ height: cv.getVar("icon-dimensions-small");
+ width: cv.getVar("icon-dimensions-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ height: cv.getVar("icon-dimensions-medium");
+ width: cv.getVar("icon-dimensions-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ height: cv.getVar("icon-dimensions-large");
+ width: cv.getVar("icon-dimensions-large");
+ }
+}
+
+.#{iv.$class-prefix}icon-text {
+ align-items: flex-start;
+ color: inherit;
+ display: inline-flex;
+ flex-wrap: wrap;
+ gap: cv.getVar("icon-text-spacing");
+ line-height: cv.getVar("icon-dimensions");
+ vertical-align: top;
+
+ .#{iv.$class-prefix}icon {
+ flex-grow: 0;
+ flex-shrink: 0;
+ }
+}
+
+div.#{iv.$class-prefix}icon-text {
+ display: flex;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/image.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/image.scss
new file mode 100644
index 0000000..b78c426
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/image.scss
@@ -0,0 +1,64 @@
+@use "sass:list";
+
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/css-variables" as cv;
+@use "../utilities/mixins" as mx;
+
+$dimensions: 16 24 32 48 64 96 128 !default;
+
+.#{iv.$class-prefix}image {
+ display: block;
+ position: relative;
+
+ img {
+ display: block;
+ height: auto;
+ width: 100%;
+
+ &.#{iv.$class-prefix}is-rounded {
+ border-radius: cv.getVar("radius-rounded");
+ }
+ }
+
+ &.#{iv.$class-prefix}is-fullwidth {
+ width: 100%;
+ }
+
+ // Ratio
+ &.#{iv.$class-prefix}is-square {
+ img,
+ .#{iv.$class-prefix}has-ratio {
+ @include mx.overlay;
+ height: 100%;
+ width: 100%;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-square {
+ aspect-ratio: 1;
+ }
+
+ @each $pair in iv.$aspect-ratios {
+ $w: list.nth($pair, 1);
+ $h: list.nth($pair, 2);
+
+ &.#{iv.$class-prefix}is-#{$w}by#{$h} {
+ aspect-ratio: #{$w} / #{$h};
+
+ img,
+ .#{iv.$class-prefix}has-ratio {
+ @include mx.overlay;
+ height: 100%;
+ width: 100%;
+ }
+ }
+ }
+
+ // Sizes
+ @each $dimension in $dimensions {
+ &.#{iv.$class-prefix}is-#{$dimension}x#{$dimension} {
+ height: $dimension * 1px;
+ width: $dimension * 1px;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/loader.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/loader.scss
new file mode 100644
index 0000000..3cd1a26
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/loader.scss
@@ -0,0 +1,15 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+
+.#{iv.$class-prefix}loader {
+ animation: spinAround 500ms infinite linear;
+ border: 2px solid cv.getVar("border");
+ border-radius: cv.getVar("radius-rounded");
+ border-right-color: transparent;
+ border-top-color: transparent;
+ content: "";
+ display: block;
+ height: 1em;
+ position: relative;
+ width: 1em;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/notification.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/notification.scss
new file mode 100644
index 0000000..0e0df7e
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/notification.scss
@@ -0,0 +1,105 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$notification-code-background-color: cv.getVar("scheme-main") !default;
+$notification-radius: cv.getVar("radius") !default;
+$notification-padding: 1.375em 1.5em !default;
+
+$notification-colors: dv.$colors !default;
+
+.#{iv.$class-prefix}notification {
+ @include cv.register-vars(
+ (
+ "notification-h": #{cv.getVar("scheme-h")},
+ "notification-s": #{cv.getVar("scheme-s")},
+ "notification-background-l": #{cv.getVar("background-l")},
+ "notification-color-l": #{cv.getVar("text-strong-l")},
+ "notification-code-background-color": #{$notification-code-background-color},
+ "notification-radius": #{$notification-radius},
+ "notification-padding": #{$notification-padding},
+ )
+ );
+}
+
+.#{iv.$class-prefix}notification {
+ @extend %block;
+
+ background-color: hsl(
+ cv.getVar("notification-h"),
+ cv.getVar("notification-s"),
+ cv.getVar("notification-background-l")
+ );
+ border-radius: cv.getVar("notification-radius");
+ color: hsl(
+ cv.getVar("notification-h"),
+ cv.getVar("notification-s"),
+ cv.getVar("notification-color-l")
+ );
+ padding: cv.getVar("notification-padding");
+ position: relative;
+
+ a:not(.#{iv.$class-prefix}button):not(.#{iv.$class-prefix}dropdown-item) {
+ color: currentColor;
+ text-decoration: underline;
+ }
+
+ strong {
+ color: currentColor;
+ }
+
+ code,
+ pre {
+ background: cv.getVar("notification-code-background-color");
+ }
+
+ pre code {
+ background: transparent;
+ }
+
+ & > .#{iv.$class-prefix}delete {
+ position: absolute;
+ inset-inline-end: 1rem;
+ top: 1rem;
+ }
+
+ .#{iv.$class-prefix}title,
+ .#{iv.$class-prefix}subtitle,
+ .#{iv.$class-prefix}content {
+ color: currentColor;
+ }
+
+ // Colors
+ @each $name, $pair in $notification-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "notification-h": #{cv.getVar($name, "", "-h")},
+ "notification-s": #{cv.getVar($name, "", "-s")},
+ "notification-background-l": #{cv.getVar($name, "", "-l")},
+ "notification-color-l": #{cv.getVar($name, "", "-invert-l")},
+ )
+ );
+
+ &.#{iv.$class-prefix}is-light {
+ @include cv.register-vars(
+ (
+ "notification-background-l": 90%,
+ "notification-color-l": #{cv.getVar($name, "", "-light-invert-l")},
+ )
+ );
+ }
+
+ &.#{iv.$class-prefix}is-dark {
+ @include cv.register-vars(
+ (
+ "notification-background-l": 20%,
+ "notification-color-l": #{cv.getVar($name, "", "-dark-invert-l")},
+ )
+ );
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/progress.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/progress.scss
new file mode 100644
index 0000000..2c38af4
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/progress.scss
@@ -0,0 +1,115 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$progress-bar-background-color: cv.getVar("border-weak") !default;
+$progress-value-background-color: cv.getVar("text") !default;
+$progress-border-radius: cv.getVar("radius-rounded") !default;
+
+$progress-indeterminate-duration: 1.5s !default;
+
+$progress-colors: dv.$colors !default;
+
+.#{iv.$class-prefix}progress {
+ @include cv.register-vars(
+ (
+ "progress-border-radius": #{$progress-border-radius},
+ "progress-bar-background-color": #{$progress-bar-background-color},
+ "progress-value-background-color": #{$progress-value-background-color},
+ "progress-indeterminate-duration": #{$progress-indeterminate-duration},
+ )
+ );
+}
+
+.#{iv.$class-prefix}progress {
+ @extend %block;
+
+ appearance: none;
+ border: none;
+ border-radius: cv.getVar("progress-border-radius");
+ display: block;
+ height: cv.getVar("size-normal");
+ overflow: hidden;
+ padding: 0;
+ width: 100%;
+
+ &::-webkit-progress-bar {
+ background-color: cv.getVar("progress-bar-background-color");
+ }
+
+ &::-webkit-progress-value {
+ background-color: cv.getVar("progress-value-background-color");
+ }
+
+ &::-moz-progress-bar {
+ background-color: cv.getVar("progress-value-background-color");
+ }
+
+ &::-ms-fill {
+ background-color: cv.getVar("progress-value-background-color");
+ border: none;
+ }
+
+ // Colors
+ @each $name, $pair in $progress-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-var(
+ "progress-value-background-color",
+ #{cv.getVar($name)}
+ );
+ }
+ }
+
+ &:indeterminate {
+ animation-duration: cv.getVar("progress-indeterminate-duration");
+ animation-iteration-count: infinite;
+ animation-name: moveIndeterminate;
+ animation-timing-function: linear;
+ background-color: cv.getVar("progress-bar-background-color");
+ background-image: linear-gradient(
+ to right,
+ cv.getVar("progress-value-background-color") 30%,
+ cv.getVar("progress-bar-background-color") 30%
+ );
+ background-position: top left;
+ background-repeat: no-repeat;
+ background-size: 150% 150%;
+
+ &::-webkit-progress-bar {
+ background-color: transparent;
+ }
+
+ &::-moz-progress-bar {
+ background-color: transparent;
+ }
+
+ &::-ms-fill {
+ animation-name: none;
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ height: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ height: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ height: cv.getVar("size-large");
+ }
+}
+
+@keyframes moveIndeterminate {
+ from {
+ background-position: 200% 0;
+ }
+
+ to {
+ background-position: (-200%) 0;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/table.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/table.scss
new file mode 100644
index 0000000..97b6e92
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/table.scss
@@ -0,0 +1,261 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$table-color: cv.getVar("text-strong") !default;
+$table-background-color: cv.getVar("scheme-main") !default;
+
+$table-cell-border-color: cv.getVar("border") !default;
+$table-cell-border-style: solid !default;
+$table-cell-border-width: 0 0 1px !default;
+$table-cell-padding: 0.5em 0.75em !default;
+$table-cell-heading-color: cv.getVar("text-strong") !default;
+$table-cell-text-align: left !default;
+
+$table-head-cell-border-width: 0 0 2px !default;
+$table-head-cell-color: cv.getVar("text-strong") !default;
+$table-foot-cell-border-width: 2px 0 0 !default;
+$table-foot-cell-color: cv.getVar("text-strong") !default;
+
+$table-head-background-color: transparent !default;
+$table-body-background-color: transparent !default;
+$table-foot-background-color: transparent !default;
+
+$table-row-hover-background-color: cv.getVar("scheme-main-bis") !default;
+
+$table-row-active-background-color: cv.getVar("primary") !default;
+$table-row-active-color: cv.getVar("primary-invert") !default;
+
+$table-striped-row-even-background-color: cv.getVar("scheme-main-bis") !default;
+$table-striped-row-even-hover-background-color: cv.getVar(
+ "scheme-main-ter"
+) !default;
+
+$table-colors: dv.$colors !default;
+
+.#{iv.$class-prefix}table {
+ @include cv.register-vars(
+ (
+ "table-color": #{$table-color},
+ "table-background-color": #{$table-background-color},
+ "table-cell-border-color": #{$table-cell-border-color},
+ "table-cell-border-style": #{$table-cell-border-style},
+ "table-cell-border-width": #{$table-cell-border-width},
+ "table-cell-padding": #{$table-cell-padding},
+ "table-cell-heading-color": #{$table-cell-heading-color},
+ "table-cell-text-align": #{$table-cell-text-align},
+ "table-head-cell-border-width": #{$table-head-cell-border-width},
+ "table-head-cell-color": #{$table-head-cell-color},
+ "table-foot-cell-border-width": #{$table-foot-cell-border-width},
+ "table-foot-cell-color": #{$table-foot-cell-color},
+ "table-head-background-color": #{$table-head-background-color},
+ "table-body-background-color": #{$table-body-background-color},
+ "table-foot-background-color": #{$table-foot-background-color},
+ "table-row-hover-background-color": #{$table-row-hover-background-color},
+ "table-row-active-background-color": #{$table-row-active-background-color},
+ "table-row-active-color": #{$table-row-active-color},
+ "table-striped-row-even-background-color": #{$table-striped-row-even-background-color},
+ "table-striped-row-even-hover-background-color": #{$table-striped-row-even-hover-background-color},
+ )
+ );
+}
+
+.#{iv.$class-prefix}table {
+ @extend %block;
+
+ background-color: cv.getVar("table-background-color");
+ color: cv.getVar("table-color");
+
+ td,
+ th {
+ background-color: cv.getVar("table-cell-background-color");
+ border-color: cv.getVar("table-cell-border-color");
+ border-style: cv.getVar("table-cell-border-style");
+ border-width: cv.getVar("table-cell-border-width");
+ color: cv.getVar("table-color");
+ padding: cv.getVar("table-cell-padding");
+ vertical-align: top;
+
+ // Colors
+ @each $name, $pair in $table-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "table-color": #{cv.getVar($name, "", "-invert")},
+ "table-cell-heading-color": #{cv.getVar($name, "", "-invert")},
+ "table-cell-background-color": #{cv.getVar($name)},
+ "table-cell-border-color": #{cv.getVar($name)},
+ )
+ );
+ }
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-narrow {
+ white-space: nowrap;
+ width: 1%;
+ }
+
+ &.#{iv.$class-prefix}is-selected {
+ background-color: cv.getVar("table-row-active-background-color");
+ color: cv.getVar("table-row-active-color");
+
+ a,
+ strong {
+ color: currentColor;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-vcentered {
+ vertical-align: middle;
+ }
+ }
+
+ th {
+ color: cv.getVar("table-cell-heading-color");
+
+ &:not([align]) {
+ text-align: cv.getVar("table-cell-text-align");
+ }
+ }
+
+ tr {
+ &.#{iv.$class-prefix}is-selected {
+ background-color: cv.getVar("table-row-active-background-color");
+ color: cv.getVar("table-row-active-color");
+
+ a,
+ strong {
+ color: currentColor;
+ }
+
+ td,
+ th {
+ border-color: cv.getVar("table-row-active-color");
+ color: currentColor;
+ }
+ }
+
+ @each $name, $pair in $table-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "table-color": #{cv.getVar($name, "", "-invert")},
+ "table-cell-heading-color": #{cv.getVar($name, "", "-invert")},
+ "table-cell-background-color": #{cv.getVar($name)},
+ "table-cell-border-color": #{cv.getVar($name)},
+ )
+ );
+ }
+ }
+ }
+
+ thead {
+ background-color: cv.getVar("table-head-background-color");
+
+ td,
+ th {
+ border-width: cv.getVar("table-head-cell-border-width");
+ color: cv.getVar("table-head-cell-color");
+ }
+ }
+
+ tfoot {
+ background-color: cv.getVar("table-foot-background-color");
+
+ td,
+ th {
+ border-width: cv.getVar("table-foot-cell-border-width");
+ color: cv.getVar("table-foot-cell-color");
+ }
+ }
+
+ tbody {
+ background-color: cv.getVar("table-body-background-color");
+
+ tr {
+ &:last-child {
+ td,
+ th {
+ border-bottom-width: 0;
+ }
+ }
+ }
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-bordered {
+ td,
+ th {
+ border-width: 1px;
+ }
+
+ tr {
+ &:last-child {
+ td,
+ th {
+ border-bottom-width: 1px;
+ }
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-fullwidth {
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-hoverable {
+ tbody {
+ tr:not(.#{iv.$class-prefix}is-selected) {
+ &:hover {
+ background-color: cv.getVar("table-row-hover-background-color");
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-striped {
+ tbody {
+ tr:not(.#{iv.$class-prefix}is-selected) {
+ &:hover {
+ background-color: cv.getVar("table-row-hover-background-color");
+
+ &:nth-child(even) {
+ background-color: cv.getVar(
+ "table-striped-row-even-hover-background-color"
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-narrow {
+ td,
+ th {
+ padding: 0.25em 0.5em;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-striped {
+ tbody {
+ tr:not(.#{iv.$class-prefix}is-selected) {
+ &:nth-child(even) {
+ background-color: cv.getVar(
+ "table-striped-row-even-background-color"
+ );
+ }
+ }
+ }
+ }
+}
+
+.#{iv.$class-prefix}table-container {
+ @extend %block;
+ @include mx.overflow-touch;
+ overflow: auto;
+ overflow-y: hidden;
+ max-width: 100%;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/tag.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/tag.scss
new file mode 100644
index 0000000..336fa97
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/tag.scss
@@ -0,0 +1,219 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$tag-h: cv.getVar("scheme-h");
+$tag-s: cv.getVar("scheme-s");
+$tag-background-l: cv.getVar("background-l");
+$tag-background-l-delta: 0%;
+$tag-hover-background-l-delta: cv.getVar("hover-background-l-delta");
+$tag-active-background-l-delta: cv.getVar("active-background-l-delta");
+$tag-color-l: cv.getVar("text-l");
+$tag-radius: cv.getVar("radius") !default;
+$tag-delete-margin: 1px !default;
+
+$tag-colors: dv.$colors !default;
+
+.#{iv.$class-prefix}tags {
+ @extend %block;
+
+ align-items: center;
+ color: hsl(cv.getVar("tag-h"), cv.getVar("tag-s"), cv.getVar("tag-color-l"));
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
+ justify-content: flex-start;
+
+ // Sizes
+ &.#{iv.$class-prefix}are-medium {
+ .#{iv.$class-prefix}tag:not(.#{iv.$class-prefix}is-normal):not(
+ .#{iv.$class-prefix}is-large
+ ) {
+ font-size: cv.getVar("size-normal");
+ }
+ }
+
+ &.#{iv.$class-prefix}are-large {
+ .#{iv.$class-prefix}tag:not(.#{iv.$class-prefix}is-normal):not(
+ .#{iv.$class-prefix}is-medium
+ ) {
+ font-size: cv.getVar("size-medium");
+ }
+ }
+
+ &.#{iv.$class-prefix}is-centered {
+ gap: 0.25rem;
+ justify-content: center;
+ }
+
+ &.#{iv.$class-prefix}is-right {
+ justify-content: flex-end;
+ }
+
+ &.#{iv.$class-prefix}has-addons {
+ gap: 0;
+
+ .#{iv.$class-prefix}tag {
+ &:not(:first-child) {
+ border-start-start-radius: 0; // Top left
+ border-end-start-radius: 0; // Top right
+ }
+
+ &:not(:last-child) {
+ border-start-end-radius: 0; // Bottom left
+ border-end-end-radius: 0; // Bottom right
+ }
+ }
+ }
+}
+
+.#{iv.$class-prefix}tag {
+ @include cv.register-vars(
+ (
+ "tag-h": #{$tag-h},
+ "tag-s": #{$tag-s},
+ "tag-background-l": #{$tag-background-l},
+ "tag-background-l-delta": #{$tag-background-l-delta},
+ "tag-hover-background-l-delta": #{$tag-hover-background-l-delta},
+ "tag-active-background-l-delta": #{$tag-active-background-l-delta},
+ "tag-color-l": #{$tag-color-l},
+ "tag-radius": #{$tag-radius},
+ "tag-delete-margin": #{$tag-delete-margin},
+ )
+ );
+
+ align-items: center;
+ background-color: hsl(
+ cv.getVar("tag-h"),
+ cv.getVar("tag-s"),
+ calc(
+ #{cv.getVar("tag-background-l")} + #{cv.getVar("tag-background-l-delta")}
+ )
+ );
+ border-radius: $tag-radius;
+ color: hsl(cv.getVar("tag-h"), cv.getVar("tag-s"), cv.getVar("tag-color-l"));
+ display: inline-flex;
+ font-size: cv.getVar("size-small");
+ height: 2em;
+ justify-content: center;
+ line-height: 1.5;
+ padding-left: 0.75em;
+ padding-right: 0.75em;
+ white-space: nowrap;
+
+ .#{iv.$class-prefix}delete {
+ margin-inline-start: 0.25rem;
+ margin-inline-end: -0.375rem;
+ }
+
+ // Colors
+ @each $name, $pair in $tag-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "tag-h": #{cv.getVar($name, "", "-h")},
+ "tag-s": #{cv.getVar($name, "", "-s")},
+ "tag-background-l": #{cv.getVar($name, "", "-l")},
+ "tag-color-l": #{cv.getVar($name, "", "-invert-l")},
+ )
+ );
+
+ &.#{iv.$class-prefix}is-light {
+ @include cv.register-vars(
+ (
+ "tag-background-l": #{cv.getVar("light-l")},
+ "tag-color-l": #{cv.getVar($name, "", "-light-invert-l")},
+ )
+ );
+ }
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-normal {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-normal");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-medium");
+ }
+
+ .#{iv.$class-prefix}icon {
+ &:first-child:not(:last-child) {
+ margin-inline-start: -0.375em;
+ margin-inline-end: 0.1875em;
+ }
+
+ &:last-child:not(:first-child) {
+ margin-inline-start: 0.1875em;
+ margin-inline-end: -0.375em;
+ }
+
+ &:first-child:last-child {
+ margin-inline-start: -0.375em;
+ margin-inline-end: -0.375em;
+ }
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-delete {
+ margin-inline-start: cv.getVar("tag-delete-margin");
+ padding: 0;
+ position: relative;
+ width: 2em;
+
+ &::before,
+ &::after {
+ background-color: currentColor;
+ content: "";
+ display: block;
+ left: 50%;
+ position: absolute;
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%) rotate(45deg);
+ transform-origin: center center;
+ }
+
+ &::before {
+ height: 1px;
+ width: 50%;
+ }
+
+ &::after {
+ height: 50%;
+ width: 1px;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-rounded {
+ border-radius: cv.getVar("radius-rounded");
+ }
+}
+
+a.#{iv.$class-prefix}tag,
+button.#{iv.$class-prefix}tag,
+.#{iv.$class-prefix}tag.is-hoverable {
+ cursor: pointer;
+
+ &:hover {
+ @include cv.register-vars(
+ (
+ "tag-background-l-delta": #{cv.getVar("tag-hover-background-l-delta")},
+ )
+ );
+ }
+
+ &:active {
+ @include cv.register-vars(
+ (
+ "tag-background-l-delta": #{cv.getVar("tag-active-background-l-delta")},
+ )
+ );
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/title.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/title.scss
new file mode 100644
index 0000000..f4c498b
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/elements/title.scss
@@ -0,0 +1,130 @@
+@use "sass:list";
+
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$title-color: cv.getVar("text-strong") !default;
+$title-family: false !default;
+$title-size: cv.getVar("size-3") !default;
+$title-weight: cv.getVar("weight-extrabold") !default;
+$title-line-height: 1.125 !default;
+$title-strong-color: inherit !default;
+$title-strong-weight: inherit !default;
+$title-sub-size: 0.75em !default;
+$title-sup-size: 0.75em !default;
+
+$subtitle-color: cv.getVar("text") !default;
+$subtitle-family: false !default;
+$subtitle-size: cv.getVar("size-5") !default;
+$subtitle-weight: cv.getVar("weight-normal") !default;
+$subtitle-line-height: 1.25 !default;
+$subtitle-strong-color: cv.getVar("text-strong") !default;
+$subtitle-strong-weight: cv.getVar("weight-semibold") !default;
+
+.#{iv.$class-prefix}title,
+.#{iv.$class-prefix}subtitle {
+ @include cv.register-vars(
+ (
+ "title-color": #{$title-color},
+ "title-family": #{$title-family},
+ "title-size": #{$title-size},
+ "title-weight": #{$title-weight},
+ "title-line-height": #{$title-line-height},
+ "title-strong-color": #{$title-strong-color},
+ "title-strong-weight": #{$title-strong-weight},
+ "title-sub-size": #{$title-sub-size},
+ "title-sup-size": #{$title-sup-size},
+ "subtitle-color": #{$subtitle-color},
+ "subtitle-family": #{$subtitle-family},
+ "subtitle-size": #{$subtitle-size},
+ "subtitle-weight": #{$subtitle-weight},
+ "subtitle-line-height": #{$subtitle-line-height},
+ "subtitle-strong-color": #{$subtitle-strong-color},
+ "subtitle-strong-weight": #{$subtitle-strong-weight},
+ )
+ );
+}
+
+.#{iv.$class-prefix}title,
+.#{iv.$class-prefix}subtitle {
+ @extend %block;
+ word-break: break-word;
+
+ em,
+ span {
+ font-weight: inherit;
+ }
+
+ sub {
+ font-size: cv.getVar("title-sub-size");
+ }
+
+ sup {
+ font-size: cv.getVar("title-sup-size");
+ }
+
+ .#{iv.$class-prefix}tag {
+ vertical-align: middle;
+ }
+}
+
+.#{iv.$class-prefix}title {
+ color: cv.getVar("title-color");
+ font-size: cv.getVar("title-size");
+ font-weight: cv.getVar("title-weight");
+ line-height: cv.getVar("title-line-height");
+
+ @if $title-family {
+ font-family: cv.getVar("title-family");
+ }
+
+ strong {
+ color: cv.getVar("title-strong-color");
+ font-weight: cv.getVar("title-strong-weight");
+ }
+
+ &:not(.#{iv.$class-prefix}is-spaced):has(+ .#{iv.$class-prefix}subtitle) {
+ margin-bottom: 0;
+ }
+
+ // Sizes
+ @each $size in dv.$sizes {
+ $i: list.index(dv.$sizes, $size);
+
+ &.#{iv.$class-prefix}is-#{$i} {
+ font-size: $size;
+ }
+ }
+}
+
+.#{iv.$class-prefix}subtitle {
+ color: cv.getVar("subtitle-color");
+ font-size: cv.getVar("subtitle-size");
+ font-weight: cv.getVar("subtitle-weight");
+ line-height: cv.getVar("subtitle-line-height");
+
+ @if $subtitle-family {
+ font-family: cv.getVar("subtitle-family");
+ }
+
+ strong {
+ color: cv.getVar("subtitle-strong-color");
+ font-weight: cv.getVar("subtitle-strong-weight");
+ }
+
+ &:not(.#{iv.$class-prefix}is-spaced):has(+ .#{iv.$class-prefix}title) {
+ margin-bottom: 0;
+ }
+
+ // Sizes
+ @each $size in dv.$sizes {
+ $i: list.index(dv.$sizes, $size);
+
+ &.#{iv.$class-prefix}is-#{$i} {
+ font-size: $size;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/_index.scss
new file mode 100644
index 0000000..7c1214d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/_index.scss
@@ -0,0 +1,9 @@
+/* Bulma Form */
+@charset "utf-8";
+
+@forward "shared";
+@forward "input-textarea";
+@forward "checkbox-radio";
+@forward "select";
+@forward "file";
+@forward "tools";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/checkbox-radio.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/checkbox-radio.scss
new file mode 100644
index 0000000..6844e6b
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/checkbox-radio.scss
@@ -0,0 +1,36 @@
+@use "shared";
+@use "../utilities/initial-variables" as iv;
+
+%checkbox-radio {
+ cursor: pointer;
+ display: inline-block;
+ line-height: 1.25;
+ position: relative;
+
+ input {
+ cursor: pointer;
+ }
+
+ &[disabled],
+ fieldset[disabled] &,
+ input[disabled] {
+ color: shared.$input-disabled-color;
+ cursor: not-allowed;
+ }
+}
+
+.#{iv.$class-prefix}checkbox {
+ @extend %checkbox-radio;
+}
+
+.#{iv.$class-prefix}radio {
+ @extend %checkbox-radio;
+}
+
+.#{iv.$class-prefix}checkboxes,
+.#{iv.$class-prefix}radios {
+ display: flex;
+ flex-wrap: wrap;
+ column-gap: 1em;
+ row-gap: 0.5em;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/file.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/file.scss
new file mode 100644
index 0000000..c75d4a1
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/file.scss
@@ -0,0 +1,330 @@
+@use "shared";
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/controls";
+@use "../utilities/extends";
+
+$file-radius: cv.getVar("radius") !default;
+
+$file-h: cv.getVar("scheme-h");
+$file-s: cv.getVar("scheme-s");
+$file-background-l: cv.getVar("scheme-main-ter-l");
+$file-background-l-delta: 0%;
+$file-hover-background-l-delta: -5%;
+$file-active-background-l-delta: -10%;
+$file-border-l: cv.getVar("border-l");
+$file-border-l-delta: 0%;
+$file-hover-border-l-delta: -10%;
+$file-active-border-l-delta: -20%;
+$file-cta-color-l: cv.getVar("text-strong-l");
+$file-name-color-l: cv.getVar("text-strong-l");
+$file-color-l-delta: 0%;
+$file-hover-color-l-delta: -5%;
+$file-active-color-l-delta: -10%;
+
+$file-cta-color: cv.getVar("text") !default;
+$file-cta-hover-color: cv.getVar("text-strong") !default;
+$file-cta-active-color: cv.getVar("text-strong") !default;
+
+$file-name-border-color: cv.getVar("border") !default;
+$file-name-border-style: solid !default;
+$file-name-border-width: 1px 1px 1px 0 !default;
+$file-name-max-width: 16em !default;
+
+$file-colors: shared.$form-colors !default;
+
+.#{iv.$class-prefix}file {
+ @extend %block;
+ @extend %unselectable;
+
+ @include cv.register-vars(
+ (
+ "file-radius": #{$file-radius},
+ "file-name-border-color": #{$file-name-border-color},
+ "file-name-border-style": #{$file-name-border-style},
+ "file-name-border-width": #{$file-name-border-width},
+ "file-name-max-width": #{$file-name-max-width},
+ "file-h": #{$file-h},
+ "file-s": #{$file-s},
+ "file-background-l": #{$file-background-l},
+ "file-background-l-delta": #{$file-background-l-delta},
+ "file-hover-background-l-delta": #{$file-hover-background-l-delta},
+ "file-active-background-l-delta": #{$file-active-background-l-delta},
+ "file-border-l": #{$file-border-l},
+ "file-border-l-delta": #{$file-border-l-delta},
+ "file-hover-border-l-delta": #{$file-hover-border-l-delta},
+ "file-active-border-l-delta": #{$file-active-border-l-delta},
+ "file-cta-color-l": #{$file-cta-color-l},
+ "file-name-color-l": #{$file-name-color-l},
+ "file-color-l-delta": #{$file-color-l-delta},
+ "file-hover-color-l-delta": #{$file-hover-color-l-delta},
+ "file-active-color-l-delta": #{$file-active-color-l-delta},
+ )
+ );
+
+ align-items: stretch;
+ display: flex;
+ justify-content: flex-start;
+ position: relative;
+
+ // Colors
+ @each $name, $pair in $file-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "file-h": #{cv.getVar($name, "", "-h")},
+ "file-s": #{cv.getVar($name, "", "-s")},
+ "file-background-l": #{cv.getVar($name, "", "-l")},
+ "file-border-l": #{cv.getVar($name, "", "-l")},
+ "file-cta-color-l": #{cv.getVar($name, "", "-invert-l")},
+ "file-name-color-l": #{cv.getVar($name, "", "-on-scheme-l")},
+ )
+ );
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-normal {
+ font-size: cv.getVar("size-normal");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-medium");
+
+ .#{iv.$class-prefix}file-icon {
+ .#{iv.$class-prefix}fa {
+ font-size: 1.5rem;
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-large");
+
+ .#{iv.$class-prefix}file-icon {
+ .#{iv.$class-prefix}fa {
+ font-size: 2rem;
+ }
+ }
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}has-name {
+ .#{iv.$class-prefix}file-cta {
+ border-end-end-radius: 0;
+ border-start-end-radius: 0;
+ }
+
+ .#{iv.$class-prefix}file-name {
+ border-end-start-radius: 0;
+ border-start-start-radius: 0;
+ }
+
+ &.#{iv.$class-prefix}is-empty {
+ .#{iv.$class-prefix}file-cta {
+ border-radius: cv.getVar("file-radius");
+ }
+
+ .#{iv.$class-prefix}file-name {
+ display: none;
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-boxed {
+ .#{iv.$class-prefix}file-label {
+ flex-direction: column;
+ }
+
+ .#{iv.$class-prefix}file-cta {
+ flex-direction: column;
+ height: auto;
+ padding: 1em 3em;
+ }
+
+ .#{iv.$class-prefix}file-name {
+ border-width: 0 1px 1px;
+ }
+
+ .#{iv.$class-prefix}file-icon {
+ height: 1.5em;
+ width: 1.5em;
+
+ .#{iv.$class-prefix}fa {
+ font-size: 1.5rem;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-small {
+ .#{iv.$class-prefix}file-icon .#{iv.$class-prefix}fa {
+ font-size: 1rem;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ .#{iv.$class-prefix}file-icon .#{iv.$class-prefix}fa {
+ font-size: 2rem;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ .#{iv.$class-prefix}file-icon .#{iv.$class-prefix}fa {
+ font-size: 2.5rem;
+ }
+ }
+
+ &.#{iv.$class-prefix}has-name {
+ .#{iv.$class-prefix}file-cta {
+ border-end-end-radius: 0;
+ border-end-start-radius: 0;
+ border-start-end-radius: cv.getVar("file-radius");
+ border-start-start-radius: cv.getVar("file-radius");
+ }
+
+ .#{iv.$class-prefix}file-name {
+ border-end-end-radius: cv.getVar("file-radius");
+ border-end-start-radius: cv.getVar("file-radius");
+ border-start-end-radius: 0;
+ border-start-start-radius: 0;
+ border-width: 0 1px 1px;
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-centered {
+ justify-content: center;
+ }
+
+ &.#{iv.$class-prefix}is-fullwidth {
+ .#{iv.$class-prefix}file-label {
+ width: 100%;
+ }
+
+ .#{iv.$class-prefix}file-name {
+ flex-grow: 1;
+ max-width: none;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-right {
+ justify-content: flex-end;
+
+ .#{iv.$class-prefix}file-cta {
+ border-radius: 0 cv.getVar("file-radius") cv.getVar("file-radius") 0;
+ }
+
+ .#{iv.$class-prefix}file-name {
+ border-radius: cv.getVar("file-radius") 0 0 cv.getVar("file-radius");
+ border-width: 1px 0 1px 1px;
+ order: -1;
+ }
+ }
+}
+
+.#{iv.$class-prefix}file-label {
+ align-items: stretch;
+ display: flex;
+ cursor: pointer;
+ justify-content: flex-start;
+ overflow: hidden;
+ position: relative;
+
+ &:hover {
+ @include cv.register-vars(
+ (
+ "file-background-l-delta": #{cv.getVar("file-hover-background-l-delta")},
+ "file-border-l-delta": #{cv.getVar("file-hover-border-l-delta")},
+ "file-color-l-delta": #{cv.getVar("file-hover-color-l-delta")},
+ )
+ );
+ }
+
+ &:active {
+ @include cv.register-vars(
+ (
+ "file-background-l-delta": #{cv.getVar("file-active-background-l-delta")},
+ "file-border-l-delta": #{cv.getVar("file-active-border-l-delta")},
+ "file-color-l-delta": #{cv.getVar("file-active-color-l-delta")},
+ )
+ );
+ }
+}
+
+.#{iv.$class-prefix}file-input {
+ height: 100%;
+ left: 0;
+ opacity: 0;
+ outline: none;
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+
+.#{iv.$class-prefix}file-cta,
+.#{iv.$class-prefix}file-name {
+ @extend %control;
+ border-color: hsl(
+ cv.getVar("file-h"),
+ cv.getVar("file-s"),
+ calc(#{cv.getVar("file-border-l")} + #{cv.getVar("file-border-l-delta")})
+ );
+ border-radius: cv.getVar("file-radius");
+ font-size: 1em;
+ padding-left: 1em;
+ padding-right: 1em;
+ white-space: nowrap;
+}
+
+.#{iv.$class-prefix}file-cta {
+ background-color: hsl(
+ cv.getVar("file-h"),
+ cv.getVar("file-s"),
+ calc(
+ #{cv.getVar("file-background-l")} + #{cv.getVar(
+ "file-background-l-delta"
+ )}
+ )
+ );
+ color: hsl(
+ cv.getVar("file-h"),
+ cv.getVar("file-s"),
+ calc(#{cv.getVar("file-cta-color-l")} + #{cv.getVar("file-color-l-delta")})
+ );
+}
+
+.#{iv.$class-prefix}file-name {
+ border-color: hsl(
+ cv.getVar("file-h"),
+ cv.getVar("file-s"),
+ calc(#{cv.getVar("file-border-l")} + #{cv.getVar("file-color-l-delta")})
+ );
+ border-style: cv.getVar("file-name-border-style");
+ border-width: cv.getVar("file-name-border-width");
+ color: hsl(
+ cv.getVar("file-h"),
+ cv.getVar("file-s"),
+ calc(#{cv.getVar("file-name-color-l")} + #{cv.getVar("file-color-l-delta")})
+ );
+ display: block;
+ max-width: cv.getVar("file-name-max-width");
+ overflow: hidden;
+ text-align: inherit;
+ text-overflow: ellipsis;
+}
+
+.#{iv.$class-prefix}file-icon {
+ align-items: center;
+ display: flex;
+ height: 1em;
+ justify-content: center;
+ margin-inline-end: 0.5em;
+ width: 1em;
+
+ .#{iv.$class-prefix}fa {
+ font-size: 1rem;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/input-textarea.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/input-textarea.scss
new file mode 100644
index 0000000..93eec25
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/input-textarea.scss
@@ -0,0 +1,115 @@
+@use "sass:list";
+
+@use "shared";
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/controls";
+
+$textarea-padding: cv.getVar("control-padding-horizontal") !default;
+$textarea-max-height: 40em !default;
+$textarea-min-height: 8em !default;
+
+$textarea-colors: shared.$form-colors !default;
+
+%input-textarea {
+ @extend %input;
+
+ box-shadow: shared.$input-shadow;
+ max-width: 100%;
+ width: 100%;
+
+ &[readonly] {
+ box-shadow: none;
+ }
+
+ // Colors
+ @each $name, $pair in $textarea-colors {
+ $color: list.nth($pair, 1);
+
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "input-h": #{cv.getVar($name, "", "-h")},
+ "input-s": #{cv.getVar($name, "", "-s")},
+ "input-l": #{cv.getVar($name, "", "-l")},
+ "input-focus-h": #{cv.getVar($name, "", "-h")},
+ "input-focus-s": #{cv.getVar($name, "", "-s")},
+ "input-focus-l": #{cv.getVar($name, "", "-l")},
+ "input-border-l": #{cv.getVar($name, "", "-l")},
+ )
+ );
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ @include controls.control-small;
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ @include controls.control-medium;
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ @include controls.control-large;
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-fullwidth {
+ display: block;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-inline {
+ display: inline;
+ width: auto;
+ }
+}
+
+.#{iv.$class-prefix}input {
+ @extend %input-textarea;
+
+ &.#{iv.$class-prefix}is-rounded {
+ border-radius: cv.getVar("radius-rounded");
+ padding-left: calc(#{controls.$control-padding-horizontal} + 0.375em);
+ padding-right: calc(#{controls.$control-padding-horizontal} + 0.375em);
+ }
+
+ &.#{iv.$class-prefix}is-static {
+ background-color: transparent;
+ border-color: transparent;
+ box-shadow: none;
+ padding-left: 0;
+ padding-right: 0;
+ }
+}
+
+.#{iv.$class-prefix}textarea {
+ @extend %input-textarea;
+ @include cv.register-vars(
+ (
+ "textarea-padding": #{$textarea-padding},
+ "textarea-max-height": #{$textarea-max-height},
+ "textarea-min-height": #{$textarea-min-height},
+ )
+ );
+ display: block;
+ max-width: 100%;
+ min-width: 100%;
+ padding: cv.getVar("textarea-padding");
+ resize: vertical;
+
+ &:not([rows]) {
+ max-height: cv.getVar("textarea-max-height");
+ min-height: cv.getVar("textarea-min-height");
+ }
+
+ &[rows] {
+ height: initial;
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}has-fixed-size {
+ resize: none;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/select.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/select.scss
new file mode 100644
index 0000000..855eac7
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/select.scss
@@ -0,0 +1,144 @@
+@use "shared";
+@use "../utilities/controls";
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+
+$select-colors: shared.$form-colors !default;
+
+.#{iv.$class-prefix}select {
+ @include cv.register-vars(
+ (
+ "input-h": #{cv.getVar("scheme-h")},
+ "input-s": #{cv.getVar("scheme-s")},
+ "input-border-style": solid,
+ "input-border-width": 1px,
+ "input-border-l": #{cv.getVar("border-l")},
+ )
+ );
+
+ display: inline-block;
+ max-width: 100%;
+ position: relative;
+ vertical-align: top;
+
+ &:not(.#{iv.$class-prefix}is-multiple) {
+ height: shared.$input-height;
+ }
+
+ &:not(.#{iv.$class-prefix}is-multiple):not(.#{iv.$class-prefix}is-loading) {
+ &::after {
+ @extend %arrow;
+ inset-inline-end: 1.125em;
+ z-index: 4;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-rounded {
+ select {
+ border-radius: cv.getVar("radius-rounded");
+ padding-inline-start: 1em;
+ }
+ }
+
+ select {
+ @extend %input;
+ cursor: pointer;
+ display: block;
+ font-size: 1em;
+ max-width: 100%;
+ outline: none;
+
+ &::-ms-expand {
+ display: none;
+ }
+
+ &[disabled]:hover,
+ fieldset[disabled] &:hover {
+ border-color: shared.$input-disabled-border-color;
+ }
+
+ &:not([multiple]) {
+ padding-inline-end: 2.5em;
+ }
+
+ &[multiple] {
+ height: auto;
+ padding: 0;
+
+ option {
+ padding: 0.5em 1em;
+ }
+ }
+ }
+
+ // Colors
+ @each $name, $pair in $select-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "input-h": #{cv.getVar($name, "", "-h")},
+ "input-s": #{cv.getVar($name, "", "-s")},
+ "input-l": #{cv.getVar($name, "", "-l")},
+ "input-focus-h": #{cv.getVar($name, "", "-h")},
+ "input-focus-s": #{cv.getVar($name, "", "-s")},
+ "input-focus-l": #{cv.getVar($name, "", "-l")},
+ "input-border-l": #{cv.getVar($name, "", "-l")},
+ "arrow-color": #{cv.getVar($name)},
+ )
+ );
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ @include controls.control-small;
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ @include controls.control-medium;
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ @include controls.control-large;
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-disabled {
+ &::after {
+ border-color: shared.$input-disabled-color !important;
+ opacity: 0.5;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-fullwidth {
+ width: 100%;
+
+ select {
+ width: 100%;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-loading {
+ &::after {
+ @extend %loader;
+ inset-inline-end: 0.625em;
+ margin-top: 0;
+ position: absolute;
+ top: 0.625em;
+ transform: none;
+ }
+
+ &.#{iv.$class-prefix}is-small:after {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium:after {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large:after {
+ font-size: cv.getVar("size-large");
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/shared.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/shared.scss
new file mode 100644
index 0000000..f28d55c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/shared.scss
@@ -0,0 +1,178 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$form-colors: dv.$colors !default;
+
+$input-h: #{cv.getVar("scheme-h")} !default;
+$input-s: #{cv.getVar("scheme-s")} !default;
+$input-l: #{cv.getVar("scheme-main-l")} !default;
+$input-border-style: solid !default;
+$input-border-width: cv.getVar("control-border-width") !default;
+$input-border-l: cv.getVar("border-l") !default;
+$input-border-l-delta: 0% !default;
+$input-border-color: hsl(
+ cv.getVar("input-h"),
+ cv.getVar("input-s"),
+ calc(#{cv.getVar("input-border-l")} + #{cv.getVar("input-border-l-delta")})
+) !default;
+$input-hover-border-l-delta: #{cv.getVar("hover-border-l-delta")} !default;
+$input-active-border-l-delta: #{cv.getVar("active-border-l-delta")} !default;
+$input-color-l: cv.getVar("text-strong-l") !default;
+$input-background-l: cv.getVar("scheme-main-l") !default;
+$input-background-l-delta: 0% !default;
+$input-height: cv.getVar("control-height") !default;
+$input-shadow: inset 0 0.0625em 0.125em
+ hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")},
+ 0.05
+ ) !default;
+$input-placeholder-color: hsla(
+ #{cv.getVar("text-h")},
+ #{cv.getVar("text-s")},
+ #{cv.getVar("text-strong-l")},
+ 0.3
+) !default;
+
+$input-focus-h: cv.getVar("focus-h") !default;
+$input-focus-s: cv.getVar("focus-s") !default;
+$input-focus-l: cv.getVar("focus-l") !default;
+$input-focus-shadow-size: cv.getVar("focus-shadow-size") !default;
+$input-focus-shadow-alpha: cv.getVar("focus-shadow-alpha") !default;
+
+$input-disabled-color: cv.getVar("text-weak") !default;
+$input-disabled-background-color: cv.getVar("background") !default;
+$input-disabled-border-color: cv.getVar("background") !default;
+$input-disabled-placeholder-color: hsla(
+ #{cv.getVar("text-h")},
+ #{cv.getVar("text-s")},
+ #{cv.getVar("text-weak-l")},
+ 0.3
+) !default;
+
+$input-arrow: cv.getVar("link") !default;
+
+$input-icon-color: cv.getVar("text-light") !default;
+$input-icon-hover-color: cv.getVar("text-weak") !default;
+$input-icon-focus-color: cv.getVar("link") !default;
+
+$input-radius: cv.getVar("radius") !default;
+
+.#{iv.$class-prefix}control,
+.#{iv.$class-prefix}input,
+.#{iv.$class-prefix}textarea,
+.#{iv.$class-prefix}select {
+ @include cv.register-vars(
+ (
+ "input-h": #{$input-h},
+ "input-s": #{$input-s},
+ "input-l": #{$input-l},
+ "input-border-style": #{$input-border-style},
+ "input-border-width": #{$input-border-width},
+ "input-border-l": #{$input-border-l},
+ "input-border-l-delta": #{$input-border-l-delta},
+ "input-border-color": #{$input-border-color},
+ "input-hover-border-l-delta": #{$input-hover-border-l-delta},
+ "input-active-border-l-delta": #{$input-active-border-l-delta},
+ "input-focus-h": #{$input-focus-h},
+ "input-focus-s": #{$input-focus-s},
+ "input-focus-l": #{$input-focus-l},
+ "input-focus-shadow-size": #{$input-focus-shadow-size},
+ "input-focus-shadow-alpha": #{$input-focus-shadow-alpha},
+ "input-color-l": #{$input-color-l},
+ "input-background-l": #{$input-background-l},
+ "input-background-l-delta": #{$input-background-l-delta},
+ "input-height": #{$input-height},
+ "input-shadow": #{$input-shadow},
+ "input-placeholder-color": #{$input-placeholder-color},
+ "input-disabled-color": #{$input-disabled-color},
+ "input-disabled-background-color": #{$input-disabled-background-color},
+ "input-disabled-border-color": #{$input-disabled-border-color},
+ "input-disabled-placeholder-color": #{$input-disabled-placeholder-color},
+ "input-arrow": #{$input-arrow},
+ "input-icon-color": #{$input-icon-color},
+ "input-icon-hover-color": #{$input-icon-hover-color},
+ "input-icon-focus-color": #{$input-icon-focus-color},
+ "input-radius": #{$input-radius},
+ )
+ );
+}
+
+@mixin input {
+ @extend %control;
+ background-color: hsl(
+ #{cv.getVar("input-h")},
+ #{cv.getVar("input-s")},
+ calc(
+ #{cv.getVar("input-background-l")} + #{cv.getVar(
+ "input-background-l-delta"
+ )}
+ )
+ );
+ border-color: cv.getVar("input-border-color");
+ border-radius: cv.getVar("input-radius");
+ color: hsl(
+ #{cv.getVar("input-h")},
+ #{cv.getVar("input-s")},
+ #{cv.getVar("input-color-l")}
+ );
+
+ @include mx.placeholder {
+ color: cv.getVar("input-placeholder-color");
+ }
+
+ &:hover,
+ &.#{iv.$class-prefix}is-hovered {
+ @include cv.register-vars(
+ (
+ "input-border-l-delta": #{cv.getVar("input-hover-border-l-delta")},
+ )
+ );
+ }
+
+ &:active,
+ &.#{iv.$class-prefix}is-active {
+ @include cv.register-vars(
+ (
+ "input-border-l-delta": #{cv.getVar("input-active-border-l-delta")},
+ )
+ );
+ }
+
+ &:focus,
+ &:focus-within,
+ &.#{iv.$class-prefix}is-focused {
+ border-color: hsl(
+ cv.getVar("input-focus-h"),
+ cv.getVar("input-focus-s"),
+ cv.getVar("input-focus-l")
+ );
+ box-shadow: cv.getVar("input-focus-shadow-size")
+ hsla(
+ cv.getVar("input-focus-h"),
+ cv.getVar("input-focus-s"),
+ cv.getVar("input-focus-l"),
+ cv.getVar("input-focus-shadow-alpha")
+ );
+ }
+
+ &[disabled],
+ fieldset[disabled] & {
+ background-color: cv.getVar("input-disabled-background-color");
+ border-color: cv.getVar("input-disabled-border-color");
+ box-shadow: none;
+ color: cv.getVar("input-disabled-color");
+
+ @include mx.placeholder {
+ color: cv.getVar("input-disabled-placeholder-color");
+ }
+ }
+}
+
+%input {
+ @include input;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/tools.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/tools.scss
new file mode 100644
index 0000000..741a5c7
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/form/tools.scss
@@ -0,0 +1,352 @@
+@use "shared";
+@use "../utilities/controls";
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$label-color: cv.getVar("text-strong") !default;
+$label-spacing: 0.5em !default;
+$label-weight: cv.getVar("weight-semibold") !default;
+
+$help-size: cv.getVar("size-small") !default;
+
+$label-colors: shared.$form-colors !default;
+
+$field-block-spacing: 0.75rem !default;
+
+#{iv.$variables-host} {
+ @include cv.register-vars(
+ (
+ "label-color": #{$label-color},
+ "label-spacing": #{$label-spacing},
+ "label-weight": #{$label-weight},
+ "help-size": #{$help-size},
+ "field-block-spacing": #{$field-block-spacing},
+ )
+ );
+}
+
+.#{iv.$class-prefix}label {
+ color: cv.getVar("label-color");
+ display: block;
+ font-size: cv.getVar("size-normal");
+ font-weight: $label-weight;
+
+ &:not(:last-child) {
+ margin-bottom: cv.getVar("label-spacing");
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-large");
+ }
+}
+
+.#{iv.$class-prefix}help {
+ display: block;
+ font-size: cv.getVar("help-size");
+ margin-top: 0.25rem;
+
+ @each $name, $pair in $label-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-on-scheme-l")}
+ );
+ }
+ }
+}
+
+// Containers
+
+.#{iv.$class-prefix}field {
+ @include cv.register-vars(
+ (
+ "block-spacing": #{cv.getVar("field-block-spacing")},
+ )
+ );
+
+ @extend %block;
+
+ // Modifiers
+ &.#{iv.$class-prefix}has-addons {
+ display: flex;
+ justify-content: flex-start;
+
+ .#{iv.$class-prefix}control {
+ &:not(:last-child) {
+ margin-inline-end: -1px;
+ }
+
+ &:not(:first-child):not(:last-child) {
+ .#{iv.$class-prefix}button,
+ .#{iv.$class-prefix}input,
+ .#{iv.$class-prefix}select select {
+ border-radius: 0;
+ }
+ }
+
+ &:first-child:not(:only-child) {
+ .#{iv.$class-prefix}button,
+ .#{iv.$class-prefix}input,
+ .#{iv.$class-prefix}select select {
+ border-start-end-radius: 0;
+ border-end-end-radius: 0;
+ }
+ }
+
+ &:last-child:not(:only-child) {
+ .#{iv.$class-prefix}button,
+ .#{iv.$class-prefix}input,
+ .#{iv.$class-prefix}select select {
+ border-start-start-radius: 0;
+ border-end-start-radius: 0;
+ }
+ }
+
+ .#{iv.$class-prefix}button,
+ .#{iv.$class-prefix}input,
+ .#{iv.$class-prefix}select select {
+ &:not([disabled]) {
+ &:hover,
+ &.#{iv.$class-prefix}is-hovered {
+ z-index: 2;
+ }
+
+ &:focus,
+ &.#{iv.$class-prefix}is-focused,
+ &:active,
+ &.#{iv.$class-prefix}is-active {
+ z-index: 3;
+
+ &:hover {
+ z-index: 4;
+ }
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-expanded {
+ flex-grow: 1;
+ flex-shrink: 1;
+ }
+ }
+
+ &.#{iv.$class-prefix}has-addons-centered {
+ justify-content: center;
+ }
+
+ &.#{iv.$class-prefix}has-addons-right {
+ justify-content: flex-end;
+ }
+
+ &.#{iv.$class-prefix}has-addons-fullwidth {
+ .#{iv.$class-prefix}control {
+ flex-grow: 1;
+ flex-shrink: 0;
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-grouped {
+ display: flex;
+ gap: 0.75rem;
+ justify-content: flex-start;
+
+ & > .#{iv.$class-prefix}control {
+ flex-shrink: 0;
+
+ &.#{iv.$class-prefix}is-expanded {
+ flex-grow: 1;
+ flex-shrink: 1;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-grouped-centered {
+ justify-content: center;
+ }
+
+ &.#{iv.$class-prefix}is-grouped-right {
+ justify-content: flex-end;
+ }
+
+ &.#{iv.$class-prefix}is-grouped-multiline {
+ flex-wrap: wrap;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-horizontal {
+ @include mx.tablet {
+ display: flex;
+ }
+ }
+}
+
+.#{iv.$class-prefix}field-label {
+ .#{iv.$class-prefix}label {
+ font-size: inherit;
+ }
+
+ @include mx.mobile {
+ margin-bottom: 0.5rem;
+ }
+
+ @include mx.tablet {
+ flex-basis: 0;
+ flex-grow: 1;
+ flex-shrink: 0;
+ margin-inline-end: 1.5rem;
+ text-align: right;
+
+ &.#{iv.$class-prefix}is-small {
+ font-size: cv.getVar("size-small");
+ padding-top: 0.375em;
+ }
+
+ &.#{iv.$class-prefix}is-normal {
+ padding-top: 0.375em;
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ font-size: cv.getVar("size-medium");
+ padding-top: 0.375em;
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ font-size: cv.getVar("size-large");
+ padding-top: 0.375em;
+ }
+ }
+}
+
+.#{iv.$class-prefix}field-body {
+ .#{iv.$class-prefix}field .#{iv.$class-prefix}field {
+ margin-bottom: 0;
+ }
+
+ @include mx.tablet {
+ display: flex;
+ flex-basis: 0;
+ flex-grow: 5;
+ flex-shrink: 1;
+
+ .#{iv.$class-prefix}field {
+ margin-bottom: 0;
+ }
+
+ & > .#{iv.$class-prefix}field {
+ flex-shrink: 1;
+
+ &:not(.#{iv.$class-prefix}is-narrow) {
+ flex-grow: 1;
+ }
+
+ &:not(:last-child) {
+ margin-inline-end: 0.75rem;
+ }
+ }
+ }
+}
+
+.#{iv.$class-prefix}control {
+ box-sizing: border-box;
+ clear: both;
+ font-size: cv.getVar("size-normal");
+ position: relative;
+ text-align: inherit;
+
+ // Modifiers
+ &.#{iv.$class-prefix}has-icons-left,
+ &.#{iv.$class-prefix}has-icons-right {
+ .#{iv.$class-prefix}input,
+ .#{iv.$class-prefix}select {
+ &:hover {
+ & ~ .#{iv.$class-prefix}icon {
+ color: cv.getVar("input-icon-hover-color");
+ }
+ }
+
+ &:focus {
+ & ~ .#{iv.$class-prefix}icon {
+ color: cv.getVar("input-icon-focus-color");
+ }
+ }
+
+ &.#{iv.$class-prefix}is-small ~ .#{iv.$class-prefix}icon {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium ~ .#{iv.$class-prefix}icon {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large ~ .#{iv.$class-prefix}icon {
+ font-size: cv.getVar("size-large");
+ }
+ }
+
+ .#{iv.$class-prefix}icon {
+ color: cv.getVar("input-icon-color");
+ height: cv.getVar("input-height");
+ pointer-events: none;
+ position: absolute;
+ top: 0;
+ width: cv.getVar("input-height");
+ z-index: 4;
+ }
+ }
+
+ &.#{iv.$class-prefix}has-icons-left {
+ .#{iv.$class-prefix}input,
+ .#{iv.$class-prefix}select select {
+ padding-left: cv.getVar("input-height");
+ }
+
+ .#{iv.$class-prefix}icon.#{iv.$class-prefix}is-left {
+ left: 0;
+ }
+ }
+
+ &.#{iv.$class-prefix}has-icons-right {
+ .#{iv.$class-prefix}input,
+ .#{iv.$class-prefix}select select {
+ padding-right: cv.getVar("input-height");
+ }
+
+ .#{iv.$class-prefix}icon.#{iv.$class-prefix}is-right {
+ right: 0;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-loading {
+ &::after {
+ @extend %loader;
+ inset-inline-end: 0.75em;
+ position: absolute !important;
+ top: 0.75em;
+ z-index: 4;
+ }
+
+ &.#{iv.$class-prefix}is-small:after {
+ font-size: cv.getVar("size-small");
+ }
+
+ &.#{iv.$class-prefix}is-medium:after {
+ font-size: cv.getVar("size-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large:after {
+ font-size: cv.getVar("size-large");
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/grid/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/grid/_index.scss
new file mode 100644
index 0000000..70d64ca
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/grid/_index.scss
@@ -0,0 +1,5 @@
+/* Bulma Grid */
+@charset "utf-8";
+
+@forward "columns";
+@forward "grid";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/grid/columns.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/grid/columns.scss
new file mode 100644
index 0000000..d26f3a8
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/grid/columns.scss
@@ -0,0 +1,961 @@
+@use "sass:math";
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$column-gap: 0.75rem !default;
+
+#{iv.$variables-host} {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$column-gap},
+ )
+ );
+}
+
+.#{iv.$class-prefix}column {
+ display: block;
+ flex-basis: 0;
+ flex-grow: 1;
+ flex-shrink: 1;
+ padding: cv.getVar("column-gap");
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-narrow {
+ flex: none;
+ width: unset;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-full {
+ flex: none;
+ width: 100%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-three-quarters {
+ flex: none;
+ width: 75%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-two-thirds {
+ flex: none;
+ width: 66.6666%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-half {
+ flex: none;
+ width: 50%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-one-third {
+ flex: none;
+ width: 33.3333%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-one-quarter {
+ flex: none;
+ width: 25%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-one-fifth {
+ flex: none;
+ width: 20%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-two-fifths {
+ flex: none;
+ width: 40%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-three-fifths {
+ flex: none;
+ width: 60%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-four-fifths {
+ flex: none;
+ width: 80%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-three-quarters {
+ margin-inline-start: 75%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-two-thirds {
+ margin-inline-start: 66.6666%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-half {
+ margin-inline-start: 50%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-one-third {
+ margin-inline-start: 0.3333%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-one-quarter {
+ margin-inline-start: 25%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-one-fifth {
+ margin-inline-start: 20%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-two-fifths {
+ margin-inline-start: 40%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-three-fifths {
+ margin-inline-start: 60%;
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-four-fifths {
+ margin-inline-start: 80%;
+ }
+
+ @for $i from 0 through 12 {
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-#{$i} {
+ flex: none;
+ width: math.percentage(math.div($i, 12));
+ }
+
+ .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile
+ > &.#{iv.$class-prefix}is-offset-#{$i} {
+ margin-inline-start: math.percentage(math.div($i, 12));
+ }
+ }
+
+ @include mx.mobile {
+ &.#{iv.$class-prefix}is-narrow-mobile {
+ flex: none;
+ width: unset;
+ }
+
+ &.#{iv.$class-prefix}is-full-mobile {
+ flex: none;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-three-quarters-mobile {
+ flex: none;
+ width: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-two-thirds-mobile {
+ flex: none;
+ width: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-half-mobile {
+ flex: none;
+ width: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-one-third-mobile {
+ flex: none;
+ width: 33.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-one-quarter-mobile {
+ flex: none;
+ width: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-one-fifth-mobile {
+ flex: none;
+ width: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-two-fifths-mobile {
+ flex: none;
+ width: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-three-fifths-mobile {
+ flex: none;
+ width: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-four-fifths-mobile {
+ flex: none;
+ width: 80%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-quarters-mobile {
+ margin-inline-start: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-thirds-mobile {
+ margin-inline-start: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-half-mobile {
+ margin-inline-start: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-third-mobile {
+ margin-inline-start: 0.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-quarter-mobile {
+ margin-inline-start: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-fifth-mobile {
+ margin-inline-start: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-fifths-mobile {
+ margin-inline-start: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-fifths-mobile {
+ margin-inline-start: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-four-fifths-mobile {
+ margin-inline-start: 80%;
+ }
+
+ @for $i from 0 through 12 {
+ &.#{iv.$class-prefix}is-#{$i}-mobile {
+ flex: none;
+ width: math.percentage(math.div($i, 12));
+ }
+
+ &.#{iv.$class-prefix}is-offset-#{$i}-mobile {
+ margin-inline-start: math.percentage(math.div($i, 12));
+ }
+ }
+ }
+
+ @include mx.tablet {
+ &.#{iv.$class-prefix}is-narrow,
+ &.#{iv.$class-prefix}is-narrow-tablet {
+ flex: none;
+ width: unset;
+ }
+
+ &.#{iv.$class-prefix}is-full,
+ &.#{iv.$class-prefix}is-full-tablet {
+ flex: none;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-three-quarters,
+ &.#{iv.$class-prefix}is-three-quarters-tablet {
+ flex: none;
+ width: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-two-thirds,
+ &.#{iv.$class-prefix}is-two-thirds-tablet {
+ flex: none;
+ width: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-half,
+ &.#{iv.$class-prefix}is-half-tablet {
+ flex: none;
+ width: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-one-third,
+ &.#{iv.$class-prefix}is-one-third-tablet {
+ flex: none;
+ width: 33.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-one-quarter,
+ &.#{iv.$class-prefix}is-one-quarter-tablet {
+ flex: none;
+ width: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-one-fifth,
+ &.#{iv.$class-prefix}is-one-fifth-tablet {
+ flex: none;
+ width: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-two-fifths,
+ &.#{iv.$class-prefix}is-two-fifths-tablet {
+ flex: none;
+ width: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-three-fifths,
+ &.#{iv.$class-prefix}is-three-fifths-tablet {
+ flex: none;
+ width: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-four-fifths,
+ &.#{iv.$class-prefix}is-four-fifths-tablet {
+ flex: none;
+ width: 80%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-quarters,
+ &.#{iv.$class-prefix}is-offset-three-quarters-tablet {
+ margin-inline-start: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-thirds,
+ &.#{iv.$class-prefix}is-offset-two-thirds-tablet {
+ margin-inline-start: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-half,
+ &.#{iv.$class-prefix}is-offset-half-tablet {
+ margin-inline-start: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-third,
+ &.#{iv.$class-prefix}is-offset-one-third-tablet {
+ margin-inline-start: 0.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-quarter,
+ &.#{iv.$class-prefix}is-offset-one-quarter-tablet {
+ margin-inline-start: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-fifth,
+ &.#{iv.$class-prefix}is-offset-one-fifth-tablet {
+ margin-inline-start: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-fifths,
+ &.#{iv.$class-prefix}is-offset-two-fifths-tablet {
+ margin-inline-start: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-fifths,
+ &.#{iv.$class-prefix}is-offset-three-fifths-tablet {
+ margin-inline-start: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-four-fifths,
+ &.#{iv.$class-prefix}is-offset-four-fifths-tablet {
+ margin-inline-start: 80%;
+ }
+
+ @for $i from 0 through 12 {
+ &.#{iv.$class-prefix}is-#{$i},
+ &.#{iv.$class-prefix}is-#{$i}-tablet {
+ flex: none;
+ width: math.percentage(math.div($i, 12));
+ }
+
+ &.#{iv.$class-prefix}is-offset-#{$i},
+ &.#{iv.$class-prefix}is-offset-#{$i}-tablet {
+ margin-inline-start: math.percentage(math.div($i, 12));
+ }
+ }
+ }
+
+ @include mx.touch {
+ &.#{iv.$class-prefix}is-narrow-touch {
+ flex: none;
+ width: unset;
+ }
+
+ &.#{iv.$class-prefix}is-full-touch {
+ flex: none;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-three-quarters-touch {
+ flex: none;
+ width: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-two-thirds-touch {
+ flex: none;
+ width: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-half-touch {
+ flex: none;
+ width: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-one-third-touch {
+ flex: none;
+ width: 33.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-one-quarter-touch {
+ flex: none;
+ width: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-one-fifth-touch {
+ flex: none;
+ width: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-two-fifths-touch {
+ flex: none;
+ width: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-three-fifths-touch {
+ flex: none;
+ width: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-four-fifths-touch {
+ flex: none;
+ width: 80%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-quarters-touch {
+ margin-inline-start: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-thirds-touch {
+ margin-inline-start: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-half-touch {
+ margin-inline-start: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-third-touch {
+ margin-inline-start: 0.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-quarter-touch {
+ margin-inline-start: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-fifth-touch {
+ margin-inline-start: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-fifths-touch {
+ margin-inline-start: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-fifths-touch {
+ margin-inline-start: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-four-fifths-touch {
+ margin-inline-start: 80%;
+ }
+
+ @for $i from 0 through 12 {
+ &.#{iv.$class-prefix}is-#{$i}-touch {
+ flex: none;
+ width: math.percentage(math.div($i, 12));
+ }
+
+ &.#{iv.$class-prefix}is-offset-#{$i}-touch {
+ margin-inline-start: math.percentage(math.div($i, 12));
+ }
+ }
+ }
+
+ @include mx.desktop {
+ &.#{iv.$class-prefix}is-narrow-desktop {
+ flex: none;
+ width: unset;
+ }
+
+ &.#{iv.$class-prefix}is-full-desktop {
+ flex: none;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-three-quarters-desktop {
+ flex: none;
+ width: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-two-thirds-desktop {
+ flex: none;
+ width: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-half-desktop {
+ flex: none;
+ width: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-one-third-desktop {
+ flex: none;
+ width: 33.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-one-quarter-desktop {
+ flex: none;
+ width: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-one-fifth-desktop {
+ flex: none;
+ width: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-two-fifths-desktop {
+ flex: none;
+ width: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-three-fifths-desktop {
+ flex: none;
+ width: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-four-fifths-desktop {
+ flex: none;
+ width: 80%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-quarters-desktop {
+ margin-inline-start: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-thirds-desktop {
+ margin-inline-start: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-half-desktop {
+ margin-inline-start: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-third-desktop {
+ margin-inline-start: 0.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-quarter-desktop {
+ margin-inline-start: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-fifth-desktop {
+ margin-inline-start: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-fifths-desktop {
+ margin-inline-start: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-fifths-desktop {
+ margin-inline-start: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-four-fifths-desktop {
+ margin-inline-start: 80%;
+ }
+
+ @for $i from 0 through 12 {
+ &.#{iv.$class-prefix}is-#{$i}-desktop {
+ flex: none;
+ width: math.percentage(math.div($i, 12));
+ }
+
+ &.#{iv.$class-prefix}is-offset-#{$i}-desktop {
+ margin-inline-start: math.percentage(math.div($i, 12));
+ }
+ }
+ }
+
+ @include mx.widescreen {
+ &.#{iv.$class-prefix}is-narrow-widescreen {
+ flex: none;
+ width: unset;
+ }
+
+ &.#{iv.$class-prefix}is-full-widescreen {
+ flex: none;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-three-quarters-widescreen {
+ flex: none;
+ width: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-two-thirds-widescreen {
+ flex: none;
+ width: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-half-widescreen {
+ flex: none;
+ width: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-one-third-widescreen {
+ flex: none;
+ width: 33.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-one-quarter-widescreen {
+ flex: none;
+ width: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-one-fifth-widescreen {
+ flex: none;
+ width: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-two-fifths-widescreen {
+ flex: none;
+ width: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-three-fifths-widescreen {
+ flex: none;
+ width: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-four-fifths-widescreen {
+ flex: none;
+ width: 80%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-quarters-widescreen {
+ margin-inline-start: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-thirds-widescreen {
+ margin-inline-start: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-half-widescreen {
+ margin-inline-start: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-third-widescreen {
+ margin-inline-start: 0.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-quarter-widescreen {
+ margin-inline-start: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-fifth-widescreen {
+ margin-inline-start: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-fifths-widescreen {
+ margin-inline-start: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-fifths-widescreen {
+ margin-inline-start: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-four-fifths-widescreen {
+ margin-inline-start: 80%;
+ }
+
+ @for $i from 0 through 12 {
+ &.#{iv.$class-prefix}is-#{$i}-widescreen {
+ flex: none;
+ width: math.percentage(math.div($i, 12));
+ }
+
+ &.#{iv.$class-prefix}is-offset-#{$i}-widescreen {
+ margin-inline-start: math.percentage(math.div($i, 12));
+ }
+ }
+ }
+
+ @include mx.fullhd {
+ &.#{iv.$class-prefix}is-narrow-fullhd {
+ flex: none;
+ width: unset;
+ }
+
+ &.#{iv.$class-prefix}is-full-fullhd {
+ flex: none;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-three-quarters-fullhd {
+ flex: none;
+ width: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-two-thirds-fullhd {
+ flex: none;
+ width: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-half-fullhd {
+ flex: none;
+ width: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-one-third-fullhd {
+ flex: none;
+ width: 33.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-one-quarter-fullhd {
+ flex: none;
+ width: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-one-fifth-fullhd {
+ flex: none;
+ width: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-two-fifths-fullhd {
+ flex: none;
+ width: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-three-fifths-fullhd {
+ flex: none;
+ width: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-four-fifths-fullhd {
+ flex: none;
+ width: 80%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-quarters-fullhd {
+ margin-inline-start: 75%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-thirds-fullhd {
+ margin-inline-start: 66.6666%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-half-fullhd {
+ margin-inline-start: 50%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-third-fullhd {
+ margin-inline-start: 33.3333%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-quarter-fullhd {
+ margin-inline-start: 25%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-one-fifth-fullhd {
+ margin-inline-start: 20%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-two-fifths-fullhd {
+ margin-inline-start: 40%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-three-fifths-fullhd {
+ margin-inline-start: 60%;
+ }
+
+ &.#{iv.$class-prefix}is-offset-four-fifths-fullhd {
+ margin-inline-start: 80%;
+ }
+
+ @for $i from 0 through 12 {
+ &.#{iv.$class-prefix}is-#{$i}-fullhd {
+ flex: none;
+ width: math.percentage(math.div($i, 12));
+ }
+
+ &.#{iv.$class-prefix}is-offset-#{$i}-fullhd {
+ margin-inline-start: math.percentage(math.div($i, 12));
+ }
+ }
+ }
+}
+
+.#{iv.$class-prefix}columns {
+ margin-inline-start: calc(-1 * #{cv.getVar("column-gap")});
+ margin-inline-end: calc(-1 * #{cv.getVar("column-gap")});
+ margin-top: calc(-1 * #{cv.getVar("column-gap")});
+
+ &:last-child {
+ margin-bottom: calc(-1 * #{cv.getVar("column-gap")});
+ }
+
+ &:not(:last-child) {
+ margin-bottom: calc(
+ #{cv.getVar("block-spacing")} - #{cv.getVar("column-gap")}
+ );
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-centered {
+ justify-content: center;
+ }
+
+ &.#{iv.$class-prefix}is-gapless {
+ margin-inline-start: 0;
+ margin-inline-end: 0;
+
+ margin-top: 0;
+
+ & > .#{iv.$class-prefix}column {
+ margin: 0;
+ padding: 0 !important;
+ }
+
+ &:not(:last-child) {
+ margin-bottom: 1.5rem;
+ }
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ &.#{iv.$class-prefix}is-mobile {
+ display: flex;
+ }
+
+ &.#{iv.$class-prefix}is-multiline {
+ flex-wrap: wrap;
+ }
+
+ &.#{iv.$class-prefix}is-vcentered {
+ align-items: center;
+ }
+
+ // Responsiveness
+ @include mx.tablet {
+ &:not(.#{iv.$class-prefix}is-desktop) {
+ display: flex;
+ }
+ }
+
+ @include mx.desktop {
+ // Modifiers
+ &.#{iv.$class-prefix}is-desktop {
+ display: flex;
+ }
+ }
+
+ @for $i from 0 through 8 {
+ &.#{iv.$class-prefix}is-#{$i} {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+
+ @include mx.mobile {
+ &.#{iv.$class-prefix}is-#{$i}-mobile {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+ }
+
+ @include mx.tablet {
+ &.#{iv.$class-prefix}is-#{$i}-tablet {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+ }
+
+ @include mx.tablet-only {
+ &.#{iv.$class-prefix}is-#{$i}-tablet-only {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+ }
+
+ @include mx.touch {
+ &.#{iv.$class-prefix}is-#{$i}-touch {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+ }
+
+ @include mx.desktop {
+ &.#{iv.$class-prefix}is-#{$i}-desktop {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+ }
+
+ @include mx.desktop-only {
+ &.#{iv.$class-prefix}is-#{$i}-desktop-only {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+ }
+
+ @include mx.widescreen {
+ &.#{iv.$class-prefix}is-#{$i}-widescreen {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+ }
+
+ @include mx.widescreen-only {
+ &.#{iv.$class-prefix}is-#{$i}-widescreen-only {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+ }
+
+ @include mx.fullhd {
+ &.#{iv.$class-prefix}is-#{$i}-fullhd {
+ @include cv.register-vars(
+ (
+ "column-gap": #{$i * 0.25rem},
+ )
+ );
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/grid/grid.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/grid/grid.scss
new file mode 100644
index 0000000..b8ce95b
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/grid/grid.scss
@@ -0,0 +1,209 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$max-column-count: 12;
+$grip-gap: 0.75rem;
+$column-min-base: 1.5rem;
+
+@mixin fixed-grid-properties($suffix: "") {
+ @for $i from 1 through $max-column-count {
+ &.#{iv.$class-prefix}has-#{$i}-cols#{$suffix} {
+ > .#{iv.$class-prefix}grid {
+ @include cv.register-var("grid-column-count", #{$i});
+ }
+ }
+ }
+}
+
+$grid-container-name: bulma-fixed-grid;
+
+.#{iv.$class-prefix}fixed-grid {
+ @extend %block;
+ container-name: $grid-container-name;
+ container-type: inline-size;
+
+ > .#{iv.$class-prefix}grid {
+ @include cv.register-vars(
+ (
+ "grid-gap-count": calc(#{cv.getVar("grid-column-count")} - 1),
+ "grid-column-count": 2,
+ )
+ );
+
+ grid-template-columns: repeat(cv.getVar("grid-column-count"), 1fr);
+ }
+
+ @include fixed-grid-properties;
+
+ @include mx.container-until($grid-container-name, iv.$tablet) {
+ @include fixed-grid-properties("-mobile");
+ }
+
+ @include mx.container-from($grid-container-name, iv.$tablet) {
+ @include fixed-grid-properties("-tablet");
+ }
+
+ @include mx.container-from($grid-container-name, iv.$desktop) {
+ @include fixed-grid-properties("-desktop");
+ }
+
+ @include mx.container-from($grid-container-name, iv.$widescreen) {
+ @include fixed-grid-properties("-widescreen");
+ }
+
+ @include mx.container-from($grid-container-name, iv.$fullhd) {
+ @include fixed-grid-properties("-fullhd");
+ }
+
+ &.#{iv.$class-prefix}has-auto-count {
+ .#{iv.$class-prefix}grid {
+ @include mx.container-until($grid-container-name, iv.$tablet) {
+ @include cv.register-var("grid-column-count", 2);
+ }
+
+ @include mx.container-from($grid-container-name, iv.$tablet) {
+ @include cv.register-var("grid-column-count", 4);
+ }
+
+ @include mx.container-from($grid-container-name, iv.$desktop) {
+ @include cv.register-var("grid-column-count", 8);
+ }
+
+ @include mx.container-from($grid-container-name, iv.$widescreen) {
+ @include cv.register-var("grid-column-count", 12);
+ }
+
+ @include mx.container-from($grid-container-name, iv.$fullhd) {
+ @include cv.register-var("grid-column-count", 16);
+ }
+ }
+ }
+}
+
+.#{iv.$class-prefix}grid {
+ @include cv.register-vars(
+ (
+ "grid-gap": $grip-gap,
+ "grid-column-min": 9rem,
+ "grid-cell-column-span": 1,
+ "grid-cell-row-span": 1,
+ )
+ );
+
+ @extend %block;
+ display: grid;
+ gap: cv.getVar("grid-gap");
+ column-gap: #{cv.getVarWithBackup("grid-column-gap", "grid-gap")};
+ row-gap: #{cv.getVarWithBackup("grid-row-gap", "grid-gap")};
+ grid-template-columns: repeat(
+ auto-fit,
+ minmax(#{cv.getVar("grid-column-min")}, 1fr)
+ );
+ grid-template-rows: auto;
+
+ &.is-auto-fill {
+ grid-template-columns: repeat(
+ auto-fill,
+ minmax(#{cv.getVar("grid-column-min")}, 1fr)
+ );
+ }
+
+ @for $i from 1 through 32 {
+ &.#{iv.$class-prefix}is-col-min-#{$i} {
+ @include cv.register-vars(
+ (
+ "grid-column-min": #{$column-min-base * $i},
+ )
+ );
+ }
+ }
+}
+
+@mixin cell-properties($suffix: "") {
+ @for $i from 1 through $max-column-count {
+ $name: $i + $suffix;
+
+ &.#{iv.$class-prefix}is-col-start-#{$name} {
+ @include cv.register-var("grid-cell-column-start", #{$i});
+ }
+
+ &.#{iv.$class-prefix}is-col-end-#{$name} {
+ @include cv.register-var("grid-cell-column-end", #{$i});
+ }
+
+ &.#{iv.$class-prefix}is-col-from-end-#{$name} {
+ @include cv.register-var("grid-cell-column-start", #{$i * -1});
+ }
+
+ &.#{iv.$class-prefix}is-col-span-#{$name} {
+ @include cv.register-var("grid-cell-column-span", #{$i});
+ }
+
+ &.#{iv.$class-prefix}is-row-start-#{$name} {
+ @include cv.register-var("grid-cell-row-start", #{$i});
+ }
+
+ &.#{iv.$class-prefix}is-row-end-#{$name} {
+ @include cv.register-var("grid-cell-row-end", #{$i});
+ }
+
+ &.#{iv.$class-prefix}is-row-from-end-#{$name} {
+ @include cv.register-var("grid-cell-row-start", #{$i * -1});
+ }
+
+ &.#{iv.$class-prefix}is-row-span-#{$name} {
+ @include cv.register-var("grid-cell-row-span", #{$i});
+ }
+ }
+}
+
+.#{iv.$class-prefix}cell {
+ grid-column-end: span cv.getVar("grid-cell-column-span");
+ grid-column-start: cv.getVar("grid-cell-column-start");
+ grid-row-end: span cv.getVar("grid-cell-row-span");
+ grid-row-start: cv.getVar("grid-cell-row-start");
+
+ // Sizes
+ &.#{iv.$class-prefix}is-col-start-end {
+ @include cv.register-var("grid-cell-column-start", -1);
+ }
+
+ &.#{iv.$class-prefix}is-row-start-end {
+ @include cv.register-var("grid-cell-row-start", -1);
+ }
+
+ @include cell-properties;
+ @include mx.mobile {
+ @include cell-properties("-mobile");
+ }
+
+ @include mx.tablet {
+ @include cell-properties("-tablet");
+ }
+
+ @include mx.tablet-only {
+ @include cell-properties("-tablet-only");
+ }
+
+ @include mx.desktop {
+ @include cell-properties("-desktop");
+ }
+
+ @include mx.desktop-only {
+ @include cell-properties("-desktop-only");
+ }
+
+ @include mx.widescreen {
+ @include cell-properties("-widescreen");
+ }
+
+ @include mx.widescreen-only {
+ @include cell-properties("-widescreen-only");
+ }
+
+ @include mx.fullhd {
+ @include cell-properties("-fullhd");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/_index.scss
new file mode 100644
index 0000000..4388647
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/_index.scss
@@ -0,0 +1,15 @@
+/* Bulma Helpers */
+@charset "utf-8";
+
+@forward "aspect-ratio";
+@forward "border";
+@forward "color";
+@forward "flexbox";
+@forward "float";
+@forward "gap";
+@forward "overflow";
+@forward "position";
+@forward "spacing";
+@forward "typography";
+@forward "visibility";
+@forward "other";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/aspect-ratio.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/aspect-ratio.scss
new file mode 100644
index 0000000..e7bf183
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/aspect-ratio.scss
@@ -0,0 +1,12 @@
+@use "sass:list";
+
+@use "../utilities/initial-variables" as iv;
+
+@each $pair in iv.$aspect-ratios {
+ $w: list.nth($pair, 1);
+ $h: list.nth($pair, 2);
+
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}aspect-ratio-#{$w}by#{$h} {
+ aspect-ratio: #{$w} / #{$h};
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/border.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/border.scss
new file mode 100644
index 0000000..1525ff3
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/border.scss
@@ -0,0 +1,15 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+
+$radii: (
+ "small": "radius-small",
+ "normal": "radius",
+ "large": "radius-large",
+ "rounded": "radius-rounded",
+);
+
+@each $name, $var in $radii {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}radius-#{$name} {
+ border-radius: cv.getVar($var);
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/color.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/color.scss
new file mode 100644
index 0000000..0121698
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/color.scss
@@ -0,0 +1,344 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+
+$digits: (
+ "00",
+ "05",
+ "10",
+ "15",
+ "20",
+ "25",
+ "30",
+ "35",
+ "40",
+ "45",
+ "50",
+ "55",
+ "60",
+ "65",
+ "70",
+ "75",
+ "80",
+ "85",
+ "90",
+ "95",
+ "100"
+);
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}background {
+ background-color: cv.getVar("background");
+}
+
+@each $name, $color in dv.$colors {
+ $background: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-l")}
+ );
+
+ $color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-l")}
+ );
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name} {
+ color: $color !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name} {
+ background-color: $background !important;
+ }
+
+ // Invert
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-invert {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-invert-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-invert {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-invert-l")}
+ ) !important;
+ }
+
+ // On Scheme
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-on-scheme {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-on-scheme-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-on-scheme {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-on-scheme-l")}
+ ) !important;
+ }
+
+ // Light
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-light {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-light-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-light {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-light-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-light-invert {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-light-invert-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-light-invert {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-light-invert-l")}
+ ) !important;
+ }
+
+ // Dark
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-dark {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-dark-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-dark {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-dark-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-dark-invert {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-dark-invert-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-dark-invert {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-dark-invert-l")}
+ ) !important;
+ }
+
+ // Soft/Bold
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-soft {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar("soft-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-soft {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar("soft-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-bold {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar("bold-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-bold {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar("bold-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-soft-invert {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar("soft-invert-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-soft-invert {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar("soft-invert-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-bold-invert {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar("bold-invert-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-bold-invert {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar("bold-invert-l")}
+ ) !important;
+ }
+
+ @each $digit in $digits {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-#{$digit} {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-#{$digit}-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-#{$digit} {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-#{$digit}-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}-#{$digit}-invert {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-#{$digit}-invert-l")}
+ ) !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}-#{$digit}-invert {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ #{cv.getVar($name, "", "-#{$digit}-invert-l")}
+ ) !important;
+ }
+ }
+
+ // Hover
+ a.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name},
+ button.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name},
+ #{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name}.is-hoverable {
+ &:hover,
+ &:focus-visible {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ calc(
+ #{cv.getVar($name, "", "-l")} + #{cv.getVar("hover-color-l-delta")}
+ )
+ ) !important;
+ }
+
+ &:active {
+ color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ calc(
+ #{cv.getVar($name, "", "-l")} + #{cv.getVar("active-color-l-delta")}
+ )
+ ) !important;
+ }
+ }
+
+ a.#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name},
+ button.#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name},
+ #{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name}.is-hoverable {
+ &:hover,
+ &:focus-visible {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ calc(
+ #{cv.getVar($name, "", "-l")} +
+ #{cv.getVar("hover-background-l-delta")}
+ )
+ ) !important;
+ }
+
+ &:active {
+ background-color: hsl(
+ #{cv.getVar($name, "", "-h")},
+ #{cv.getVar($name, "", "-s")},
+ calc(
+ #{cv.getVar($name, "", "-l")} +
+ #{cv.getVar("active-background-l-delta")}
+ )
+ ) !important;
+ }
+ }
+
+ // Palettes
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}palette-#{$name} {
+ --h: #{cv.getVar($name, "", "-h")};
+ --s: #{cv.getVar($name, "", "-s")};
+ --l: #{cv.getVar($name, "", "-l")};
+ --color: hsl(var(--h), var(--s), var(--l));
+
+ @each $digit in $digits {
+ --#{$digit}-l: #{cv.getVar($name, "", "-#{$digit}-l")};
+ --color-#{$digit}: hsl(var(--h), var(--s), var(--#{$digit}-l));
+ }
+ }
+}
+
+@each $name, $shade in dv.$shades {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$name} {
+ color: $shade !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-#{$name} {
+ background-color: $shade !important;
+ }
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-current {
+ color: currentColor !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-inherit {
+ color: inherit !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-current {
+ background-color: currentColor !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}background-inherit {
+ background-color: inherit !important;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/flexbox.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/flexbox.scss
new file mode 100644
index 0000000..b8c1544
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/flexbox.scss
@@ -0,0 +1,62 @@
+@use "../utilities/initial-variables" as iv;
+
+$flex-direction-values: row, row-reverse, column, column-reverse;
+
+@each $value in $flex-direction-values {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}flex-direction-#{$value} {
+ flex-direction: $value !important;
+ }
+}
+
+$flex-wrap-values: nowrap, wrap, wrap-reverse;
+
+@each $value in $flex-wrap-values {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}flex-wrap-#{$value} {
+ flex-wrap: $value !important;
+ }
+}
+
+$justify-content-values: flex-start, flex-end, center, space-between,
+ space-around, space-evenly, start, end, left, right;
+
+@each $value in $justify-content-values {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}justify-content-#{$value} {
+ justify-content: $value !important;
+ }
+}
+
+$align-content-values: flex-start, flex-end, center, space-between, space-around,
+ space-evenly, stretch, start, end, baseline;
+
+@each $value in $align-content-values {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}align-content-#{$value} {
+ align-content: $value !important;
+ }
+}
+
+$align-items-values: stretch, flex-start, flex-end, center, baseline, start, end,
+ self-start, self-end;
+
+@each $value in $align-items-values {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}align-items-#{$value} {
+ align-items: $value !important;
+ }
+}
+
+$align-self-values: auto, flex-start, flex-end, center, baseline, stretch;
+
+@each $value in $align-self-values {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}align-self-#{$value} {
+ align-self: $value !important;
+ }
+}
+
+$flex-operators: grow, shrink;
+
+@each $operator in $flex-operators {
+ @for $i from 0 through 5 {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}flex-#{$operator}-#{$i} {
+ flex-#{$operator}: $i !important;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/float.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/float.scss
new file mode 100644
index 0000000..9a2bb4e
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/float.scss
@@ -0,0 +1,28 @@
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/mixins" as mx;
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}clearfix {
+ @include mx.clearfix;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}float-left,
+.#{iv.$class-prefix}#{iv.$helpers-prefix}pulled-left {
+ float: left !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}float-right,
+.#{iv.$class-prefix}#{iv.$helpers-prefix}pulled-right {
+ float: right !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}float-none {
+ float: none !important;
+}
+
+$clears: both left none right;
+
+@each $clear in $clears {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}clear-#{$clear} {
+ clear: $clear !important;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/gap.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/gap.scss
new file mode 100644
index 0000000..d386c3d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/gap.scss
@@ -0,0 +1,24 @@
+@use "sass:math";
+@use "sass:string";
+@use "../utilities/initial-variables" as iv;
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}gapless {
+ gap: 0 !important;
+}
+
+$gaps: "gap", "column-gap", "row-gap";
+$gap-base: 0.5rem;
+
+@each $gap in $gaps {
+ @for $i from 0 through 8 {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$gap}-#{$i} {
+ #{$gap}: ($gap-base * $i) !important;
+ }
+
+ @if $i < 8 {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$gap}-#{$i}\.5 {
+ #{$gap}: ($gap-base * $i + math.div($gap-base, 2)) !important;
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/other.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/other.scss
new file mode 100644
index 0000000..66eb040
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/other.scss
@@ -0,0 +1,19 @@
+@use "../utilities/extends";
+@use "../utilities/initial-variables" as iv;
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}radiusless {
+ border-radius: 0 !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}shadowless {
+ box-shadow: none !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}clickable {
+ cursor: pointer !important;
+ pointer-events: all !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}unselectable {
+ @extend %unselectable;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/overflow.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/overflow.scss
new file mode 100644
index 0000000..a03268c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/overflow.scss
@@ -0,0 +1,21 @@
+@use "../utilities/initial-variables" as iv;
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}clipped {
+ overflow: hidden !important;
+}
+
+$overflows: auto clip hidden scroll visible;
+
+@each $overflow in $overflows {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}overflow-#{$overflow} {
+ overflow: $overflow !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}overflow-x-#{$overflow} {
+ overflow-x: $overflow !important;
+ }
+
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}overflow-y-#{$overflow} {
+ overflow-y: $overflow !important;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/position.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/position.scss
new file mode 100644
index 0000000..fca128a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/position.scss
@@ -0,0 +1,19 @@
+@use "../utilities/extends";
+@use "../utilities/initial-variables" as iv;
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}overlay,
+.#{iv.$class-prefix}#{iv.$helpers-prefix}overlay {
+ @extend %overlay;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}relative {
+ position: relative !important;
+}
+
+$positions: absolute fixed relative static sticky;
+
+@each $position in $positions {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}position-#{$position} {
+ position: $position !important;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/spacing.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/spacing.scss
new file mode 100644
index 0000000..1b8dbba
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/spacing.scss
@@ -0,0 +1,64 @@
+@use "../utilities/initial-variables" as iv;
+
+.#{iv.$class-prefix}marginless {
+ margin: 0 !important;
+}
+
+.#{iv.$class-prefix}paddingless {
+ padding: 0 !important;
+}
+
+$spacing-shortcuts: (
+ "margin": "m",
+ "padding": "p",
+) !default;
+$spacing-directions: (
+ "top": "t",
+ "right": "r",
+ "bottom": "b",
+ "left": "l",
+) !default;
+$spacing-horizontal: "x" !default;
+$spacing-vertical: "y" !default;
+$spacing-values: (
+ "0": 0,
+ "1": 0.25rem,
+ "2": 0.5rem,
+ "3": 0.75rem,
+ "4": 1rem,
+ "5": 1.5rem,
+ "6": 3rem,
+ "auto": auto,
+) !default;
+
+@each $property, $shortcut in $spacing-shortcuts {
+ @each $name, $value in $spacing-values {
+ // All directions
+ .#{iv.$class-prefix}#{$shortcut}-#{$name} {
+ #{$property}: $value !important;
+ }
+
+ // Cardinal directions
+ @each $direction, $suffix in $spacing-directions {
+ .#{iv.$class-prefix}#{$shortcut}#{$suffix}-#{$name} {
+ #{$property}-#{$direction}: $value !important;
+ }
+ }
+
+ // Horizontal axis
+ @if $spacing-horizontal != null {
+ .#{iv.$class-prefix}#{$shortcut}#{$spacing-horizontal}-#{$name} {
+ #{$property}-left: $value !important;
+ #{$property}-right: $value !important;
+ }
+ }
+
+ // Vertical axis
+ @if $spacing-vertical != null {
+ .#{iv.$class-prefix}#{$shortcut}#{$spacing-vertical}-#{$name} {
+ #{$property}-top: $value !important;
+ #{$property}-bottom: $value !important;
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/typography.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/typography.scss
new file mode 100644
index 0000000..fbfcabc
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/typography.scss
@@ -0,0 +1,174 @@
+@use "sass:list";
+
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/mixins" as mx;
+
+@mixin typography-size($target: "") {
+ @each $size in dv.$sizes {
+ $i: list.index(dv.$sizes, $size);
+
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}size-#{$i}#{if($target == "", "", "-" + $target)} {
+ font-size: $size !important;
+ }
+ }
+}
+
+@include typography-size;
+
+@include mx.mobile {
+ @include typography-size("mobile");
+}
+
+@include mx.tablet {
+ @include typography-size("tablet");
+}
+
+@include mx.touch {
+ @include typography-size("touch");
+}
+
+@include mx.desktop {
+ @include typography-size("desktop");
+}
+
+@include mx.widescreen {
+ @include typography-size("widescreen");
+}
+
+@include mx.fullhd {
+ @include typography-size("fullhd");
+}
+
+$alignments: (
+ "centered": "center",
+ "justified": "justify",
+ "left": "left",
+ "right": "right",
+);
+
+@each $alignment, $text-align in $alignments {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment} {
+ text-align: #{$text-align} !important;
+ }
+}
+
+@each $alignment, $text-align in $alignments {
+ @include mx.mobile {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment}-mobile {
+ text-align: #{$text-align} !important;
+ }
+ }
+
+ @include mx.tablet {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment}-tablet {
+ text-align: #{$text-align} !important;
+ }
+ }
+
+ @include mx.tablet-only {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment}-tablet-only {
+ text-align: #{$text-align} !important;
+ }
+ }
+
+ @include mx.touch {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment}-touch {
+ text-align: #{$text-align} !important;
+ }
+ }
+
+ @include mx.desktop {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment}-desktop {
+ text-align: #{$text-align} !important;
+ }
+ }
+
+ @include mx.desktop-only {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment}-desktop-only {
+ text-align: #{$text-align} !important;
+ }
+ }
+
+ @include mx.widescreen {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment}-widescreen {
+ text-align: #{$text-align} !important;
+ }
+ }
+
+ @include mx.widescreen-only {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment}-widescreen-only {
+ text-align: #{$text-align} !important;
+ }
+ }
+
+ @include mx.fullhd {
+ .#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-#{$alignment}-fullhd {
+ text-align: #{$text-align} !important;
+ }
+ }
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}capitalized {
+ text-transform: capitalize !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}lowercase {
+ text-transform: lowercase !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}uppercase {
+ text-transform: uppercase !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}italic {
+ font-style: italic !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}underlined {
+ text-decoration: underline !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-weight-light {
+ font-weight: iv.$weight-light !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-weight-normal {
+ font-weight: iv.$weight-normal !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-weight-medium {
+ font-weight: iv.$weight-medium !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-weight-semibold {
+ font-weight: iv.$weight-semibold !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-weight-bold {
+ font-weight: iv.$weight-bold !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-has-prefix}text-weight-extrabold {
+ font-weight: iv.$weight-extrabold !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}family-primary {
+ font-family: dv.$family-primary !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}family-secondary {
+ font-family: dv.$family-secondary !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}family-sans-serif {
+ font-family: iv.$family-sans-serif !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}family-monospace {
+ font-family: iv.$family-monospace !important;
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}family-code {
+ font-family: dv.$family-code !important;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/visibility.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/visibility.scss
new file mode 100644
index 0000000..bccb53f
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/helpers/visibility.scss
@@ -0,0 +1,221 @@
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/mixins" as mx;
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}display-none,
+.#{iv.$class-prefix}#{iv.$helpers-prefix}hidden {
+ display: none !important;
+}
+
+$displays: block flex inline inline-block inline-flex grid;
+
+@each $display in $displays {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display},
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display} {
+ display: $display !important;
+ }
+
+ @include mx.mobile {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display}-mobile,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display}-mobile {
+ display: $display !important;
+ }
+ }
+
+ @include mx.tablet {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display}-tablet,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display}-tablet {
+ display: $display !important;
+ }
+ }
+
+ @include mx.tablet-only {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display}-tablet-only,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display}-tablet-only {
+ display: $display !important;
+ }
+ }
+
+ @include mx.touch {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display}-touch,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display}-touch {
+ display: $display !important;
+ }
+ }
+
+ @include mx.desktop {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display}-desktop,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display}-desktop {
+ display: $display !important;
+ }
+ }
+
+ @include mx.desktop-only {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display}-desktop-only,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display}-desktop-only {
+ display: $display !important;
+ }
+ }
+
+ @include mx.widescreen {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display}-widescreen,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display}-widescreen {
+ display: $display !important;
+ }
+ }
+
+ @include mx.widescreen-only {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display}-widescreen-only,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display}-widescreen-only {
+ display: $display !important;
+ }
+ }
+
+ @include mx.fullhd {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-#{$display}-fullhd,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}#{$display}-fullhd {
+ display: $display !important;
+ }
+ }
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}sr-only {
+ border: none !important;
+ clip: rect(0, 0, 0, 0) !important;
+ height: 0.01em !important;
+ overflow: hidden !important;
+ padding: 0 !important;
+ position: absolute !important;
+ white-space: nowrap !important;
+ width: 0.01em !important;
+}
+
+@include mx.mobile {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-none-mobile,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}hidden-mobile {
+ display: none !important;
+ }
+}
+
+@include mx.tablet {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-none-tablet,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}hidden-tablet {
+ display: none !important;
+ }
+}
+
+@include mx.tablet-only {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-none-tablet-only,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}hidden-tablet-only {
+ display: none !important;
+ }
+}
+
+@include mx.touch {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-none-touch,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}hidden-touch {
+ display: none !important;
+ }
+}
+
+@include mx.desktop {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-none-desktop,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}hidden-desktop {
+ display: none !important;
+ }
+}
+
+@include mx.desktop-only {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-none-desktop-only,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}hidden-desktop-only {
+ display: none !important;
+ }
+}
+
+@include mx.widescreen {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-none-widescreen,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}hidden-widescreen {
+ display: none !important;
+ }
+}
+
+@include mx.widescreen-only {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-none-widescreen-only,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}hidden-widescreen-only {
+ display: none !important;
+ }
+}
+
+@include mx.fullhd {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}display-none-fullhd,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}hidden-fullhd {
+ display: none !important;
+ }
+}
+
+.#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden,
+.#{iv.$class-prefix}#{iv.$helpers-prefix}invisible {
+ visibility: hidden !important;
+}
+
+@include mx.mobile {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden-mobile,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}invisible-mobile {
+ visibility: hidden !important;
+ }
+}
+
+@include mx.tablet {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden-tablet,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}invisible-tablet {
+ visibility: hidden !important;
+ }
+}
+
+@include mx.tablet-only {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden-tablet-only,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}invisible-tablet-only {
+ visibility: hidden !important;
+ }
+}
+
+@include mx.touch {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden-touch,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}invisible-touch {
+ visibility: hidden !important;
+ }
+}
+
+@include mx.desktop {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden-desktop,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}invisible-desktop {
+ visibility: hidden !important;
+ }
+}
+
+@include mx.desktop-only {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden-desktop-only,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}invisible-desktop-only {
+ visibility: hidden !important;
+ }
+}
+
+@include mx.widescreen {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden-widescreen,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}invisible-widescreen {
+ visibility: hidden !important;
+ }
+}
+
+@include mx.widescreen-only {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden-widescreen-only,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}invisible-widescreen-only {
+ visibility: hidden !important;
+ }
+}
+
+@include mx.fullhd {
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}visibility-hidden-fullhd,
+ .#{iv.$class-prefix}#{iv.$helpers-prefix}invisible-fullhd {
+ visibility: hidden !important;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/_index.scss
new file mode 100644
index 0000000..c28494d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/_index.scss
@@ -0,0 +1,9 @@
+/* Bulma Components */
+@charset "utf-8";
+
+@forward "container";
+@forward "footer";
+@forward "hero";
+@forward "level";
+@forward "media";
+@forward "section";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/container.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/container.scss
new file mode 100644
index 0000000..d2d35c1
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/container.scss
@@ -0,0 +1,59 @@
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/mixins" as mx;
+
+$container-offset: 2 * iv.$gap !default;
+$container-max-width: iv.$fullhd !default;
+
+.#{iv.$class-prefix}container {
+ flex-grow: 1;
+ margin: 0 auto;
+ position: relative;
+ width: 100%;
+
+ &.#{iv.$class-prefix}is-fluid {
+ max-width: none !important;
+ padding-left: iv.$gap;
+ padding-right: iv.$gap;
+ width: 100%;
+ }
+
+ &.#{iv.$class-prefix}is-max-tablet {
+ max-width: iv.$tablet - $container-offset;
+ }
+
+ @include mx.desktop {
+ max-width: iv.$desktop - $container-offset;
+ }
+
+ @include mx.until-widescreen {
+ &.#{iv.$class-prefix}is-widescreen:not(
+ .#{iv.$class-prefix}is-max-tablet
+ ):not(.#{iv.$class-prefix}is-max-desktop) {
+ max-width: min(iv.$widescreen, $container-max-width) - $container-offset;
+ }
+ }
+
+ @include mx.until-fullhd {
+ &.#{iv.$class-prefix}is-fullhd:not(.#{iv.$class-prefix}is-max-tablet):not(
+ .#{iv.$class-prefix}is-max-desktop
+ ):not(.#{iv.$class-prefix}is-max-widescreen) {
+ max-width: min(iv.$fullhd, $container-max-width) - $container-offset;
+ }
+ }
+
+ @include mx.widescreen {
+ &:not(.#{iv.$class-prefix}is-max-tablet):not(
+ .#{iv.$class-prefix}is-max-desktop
+ ) {
+ max-width: min(iv.$widescreen, $container-max-width) - $container-offset;
+ }
+ }
+
+ @include mx.fullhd {
+ &:not(.#{iv.$class-prefix}is-max-tablet):not(
+ .#{iv.$class-prefix}is-max-desktop
+ ):not(.#{iv.$class-prefix}is-max-widescreen) {
+ max-width: min(iv.$fullhd, $container-max-width) - $container-offset;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/footer.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/footer.scss
new file mode 100644
index 0000000..bc9b6c8
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/footer.scss
@@ -0,0 +1,23 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+
+$footer-background-color: cv.getVar("scheme-main-bis") !default;
+$footer-color: false !default;
+$footer-padding: 3rem 1.5rem 6rem !default;
+
+.#{iv.$class-prefix}footer {
+ @include cv.register-vars(
+ (
+ "footer-background-color": #{$footer-background-color},
+ "footer-color": #{$footer-color},
+ "footer-padding": #{$footer-padding},
+ )
+ );
+
+ background-color: cv.getVar("footer-background-color");
+ padding: cv.getVar("footer-padding");
+
+ @if $footer-color {
+ color: cv.getVar("footer-color");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/hero.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/hero.scss
new file mode 100644
index 0000000..95db208
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/hero.scss
@@ -0,0 +1,273 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/extends";
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/mixins" as mx;
+
+$hero-body-padding: 3rem 1.5rem !default;
+$hero-body-padding-tablet: 3rem 3rem !default;
+$hero-body-padding-small: 1.5rem !default;
+$hero-body-padding-medium: 9rem 4.5rem !default;
+$hero-body-padding-large: 18rem 6rem !default;
+
+$hero-gradient-h-offset: 5deg !default;
+$hero-gradient-s-offset: 10% !default;
+$hero-gradient-l-offset: 5% !default;
+
+$hero-colors: dv.$colors !default;
+
+// Main container
+.#{iv.$class-prefix}hero {
+ @include cv.register-vars(
+ (
+ "hero-body-padding": #{$hero-body-padding},
+ "hero-body-padding-tablet": #{$hero-body-padding-tablet},
+ "hero-body-padding-small": #{$hero-body-padding-small},
+ "hero-body-padding-medium": #{$hero-body-padding-medium},
+ "hero-body-padding-large": #{$hero-body-padding-large},
+ "hero-gradient-h-offset": #{$hero-gradient-h-offset},
+ "hero-gradient-s-offset": #{$hero-gradient-s-offset},
+ "hero-gradient-l-offset": #{$hero-gradient-l-offset},
+ )
+ );
+}
+
+.#{iv.$class-prefix}hero {
+ align-items: stretch;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+
+ .#{iv.$class-prefix}navbar {
+ background: none;
+ }
+
+ .#{iv.$class-prefix}tabs {
+ ul {
+ border-bottom: none;
+ }
+ }
+
+ // Colors
+ @each $name, $pair in $hero-colors {
+ &.#{iv.$class-prefix}is-#{$name} {
+ @include cv.register-vars(
+ (
+ "hero-h": #{cv.getVar($name, "", "-h")},
+ "hero-s": #{cv.getVar($name, "", "-s")},
+ "hero-background-l": #{cv.getVar($name, "", "-l")},
+ "hero-color-l": #{cv.getVar($name, "", "-invert-l")},
+ )
+ );
+
+ $background-color: hsl(
+ #{cv.getVar("hero-h")},
+ #{cv.getVar("hero-s")},
+ #{cv.getVar("hero-background-l")}
+ );
+ $color: hsl(
+ #{cv.getVar("hero-h")},
+ #{cv.getVar("hero-s")},
+ #{cv.getVar("hero-color-l")}
+ );
+
+ background-color: hsl(
+ #{cv.getVar("hero-h")},
+ #{cv.getVar("hero-s")},
+ #{cv.getVar("hero-background-l")}
+ );
+ color: $color;
+
+ .#{iv.$class-prefix}navbar {
+ @include cv.register-vars(
+ (
+ "navbar-item-color": $color,
+ "navbar-item-hover-background-color": $color,
+ "navbar-item-hover-color": $background-color,
+ "navbar-item-active-background-color": $color,
+ "navbar-item-active-color": $background-color,
+ )
+ );
+ }
+
+ .#{iv.$class-prefix}tabs {
+ @include cv.register-vars(
+ (
+ "tabs-link-color": $color,
+ "tabs-boxed-link-active-background-color": $color,
+ "tabs-boxed-link-active-border-color": $background-color,
+ "tabs-link-active-color": $background-color,
+ )
+ );
+ }
+
+ .#{iv.$class-prefix}subtitle {
+ @include cv.register-vars(
+ (
+ "subtitle-color": $color,
+ "subtitle-strong-color": $color,
+ )
+ );
+ }
+
+ .#{iv.$class-prefix}title {
+ @include cv.register-vars(
+ (
+ "title-color": $color,
+ "title-strong-color": $color,
+ )
+ );
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-bold {
+ $gradient-top-left: hsl(
+ calc(#{cv.getVar("hero-h")} - #{$hero-gradient-h-offset}),
+ calc(#{cv.getVar("hero-s")} + #{$hero-gradient-s-offset}),
+ calc(#{cv.getVar("hero-background-l")} + #{$hero-gradient-l-offset})
+ );
+ $gradient-middle: hsl(
+ #{cv.getVar("hero-h")},
+ #{cv.getVar("hero-s")},
+ #{cv.getVar("hero-background-l")}
+ );
+ $gradient-bottom-right: hsl(
+ calc(#{cv.getVar("hero-h")} + #{$hero-gradient-h-offset}),
+ calc(#{cv.getVar("hero-s")} - #{$hero-gradient-s-offset}),
+ calc(#{cv.getVar("hero-background-l")} - #{$hero-gradient-l-offset})
+ );
+
+ background-image: linear-gradient(
+ 141deg,
+ $gradient-top-left 0%,
+ $gradient-middle 71%,
+ $gradient-bottom-right 100%
+ );
+
+ @include mx.mobile {
+ .#{iv.$class-prefix}navbar-menu {
+ background-image: linear-gradient(
+ 141deg,
+ $gradient-top-left 0%,
+ $color 71%,
+ $gradient-bottom-right 100%
+ );
+ }
+ }
+ }
+ }
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ .#{iv.$class-prefix}hero-body {
+ padding: cv.getVar("hero-body-padding-small");
+ }
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ @include mx.tablet {
+ .#{iv.$class-prefix}hero-body {
+ padding: cv.getVar("hero-body-padding-medium");
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ @include mx.tablet {
+ .#{iv.$class-prefix}hero-body {
+ padding: cv.getVar("hero-body-padding-large");
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-halfheight,
+ &.#{iv.$class-prefix}is-fullheight,
+ &.#{iv.$class-prefix}is-fullheight-with-navbar {
+ .#{iv.$class-prefix}hero-body {
+ align-items: center;
+ display: flex;
+
+ & > .#{iv.$class-prefix}container {
+ flex-grow: 1;
+ flex-shrink: 1;
+ }
+ }
+ }
+
+ &.#{iv.$class-prefix}is-halfheight {
+ min-height: 50vh;
+ }
+
+ &.#{iv.$class-prefix}is-fullheight {
+ min-height: 100vh;
+ }
+}
+
+// Components
+
+.#{iv.$class-prefix}hero-video {
+ @extend %overlay;
+ overflow: hidden;
+
+ video {
+ left: 50%;
+ min-height: 100%;
+ min-width: 100%;
+ position: absolute;
+ top: 50%;
+ transform: translate3d(-50%, -50%, 0);
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-transparent {
+ opacity: 0.3;
+ }
+
+ // Responsiveness
+ @include mx.mobile {
+ display: none;
+ }
+}
+
+.#{iv.$class-prefix}hero-buttons {
+ margin-top: 1.5rem;
+
+ // Responsiveness
+ @include mx.mobile {
+ .#{iv.$class-prefix}button {
+ display: flex;
+
+ &:not(:last-child) {
+ margin-bottom: 0.75rem;
+ }
+ }
+ }
+
+ @include mx.tablet {
+ display: flex;
+ justify-content: center;
+
+ .#{iv.$class-prefix}button:not(:last-child) {
+ margin-inline-end: 1.5rem;
+ }
+ }
+}
+
+// Containers
+
+.#{iv.$class-prefix}hero-head,
+.#{iv.$class-prefix}hero-foot {
+ flex-grow: 0;
+ flex-shrink: 0;
+}
+
+.#{iv.$class-prefix}hero-body {
+ flex-grow: 1;
+ flex-shrink: 0;
+ padding: cv.getVar("hero-body-padding");
+
+ @include mx.tablet {
+ padding: cv.getVar("hero-body-padding-tablet");
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/level.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/level.scss
new file mode 100644
index 0000000..dbb5a47
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/level.scss
@@ -0,0 +1,107 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$level-item-spacing: calc(#{cv.getVar("block-spacing")} * 0.5) !default;
+
+.#{iv.$class-prefix}level {
+ @extend %block;
+ @include cv.register-var("level-item-spacing", #{$level-item-spacing});
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ gap: cv.getVar("level-item-spacing");
+
+ code {
+ border-radius: cv.getVar("radius");
+ }
+
+ img {
+ display: inline-block;
+ vertical-align: top;
+ }
+
+ // Modifiers
+ &.#{iv.$class-prefix}is-mobile {
+ display: flex;
+ flex-direction: row;
+
+ .#{iv.$class-prefix}level-left,
+ .#{iv.$class-prefix}level-right {
+ display: flex;
+ }
+
+ .#{iv.$class-prefix}level-item {
+ &:not(.#{iv.$class-prefix}is-narrow) {
+ flex-grow: 1;
+ }
+ }
+ }
+
+ // Responsiveness
+ @include mx.tablet {
+ display: flex;
+ flex-direction: row;
+
+ & > .#{iv.$class-prefix}level-item {
+ &:not(.#{iv.$class-prefix}is-narrow) {
+ flex-grow: 1;
+ }
+ }
+ }
+}
+
+.#{iv.$class-prefix}level-item {
+ align-items: center;
+ display: flex;
+ flex-basis: auto;
+ flex-grow: 0;
+ flex-shrink: 0;
+ justify-content: center;
+
+ .#{iv.$class-prefix}title,
+ .#{iv.$class-prefix}subtitle {
+ margin-bottom: 0;
+ }
+}
+
+.#{iv.$class-prefix}level-left,
+.#{iv.$class-prefix}level-right {
+ flex-basis: auto;
+ flex-grow: 0;
+ flex-shrink: 0;
+ gap: $level-item-spacing;
+
+ .#{iv.$class-prefix}level-item {
+ // Modifiers
+ &.#{iv.$class-prefix}is-flexible {
+ flex-grow: 1;
+ }
+ }
+}
+
+.#{iv.$class-prefix}level-left {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+
+ // Responsiveness
+ @include mx.tablet {
+ flex-direction: row;
+ }
+}
+
+.#{iv.$class-prefix}level-right {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+
+ // Responsiveness
+ @include mx.tablet {
+ flex-direction: row;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/media.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/media.scss
new file mode 100644
index 0000000..e65ced8
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/media.scss
@@ -0,0 +1,106 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/extends";
+@use "../utilities/mixins" as mx;
+
+$media-border-color: hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("border-l")},
+ 0.5
+) !default;
+$media-border-size: 1px !default;
+$media-spacing: 1rem !default;
+$media-spacing-large: 1.5rem !default;
+$media-content-spacing: 0.75rem !default;
+$media-level-1-spacing: 0.75rem !default;
+$media-level-1-content-spacing: 0.5rem !default;
+$media-level-2-spacing: 0.5rem !default;
+
+.#{iv.$class-prefix}media {
+ @extend %block;
+ @include cv.register-vars(
+ (
+ "media-border-color": #{$media-border-color},
+ "media-border-size": #{$media-border-size},
+ "media-spacing": #{$media-spacing},
+ "media-spacing-large": #{$media-spacing-large},
+ "media-content-spacing": #{$media-content-spacing},
+ "media-level-1-spacing": #{$media-level-1-spacing},
+ "media-level-1-content-spacing": #{$media-level-1-content-spacing},
+ "media-level-2-spacing": #{$media-level-2-spacing},
+ )
+ );
+ align-items: flex-start;
+ display: flex;
+ text-align: inherit;
+
+ .#{iv.$class-prefix}content:not(:last-child) {
+ margin-bottom: cv.getVar("media-content-spacing");
+ }
+
+ .#{iv.$class-prefix}media {
+ border-top-color: cv.getVar("media-border-color");
+ border-top-style: solid;
+ border-top-width: cv.getVar("media-border-size");
+ display: flex;
+ padding-top: cv.getVar("media-level-1-spacing");
+
+ .#{iv.$class-prefix}content:not(:last-child),
+ .#{iv.$class-prefix}control:not(:last-child) {
+ margin-bottom: cv.getVar("media-level-1-content-spacing");
+ }
+
+ .#{iv.$class-prefix}media {
+ padding-top: cv.getVar("media-level-2-spacing");
+
+ & + .#{iv.$class-prefix}media {
+ margin-top: cv.getVar("media-level-2-spacing");
+ }
+ }
+ }
+
+ & + .#{iv.$class-prefix}media {
+ border-top-color: cv.getVar("media-border-color");
+ border-top-style: solid;
+ border-top-width: cv.getVar("media-border-size");
+ margin-top: cv.getVar("media-spacing");
+ padding-top: cv.getVar("media-spacing");
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-large {
+ & + .#{iv.$class-prefix}media {
+ margin-top: cv.getVar("media-spacing-large");
+ padding-top: cv.getVar("media-spacing-large");
+ }
+ }
+}
+
+.#{iv.$class-prefix}media-left,
+.#{iv.$class-prefix}media-right {
+ flex-basis: auto;
+ flex-grow: 0;
+ flex-shrink: 0;
+}
+
+.#{iv.$class-prefix}media-left {
+ margin-inline-end: cv.getVar("media-spacing");
+}
+
+.#{iv.$class-prefix}media-right {
+ margin-inline-start: cv.getVar("media-spacing");
+}
+
+.#{iv.$class-prefix}media-content {
+ flex-basis: auto;
+ flex-grow: 1;
+ flex-shrink: 1;
+ text-align: inherit;
+}
+
+@include mx.mobile {
+ .#{iv.$class-prefix}media-content {
+ overflow-x: auto;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/section.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/section.scss
new file mode 100644
index 0000000..ba9d162
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/layout/section.scss
@@ -0,0 +1,38 @@
+@use "../utilities/css-variables" as cv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/mixins" as mx;
+
+$section-padding: 3rem 1.5rem !default;
+$section-padding-desktop: 3rem 3rem !default;
+$section-padding-medium: 9rem 4.5rem !default;
+$section-padding-large: 18rem 6rem !default;
+
+.#{iv.$class-prefix}section {
+ @include cv.register-vars(
+ (
+ "section-padding": #{$section-padding},
+ "section-padding-desktop": #{$section-padding-desktop},
+ "section-padding-medium": #{$section-padding-medium},
+ "section-padding-large": #{$section-padding-large},
+ )
+ );
+ padding: cv.getVar("section-padding");
+
+ // Responsiveness
+ @include mx.desktop {
+ padding: cv.getVar("section-padding-desktop");
+
+ // Sizes
+ &.#{iv.$class-prefix}is-medium {
+ padding: cv.getVar("section-padding-medium");
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ padding: cv.getVar("section-padding-large");
+ }
+ }
+
+ &.#{iv.$class-prefix}is-fullheight {
+ min-height: 100vh;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/_index.scss
new file mode 100644
index 0000000..d665f38
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/_index.scss
@@ -0,0 +1,36 @@
+/* Bulma Themes */
+@charset "utf-8";
+
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/css-variables" as cv;
+
+@use "light";
+@use "dark";
+@use "setup";
+
+#{iv.$variables-host} {
+ @include light.light-theme;
+ @include setup.setup-theme;
+}
+
+// prefers-color-scheme: light
+@include cv.system-theme($name: "light") {
+ @include light.light-theme;
+}
+
+// prefers-color-scheme: dark
+@include cv.system-theme($name: "dark") {
+ @include dark.dark-theme;
+}
+
+// :root, [data-theme=light], .theme-light
+@include cv.bulma-theme($name: "light") {
+ @include light.light-theme;
+ @include setup.setup-theme;
+}
+
+// [data-theme=dark], .theme-dark
+@include cv.bulma-theme($name: "dark") {
+ @include dark.dark-theme;
+ @include setup.setup-theme;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/dark.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/dark.scss
new file mode 100644
index 0000000..f51869c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/dark.scss
@@ -0,0 +1,57 @@
+@use "sass:list";
+@use "sass:meta";
+
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "setup";
+
+// The main lightness of this theme
+$scheme-main-l: 9%;
+$background-l: 14%;
+$text-l: 71%;
+
+// The main scheme color, used to make calculations
+$scheme-main: hsl(iv.$scheme-h, iv.$scheme-s, $scheme-main-l);
+$background: hsl(iv.$scheme-h, iv.$scheme-s, $background-l);
+$text: hsl(iv.$scheme-h, iv.$scheme-s, $text-l);
+
+@mixin dark-theme {
+ @each $name, $color in dv.$colors {
+ $base: $color;
+
+ @if meta.type-of($color == "list") {
+ $base: list.nth($color, 1);
+ }
+
+ @include cv.generate-on-scheme-colors($name, $base, $scheme-main);
+ }
+
+ @include cv.register-vars(
+ (
+ "scheme-brightness": "dark",
+ "scheme-main-l": $scheme-main-l,
+ "scheme-main-bis-l": $scheme-main-l + 2%,
+ "scheme-main-ter-l": $scheme-main-l + 4%,
+ "soft-l": iv.$dark-l,
+ "bold-l": iv.$light-l,
+ "soft-invert-l": iv.$light-l,
+ "bold-invert-l": iv.$dark-l,
+ "background-l": $background-l,
+ "border-weak-l": 21%,
+ "border-l": 24%,
+ "text-weak-l": 53%,
+ "text-l": $text-l,
+ "text-strong-l": 93%,
+ "text-title-l": 100%,
+ "hover-background-l-delta": 5%,
+ "active-background-l-delta": 10%,
+ "hover-border-l-delta": 10%,
+ "active-border-l-delta": 20%,
+ "hover-color-l-delta": 5%,
+ "active-color-l-delta": 10%,
+ )
+ );
+
+ @include cv.register-hsl("shadow", white);
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/light.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/light.scss
new file mode 100644
index 0000000..3be1ac6
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/light.scss
@@ -0,0 +1,147 @@
+@use "sass:list";
+@use "sass:meta";
+
+@use "../utilities/css-variables" as cv;
+@use "../utilities/derived-variables" as dv;
+@use "../utilities/initial-variables" as iv;
+@use "../utilities/functions" as fn;
+@use "setup";
+
+// The main lightness of this theme
+$scheme-main-l: 100%;
+
+// The main scheme color, used to make calculations
+$scheme-main: hsl(iv.$scheme-h, iv.$scheme-s, $scheme-main-l);
+
+@mixin light-theme {
+ @include cv.register-vars(
+ (
+ "scheme-h": iv.$scheme-h,
+ "scheme-s": iv.$scheme-s,
+ "light-l": iv.$light-l,
+ "light-invert-l": iv.$dark-l,
+ "dark-l": iv.$dark-l,
+ "dark-invert-l": iv.$light-l,
+ "soft-l": iv.$light-l,
+ "bold-l": iv.$dark-l,
+ "soft-invert-l": iv.$dark-l,
+ "bold-invert-l": iv.$light-l,
+
+ // Deltas
+ "hover-background-l-delta": -5%,
+ "active-background-l-delta": -10%,
+
+ "hover-border-l-delta": -10%,
+ "active-border-l-delta": -20%,
+
+ "hover-color-l-delta": -5%,
+ "active-color-l-delta": -10%,
+
+ "hover-shadow-a-delta": -0.05,
+ "active-shadow-a-delta": -0.1,
+
+ // Light only
+ "scheme-brightness": "light",
+ "scheme-main-l": $scheme-main-l,
+ "scheme-main-bis-l": 98%,
+ "scheme-main-ter-l": 96%,
+ "background-l": 96%,
+ "border-weak-l": 93%,
+ "border-l": 86%,
+ "text-weak-l": 48%,
+ "text-l": 29%,
+ "text-strong-l": 21%,
+ "text-title-l": 14%,
+ "scheme-invert-ter-l": 14%,
+ "scheme-invert-bis-l": 7%,
+ "scheme-invert-l": 4%,
+
+ // Typography
+ "family-primary": dv.$family-primary,
+ "family-secondary": dv.$family-secondary,
+ "family-code": dv.$family-code,
+ "size-small": dv.$size-small,
+ "size-normal": dv.$size-normal,
+ "size-medium": dv.$size-medium,
+ "size-large": dv.$size-large,
+ "weight-light": iv.$weight-light,
+ "weight-normal": iv.$weight-normal,
+ "weight-medium": iv.$weight-medium,
+ "weight-semibold": iv.$weight-semibold,
+ "weight-bold": iv.$weight-bold,
+ "weight-extrabold": iv.$weight-extrabold,
+
+ // Other
+ "block-spacing": iv.$block-spacing,
+ "duration": iv.$duration,
+ "easing": iv.$easing,
+ "radius-small": iv.$radius-small,
+ "radius": iv.$radius,
+ "radius-medium": iv.$radius-medium,
+ "radius-large": iv.$radius-large,
+ "radius-rounded": iv.$radius-rounded,
+ "speed": iv.$speed,
+
+ "arrow-color": #{cv.getVar("link")},
+ "loading-color": #{cv.getVar("border")},
+ "burger-h": #{cv.getVar("link-h")},
+ "burger-s": #{cv.getVar("link-s")},
+ "burger-l": #{cv.getVar("link-l")},
+ "burger-border-radius": 0.5em,
+ // Using px values to prevent half pixel issues
+ "burger-gap": 5px,
+ "burger-item-height": 2px,
+ "burger-item-width": 20px,
+ )
+ );
+
+ // Colors
+ $no-palette: ("white", "black", "light", "dark");
+
+ @each $name, $color in dv.$colors {
+ $base: $color;
+ $invert: null;
+ $light: null;
+ $dark: null;
+
+ @if meta.type-of($color == "list") {
+ $base: list.nth($color, 1);
+
+ @if list.length($color) > 3 {
+ $invert: list.nth($color, 2);
+ $light: list.nth($color, 3);
+ $dark: list.nth($color, 4);
+ } @else if list.length($color) > 1 {
+ $invert: list.nth($color, 2);
+ }
+ }
+
+ @if list.index($no-palette, $name) {
+ @include cv.generate-basic-palette($name, $base, $invert);
+ } @else {
+ @include cv.generate-color-palette(
+ $name,
+ $base,
+ $scheme-main-l,
+ $invert,
+ $light,
+ $dark
+ );
+ }
+
+ @include cv.generate-on-scheme-colors($name, $base, $scheme-main);
+ }
+
+ // Shades
+ @each $name, $shade in dv.$shades {
+ @include cv.register-var($name, $shade);
+ }
+
+ @include cv.register-hsl("shadow", dv.$shadow-color);
+
+ @each $size in dv.$sizes {
+ $i: list.index(dv.$sizes, $size);
+ $name: "size-#{$i}";
+ @include cv.register-var($name, $size);
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/setup.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/setup.scss
new file mode 100644
index 0000000..6caddf7
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/themes/setup.scss
@@ -0,0 +1,174 @@
+@use "../utilities/css-variables" as cv;
+
+@mixin setup-theme() {
+ @include cv.register-vars(
+ (
+ // Computed
+ "scheme-main":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-main-l")}
+ ),
+ "scheme-main-bis":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-main-bis-l")}
+ ),
+ "scheme-main-ter":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-main-ter-l")}
+ ),
+ "background":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("background-l")}
+ ),
+ "background-hover":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ calc(
+ #{cv.getVar("background-l")} + #{cv.getVar(
+ "hover-background-l-delta"
+ )}
+ )
+ ),
+ "background-active":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ calc(
+ #{cv.getVar("background-l")} + #{cv.getVar(
+ "active-background-l-delta"
+ )}
+ )
+ ),
+ "border-weak":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("border-weak-l")}
+ ),
+ "border":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("border-l")}
+ ),
+ "border-hover":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ calc(#{cv.getVar("border-l")} + #{cv.getVar("hover-border-l-delta")})
+ ),
+ "border-active":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ calc(#{cv.getVar("border-l")} + #{cv.getVar("active-border-l-delta")})
+ ),
+ "text-weak":
+ hsl(
+ #{cv.getVar("text-h")},
+ #{cv.getVar("text-s")},
+ #{cv.getVar("text-weak-l")}
+ ),
+ "text":
+ hsl(
+ #{cv.getVar("text-h")},
+ #{cv.getVar("text-s")},
+ #{cv.getVar("text-l")}
+ ),
+ "text-strong":
+ hsl(
+ #{cv.getVar("text-h")},
+ #{cv.getVar("text-s")},
+ #{cv.getVar("text-strong-l")}
+ ),
+ "scheme-invert-ter":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-ter-l")}
+ ),
+ "scheme-invert-bis":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-bis-l")}
+ ),
+ "scheme-invert":
+ hsl(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("scheme-invert-l")}
+ ),
+ "link":
+ hsl(
+ #{cv.getVar("link-h")},
+ #{cv.getVar("link-s")},
+ #{cv.getVar("link-l")}
+ ),
+ "link-text":
+ hsl(
+ #{cv.getVar("link-h")},
+ #{cv.getVar("link-s")},
+ #{cv.getVar("link-on-scheme-l")}
+ ),
+ "link-text-hover":
+ hsl(
+ #{cv.getVar("link-h")},
+ #{cv.getVar("link-s")},
+ calc(
+ #{cv.getVar("link-on-scheme-l")} + #{cv.getVar(
+ "hover-color-l-delta"
+ )}
+ )
+ ),
+ "link-text-active":
+ hsl(
+ #{cv.getVar("link-h")},
+ #{cv.getVar("link-s")},
+ calc(
+ #{cv.getVar("link-on-scheme-l")} + #{cv.getVar(
+ "active-color-l-delta"
+ )}
+ )
+ ),
+ "focus-h": #{cv.getVar("link-h")},
+ "focus-s": #{cv.getVar("link-s")},
+ "focus-l": #{cv.getVar("link-l")},
+ "focus-offset": 1px,
+ "focus-style": solid,
+ "focus-width": 2px,
+ "focus-shadow-size": 0 0 0 0.1875em,
+ "focus-shadow-alpha": 0.25,
+ "code":
+ hsl(
+ #{cv.getVar("danger-h")},
+ #{cv.getVar("danger-s")},
+ #{cv.getVar("danger-on-scheme-l")}
+ ),
+ "code-background": #{cv.getVar("background")},
+ "pre": #{cv.getVar("text")},
+ "pre-background": #{cv.getVar("background")},
+ "shadow": (
+ 0 0.5em 1em -0.125em hsla(#{cv.getVar("shadow-h")}, #{cv.getVar(
+ "shadow-s"
+ )}, #{cv.getVar("shadow-l")}, 0.1),
+ 0 0px 0 1px
+ hsla(
+ #{cv.getVar("shadow-h")},
+ #{cv.getVar("shadow-s")},
+ #{cv.getVar("shadow-l")},
+ 0.02
+ )
+ )
+ )
+ );
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/_index.scss
new file mode 100644
index 0000000..12e06bc
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/_index.scss
@@ -0,0 +1,7 @@
+/* Bulma Utilities */
+@charset "utf-8";
+
+@forward "initial-variables";
+@forward "functions";
+@forward "derived-variables";
+@forward "controls";
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/controls.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/controls.scss
new file mode 100644
index 0000000..47a3d75
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/controls.scss
@@ -0,0 +1,85 @@
+@use "css-variables" as cv;
+@use "derived-variables" as dv;
+@use "initial-variables" as iv;
+
+$control-radius: cv.getVar("radius") !default;
+$control-radius-small: cv.getVar("radius-small") !default;
+
+$control-border-width: 1px !default;
+$control-size: cv.getVar("size-normal") !default;
+
+$control-height: 2.5em !default;
+$control-line-height: 1.5 !default;
+
+$control-padding-vertical: calc(0.5em - #{$control-border-width}) !default;
+$control-padding-horizontal: calc(0.75em - #{$control-border-width}) !default;
+
+$control-focus-shadow-l: 50% !default;
+
+#{iv.$variables-host} {
+ @include cv.register-vars(
+ (
+ "control-radius": #{$control-radius},
+ "control-radius-small": #{$control-radius-small},
+ "control-border-width": #{$control-border-width},
+ "control-height": #{$control-height},
+ "control-line-height": #{$control-line-height},
+ "control-padding-vertical": #{$control-padding-vertical},
+ "control-padding-horizontal": #{$control-padding-horizontal},
+ "control-size": #{$control-size},
+ "control-focus-shadow-l": #{$control-focus-shadow-l},
+ )
+ );
+}
+
+@mixin control {
+ align-items: center;
+ appearance: none;
+ border-color: transparent;
+ border-style: solid;
+ border-width: cv.getVar("control-border-width");
+ border-radius: cv.getVar("control-radius");
+ box-shadow: none;
+ display: inline-flex;
+ font-size: cv.getVar("control-size");
+ height: cv.getVar("control-height");
+ justify-content: flex-start;
+ line-height: cv.getVar("control-line-height");
+ padding-bottom: cv.getVar("control-padding-vertical");
+ padding-left: cv.getVar("control-padding-horizontal");
+ padding-right: cv.getVar("control-padding-horizontal");
+ padding-top: cv.getVar("control-padding-vertical");
+ position: relative;
+ transition-duration: cv.getVar("duration");
+ transition-property: background-color, border-color, box-shadow, color;
+ vertical-align: top;
+
+ // States
+ &:focus,
+ &:focus-visible,
+ &:focus-within,
+ &.#{iv.$class-prefix}is-focused,
+ &:active,
+ &.#{iv.$class-prefix}is-active {
+ outline: none;
+ }
+
+ &[disabled],
+ fieldset[disabled] & {
+ cursor: not-allowed;
+ }
+}
+
+// The controls sizes use mixins so they can be used at different breakpoints
+@mixin control-small {
+ border-radius: $control-radius-small;
+ font-size: cv.getVar("size-small");
+}
+
+@mixin control-medium {
+ font-size: cv.getVar("size-medium");
+}
+
+@mixin control-large {
+ font-size: cv.getVar("size-large");
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/css-variables.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/css-variables.scss
new file mode 100644
index 0000000..499fa35
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/css-variables.scss
@@ -0,0 +1,502 @@
+@use "sass:color";
+@use "sass:list";
+@use "sass:map";
+@use "sass:math";
+
+@use "initial-variables" as iv;
+@use "functions" as fn;
+
+@function buildVarName($name, $prefix: "", $suffix: "") {
+ @return "--#{iv.$cssvars-prefix}#{$prefix}#{$name}#{$suffix}";
+}
+
+@function buildHslaString($name, $l, $a: 1) {
+ $lightness: getVar($name, "", "-l");
+ @if ($l) {
+ $lightness: $l;
+ }
+ @return "hsla(#{getVar($name, '', '-h')}, #{getVar($name, '', '-s')}, #{$lightness}, #{$a})";
+}
+
+@function getVar($name, $prefix: "", $suffix: "") {
+ $varName: buildVarName($name, $prefix, $suffix);
+ @return var(#{$varName});
+}
+
+@function getVarWithBackup($name, $backup, $prefix: "", $suffix: "") {
+ $varName: buildVarName($name, $prefix, $suffix);
+ $backupName: buildVarName($backup, $prefix, $suffix);
+ @return var(#{$varName}, var(#{$backupName}));
+}
+
+@function getRgbaVar($name, $alpha, $prefix: "", $suffix: "") {
+ $varName: buildVarName($name, $prefix, $suffix);
+ @return unquote("rgba(var(#{$varName}), #{$alpha})");
+}
+
+@mixin register-var($name, $value, $prefix: "", $suffix: "") {
+ $varName: buildVarName($name, $prefix, $suffix);
+ #{$varName}: #{$value};
+}
+
+@mixin register-vars($vars, $prefix: "", $suffix: "") {
+ @each $name, $value in $vars {
+ @include register-var($name, $value, $prefix, $suffix);
+ }
+}
+
+@mixin register-rgb($name, $value) {
+ @include register-var(
+ $name,
+ (
+ color.channel($value, "red", $space: rgb),
+ color.channel($value, "green", $space: rgb),
+ color.channel($value, "blue", $space: rgb)
+ ),
+ "",
+ "-rgb"
+ );
+}
+
+@mixin register-hsl($name, $value) {
+ @include register-var(
+ $name,
+ math.round(color.channel($value, "hue", $space: hsl)),
+ "",
+ "-h"
+ );
+ @include register-var(
+ $name,
+ math.round(color.channel($value, "saturation", $space: hsl)),
+ "",
+ "-s"
+ );
+ @include register-var(
+ $name,
+ math.round(color.channel($value, "lightness", $space: hsl)),
+ "",
+ "-l"
+ );
+}
+
+@mixin generate-on-scheme-colors($name, $base, $scheme-main) {
+ // Accessibility Contrast System
+ $scheme-main-brightness: fn.bulmaColorBrightness($scheme-main);
+ $on-scheme-color: $base;
+ $fg-lum: fn.bulmaColorLuminance($on-scheme-color);
+ $bg-lum: fn.bulmaColorLuminance($scheme-main);
+ $ratio: 0;
+ $found-decent-color: false;
+
+ @if ($fg-lum > $bg-lum) {
+ @for $i from 0 through 20 {
+ $ratio: math.div(($fg-lum + 0.05), ($bg-lum + 0.05));
+
+ @if $ratio > 5 {
+ $found-decent-color: true;
+ } @else {
+ $on-scheme-color: color.adjust(
+ $on-scheme-color,
+ $lightness: 5%,
+ $space: hsl
+ );
+ $fg-lum: fn.bulmaColorLuminance($on-scheme-color);
+ }
+ }
+ } @else {
+ @for $i from 0 through 20 {
+ $ratio: math.div(($bg-lum + 0.05), ($fg-lum + 0.05));
+
+ @if $ratio > 5 {
+ $found-decent-color: true;
+ } @else {
+ $on-scheme-color: color.adjust(
+ $on-scheme-color,
+ $lightness: -5%,
+ $space: hsl
+ );
+ $fg-lum: fn.bulmaColorLuminance($on-scheme-color);
+ }
+ }
+ }
+
+ $on-scheme-lightness: color.channel(
+ $on-scheme-color,
+ "lightness",
+ $space: hsl
+ );
+ @include register-var($name, $on-scheme-lightness, "", "-on-scheme-l");
+ $on-scheme-l: getVar($name, "", "-on-scheme-l");
+ @include register-var(
+ "#{$name}-on-scheme",
+ buildHslaString($name, $on-scheme-l)
+ );
+}
+
+@mixin v1-generate-on-scheme-colors($name, $base, $scheme-main) {
+ // Accessibility Contrast System
+ $scheme-main-brightness: fn.bulmaColorBrightness($scheme-main);
+ $on-scheme-color: $base;
+
+ @if ($scheme-main-brightness == "bright") {
+ @while (fn.bulmaEnoughContrast($on-scheme-color, #fff) == false) {
+ // We're on a light background, so we'll darken the test color step by step.
+ $on-scheme-color: color.adjust(
+ $on-scheme-color,
+ $lightness: -5%,
+ $space: hsl
+ );
+ }
+ } @else {
+ @while (fn.bulmaEnoughContrast($on-scheme-color, #000) == false) {
+ // We're on a dark background, so we'll lighten the test color step by step.
+ $on-scheme-color: color.adjust(
+ $on-scheme-color,
+ $lightness: 5%,
+ $space: hsl
+ );
+ }
+ }
+
+ $on-scheme-lightness: color.channel(
+ $on-scheme-color,
+ "lightness",
+ $space: hsl
+ );
+ @include register-var($name, $on-scheme-lightness, "", "-on-scheme-l");
+}
+
+@mixin register-base-color($name, $base) {
+ $hsla: buildHslaString($name, getVar($name, "", "-l"));
+ @include register-var($name, $hsla);
+ @include register-var($name, $hsla, "", "-base"); // Just for reference
+ @include register-rgb($name, $base);
+ @include register-hsl($name, $base);
+}
+
+@mixin generate-basic-palette($name, $base, $invert: null) {
+ @include register-base-color($name, $base);
+
+ @if $invert {
+ @include register-var(
+ $name,
+ color.channel($invert, "lightness", $space: hsl),
+ "",
+ "-invert-l"
+ );
+ @include register-var("#{$name}-invert", $invert);
+ }
+}
+
+@mixin generate-color-palette(
+ $name,
+ $base,
+ $scheme-main-l: 100%,
+ $invert: null,
+ $light: null,
+ $dark: null
+) {
+ $h:math.round(color.channel($base, "hue", $space: hsl)); // Hue
+ $s:math.round(color.channel($base, "saturation", $space: hsl)); // Saturation
+ $l:math.round(color.channel($base, "lightness", $space: hsl)); // Lightness
+ $base-lum: fn.bulmaColorLuminance($base);
+ $l-base: math.round($l % 10); // Get lightness second digit: 53% -> 3%
+ $l-0: 0%; // 5% or less
+ $l-5: 5%; // More than 5%
+ $a: 1; // Alpha
+ $base-digits: "00";
+
+ // Calculate digits like "40" for the scheme-main
+ $scheme-l-0: 0%;
+ $scheme-l-base: math.round($scheme-main-l % 10);
+ $closest-5: math.round(math.div($scheme-main-l, 5)) * 5;
+ $pct-to-int: math.div($closest-5, 100%) * 100;
+ $scheme-main-digits: #{$pct-to-int};
+
+ // === STEP 1 ===
+ // Register the base colors
+ @include register-base-color($name, $base);
+
+ // === STEP 2 ===
+ // Generating 20 shades of the color
+
+ // 00: 0%, 1%, 2%
+ // 05: 3%, 4%, 5%, 6%, 7%
+ // 10: 8%, 9%
+
+ @if ($l-base < 3%) {
+ $l-0: $l-base;
+ $l-5: $l-base + 5%;
+ } @else if ($l-base < 8%) {
+ // $l-0: math.max($l-base - 5%, 0%);
+ $l-0: $l-base - 5%;
+ $l-5: $l-base;
+ } @else {
+ // $l-0: math.max($l-base - 10%, 0%);
+ $l-0: $l-base - 10%;
+ $l-5: $l-base - 5%;
+ }
+
+ $shades: ();
+
+ @for $i from 0 through 9 {
+ // if $l-base = 3%, then we get 3%, 13%, 23%, 33% etc.
+ $color-l-0: math.max($l-0 + $i * 10, 0%);
+
+ // if $l-base = 3%, then we get 8%, 18%, 28%, 38% etc.
+ $color-l-5: $l-5 + $i * 10;
+
+ $shades: map.set($shades, "#{$i}0", $color-l-0);
+ $shades: map.set($shades, "#{$i}5", $color-l-5);
+
+ @include register-var($name, $color-l-0, "", "-#{$i}0-l");
+ @include register-var($name, $color-l-5, "", "-#{$i}5-l");
+
+ @if $color-l-0 == $l {
+ $base-digits: "#{$i}0";
+ } @else if $color-l-5 == $l {
+ $base-digits: "#{$i}5";
+ }
+ }
+
+ $l-100: math.min($l-0 + 100%, 100%);
+ $shades: map.set($shades, "100", $l-100);
+ @include register-var($name, $l-100, "", "-100-l");
+
+ // === STEP 3 ===
+ // Find accessible color combinations
+
+ $combos: ();
+
+ @each $digits-bg, $bg-l in $shades {
+ $background: hsl($h, $s, $bg-l);
+ $bg-lum: fn.bulmaColorLuminance($background);
+ $bg-is-light: $bg-lum > 0.55;
+ $candidates: ();
+ $found: false;
+
+ // If the background color is the base color
+ @if $bg-l == $l {
+ $base-digits: $digits-bg;
+
+ // Even if the base color as a background
+ // doesn't have an appropriate foreground,
+ // we still add to the list of "valid" contrast combos for now.
+ @if $bg-is-light {
+ $combos: map.set($combos, $base-digits, "10");
+ } @else {
+ $combos: map.set($combos, $base-digits, "100");
+ }
+ }
+
+ // We capture all contrast ratios for any given background
+ // using all foreground options
+ $current-best-digits: "00";
+ $current-best-ratio: 0;
+
+ @each $digits-fg, $fg-l in $shades {
+ $foreground: hsl($h, $s, $fg-l);
+ $ratio: 0;
+ $is-light-fg: false;
+
+ // Source: https://www.w3.org/TR/WCAG20-TECHS/G17.html
+ $fg-lum: fn.bulmaColorLuminance($foreground);
+
+ @if (
+ color.channel($foreground, "lightness", $space: hsl) >
+ color.channel($background, "lightness", $space: hsl)
+ ) {
+ $is-light-fg: true;
+ $ratio: math.div(($fg-lum + 0.05), ($bg-lum + 0.05));
+ } @else {
+ $ratio: math.div(($bg-lum + 0.05), ($fg-lum + 0.05));
+ }
+
+ @if $ratio > 7 {
+ $candidates: list.append(
+ $candidates,
+ fn.bulmaStringToNumber($digits-fg)
+ );
+
+ @if ($is-light-fg) {
+ @if (not $found) {
+ // Store the background/foreground combination
+ $combos: map.set($combos, $digits-bg, $digits-fg);
+ $current-best-digits: $digits-fg;
+ $current-best-ratio: $ratio;
+ $found: true;
+ }
+ } @else {
+ $combos: map.set($combos, $digits-bg, $digits-fg);
+ $current-best-digits: $digits-fg;
+ $current-best-ratio: $ratio;
+ }
+ }
+ }
+
+ // We haven't found a decent ratio
+ @each $digits-fg, $fg-l in $shades {
+ @if (map.has-key($combos, $digits-bg) == false) {
+ @if ($bg-is-light) {
+ // Light background so we set a dark foreground
+ $combos: map.set($combos, $digits-bg, "00");
+ } @else {
+ // Dark background so we set a light foreground
+ $combos: map.set($combos, $digits-bg, "100");
+ }
+ }
+ }
+ }
+
+ // The output needs to be:
+ // --bulma-primary-invert-l: var(--bulma-primary-100-l);
+
+ @each $bg, $fg in $combos {
+ // Just using this loop to register all 20 digits
+ $bg-l: getVar($name, "", "-#{$bg}-l");
+ @include register-var("#{$name}-#{$bg}", buildHslaString($name, $bg-l));
+
+ // Register the lightness
+ @include register-var(
+ $name,
+ getVar($name, "", "-#{$fg}-l"),
+ "",
+ "-#{$bg}-invert-l"
+ );
+
+ // Resiter the color using that lightness
+ $bg-invert-l: getVar($name, "", "-#{$bg}-invert-l");
+ @include register-var(
+ "#{$name}-#{$bg}-invert",
+ buildHslaString($name, $bg-invert-l)
+ );
+ }
+
+ // If an invert color is provided by the user
+ @if $invert {
+ @include register-var(
+ $name,
+ color.channel($invert, "lightness", $space: hsl),
+ "",
+ "-invert-l"
+ );
+ @include register-var("#{$name}-invert", $invert);
+ } @else {
+ $base-invert-l-digits: map.get($combos, $base-digits);
+ @include register-var(
+ $name,
+ getVar($name, "", "-#{$base-invert-l-digits}-l"),
+ "",
+ "-invert-l"
+ );
+
+ $base-invert-l: getVar($name, "", "-invert-l");
+ @include register-var(
+ "#{$name}-invert",
+ buildHslaString($name, $base-invert-l)
+ );
+ }
+
+ // Good color on light background (90% lightness)
+ @if $light and $dark {
+ @include register-var(
+ $name,
+ color.channel($light, "lightness", $space: hsl),
+ "",
+ "-light-l"
+ );
+ @include register-var(
+ $name,
+ color.channel($light, "lightness", $space: hsl),
+ "",
+ "-dark-invert-l"
+ );
+ @include register-var("#{$name}-light", $light);
+ @include register-var("#{$name}-dark-invert", $light);
+
+ @include register-var(
+ $name,
+ color.channel($dark, "lightness", $space: hsl),
+ "",
+ "-dark-l"
+ );
+ @include register-var(
+ $name,
+ color.channel($dark, "lightness", $space: hsl),
+ "",
+ "-light-invert-l"
+ );
+ @include register-var("#{$name}-dark", $dark);
+ @include register-var("#{$name}-light-invert", $dark);
+ } @else {
+ @include register-var($name, getVar($name, "", "-90-l"), "", "-light-l");
+
+ $light-l: getVar($name, "", "-light-l");
+ @include register-var("#{$name}-light", buildHslaString($name, $light-l));
+
+ $light-invert-l-digits: map.get($combos, "90");
+ @include register-var(
+ $name,
+ getVar($name, "", "-#{$light-invert-l-digits}-l"),
+ "",
+ "-light-invert-l"
+ );
+
+ $light-invert-l: getVar($name, "", "-light-invert-l");
+ @include register-var(
+ "#{$name}-light-invert",
+ buildHslaString($name, $light-invert-l)
+ );
+
+ // Good color on dark background (10% lightness)
+ @include register-var($name, getVar($name, "", "-10-l"), "", "-dark-l");
+
+ $dark-l: getVar($name, "", "-dark-l");
+ @include register-var("#{$name}-dark", buildHslaString($name, $dark-l));
+
+ $dark-invert-l-digits: map.get($combos, "10");
+ @include register-var(
+ $name,
+ getVar($name, "", "-#{$dark-invert-l-digits}-l"),
+ "",
+ "-dark-invert-l"
+ );
+
+ $dark-invert-l: getVar($name, "", "-dark-invert-l");
+ @include register-var(
+ "#{$name}-dark-invert",
+ buildHslaString($name, $dark-invert-l)
+ );
+
+ // Soft and Bold colors
+ $soft-l: getVar("soft-l");
+ $soft-invert-l: getVar("soft-invert-l");
+ $bold-l: getVar("bold-l");
+ $bold-invert-l: getVar("bold-invert-l");
+ @include register-var("#{$name}-soft", buildHslaString($name, $soft-l));
+ @include register-var("#{$name}-bold", buildHslaString($name, $bold-l));
+ @include register-var(
+ "#{$name}-soft-invert",
+ buildHslaString($name, $soft-invert-l)
+ );
+ @include register-var(
+ "#{$name}-bold-invert",
+ buildHslaString($name, $bold-invert-l)
+ );
+ }
+}
+
+@mixin bulma-theme($name) {
+ [data-#{iv.$class-prefix}theme="#{$name}"],
+ .#{iv.$class-prefix}theme-#{$name} {
+ @content;
+ }
+}
+
+@mixin system-theme($name) {
+ @media (prefers-color-scheme: #{$name}) {
+ #{iv.$variables-host} {
+ @content;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/derived-variables.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/derived-variables.scss
new file mode 100644
index 0000000..6f1440d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/derived-variables.scss
@@ -0,0 +1,112 @@
+@use "initial-variables" as iv;
+@use "functions" as fn;
+
+// Scheme colors
+
+$scheme-main: iv.$white !default;
+$scheme-main-bis: iv.$white-bis !default;
+$scheme-main-ter: iv.$white-ter !default;
+$scheme-invert: iv.$black !default;
+$scheme-invert-bis: iv.$black-bis !default;
+$scheme-invert-ter: iv.$black-ter !default;
+
+// Text colors
+
+$text: iv.$grey-dark !default;
+$text-invert: fn.bulmaFindColorInvert($text) !default;
+$text-weak: iv.$grey !default;
+$text-strong: iv.$grey-darker !default;
+
+// Status colors
+
+$primary: iv.$turquoise !default;
+$info: iv.$cyan !default;
+$success: iv.$green !default;
+$warning: iv.$yellow !default;
+$danger: iv.$red !default;
+$light: iv.$white-ter !default;
+$dark: iv.$grey-darker !default;
+
+// Link colors
+
+$link: iv.$blue !default;
+
+// Decorative colors
+
+$background: iv.$white-ter !default;
+$border: iv.$grey-lighter !default;
+$border-weak: iv.$grey-lightest !default;
+
+// Code colors
+
+$code: iv.$red !default;
+$code-background: $background !default;
+
+$pre: $text !default;
+$pre-background: $background !default;
+
+// Typography
+
+$family-primary: iv.$family-sans-serif !default;
+$family-secondary: iv.$family-sans-serif !default;
+$family-code: iv.$family-monospace !default;
+
+$size-small: iv.$size-7 !default;
+$size-normal: iv.$size-6 !default;
+$size-medium: iv.$size-5 !default;
+$size-large: iv.$size-4 !default;
+
+// Effects
+
+$shadow-color: iv.$black !default;
+
+// Lists and maps
+$custom-colors: null !default;
+$custom-shades: null !default;
+
+$colors: fn.mergeColorMaps(
+ (
+ "white": (
+ iv.$white,
+ iv.$black,
+ ),
+ "black": (
+ iv.$black,
+ iv.$white,
+ ),
+ "light": (
+ $light,
+ $dark,
+ ),
+ "dark": (
+ $dark,
+ $light,
+ ),
+ "text": $text,
+ "primary": $primary,
+ "link": $link,
+ "info": $info,
+ "success": $success,
+ "warning": $warning,
+ "danger": $danger,
+ ),
+ $custom-colors
+) !default;
+
+$shades: fn.mergeColorMaps(
+ (
+ "black-bis": iv.$black-bis,
+ "black-ter": iv.$black-ter,
+ "grey-darker": iv.$grey-darker,
+ "grey-dark": iv.$grey-dark,
+ "grey": iv.$grey,
+ "grey-light": iv.$grey-light,
+ "grey-lighter": iv.$grey-lighter,
+ "white-ter": iv.$white-ter,
+ "white-bis": iv.$white-bis,
+ ),
+ $custom-shades
+) !default;
+
+$sizes: iv.$size-1 iv.$size-2 iv.$size-3 iv.$size-4 iv.$size-5 iv.$size-6
+ iv.$size-7 !default;
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/extends.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/extends.scss
new file mode 100644
index 0000000..42d05fe
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/extends.scss
@@ -0,0 +1,34 @@
+@use "controls";
+@use "mixins";
+
+%arrow {
+ @include mixins.arrow;
+}
+
+%block {
+ @include mixins.block;
+}
+
+%control {
+ @include controls.control;
+}
+
+%delete {
+ @include mixins.delete;
+}
+
+%loader {
+ @include mixins.loader;
+}
+
+%overlay {
+ @include mixins.overlay;
+}
+
+%reset {
+ @include mixins.reset;
+}
+
+%unselectable {
+ @include mixins.unselectable;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/functions.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/functions.scss
new file mode 100644
index 0000000..2ea2b10
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/functions.scss
@@ -0,0 +1,310 @@
+@use "sass:color";
+@use "sass:list";
+@use "sass:map";
+@use "sass:math";
+@use "sass:meta";
+@use "sass:string";
+
+@function mergeColorMaps($bulma-colors, $custom-colors) {
+ // We return at least Bulma's hard-coded colors
+ $merged-colors: $bulma-colors;
+
+ // We want a map as input
+ @if meta.type-of($custom-colors) == "map" {
+ @each $name, $components in $custom-colors {
+ // The color name should be a string
+ // and the components either a single color
+ // or a colors list with at least one element
+ @if meta.type-of($name) ==
+ "string" and
+ (
+ meta.type-of($components) ==
+ "list" or
+ meta.type-of($components) ==
+ "color"
+ ) and
+ list.length($components) >=
+ 1
+ {
+ $color-base: null;
+ $color-invert: null;
+ $color-light: null;
+ $color-dark: null;
+ $value: null;
+
+ // The param can either be a single color
+ // or a list of 2 colors
+ @if meta.type-of($components) == "color" {
+ $color-base: $components;
+ $color-invert: bulmaFindColorInvert($color-base);
+ $color-light: bulmaFindLightColor($color-base);
+ $color-dark: bulmaFindDarkColor($color-base);
+ } @else if meta.type-of($components) == "list" {
+ $color-base: list.nth($components, 1);
+
+ // If Invert, Light and Dark are provided
+ @if list.length($components) > 3 {
+ $color-invert: list.nth($components, 2);
+ $color-light: list.nth($components, 3);
+ $color-dark: list.nth($components, 4);
+
+ // If only Invert and Light are provided
+ } @else if list.length($components) > 2 {
+ $color-invert: list.nth($components, 2);
+ $color-light: list.nth($components, 3);
+ $color-dark: bulmaFindDarkColor($color-base);
+
+ // If only Invert is provided
+ } @else {
+ $color-invert: list.nth($components, 2);
+ $color-light: bulmaFindLightColor($color-base);
+ $color-dark: bulmaFindDarkColor($color-base);
+ }
+ }
+
+ $value: $color-base, $color-invert, $color-light, $color-dark;
+
+ // We only want to merge the map if the color base is an actual color
+ @if meta.type-of($color-base) == "color" {
+ // We merge this colors elements as map with Bulma's colors map
+ // (we can override them this way, no multiple definition for the same name)
+ // $merged-colors: map_merge($merged-colors, ($name: ($color-base, $color-invert, $color-light, $color-dark)))
+ $merged-colors: map.merge(
+ $merged-colors,
+ (
+ $name: $value,
+ )
+ );
+ }
+ }
+ }
+ }
+
+ @return $merged-colors;
+}
+
+@function powerNumber($number, $exp) {
+ $value: 1;
+
+ @if $exp > 0 {
+ @for $i from 1 through $exp {
+ $value: $value * $number;
+ }
+ } @else if $exp < 0 {
+ @for $i from 1 through -$exp {
+ $value: math.div($value, $number);
+ }
+ }
+
+ @return $value;
+}
+
+@function bulmaColorLuminance($color) {
+ @if meta.type-of($color) != "color" {
+ @return 0.55;
+ }
+
+ $color-rgb: (
+ "red": color.channel($color, "red", $space: rgb),
+ "green": color.channel($color, "green", $space: rgb),
+ "blue": color.channel($color, "blue", $space: rgb),
+ );
+
+ @each $name, $value in $color-rgb {
+ $adjusted: 0;
+ $value: math.div($value, 255);
+
+ @if $value < 0.03928 {
+ $value: math.div($value, 12.92);
+ } @else {
+ $value: math.div($value + 0.055, 1.055);
+ $value: powerNumber($value, 2);
+ }
+
+ $color-rgb: map.merge(
+ $color-rgb,
+ (
+ $name: $value,
+ )
+ );
+ }
+
+ @return map.get($color-rgb, "red") * 0.2126 + map.get($color-rgb, "green") *
+ 0.7152 + map.get($color-rgb, "blue") * 0.0722;
+}
+
+@function bulmaFindColorInvert($color) {
+ @if bulmaColorLuminance($color) > 0.55 {
+ @return rgba(#000, 0.7);
+ } @else {
+ @return #fff;
+ }
+}
+
+@function bulmaFindLightColor($color, $l: 96%) {
+ @if meta.type-of($color) == "color" {
+ $l: 96%;
+
+ @if color.channel($color, "lightness", $space: hsl) > 96% {
+ $l: color.channel($color, "lightness", $space: hsl);
+ }
+
+ @return color.change($color, $lightness: $l);
+ }
+
+ @return $background;
+}
+
+@function bulmaFindDarkColor($color, $base-l: 29%) {
+ @if meta.type-of($color) == "color" {
+ $luminance: bulmaColorLuminance($color);
+ $luminance-delta: 0.53 - $luminance;
+ $target-l: math.round($base-l + $luminance-delta * 53);
+
+ @return color.change($color, $lightness: max($base-l, $target-l));
+ }
+
+ @return $text-strong;
+}
+
+@function bulmaRgba($color, $alpha) {
+ @if meta.type-of($color) != "color" {
+ @return $color;
+ }
+
+ @return rgba($color, $alpha);
+}
+
+@function bulmaDarken($color, $amount) {
+ @if meta.type-of($color) != "color" {
+ @return $color;
+ }
+
+ @return color.adjust($color, $lightness: -$amount, $space: hsl);
+}
+
+@function bulmaLighten($color, $amount) {
+ @if meta.type-of($color) != "color" {
+ @return $color;
+ }
+
+ @return color.adjust($color, $lightness: $amount, $space: hsl);
+}
+
+@function bulmaColorBrightness($n) {
+ $color-brightness: math.round(
+ math.div(
+ (color.channel($n, "red", $space: rgb) * 299) +
+ (color.channel($n, "green", $space: rgb) * 587) +
+ (color.channel($n, "blue", $space: rgb) * 114),
+ 1000
+ )
+ );
+ $light-color: math.round(
+ math.div(
+ (color.channel(#ffffff, "red", $space: rgb) * 299) +
+ (color.channel(#ffffff, "green", $space: rgb) * 587) +
+ (color.channel(#ffffff, "blue", $space: rgb) * 114),
+ 1000
+ )
+ );
+
+ @if abs($color-brightness) < math.div($light-color, 2) {
+ @return "dark";
+ }
+
+ @return "bright";
+}
+
+@function bulmaEnoughContrast($foreground, $background) {
+ $r: (
+ max(
+ color.channel($foreground, "red", $space: rgb),
+ color.channel($background, "red", $space: rgb)
+ )
+ ) -
+ (
+ min(
+ color.channel($foreground, "red", $space: rgb),
+ color.channel($background, "red", $space: rgb)
+ )
+ );
+ $g: (
+ max(
+ color.channel($foreground, "green", $space: rgb),
+ color.channel($background, "green", $space: rgb)
+ )
+ ) -
+ (
+ min(
+ color.channel($foreground, "green", $space: rgb),
+ color.channel($background, "green", $space: rgb)
+ )
+ );
+ $b: (
+ max(
+ color.channel($foreground, "blue", $space: rgb),
+ color.channel($background, "blue", $space: rgb)
+ )
+ ) -
+ (
+ min(
+ color.channel($foreground, "blue", $space: rgb),
+ color.channel($background, "blue", $space: rgb)
+ )
+ );
+ $sum-rgb: $r + $g + $b;
+
+ @if $sum-rgb < 500 {
+ @return false;
+ }
+
+ @return true;
+}
+
+// By Cory Simmons https://corysimmons.com/
+@function bulmaStringToNumber($value) {
+ @if meta.type-of($value) == "number" {
+ @return $value;
+ } @else if meta.type-of($value) != "string" {
+ $_: log("Value for `to-number` should be a number or a string.");
+ }
+
+ $result: 0;
+ $digits: 0;
+ $minus: string.slice($value, 1, 1) == "-";
+ $numbers: (
+ "0": 0,
+ "1": 1,
+ "2": 2,
+ "3": 3,
+ "4": 4,
+ "5": 5,
+ "6": 6,
+ "7": 7,
+ "8": 8,
+ "9": 9,
+ );
+
+ @for $i from if($minus, 2, 1) through string.length($value) {
+ $character: string.slice($value, $i, $i);
+
+ @if not(list.index(map.keys($numbers), $character) or $character == ".") {
+ @return to-length(
+ if($minus, -$result, $result),
+ string.slice($value, $i)
+ );
+ }
+
+ @if $character == "." {
+ $digits: 1;
+ } @else if $digits == 0 {
+ $result: $result * 10 + map.get($numbers, $character);
+ } @else {
+ $digits: $digits * 10;
+ $result: $result + map.get($numbers, $character) / $digits;
+ }
+ }
+
+ @return if($minus, -$result, $result);
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/initial-variables.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/initial-variables.scss
new file mode 100644
index 0000000..8d68061
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/initial-variables.scss
@@ -0,0 +1,157 @@
+// Scheme Hue and Saturation
+
+$scheme-h: 221 !default;
+$scheme-s: 14% !default;
+$dark-l: 20% !default;
+$light-l: 90% !default;
+
+// Colors
+
+$black: hsl(221, 14%, 4%) !default;
+$black-bis: hsl(221, 14%, 9%) !default;
+$black-ter: hsl(221, 14%, 14%) !default;
+
+$grey-darker: hsl(221, 14%, 21%) !default;
+$grey-dark: hsl(221, 14%, 29%) !default;
+$grey: hsl(221, 14%, 48%) !default;
+$grey-light: hsl(221, 14%, 71%) !default;
+$grey-lighter: hsl(221, 14%, 86%) !default;
+$grey-lightest: hsl(221, 14%, 93%) !default;
+
+$white-ter: hsl(221, 14%, 96%) !default;
+$white-bis: hsl(221, 14%, 98%) !default;
+$white: hsl(221, 14%, 100%) !default;
+
+$orange: hsl(14, 100%, 53%) !default;
+$yellow: hsl(42, 100%, 53%) !default;
+$green: hsl(153, 53%, 53%) !default;
+$turquoise: hsl(171, 100%, 41%) !default;
+$cyan: hsl(198, 100%, 70%) !default;
+$blue: hsl(233, 100%, 63%) !default;
+$purple: hsl(271, 100%, 71%) !default;
+$red: hsl(348, 100%, 70%) !default;
+
+// Typography
+
+$family-sans-serif: "Inter", "SF Pro", "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
+ "Helvetica Neue", "Helvetica", "Arial", sans-serif !default;
+$family-monospace: "Inconsolata", "Hack", "SF Mono", "Roboto Mono",
+ "Source Code Pro", "Ubuntu Mono", monospace !default;
+$render-mode: optimizeLegibility !default;
+
+$size-1: 3rem !default;
+$size-2: 2.5rem !default;
+$size-3: 2rem !default;
+$size-4: 1.5rem !default;
+$size-5: 1.25rem !default;
+$size-6: 1rem !default;
+$size-7: 0.75rem !default;
+
+$weight-light: 300 !default;
+$weight-normal: 400 !default;
+$weight-medium: 500 !default;
+$weight-semibold: 600 !default;
+$weight-bold: 700 !default;
+$weight-extrabold: 800 !default;
+
+// Spacing
+
+$block-spacing: 1.5rem !default;
+$aspect-ratios: (
+ (1, 1),
+ (5, 4),
+ (4, 3),
+ (3, 2),
+ (5, 3),
+ (16, 9),
+ (2, 1),
+ (3, 1),
+ (4, 5),
+ (3, 4),
+ (2, 3),
+ (3, 5),
+ (9, 16),
+ (1, 2),
+ (1, 3)
+) !default;
+
+// Responsiveness
+
+// The container horizontal gap, which acts as the offset for breakpoints
+$gap: 32px !default;
+
+// 960, 1152, and 1344 have been chosen because they are divisible by both 12 and 16
+$tablet: 769px !default;
+
+// 960px container + 4rem
+$desktop: 960px + 2 * $gap !default;
+
+// 1152px container + 4rem
+$widescreen: 1152px + 2 * $gap !default;
+$widescreen-enabled: true !default;
+
+// 1344px container + 4rem
+$fullhd: 1344px + 2 * $gap !default;
+$fullhd-enabled: true !default;
+$breakpoints: (
+ "mobile": (
+ "until": $tablet,
+ ),
+ "tablet": (
+ "from": $tablet,
+ ),
+ "tablet-only": (
+ "from": $tablet,
+ "until": $desktop,
+ ),
+ "touch": (
+ "from": $desktop,
+ ),
+ "desktop": (
+ "from": $desktop,
+ ),
+ "desktop-only": (
+ "from": $desktop,
+ "until": $widescreen,
+ ),
+ "until-widescreen": (
+ "until": $widescreen,
+ ),
+ "widescreen": (
+ "from": $widescreen,
+ ),
+ "widescreen-only": (
+ "from": $widescreen,
+ "until": $fullhd,
+ ),
+ "until-fullhd": (
+ "until": $fullhd,
+ ),
+ "fullhd": (
+ "from": $fullhd,
+ ),
+) !default;
+
+// Miscellaneous
+
+$duration: 294ms !default;
+$easing: ease-out !default;
+$radius-small: 0.25rem !default;
+$radius: 0.375rem !default;
+$radius-medium: 0.5em !default;
+$radius-large: 0.75rem !default;
+$radius-rounded: 9999px !default;
+$speed: 86ms !default;
+
+// Flags
+
+$variable-columns: true !default;
+$rtl: false !default;
+
+// Prefixes
+
+$class-prefix: "" !default;
+$cssvars-prefix: "bulma-" !default;
+$helpers-prefix: "is-" !default;
+$helpers-has-prefix: "has-" !default;
+$variables-host: ":root" !default;
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/mixins.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/mixins.scss
new file mode 100644
index 0000000..8481cac
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/01_frameworks/bulma-1.04/utilities/mixins.scss
@@ -0,0 +1,462 @@
+@use "sass:map";
+
+@use "initial-variables" as iv;
+@use "css-variables" as cv;
+
+@mixin arrow($color: #{cv.getVar("arrow-color")}) {
+ border: 0.125em solid $color;
+ border-right: 0;
+ border-top: 0;
+ content: " ";
+ display: block;
+ height: 0.625em;
+ margin-top: -0.4375em;
+ pointer-events: none;
+ position: absolute;
+ top: 50%;
+ transform: rotate(-45deg);
+ transform-origin: center;
+ transition-duration: cv.getVar("duration");
+ transition-property: border-color;
+ width: 0.625em;
+}
+
+@mixin block($spacing: cv.getVar("block-spacing")) {
+ &:not(:last-child) {
+ margin-bottom: $spacing;
+ }
+}
+
+@mixin center($width, $height: 0) {
+ position: absolute;
+ @if $height != 0 {
+ left: calc(50% - (#{$width} * 0.5));
+ top: calc(50% - (#{$height} * 0.5));
+ } @else {
+ left: calc(50% - (#{$width} * 0.5));
+ top: calc(50% - (#{$width} * 0.5));
+ }
+}
+
+@mixin clearfix {
+ &::after {
+ clear: both;
+ content: " ";
+ display: table;
+ }
+}
+
+@mixin delete {
+ @include cv.register-vars(
+ (
+ "delete-dimensions": 1.25rem,
+ "delete-background-l": 0%,
+ "delete-background-alpha": 0.5,
+ "delete-color": #{cv.getVar("white")},
+ )
+ );
+
+ appearance: none;
+ background-color: hsla(
+ #{cv.getVar("scheme-h")},
+ #{cv.getVar("scheme-s")},
+ #{cv.getVar("delete-background-l")},
+ #{cv.getVar("delete-background-alpha")}
+ );
+ border: none;
+ border-radius: cv.getVar("radius-rounded");
+ cursor: pointer;
+ pointer-events: auto;
+ display: inline-flex;
+ flex-grow: 0;
+ flex-shrink: 0;
+ font-size: 1em;
+ height: cv.getVar("delete-dimensions");
+ max-height: cv.getVar("delete-dimensions");
+ max-width: cv.getVar("delete-dimensions");
+ min-height: cv.getVar("delete-dimensions");
+ min-width: cv.getVar("delete-dimensions");
+ outline: none;
+ position: relative;
+ vertical-align: top;
+ width: cv.getVar("delete-dimensions");
+
+ &::before,
+ &::after {
+ background-color: cv.getVar("delete-color");
+ content: "";
+ display: block;
+ left: 50%;
+ position: absolute;
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%) rotate(45deg);
+ transform-origin: center center;
+ }
+
+ &::before {
+ height: 2px;
+ width: 50%;
+ }
+
+ &::after {
+ height: 50%;
+ width: 2px;
+ }
+
+ &:hover,
+ &:focus {
+ @include cv.register-var("delete-background-alpha", 0.4);
+ }
+
+ &:active {
+ @include cv.register-var("delete-background-alpha", 0.5);
+ }
+
+ // Sizes
+ &.#{iv.$class-prefix}is-small {
+ @include cv.register-var("delete-dimensions", 1rem);
+ }
+
+ &.#{iv.$class-prefix}is-medium {
+ @include cv.register-var("delete-dimensions", 1.5rem);
+ }
+
+ &.#{iv.$class-prefix}is-large {
+ @include cv.register-var("delete-dimensions", 2rem);
+ }
+}
+
+@mixin fa($size, $dimensions) {
+ display: inline-block;
+ font-size: $size;
+ height: $dimensions;
+ line-height: $dimensions;
+ text-align: center;
+ vertical-align: top;
+ width: $dimensions;
+}
+
+@mixin burger($dimensions) {
+ align-items: center;
+ appearance: none;
+ background: none;
+ border: none;
+ border-radius: cv.getVar("burger-border-radius");
+ color: hsl(
+ cv.getVar("burger-h"),
+ cv.getVar("burger-s"),
+ cv.getVar("burger-l")
+ );
+ cursor: pointer;
+ display: inline-flex;
+ flex-direction: column;
+ flex-shrink: 0;
+ height: $dimensions;
+ justify-content: center;
+ position: relative;
+ vertical-align: top;
+ width: $dimensions;
+
+ span {
+ background-color: currentColor;
+ display: block;
+ height: cv.getVar("burger-item-height");
+ left: calc(50% - calc(#{cv.getVar("burger-item-width")}) / 2);
+ position: absolute;
+ transform-origin: center;
+ transition-duration: cv.getVar("duration");
+ transition-property: background-color, color, opacity, transform;
+ transition-timing-function: cv.getVar("easing");
+ width: cv.getVar("burger-item-width");
+
+ &:nth-child(1),
+ &:nth-child(2) {
+ top: calc(50% - calc(#{cv.getVar("burger-item-height")}) / 2);
+ }
+
+ &:nth-child(3) {
+ bottom: calc(50% + #{cv.getVar("burger-gap")});
+ }
+
+ &:nth-child(4) {
+ top: calc(50% + #{cv.getVar("burger-gap")});
+ }
+ }
+
+ &:hover {
+ background-color: hsla(
+ cv.getVar("burger-h"),
+ cv.getVar("burger-s"),
+ cv.getVar("burger-l"),
+ 0.1
+ );
+ }
+
+ &:active {
+ background-color: hsla(
+ cv.getVar("burger-h"),
+ cv.getVar("burger-s"),
+ cv.getVar("burger-l"),
+ 0.2
+ );
+ }
+
+ // Modifers
+ &.#{iv.$class-prefix}is-active {
+ span {
+ &:nth-child(1) {
+ transform: rotate(-45deg);
+ }
+
+ &:nth-child(2) {
+ transform: rotate(45deg);
+ }
+
+ &:nth-child(3),
+ &:nth-child(4) {
+ opacity: 0;
+ }
+ }
+ }
+}
+
+@mixin overflow-touch {
+ -webkit-overflow-scrolling: touch;
+}
+
+@mixin placeholder {
+ $placeholders: ":-moz" ":-webkit-input" "-moz" "-ms-input";
+
+ @each $placeholder in $placeholders {
+ &:#{$placeholder}-placeholder {
+ @content;
+ }
+ }
+}
+
+@mixin reset {
+ appearance: none;
+ background: none;
+ border: none;
+ color: inherit;
+ font-family: inherit;
+ font-size: 1em;
+ margin: 0;
+ padding: 0;
+}
+
+@mixin selection($current-selector: false) {
+ @if $current-selector {
+ &::-moz-selection {
+ @content;
+ }
+ &::selection {
+ @content;
+ }
+ } @else {
+ ::-moz-selection {
+ @content;
+ }
+ ::selection {
+ @content;
+ }
+ }
+}
+
+// Responsiveness
+
+@mixin from($device) {
+ @media screen and (min-width: $device) {
+ @content;
+ }
+}
+
+@mixin until($device) {
+ @media screen and (max-width: ($device - 1px)) {
+ @content;
+ }
+}
+
+@mixin between($from, $until) {
+ @media screen and (min-width: $from) and (max-width: ($until - 1px)) {
+ @content;
+ }
+}
+
+@mixin mobile {
+ @media screen and (max-width: (iv.$tablet - 1px)) {
+ @content;
+ }
+}
+
+@mixin tablet {
+ @media screen and (min-width: iv.$tablet), print {
+ @content;
+ }
+}
+
+@mixin tablet-only {
+ @media screen and (min-width: iv.$tablet) and (max-width: (iv.$desktop - 1px)) {
+ @content;
+ }
+}
+
+@mixin touch {
+ @media screen and (max-width: (iv.$desktop - 1px)) {
+ @content;
+ }
+}
+
+@mixin desktop {
+ @media screen and (min-width: iv.$desktop) {
+ @content;
+ }
+}
+
+@mixin desktop-only {
+ @if iv.$widescreen-enabled {
+ @media screen and (min-width: iv.$desktop) and (max-width: (iv.$widescreen - 1px)) {
+ @content;
+ }
+ }
+}
+
+@mixin until-widescreen {
+ @if iv.$widescreen-enabled {
+ @media screen and (max-width: (iv.$widescreen - 1px)) {
+ @content;
+ }
+ }
+}
+
+@mixin widescreen {
+ @if iv.$widescreen-enabled {
+ @media screen and (min-width: iv.$widescreen) {
+ @content;
+ }
+ }
+}
+
+@mixin widescreen-only {
+ @if iv.$widescreen-enabled and iv.$fullhd-enabled {
+ @media screen and (min-width: iv.$widescreen) and (max-width: (iv.$fullhd - 1px)) {
+ @content;
+ }
+ }
+}
+
+@mixin until-fullhd {
+ @if iv.$fullhd-enabled {
+ @media screen and (max-width: (iv.$fullhd - 1px)) {
+ @content;
+ }
+ }
+}
+
+@mixin fullhd {
+ @if iv.$fullhd-enabled {
+ @media screen and (min-width: iv.$fullhd) {
+ @content;
+ }
+ }
+}
+
+@mixin breakpoint($name) {
+ $breakpoint: map.get(iv.$breakpoints, $name);
+
+ @if $breakpoint {
+ $from: map.get($breakpoint, "from");
+ $until: map.get($breakpoint, "until");
+
+ @if $from and $until {
+ @include between($from, $until) {
+ @content;
+ }
+ } @else if $from {
+ @include from($from) {
+ @content;
+ }
+ } @else if $until {
+ @include until($until) {
+ @content;
+ }
+ }
+ }
+}
+
+@mixin container-from($name, $width) {
+ @container #{$name} (min-width: #{$width}) {
+ @content;
+ }
+}
+
+@mixin container-until($name, $width) {
+ @container #{$name} (max-width: #{$width - 1px}) {
+ @content;
+ }
+}
+
+@mixin ltr {
+ @if not iv.$rtl {
+ @content;
+ }
+}
+
+@mixin rtl {
+ @if iv.$rtl {
+ @content;
+ }
+}
+
+@mixin ltr-property($property, $spacing, $right: true) {
+ $normal: if($right, "right", "left");
+ $opposite: if($right, "left", "right");
+
+ @if iv.$rtl {
+ #{$property}-#{$opposite}: $spacing;
+ } @else {
+ #{$property}-#{$normal}: $spacing;
+ }
+}
+
+@mixin ltr-position($spacing, $right: true) {
+ $normal: if($right, "right", "left");
+ $opposite: if($right, "left", "right");
+
+ @if iv.$rtl {
+ #{$opposite}: $spacing;
+ } @else {
+ #{$normal}: $spacing;
+ }
+}
+
+// Placeholders
+
+@mixin unselectable {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+@mixin loader {
+ animation: spinAround 500ms infinite linear;
+ border: 2px solid cv.getVar("loading-color");
+ border-radius: cv.getVar("radius-rounded");
+ border-right-color: transparent;
+ border-top-color: transparent;
+ content: "";
+ display: block;
+ height: 1em;
+ position: relative;
+ width: 1em;
+}
+
+@mixin overlay($offset: 0) {
+ bottom: $offset;
+ left: $offset;
+ position: absolute;
+ right: $offset;
+ top: $offset;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/02_fonts/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/02_fonts/_index.scss
new file mode 100644
index 0000000..09929c7
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/02_fonts/_index.scss
@@ -0,0 +1,3 @@
+// @import 'playfair-display-v40-latin';
+// @import 'source-sans-3-v19-latin';
+@import 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.3.0/css/all.min.css';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/02_fonts/_playfair-display-v40-latin.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/02_fonts/_playfair-display-v40-latin.scss
new file mode 100644
index 0000000..3069a6f
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/02_fonts/_playfair-display-v40-latin.scss
@@ -0,0 +1,96 @@
+// playfair-display-regular - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: normal;
+ font-weight: 400;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-regular.woff2') format('woff2');
+}
+// playfair-display-italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: italic;
+ font-weight: 400;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-italic.woff2') format('woff2');
+}
+// playfair-display-500 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: normal;
+ font-weight: 500;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-500.woff2') format('woff2');
+}
+// playfair-display-500italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: italic;
+ font-weight: 500;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-500italic.woff2') format('woff2');
+}
+// playfair-display-600 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: normal;
+ font-weight: 600;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-600.woff2') format('woff2');
+}
+// playfair-display-600italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: italic;
+ font-weight: 600;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-600italic.woff2') format('woff2');
+}
+// playfair-display-700 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: normal;
+ font-weight: 700;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-700.woff2') format('woff2');
+}
+// playfair-display-700italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: italic;
+ font-weight: 700;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-700italic.woff2') format('woff2');
+}
+// playfair-display-800 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: normal;
+ font-weight: 800;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-800.woff2') format('woff2');
+}
+// playfair-display-800italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: italic;
+ font-weight: 800;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-800italic.woff2') format('woff2');
+}
+// playfair-display-900 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: normal;
+ font-weight: 900;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-900.woff2') format('woff2');
+}
+// playfair-display-900italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Playfair Display';
+ font-style: italic;
+ font-weight: 900;
+ src: url('../fonts/playfair-display-v40-latin/playfair-display-v40-latin-900italic.woff2') format('woff2');
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/02_fonts/_source-sans-3-v19-latin.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/02_fonts/_source-sans-3-v19-latin.scss
new file mode 100644
index 0000000..21173b6
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/02_fonts/_source-sans-3-v19-latin.scss
@@ -0,0 +1,134 @@
+// source-sans-3-200 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: normal;
+ font-weight: 200;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-200.woff2') format('woff2');
+}
+
+// source-sans-3-200italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: italic;
+ font-weight: 200;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-200italic.woff2') format('woff2');
+}
+
+// source-sans-3-300 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: normal;
+ font-weight: 300;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-300.woff2') format('woff2');
+}
+
+// source-sans-3-300italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: italic;
+ font-weight: 300;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-300italic.woff2') format('woff2');
+}
+
+// source-sans-3-regular - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: normal;
+ font-weight: 400;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-regular.woff2') format('woff2');
+}
+
+// source-sans-3-italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: italic;
+ font-weight: 400;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-italic.woff2') format('woff2');
+}
+// source-sans-3-500 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: normal;
+ font-weight: 500;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-500.woff2') format('woff2');
+}
+// source-sans-3-500italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: italic;
+ font-weight: 500;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-500italic.woff2') format('woff2');
+}
+
+// source-sans-3-600 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: normal;
+ font-weight: 600;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-600.woff2') format('woff2');
+}
+// source-sans-3-600italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: italic;
+ font-weight: 600;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-600italic.woff2') format('woff2');
+}
+// source-sans-3-700 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: normal;
+ font-weight: 700;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-700.woff2') format('woff2');
+}
+// source-sans-3-700italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: italic;
+ font-weight: 700;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-700italic.woff2') format('woff2');
+}
+// source-sans-3-800 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: normal;
+ font-weight: 800;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-800.woff2') format('woff2');
+}
+// source-sans-3-800italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: italic;
+ font-weight: 800;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-800italic.woff2') format('woff2');
+}
+// source-sans-3-900 - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: normal;
+ font-weight: 900;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-900.woff2') format('woff2');
+}
+// source-sans-3-900italic - latin
+@font-face {
+ font-display: swap;
+ font-family: 'Source Sans 3';
+ font-style: italic;
+ font-weight: 900;
+ src: url('../fonts/source-sans-3-v19-latin/source-sans-3-v19-latin-900italic.woff2') format('woff2');
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_colors.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_colors.scss
new file mode 100644
index 0000000..fcd9a54
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_colors.scss
@@ -0,0 +1,12 @@
+/* Color Theme Swatches in Hex */
+$color-1: #5c4b51;
+$color-2: #8cbeb2;
+$color-3: #f2ebbf;
+$color-4: #f3b562;
+$color-5: #f06060;
+
+$color-red: $color-5;
+$color-white: white; // falls weiß geändert wird z.B.: #f8f8f8
+
+$color-dark-blue: #283e4a;
+$linear-gradient-dark: linear-gradient(180deg, rgba(40, 62, 74, 1) 0%, rgba(24, 32, 38, 1) 100%);
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_index.scss
new file mode 100644
index 0000000..b9585eb
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_index.scss
@@ -0,0 +1,5 @@
+@import 'variables';
+@import 'utils';
+@import 'typography';
+@import 'colors';
+@import 'theme';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_theme.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_theme.scss
new file mode 100644
index 0000000..a892494
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_theme.scss
@@ -0,0 +1,46 @@
+// Allgemeine Formatierungen für die ganze Webanwendung
+
+*,
+html {
+ box-sizing: border-box;
+}
+
+html,
+body,
+#root {
+ height: 100%;
+ padding: 0;
+ margin: 0;
+}
+
+body {
+ font-family: $font-copy;
+}
+
+// Sticky footer
+body,
+#root {
+ display: flex;
+ flex-direction: column;
+}
+
+main,
+#main {
+ flex: 1 0 auto;
+}
+
+body > footer,
+.footer-main {
+ flex-shrink: 0;
+}
+// /Sticky footer
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: $font-headline;
+ font-weight: 700;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_typography.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_typography.scss
new file mode 100644
index 0000000..f633381
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_typography.scss
@@ -0,0 +1,9 @@
+$fallback-serif: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
+$fallback-sans-serif: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+
+$font-headline: 'Playfair Display', $fallback-serif;
+$font-subclaim: $fallback-sans-serif;
+
+$font-menu: $fallback-sans-serif;
+$font-copy: 'Source Sans 3', $fallback-sans-serif;
+$font-quote: $fallback-serif;
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_utils.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_utils.scss
new file mode 100644
index 0000000..e69de29
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_variables.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/03_base/_variables.scss
new file mode 100644
index 0000000..e69de29
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/_index.scss
new file mode 100644
index 0000000..162f2b9
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/_index.scss
@@ -0,0 +1,4 @@
+// @import 'splide-4.1.4/themes/default/index';
+// @import 'splide-4.1.4/core/index';
+
+// @import 'toastify-1.12/toastify';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/foundation/animations.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/foundation/animations.scss
new file mode 100644
index 0000000..f2d7a43
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/foundation/animations.scss
@@ -0,0 +1,9 @@
+@keyframes splide-loading {
+ 0% {
+ transform: rotateZ( 0 );
+ }
+
+ 100% {
+ transform: rotateZ( 360deg );
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/index.scss
new file mode 100644
index 0000000..62a9983
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/index.scss
@@ -0,0 +1,3 @@
+@forward 'foundation/animations';
+@forward 'object/modifiers';
+@forward 'object/objects';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/draggable.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/draggable.scss
new file mode 100644
index 0000000..c1c6dc0
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/draggable.scss
@@ -0,0 +1,8 @@
+.splide {
+ $root: &;
+
+ &__track--draggable {
+ -webkit-touch-callout: none;
+ user-select: none;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/fade.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/fade.scss
new file mode 100644
index 0000000..44241da
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/fade.scss
@@ -0,0 +1,18 @@
+.splide {
+ $root: &;
+
+ &__track--fade {
+ > #{ $root }__list {
+ > #{ $root }__slide {
+ margin: 0 !important;
+ opacity: 0;
+ z-index: 0;
+
+ &.is-active {
+ opacity: 1;
+ z-index: 1;
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/index.scss
new file mode 100644
index 0000000..4681562
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/index.scss
@@ -0,0 +1,4 @@
+@forward 'draggable';
+@forward 'fade';
+@forward 'rtl';
+@forward 'ttb';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/rtl.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/rtl.scss
new file mode 100644
index 0000000..26da654
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/rtl.scss
@@ -0,0 +1,5 @@
+.splide {
+ &--rtl {
+ direction: rtl;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/ttb.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/ttb.scss
new file mode 100644
index 0000000..e612595
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/modifiers/ttb.scss
@@ -0,0 +1,9 @@
+.splide {
+ $root: &;
+
+ &__track--ttb {
+ > #{ $root }__list {
+ display: block;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/container.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/container.scss
new file mode 100644
index 0000000..4f12502
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/container.scss
@@ -0,0 +1,6 @@
+.splide {
+ &__container {
+ box-sizing: border-box;
+ position: relative;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/index.scss
new file mode 100644
index 0000000..488b898
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/index.scss
@@ -0,0 +1,10 @@
+@forward 'container';
+@forward 'list';
+@forward 'pagination';
+@forward 'progress';
+@forward 'root';
+@forward 'slide';
+@forward 'spinner' as spinner-*;
+@forward 'sr';
+@forward 'toggle';
+@forward 'track';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/list.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/list.scss
new file mode 100644
index 0000000..70dc54a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/list.scss
@@ -0,0 +1,17 @@
+.splide {
+ $root: &;
+
+ &__list {
+ backface-visibility: hidden;
+ display: flex;
+ height: 100%;
+ margin: 0 !important;
+ padding: 0 !important;
+ }
+
+ &.is-initialized:not( .is-active ) {
+ #{ $root }__list {
+ display: block;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/pagination.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/pagination.scss
new file mode 100644
index 0000000..701fd57
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/pagination.scss
@@ -0,0 +1,26 @@
+.splide {
+ $root: &;
+
+ &__pagination {
+ align-items: center;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ margin: 0;
+ pointer-events: none;
+
+ li {
+ display: inline-block;
+ line-height: 1;
+ list-style-type: none;
+ margin: 0;
+ pointer-events: auto;
+ }
+ }
+
+ &:not( .is-overflow ) {
+ #{ $root }__pagination {
+ display: none;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/progress.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/progress.scss
new file mode 100644
index 0000000..e765dfc
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/progress.scss
@@ -0,0 +1,7 @@
+.splide {
+ &__progress {
+ &__bar {
+ width: 0;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/root.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/root.scss
new file mode 100644
index 0000000..aa315bc
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/root.scss
@@ -0,0 +1,9 @@
+.splide {
+ position: relative;
+ visibility: hidden;
+
+ &.is-initialized,
+ &.is-rendered {
+ visibility: visible;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/slide.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/slide.scss
new file mode 100644
index 0000000..b87e49b
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/slide.scss
@@ -0,0 +1,14 @@
+.splide {
+ &__slide {
+ backface-visibility: hidden;
+ box-sizing: border-box;
+ flex-shrink: 0;
+ list-style-type: none !important;
+ margin: 0;
+ position: relative;
+
+ img {
+ vertical-align: bottom;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/spinner.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/spinner.scss
new file mode 100644
index 0000000..b60e338
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/spinner.scss
@@ -0,0 +1,21 @@
+$size: 20px !default;
+$border: 2px solid #999 !default;
+
+.splide {
+ &__spinner {
+ animation: splide-loading 1s infinite linear;
+ border: $border;
+ border-left-color: transparent;
+ border-radius: 50%;
+ bottom: 0;
+ contain: strict;
+ display: inline-block;
+ height: $size;
+ left: 0;
+ margin: auto;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: $size;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/sr.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/sr.scss
new file mode 100644
index 0000000..a15d8af
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/sr.scss
@@ -0,0 +1,12 @@
+.splide {
+ &__sr {
+ border: 0;
+ clip: rect( 0 0 0 0 );
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/toggle.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/toggle.scss
new file mode 100644
index 0000000..3f3eb7f
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/toggle.scss
@@ -0,0 +1,22 @@
+.splide {
+ &__toggle {
+ $parent: &;
+
+ &__play {
+ }
+
+ &__pause {
+ display: none;
+ }
+
+ &.is-active {
+ #{ $parent }__play {
+ display: none;
+ }
+
+ #{ $parent }__pause {
+ display: inline;
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/track.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/track.scss
new file mode 100644
index 0000000..ddd2d8c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/core/object/objects/track.scss
@@ -0,0 +1,7 @@
+.splide {
+ &__track {
+ overflow: hidden;
+ position: relative;
+ z-index: 0;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/foundation/colors.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/foundation/colors.scss
new file mode 100644
index 0000000..badbd7b
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/foundation/colors.scss
@@ -0,0 +1,8 @@
+$main: #000 !default;
+$sub01: #333 !default;
+$sub02: #999 !default;
+
+$background: #ccc !default;
+$background-active: #fff !default;
+
+$focus: #0bf !default;
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/foundation/mixins.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/foundation/mixins.scss
new file mode 100644
index 0000000..764bdd8
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/foundation/mixins.scss
@@ -0,0 +1,27 @@
+@use './colors';
+
+$outline: colors.$focus 3px solid !default;
+$outline-offset: 3px !default;
+$outline-offset-inset: -3px !default;
+
+@mixin ie-only {
+ @media screen and (-ms-high-contrast: none) {
+ @content;
+ }
+}
+
+@mixin focus-outline( $offset: $outline-offset ) {
+ outline: $outline;
+ outline-offset: $offset;
+}
+
+@mixin focus-outline-inset {
+ @supports ( outline-offset: $outline-offset-inset ) {
+ @include focus-outline( $outline-offset-inset );
+ }
+
+ /* IE does not support outline-offset */
+ @include ie-only {
+ border: $outline;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/index.scss
new file mode 100644
index 0000000..d7f6daa
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/index.scss
@@ -0,0 +1,13 @@
+@use 'foundation/colors';
+
+$spinner-size: 20px !default;
+$spinner-border: 2px solid colors.$sub02 !default;
+
+@use '../../core/object/objects' with (
+ $spinner-size: $spinner-size,
+ $spinner-border: $spinner-border,
+);
+
+@forward '../../core';
+@forward 'object/objects';
+@forward 'object/modifiers';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/index.scss
new file mode 100644
index 0000000..dd5c959
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/index.scss
@@ -0,0 +1,3 @@
+@forward 'nav' as nav-*;
+@forward 'rtl' as rtl-*;
+@forward 'ttb' as ttb-*;
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/nav.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/nav.scss
new file mode 100644
index 0000000..c2174d2
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/nav.scss
@@ -0,0 +1,37 @@
+@use '../../foundation/colors';
+@use '../../foundation/mixins';
+
+$border: 3px solid transparent !default;
+$border-active: 3px solid colors.$main !default;
+$border-radius: false !default;
+$opacity: false !default;
+$opacity-active: false !default;
+
+.splide {
+ $root: &;
+
+ &__track--nav {
+ > #{ $root }__list {
+ > #{ $root }__slide {
+ border: $border;
+ cursor: pointer;
+
+ @if $opacity {
+ opacity: $opacity;
+ }
+
+ @if $border-radius {
+ border-radius: $border-radius;
+ }
+
+ &.is-active {
+ border: $border-active;
+
+ @if $opacity {
+ opacity: $opacity-active;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/rtl.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/rtl.scss
new file mode 100644
index 0000000..712e250
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/rtl.scss
@@ -0,0 +1,28 @@
+$arrow-right: 1em !default;
+$arrow-left: 1em !default;
+
+.splide {
+ $root: &;
+
+ &__arrows--rtl {
+ #{ $root }__arrow {
+ &--prev {
+ left: auto;
+ right: $arrow-right;
+
+ svg {
+ transform: scaleX( 1 );
+ }
+ }
+
+ &--next {
+ left: $arrow-left;
+ right: auto;
+
+ svg {
+ transform: scaleX( -1 );
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/ttb.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/ttb.scss
new file mode 100644
index 0000000..903e0fa
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/modifiers/ttb.scss
@@ -0,0 +1,54 @@
+$arrow-top: 1em !default;
+$arrow-bottom: 1em !default;
+$pagination-left: auto !default;
+$pagination-right: .5em !default;
+$pagination-dot-width: false !default;
+$pagination-dot-height: false !default;
+
+.splide {
+ $root: &;
+
+ &__arrows--ttb {
+ #{ $root }__arrow {
+ left: 50%;
+ transform: translate( -50%, 0 );
+
+ &--prev {
+ top: $arrow-top;
+
+ svg {
+ transform: rotateZ( -90deg );
+ }
+ }
+
+ &--next {
+ bottom: $arrow-bottom;
+ top: auto;
+
+ svg {
+ transform: rotateZ( 90deg );
+ }
+ }
+ }
+ }
+
+ &__pagination--ttb {
+ bottom: 0;
+ display: flex;
+ flex-direction: column;
+ left: $pagination-left;
+ padding: 1em 0;
+ right: $pagination-right;
+ top: 0;
+
+ #{ $root }__pagination__page {
+ @if $pagination-dot-width {
+ width: $pagination-dot-width;
+ }
+
+ @if $pagination-dot-height {
+ height: $pagination-dot-height;
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/arrow.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/arrow.scss
new file mode 100644
index 0000000..45448f4
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/arrow.scss
@@ -0,0 +1,105 @@
+@use '../../foundation/colors';
+@use '../../foundation/mixins';
+
+$size: 1.2em !default;
+$fill: colors.$main !default;
+$fill-hover: false !default;
+$transition: false !default;
+$button-size: 2em !default;
+$button-background: colors.$background !default;
+$button-background-hover: false !default;
+$button-border: 0 !default;
+$button-padding: 0 !default;
+$button-border-radius: 50% !default;
+$button-transition: false !default;
+$opacity: .7 !default;
+$opacity-hover: .9 !default;
+$opacity-disabled: .3 !default;
+$left: 1em !default;
+$right: 1em !default;
+
+.splide {
+ $root: &;
+
+ &__arrow {
+ background: $button-background;
+ border: $button-border;
+ cursor: pointer;
+ padding: $button-padding;
+ position: absolute;
+ top: 50%;
+ transform: translateY( -50% );
+ z-index: 1;
+
+ @if $opacity {
+ opacity: $opacity;
+ }
+
+ @if $button-size {
+ align-items: center;
+ border-radius: $button-border-radius;
+ display: flex;
+ justify-content: center;
+ height: $button-size;
+ width: $button-size;
+ }
+
+ @if $button-transition {
+ transition: $button-transition;
+ }
+
+ svg {
+ fill: $fill;
+ height: $size;
+ width: $size;
+
+ @if $transition {
+ transition: $transition;
+ }
+ }
+
+ &:hover:not(:disabled) {
+ @if $opacity-hover {
+ opacity: $opacity-hover;
+ }
+
+ @if $button-background-hover {
+ background: $button-background-hover;
+ }
+
+ @if $fill-hover {
+ svg {
+ fill: $fill-hover;
+ }
+ }
+ }
+
+ &:disabled {
+ @if $opacity-disabled {
+ opacity: $opacity-disabled;
+ }
+ }
+
+ &:focus-visible {
+ @include mixins.focus-outline;
+ }
+
+ &--prev {
+ left: $left;
+
+ svg {
+ transform: scaleX( -1 );
+ }
+ }
+
+ &--next {
+ right: $right;
+ }
+ }
+
+ &.is-focus-in {
+ #{ $root }__arrow:focus {
+ @include mixins.focus-outline;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/index.scss
new file mode 100644
index 0000000..5295aab
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/index.scss
@@ -0,0 +1,5 @@
+@forward 'arrow' as arrow-*;
+@forward 'pagination' as pagination-*;
+@forward 'progress' as progress-*;
+@forward 'slide' as slide-*;
+@forward 'toggle' as toggle-*;
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/pagination.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/pagination.scss
new file mode 100644
index 0000000..043169d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/pagination.scss
@@ -0,0 +1,80 @@
+@use '../../foundation/colors';
+@use '../../foundation/mixins';
+
+$bottom: .5em !default;
+$dot-width: 8px !default;
+$dot-height: 8px !default;
+$dot-background: colors.$background !default;
+$dot-background-hover: false !default;
+$dot-background-active: colors.$background-active !default;
+$dot-border: 0 !default;
+$dot-border-radius: 50% !default;
+$dot-margin: 3px !default;
+$dot-padding: 0 !default;
+$dot-opacity: .7 !default;
+$dot-opacity-hover: .9 !default;
+$dot-transition: transform .2s linear !default;
+$dot-transform-active: scale( 1.4 ) !default;
+
+.splide {
+ $root: &;
+
+ &__pagination {
+ bottom: $bottom;
+ left: 0;
+ padding: 0 1em;
+ position: absolute;
+ right: 0;
+ z-index: 1;
+
+ &__page {
+ background: $dot-background;
+ border: $dot-border;
+ border-radius: $dot-border-radius;
+ display: inline-block;
+ height: $dot-height;
+ margin: $dot-margin;
+ padding: $dot-padding;
+ position: relative;
+ transition: $dot-transition;
+ width: $dot-width;
+
+ @if $dot-opacity {
+ opacity: $dot-opacity;
+ }
+
+ &.is-active {
+ background: $dot-background-active;
+ z-index: 1;
+
+ @if $dot-transform-active {
+ transform: $dot-transform-active;
+ }
+ }
+
+ &:hover {
+ cursor: pointer;
+
+ @if $dot-opacity-hover {
+ opacity: $dot-opacity-hover;
+ }
+
+ @if $dot-background-hover {
+ background: $dot-background-hover;
+ }
+ }
+
+ &:focus-visible {
+ @include mixins.focus-outline;
+ }
+ }
+ }
+
+ &.is-focus-in {
+ #{ $root }__pagination {
+ &__page:focus {
+ @include mixins.focus-outline;
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/progress.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/progress.scss
new file mode 100644
index 0000000..a3643e4
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/progress.scss
@@ -0,0 +1,13 @@
+@use '../../foundation/colors';
+
+$height: 3px !default;
+$background: colors.$background;
+
+.splide {
+ &__progress {
+ &__bar {
+ background: $background;
+ height: $height;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/slide.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/slide.scss
new file mode 100644
index 0000000..8a613b1
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/slide.scss
@@ -0,0 +1,42 @@
+@use '../../foundation/colors';
+@use '../../foundation/mixins';
+
+$border-radius: false !default;
+$outline-offset: -2px !default;
+
+.splide {
+ $root: &;
+
+ &__slide {
+ -webkit-tap-highlight-color: transparent;
+
+ @if $border-radius {
+ border-radius: $border-radius;
+ }
+
+ // Gets rid of a focus ring in IE and Safari
+ &:focus {
+ outline: 0;
+ }
+
+ &:focus-visible {
+ @include mixins.focus-outline-inset;
+ }
+ }
+
+ &.is-focus-in {
+ #{ $root }__slide:focus {
+ @include mixins.focus-outline-inset;
+ }
+
+ #{ $root }__track {
+ > #{ $root }__list {
+ > #{ $root }__slide:focus {
+ @include mixins.ie-only {
+ border-color: colors.$focus;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/toggle.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/toggle.scss
new file mode 100644
index 0000000..a99abf6
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/template/default/object/objects/toggle.scss
@@ -0,0 +1,19 @@
+@use '../../foundation/mixins';
+
+.splide {
+ $root: &;
+
+ &__toggle {
+ cursor: pointer;
+
+ &:focus-visible {
+ @include mixins.focus-outline;
+ }
+ }
+
+ &.is-focus-in {
+ #{ $root }__toggle:focus {
+ @include mixins.focus-outline;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/default/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/default/index.scss
new file mode 100644
index 0000000..8414ec5
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/default/index.scss
@@ -0,0 +1 @@
+@forward '../../template/default';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/index.scss
new file mode 100644
index 0000000..a9f2b2d
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/index.scss
@@ -0,0 +1,52 @@
+$main: #20b2aa !default;
+$main-light: lighten( $main, 20% ) !default;
+
+@use '../../template/default/foundation/colors' with (
+ $main: $main,
+ $sub01: $main,
+ $sub02: $main,
+ $background: #ccc,
+ $background-active: $main,
+ $focus: $main,
+);
+
+@use '../../template/default/object/modifiers/nav' with (
+ $border-radius: 4px,
+ $opacity: .7,
+ $opacity-active: 1,
+);
+
+@use '../../template/default/object/modifiers/ttb' with (
+ $pagination-dot-width: 5px,
+ $pagination-dot-height: 20px,
+ $pagination-right: 1em,
+);
+
+@use '../../template/default/object/objects/arrow' with (
+ $size: 2.5em,
+ $opacity: false,
+ $opacity-hover: false,
+ $fill-hover: $main-light,
+ $transition: fill .2s linear,
+ $button-size: 2.5em,
+ $button-border-radius: 0,
+ $button-background: transparent,
+);
+
+@use '../../template/default/object/objects/pagination' with (
+ $bottom: 1em,
+ $dot-width: 20px,
+ $dot-height: 5px,
+ $dot-border-radius: 2.5px,
+ $dot-opacity: false,
+ $dot-transition: background-color .2s linear,
+ $dot-background-hover: $main-light,
+ $dot-transform-active: false,
+);
+
+@use '../../template/default/object/objects/slide' with (
+ $border-radius: 4px,
+);
+
+@forward '../../template/default';
+@forward 'object/objects';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/arrow.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/arrow.scss
new file mode 100644
index 0000000..c96078a
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/arrow.scss
@@ -0,0 +1,17 @@
+.splide {
+ $root: &;
+
+ &__slider {
+ > #{ $root }__arrows {
+ #{ $root }__arrow {
+ &--prev {
+ left: -2.5em;
+ }
+
+ &--next {
+ right: -2.5em;
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/index.scss
new file mode 100644
index 0000000..1055d3c
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/index.scss
@@ -0,0 +1,3 @@
+@forward 'arrow';
+@forward 'root';
+
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/root.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/root.scss
new file mode 100644
index 0000000..c100cd4
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/sea-green/object/objects/root.scss
@@ -0,0 +1,3 @@
+.splide {
+ padding: 3em;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/skyblue/index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/skyblue/index.scss
new file mode 100644
index 0000000..2947989
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/splide-4.1.4/themes/skyblue/index.scss
@@ -0,0 +1,37 @@
+$main: #00bfff !default;
+$main-light: lighten( $main, 20% ) !default;
+
+@use '../../template/default/foundation/colors' with (
+ $main: $main,
+ $sub01: $main,
+ $sub02: $main,
+ $background: #ccc,
+ $background-active: $main,
+ $focus: $main,
+);
+
+@use '../../template/default/object/modifiers/nav' with (
+ $opacity: .7,
+ $opacity-active: 1,
+);
+
+@use '../../template/default/object/objects/arrow' with (
+ $size: 2.5em,
+ $opacity: false,
+ $opacity-hover: false,
+ $fill-hover: $main-light,
+ $transition: fill .2s linear,
+ $button-size: 2.5em,
+ $button-border-radius: 0,
+ $button-background: transparent,
+);
+
+@use '../../template/default/object/objects/pagination' with (
+ $dot-width: 10px,
+ $dot-height: 10px,
+ $dot-opacity: false,
+ $dot-transition: ( background-color .2s linear, transform .2s linear ),
+ $dot-background-hover: $main-light,
+);
+
+@forward '../../template/default';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/toastify-1.12/_toastify.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/toastify-1.12/_toastify.scss
new file mode 100644
index 0000000..e359a14
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/04_plugins/toastify-1.12/_toastify.scss
@@ -0,0 +1,88 @@
+/*!
+ * Toastify js 1.12.0
+ * https://github.com/apvarun/toastify-js
+ * @license MIT licensed
+ *
+ * Copyright (C) 2018 Varun A P
+ */
+
+.toastify {
+ padding: 12px 20px;
+ color: #ffffff;
+ display: inline-block;
+ box-shadow:
+ 0 3px 6px -1px rgba(0, 0, 0, 0.12),
+ 0 10px 36px -4px rgba(77, 96, 232, 0.3);
+ background: -webkit-linear-gradient(315deg, #73a5ff, #5477f5);
+ background: linear-gradient(135deg, #73a5ff, #5477f5);
+ position: fixed;
+ opacity: 0;
+ transition: all 0.4s cubic-bezier(0.215, 0.61, 0.355, 1);
+ border-radius: 2px;
+ cursor: pointer;
+ text-decoration: none;
+ max-width: calc(50% - 20px);
+ z-index: 2147483647;
+}
+
+.toastify.on {
+ opacity: 1;
+}
+
+.toast-close {
+ background: transparent;
+ border: 0;
+ color: white;
+ cursor: pointer;
+ font-family: inherit;
+ font-size: 1em;
+ opacity: 0.4;
+ padding: 0 5px;
+}
+
+.toastify-right {
+ right: 15px;
+}
+
+.toastify-left {
+ left: 15px;
+}
+
+.toastify-top {
+ top: -150px;
+}
+
+.toastify-bottom {
+ bottom: -150px;
+}
+
+.toastify-rounded {
+ border-radius: 25px;
+}
+
+.toastify-avatar {
+ width: 1.5em;
+ height: 1.5em;
+ margin: -7px 5px;
+ border-radius: 2px;
+}
+
+.toastify-center {
+ margin-left: auto;
+ margin-right: auto;
+ left: 0;
+ right: 0;
+ max-width: fit-content;
+ max-width: -moz-fit-content;
+}
+
+@media only screen and (max-width: 360px) {
+ .toastify-right,
+ .toastify-left {
+ margin-left: auto;
+ margin-right: auto;
+ left: 0;
+ right: 0;
+ max-width: fit-content;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_button.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_button.scss
new file mode 100644
index 0000000..f91b983
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_button.scss
@@ -0,0 +1,13 @@
+.btn-custom {
+ &:hover,
+ &:focus {
+ background-color: #e0e0e0;
+ color: #333;
+ border: 1px solid #ccc;
+ }
+ background-color: steelblue;
+ color: white;
+ border: 1px solid #ccc;
+ padding: 8px 16px;
+ border-radius: 0px;
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_footer-main.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_footer-main.scss
new file mode 100644
index 0000000..e171af5
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_footer-main.scss
@@ -0,0 +1,37 @@
+.m-footer-main {
+ background: $color-dark-blue; // Fallback für ältere Browser
+ background: $linear-gradient-dark;
+ padding: 3rem 0;
+ [class^='col'] {
+ color: $color-white;
+ h2,
+ h3,
+ h4,
+ h5 {
+ font-size: 1.5rem;
+ color: $color-5;
+ padding: 0.5rem 0;
+ margin-bottom: 1rem;
+ letter-spacing: 2px;
+ }
+ }
+
+ .row {
+ flex-direction: column;
+ > div {
+ &:nth-child(1) {
+ order: 2;
+ }
+ &:nth-child(2) {
+ order: 1;
+ }
+ }
+ }
+
+ // @media (min-width:576px) {
+ @include media-breakpoint-up(sm) {
+ .row {
+ flex-direction: row;
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_header-main.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_header-main.scss
new file mode 100644
index 0000000..0516fc1
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_header-main.scss
@@ -0,0 +1,83 @@
+.header-main {
+ position: relative;
+
+ width: 100%;
+ min-height: 400px;
+ .content-box {
+ position: relative;
+ z-index: 2;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: auto;
+ margin: 0 auto;
+ height: 100%;
+ max-width: 360px;
+ max-height: 380px;
+ }
+
+ background: $color-3 url('../img/header-image.webp') center no-repeat;
+ background-size: cover;
+
+ &--min {
+ height: 150px;
+ background-color: $color-2;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ .content-box {
+ figure {
+ width: 150px;
+ }
+ }
+ }
+
+ .splide {
+ position: absolute;
+ z-index: 1;
+ height: 100%;
+ width: 100%;
+ top: 0;
+ overflow: hidden;
+ .splide__track {
+ height: 100%;
+ .splider-content {
+ &::after {
+ content: '';
+ position: absolute;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.2);
+ }
+
+ height: 100%;
+ padding: 0;
+ img {
+ object-fit: cover;
+ width: 100%;
+ height: 100%;
+ }
+ }
+ }
+ }
+
+ // .content-box {
+ // figure {
+ // width: 280px;
+ // figcaption {
+ // position: absolute;
+ // clip: rect(1px, 1px, 1px, 1px);
+ // clip-path: inset(0 0 99.9% 99.9%);
+ // overflow: hidden;
+ // height: 1px;
+ // width: 1px;
+
+ // padding: 0;
+ // border: 0;
+ // }
+ // }
+ // }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_index.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_index.scss
new file mode 100644
index 0000000..06efadc
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_index.scss
@@ -0,0 +1,8 @@
+@import 'button';
+@import 'footer-main';
+@import 'header-main';
+@import 'inputAmount';
+@import 'logo-main';
+@import 'nav-menu';
+// @import 'menu-main';
+// @import 'product-manager';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_inputAmount.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_inputAmount.scss
new file mode 100644
index 0000000..928b429
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_inputAmount.scss
@@ -0,0 +1,29 @@
+// Input Amount Component
+.m-input-amount {
+ .input-group {
+ .input-group-text {
+ padding: 0;
+ display: inline-block;
+ overflow: hidden;
+ button {
+ border-radius: 0;
+ }
+ }
+ }
+ .input-amount {
+ max-width: 80px;
+ text-align: center;
+ }
+
+ /* Chrome, Safari, Edge, Opera */
+ input::-webkit-outer-spin-button,
+ input::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+ }
+
+ /* Firefox */
+ input[type='number'] {
+ appearance: textfield;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_logo-main.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_logo-main.scss
new file mode 100644
index 0000000..9d5cce9
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_logo-main.scss
@@ -0,0 +1,14 @@
+figure.logo-main {
+ width: 280px;
+ figcaption {
+ position: absolute;
+ clip: rect(1px, 1px, 1px, 1px);
+ clip-path: inset(0 0 99.9% 99.9%);
+ overflow: hidden;
+ height: 1px;
+ width: 1px;
+
+ padding: 0;
+ border: 0;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_menu-main.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_menu-main.scss
new file mode 100644
index 0000000..cc91cc5
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_menu-main.scss
@@ -0,0 +1,60 @@
+.menu-main {
+ background-color: $color-5;
+
+ ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ }
+
+ ul ul {
+ display: none; // TODO: change to not visible
+ }
+ ul > li:hover,
+ ul > li:focus,
+ ul > li:focus-within {
+ ul {
+ display: block;
+ }
+ }
+
+ ul.list {
+ display: flex;
+
+ justify-content: center;
+ li {
+ a {
+ display: inline-block;
+ text-decoration: none;
+ text-transform: uppercase;
+ color: $color-white;
+ padding: 0.5rem 1rem;
+ transition: all 0.4s ease-out;
+ &:hover,
+ &:focus {
+ background-color: $color-white;
+ color: $color-5;
+ }
+ }
+ }
+ }
+
+ ul.sublist {
+ position: absolute;
+ background-color: rgba($color-5, 0.8);
+ li {
+ a {
+ display: inline-block;
+ background-color: $color-5;
+ color: $color-white;
+ padding: 0.5rem 1rem;
+ transition: all 0.4s ease-out;
+ &:hover,
+ &:focus {
+ background-color: $color-white;
+ color: $color-5;
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_nav-menu.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_nav-menu.scss
new file mode 100644
index 0000000..d4e2ba1
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_nav-menu.scss
@@ -0,0 +1,6 @@
+.m-nav-menu {
+ .navbar-nav .nav-link.active,
+ .navbar-nav .nav-link.show {
+ color: $color-5;
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_product-manager.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_product-manager.scss
new file mode 100644
index 0000000..906cc1b
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/05_modules/_product-manager.scss
@@ -0,0 +1,37 @@
+.product-manager {
+ .nav-products-actions {
+ margin: 1rem 0;
+ display: flex;
+ justify-content: flex-end;
+ .list {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ gap: 1rem;
+ }
+ }
+
+ table {
+ .th-actions {
+ width: 200px;
+ }
+ tbody {
+ td {
+ vertical-align: middle;
+ button {
+ margin: 3px;
+ }
+ }
+ }
+
+ tfoot {
+ .row > * {
+ margin-bottom: 1rem;
+ @media (min-width: 992px) {
+ margin-bottom: 0;
+ }
+ }
+ }
+ }
+}
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/styles/main.scss b/05_react/unterricht/tag43/01_react-with-forms/src/styles/main.scss
new file mode 100644
index 0000000..aa8f3f6
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/styles/main.scss
@@ -0,0 +1,16 @@
+// sass dev/assets/scss/main.scss:assets/css/main.css
+
+// 01 FRAMEWORKS
+@import '01_frameworks/index';
+
+// 02 FONTS
+@import '02_fonts/index';
+
+// 03 BASE
+@import '03_base/index';
+
+// 04 PLUGINS
+@import '04_plugins/index';
+
+// 05 MODULES
+@import '05_modules/index';
diff --git a/05_react/unterricht/tag43/01_react-with-forms/src/utils/validators/validate.js b/05_react/unterricht/tag43/01_react-with-forms/src/utils/validators/validate.js
new file mode 100644
index 0000000..97b4829
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/src/utils/validators/validate.js
@@ -0,0 +1,29 @@
+const validate = (formData) => {
+ const errors = {};
+
+ const emailRegEx = new RegExp(
+ /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
+ );
+
+ if (!formData.firstname) {
+ errors.firstname = 'Firstname is required';
+ }
+
+ if (!formData.lastname) {
+ errors.lastname = 'Lastname is required';
+ }
+
+ if (!formData.email) {
+ errors.email = 'Email is required';
+ } else if (!emailRegEx.test(formData.email)) {
+ errors.email = 'Email is invalid';
+ }
+
+ if (!formData.message) {
+ errors.message = 'Message is required';
+ }
+
+ return errors;
+};
+
+export default validate;
diff --git a/05_react/unterricht/tag43/01_react-with-forms/vite.config.js b/05_react/unterricht/tag43/01_react-with-forms/vite.config.js
new file mode 100644
index 0000000..a69e4aa
--- /dev/null
+++ b/05_react/unterricht/tag43/01_react-with-forms/vite.config.js
@@ -0,0 +1,15 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ css: {
+ preprocessorOptions: {
+ scss: {
+ quietDeps: true, // Unix
+ silenceDeprecations: ['color-functions', 'global-builtin', 'import', 'legacy-js-api', 'if-function'],
+ },
+ },
+ },
+});