Fix wheel-photo squareness bug, native select popups, image-cycle crash
.bildbox.radbild lost to a same-specificity, later-declared .bildbox rule, so the wheel photo stayed a full-width 4:3 box despite the earlier crop fix - only which slice showed ever changed. Fixed with a compound selector and moved "Montiert" to top-left to match the now-correctly-sized photo. Native <select> popups had no color-scheme hint and rendered in the browser's default light palette regardless of the app's dark theme - this is what made "Modell" and other dropdowns flash bright white. bildWeiter() (Mein Audi image-cycle tap) referenced a CSS class that was never emitted (.platzhalter-datei vs. the real .platzhalter-aktion), throwing and aborting before the page-dot indicator update - the photo advanced but the dots never moved. Merged the separate "Fahrzeugbilder" upload grid into "Bild der Übersicht": pick a view from the existing dropdown, tap its preview to upload/replace/delete - same generic popup plumbing, no new mechanism. Removed the now-dead BILDER_UPLOAD_SLOTS/.bildgrid/.bildslot/.carfix.mini. Back arrow changed from red to the neutral headline color, matching every other navigation-color decision in this project. Investigated but could not reproduce: user-reported "whole tab bar disappears" when hiding labels. Traced the exact commit that added the icon+label highlight and confirmed it's correctly scoped to :not(.ohne); live DOM/computed-style testing across toggle, navigation, and both mobile/desktop widths showed the tab bar staying visible throughout. Left unchanged pending a repro from the user. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,13 @@ generic-receipt-parser gaps; a sixth round the same day fixed the map pins' real
|
|||||||
(the CI `poi-car`/`poi` icons are thin outline-only paths, only 13-40% filled — solved with a solid
|
(the CI `poi-car`/`poi` icons are thin outline-only paths, only 13-40% filled — solved with a solid
|
||||||
silhouette layer extracted from each icon's own outer contour, not a redraw), applied a batch of
|
silhouette layer extracted from each icon's own outer contour, not a redraw), applied a batch of
|
||||||
~20 user-reported UI polish items against Apple's Human Interface Guidelines, some via a guided
|
~20 user-reported UI polish items against Apple's Human Interface Guidelines, some via a guided
|
||||||
Q&A, and lowered the battery-voltage statistic's cutoff from 13.2V to 12.8V). This file is the entry point for every new agent
|
Q&A, and lowered the battery-voltage statistic's cutoff from 13.2V to 12.8V; a seventh round the
|
||||||
|
same day fixed a real CSS specificity bug that kept the wheel photo a wide 4:3 box instead of the
|
||||||
|
intended 96x96 square, moved the "Montiert" pill to match, added `color-scheme` so native `<select>`
|
||||||
|
popups stop rendering in the browser's default light palette against the dark app, root-caused and
|
||||||
|
fixed a JS crash in the "Mein Audi" image-cycle click handler, merged the separate "Fahrzeugbilder"
|
||||||
|
upload grid into "Bild der Übersicht" (pick a view, tap its photo to upload), and turned the back
|
||||||
|
arrow from red to the neutral headline color — see section C). This file is the entry point for every new agent
|
||||||
session: what this repo is, what is finished, what is missing, and how to work here. Detail lives in
|
session: what this repo is, what is finished, what is missing, and how to work here. Detail lives in
|
||||||
the linked documents — this file points, it does not duplicate.
|
the linked documents — this file points, it does not duplicate.
|
||||||
|
|
||||||
@@ -926,6 +932,63 @@ wraps the web app for iPhone; a PWA home-screen install is the accepted intermed
|
|||||||
Deployed to `audi_ha_test` (version `1786901000`); pin fix visually confirmed live (solid
|
Deployed to `audi_ha_test` (version `1786901000`); pin fix visually confirmed live (solid
|
||||||
teardrop pin with white car glyph, clearly over the map's "Obergurgl" label text) and the
|
teardrop pin with white car glyph, clearly over the map's "Obergurgl" label text) and the
|
||||||
tab-bar highlight confirmed covering both icon and "Übersicht" label.
|
tab-bar highlight confirmed covering both icon and "Übersicht" label.
|
||||||
|
- [x] Seventh round the same day (2026-08-16) — more user-reported layout/interaction bugs:
|
||||||
|
(1) **Wheel photo (Sommerrad/Winterrad) was never actually a square, despite the fifth round's
|
||||||
|
crop-direction fix.** Root cause: `bildMitPlatzhalter()` puts the `radbild` class on *both* the
|
||||||
|
wrapping `.bildbox` div and the `<img>`; the old `.radbild{width:96px;height:96px;...}` rule and
|
||||||
|
`.bildbox{width:100%;aspect-ratio:4/3;...}` have equal specificity (one class each), and
|
||||||
|
`.bildbox` is declared later in the file, so it silently won — the box stayed a full-width 4:3
|
||||||
|
rectangle the whole time, `object-position:right center` just changed which slice of that wide
|
||||||
|
box showed. Fixed with a `.bildbox.radbild{width:96px;height:96px;aspect-ratio:1/1}` compound
|
||||||
|
selector (two classes, unambiguously higher specificity than plain `.bildbox`); `.radbild` alone
|
||||||
|
now only carries `object-position`. Verified live: `.bildbox.radbild` now measures exactly
|
||||||
|
96×96px.
|
||||||
|
(2) **"Montiert" moved from top-right to top-left**, per explicit request — this was the visible
|
||||||
|
symptom of (1): the pill was anchored top-right assuming it overlaid the (accidentally) full-
|
||||||
|
width photo; once the photo is a real 96px square on the left, top-left is where it actually
|
||||||
|
needs to sit to stay over the picture.
|
||||||
|
(3) **Native `<select>` popups now get a `color-scheme` hint.** The closed `<select>` box itself
|
||||||
|
was already themed correctly, but the *opened* native option list ignores app CSS and falls back
|
||||||
|
to the browser/OS default palette unless `color-scheme` says otherwise — this is what made
|
||||||
|
"Modell" and every other dropdown "flash" bright white against the dark app on open. Added
|
||||||
|
`color-scheme: dark` under `:host([data-theme="nacht"])` and `color-scheme: light` under
|
||||||
|
`:host([data-theme="tag"])` in `audi-dashboard-ios.css`.
|
||||||
|
(4) **Fixed a real JS crash in the "Mein Audi" image-cycle click handler.** `bildWeiter()` (fires
|
||||||
|
on tapping the hero photo) tried `box.querySelector(".platzhalter-datei").textContent = ...` —
|
||||||
|
that class was never emitted by `bildMitPlatzhalter()` (the actual class is `.platzhalter-
|
||||||
|
aktion`, and in gallery mode it deliberately shows a static "Foto hinzufügen" prompt, not a
|
||||||
|
filename). `querySelector` returned `null`, the assignment threw, and the exception aborted the
|
||||||
|
function *before* reaching the line that updates the `.dots` page indicator — so the photo
|
||||||
|
itself advanced (that line ran first) but the dots never moved, reading as "doesn't work."
|
||||||
|
Removed the dead line entirely; verified live that the `.dots` `on` class now correctly moves
|
||||||
|
with each click and no exception is thrown.
|
||||||
|
(5) **Merged the separate "Fahrzeugbilder" upload grid into "Bild der Übersicht"**, per explicit
|
||||||
|
request: pick a view from the existing "Ansicht" dropdown, then tap the (now also click-to-
|
||||||
|
upload) preview below it to upload/replace/delete that specific photo — reusing the same
|
||||||
|
generic `data-bildklick`/`bildMenuOffen` popup plumbing already used by the wheel-photo tiles,
|
||||||
|
not a new mechanism. `bildInfo()`'s existing winter-side-view special case (swaps in
|
||||||
|
`seitenansicht-winter.webp` while winter tires are marked mounted) means the winter variant
|
||||||
|
stays uploadable through the same control, gated by current tire season instead of a permanently
|
||||||
|
visible separate slot. The now-unused `BILDER_UPLOAD_SLOTS` constant and the `.bildgrid`/
|
||||||
|
`.bildslot`/`.bildslot-label`/`.carfix.mini` CSS were removed as dead code; a new
|
||||||
|
`.bildmenu.ansicht` positions the ersetzen/löschen popup anchored to the tile's *bottom* edge
|
||||||
|
(not a fixed top offset like the other two menu variants) since this preview's height varies
|
||||||
|
with the tile's own content instead of being a fixed small thumbnail.
|
||||||
|
(6) **Back arrow changed from red (`--ios-tint`) to the neutral headline color (`--fg`)** in
|
||||||
|
`audi-dashboard-ios.css`, matching every other navigation-color decision made this project (red
|
||||||
|
stays reserved for destructive actions per Apple's HIG).
|
||||||
|
Investigated but could not reproduce: user reported that hiding tab labels ("Beschriftung in der
|
||||||
|
Menüleiste" off) makes the *entire* tab bar disappear. Traced the full CSS cascade and the exact
|
||||||
|
commit that added the sixth round's icon+label highlight (`git show` on the relevant lines) —
|
||||||
|
the new rules are correctly scoped to `:not(.ohne)` and provably never touched the icon-only
|
||||||
|
path; live DOM/computed-style testing (toggle the switch, click the actual label, navigate away
|
||||||
|
and back, both mobile and desktop container widths) showed the tab bar staying visible, correctly
|
||||||
|
sized, and correctly classed in every case tried in the in-app Chromium browser. Left unchanged
|
||||||
|
pending a repro (screenshot or the exact device/browser) from the user, since no defect could be
|
||||||
|
located to fix.
|
||||||
|
Deployed to `audi_ha_test`; wheel-photo squareness, Montiert position, back-arrow color, and the
|
||||||
|
image-cycle dots all confirmed live via direct DOM/computed-style checks (no visual screenshot
|
||||||
|
tool available this session — see running note below).
|
||||||
- [ ] Fix remaining documentation drift (statistics claim, README gaps, obsolete TODO comment) —
|
- [ ] Fix remaining documentation drift (statistics claim, README gaps, obsolete TODO comment) —
|
||||||
text-only changes; INSTALL.md's WLAN/TommiG1 drift and stale variable names were fixed
|
text-only changes; INSTALL.md's WLAN/TommiG1 drift and stale variable names were fixed
|
||||||
2026-08-12 (see section B); `DESIGN_REVIEW_2026-08-13.md` and `REVIEW_main_2026-08-13.md`
|
2026-08-12 (see section B); `DESIGN_REVIEW_2026-08-13.md` and `REVIEW_main_2026-08-13.md`
|
||||||
|
|||||||
@@ -207,10 +207,6 @@ const BILDER = [
|
|||||||
];
|
];
|
||||||
let bild = 0;
|
let bild = 0;
|
||||||
const SEITE_WINTER = { label: "Auto Seite mit Winterrädern", datei: "seitenansicht-winter.webp" };
|
const SEITE_WINTER = { label: "Auto Seite mit Winterrädern", datei: "seitenansicht-winter.webp" };
|
||||||
// Alle einzeln hochladbaren Bild-Plätze (§ Fahrzeugbilder-Upload in
|
|
||||||
// Einstellungen) - dieselben festen Dateinamen wie BILDER, plus die separat
|
|
||||||
// geführte Winter-Variante der Seitenansicht.
|
|
||||||
const BILDER_UPLOAD_SLOTS = [...BILDER, { name: "Seitenansicht (Winter)", label: SEITE_WINTER.label, datei: SEITE_WINTER.datei }];
|
|
||||||
// Bei jedem Hochladen/Löschen eines Fahrzeugfotos hochgezählt und als
|
// Bei jedem Hochladen/Löschen eines Fahrzeugfotos hochgezählt und als
|
||||||
// Query-Parameter an alle bilder/-URLs gehängt (siehe bildInfo()
|
// Query-Parameter an alle bilder/-URLs gehängt (siehe bildInfo()
|
||||||
// unten) - ohne das würde der Browser nach einem Upload weiter das alte Bild
|
// unten) - ohne das würde der Browser nach einem Upload weiter das alte Bild
|
||||||
@@ -225,8 +221,9 @@ let bildVersion = Date.now();
|
|||||||
Klassen erhalten, siehe carfix/carfix.klein/radbild in audi-dashboard.css). */
|
Klassen erhalten, siehe carfix/carfix.klein/radbild in audi-dashboard.css). */
|
||||||
/* A5: Der Platzhalter nennt das Motiv und die nächste Handlung - der
|
/* A5: Der Platzhalter nennt das Motiv und die nächste Handlung - der
|
||||||
Dateiname ist Entwicklersprache und steht nur noch in den Einstellungen
|
Dateiname ist Entwicklersprache und steht nur noch in den Einstellungen
|
||||||
(siehe BILDER_UPLOAD_SLOTS). Die Maße bleiben über die CSS-Klassen erhalten,
|
(Bild der Übersicht: Ansicht wählen, dann auf das Bild tippen). Die Maße
|
||||||
das Layout springt beim Nachliefern eines Fotos nicht. */
|
bleiben über die CSS-Klassen erhalten, das Layout springt beim Nachliefern
|
||||||
|
eines Fotos nicht. */
|
||||||
function bildMitPlatzhalter(src, datei, label, klasse, imgId, dateiZeigen = false) {
|
function bildMitPlatzhalter(src, datei, label, klasse, imgId, dateiZeigen = false) {
|
||||||
const idTeil = imgId ? ` id="${imgId}"` : "";
|
const idTeil = imgId ? ` id="${imgId}"` : "";
|
||||||
return `<div class="bildbox ${klasse}" data-bildbox title="${esc(label)}">
|
return `<div class="bildbox ${klasse}" data-bildbox title="${esc(label)}">
|
||||||
@@ -294,7 +291,6 @@ function bildWeiter() {
|
|||||||
if (box) {
|
if (box) {
|
||||||
box.classList.remove("bild-fehlt"); // neues Bild kann laden, auch wenn das vorherige fehlte
|
box.classList.remove("bild-fehlt"); // neues Bild kann laden, auch wenn das vorherige fehlte
|
||||||
box.querySelector(".platzhalter-label").textContent = info.label;
|
box.querySelector(".platzhalter-label").textContent = info.label;
|
||||||
box.querySelector(".platzhalter-datei").textContent = info.datei;
|
|
||||||
}
|
}
|
||||||
const sz = ROOT.getElementById("szene");
|
const sz = ROOT.getElementById("szene");
|
||||||
if (sz) sz.className = "szene " + szeneKlasse(bild);
|
if (sz) sz.className = "szene " + szeneKlasse(bild);
|
||||||
@@ -2004,28 +2000,24 @@ function vEinst() {
|
|||||||
<div class="tile"><span class="label">Bild der Übersicht</span>
|
<div class="tile"><span class="label">Bild der Übersicht</span>
|
||||||
<div class="feld" style="border-bottom:0"><label for="startbild">Ansicht</label>
|
<div class="feld" style="border-bottom:0"><label for="startbild">Ansicht</label>
|
||||||
<select id="startbild" data-startbild>${BILDER.map((b) => `<option ${b.name === CONFIG.startbild ? "selected" : ""}>${b.name}</option>`).join("")}</select></div>
|
<select id="startbild" data-startbild>${BILDER.map((b) => `<option ${b.name === CONFIG.startbild ? "selected" : ""}>${b.name}</option>`).join("")}</select></div>
|
||||||
<div style="margin-top:16px">${(() => { const info = bildInfo(startIndex()); return bildMitPlatzhalter(info.src, info.datei, info.label, "carfix"); })()}</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile"><span class="label">Fahrzeugbilder</span>
|
|
||||||
<span class="label" style="margin-top:10px;color:var(--fg2);letter-spacing:0;
|
<span class="label" style="margin-top:10px;color:var(--fg2);letter-spacing:0;
|
||||||
text-transform:none;font-size:12.5px;line-height:1.6">
|
text-transform:none;font-size:12.5px;line-height:1.6">
|
||||||
Auf ein Bild tippen, um ein eigenes Foto hochzuladen oder zu ersetzen.</span>
|
Auf das Bild tippen, um für diese Ansicht ein eigenes Foto hochzuladen oder zu ersetzen.</span>
|
||||||
<div class="bildgrid">
|
${(() => {
|
||||||
${BILDER_UPLOAD_SLOTS.map((s) => `
|
const info = bildInfo(startIndex());
|
||||||
<div class="bildslot">
|
return `<div style="margin-top:12px">
|
||||||
<div data-bildklick="${esc(s.datei)}">
|
<div data-bildklick="${esc(info.datei)}">
|
||||||
${bildMitPlatzhalter(`/local/bilder/${s.datei}?v=${bildVersion}`, s.datei, s.label, "carfix mini", null, true)}
|
${bildMitPlatzhalter(info.src, info.datei, info.label, "carfix", null, true)}
|
||||||
</div>
|
</div>
|
||||||
<input type="file" accept="image/*" hidden data-bildupload="${esc(s.datei)}">
|
<input type="file" accept="image/*" hidden data-bildupload="${esc(info.datei)}">
|
||||||
<span class="bildslot-label">${esc(s.name)}</span>
|
${bildMenuOffen === info.datei ? `
|
||||||
${bildMenuOffen === s.datei ? `
|
<div class="bildmenu-catcher" data-bildmenu-schliessen></div>
|
||||||
<div class="bildmenu-catcher" data-bildmenu-schliessen></div>
|
<div class="bildmenu ansicht">
|
||||||
<div class="bildmenu slot">
|
<button type="button" data-bildersetzen="${esc(info.datei)}">Foto ersetzen</button>
|
||||||
<button type="button" data-bildersetzen="${esc(s.datei)}">Foto ersetzen</button>
|
<button type="button" class="loeschen" data-bildloeschen="${esc(info.datei)}">Löschen</button>
|
||||||
<button type="button" class="loeschen" data-bildloeschen="${esc(s.datei)}">Löschen</button>
|
</div>` : ""}
|
||||||
</div>` : ""}
|
</div>`;
|
||||||
</div>`).join("")}
|
})()}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tile"><span class="label">Kraftstoff-Rabatt</span>
|
<div class="tile"><span class="label">Kraftstoff-Rabatt</span>
|
||||||
<div class="feld"><label for="sdAktiv" style="display:flex;align-items:center;gap:6px">
|
<div class="feld"><label for="sdAktiv" style="display:flex;align-items:center;gap:6px">
|
||||||
@@ -3563,7 +3555,7 @@ function ereignisseVerdrahten() {
|
|||||||
if (bildKlick) {
|
if (bildKlick) {
|
||||||
const dateiname = bildKlick.dataset.bildklick;
|
const dateiname = bildKlick.dataset.bildklick;
|
||||||
const box = bildKlick.querySelector(".bildbox");
|
const box = bildKlick.querySelector(".bildbox");
|
||||||
const container = bildKlick.closest(".tile, .bildslot");
|
const container = bildKlick.closest(".tile");
|
||||||
if (box && box.classList.contains("bild-fehlt")) {
|
if (box && box.classList.contains("bild-fehlt")) {
|
||||||
const input = container.querySelector(`[data-bildupload="${dateiname}"]`);
|
const input = container.querySelector(`[data-bildupload="${dateiname}"]`);
|
||||||
if (input) input.click();
|
if (input) input.click();
|
||||||
@@ -3575,7 +3567,7 @@ function ereignisseVerdrahten() {
|
|||||||
if (e.target.closest("[data-bildmenu-schliessen]")) { bildMenuOffen = null; render(); return; }
|
if (e.target.closest("[data-bildmenu-schliessen]")) { bildMenuOffen = null; render(); return; }
|
||||||
const bildErsetzen = e.target.closest("[data-bildersetzen]");
|
const bildErsetzen = e.target.closest("[data-bildersetzen]");
|
||||||
if (bildErsetzen) {
|
if (bildErsetzen) {
|
||||||
const container = bildErsetzen.closest(".tile, .bildslot");
|
const container = bildErsetzen.closest(".tile");
|
||||||
const input = container.querySelector(`[data-bildupload="${bildErsetzen.dataset.bildersetzen}"]`);
|
const input = container.querySelector(`[data-bildupload="${bildErsetzen.dataset.bildersetzen}"]`);
|
||||||
if (input) input.click();
|
if (input) input.click();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -26,6 +26,11 @@
|
|||||||
--line-strong:rgba(255,255,255,.24);
|
--line-strong:rgba(255,255,255,.24);
|
||||||
--fg:#FFFFFF; --fg2:#BFC4CC; --fg3:#8E8E93;
|
--fg:#FFFFFF; --fg2:#BFC4CC; --fg3:#8E8E93;
|
||||||
--ok:#30D158; --warn:#FFD60A; --bad:#FF453A;
|
--ok:#30D158; --warn:#FFD60A; --bad:#FF453A;
|
||||||
|
/* Ohne diese Angabe rendert der Browser native Steuerelemente (Dropdown-
|
||||||
|
Aufklapp-Liste bei <select>, Scrollbars) in seiner Standard-Hellansicht,
|
||||||
|
egal wie dunkel die App selbst ist - das liess z. B. "Modell" beim
|
||||||
|
Aufklappen grell-weiss aufblitzen. Betrifft alle <select>-Felder. */
|
||||||
|
color-scheme: dark;
|
||||||
}
|
}
|
||||||
:host([data-theme="tag"]){
|
:host([data-theme="tag"]){
|
||||||
--canvas:#F2F2F7;
|
--canvas:#F2F2F7;
|
||||||
@@ -38,6 +43,7 @@
|
|||||||
--ios-sep:rgba(60,60,67,.16);
|
--ios-sep:rgba(60,60,67,.16);
|
||||||
--ios-fill:rgba(120,120,128,.16);
|
--ios-fill:rgba(120,120,128,.16);
|
||||||
--tile-deckend:#FFFFFF;
|
--tile-deckend:#FFFFFF;
|
||||||
|
color-scheme: light;
|
||||||
}
|
}
|
||||||
|
|
||||||
body{padding:0;background:var(--canvas)}
|
body{padding:0;background:var(--canvas)}
|
||||||
@@ -67,7 +73,10 @@ html,body{height:100%}
|
|||||||
.eyebrow{display:none}
|
.eyebrow{display:none}
|
||||||
.title{font-size:22px;font-weight:400;letter-spacing:-.01em;line-height:1.2}
|
.title{font-size:22px;font-weight:400;letter-spacing:-.01em;line-height:1.2}
|
||||||
.back{width:34px;height:34px;margin-left:-8px;justify-content:center}
|
.back{width:34px;height:34px;margin-left:-8px;justify-content:center}
|
||||||
.back svg{width:22px;height:22px;color:var(--ios-tint)}
|
/* Rot bleibt Akzent/destruktiv, nicht Navigationsfarbe (dieselbe Regel wie
|
||||||
|
bei den Aktions-Buttons und dem aktiven Menü-Icon) - derselbe neutrale Ton
|
||||||
|
wie die Kopfzeile selbst. */
|
||||||
|
.back svg{width:22px;height:22px;color:var(--fg)}
|
||||||
.sync{margin-top:3px;font-size:12.5px;color:var(--fg3)}
|
.sync{margin-top:3px;font-size:12.5px;color:var(--fg3)}
|
||||||
.sync svg{width:13px;height:13px}
|
.sync svg{width:13px;height:13px}
|
||||||
.themebtn{width:36px;height:36px;border:0;background:var(--ios-fill);color:var(--fg2)}
|
.themebtn{width:36px;height:36px;border:0;background:var(--ios-fill);color:var(--fg2)}
|
||||||
|
|||||||
@@ -442,11 +442,15 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
.carbox { position: relative; }
|
.carbox { position: relative; }
|
||||||
.carfix { width: 100%; aspect-ratio: 16 / 9; }
|
.carfix { width: 100%; aspect-ratio: 16 / 9; }
|
||||||
.carfix.klein { aspect-ratio: 16 / 8; }
|
.carfix.klein { aspect-ratio: 16 / 8; }
|
||||||
.carfix.mini { width: 78px; height: 78px; aspect-ratio: auto; }
|
|
||||||
/* Reifenfoto ist oft eine breite Aufnahme; statt beide Ränder symmetrisch
|
/* Reifenfoto ist oft eine breite Aufnahme; statt beide Ränder symmetrisch
|
||||||
wegzuschneiden (object-fit:cover-Standard), bleibt bewusst der rechte Rand
|
wegzuschneiden (object-fit:cover-Standard), bleibt bewusst der rechte Rand
|
||||||
des Originalfotos erhalten - dort sitzt das Rad meist im Bild. */
|
des Originalfotos erhalten - dort sitzt das Rad meist im Bild. */
|
||||||
.radbild { width: 96px; height: 96px; aspect-ratio: auto; border-radius: 50%; object-position: right center; }
|
.radbild { object-position: right center; }
|
||||||
|
/* .bildbox.radbild statt .radbild allein: .bildbox unten setzt width/aspect-
|
||||||
|
ratio auf derselben Spezifitaet (eine Klasse) und gewinnt als spaeter
|
||||||
|
notierte Regel sonst automatisch - die Box blieb dadurch bislang die volle
|
||||||
|
Kachelbreite im 4:3-Format statt eines echten 96x96-Quadrats. */
|
||||||
|
.bildbox.radbild { width: 96px; height: 96px; aspect-ratio: 1 / 1; }
|
||||||
|
|
||||||
.bildbox { position: relative; width: 100%; aspect-ratio: 4 / 3; border-radius: 12px; overflow: hidden; }
|
.bildbox { position: relative; width: 100%; aspect-ratio: 4 / 3; border-radius: 12px; overflow: hidden; }
|
||||||
.bildbox img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
.bildbox img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
||||||
@@ -458,7 +462,6 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
App. Mit Foto gilt wieder das volle Seitenverhältnis. */
|
App. Mit Foto gilt wieder das volle Seitenverhältnis. */
|
||||||
.bildbox.bild-fehlt.carfix { aspect-ratio: auto; height: 132px; }
|
.bildbox.bild-fehlt.carfix { aspect-ratio: auto; height: 132px; }
|
||||||
.bildbox.bild-fehlt.carfix.klein { height: 120px; }
|
.bildbox.bild-fehlt.carfix.klein { height: 120px; }
|
||||||
.bildbox.bild-fehlt.carfix.mini { height: 78px; }
|
|
||||||
.szene.bleed:has(.bild-fehlt)::before { display: none; }
|
.szene.bleed:has(.bild-fehlt)::before { display: none; }
|
||||||
.szene.bleed:has(.bild-fehlt) { margin-left: 0; margin-right: 0; }
|
.szene.bleed:has(.bild-fehlt) { margin-left: 0; margin-right: 0; }
|
||||||
.szene.bleed:has(.bild-fehlt) .carbox { padding: 0; }
|
.szene.bleed:has(.bild-fehlt) .carbox { padding: 0; }
|
||||||
@@ -840,9 +843,6 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
.standort-pille[disabled] { opacity: .4; pointer-events: none; }
|
.standort-pille[disabled] { opacity: .4; pointer-events: none; }
|
||||||
|
|
||||||
/* ------------------------------------------------------- Bilderverwaltung */
|
/* ------------------------------------------------------- Bilderverwaltung */
|
||||||
.bildgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-4); margin-top: var(--sp-4); }
|
|
||||||
.bildslot { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; }
|
|
||||||
.bildslot-label { font-size: 11.5px; letter-spacing: normal; color: var(--fg2); text-align: center; }
|
|
||||||
.bildmenu-catcher { position: fixed; inset: 0; z-index: 1000; }
|
.bildmenu-catcher { position: fixed; inset: 0; z-index: 1000; }
|
||||||
.bildmenu {
|
.bildmenu {
|
||||||
position: absolute; z-index: 1001;
|
position: absolute; z-index: 1001;
|
||||||
@@ -852,8 +852,12 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
display: flex; flex-direction: column;
|
display: flex; flex-direction: column;
|
||||||
min-width: 160px;
|
min-width: 160px;
|
||||||
}
|
}
|
||||||
.bildmenu.slot { top: 60px; left: 50%; transform: translateX(-50%); }
|
|
||||||
.bildmenu.rad { top: 90px; left: 22px; }
|
.bildmenu.rad { top: 90px; left: 22px; }
|
||||||
|
/* "Bild der Übersicht": das Vorschaubild füllt die ganze Kachelbreite, seine
|
||||||
|
Unterkante liegt daher immer nah an der Kachel-Unterkante - das Menü von
|
||||||
|
dort aus verankern statt mit einem festen top-Wert, der bei jedem
|
||||||
|
Bildseitenverhältnis neu nachgemessen werden müsste. */
|
||||||
|
.bildmenu.ansicht { bottom: var(--sp-5); left: 50%; transform: translateX(-50%); }
|
||||||
.bildmenu button {
|
.bildmenu button {
|
||||||
display: block; width: 100%; text-align: left;
|
display: block; width: 100%; text-align: left;
|
||||||
background: none; border: none;
|
background: none; border: none;
|
||||||
@@ -874,12 +878,12 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
|
|
||||||
.radkopf { display: flex; flex-direction: column; margin-top: var(--sp-4); }
|
.radkopf { display: flex; flex-direction: column; margin-top: var(--sp-4); }
|
||||||
|
|
||||||
/* Kompakte Pille statt voller Breite (Apple-HIG-Pull-down-Maß): oben rechts
|
/* Kompakte Pille statt voller Breite (Apple-HIG-Pull-down-Maß): oben links
|
||||||
in der Kachel, obere Kante auf Höhe des Radfotos, rechter Abstand
|
in der Kachel, obere Kante auf Höhe des Radfotos, linker Abstand
|
||||||
identisch zum linken Texteinzug (beides var(--sp-5), die Kachel-Innen-
|
identisch zum Texteinzug (beides var(--sp-5), die Kachel-Innen-
|
||||||
polsterung). */
|
polsterung). */
|
||||||
.montiert {
|
.montiert {
|
||||||
position: absolute; top: var(--sp-5); right: var(--sp-5);
|
position: absolute; top: var(--sp-5); left: var(--sp-5);
|
||||||
display: inline-flex; align-items: center; justify-content: center;
|
display: inline-flex; align-items: center; justify-content: center;
|
||||||
font-family: inherit; font-size: 12px; letter-spacing: normal;
|
font-family: inherit; font-size: 12px; letter-spacing: normal;
|
||||||
color: var(--fg2);
|
color: var(--fg2);
|
||||||
|
|||||||
@@ -207,10 +207,6 @@ const BILDER = [
|
|||||||
];
|
];
|
||||||
let bild = 0;
|
let bild = 0;
|
||||||
const SEITE_WINTER = { label: "Auto Seite mit Winterrädern", datei: "seitenansicht-winter.webp" };
|
const SEITE_WINTER = { label: "Auto Seite mit Winterrädern", datei: "seitenansicht-winter.webp" };
|
||||||
// Alle einzeln hochladbaren Bild-Plätze (§ Fahrzeugbilder-Upload in
|
|
||||||
// Einstellungen) - dieselben festen Dateinamen wie BILDER, plus die separat
|
|
||||||
// geführte Winter-Variante der Seitenansicht.
|
|
||||||
const BILDER_UPLOAD_SLOTS = [...BILDER, { name: "Seitenansicht (Winter)", label: SEITE_WINTER.label, datei: SEITE_WINTER.datei }];
|
|
||||||
// Bei jedem Hochladen/Löschen eines Fahrzeugfotos hochgezählt und als
|
// Bei jedem Hochladen/Löschen eines Fahrzeugfotos hochgezählt und als
|
||||||
// Query-Parameter an alle bilder/-URLs gehängt (siehe bildInfo()
|
// Query-Parameter an alle bilder/-URLs gehängt (siehe bildInfo()
|
||||||
// unten) - ohne das würde der Browser nach einem Upload weiter das alte Bild
|
// unten) - ohne das würde der Browser nach einem Upload weiter das alte Bild
|
||||||
@@ -225,8 +221,9 @@ let bildVersion = Date.now();
|
|||||||
Klassen erhalten, siehe carfix/carfix.klein/radbild in audi-dashboard.css). */
|
Klassen erhalten, siehe carfix/carfix.klein/radbild in audi-dashboard.css). */
|
||||||
/* A5: Der Platzhalter nennt das Motiv und die nächste Handlung - der
|
/* A5: Der Platzhalter nennt das Motiv und die nächste Handlung - der
|
||||||
Dateiname ist Entwicklersprache und steht nur noch in den Einstellungen
|
Dateiname ist Entwicklersprache und steht nur noch in den Einstellungen
|
||||||
(siehe BILDER_UPLOAD_SLOTS). Die Maße bleiben über die CSS-Klassen erhalten,
|
(Bild der Übersicht: Ansicht wählen, dann auf das Bild tippen). Die Maße
|
||||||
das Layout springt beim Nachliefern eines Fotos nicht. */
|
bleiben über die CSS-Klassen erhalten, das Layout springt beim Nachliefern
|
||||||
|
eines Fotos nicht. */
|
||||||
function bildMitPlatzhalter(src, datei, label, klasse, imgId, dateiZeigen = false) {
|
function bildMitPlatzhalter(src, datei, label, klasse, imgId, dateiZeigen = false) {
|
||||||
const idTeil = imgId ? ` id="${imgId}"` : "";
|
const idTeil = imgId ? ` id="${imgId}"` : "";
|
||||||
return `<div class="bildbox ${klasse}" data-bildbox title="${esc(label)}">
|
return `<div class="bildbox ${klasse}" data-bildbox title="${esc(label)}">
|
||||||
@@ -294,7 +291,6 @@ function bildWeiter() {
|
|||||||
if (box) {
|
if (box) {
|
||||||
box.classList.remove("bild-fehlt"); // neues Bild kann laden, auch wenn das vorherige fehlte
|
box.classList.remove("bild-fehlt"); // neues Bild kann laden, auch wenn das vorherige fehlte
|
||||||
box.querySelector(".platzhalter-label").textContent = info.label;
|
box.querySelector(".platzhalter-label").textContent = info.label;
|
||||||
box.querySelector(".platzhalter-datei").textContent = info.datei;
|
|
||||||
}
|
}
|
||||||
const sz = ROOT.getElementById("szene");
|
const sz = ROOT.getElementById("szene");
|
||||||
if (sz) sz.className = "szene " + szeneKlasse(bild);
|
if (sz) sz.className = "szene " + szeneKlasse(bild);
|
||||||
@@ -2004,28 +2000,24 @@ function vEinst() {
|
|||||||
<div class="tile"><span class="label">Bild der Übersicht</span>
|
<div class="tile"><span class="label">Bild der Übersicht</span>
|
||||||
<div class="feld" style="border-bottom:0"><label for="startbild">Ansicht</label>
|
<div class="feld" style="border-bottom:0"><label for="startbild">Ansicht</label>
|
||||||
<select id="startbild" data-startbild>${BILDER.map((b) => `<option ${b.name === CONFIG.startbild ? "selected" : ""}>${b.name}</option>`).join("")}</select></div>
|
<select id="startbild" data-startbild>${BILDER.map((b) => `<option ${b.name === CONFIG.startbild ? "selected" : ""}>${b.name}</option>`).join("")}</select></div>
|
||||||
<div style="margin-top:16px">${(() => { const info = bildInfo(startIndex()); return bildMitPlatzhalter(info.src, info.datei, info.label, "carfix"); })()}</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile"><span class="label">Fahrzeugbilder</span>
|
|
||||||
<span class="label" style="margin-top:10px;color:var(--fg2);letter-spacing:0;
|
<span class="label" style="margin-top:10px;color:var(--fg2);letter-spacing:0;
|
||||||
text-transform:none;font-size:12.5px;line-height:1.6">
|
text-transform:none;font-size:12.5px;line-height:1.6">
|
||||||
Auf ein Bild tippen, um ein eigenes Foto hochzuladen oder zu ersetzen.</span>
|
Auf das Bild tippen, um für diese Ansicht ein eigenes Foto hochzuladen oder zu ersetzen.</span>
|
||||||
<div class="bildgrid">
|
${(() => {
|
||||||
${BILDER_UPLOAD_SLOTS.map((s) => `
|
const info = bildInfo(startIndex());
|
||||||
<div class="bildslot">
|
return `<div style="margin-top:12px">
|
||||||
<div data-bildklick="${esc(s.datei)}">
|
<div data-bildklick="${esc(info.datei)}">
|
||||||
${bildMitPlatzhalter(`/local/bilder/${s.datei}?v=${bildVersion}`, s.datei, s.label, "carfix mini", null, true)}
|
${bildMitPlatzhalter(info.src, info.datei, info.label, "carfix", null, true)}
|
||||||
</div>
|
</div>
|
||||||
<input type="file" accept="image/*" hidden data-bildupload="${esc(s.datei)}">
|
<input type="file" accept="image/*" hidden data-bildupload="${esc(info.datei)}">
|
||||||
<span class="bildslot-label">${esc(s.name)}</span>
|
${bildMenuOffen === info.datei ? `
|
||||||
${bildMenuOffen === s.datei ? `
|
<div class="bildmenu-catcher" data-bildmenu-schliessen></div>
|
||||||
<div class="bildmenu-catcher" data-bildmenu-schliessen></div>
|
<div class="bildmenu ansicht">
|
||||||
<div class="bildmenu slot">
|
<button type="button" data-bildersetzen="${esc(info.datei)}">Foto ersetzen</button>
|
||||||
<button type="button" data-bildersetzen="${esc(s.datei)}">Foto ersetzen</button>
|
<button type="button" class="loeschen" data-bildloeschen="${esc(info.datei)}">Löschen</button>
|
||||||
<button type="button" class="loeschen" data-bildloeschen="${esc(s.datei)}">Löschen</button>
|
</div>` : ""}
|
||||||
</div>` : ""}
|
</div>`;
|
||||||
</div>`).join("")}
|
})()}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tile"><span class="label">Kraftstoff-Rabatt</span>
|
<div class="tile"><span class="label">Kraftstoff-Rabatt</span>
|
||||||
<div class="feld"><label for="sdAktiv" style="display:flex;align-items:center;gap:6px">
|
<div class="feld"><label for="sdAktiv" style="display:flex;align-items:center;gap:6px">
|
||||||
@@ -3563,7 +3555,7 @@ function ereignisseVerdrahten() {
|
|||||||
if (bildKlick) {
|
if (bildKlick) {
|
||||||
const dateiname = bildKlick.dataset.bildklick;
|
const dateiname = bildKlick.dataset.bildklick;
|
||||||
const box = bildKlick.querySelector(".bildbox");
|
const box = bildKlick.querySelector(".bildbox");
|
||||||
const container = bildKlick.closest(".tile, .bildslot");
|
const container = bildKlick.closest(".tile");
|
||||||
if (box && box.classList.contains("bild-fehlt")) {
|
if (box && box.classList.contains("bild-fehlt")) {
|
||||||
const input = container.querySelector(`[data-bildupload="${dateiname}"]`);
|
const input = container.querySelector(`[data-bildupload="${dateiname}"]`);
|
||||||
if (input) input.click();
|
if (input) input.click();
|
||||||
@@ -3575,7 +3567,7 @@ function ereignisseVerdrahten() {
|
|||||||
if (e.target.closest("[data-bildmenu-schliessen]")) { bildMenuOffen = null; render(); return; }
|
if (e.target.closest("[data-bildmenu-schliessen]")) { bildMenuOffen = null; render(); return; }
|
||||||
const bildErsetzen = e.target.closest("[data-bildersetzen]");
|
const bildErsetzen = e.target.closest("[data-bildersetzen]");
|
||||||
if (bildErsetzen) {
|
if (bildErsetzen) {
|
||||||
const container = bildErsetzen.closest(".tile, .bildslot");
|
const container = bildErsetzen.closest(".tile");
|
||||||
const input = container.querySelector(`[data-bildupload="${bildErsetzen.dataset.bildersetzen}"]`);
|
const input = container.querySelector(`[data-bildupload="${bildErsetzen.dataset.bildersetzen}"]`);
|
||||||
if (input) input.click();
|
if (input) input.click();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -26,6 +26,11 @@
|
|||||||
--line-strong:rgba(255,255,255,.24);
|
--line-strong:rgba(255,255,255,.24);
|
||||||
--fg:#FFFFFF; --fg2:#BFC4CC; --fg3:#8E8E93;
|
--fg:#FFFFFF; --fg2:#BFC4CC; --fg3:#8E8E93;
|
||||||
--ok:#30D158; --warn:#FFD60A; --bad:#FF453A;
|
--ok:#30D158; --warn:#FFD60A; --bad:#FF453A;
|
||||||
|
/* Ohne diese Angabe rendert der Browser native Steuerelemente (Dropdown-
|
||||||
|
Aufklapp-Liste bei <select>, Scrollbars) in seiner Standard-Hellansicht,
|
||||||
|
egal wie dunkel die App selbst ist - das liess z. B. "Modell" beim
|
||||||
|
Aufklappen grell-weiss aufblitzen. Betrifft alle <select>-Felder. */
|
||||||
|
color-scheme: dark;
|
||||||
}
|
}
|
||||||
:host([data-theme="tag"]){
|
:host([data-theme="tag"]){
|
||||||
--canvas:#F2F2F7;
|
--canvas:#F2F2F7;
|
||||||
@@ -38,6 +43,7 @@
|
|||||||
--ios-sep:rgba(60,60,67,.16);
|
--ios-sep:rgba(60,60,67,.16);
|
||||||
--ios-fill:rgba(120,120,128,.16);
|
--ios-fill:rgba(120,120,128,.16);
|
||||||
--tile-deckend:#FFFFFF;
|
--tile-deckend:#FFFFFF;
|
||||||
|
color-scheme: light;
|
||||||
}
|
}
|
||||||
|
|
||||||
body{padding:0;background:var(--canvas)}
|
body{padding:0;background:var(--canvas)}
|
||||||
@@ -67,7 +73,10 @@ html,body{height:100%}
|
|||||||
.eyebrow{display:none}
|
.eyebrow{display:none}
|
||||||
.title{font-size:22px;font-weight:400;letter-spacing:-.01em;line-height:1.2}
|
.title{font-size:22px;font-weight:400;letter-spacing:-.01em;line-height:1.2}
|
||||||
.back{width:34px;height:34px;margin-left:-8px;justify-content:center}
|
.back{width:34px;height:34px;margin-left:-8px;justify-content:center}
|
||||||
.back svg{width:22px;height:22px;color:var(--ios-tint)}
|
/* Rot bleibt Akzent/destruktiv, nicht Navigationsfarbe (dieselbe Regel wie
|
||||||
|
bei den Aktions-Buttons und dem aktiven Menü-Icon) - derselbe neutrale Ton
|
||||||
|
wie die Kopfzeile selbst. */
|
||||||
|
.back svg{width:22px;height:22px;color:var(--fg)}
|
||||||
.sync{margin-top:3px;font-size:12.5px;color:var(--fg3)}
|
.sync{margin-top:3px;font-size:12.5px;color:var(--fg3)}
|
||||||
.sync svg{width:13px;height:13px}
|
.sync svg{width:13px;height:13px}
|
||||||
.themebtn{width:36px;height:36px;border:0;background:var(--ios-fill);color:var(--fg2)}
|
.themebtn{width:36px;height:36px;border:0;background:var(--ios-fill);color:var(--fg2)}
|
||||||
|
|||||||
@@ -442,11 +442,15 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
.carbox { position: relative; }
|
.carbox { position: relative; }
|
||||||
.carfix { width: 100%; aspect-ratio: 16 / 9; }
|
.carfix { width: 100%; aspect-ratio: 16 / 9; }
|
||||||
.carfix.klein { aspect-ratio: 16 / 8; }
|
.carfix.klein { aspect-ratio: 16 / 8; }
|
||||||
.carfix.mini { width: 78px; height: 78px; aspect-ratio: auto; }
|
|
||||||
/* Reifenfoto ist oft eine breite Aufnahme; statt beide Ränder symmetrisch
|
/* Reifenfoto ist oft eine breite Aufnahme; statt beide Ränder symmetrisch
|
||||||
wegzuschneiden (object-fit:cover-Standard), bleibt bewusst der rechte Rand
|
wegzuschneiden (object-fit:cover-Standard), bleibt bewusst der rechte Rand
|
||||||
des Originalfotos erhalten - dort sitzt das Rad meist im Bild. */
|
des Originalfotos erhalten - dort sitzt das Rad meist im Bild. */
|
||||||
.radbild { width: 96px; height: 96px; aspect-ratio: auto; border-radius: 50%; object-position: right center; }
|
.radbild { object-position: right center; }
|
||||||
|
/* .bildbox.radbild statt .radbild allein: .bildbox unten setzt width/aspect-
|
||||||
|
ratio auf derselben Spezifitaet (eine Klasse) und gewinnt als spaeter
|
||||||
|
notierte Regel sonst automatisch - die Box blieb dadurch bislang die volle
|
||||||
|
Kachelbreite im 4:3-Format statt eines echten 96x96-Quadrats. */
|
||||||
|
.bildbox.radbild { width: 96px; height: 96px; aspect-ratio: 1 / 1; }
|
||||||
|
|
||||||
.bildbox { position: relative; width: 100%; aspect-ratio: 4 / 3; border-radius: 12px; overflow: hidden; }
|
.bildbox { position: relative; width: 100%; aspect-ratio: 4 / 3; border-radius: 12px; overflow: hidden; }
|
||||||
.bildbox img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
.bildbox img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
||||||
@@ -458,7 +462,6 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
App. Mit Foto gilt wieder das volle Seitenverhältnis. */
|
App. Mit Foto gilt wieder das volle Seitenverhältnis. */
|
||||||
.bildbox.bild-fehlt.carfix { aspect-ratio: auto; height: 132px; }
|
.bildbox.bild-fehlt.carfix { aspect-ratio: auto; height: 132px; }
|
||||||
.bildbox.bild-fehlt.carfix.klein { height: 120px; }
|
.bildbox.bild-fehlt.carfix.klein { height: 120px; }
|
||||||
.bildbox.bild-fehlt.carfix.mini { height: 78px; }
|
|
||||||
.szene.bleed:has(.bild-fehlt)::before { display: none; }
|
.szene.bleed:has(.bild-fehlt)::before { display: none; }
|
||||||
.szene.bleed:has(.bild-fehlt) { margin-left: 0; margin-right: 0; }
|
.szene.bleed:has(.bild-fehlt) { margin-left: 0; margin-right: 0; }
|
||||||
.szene.bleed:has(.bild-fehlt) .carbox { padding: 0; }
|
.szene.bleed:has(.bild-fehlt) .carbox { padding: 0; }
|
||||||
@@ -840,9 +843,6 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
.standort-pille[disabled] { opacity: .4; pointer-events: none; }
|
.standort-pille[disabled] { opacity: .4; pointer-events: none; }
|
||||||
|
|
||||||
/* ------------------------------------------------------- Bilderverwaltung */
|
/* ------------------------------------------------------- Bilderverwaltung */
|
||||||
.bildgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-4); margin-top: var(--sp-4); }
|
|
||||||
.bildslot { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; }
|
|
||||||
.bildslot-label { font-size: 11.5px; letter-spacing: normal; color: var(--fg2); text-align: center; }
|
|
||||||
.bildmenu-catcher { position: fixed; inset: 0; z-index: 1000; }
|
.bildmenu-catcher { position: fixed; inset: 0; z-index: 1000; }
|
||||||
.bildmenu {
|
.bildmenu {
|
||||||
position: absolute; z-index: 1001;
|
position: absolute; z-index: 1001;
|
||||||
@@ -852,8 +852,12 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
display: flex; flex-direction: column;
|
display: flex; flex-direction: column;
|
||||||
min-width: 160px;
|
min-width: 160px;
|
||||||
}
|
}
|
||||||
.bildmenu.slot { top: 60px; left: 50%; transform: translateX(-50%); }
|
|
||||||
.bildmenu.rad { top: 90px; left: 22px; }
|
.bildmenu.rad { top: 90px; left: 22px; }
|
||||||
|
/* "Bild der Übersicht": das Vorschaubild füllt die ganze Kachelbreite, seine
|
||||||
|
Unterkante liegt daher immer nah an der Kachel-Unterkante - das Menü von
|
||||||
|
dort aus verankern statt mit einem festen top-Wert, der bei jedem
|
||||||
|
Bildseitenverhältnis neu nachgemessen werden müsste. */
|
||||||
|
.bildmenu.ansicht { bottom: var(--sp-5); left: 50%; transform: translateX(-50%); }
|
||||||
.bildmenu button {
|
.bildmenu button {
|
||||||
display: block; width: 100%; text-align: left;
|
display: block; width: 100%; text-align: left;
|
||||||
background: none; border: none;
|
background: none; border: none;
|
||||||
@@ -874,12 +878,12 @@ button.tile, .tilebtn { transition: background .15s, transform .1s; }
|
|||||||
|
|
||||||
.radkopf { display: flex; flex-direction: column; margin-top: var(--sp-4); }
|
.radkopf { display: flex; flex-direction: column; margin-top: var(--sp-4); }
|
||||||
|
|
||||||
/* Kompakte Pille statt voller Breite (Apple-HIG-Pull-down-Maß): oben rechts
|
/* Kompakte Pille statt voller Breite (Apple-HIG-Pull-down-Maß): oben links
|
||||||
in der Kachel, obere Kante auf Höhe des Radfotos, rechter Abstand
|
in der Kachel, obere Kante auf Höhe des Radfotos, linker Abstand
|
||||||
identisch zum linken Texteinzug (beides var(--sp-5), die Kachel-Innen-
|
identisch zum Texteinzug (beides var(--sp-5), die Kachel-Innen-
|
||||||
polsterung). */
|
polsterung). */
|
||||||
.montiert {
|
.montiert {
|
||||||
position: absolute; top: var(--sp-5); right: var(--sp-5);
|
position: absolute; top: var(--sp-5); left: var(--sp-5);
|
||||||
display: inline-flex; align-items: center; justify-content: center;
|
display: inline-flex; align-items: center; justify-content: center;
|
||||||
font-family: inherit; font-size: 12px; letter-spacing: normal;
|
font-family: inherit; font-size: 12px; letter-spacing: normal;
|
||||||
color: var(--fg2);
|
color: var(--fg2);
|
||||||
|
|||||||
Reference in New Issue
Block a user