Die Kontostands-Karte zeigte die Saeule 3a wie jedes andere Konto: ein Name, ein Betrag. Dass man an das Geld nicht herankommt, stand nur in der Summe darunter – und wer den Betrag liest, rechnet ihn im Kopf doch mit. Die Zeile traegt jetzt dieselbe Marke wie auf der Kontenseite. Dabei ist ein Fehler aufgefallen, den ich selbst eingebaut hatte: Die Zeile "zusaetzlich gebunden" stand im Markup HINTER der Summe. Die klebt per position:sticky am unteren Rand des Rollbereichs – alles dahinter liegt darunter und ist praktisch nie zu sehen. Summe und gebundener Betrag stehen jetzt gemeinsam im angehefteten Fuss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2039 lines
48 KiB
CSS
2039 lines
48 KiB
CSS
/* Eigene Stil-Ergänzungen für Certain Finance – bewusst getrennt von der aus
|
||
der Vorlage übernommenen styles.css, damit Basis und Ergänzung sauber bleiben. */
|
||
|
||
.brand-mark {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
}
|
||
.brand-logo {
|
||
display: block;
|
||
flex: 0 0 auto;
|
||
}
|
||
.brand-name {
|
||
font-weight: 650;
|
||
font-size: 1rem;
|
||
letter-spacing: -0.01em;
|
||
color: var(--text);
|
||
}
|
||
|
||
/* Beträge: Vorzeichenfarbe. Grün = Einnahme/im Budget, Rot = Ausgabe/über Budget. */
|
||
.amount.pos { color: var(--ok); }
|
||
.amount.neg { color: var(--danger); }
|
||
.amount.muted { color: var(--muted); }
|
||
|
||
/* Umgerechneter Zweitbetrag (Originalwährung -> Hauptwährung) klein und gedämpft. */
|
||
.amount-converted {
|
||
color: var(--muted);
|
||
font-size: 0.82em;
|
||
margin-left: 4px;
|
||
}
|
||
|
||
/* Schlichtes zentriertes Layout für Login / Passwort ändern. */
|
||
.auth-screen {
|
||
min-height: 100vh;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: var(--sp-5);
|
||
background: var(--bg);
|
||
}
|
||
.auth-card {
|
||
width: 100%;
|
||
max-width: 380px;
|
||
}
|
||
.auth-card .brand-mark {
|
||
justify-content: center;
|
||
margin-bottom: var(--sp-4);
|
||
}
|
||
|
||
/* Eingabefeld mit angehängtem Icon-Knopf (z. B. Passwort ein-/ausblenden). */
|
||
.input-with-button {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
}
|
||
.input-with-button > input {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
}
|
||
|
||
/* Flex-Kinder dürfen schrumpfen – sonst drängt ein 100%-breites select/input
|
||
ein danebenliegendes Feld auf 0 (das war der Grund für das winzige IBAN-Feld). */
|
||
.row > * {
|
||
min-width: 0;
|
||
}
|
||
|
||
/* Leerer Zustand (z. B. Dashboard ohne Karten). */
|
||
.empty-state {
|
||
text-align: center;
|
||
color: var(--muted);
|
||
padding: var(--sp-6) var(--sp-4);
|
||
}
|
||
.empty-state .icon {
|
||
opacity: 0.5;
|
||
margin-bottom: var(--sp-3);
|
||
}
|
||
|
||
/* Farbiges Icon-Plättchen (Konten/Kategorien). */
|
||
.icon-chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: var(--radius-sm);
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
/* Betrag + umgerechneter Wert (rechtsbündig gestapelt). */
|
||
.money {
|
||
display: inline-flex;
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
line-height: 1.3;
|
||
}
|
||
.money .amount {
|
||
font-variant-numeric: tabular-nums;
|
||
font-weight: 560;
|
||
}
|
||
|
||
/* Icon-Auswahlgitter. */
|
||
.icon-picker {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: var(--sp-2);
|
||
margin-top: 5px;
|
||
}
|
||
.icon-picker-item {
|
||
width: 38px;
|
||
height: 38px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: var(--radius-sm);
|
||
background: var(--surface);
|
||
color: var(--muted);
|
||
cursor: pointer;
|
||
transition: border-color .12s, color .12s, background .12s;
|
||
}
|
||
.icon-picker-item:hover {
|
||
color: var(--text);
|
||
background: var(--surface-2);
|
||
}
|
||
.icon-picker-item.selected {
|
||
background: var(--accent-soft);
|
||
}
|
||
|
||
/* Farbwähler-Zeile. */
|
||
.color-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
margin-top: 5px;
|
||
}
|
||
.color-row input[type="color"] {
|
||
width: 44px;
|
||
height: 34px;
|
||
padding: 2px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* Name + Icon nebeneinander (Listen). */
|
||
.named {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
min-width: 0;
|
||
}
|
||
.named .named-text {
|
||
min-width: 0;
|
||
}
|
||
.named .named-sub {
|
||
color: var(--muted);
|
||
font-size: 0.8rem;
|
||
}
|
||
|
||
/* Kategorien-Verwaltung: durchgehende Liste in EINER Karte, die Gruppen nur als
|
||
dezente Zwischenüberschrift dazwischen (keine abgesetzten Gruppen-Karten). */
|
||
.cat-section + .cat-section {
|
||
margin-top: var(--sp-5);
|
||
}
|
||
.cat-section-head {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding-bottom: var(--sp-2);
|
||
margin-bottom: 2px;
|
||
border-bottom: 2px solid var(--border-strong);
|
||
}
|
||
.cat-section-name {
|
||
flex: 1;
|
||
min-width: 0;
|
||
font-size: 1.05rem;
|
||
font-weight: 650;
|
||
}
|
||
.cat-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
padding: 9px 4px;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.cat-section .cat-row:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.cat-row:hover {
|
||
background: var(--surface-2);
|
||
}
|
||
.cat-row .grow {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
/* Seitenkopf mit Titel + Aktion rechts. */
|
||
.page-head {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: var(--sp-3);
|
||
margin-bottom: var(--sp-4);
|
||
}
|
||
.page-head h1 {
|
||
margin: 0;
|
||
}
|
||
|
||
/* Konten. */
|
||
.account-total {
|
||
display: flex;
|
||
align-items: baseline;
|
||
justify-content: space-between;
|
||
padding-bottom: var(--sp-3);
|
||
margin-bottom: var(--sp-2);
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.account-total strong {
|
||
font-size: 1.2rem;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.account-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.account-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
padding: var(--sp-3) 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.account-row:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
/* Die Kategorie-Auswahl ist `width: 100%` – als Flex-Element heisst das „ich
|
||
brauche die ganze Zeile", und alles daneben wird bis zum Umbruch
|
||
zusammengedrückt. In einer Listenzeile bekommt sie deshalb eine eigene
|
||
Breite, die nur noch schrumpfen darf. */
|
||
.account-row .catsel {
|
||
flex: 0 1 clamp(180px, 26%, 300px);
|
||
width: auto;
|
||
/* Ohne das schrumpft ein Flex-Element nie unter die Breite seines längsten
|
||
Wortes – die Auswahl bliebe breiter als vorgesehen und schöbe die Knöpfe
|
||
aus der Zeile. Der Text darin kürzt sich selbst mit „…". */
|
||
min-width: 0;
|
||
}
|
||
/* Der Abstand darüber ist für Formulare gedacht, wo die Auswahl unter ihrer
|
||
Beschriftung steht. In einer mittig ausgerichteten Zeile verrutscht sie nur. */
|
||
.account-row .catsel-btn {
|
||
margin-top: 0;
|
||
}
|
||
/* Beträge in einer Spalte statt ausgefranst. */
|
||
.account-row .money {
|
||
flex: 0 0 auto;
|
||
min-width: 104px;
|
||
white-space: nowrap;
|
||
}
|
||
/* Der Name nimmt den übrigen Platz. Nicht mit „…" abschneiden: Die Texte
|
||
sollen sich weiterhin vollständig markieren und kopieren lassen. */
|
||
.account-row .named-text {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
}
|
||
|
||
@media (max-width: 820px) {
|
||
/* Auf dem Telefon passt das nicht in eine Zeile. Zwei Zeilen: oben Name und
|
||
Betrag, darunter Auswahl und Knöpfe. Die Prozentwerte sind die Bruchstelle
|
||
– sie sind gross genug, dass unten kein Platz mehr für Name und Betrag
|
||
bleibt, und klein genug, dass die Knöpfe neben der Auswahl bleiben. */
|
||
.account-row {
|
||
flex-wrap: wrap;
|
||
row-gap: var(--sp-2);
|
||
}
|
||
.account-row .named-text {
|
||
flex: 1 1 50%;
|
||
}
|
||
.account-row .money {
|
||
min-width: 0;
|
||
}
|
||
.account-row .catsel {
|
||
flex: 1 1 40%;
|
||
}
|
||
}
|
||
.row-actions {
|
||
display: flex;
|
||
gap: 4px;
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
/* Filterleiste. */
|
||
.filter-bar {
|
||
display: flex;
|
||
gap: var(--sp-3);
|
||
flex-wrap: wrap;
|
||
margin-bottom: var(--sp-4);
|
||
}
|
||
.filter-bar select {
|
||
width: auto;
|
||
min-width: 160px;
|
||
margin-top: 0;
|
||
}
|
||
|
||
/* Segmentierte Umschaltung (Ausgabe/Einnahme/Transfer). */
|
||
.seg {
|
||
display: flex;
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: var(--radius-sm);
|
||
overflow: hidden;
|
||
margin-bottom: var(--sp-4);
|
||
}
|
||
.seg-btn {
|
||
flex: 1;
|
||
padding: 8px 10px;
|
||
border: none;
|
||
background: var(--surface);
|
||
color: var(--muted);
|
||
font-weight: 560;
|
||
cursor: pointer;
|
||
border-right: 1px solid var(--border);
|
||
}
|
||
.seg-btn:last-child {
|
||
border-right: none;
|
||
}
|
||
.seg-btn.active {
|
||
background: var(--accent);
|
||
color: #fff;
|
||
}
|
||
|
||
.nowrap {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Nimmt den freien Platz in einer Flex-Zeile und darf schrumpfen (Ellipsis). */
|
||
.grow {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
}
|
||
|
||
/* Nutzer-Chip in der Seitenleisten-Fußzeile ist ein Link auf „Mein Konto". */
|
||
a.sidebar-user {
|
||
text-decoration: none;
|
||
border-radius: var(--radius-sm);
|
||
padding: 2px 4px;
|
||
margin: -2px -4px;
|
||
transition: background .12s;
|
||
}
|
||
a.sidebar-user:hover {
|
||
background: var(--surface-2);
|
||
}
|
||
a.sidebar-user:hover .name {
|
||
color: var(--accent);
|
||
}
|
||
|
||
/* Budget: mehrere Monate nebeneinander. */
|
||
.budget-months {
|
||
display: grid;
|
||
gap: var(--sp-4);
|
||
grid-template-columns: repeat(var(--cols, 1), minmax(0, 1fr));
|
||
align-items: start;
|
||
}
|
||
@media (max-width: 820px) {
|
||
.budget-months {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
.budget-col {
|
||
min-width: 0;
|
||
}
|
||
.budget-col-head {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
padding-bottom: var(--sp-2);
|
||
margin-bottom: var(--sp-2);
|
||
border-bottom: 2px solid var(--border-strong);
|
||
}
|
||
.budget-col-head strong {
|
||
font-size: 1.05rem;
|
||
}
|
||
.budget-col-income {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 4px 0 var(--sp-2);
|
||
margin-bottom: var(--sp-2);
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.budget-crow {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 6px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.budget-crow:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.budget-crow .amount.small {
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
/* Budget. */
|
||
.budget-navbar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
}
|
||
.budget-month {
|
||
font-size: 1.05rem;
|
||
min-width: 170px;
|
||
text-align: center;
|
||
}
|
||
.flip {
|
||
transform: rotate(180deg);
|
||
}
|
||
.budget-group + .budget-group {
|
||
margin-top: var(--sp-4);
|
||
}
|
||
.budget-group-head {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: var(--sp-2) 0;
|
||
margin-bottom: 4px;
|
||
border-bottom: 2px solid var(--border-strong);
|
||
}
|
||
.budget-cat {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
padding: 7px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.budget-cat:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.budget-cat-name {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
min-width: 0;
|
||
}
|
||
.budget-cat-bar {
|
||
flex: 1;
|
||
}
|
||
.amount-input {
|
||
width: 96px;
|
||
text-align: right;
|
||
margin-top: 0;
|
||
padding: 5px 8px;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.budget-actual {
|
||
width: 96px;
|
||
text-align: right;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.budget-slash {
|
||
margin: 0 -4px;
|
||
}
|
||
.budget-bar {
|
||
height: 7px;
|
||
background: var(--surface-2);
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
}
|
||
.budget-bar-fill {
|
||
height: 100%;
|
||
background: var(--ok);
|
||
border-radius: 4px;
|
||
transition: width 0.2s;
|
||
}
|
||
.budget-bar-fill.over {
|
||
background: var(--danger);
|
||
}
|
||
.budget-total-row.card-total {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding-top: var(--sp-3);
|
||
margin-top: var(--sp-2);
|
||
border-top: 2px solid var(--border-strong);
|
||
}
|
||
tr.budget-total-row td {
|
||
border-top: 2px solid var(--border-strong);
|
||
padding-top: var(--sp-2);
|
||
}
|
||
|
||
/* Sparen-Option im Transfer-Formular. */
|
||
.savings-opt {
|
||
padding: var(--sp-3);
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-sm);
|
||
background: var(--surface-2);
|
||
margin-bottom: var(--sp-4);
|
||
}
|
||
.checkline {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
margin-bottom: var(--sp-2);
|
||
}
|
||
.checkline span {
|
||
color: var(--text);
|
||
font-weight: 560;
|
||
}
|
||
|
||
/* ---------- Dashboard-Grid ---------- */
|
||
.dash-toolbar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
position: relative;
|
||
}
|
||
.dash-add {
|
||
position: relative;
|
||
}
|
||
.dash-add-menu {
|
||
position: absolute;
|
||
right: 0;
|
||
top: calc(100% + 4px);
|
||
z-index: 20;
|
||
background: var(--surface);
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: var(--radius-sm);
|
||
box-shadow: var(--shadow);
|
||
min-width: 200px;
|
||
overflow: hidden;
|
||
}
|
||
.dash-add-item {
|
||
display: block;
|
||
width: 100%;
|
||
text-align: left;
|
||
padding: 8px 12px;
|
||
border: none;
|
||
background: none;
|
||
color: var(--text);
|
||
cursor: pointer;
|
||
}
|
||
.dash-add-item:hover {
|
||
background: var(--surface-2);
|
||
}
|
||
|
||
/* Karten-Optionen im Anordnen-Modus (z. B. Gruppen vs. Kategorien). */
|
||
.dash-config-bar {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: var(--sp-3);
|
||
padding-bottom: var(--sp-2);
|
||
margin-bottom: var(--sp-2);
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.dash-config-opt {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
gap: 4px;
|
||
min-width: 0;
|
||
flex: 1 1 140px;
|
||
}
|
||
.seg.sm {
|
||
margin-bottom: 0;
|
||
width: 100%;
|
||
}
|
||
.seg.sm .seg-btn {
|
||
padding: 4px 9px;
|
||
font-size: 0.78rem;
|
||
}
|
||
|
||
.dash-grid {
|
||
position: relative;
|
||
}
|
||
.dash-card {
|
||
background: var(--surface);
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius);
|
||
box-shadow: var(--shadow);
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: hidden;
|
||
}
|
||
.dash-card-head {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid var(--border);
|
||
flex: 0 0 auto;
|
||
}
|
||
.dash-card-title {
|
||
font-size: 0.7rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
color: var(--muted);
|
||
font-weight: 650;
|
||
flex: 1;
|
||
}
|
||
.dash-grid.editing .dash-card-head {
|
||
cursor: move;
|
||
background: var(--surface-2);
|
||
}
|
||
.dash-remove {
|
||
color: var(--danger);
|
||
}
|
||
.dash-card-body {
|
||
flex: 1;
|
||
min-height: 0;
|
||
overflow: auto;
|
||
padding: var(--sp-3);
|
||
}
|
||
|
||
.dash-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
}
|
||
.dash-line {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 6px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.dash-line:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.dash-total {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: var(--sp-2);
|
||
padding-top: var(--sp-2);
|
||
margin-top: 2px;
|
||
border-top: 2px solid var(--border-strong);
|
||
font-variant-numeric: tabular-nums;
|
||
/* Die Summe bleibt stehen, waehrend die Liste darunter durchlaeuft. Sie ist
|
||
die Zahl, wegen der man auf die Karte schaut – sie darf nicht die eine
|
||
sein, die man wegscrollen muss. Klebt am unteren Rand des Rollbereichs,
|
||
also am Karten-Koerper; ein eigener Hintergrund, damit die Zeilen nicht
|
||
durchscheinen, und Abstand nach unten statt des Innenabstands der Karte. */
|
||
position: sticky;
|
||
bottom: calc(-1 * var(--sp-3));
|
||
background: var(--surface);
|
||
padding-bottom: var(--sp-3);
|
||
margin-bottom: calc(-1 * var(--sp-3));
|
||
}
|
||
/* Zwei Zeilen im angehefteten Fuss: die Summe und, was daneben gebunden ist.
|
||
Beides muss stehen bleiben – eine Zeile hinter dem Angehefteten laege
|
||
darunter und waere nie zu sehen. */
|
||
.dash-total.gestapelt {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
gap: 2px;
|
||
}
|
||
.dash-total-zeile {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: var(--sp-2);
|
||
}
|
||
.ellipsis {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.dash-loading, .dash-empty {
|
||
padding: var(--sp-4);
|
||
text-align: center;
|
||
}
|
||
.dash-progress {
|
||
padding: 6px 0;
|
||
}
|
||
.dash-progress-top {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
margin-bottom: 4px;
|
||
}
|
||
.dash-kpis {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
gap: var(--sp-2);
|
||
height: 100%;
|
||
}
|
||
.dash-kpi {
|
||
display: flex;
|
||
align-items: baseline;
|
||
justify-content: space-between;
|
||
}
|
||
.dash-kpi strong {
|
||
font-size: 1.1rem;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
/* react-grid-layout: Platzhalter + Resize-Griff an das Theme angleichen. */
|
||
.react-grid-item.react-grid-placeholder {
|
||
background: var(--accent);
|
||
opacity: 0.15;
|
||
border-radius: var(--radius);
|
||
}
|
||
.react-grid-item > .react-resizable-handle::after {
|
||
border-right-color: var(--border-strong);
|
||
border-bottom-color: var(--border-strong);
|
||
}
|
||
|
||
/* ---------- CSV-Import ---------- */
|
||
.table-scroll {
|
||
overflow-x: auto;
|
||
}
|
||
.raw-table {
|
||
font-size: 0.8rem;
|
||
}
|
||
.raw-table th,
|
||
.raw-table td {
|
||
white-space: nowrap;
|
||
max-width: 220px;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.raw-table th {
|
||
color: var(--muted);
|
||
font-weight: 600;
|
||
}
|
||
.map-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
|
||
gap: var(--sp-3);
|
||
margin-top: var(--sp-3);
|
||
}
|
||
.map-grid label {
|
||
margin-bottom: 0;
|
||
}
|
||
tr.row-invalid {
|
||
opacity: 0.45;
|
||
}
|
||
tr.row-dup {
|
||
opacity: 0.55;
|
||
}
|
||
.doc-text {
|
||
max-height: 240px;
|
||
overflow: auto;
|
||
font-size: 0.78rem;
|
||
white-space: pre-wrap;
|
||
color: var(--muted);
|
||
background: var(--surface-2);
|
||
padding: var(--sp-3);
|
||
border-radius: var(--radius-sm);
|
||
margin-top: var(--sp-2);
|
||
}
|
||
/* Beleg-Seiten als Bildstreifen (horizontal scrollbar). */
|
||
.doc-pages {
|
||
display: flex;
|
||
gap: var(--sp-3);
|
||
overflow-x: auto;
|
||
padding-bottom: var(--sp-2);
|
||
}
|
||
.doc-page {
|
||
height: 440px;
|
||
width: auto;
|
||
flex: 0 0 auto;
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-sm);
|
||
background: #fff;
|
||
}
|
||
.import-more {
|
||
margin-top: var(--sp-3);
|
||
}
|
||
.import-more > summary {
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* DataTable-Zellen einzeilig halten, damit „…" greift (Excel-artig). */
|
||
.datatable td { white-space: nowrap; vertical-align: middle; }
|
||
.datatable td .named-text { min-width: 0; }
|
||
/* Interaktive Zellen (Import-Prüfansicht) füllen ihre Spalte, statt auf 60% zu
|
||
schrumpfen (globale .table td select/input-Regel überschreiben). */
|
||
.datatable td select,
|
||
.datatable td input[inputmode],
|
||
.datatable td input[type="text"] { max-width: none; width: 100%; }
|
||
.datatable td .catsel { width: 100%; }
|
||
|
||
/* ---------- Kategorie-Auswahl (auf-/zuklappbarer Baum, Ersatz für <select>) ---------- */
|
||
.catsel {
|
||
width: 100%;
|
||
}
|
||
.catsel-btn {
|
||
width: 100%;
|
||
margin-top: 5px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 7px 10px;
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: var(--radius-sm);
|
||
background: var(--surface);
|
||
color: var(--text);
|
||
font: inherit;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
transition: border-color .12s, box-shadow .12s;
|
||
}
|
||
.catsel-btn:hover:not(:disabled) {
|
||
border-color: var(--accent);
|
||
}
|
||
.catsel-btn:disabled {
|
||
opacity: 0.6;
|
||
cursor: default;
|
||
}
|
||
.catsel-btn.open {
|
||
border-color: var(--accent);
|
||
box-shadow: 0 0 0 3px var(--accent-soft);
|
||
}
|
||
.catsel-value {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
}
|
||
.catsel-caret {
|
||
flex: 0 0 auto;
|
||
color: var(--muted);
|
||
}
|
||
|
||
.catsel-panel {
|
||
position: fixed;
|
||
z-index: 1000;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: var(--surface);
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: var(--radius);
|
||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
|
||
overflow: hidden;
|
||
}
|
||
.catsel-search {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 8px 10px;
|
||
border-bottom: 1px solid var(--border);
|
||
color: var(--muted);
|
||
flex: 0 0 auto;
|
||
}
|
||
.catsel-search input {
|
||
width: 100%;
|
||
border: none;
|
||
background: none;
|
||
outline: none;
|
||
margin: 0;
|
||
padding: 0;
|
||
color: var(--text);
|
||
font: inherit;
|
||
}
|
||
.catsel-list {
|
||
overflow-y: auto;
|
||
padding: 5px;
|
||
}
|
||
.catsel-group + .catsel-group {
|
||
margin-top: 2px;
|
||
}
|
||
.catsel-group-head {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
width: 100%;
|
||
padding: 6px;
|
||
border: none;
|
||
background: none;
|
||
cursor: pointer;
|
||
color: var(--muted);
|
||
font-weight: 650;
|
||
font-size: 0.72rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.03em;
|
||
}
|
||
.catsel-group-head:hover {
|
||
color: var(--text);
|
||
}
|
||
.catsel-gchev {
|
||
flex: 0 0 auto;
|
||
transition: transform .12s ease;
|
||
}
|
||
.catsel-gchev.collapsed {
|
||
transform: rotate(-90deg);
|
||
}
|
||
.catsel-opt {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
width: 100%;
|
||
padding: 6px 8px 6px 22px;
|
||
border: none;
|
||
border-radius: var(--radius-sm);
|
||
background: none;
|
||
color: var(--text);
|
||
font: inherit;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
}
|
||
.catsel-opt:hover {
|
||
background: var(--surface-2);
|
||
}
|
||
.catsel-opt.selected {
|
||
background: var(--accent-soft);
|
||
color: var(--accent);
|
||
font-weight: 600;
|
||
}
|
||
.catsel-check {
|
||
margin-left: auto;
|
||
flex: 0 0 auto;
|
||
color: var(--accent);
|
||
}
|
||
.catsel-empty {
|
||
padding: 10px;
|
||
}
|
||
|
||
/* ---------- Schlagwörter (Kategorie-Popup + Prüfmeldungen) ---------- */
|
||
.kw-add {
|
||
display: flex;
|
||
gap: var(--sp-2);
|
||
margin-bottom: var(--sp-3);
|
||
}
|
||
.kw-add input {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
margin-top: 0;
|
||
}
|
||
.kw-chips {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: var(--sp-2);
|
||
}
|
||
.kw-chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 4px 6px 4px 11px;
|
||
border-radius: 20px;
|
||
background: var(--surface-2);
|
||
border: 1px solid var(--border);
|
||
font-size: 0.85rem;
|
||
}
|
||
.kw-amount {
|
||
color: var(--muted);
|
||
font-variant-numeric: tabular-nums;
|
||
font-size: 0.8em;
|
||
}
|
||
.kw-chip button {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 18px;
|
||
height: 18px;
|
||
padding: 0;
|
||
margin: 0;
|
||
border: none;
|
||
border-radius: 50%;
|
||
background: none;
|
||
color: var(--muted);
|
||
cursor: pointer;
|
||
}
|
||
.kw-chip button:hover {
|
||
background: var(--danger);
|
||
color: #fff;
|
||
}
|
||
/* Schlagwort-Knopf in der Kategorienliste. Belegte Kategorien tragen die
|
||
Akzentfarbe und die Anzahl – so sieht man der Liste an, wo schon etwas
|
||
hinterlegt ist, ohne jede Kategorie einzeln zu öffnen. */
|
||
.kw-btn {
|
||
gap: 5px;
|
||
}
|
||
.kw-btn.belegt {
|
||
color: var(--accent);
|
||
border-color: var(--accent-soft);
|
||
background: var(--accent-soft);
|
||
}
|
||
.kw-btn-zahl {
|
||
font-size: 0.72rem;
|
||
font-weight: 640;
|
||
font-variant-numeric: tabular-nums;
|
||
line-height: 1;
|
||
}
|
||
|
||
/* Das Schlagwort, das gerade oben in der Zeile liegt. Bearbeitet wird dort,
|
||
nicht im Chip – im Chip war für den Betrag kein Platz. */
|
||
.kw-chip.aktiv {
|
||
border-color: var(--accent);
|
||
box-shadow: 0 0 0 2px var(--accent-soft);
|
||
}
|
||
/* Passend dazu die Eingabezeile hervorheben, damit klar ist, dass dort gerade
|
||
ein vorhandenes Wort liegt und nicht ein neues entsteht. */
|
||
.kw-add.bearbeitet input {
|
||
border-color: var(--accent);
|
||
}
|
||
|
||
.kw-flag {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
padding: var(--sp-3) 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.kw-flag:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.kw-flag-main {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
.kw-flag-word {
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* ---------- Passwort: Anforderungsliste, Zwei-Faktor ---------- */
|
||
|
||
/* Nur für Screenreader – optisch weg, aber vorlesbar. */
|
||
.sr-only {
|
||
position: absolute;
|
||
width: 1px;
|
||
height: 1px;
|
||
padding: 0;
|
||
margin: -1px;
|
||
overflow: hidden;
|
||
clip: rect(0 0 0 0);
|
||
white-space: nowrap;
|
||
border: 0;
|
||
}
|
||
|
||
/* Hakt sich beim Tippen ab. Farben ausschliesslich aus Tokens, sonst bricht
|
||
das dunkle Thema. */
|
||
.pw-rules {
|
||
list-style: none;
|
||
margin: var(--sp-2) 0 0;
|
||
padding: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 3px;
|
||
font-size: 0.82rem;
|
||
}
|
||
.pw-rule {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
color: var(--muted);
|
||
transition: color 0.16s ease;
|
||
}
|
||
.pw-rule.erfuellt {
|
||
color: var(--ok);
|
||
}
|
||
.pw-rule-mark {
|
||
flex: 0 0 auto;
|
||
width: 16px;
|
||
height: 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
/* Offener Punkt, solange die Regel nicht erfüllt ist. */
|
||
.pw-rule-dot {
|
||
width: 7px;
|
||
height: 7px;
|
||
border-radius: 50%;
|
||
border: 1.5px solid currentColor;
|
||
opacity: 0.55;
|
||
}
|
||
/* Kurzer Impuls, wenn das Häkchen erscheint. */
|
||
.pw-rule.erfuellt .pw-rule-mark {
|
||
animation: pw-rule-pop 0.18s ease-out;
|
||
}
|
||
|
||
@keyframes pw-rule-pop {
|
||
from { transform: scale(0.4); opacity: 0; }
|
||
60% { transform: scale(1.18); opacity: 1; }
|
||
to { transform: scale(1); opacity: 1; }
|
||
}
|
||
|
||
/* styles.css hat keinen globalen Bewegungs-Reset, nur eine Aufzählung –
|
||
deshalb hier noch einmal ausdrücklich für die neuen Bewegungen. */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.pw-rule { transition: none; }
|
||
.pw-rule.erfuellt .pw-rule-mark { animation: none; }
|
||
}
|
||
|
||
/* Zwei-Faktor: QR-Code, Secret und Wiederherstellungscodes. */
|
||
.tfa-qr {
|
||
display: block;
|
||
width: 190px;
|
||
height: 190px;
|
||
/* Der QR-Code braucht weissen Grund, damit er auch im dunklen Thema
|
||
zuverlässig gescannt wird. */
|
||
background: #fff;
|
||
padding: var(--sp-2);
|
||
border-radius: var(--radius-sm);
|
||
border: 1px solid var(--border);
|
||
}
|
||
.tfa-secret {
|
||
display: inline-block;
|
||
padding: 6px var(--sp-2);
|
||
border-radius: var(--radius-sm);
|
||
background: var(--surface-2);
|
||
border: 1px solid var(--border);
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||
font-size: 0.9rem;
|
||
letter-spacing: 0.06em;
|
||
/* styles.css setzt body { user-select: none } – ohne das hier liesse sich
|
||
das Secret nicht markieren und kopieren. */
|
||
user-select: text;
|
||
}
|
||
.tfa-codes {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||
gap: var(--sp-2);
|
||
margin: var(--sp-3) 0;
|
||
padding: var(--sp-3);
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-sm);
|
||
background: var(--surface-2);
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||
font-size: 0.9rem;
|
||
user-select: text;
|
||
}
|
||
.tfa-codes .verbraucht {
|
||
color: var(--muted);
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
/* Zusammenfassung der Prüfansicht beim Wiederherstellen. */
|
||
.restore-summary {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin-top: var(--sp-2);
|
||
font-size: 0.88rem;
|
||
}
|
||
.restore-summary td {
|
||
padding: 3px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.restore-summary td:last-child {
|
||
text-align: right;
|
||
font-variant-numeric: tabular-nums;
|
||
color: var(--muted);
|
||
}
|
||
.restore-summary tr:last-child td {
|
||
border-bottom: none;
|
||
}
|
||
|
||
/* Zweiter Buchen-Knopf unter der Prüfliste – bei vielen Zeilen ist der obere
|
||
längst aus dem Bild gescrollt. */
|
||
.commit-footer {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
padding-top: var(--sp-3);
|
||
margin-top: var(--sp-2);
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
|
||
/* Ausgaben-Anteile: der Prozentwert ist die Kernaussage der Karte und steht
|
||
deshalb vor dem Betrag, mit gleichbleibender Ziffernbreite. */
|
||
.share-pct {
|
||
font-variant-numeric: tabular-nums;
|
||
white-space: nowrap;
|
||
}
|
||
/* Wird die Karte schmal, gibt zuerst der Betrag nach – ohne den Kategorienamen
|
||
sagt die Zeile nichts mehr aus, ohne den Betrag bleibt der Anteil lesbar. */
|
||
.share-row .share-name {
|
||
min-width: 4.5rem;
|
||
}
|
||
.share-row .share-amount {
|
||
flex: 0 1 auto;
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Abgleich des selbst gerechneten Saldos mit dem, den die Bank fuehrt.
|
||
Eine Abweichung ist kein Fehler der Bank, sondern ein Hinweis auf eine
|
||
fehlende oder doppelte Buchung – deshalb warnend, nicht rot. */
|
||
.saldo-ok { color: var(--ok); }
|
||
.saldo-abweichung { color: var(--warn); font-weight: 560; }
|
||
|
||
/* ---------- Kreditrahmen ----------
|
||
Wie viel von der Karte noch uebrig ist. Der Balken faellt bewusst schmal
|
||
aus: Er begleitet den Saldo, er ersetzt ihn nicht. Neutral gefaerbt, denn
|
||
einen Rahmen auszunutzen ist nicht falsch – erst ihn zu ueberziehen. */
|
||
.kreditrahmen {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
margin-top: 3px;
|
||
}
|
||
.rahmen-balken {
|
||
flex: 0 0 64px;
|
||
height: 5px;
|
||
background: var(--surface-2);
|
||
border-radius: 3px;
|
||
overflow: hidden;
|
||
}
|
||
.rahmen-fuellung {
|
||
height: 100%;
|
||
background: var(--muted);
|
||
border-radius: 3px;
|
||
transition: width 0.2s;
|
||
}
|
||
.rahmen-balken.ueber .rahmen-fuellung { background: var(--warn); }
|
||
|
||
/* ---------- Gebundenes Geld ----------
|
||
Steht unter „Gesamt", nicht darin. Aufklappbar, weil eine Summe, die man
|
||
nicht nachrechnen kann, man glauben muss. */
|
||
.gebunden-zeile {
|
||
padding: 0 var(--sp-4) var(--sp-2);
|
||
margin-top: -6px;
|
||
}
|
||
.gebunden-zeile summary {
|
||
cursor: pointer;
|
||
padding: 4px 0;
|
||
}
|
||
.gebunden-posten {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 3px 0 3px var(--sp-3);
|
||
font-size: 0.9em;
|
||
}
|
||
|
||
/* Eigene Notiz an einer Buchung – von Hand geschrieben und deshalb
|
||
aussagekraeftiger als jeder Banktext. Abgesetzt, damit sie nicht mit dem
|
||
Verwendungszweck verwechselt wird. */
|
||
.buchungsnotiz {
|
||
color: var(--muted);
|
||
font-style: italic;
|
||
opacity: 0.95;
|
||
}
|
||
.buchungsnotiz svg { vertical-align: -1px; }
|
||
|
||
/* Der Rueckweg aus „Ignorieren" – selten gebraucht, aber vorhanden. */
|
||
.abgelehnte {
|
||
margin-top: var(--sp-3);
|
||
border-top: 1px solid var(--border);
|
||
padding-top: var(--sp-2);
|
||
}
|
||
.abgelehnte summary { cursor: pointer; padding: 4px 0; }
|
||
|
||
/* ---------- Übertrags-Vorschläge ---------- */
|
||
.uebertrag-vorschlag {
|
||
padding: var(--sp-3) 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.uebertrag-vorschlag:last-child {
|
||
border-bottom: none;
|
||
}
|
||
/* Die beiden Seiten nebeneinander, damit man sie vergleicht statt sie zu
|
||
lesen. Auf schmalen Schirmen untereinander – gestapelt bleibt der Vergleich
|
||
möglich, gequetscht nicht. */
|
||
.uebertrag-seiten {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
}
|
||
.uebertrag-seite {
|
||
flex: 1 1 0;
|
||
min-width: 0;
|
||
}
|
||
.uebertrag-pfeil {
|
||
flex: 0 0 auto;
|
||
color: var(--muted);
|
||
}
|
||
@media (max-width: 820px) {
|
||
.uebertrag-seiten {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
gap: var(--sp-2);
|
||
}
|
||
}
|
||
|
||
/* Übertrags-Marke in der Buchungsliste: gedämpft, nicht warnend – die Buchung
|
||
ist in Ordnung, sie zählt nur nicht als Ausgabe oder Einnahme. */
|
||
.uebertrag-marke {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
color: var(--accent);
|
||
}
|
||
|
||
/* ---------- Einstellungen: Abschnittsleiste + gestapelte Abschnitte ----------
|
||
Vorher lagen die Karten in einem Spaltenfluss nebeneinander. Man fand nichts
|
||
wieder, weil die Reihenfolge von der Kartenhöhe abhing statt vom Thema.
|
||
Jetzt: eine Spalte in fester Reihenfolge, daneben eine Leiste, die zeigt, wo
|
||
man ist, und mit einem Klick dorthin springt. */
|
||
.settings-layout {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: var(--sp-5);
|
||
}
|
||
.settings-nav {
|
||
flex: 0 0 200px;
|
||
position: sticky;
|
||
top: var(--sp-5);
|
||
/* Eigener Bildlauf, falls die Liste einmal höher wird als der Schirm –
|
||
sonst wären die untersten Punkte nicht erreichbar. */
|
||
max-height: calc(100vh - var(--sp-6) * 2);
|
||
overflow-y: auto;
|
||
}
|
||
.settings-nav ul {
|
||
list-style: none;
|
||
margin: 0;
|
||
padding: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
}
|
||
.settings-nav a {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 8px 10px;
|
||
border-radius: var(--radius-sm);
|
||
color: var(--muted);
|
||
text-decoration: none;
|
||
font-weight: 560;
|
||
border-left: 2px solid transparent;
|
||
min-width: 0;
|
||
}
|
||
.settings-nav a:hover {
|
||
background: var(--surface-2);
|
||
color: var(--text);
|
||
}
|
||
.settings-nav a.active {
|
||
background: var(--surface-2);
|
||
color: var(--accent);
|
||
border-left-color: var(--accent);
|
||
}
|
||
.settings-inhalt {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--sp-4);
|
||
}
|
||
/* Beim Anspringen soll die Überschrift nicht am oberen Rand kleben. */
|
||
.settings-section {
|
||
scroll-margin-top: var(--sp-5);
|
||
}
|
||
|
||
@media (max-width: 1000px) {
|
||
/* Drei Spalten passen nicht mehr: Die Abschnittsleiste klappt über den
|
||
Inhalt und wird zur waagerecht scrollbaren Reihe. */
|
||
.settings-layout {
|
||
flex-direction: column;
|
||
/* Ohne das erbt die Spalten-Anordnung das flex-start von oben – dort ist
|
||
es für die klebende Leiste nötig, hier presst es Leiste und Inhalt auf
|
||
ihre Inhaltsbreite zusammen statt auf die volle. */
|
||
align-items: stretch;
|
||
}
|
||
.settings-nav {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 5;
|
||
flex: 0 0 auto;
|
||
width: 100%;
|
||
max-height: none;
|
||
padding: var(--sp-2) 0;
|
||
background: var(--bg);
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.settings-nav ul {
|
||
flex-direction: row;
|
||
overflow-x: auto;
|
||
gap: var(--sp-2);
|
||
}
|
||
.settings-nav a {
|
||
white-space: nowrap;
|
||
border-left: none;
|
||
border-bottom: 2px solid transparent;
|
||
}
|
||
.settings-nav a.active {
|
||
border-left-color: transparent;
|
||
border-bottom-color: var(--accent);
|
||
}
|
||
.settings-section {
|
||
scroll-margin-top: 56px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 760px) {
|
||
/* Ab hier ist die Hauptnavigation selbst eine klebende Leiste am oberen Rand
|
||
(z-index 20). Eine zweite klebende Leiste darunter verschwände hinter ihr –
|
||
also scrollt die Abschnittsleiste hier einfach mit. */
|
||
.settings-nav {
|
||
position: static;
|
||
border-bottom: none;
|
||
}
|
||
.settings-section {
|
||
scroll-margin-top: var(--sp-3);
|
||
}
|
||
}
|
||
|
||
/* Kategorie-Auswahl in einer Tabellenzeile: eigene Spalte, also volle
|
||
Zellenbreite – aber ohne den Abstand, den sie im Formular unter ihrer
|
||
Beschriftung braucht. Der verschöbe sie gegen die übrigen Zellen. */
|
||
.datatable td .catsel-btn {
|
||
margin-top: 0;
|
||
padding: 4px 8px;
|
||
}
|
||
|
||
/* Herkunft einer Buchung: Bank, Mail, Kurzbefehl, Datei, von Hand. Sie steht
|
||
NEBEN dem Titel und in dessen Grösse – nicht kleingedruckt darunter, wo sich
|
||
sonst alles Neue stapelt. */
|
||
.titelzeile {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
min-width: 0;
|
||
}
|
||
.titelzeile > .ellipsis {
|
||
min-width: 0;
|
||
}
|
||
/* Aussehen kommt von `.badge` – dieselbe Pille wie überall sonst. Hier steht
|
||
nur, wie sie sich in der Titelzeile verhält: nicht schrumpfen, nicht
|
||
umbrechen. Eng wird zuerst der Titel, denn ein halbes „Datei-Imp…" nützt
|
||
niemandem, ein gekürzter Titel bleibt lesbar. */
|
||
.herkunft {
|
||
flex: 0 0 auto;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* ---------- Bankanbindung: Verbindung, Konto, neue Bank ----------
|
||
Vorher lieh sich das die Klassen des Postfachs: gestrichelte Trennlinien,
|
||
sonst nichts. Damit war nicht zu sehen, welcher Knopf zu welchem Konto
|
||
gehört und wo eine Bank aufhört. */
|
||
.bank-verbindung {
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius);
|
||
padding: var(--sp-4);
|
||
margin-top: var(--sp-4);
|
||
}
|
||
.bank-verbindung-kopf {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding-bottom: var(--sp-2);
|
||
margin-bottom: var(--sp-2);
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
/* Ein Konto der Verbindung: eingerückt und mit eigener Kante. Die Kante ist
|
||
das, was seine Knöpfe sichtbar an es bindet. */
|
||
.bank-konto {
|
||
border-left: 2px solid var(--border-strong);
|
||
padding: var(--sp-3) 0 var(--sp-3) var(--sp-3);
|
||
margin-top: var(--sp-3);
|
||
}
|
||
.bank-konto + .bank-konto {
|
||
margin-top: var(--sp-2);
|
||
}
|
||
.bank-konto select {
|
||
width: 100%;
|
||
margin-top: 4px;
|
||
}
|
||
/* Die Knöpfe der VERBINDUNG (alle Konten, Salden, trennen) stehen ohne
|
||
Einrückung – so gehören sie sichtbar zur Bank und nicht zum letzten Konto. */
|
||
.bank-verbindung > .mail-actions {
|
||
padding-top: var(--sp-3);
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
/* Eine neue Bank hinzufügen ist etwas anderes als eine bestehende zu pflegen. */
|
||
.bank-neu {
|
||
margin-top: var(--sp-5);
|
||
padding-top: var(--sp-4);
|
||
border-top: 2px solid var(--border-strong);
|
||
}
|
||
.bank-neu h3 {
|
||
margin: 0 0 var(--sp-3);
|
||
font-size: 1rem;
|
||
}
|
||
|
||
/* Die Einheit neben dem Zahlenfeld darf nicht umbrechen – „Minuten (0" in der
|
||
einen und „= aus)" in der nächsten Zeile las sich wie ein Fehler. */
|
||
.bank-verbindung .input-with-button > .muted {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Rückfrage in der Buchungszeile: „Das könnte ein Übertrag sein." Bewusst
|
||
auffällig genug, um gesehen zu werden – sie verlangt eine Antwort, anders
|
||
als die Marke einer schon bestätigten Verknüpfung. */
|
||
.uebertrag-frage {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
margin-top: 3px;
|
||
font-size: 0.8rem;
|
||
color: var(--warn);
|
||
min-width: 0;
|
||
}
|
||
.uebertrag-frage .btn {
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
/* Aufgeschlüsselter Kontostand: eine Rechnung, also untereinander und rechts
|
||
ausgerichtet – so lässt sie sich nachvollziehen wie auf Papier. */
|
||
/* Die Zeile darf nur umbrechen, wenn die Rechnung offen ist – sonst
|
||
verschiebt sich die Kontenliste ohne Grund. */
|
||
.account-row.mit-aufschluss {
|
||
flex-wrap: wrap;
|
||
}
|
||
.aufschluss {
|
||
flex: 1 1 100%;
|
||
margin: var(--sp-2) 0 0 38px;
|
||
padding: var(--sp-3);
|
||
border-left: 2px solid var(--border-strong);
|
||
font-size: 0.85rem;
|
||
}
|
||
.aufschluss-zeile {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: var(--sp-3);
|
||
padding: 2px 0;
|
||
min-width: 0;
|
||
}
|
||
.aufschluss-zeile > span:last-child {
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.aufschluss-summe {
|
||
margin-top: 4px;
|
||
padding-top: 4px;
|
||
border-top: 1px solid var(--border-strong);
|
||
font-weight: 600;
|
||
}
|
||
.aufschluss-uebertraege {
|
||
margin-top: var(--sp-3);
|
||
padding-top: var(--sp-2);
|
||
border-top: 1px dashed var(--border);
|
||
}
|
||
|
||
/* Budget-Stand im Ringdiagramm: grün im Rahmen, rot darüber – in der Legende
|
||
und in der Mitte. Ohne Plan bleibt beides, wie es war: Da gibt es nichts zu
|
||
überschreiten, und eine Farbe behauptete etwas. */
|
||
.legend-value.budget-ok,
|
||
.donut-value.budget-ok {
|
||
fill: var(--ok);
|
||
color: var(--ok);
|
||
}
|
||
.legend-value.budget-over,
|
||
.donut-value.budget-over {
|
||
fill: var(--danger);
|
||
color: var(--danger);
|
||
}
|
||
|
||
/* Gleich aussehende Buchungen: die Gruppe als Block, die Zeilen darin
|
||
eingerückt – so sieht man auf einen Blick, wie viele es sind. */
|
||
.dubletten-gruppe {
|
||
padding: var(--sp-3) 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.dubletten-gruppe:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.dubletten-zeile {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 3px 0 3px var(--sp-3);
|
||
border-left: 2px solid var(--border-strong);
|
||
margin-top: 4px;
|
||
min-width: 0;
|
||
}
|
||
.dubletten-zeile > .ellipsis {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
}
|
||
|
||
/* Zeitraum einer Dashboard-Karte: leise, aber da – ohne ihn ist bei einem
|
||
Budget-Monat, der nicht am Ersten beginnt, nicht nachvollziehbar, was
|
||
gezählt wurde. */
|
||
.dash-zeitraum {
|
||
margin-bottom: var(--sp-2);
|
||
}
|
||
|
||
/* ---------- Budgetzeitraum einer Buchung ----------
|
||
Normalerweise entscheidet das Datum, und dann steht hier nur, was gilt. Das
|
||
Ändern liegt hinter einem Klick und hinter Pfeilen statt hinter einer
|
||
Auswahlliste: Es ist der Ausnahmefall und soll sich auch so anfühlen. */
|
||
.budgetzeitraum {
|
||
margin-bottom: var(--sp-4);
|
||
}
|
||
.budgetzeitraum-kopf {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
min-height: 32px;
|
||
}
|
||
.budgetzeitraum-wahl {
|
||
margin-top: var(--sp-2);
|
||
padding: var(--sp-3);
|
||
border: 1px dashed var(--border-strong);
|
||
border-radius: var(--radius-sm);
|
||
}
|
||
.budgetzeitraum-wahl p {
|
||
margin: 0 0 var(--sp-3);
|
||
}
|
||
.budgetzeitraum-schritte {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
flex-wrap: wrap;
|
||
}
|
||
/* Feste Breite: Sonst springen die Pfeile, sobald „Mai" auf „September" folgt. */
|
||
.budgetzeitraum-monat {
|
||
min-width: 9.5em;
|
||
text-align: center;
|
||
font-weight: 580;
|
||
color: var(--text);
|
||
}
|
||
|
||
/* ---------- Woraus ein Anteil besteht ----------
|
||
Eine Zahl, die man nicht aufschlüsseln kann, muss man glauben. Deshalb ist
|
||
jede Zeile der Ausgaben-Anteile ein Knopf – sie sieht aus wie vorher, führt
|
||
aber zu den Buchungen dahinter. */
|
||
.anteil-knopf {
|
||
display: block;
|
||
width: 100%;
|
||
background: none;
|
||
border: 0;
|
||
padding: 0;
|
||
margin: 0;
|
||
font: inherit;
|
||
color: inherit;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
border-radius: var(--radius-sm);
|
||
}
|
||
.anteil-knopf:hover .share-name {
|
||
text-decoration: underline;
|
||
}
|
||
.chart-legend li > .legend-zeile {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
width: 100%;
|
||
min-width: 0;
|
||
background: none;
|
||
border: 0;
|
||
padding: 0;
|
||
margin: 0;
|
||
font: inherit;
|
||
color: inherit;
|
||
text-align: left;
|
||
}
|
||
.chart-legend li > .legend-zeile.klickbar {
|
||
cursor: pointer;
|
||
}
|
||
.chart-legend li > .legend-zeile.klickbar:hover .legend-name {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.anteil-liste {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.anteil-zeile {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: var(--sp-3);
|
||
padding: 6px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
font-size: 0.85rem;
|
||
}
|
||
/* Feste Breite für Datum und Konto: Sonst rutscht der Betrag von Zeile zu
|
||
Zeile, und genau die Beträge will man hier untereinander vergleichen. */
|
||
.anteil-datum {
|
||
flex: 0 0 auto;
|
||
min-width: 5.5em;
|
||
}
|
||
.anteil-konto {
|
||
flex: 0 1 auto;
|
||
max-width: 9em;
|
||
}
|
||
|
||
/* ---------- Halbes Update ----------
|
||
Gebaut, aber der Dienst nicht neu gestartet: Die Oberfläche ruft dann
|
||
Endpunkte auf, die es serverseitig noch gar nicht gibt. Ohne diesen Hinweis
|
||
sieht das aus wie ein Fehler in der Funktion. */
|
||
.stand-hinweis {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: var(--sp-2);
|
||
margin-bottom: var(--sp-4);
|
||
padding: var(--sp-3) var(--sp-4);
|
||
border: 1px solid var(--warn);
|
||
border-radius: var(--radius-sm);
|
||
background: var(--warn-soft);
|
||
color: var(--text);
|
||
font-size: 0.85rem;
|
||
line-height: 1.45;
|
||
}
|
||
.stand-hinweis svg {
|
||
flex: 0 0 auto;
|
||
margin-top: 2px;
|
||
}
|
||
.stand-hinweis code {
|
||
padding: 1px 5px;
|
||
border-radius: 4px;
|
||
background: var(--surface-2);
|
||
font-size: 0.95em;
|
||
}
|
||
|
||
/* --- Abos & Verträge ----------------------------------------------------- */
|
||
|
||
/* Die Summe ganz oben: Sie ist die Antwort auf die Frage, wegen der man die
|
||
Seite überhaupt öffnet. */
|
||
.abo-summe {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: var(--sp-5);
|
||
}
|
||
.abo-summe-zahl {
|
||
font-size: 1.4rem;
|
||
font-weight: 600;
|
||
font-variant-numeric: tabular-nums;
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.abo-liste {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
/* Als Gitter und nicht als Reihe: Auf dem Telefon rutscht der Betrag unter den
|
||
Namen, statt vier Spalten in 375 Pixel zu quetschen. Mit Reihe blieb vom
|
||
Namen "Sal..." uebrig und von der Kategorie ein Punkt. */
|
||
.abo-zeile {
|
||
display: grid;
|
||
grid-template-columns: auto 1fr auto auto;
|
||
grid-template-areas: "symbol mitte betrag knoepfe";
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
padding: var(--sp-2) 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.abo-zeile > :nth-child(1) { grid-area: symbol; }
|
||
.abo-mitte { grid-area: mitte; }
|
||
.abo-betrag { grid-area: betrag; }
|
||
.abo-knoepfe { grid-area: knoepfe; }
|
||
.abo-zeile:last-child { border-bottom: none; }
|
||
/* Gekündigtes bleibt lesbar, tritt aber zurück – es zählt nicht mehr mit. */
|
||
.abo-beendet { opacity: 0.55; }
|
||
|
||
.abo-mitte { min-width: 0; }
|
||
.abo-kopf {
|
||
display: flex;
|
||
align-items: baseline;
|
||
flex-wrap: wrap;
|
||
gap: 2px var(--sp-2);
|
||
min-width: 0;
|
||
}
|
||
.abo-unten {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0 5px;
|
||
min-width: 0;
|
||
margin-top: 1px;
|
||
}
|
||
.abo-faellig { color: var(--muted); white-space: nowrap; }
|
||
.abo-faellig.warn { color: var(--warn); }
|
||
|
||
.abo-betrag {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
white-space: nowrap;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.abo-knoepfe { display: flex; gap: 2px; }
|
||
|
||
/* Das Ansparen gehört sichtbar zum Intervall darüber, nicht daneben. */
|
||
.abo-ansparen {
|
||
border-left: 2px solid var(--border-strong);
|
||
padding-left: var(--sp-3);
|
||
margin-bottom: var(--sp-3);
|
||
}
|
||
|
||
@media (max-width: 620px) {
|
||
/* Betrag unter den Namen, Knoepfe bleiben rechts oben. So bekommt der Name
|
||
die volle Breite – auf dem Telefon ist er das Einzige, woran man die Zeile
|
||
erkennt. */
|
||
.abo-zeile {
|
||
grid-template-columns: auto 1fr auto;
|
||
grid-template-areas:
|
||
"symbol mitte knoepfe"
|
||
"symbol betrag knoepfe";
|
||
align-items: start;
|
||
row-gap: 2px;
|
||
padding: var(--sp-3) 0;
|
||
}
|
||
.abo-zeile > :nth-child(1),
|
||
.abo-knoepfe { align-self: center; }
|
||
/* Waagrecht statt untereinander: Unter dem Namen ist Breite da, Hoehe nicht. */
|
||
.abo-betrag {
|
||
flex-direction: row;
|
||
align-items: baseline;
|
||
flex-wrap: wrap;
|
||
gap: 0 var(--sp-2);
|
||
}
|
||
.abo-summe { gap: var(--sp-3) var(--sp-5); }
|
||
.abo-summe-zahl { font-size: 1.2rem; }
|
||
}
|
||
|
||
/* Waehrungs-Auswahl in den Einstellungen: ein Gitter aus Kacheln statt einer
|
||
Liste mit dreissig Zeilen. */
|
||
.waehrung-gitter {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
|
||
gap: 6px;
|
||
margin-bottom: var(--sp-2);
|
||
}
|
||
.waehrung-kachel {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
margin: 0;
|
||
padding: 6px 8px;
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-sm, 6px);
|
||
cursor: pointer;
|
||
font-size: 0.85rem;
|
||
white-space: nowrap;
|
||
}
|
||
.waehrung-kachel.an { border-color: var(--accent, var(--border-strong)); }
|
||
.waehrung-kachel input { width: auto; margin: 0; }
|
||
.waehrung-kachel:has(input:disabled) { opacity: 0.6; cursor: default; }
|
||
|
||
/* Logo statt Symbol. Gleiche Kantenlänge wie der IconChip daneben, damit die
|
||
Liste nicht wackelt, je nachdem ob ein Vertrag ein Logo hat. */
|
||
.abo-logo {
|
||
width: 30px;
|
||
height: 30px;
|
||
object-fit: contain;
|
||
border-radius: 6px;
|
||
flex: none;
|
||
}
|
||
.abo-logo.gross { width: 48px; height: 48px; border-radius: 8px; }
|
||
|
||
.abo-logo-feld {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
margin-bottom: var(--sp-2);
|
||
}
|
||
.abo-logo-knoepfe { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
|
||
/* Das Dateifeld steckt in einem <label>, das wie ein Knopf aussieht. */
|
||
.abo-logo-knoepfe label.btn { cursor: pointer; margin: 0; }
|
||
.abo-logo-knoepfe label.btn.deaktiviert { opacity: 0.5; cursor: not-allowed; }
|
||
|
||
/* --- Logo zuschneiden ---------------------------------------------------- */
|
||
|
||
.zuschnitt-flaeche {
|
||
position: relative;
|
||
margin: 0 auto var(--sp-2);
|
||
border-radius: var(--radius);
|
||
/* Schachbrett: zeigt, wo das Bild durchsichtig ist. Bei einem freigestellten
|
||
Logo ist das der Unterschied zwischen "weisser Kasten" und "nichts da". */
|
||
background:
|
||
repeating-conic-gradient(var(--border) 0% 25%, transparent 0% 50%) 50% / 16px 16px;
|
||
touch-action: none;
|
||
user-select: none;
|
||
overflow: hidden;
|
||
}
|
||
.zuschnitt-flaeche img {
|
||
display: block;
|
||
width: 100%;
|
||
height: 100%;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.zuschnitt-rahmen {
|
||
position: absolute;
|
||
box-sizing: border-box;
|
||
border: 1px solid #fff;
|
||
cursor: move;
|
||
/* Alles ausserhalb abdunkeln – mit EINEM Schatten statt vier Kacheln.
|
||
So bleibt der Ausschnitt das Helle, und man sieht sofort, was bleibt. */
|
||
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.55);
|
||
}
|
||
/* Drittel-Linien: helfen beim Ausrichten, ohne den Ausschnitt zuzustellen. */
|
||
.zuschnitt-rahmen::before,
|
||
.zuschnitt-rahmen::after {
|
||
content: "";
|
||
position: absolute;
|
||
inset: 0;
|
||
pointer-events: none;
|
||
opacity: 0.35;
|
||
}
|
||
.zuschnitt-rahmen::before {
|
||
border-left: 1px solid #fff;
|
||
border-right: 1px solid #fff;
|
||
left: 33.33%;
|
||
right: 33.33%;
|
||
}
|
||
.zuschnitt-rahmen::after {
|
||
border-top: 1px solid #fff;
|
||
border-bottom: 1px solid #fff;
|
||
top: 33.33%;
|
||
bottom: 33.33%;
|
||
}
|
||
|
||
.zuschnitt-griff {
|
||
position: absolute;
|
||
width: 14px;
|
||
height: 14px;
|
||
background: #fff;
|
||
border-radius: 3px;
|
||
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
|
||
}
|
||
.griff-nw { left: -7px; top: -7px; cursor: nwse-resize; }
|
||
.griff-n { left: calc(50% - 7px); top: -7px; cursor: ns-resize; }
|
||
.griff-ne { right: -7px; top: -7px; cursor: nesw-resize; }
|
||
.griff-w { left: -7px; top: calc(50% - 7px); cursor: ew-resize; }
|
||
.griff-e { right: -7px; top: calc(50% - 7px); cursor: ew-resize; }
|
||
.griff-sw { left: -7px; bottom: -7px; cursor: nesw-resize; }
|
||
.griff-s { left: calc(50% - 7px); bottom: -7px; cursor: ns-resize; }
|
||
.griff-se { right: -7px; bottom: -7px; cursor: nwse-resize; }
|
||
|
||
.zuschnitt-fuss {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
margin-bottom: var(--sp-2);
|
||
}
|
||
.zuschnitt-fuss span { flex: 1; font-variant-numeric: tabular-nums; }
|
||
|
||
/* Auf dem Telefon sind die Griffe mit dem Finger sonst nicht zu treffen. */
|
||
@media (pointer: coarse) {
|
||
.zuschnitt-griff { width: 20px; height: 20px; }
|
||
.griff-nw, .griff-w, .griff-sw { left: -10px; }
|
||
.griff-ne, .griff-e, .griff-se { right: -10px; }
|
||
.griff-nw, .griff-n, .griff-ne { top: -10px; }
|
||
.griff-sw, .griff-s, .griff-se { bottom: -10px; }
|
||
.griff-n, .griff-s { left: calc(50% - 10px); }
|
||
.griff-w, .griff-e { top: calc(50% - 10px); }
|
||
}
|
||
|
||
/* --- Budget aus Verträgen ------------------------------------------------ */
|
||
|
||
/* Die Rechnung unter der Zeile. Eingerückt bis unter den Namen, damit sie zur
|
||
Zeile darüber gehört und nicht wie eine eigene Kategorie aussieht. */
|
||
.budget-rechnung {
|
||
padding: 0 0 6px 30px;
|
||
margin-top: -4px;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.budget-hinweis { margin: 0 0 var(--sp-2); }
|
||
|
||
/* Der Umschalter. Schmal – er steht zwischen Ist-Betrag und Eingabefeld, und
|
||
dort ist wenig Platz. */
|
||
.btn-sigma {
|
||
flex: none;
|
||
width: 26px;
|
||
height: 26px;
|
||
padding: 0;
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
background: transparent;
|
||
color: var(--muted);
|
||
font-size: 0.9rem;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
}
|
||
.btn-sigma:hover { border-color: var(--border-strong); color: var(--fg); }
|
||
.btn-sigma.an {
|
||
border-color: var(--accent, var(--border-strong));
|
||
color: var(--accent, var(--fg));
|
||
background: var(--accent-soft, transparent);
|
||
}
|
||
|
||
/* Die Aufschlüsselung unter einer Budget-Zeile. Aufklappbar, weil eine Summe,
|
||
die man nicht nachrechnen kann, geglaubt werden muss. */
|
||
.budget-rechnung-kopf {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
width: 100%;
|
||
padding: 0;
|
||
border: 0;
|
||
background: none;
|
||
color: inherit;
|
||
font: inherit;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
}
|
||
.budget-rechnung-kopf .icon { color: var(--muted); flex: none; }
|
||
.budget-rechnung-kopf:hover .muted { color: var(--fg); }
|
||
.budget-rechnung-kopf .warn { margin-left: auto; white-space: nowrap; }
|
||
|
||
.budget-vertragsliste {
|
||
list-style: none;
|
||
margin: 2px 0 6px;
|
||
padding: 0 0 0 17px;
|
||
}
|
||
.budget-vertragsliste li {
|
||
display: flex;
|
||
gap: var(--sp-2);
|
||
padding: 1px 0;
|
||
}
|
||
.budget-vertragsliste li > :first-child { flex: 1; min-width: 0; }
|
||
.budget-vertrag-betrag { white-space: nowrap; font-variant-numeric: tabular-nums; }
|
||
|
||
/* --- Anmeldung über einen fremden Dienst --------------------------------- */
|
||
|
||
/* Trennlinie mit „oder" auf der Login-Seite: Der SSO-Knopf ist eine
|
||
Alternative zum Formular darüber, keine Fortsetzung davon. */
|
||
.login-trenner {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-3);
|
||
margin: var(--sp-4) 0 var(--sp-3);
|
||
color: var(--muted);
|
||
font-size: 0.85rem;
|
||
}
|
||
.login-trenner::before,
|
||
.login-trenner::after {
|
||
content: "";
|
||
flex: 1;
|
||
height: 1px;
|
||
background: var(--border);
|
||
}
|
||
.btn.login-sso {
|
||
width: 100%;
|
||
justify-content: center;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.sso-liste { display: flex; flex-direction: column; gap: var(--sp-2); }
|
||
.sso-zeile {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--sp-2);
|
||
padding: 6px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.sso-zeile:last-child { border-bottom: none; }
|
||
.sso-haken { color: var(--ok); flex: none; }
|
||
.btn.sso-verknuepfen { justify-content: center; text-decoration: none; }
|