Initial commit: Lagerbestand Blazor Projekt
This commit is contained in:
commit
cba9414e92
105 files changed
+36431
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,7 @@
|
||||
@charset "UTF-8";/*!
|
||||
* Bootstrap v5.1.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-rgb:33,37,41;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){leLine truncated
|
||||
/*# sourceMappingURL=bootstrap.min.css.map */
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_root.scss","../../scss/_reboot.scss","dist/css/bootstrap.css","../../scss/vendor/_rfs.scss","../../scss/mixins/_border-radius.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/_containers.scss","../../scss/mixins/_container.scss","../../scss/mixins/_breakpoints.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/_tables.scss","../../scss/mixins/_table-variants.scss","../../scss/forms/_labels.scss","../../scss/forms/_form-text.scss","../../scss/forms/_form-control.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_gradients.scss","../../scss/forms/_form-select.scss","../../scss/forms/_form-check.scss","../../scss/forms/_form-range.scss","../../scss/forms/_floating-labels.scss","../../scss/forms/_input-group.scss","../../scss/mixins/_forms.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/_button-group.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_accordion.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_toasts.scss","../../scss/_modal.scss","../../scss/mixins/_backdrop.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/mixins/_clearfix.scss","../../scss/_spinners.scss","../../scss/_offcanvas.scss","../../scss/_placeholders.scss","../../scss/helpers/_colored-links.scss","../../scss/helpers/_ratio.scss","../../scss/helpers/_position.scss","../../scss/helpers/_stacks.scss","../../scss/helpers/_visually-hidden.scss","../../scss/mixins/_visually-hidden.scss","../../scss/helpers/_stretched-link.scss","../../scss/helpers/_text-truncation.scss","../../scss/mixins/_text-truncate.scss","../../scss/helpers/_vr.scss","../../scss/mixins/_utilities.scss","../../scss/utilities/_api.scss"],"names":[],"mappings":"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 truncated
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Reifen Späth – App Interop styles
|
||||
* Reconnect overlay + idle-lock overlay.
|
||||
* Uses global design tokens from app.css.
|
||||
*/
|
||||
|
||||
/* =============================================
|
||||
Blazor reconnect overlay (replaces default)
|
||||
The framework toggles styles on:
|
||||
#components-reconnect-modal
|
||||
via classes: components-reconnect-show / hide / failed / rejected
|
||||
============================================= */
|
||||
#components-reconnect-modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 2147483000;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: var(--space-4, 1rem);
|
||||
background: rgba(0, 0, 0, 0.78);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
font-family: var(--font-family-base, sans-serif);
|
||||
color: var(--text-primary, #fff);
|
||||
}
|
||||
|
||||
#components-reconnect-modal.components-reconnect-show,
|
||||
#components-reconnect-modal.components-reconnect-failed,
|
||||
#components-reconnect-modal.components-reconnect-rejected {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#components-reconnect-modal .reconnect-dialog {
|
||||
background: var(--surface-primary, rgba(28, 28, 30, 0.95));
|
||||
border: 0.5px solid var(--border-default, rgba(255, 255, 255, 0.1));
|
||||
border-radius: var(--radius-xl, 20px);
|
||||
box-shadow: var(--shadow-xl, 0 20px 40px rgba(0, 0, 0, 0.5));
|
||||
padding: var(--space-6, 1.5rem);
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#components-reconnect-modal .reconnect-icon {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin: 0 auto var(--space-4, 1rem);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: rgba(220, 38, 38, 0.15);
|
||||
color: var(--color-primary-light, #ef4444);
|
||||
}
|
||||
|
||||
#components-reconnect-modal .reconnect-icon svg {
|
||||
animation: reconnect-spin 1.4s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes reconnect-spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
#components-reconnect-modal h2 {
|
||||
margin: 0 0 var(--space-2, 0.5rem);
|
||||
font-size: var(--text-xl, 1.25rem);
|
||||
font-family: var(--font-family-base, sans-serif);
|
||||
font-weight: var(--font-weight-semibold, 600);
|
||||
}
|
||||
|
||||
#components-reconnect-modal p {
|
||||
margin: 0 0 var(--space-5, 1.25rem);
|
||||
color: var(--text-secondary, rgba(255, 255, 255, 0.7));
|
||||
font-size: var(--text-sm, 0.875rem);
|
||||
line-height: var(--line-height-relaxed, 1.6);
|
||||
}
|
||||
|
||||
#components-reconnect-modal .reconnect-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-3, 0.75rem);
|
||||
}
|
||||
|
||||
#components-reconnect-modal .reconnect-text-show,
|
||||
#components-reconnect-modal .reconnect-text-failed,
|
||||
#components-reconnect-modal .reconnect-text-rejected,
|
||||
#components-reconnect-modal .reconnect-actions-failed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#components-reconnect-modal.components-reconnect-show .reconnect-text-show { display: block; }
|
||||
#components-reconnect-modal.components-reconnect-failed .reconnect-text-failed,
|
||||
#components-reconnect-modal.components-reconnect-failed .reconnect-actions-failed { display: block; }
|
||||
#components-reconnect-modal.components-reconnect-failed .reconnect-actions-failed { display: flex; flex-direction: column; gap: var(--space-3, 0.75rem); }
|
||||
#components-reconnect-modal.components-reconnect-rejected .reconnect-text-rejected,
|
||||
#components-reconnect-modal.components-reconnect-rejected .reconnect-actions-failed { display: block; }
|
||||
#components-reconnect-modal.components-reconnect-rejected .reconnect-actions-failed { display: flex; flex-direction: column; gap: var(--space-3, 0.75rem); }
|
||||
|
||||
/* Hide default retry countdown */
|
||||
#components-reconnect-modal .components-reconnect-current-attempt,
|
||||
#components-reconnect-modal .components-reconnect-max-retries {
|
||||
color: var(--text-tertiary, rgba(255, 255, 255, 0.5));
|
||||
font-size: var(--text-xs, 0.75rem);
|
||||
}
|
||||
|
||||
#components-reconnect-modal button {
|
||||
min-height: var(--touch-target, 44px);
|
||||
padding: var(--space-3, 0.75rem) var(--space-5, 1.25rem);
|
||||
border-radius: var(--radius-md, 10px);
|
||||
border: none;
|
||||
font-family: var(--font-family-base, sans-serif);
|
||||
font-size: var(--text-sm, 0.875rem);
|
||||
font-weight: var(--font-weight-semibold, 600);
|
||||
cursor: pointer;
|
||||
transition: all var(--duration-fast, 150ms) var(--ease-out, ease);
|
||||
}
|
||||
|
||||
#components-reconnect-modal .reconnect-retry {
|
||||
background: linear-gradient(180deg, var(--color-primary-light, #ef4444) 0%, var(--color-primary, #dc2626) 100%);
|
||||
color: var(--text-primary, #fff);
|
||||
box-shadow: var(--shadow-btn-primary, 0 4px 12px rgba(220, 38, 38, 0.3));
|
||||
}
|
||||
|
||||
#components-reconnect-modal .reconnect-reload {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: var(--text-primary, #fff);
|
||||
border: 0.5px solid var(--border-default, rgba(255, 255, 255, 0.1));
|
||||
}
|
||||
|
||||
#components-reconnect-modal button:hover:not(:disabled) {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* =============================================
|
||||
Idle lock overlay
|
||||
============================================= */
|
||||
#app-idle-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 2147482000;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: var(--space-4, 1rem);
|
||||
background: rgba(0, 0, 0, 0.82);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
font-family: var(--font-family-base, sans-serif);
|
||||
color: var(--text-primary, #fff);
|
||||
animation: fadeIn var(--duration-normal, 250ms) var(--ease-out, ease);
|
||||
}
|
||||
|
||||
#app-idle-overlay.visible {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#app-idle-overlay .app-idle-dialog {
|
||||
background: var(--surface-primary, rgba(28, 28, 30, 0.95));
|
||||
border: 0.5px solid var(--border-default, rgba(255, 255, 255, 0.1));
|
||||
border-radius: var(--radius-xl, 20px);
|
||||
box-shadow: var(--shadow-xl, 0 20px 40px rgba(0, 0, 0, 0.5));
|
||||
padding: var(--space-6, 1.5rem);
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#app-idle-overlay .app-idle-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 0 auto var(--space-4, 1rem);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: rgba(251, 191, 36, 0.15);
|
||||
color: var(--color-warning, #fbbf24);
|
||||
}
|
||||
|
||||
#app-idle-overlay h2 {
|
||||
margin: 0 0 var(--space-2, 0.5rem);
|
||||
font-size: var(--text-xl, 1.25rem);
|
||||
font-weight: var(--font-weight-semibold, 600);
|
||||
}
|
||||
|
||||
#app-idle-overlay p {
|
||||
margin: 0 0 var(--space-5, 1.25rem);
|
||||
color: var(--text-secondary, rgba(255, 255, 255, 0.7));
|
||||
font-size: var(--text-sm, 0.875rem);
|
||||
line-height: var(--line-height-relaxed, 1.6);
|
||||
}
|
||||
|
||||
#app-idle-overlay .app-idle-resume {
|
||||
min-height: var(--touch-target, 44px);
|
||||
width: 100%;
|
||||
padding: var(--space-3, 0.75rem) var(--space-5, 1.25rem);
|
||||
border-radius: var(--radius-md, 10px);
|
||||
border: none;
|
||||
background: linear-gradient(180deg, var(--color-primary-light, #ef4444) 0%, var(--color-primary, #dc2626) 100%);
|
||||
color: var(--text-primary, #fff);
|
||||
font-family: var(--font-family-base, sans-serif);
|
||||
font-size: var(--text-base, 1rem);
|
||||
font-weight: var(--font-weight-semibold, 600);
|
||||
cursor: pointer;
|
||||
box-shadow: var(--shadow-btn-primary, 0 4px 12px rgba(220, 38, 38, 0.3));
|
||||
transition: transform var(--duration-fast, 150ms) var(--ease-out, ease);
|
||||
}
|
||||
|
||||
#app-idle-overlay .app-idle-resume:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
#app-idle-overlay .app-idle-resume:focus-visible {
|
||||
outline: 3px solid rgba(220, 38, 38, 0.5);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
@charset "UTF-8";/*!
|
||||
* Bootstrap v5.1.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-rgb:33,37,41;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){leLine truncated
|
||||
/*# sourceMappingURL=bootstrap.min.css.map */
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_root.scss","../../scss/_reboot.scss","dist/css/bootstrap.css","../../scss/vendor/_rfs.scss","../../scss/mixins/_border-radius.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/_containers.scss","../../scss/mixins/_container.scss","../../scss/mixins/_breakpoints.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/_tables.scss","../../scss/mixins/_table-variants.scss","../../scss/forms/_labels.scss","../../scss/forms/_form-text.scss","../../scss/forms/_form-control.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_gradients.scss","../../scss/forms/_form-select.scss","../../scss/forms/_form-check.scss","../../scss/forms/_form-range.scss","../../scss/forms/_floating-labels.scss","../../scss/forms/_input-group.scss","../../scss/mixins/_forms.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/_button-group.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_accordion.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_toasts.scss","../../scss/_modal.scss","../../scss/mixins/_backdrop.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/mixins/_clearfix.scss","../../scss/_spinners.scss","../../scss/_offcanvas.scss","../../scss/_placeholders.scss","../../scss/helpers/_colored-links.scss","../../scss/helpers/_ratio.scss","../../scss/helpers/_position.scss","../../scss/helpers/_stacks.scss","../../scss/helpers/_visually-hidden.scss","../../scss/mixins/_visually-hidden.scss","../../scss/helpers/_stretched-link.scss","../../scss/helpers/_text-truncation.scss","../../scss/mixins/_text-truncate.scss","../../scss/helpers/_vr.scss","../../scss/mixins/_utilities.scss","../../scss/utilities/_api.scss"],"names":[],"mappings":"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 truncated
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
@@ -0,0 +1 @@
|
||||
google-site-verification: google6d5a1b5c60a38816.html
|
||||
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Reifen Späth – App Interop
|
||||
* =============================================================
|
||||
* Browser-side helpers for long-duration usage:
|
||||
* - Visibility refresh (tab re-activated after N minutes)
|
||||
* - Idle-lock overlay (confirm-to-continue after N minutes)
|
||||
* - beforeunload warning when a form has unsaved draft data
|
||||
* - sessionStorage draft helpers (per-tab)
|
||||
* - focus-trap + Escape + click-outside helpers for modals/menus
|
||||
* - Custom Blazor reconnect UI wiring (handled via CSS selectors
|
||||
* on #components-reconnect-modal in App.razor)
|
||||
* =============================================================
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// sessionStorage drafts (per-browser, per-tab)
|
||||
// ---------------------------------------------------------
|
||||
const DRAFT_PREFIX = 'rs-draft:';
|
||||
|
||||
window.appInterop = window.appInterop || {};
|
||||
|
||||
window.appInterop.saveDraft = function (key, json) {
|
||||
try {
|
||||
if (json == null) {
|
||||
sessionStorage.removeItem(DRAFT_PREFIX + key);
|
||||
return true;
|
||||
}
|
||||
sessionStorage.setItem(DRAFT_PREFIX + key, json);
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.warn('[appInterop] saveDraft failed', e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
window.appInterop.loadDraft = function (key) {
|
||||
try {
|
||||
return sessionStorage.getItem(DRAFT_PREFIX + key);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
window.appInterop.clearDraft = function (key) {
|
||||
try {
|
||||
sessionStorage.removeItem(DRAFT_PREFIX + key);
|
||||
} catch (e) { /* ignore */ }
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// beforeunload: warn user when draft flag is set
|
||||
// ---------------------------------------------------------
|
||||
let hasUnsavedChanges = false;
|
||||
|
||||
window.appInterop.setUnsaved = function (value) {
|
||||
hasUnsavedChanges = !!value;
|
||||
};
|
||||
|
||||
window.addEventListener('beforeunload', function (e) {
|
||||
if (hasUnsavedChanges) {
|
||||
e.preventDefault();
|
||||
// Most browsers ignore the custom message and show a generic one.
|
||||
e.returnValue = '';
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Visibility refresh: fire .NET callback when tab returns
|
||||
// after being hidden for more than `thresholdSeconds`.
|
||||
//
|
||||
// One .NET target per page; replacing cancels the previous.
|
||||
// ---------------------------------------------------------
|
||||
let visibilityHiddenAt = null;
|
||||
let visibilityTarget = null; // DotNetObjectReference
|
||||
let visibilityMethod = null;
|
||||
let visibilityThresholdSec = 120;
|
||||
|
||||
function onVisibilityChange() {
|
||||
if (document.visibilityState === 'hidden') {
|
||||
visibilityHiddenAt = Date.now();
|
||||
} else if (document.visibilityState === 'visible') {
|
||||
if (!visibilityTarget || !visibilityHiddenAt) return;
|
||||
const hiddenFor = (Date.now() - visibilityHiddenAt) / 1000;
|
||||
visibilityHiddenAt = null;
|
||||
if (hiddenFor >= visibilityThresholdSec) {
|
||||
try {
|
||||
visibilityTarget.invokeMethodAsync(visibilityMethod, Math.round(hiddenFor));
|
||||
} catch (e) {
|
||||
console.warn('[appInterop] visibility invoke failed', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('visibilitychange', onVisibilityChange);
|
||||
|
||||
window.appInterop.registerVisibilityRefresh = function (dotNetRef, methodName, thresholdSeconds) {
|
||||
visibilityTarget = dotNetRef;
|
||||
visibilityMethod = methodName || 'OnVisibilityReturn';
|
||||
visibilityThresholdSec = thresholdSeconds > 0 ? thresholdSeconds : 120;
|
||||
visibilityHiddenAt = null;
|
||||
};
|
||||
|
||||
window.appInterop.unregisterVisibilityRefresh = function () {
|
||||
visibilityTarget = null;
|
||||
visibilityMethod = null;
|
||||
visibilityHiddenAt = null;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Idle lock overlay (per-tab).
|
||||
// Fires after N minutes of no user input; requires a click
|
||||
// on the "Weiter" button to resume (no password — matches
|
||||
// confirmed UX decision).
|
||||
// ---------------------------------------------------------
|
||||
const IDLE_EVENTS = ['mousemove', 'mousedown', 'keydown', 'touchstart', 'scroll', 'wheel'];
|
||||
let idleTimerId = null;
|
||||
let idleTimeoutMs = 60 * 60 * 1000; // 60 min default
|
||||
let idleActive = false;
|
||||
let idleLocked = false;
|
||||
|
||||
function resetIdleTimer() {
|
||||
if (!idleActive || idleLocked) return;
|
||||
if (idleTimerId) clearTimeout(idleTimerId);
|
||||
idleTimerId = setTimeout(triggerIdleLock, idleTimeoutMs);
|
||||
}
|
||||
|
||||
function triggerIdleLock() {
|
||||
idleLocked = true;
|
||||
const overlay = document.getElementById('app-idle-overlay');
|
||||
if (overlay) {
|
||||
overlay.classList.add('visible');
|
||||
const btn = overlay.querySelector('.app-idle-resume');
|
||||
if (btn) {
|
||||
setTimeout(function () { try { btn.focus(); } catch (e) { } }, 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function releaseIdleLock() {
|
||||
idleLocked = false;
|
||||
const overlay = document.getElementById('app-idle-overlay');
|
||||
if (overlay) overlay.classList.remove('visible');
|
||||
resetIdleTimer();
|
||||
}
|
||||
|
||||
window.appInterop.startIdleWatcher = function (idleMinutes) {
|
||||
const minutes = parseInt(idleMinutes, 10);
|
||||
if (!minutes || minutes <= 0) {
|
||||
window.appInterop.stopIdleWatcher();
|
||||
return;
|
||||
}
|
||||
idleTimeoutMs = minutes * 60 * 1000;
|
||||
if (!idleActive) {
|
||||
idleActive = true;
|
||||
IDLE_EVENTS.forEach(function (ev) {
|
||||
window.addEventListener(ev, resetIdleTimer, { passive: true });
|
||||
});
|
||||
const btn = document.querySelector('#app-idle-overlay .app-idle-resume');
|
||||
if (btn && !btn.dataset.bound) {
|
||||
btn.dataset.bound = '1';
|
||||
btn.addEventListener('click', releaseIdleLock);
|
||||
}
|
||||
}
|
||||
resetIdleTimer();
|
||||
};
|
||||
|
||||
window.appInterop.stopIdleWatcher = function () {
|
||||
if (!idleActive) return;
|
||||
idleActive = false;
|
||||
if (idleTimerId) clearTimeout(idleTimerId);
|
||||
idleTimerId = null;
|
||||
IDLE_EVENTS.forEach(function (ev) {
|
||||
window.removeEventListener(ev, resetIdleTimer);
|
||||
});
|
||||
releaseIdleLock();
|
||||
};
|
||||
|
||||
// Auto-load session settings and start watcher once DOM is ready.
|
||||
// Only activates if the body has [data-authenticated="true"], which
|
||||
// MainLayout sets when a user is logged in.
|
||||
function tryAutoStartIdle() {
|
||||
if (document.body && document.body.dataset.authenticated === 'true') {
|
||||
fetch('/api/session-settings', { credentials: 'same-origin' })
|
||||
.then(function (r) { return r.ok ? r.json() : null; })
|
||||
.then(function (s) {
|
||||
if (s && s.idleTimeoutMinutes > 0) {
|
||||
window.appInterop.startIdleWatcher(s.idleTimeoutMinutes);
|
||||
}
|
||||
})
|
||||
.catch(function () { /* non-fatal */ });
|
||||
}
|
||||
}
|
||||
|
||||
// Observe auth marker on <body> so the watcher (re)starts after login/logout.
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
tryAutoStartIdle();
|
||||
if (document.body) {
|
||||
const mo = new MutationObserver(function () { tryAutoStartIdle(); });
|
||||
mo.observe(document.body, { attributes: true, attributeFilter: ['data-authenticated'] });
|
||||
}
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Click-outside for user-menu dropdown and mobile-menu.
|
||||
// The Blazor component sets [data-click-outside-id="..."] on
|
||||
// the open panel and exposes a .NET method we call back.
|
||||
// ---------------------------------------------------------
|
||||
let clickOutsideTarget = null;
|
||||
let clickOutsideMethod = null;
|
||||
let clickOutsideContainerSelector = null;
|
||||
|
||||
function onDocumentClick(e) {
|
||||
if (!clickOutsideTarget || !clickOutsideContainerSelector) return;
|
||||
const container = document.querySelector(clickOutsideContainerSelector);
|
||||
if (!container) return;
|
||||
if (!container.contains(e.target)) {
|
||||
try {
|
||||
clickOutsideTarget.invokeMethodAsync(clickOutsideMethod);
|
||||
} catch (err) { /* circuit may be reconnecting */ }
|
||||
}
|
||||
}
|
||||
|
||||
window.appInterop.registerClickOutside = function (dotNetRef, methodName, containerSelector) {
|
||||
clickOutsideTarget = dotNetRef;
|
||||
clickOutsideMethod = methodName;
|
||||
clickOutsideContainerSelector = containerSelector;
|
||||
// Use capture phase so stopPropagation inside the panel still works for us.
|
||||
document.addEventListener('mousedown', onDocumentClick, true);
|
||||
document.addEventListener('touchstart', onDocumentClick, { capture: true, passive: true });
|
||||
};
|
||||
|
||||
window.appInterop.unregisterClickOutside = function () {
|
||||
clickOutsideTarget = null;
|
||||
clickOutsideMethod = null;
|
||||
clickOutsideContainerSelector = null;
|
||||
document.removeEventListener('mousedown', onDocumentClick, true);
|
||||
document.removeEventListener('touchstart', onDocumentClick, { capture: true });
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Focus trap for modals (autofocus + Tab cycle + Escape).
|
||||
// Caller passes the container selector; we remember the
|
||||
// previously-focused element and restore it on release.
|
||||
// ---------------------------------------------------------
|
||||
const FOCUSABLE = [
|
||||
'a[href]', 'area[href]', 'input:not([disabled])', 'select:not([disabled])',
|
||||
'textarea:not([disabled])', 'button:not([disabled])', 'iframe',
|
||||
'object', 'embed', '[contenteditable]', '[tabindex]:not([tabindex="-1"])'
|
||||
].join(',');
|
||||
|
||||
let trapState = null;
|
||||
|
||||
function onTrapKey(e) {
|
||||
if (!trapState) return;
|
||||
if (e.key === 'Escape' && trapState.escapeMethod) {
|
||||
try { trapState.dotNetRef.invokeMethodAsync(trapState.escapeMethod); } catch (err) { }
|
||||
return;
|
||||
}
|
||||
if (e.key !== 'Tab') return;
|
||||
const container = document.querySelector(trapState.selector);
|
||||
if (!container) return;
|
||||
const focusables = Array.prototype.filter.call(
|
||||
container.querySelectorAll(FOCUSABLE),
|
||||
function (el) { return el.offsetParent !== null; });
|
||||
if (focusables.length === 0) return;
|
||||
const first = focusables[0];
|
||||
const last = focusables[focusables.length - 1];
|
||||
if (e.shiftKey && document.activeElement === first) {
|
||||
e.preventDefault();
|
||||
last.focus();
|
||||
} else if (!e.shiftKey && document.activeElement === last) {
|
||||
e.preventDefault();
|
||||
first.focus();
|
||||
}
|
||||
}
|
||||
|
||||
window.appInterop.trapFocus = function (selector, dotNetRef, escapeMethod) {
|
||||
if (trapState) { try { document.removeEventListener('keydown', onTrapKey, true); } catch (e) { } }
|
||||
trapState = {
|
||||
selector: selector,
|
||||
dotNetRef: dotNetRef || null,
|
||||
escapeMethod: escapeMethod || null,
|
||||
previouslyFocused: document.activeElement
|
||||
};
|
||||
document.addEventListener('keydown', onTrapKey, true);
|
||||
// Autofocus the first tabbable element.
|
||||
setTimeout(function () {
|
||||
const container = document.querySelector(selector);
|
||||
if (!container) return;
|
||||
const focusables = Array.prototype.filter.call(
|
||||
container.querySelectorAll(FOCUSABLE),
|
||||
function (el) { return el.offsetParent !== null; });
|
||||
if (focusables.length > 0) {
|
||||
try { focusables[0].focus(); } catch (e) { }
|
||||
}
|
||||
}, 30);
|
||||
};
|
||||
|
||||
window.appInterop.releaseFocusTrap = function () {
|
||||
document.removeEventListener('keydown', onTrapKey, true);
|
||||
if (trapState && trapState.previouslyFocused && typeof trapState.previouslyFocused.focus === 'function') {
|
||||
try { trapState.previouslyFocused.focus(); } catch (e) { }
|
||||
}
|
||||
trapState = null;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Blazor reconnect UI — replace the default overlay.
|
||||
// App.razor provides #components-reconnect-modal with German
|
||||
// copy; Blazor sets body[data-reconnect-state] automatically
|
||||
// via the official contract (components-reconnect-show etc.).
|
||||
// We just add a manual reload button handler.
|
||||
// ---------------------------------------------------------
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const reload = document.querySelector('#components-reconnect-modal .reconnect-reload');
|
||||
if (reload) {
|
||||
reload.addEventListener('click', function () { location.reload(); });
|
||||
}
|
||||
const retry = document.querySelector('#components-reconnect-modal .reconnect-retry');
|
||||
if (retry) {
|
||||
retry.addEventListener('click', function () {
|
||||
if (window.Blazor && typeof window.Blazor.reconnect === 'function') {
|
||||
window.Blazor.reconnect();
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,25 @@
|
||||
# Robots.txt for Reifen Späth - www.reifenspaeth.de
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
|
||||
User-agent: *
|
||||
|
||||
# Allow public pages
|
||||
Allow: /
|
||||
Allow: /impressum
|
||||
Allow: /datenschutz
|
||||
|
||||
# Disallow internal/admin pages
|
||||
Disallow: /login
|
||||
Disallow: /tire-storage
|
||||
Disallow: /tire-checkin
|
||||
Disallow: /tire-checkout
|
||||
Disallow: /customers
|
||||
Disallow: /storage-locations
|
||||
Disallow: /users
|
||||
Disallow: /status
|
||||
|
||||
# Allow required rendering assets so search engines can render the page correctly
|
||||
Allow: /_framework/
|
||||
Allow: /_content/
|
||||
|
||||
Sitemap: https://www.reifenspaeth.de/sitemap.xml
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
|
||||
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
||||
|
||||
<!-- Homepage - highest priority -->
|
||||
<url>
|
||||
<loc>https://www.reifenspaeth.de/</loc>
|
||||
<lastmod>2026-05-11</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
|
||||
<!-- Impressum - legal page -->
|
||||
<url>
|
||||
<loc>https://www.reifenspaeth.de/impressum</loc>
|
||||
<lastmod>2026-05-11</lastmod>
|
||||
<changefreq>yearly</changefreq>
|
||||
<priority>0.3</priority>
|
||||
</url>
|
||||
|
||||
<!-- Datenschutz - legal page -->
|
||||
<url>
|
||||
<loc>https://www.reifenspaeth.de/datenschutz</loc>
|
||||
<lastmod>2026-05-11</lastmod>
|
||||
<changefreq>yearly</changefreq>
|
||||
<priority>0.3</priority>
|
||||
</url>
|
||||
|
||||
</urlset>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
Reference in new issue
Block a user