@charset "utf-8";
/* ==========================================================================
   Libretto Design System  —  "Editorial x Instrument"
   Cascade layers: reset < tokens < base < components.
   Fully self-contained: a compact element reset in the reset layer, design
   tokens (colours, type, spacing, radius, timing) in the tokens layer, and the
   base/component styles below. No external stylesheet or framework is loaded.
   Bulk component styles below stay unlayered, so they keep authority over this
   baseline. Self-hosted fonts; OS light/dark via light-dark().
   ========================================================================== */
@layer reset, tokens, base, components;

@layer reset {
	/* Compact cross-browser element reset (box-sizing, margin, border defaults,
	   media block-sizing, form-control inheritance). Zero-specificity :where()
	   selectors keep every app rule in charge; no external stylesheet required. */
	*, ::before, ::after { box-sizing: border-box; }
	:where(:not(dialog)) { margin: 0; }
	:where(:not(fieldset, progress, meter)) {
		background-origin: border-box;
		background-repeat: no-repeat;
		border-style: solid;
		border-width: 0;
	}
	:where(html) { -webkit-text-size-adjust: none; }
	:where(body) { min-block-size: 100%; }
	@media (prefers-reduced-motion: no-preference) {
		:where(html) { scroll-behavior: smooth; }
	}
	:where(h1, h2, h3, h4, h5, h6) { text-wrap: balance; }
	:where(p) { text-wrap: pretty; }
	:where(img, svg, video, canvas, audio, iframe, embed, object) { display: block; }
	:where(img, svg, video) { max-inline-size: 100%; block-size: auto; }
	:where(input, button, textarea, select) { color: inherit; font: inherit; letter-spacing: inherit; }
	:where(textarea) { resize: vertical; }
	::placeholder { color: var(--text-4); opacity: 0.75; }
}

/* ── Self-hosted typefaces (woff2, OFL) ─────────────────────────────────── */
@font-face {
	font-family: "Inter Variable"; font-style: normal; font-weight: 100 900;
	font-display: swap; src: url("/static/fonts/inter-latin-wght-normal.woff2") format("woff2-variations");
	unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
	font-family: "Inter Variable"; font-style: normal; font-weight: 100 900;
	font-display: swap; src: url("/static/fonts/inter-latin-ext-wght-normal.woff2") format("woff2-variations");
	unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
	font-family: "Playfair Display Variable"; font-style: normal; font-weight: 400 900;
	font-display: swap; src: url("/static/fonts/playfair-display-latin-wght-normal.woff2") format("woff2-variations");
	unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
	font-family: "Playfair Display Variable"; font-style: normal; font-weight: 400 900;
	font-display: swap; src: url("/static/fonts/playfair-display-latin-ext-wght-normal.woff2") format("woff2-variations");
	unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
	font-family: "Playfair Display Variable"; font-style: italic; font-weight: 400 900;
	font-display: swap; src: url("/static/fonts/playfair-display-latin-wght-italic.woff2") format("woff2-variations");
	unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
	font-family: "Playfair Display Variable"; font-style: italic; font-weight: 400 900;
	font-display: swap; src: url("/static/fonts/playfair-display-latin-ext-wght-italic.woff2") format("woff2-variations");
	unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
	font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400;
	font-display: swap; src: url("/static/fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2");
	unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
	font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400;
	font-display: swap; src: url("/static/fonts/ibm-plex-mono-latin-ext-400-normal.woff2") format("woff2");
	unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+1E00-1E9F,U+2020,U+20A0-20AB,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
	font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600;
	font-display: swap; src: url("/static/fonts/ibm-plex-mono-latin-600-normal.woff2") format("woff2");
	unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@layer base {
	* { box-sizing: border-box; }
	input::-webkit-outer-spin-button,
	input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
	input[type=number] { -moz-appearance: textfield; appearance: textfield; }
	select option { background: var(--surface-raised); color: var(--text); }

	/* Prose / content links default to the accent colour with a legible
	   underline. Lives in @layer base (the lowest tier), so every classed link
	   -- .btn, .footer-link, .side-link, .activity-row, ... -- sets its own
	   colour/decoration and wins; only bare <a> in copy falls back to this. */
	a { color: var(--accent); text-underline-offset: 0.18em; text-decoration-thickness: from-font; }
	a:hover { text-decoration-thickness: 2px; }
}

@layer tokens {
:root {
	color-scheme: light dark;

	/* ── Type ────────────────────────────────────────────── */
	--font-serif: "Playfair Display Variable", "Playfair Display", Georgia, "Times New Roman", serif;
	--font-sans:  "Inter Variable", Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	--font-mono:  "IBM Plex Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

	/* ── Surfaces (paper light / warm-ink dark) ──────────── */
	--surface:          light-dark(#faf9f5, #14130f);  /* page */
	--surface-raised:   light-dark(#ffffff, #1c1b16);  /* cards, modals */
	--surface-sunken:   light-dark(#f1efe8, #100f0b);  /* table head, wells */
	--bg:               var(--surface);                /* legacy alias */
	--bg-2:             color-mix(in oklab, var(--ink) 3%, transparent);
	--bg-3:             color-mix(in oklab, var(--ink) 4.5%, transparent);

	/* Surface tints — flip automatically because --ink flips with theme */
	--tint-xs:          color-mix(in oklab, var(--ink) 4%,  transparent);
	--tint-sm:          color-mix(in oklab, var(--ink) 7%,  transparent);
	--tint-md:          color-mix(in oklab, var(--ink) 12%, transparent);
	--tint-lg:          color-mix(in oklab, var(--ink) 20%, transparent);

	/* Dark scrims — always darken */
	--scrim-xs:         color-mix(in oklab, #000 5%,  transparent);
	--scrim-sm:         color-mix(in oklab, #000 10%, transparent);
	--scrim-md:         color-mix(in oklab, #000 18%, transparent);
	--scrim-lg:         color-mix(in oklab, #000 35%, transparent);
	/* Modal/sheet backdrop — theme-aware: a light frosted veil over the page in
	   light mode (the page is bright, so a black scrim looked wrong), a dark one
	   in dark mode. Pairs with backdrop-filter: blur() on the ::backdrop rules. */
	--modal-scrim:      light-dark(color-mix(in oklab, #faf9f5 62%, transparent), color-mix(in oklab, #000 82%, transparent));
	--sheet-scrim:      light-dark(color-mix(in oklab, #faf9f5 55%, transparent), color-mix(in oklab, #000 45%, transparent));

	/* ── Ink / text ──────────────────────────────────────── */
	--ink:              light-dark(#1b1815, #ece8df);
	--text:             var(--ink);
	--text-1:           var(--ink);
	--text-2:           light-dark(#3d3833, #c9c4b8);
	--text-3:           light-dark(#574f46, #a39d90);
	--text-4:           light-dark(#6a645a, #918a7e);
	--text-5:           light-dark(#a49e92, #5e594f);

	/* ── Borders ─────────────────────────────────────────── */
	--border:           color-mix(in oklab, var(--ink) 13%, transparent);
	--border-subtle:    color-mix(in oklab, var(--ink) 7%,  transparent);

	/* ── Accent (cultured forest) ────────────────────────── */
	--accent:           light-dark(#1f4d3a, #6fb894);
	--accent-ink:       light-dark(#faf9f5, #11130f);  /* text on accent fill */
	--accent-glow:      color-mix(in oklab, var(--accent) 16%, transparent);
	--accent-soft:      color-mix(in oklab, var(--accent) 9%,  transparent);

	/* ── Cost category colors (recalibrated, muted-editorial) ── */
	--clr-buy:          light-dark(#2f5e8c, #7fb0dc);
	--clr-sell:         light-dark(color-mix(in oklab, #2e7d52 84%, #000), #6fcb97);
	/* Light-mode slots are darkened (hue kept) so the colours clear 4.5:1 as
	   small text on paper; dark-mode slots already pass on the warm-ink ground. */
	--clr-service:      light-dark(color-mix(in oklab, #b6792a 74%, #000), #e0b062);
	--clr-repair:       light-dark(color-mix(in oklab, #b3423a 90%, #000), #e08b82);
	--clr-upgrade:      light-dark(color-mix(in oklab, #2a7e8c 84%, #000), #6fc2ce);
	--clr-asset:        light-dark(#6a4e9c, #b79fe0);
	--clr-fixed:        light-dark(color-mix(in oklab, #c2622e 80%, #000), #e89e6b);
	--clr-fuel:         light-dark(color-mix(in oklab, #b89134 70%, #000), #e3c768);

	/* ── Chart *fill* variants ───────────────────────────────
	   The tokens above are darkened in light mode to clear 4.5:1 as small text
	   (category pills, coloured figures). Chart areas are large fills that need
	   no text contrast, so on paper the darkened warms read as muddy browns.
	   These -fill slots restore the cleaner, brighter hue for chart series only;
	   the dark slots match the base tokens (already legible on warm-ink). */
	--clr-buy-fill:     light-dark(#3f7fbf, #7fb0dc);
	--clr-sell-fill:    light-dark(#2f9e63, #6fcb97);
	--clr-service-fill: light-dark(#e39a2c, #e0b062);
	--clr-repair-fill:  light-dark(#d95448, #e08b82);
	--clr-upgrade-fill: light-dark(#2aa5bb, #6fc2ce);
	--clr-asset-fill:   light-dark(#8a5fc9, #b79fe0);
	--clr-fixed-fill:   light-dark(#e0703a, #e89e6b);
	--clr-fuel-fill:    light-dark(#e6bf3c, #e3c768);

	--clr-buy-bg:       color-mix(in oklab, var(--clr-buy) 10%, transparent);
	--clr-buy-border:   color-mix(in oklab, var(--clr-buy) 26%, transparent);
	--clr-sell-bg:      color-mix(in oklab, var(--clr-sell) 10%, transparent);
	--clr-sell-border:  color-mix(in oklab, var(--clr-sell) 26%, transparent);
	--clr-service-bg:   color-mix(in oklab, var(--clr-service) 10%, transparent);
	--clr-service-border: color-mix(in oklab, var(--clr-service) 26%, transparent);
	--clr-repair-bg:    color-mix(in oklab, var(--clr-repair) 10%, transparent);
	--clr-repair-border: color-mix(in oklab, var(--clr-repair) 26%, transparent);
	--clr-upgrade-bg:   color-mix(in oklab, var(--clr-upgrade) 10%, transparent);
	--clr-upgrade-border: color-mix(in oklab, var(--clr-upgrade) 26%, transparent);
	--clr-asset-bg:     color-mix(in oklab, var(--clr-asset) 10%, transparent);
	--clr-asset-border: color-mix(in oklab, var(--clr-asset) 26%, transparent);
	--clr-fuel-bg:      color-mix(in oklab, var(--clr-fuel) 10%, transparent);
	--clr-fuel-border:  color-mix(in oklab, var(--clr-fuel) 26%, transparent);

	/* ── Summary / result values ─────────────────────────── */
	--clr-tco:          var(--clr-sell);
	--clr-profit:       var(--clr-sell);
	--clr-cost:         var(--clr-repair);
	--clr-warn:         var(--clr-service);
	--clr-highlight:    var(--accent);
	--critical:         light-dark(#b3261e, #f2998f);  /* overdue / MFK red */

	/* ── Named color aliases ─────────────────────────────── */
	--clr-green:        var(--clr-sell);
	--clr-orange:       var(--clr-service);
	--clr-red:          var(--clr-repair);

	/* ── Legacy alias tokens (previously undefined → hardcoded fallbacks) ── */
	--clr-accent:         var(--accent);
	--clr-accent-subtle:  var(--accent-soft);
	--color-primary:      var(--accent);
	--text-primary:       var(--text);
	--text-secondary:     var(--text-2);
	--text-muted:         var(--text-4);
	--surface-1:          var(--surface-raised);

	/* ── Modal / dialog / tooltip ────────────────────────── */
	--modal-content-bg: linear-gradient(180deg, var(--surface-raised) 0%, var(--surface) 100%);
	--modal-border:     var(--border);
	--tooltip-bg:       #211f19;
	--tooltip-border:   color-mix(in oklab, #fff 12%, transparent);
	--tooltip-text:     #ece8df;

	/* ── Import preview surfaces ─────────────────────────── */
	--surface-2:        var(--tint-xs);
	--surface-3:        var(--tint-sm);

	/* ── Radius ──────────────────────────────────────────── */
	--radius-card:      10px;
	--radius-control:   7px;
	--radius-pill:      999px;

	/* ── Elevation (shadows) ─────────────────────────────── */
	/* Warm scrim-based so they read on paper (light) and warm-ink (dark). */
	--shadow-lg:    0 12px 40px var(--scrim-lg);
	--shadow-modal: 0 25px 50px -12px var(--scrim-lg), 0 0 0 1px var(--tint-sm) inset;

	/* ── Modal geometry (single source of truth for header/body/footer) ──── */
	--modal-pad-x: clamp(1.25rem, 3vw, 2rem);
	--modal-pad-y: 1.5rem;

	/* ── Layout ──────────────────────────────────────────── */
	/* Sidebar column width — the max of the .app-shell grid track, named so the
	   width is a single documented value rather than a bare number in the grid. */
	--sidebar-w: 260px;

	/* ── Animation timing ────────────────────────────────── */
	--timing-fast:   150ms;
	--timing-base:   250ms;
	--timing-slow:   400ms;
	--timing-slower: 600ms;
	--ease-out:      cubic-bezier(0.33, 1, 0.68, 1);
	--ease-in-out:   cubic-bezier(0.65, 0, 0.35, 1);
	--ease-bounce:   cubic-bezier(0.34, 1.56, 0.64, 1);
	--ease-spring:   cubic-bezier(0.34, 1.4, 0.5, 1);
}
}

/* Playfair Display ships real ct/st/Th/sp ligatures via `dlig`, which the CSS
   spec leaves off by default — opt in to ALL ligature classes wherever the
   display serif renders (every heading). */
:is(.cmp-card__title, .section-head__title,
	.car-row__name, .car-hero__name, .car-hero__submodel,
	.form-title, .empty-state-title, .sidebar__wordmark, .topbar__greeting,
	.topbar__title, .haupt__name) {
	font-variant-ligatures: common-ligatures discretionary-ligatures contextual historical-ligatures;
}

/* ==========================================================================
   Keyframe Animations
   ========================================================================== */

@keyframes fadeIn {
	from {
		opacity: 0;
		transform: translateY(10px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@keyframes fadeInScale {
	from {
		opacity: 0;
		transform: scale(0.95);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

@keyframes slideDown {
	from {
		opacity: 0;
		transform: translateY(-10px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@keyframes pulse {
	0%, 100% {
		opacity: 1;
	}
	50% {
		opacity: 0.7;
	}
}

@keyframes shimmer {
	0% {
		background-position: -1000px 0;
	}
	100% {
		background-position: 1000px 0;
	}
}

@keyframes popIn {
	0% {
		transform: scale(0.8);
		opacity: 0;
	}
	50% {
		transform: scale(1.05);
	}
	100% {
		transform: scale(1);
		opacity: 1;
	}
}

@keyframes glow {
	0%, 100% {
		box-shadow: 0 0 5px color-mix(in oklab, var(--accent) 30%, transparent);
	}
	50% {
		box-shadow: 0 0 20px color-mix(in oklab, var(--accent) 60%, transparent);
	}
}

@keyframes ripple {
	0% {
		transform: scale(0);
		opacity: 0.6;
	}
	100% {
		transform: scale(4);
		opacity: 0;
	}
}

/* Background lives on the root so the page canvas is always --surface, even
   during view transitions and before <body> paints. Declaring it only on
   <body> relied on background propagation, which breaks the moment <body>
   gets opacity/transform (e.g. an entrance animation) — yielding a white flash. */
html {
	background: var(--surface);
	/* Always reserve the scrollbar gutter so short pages (no scrollbar) and tall
	   pages (scrollbar) have the same content width. Without this the centered
	   container shifts ~7px horizontally between pages, so the masthead appears
	   to jump on navigation. */
	scrollbar-gutter: stable;
}

body {
	background: var(--surface);
	color: var(--text);
	font-family: var(--font-sans);
	font-size: 14px;
	line-height: 1.55;
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
	padding: clamp(20px, 4vw, 40px) clamp(14px, 3vw, 24px) 48px;
	margin: 0;
	min-height: 100vh;
}

.container {
	max-width: 1180px;
	width: 100%;
	margin: 0 auto;
}

h1 {
	margin: 0;
	font-size: 28px;
	font-weight: 400;
	color: var(--text);
	letter-spacing: -0.5px;
}

/* ==========================================================================
   Central component primitives
   The reusable vocabulary every feature composes from — buttons, badges,
   callouts and modal structure. Add a variant here instead of inventing a
   one-off class in a feature block. See book/src/development/components.md.
   ========================================================================== */

/* ── Button — .btn + intent + shape + size ──────────────────────────────────
   Intent (fill/colour): --primary --secondary --danger --ghost
   Shape:                --icon (square, subtle) / --close (icon that rotates)
   Size:                 --sm --lg / --block (full width)
   Compose e.g. `btn btn--icon btn--danger` for a red icon button. */
.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	padding: 0.625rem 1.25rem;
	border: 1px solid transparent;
	border-radius: var(--radius-control);
	font: inherit;
	font-size: 0.875rem;
	font-weight: 500;
	line-height: 1.2;
	white-space: nowrap;
	text-decoration: none;
	cursor: pointer;
	transition: background var(--timing-base) var(--ease-out),
	            border-color var(--timing-base) var(--ease-out),
	            color var(--timing-base) var(--ease-out),
	            box-shadow var(--timing-base) var(--ease-out),
	            transform var(--timing-base) var(--ease-out);
}
.btn:disabled { opacity: 0.6; pointer-events: none; }

/* §56 loading state — the clicked action button spins (colour adapts to intent
   via --btn-spinner); every other action button is disabled ($busy) and dims
   via .btn:disabled above. color:transparent hides the label + currentColor
   icon, leaving only the ::after ring. */
.btn          { --btn-spinner: var(--text-2); }
.btn--primary { --btn-spinner: var(--accent-ink); }
.btn--danger  { --btn-spinner: var(--critical); }
.btn--soft    { --btn-spinner: var(--accent); }
.btn--ghost   { --btn-spinner: var(--accent); }
.btn.is-loading {
	opacity: 1;
	color: transparent;
	position: relative;
	pointer-events: none;
}
.btn.is-loading::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 1em;
	height: 1em;
	margin: -0.5em 0 0 -0.5em;
	border: 2px solid var(--btn-spinner);
	border-right-color: transparent;
	border-radius: 50%;
	animation: btn-spin 0.6s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

.btn--secondary {
	background: var(--tint-sm);
	color: var(--text-2);
	border-color: var(--border);
}
.btn--secondary:hover {
	background: var(--tint-md);
	color: var(--text);
	border-color: var(--tint-lg);
}

.btn--primary {
	background: var(--accent);
	color: var(--accent-ink);
	font-weight: 600;
	box-shadow: 0 2px 10px var(--accent-glow);
}
.btn--primary:hover {
	transform: translateY(-1px);
	background: color-mix(in oklab, var(--accent) 88%, #000);
	box-shadow: 0 4px 16px color-mix(in oklab, var(--accent) 40%, transparent);
}
.btn--primary:active { transform: translateY(0); }

.btn--danger {
	background: transparent;
	color: var(--critical);
	border-color: var(--critical);
}
.btn--danger:hover {
	background: var(--critical);
	color: var(--accent-ink);
}

.btn--ghost {
	background: transparent;
	color: var(--accent);
	border-color: color-mix(in oklab, var(--accent) 40%, transparent);
}
.btn--ghost:hover { background: var(--accent-soft); }

/* Soft accent fill — the resting-accent look used by the primary toolbar action
   ("+ Eintrag") without the weight of a full primary fill. */
.btn--soft {
	background: var(--accent-soft);
	color: var(--accent);
	border-color: color-mix(in oklab, var(--accent) 30%, transparent);
	box-shadow: none;
}
.btn--soft:hover { background: color-mix(in oklab, var(--accent) 16%, transparent); }

/* §56 — modal submit error slot. Empty by default → hidden; the SSE loop patches
   the failed submit's message into the open dialog's slot, leaving it open. */
.form-error {
	margin: 0 0 0.75rem;
	padding: 0.6rem 0.8rem;
	border-radius: var(--radius-control);
	background: var(--clr-repair-bg);
	color: var(--clr-repair);
	border: 1px solid color-mix(in oklab, var(--critical) 40%, transparent);
	font-size: 0.85rem;
}
.form-error:empty { display: none; }

.btn--sm { padding: 0.4rem 0.8rem; font-size: 0.78rem; }
.btn--lg { padding: 1rem 2rem; font-size: 1.125rem; font-weight: 600; }
.btn--block { width: 100%; }

/* Square, low-chrome icon button. Neutral by default; compose with an intent
   modifier for accent (--primary) or red (--danger) tint. */
.btn--icon {
	padding: 0.35rem;
	min-width: 2rem;
	min-height: 2rem;
	background: transparent;
	border-color: transparent;
	color: var(--text-3);
	font-size: 1rem;
	line-height: 1;
	box-shadow: none;
}
.btn--icon:hover {
	background: var(--tint-md);
	color: var(--text);
	transform: none;
	box-shadow: none;
}
.btn--icon.btn--primary { color: var(--accent); font-weight: inherit; }
.btn--icon.btn--primary:hover { background: var(--accent-soft); color: var(--accent); }
.btn--icon.btn--danger { color: var(--clr-repair); }
.btn--icon.btn--danger:hover { background: var(--clr-repair-bg); color: var(--clr-repair); }
/* §56 — row quick-action (mark done / confirm paid): a soft-filled affirmative
   chip, so it reads as a distinct role from the bare accent edit icon and the
   bare danger delete icon in the same row. */
.btn--icon.btn--quick { color: var(--accent); background: var(--accent-soft); --btn-spinner: var(--accent); }
.btn--icon.btn--quick:hover { background: color-mix(in oklab, var(--accent) 16%, transparent); color: var(--accent); }

/* Modal close glyph — icon button that spins on hover. */
.btn--close {
	min-width: 2.5rem;
	min-height: 2.5rem;
	font-size: 1.5rem;
}
.btn--close:hover { transform: rotate(90deg); }

/* ── Badge — .badge, colour driven by [data-cat] ────────────────────────────
   `<span class="badge" data-cat="service">`. --soft (default, tinted chip) or
   --solid (filled). One category table feeds badges, swatches and amounts. */
.badge {
	display: inline-block;
	border-radius: 4px;
	padding: 2px 7px;
	font-size: 9px;
	font-weight: 600;
	letter-spacing: 1px;
	line-height: 1.4;
	text-transform: uppercase;
	white-space: nowrap;
	color: var(--cat, var(--text-2));
	background: var(--cat-bg, var(--tint-sm));
	border: 1px solid var(--cat-border, var(--border));
}
.badge--solid {
	color: var(--accent-ink);
	background: var(--cat, var(--accent));
	border-color: transparent;
}

/* Category palette — the single source of truth for cost-category colour.
   Sets custom properties only (renders nothing itself), consumed by .badge,
   .charge-swatch and category-coloured amounts via var(--cat*). */
[data-cat="buy"]     { --cat: var(--clr-buy);     --cat-bg: var(--clr-buy-bg);     --cat-border: var(--clr-buy-border); }
[data-cat="sell"]    { --cat: var(--clr-sell);    --cat-bg: var(--clr-sell-bg);    --cat-border: var(--clr-sell-border); }
[data-cat="service"] { --cat: var(--clr-service); --cat-bg: var(--clr-service-bg); --cat-border: var(--clr-service-border); }
[data-cat="repair"]  { --cat: var(--clr-repair);  --cat-bg: var(--clr-repair-bg);  --cat-border: var(--clr-repair-border); }
[data-cat="upgrade"] { --cat: var(--clr-upgrade); --cat-bg: var(--clr-upgrade-bg); --cat-border: var(--clr-upgrade-border); }
[data-cat="asset"]   { --cat: var(--clr-asset);   --cat-bg: var(--clr-asset-bg);   --cat-border: var(--clr-asset-border); }
[data-cat="energy"]  { --cat: var(--clr-fuel);    --cat-bg: var(--clr-fuel-bg);    --cat-border: var(--clr-fuel-border); }
[data-cat="fixed"]   { --cat: var(--clr-fixed); }
[data-cat="tco"]     { --cat: var(--clr-tco); }

/* ── Callout — tinted advisory box, .callout + tone ─────────────────────────
   Tone (--info --warn --danger --success) sets bg + border from a --clr token,
   so every callout is theme-correct (light-dark) for free. --bar adds a left
   accent rule. Replaces the per-feature hint/notice/warning boxes. */
.callout {
	padding: 0.65rem 0.85rem;
	border-radius: var(--radius-control);
	border: 1px solid var(--callout-border, var(--border));
	background: var(--callout-bg, var(--tint-xs));
	color: var(--text-2);
	font-size: 0.85rem;
	line-height: 1.5;
}
.callout--info    { --callout-bg: var(--accent-soft);                                    --callout-border: color-mix(in oklab, var(--accent) 22%, transparent); }
.callout--warn    { --callout-bg: color-mix(in oklab, var(--clr-service) 12%, transparent); --callout-border: color-mix(in oklab, var(--clr-service) 40%, transparent); color: var(--text-1); }
.callout--danger  { --callout-bg: color-mix(in oklab, var(--clr-repair) 12%, transparent);  --callout-border: color-mix(in oklab, var(--clr-repair) 40%, transparent); }
.callout--success { --callout-bg: color-mix(in oklab, var(--clr-sell) 12%, transparent);    --callout-border: color-mix(in oklab, var(--clr-sell) 40%, transparent); }
.callout--bar {
	border-left-width: 3px;
	border-left-color: var(--callout-accent, var(--accent));
}
/* Inline icon + text status strip (e.g. §58 replication status). */
.callout--row {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin-bottom: 0.85rem;
}
.callout--row .icon { flex: none; }

/* §59 "Your data & privacy" page — a single, readable column of stacked panels.
   Provides its own padding (the layout content slot has none; each section
   supplies its own, e.g. .settings-content). */
.data-privacy {
	padding: clamp(1.1rem, 2.4vw, 2.2rem);
	max-width: 820px;
	display: flex;
	flex-direction: column;
	gap: 1rem;
}
.data-privacy > .panel { margin: 0; }

/* §46 onboarding nudge — completion prompt (text + actions) inside a .callout */
.onboarding-nudge {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 1rem;
	margin-bottom: 0.75rem;
}
.onboarding-nudge__text { flex: 1 1 15rem; min-width: 0; }
.onboarding-nudge__title { margin: 0; font-weight: 600; color: var(--text-1); }
.onboarding-nudge__body { margin: 0.15rem 0 0; }
.onboarding-nudge__actions { display: flex; flex-shrink: 0; gap: 0.5rem; }

/* ── Modal structure — self-padded header/body/footer ───────────────────────
   Direct children of .form-modal-content. Padding comes from --modal-pad-*,
   so a footer is correct wherever it sits and never needs a one-off padding
   fix (the reason the old .intake-footer existed). */
.modal__body { padding: var(--modal-pad-y) var(--modal-pad-x); }
.modal__footer {
	display: flex;
	justify-content: flex-end;
	align-items: center;
	gap: 0.75rem;
	padding: var(--modal-pad-y) var(--modal-pad-x);
	border-top: 1px solid var(--border);
}
.modal__footer--split { justify-content: space-between; }

/* ==========================================================================
   Demo Banner
   ========================================================================== */

.demo-banner {
	background: rgba(251, 191, 36, 0.12);
	border-bottom: 1px solid rgba(251, 191, 36, 0.3);
	color: var(--text-2);
	font-size: 0.8rem;
	font-weight: 500;
	text-align: center;
	padding: 0.55rem 1rem;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.6rem;
	flex-wrap: wrap;
}

/* §47: the demo → signup CTA sitting inline in the reset-notice banner. */
.demo-banner__cta {
	flex: none;
	font-weight: 600;
	color: var(--accent, #1f4d3a);
	text-decoration: none;
	border: 1px solid color-mix(in oklab, var(--accent, #1f4d3a) 45%, transparent);
	border-radius: 999px;
	padding: 0.15rem 0.7rem;
	white-space: nowrap;
	transition: background 0.15s ease, color 0.15s ease;
}

.demo-banner__cta:hover {
	background: var(--accent, #1f4d3a);
	color: #fff;
}

/* ==========================================================================
   Impersonation Banner (§40 operator console)
   ========================================================================== */

.impersonation-banner {
	background: color-mix(in oklab, var(--clr-repair) 14%, transparent);
	border-bottom: 1px solid color-mix(in oklab, var(--clr-repair) 40%, transparent);
	color: var(--clr-repair);
	font-size: 0.8rem;
	font-weight: 600;
	text-align: center;
	padding: 0.55rem 1rem;
	position: sticky;
	top: 0;
	z-index: 100;
}
.impersonation-banner form { display: inline; margin-left: 0.6rem; }
.impersonation-banner button {
	font: inherit;
	font-weight: 600;
	color: inherit;
	background: none;
	border: 1px solid currentColor;
	border-radius: 4px;
	padding: 0.1rem 0.5rem;
	cursor: pointer;
}
.impersonation-banner button:hover { background: color-mix(in oklab, var(--clr-repair) 16%, transparent); }

.header-description {
	margin: 5px 0 0;
	color: var(--text-4);
	font-size: 12px;
}

.header-actions-left {
	display: flex;
	gap: 0.7rem;
	flex-wrap: wrap;
	align-items: center;
	flex: 1;
}

.header-actions-right {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin-left: auto;
}

.profile-switcher {
	display: flex;
	align-items: center;
	gap: 0.375rem;
	flex-wrap: wrap;
}

.profile-switcher-label {
	font-size: 0.75rem;
	color: var(--text-muted);
	margin-right: 0.25rem;
	white-space: nowrap;
}

.profile-switcher-active {
	font-size: 0.8rem;
	font-weight: 600;
	color: var(--accent);
	padding: 0.3rem 0.75rem;
	border-radius: var(--radius-pill);
	background: var(--accent-soft);
	border: 1px solid color-mix(in oklab, var(--accent) 35%, transparent);
	white-space: nowrap;
}

.profile-switcher-item {
	display: inline-flex;
	align-items: center;
}

.profile-switcher-btn {
	font-size: 0.78rem;
	padding: 0.28rem 0.7rem;
	border-radius: var(--radius-pill);
	border: 1px solid var(--border);
	background: transparent;
	color: var(--text-3);
	cursor: pointer;
	transition: all 0.15s ease;
	white-space: nowrap;
}
.profile-switcher-btn:hover {
	border-color: color-mix(in oklab, var(--accent) 45%, transparent);
	color: var(--ink);
	background: var(--accent-soft);
}
.profile-switcher-btn .icon {
	margin-right: 0.3rem;
	color: var(--text-4);
}

.profile-switcher-add {
	color: var(--text-3);
	border-style: dashed;
}
.profile-switcher-add:hover {
	color: var(--accent);
	border-color: color-mix(in oklab, var(--accent) 45%, transparent);
	border-style: solid;
}

.profile-switcher-login {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	padding: 0.2rem 0.4rem 0.2rem 0.55rem;
	border-radius: var(--radius-pill);
	border: 1px solid var(--border);
	background: transparent;
}
.profile-switcher-login .icon {
	width: 0.85em;
	height: 0.85em;
	color: var(--text-4);
	flex-shrink: 0;
}
.profile-switcher-login-input {
	width: 6rem;
	font-size: 0.78rem;
	padding: 0.2rem 0.4rem;
	border: none;
	background: transparent;
	color: var(--ink);
}
.profile-switcher-login-input:focus {
	outline: none;
}
.profile-switcher-login .profile-switcher-btn {
	padding: 0.2rem 0.6rem;
	border: none;
}

.profile-switcher-delete {
	font-size: 0.7rem;
	line-height: 1;
	display: inline-grid;
	place-items: center;
	min-width: 24px;
	min-height: 24px;
	margin-left: 0.1rem;
	border-radius: 50%;
	border: none;
	background: transparent;
	color: var(--text-4);
	cursor: pointer;
	transition: all 0.15s ease;
}
.profile-switcher-delete:hover {
	background: color-mix(in oklab, var(--critical) 18%, transparent);
	color: var(--critical);
}
.car-photo-upload {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 20px;
	cursor: pointer;
	opacity: 0;
	transition: opacity var(--timing-base) var(--ease-out);
	background: rgba(0,0,0,0.35);
	border-radius: 10px;
}

.car-photo-wrap:hover .car-photo-upload {
	opacity: 1;
}

/* Show upload icon on placeholder immediately (no image to obscure) */
.car-photo-wrap:has(.car-photo-placeholder) .car-photo-upload {
	opacity: 0.6;
	background: transparent;
}

.car-photo-wrap:has(.car-photo-placeholder):hover .car-photo-upload {
	opacity: 1;
}

.car-photo-delete {
	position: absolute;
	top: 3px;
	right: 3px;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: rgba(0,0,0,0.7);
	border: none;
	color: #fff;
	font-size: 13px;
	line-height: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	opacity: 0;
	transition: opacity var(--timing-base) var(--ease-out);
	z-index: 1;
	padding: 0;
}

.car-photo-wrap:hover .car-photo-delete {
	opacity: 1;
}

.car-photo-delete:hover {
	background: var(--clr-sell);
}
.car-category {
	background: var(--tint-sm);
	padding: 2px 6px;
	border-radius: 4px;
	font-weight: 600;
	color: var(--text-2);
	border: 1px solid var(--border);
	transition: all var(--timing-base) var(--ease-out);
	display: inline-block;
}

.car-category:hover {
	background: var(--tint-md);
	border-color: var(--tint-lg);
	transform: scale(1.05);
}

.car-status-sold {
	color: var(--clr-sell);
}

.car-status-owned {
	color: var(--text-2);
}

/* MFK status (§8) */
.car-status-mfk-ok {
	color: var(--clr-green);
}

.car-status-mfk-soon {
	color: var(--clr-orange);
}

.car-status-mfk-overdue {
	color: var(--clr-red);
}

/* ==========================================================================
   Sharing (§1)
   ========================================================================== */

/* "Geteilt" badge on shared-in cars (detail hero eyebrow + list row meta). */
.car-badge-shared {
	display: inline-flex;
	align-items: center;
	gap: 0.25em;
	color: var(--text-2);
}

.car-badge-shared .icon {
	width: 0.95em;
	height: 0.95em;
}

/* Kennzeichen badge (§14) — list row meta + detail hero title. */
.car-badge-plate {
	display: inline-block;
	font-family: var(--font-mono, monospace);
	font-size: 0.8em;
	letter-spacing: 0.03em;
	padding: 0.1em 0.5em;
	border: 1px solid var(--border);
	border-radius: 4px;
	color: var(--text-2);
	vertical-align: middle;
}

/* Read-only view of a shared car: hide every mutate affordance. The server also
   rejects writes (defense in depth); this just keeps the UI honest. */
.car-detail--readonly .entry-actions,
.car-detail--readonly .th-actions {
	display: none;
}

/* Share picker (ShareModal) — one row per profile with an access selector. */
.share-list {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	margin: 0.75rem 0;
}

.share-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
}

.share-row__name {
	font-weight: 500;
}

.share-row__select {
	width: auto;
	min-width: 11rem;
}

/* ==========================================================================
   Pills
   ========================================================================== */

.pills {
	display: flex;
	gap: 14px;
	align-items: center;
	flex-shrink: 0;
	flex-wrap: wrap;
}

.car-actions {
	display: flex;
	gap: 6px;
	align-items: center;
}
/* Primary-vehicle star toggle (§14) — outline by default, filled once set. */
.car-action-btn--primary .icon,
.car-hero__primary .icon {
	color: var(--text-4);
	transition: color var(--timing-base) var(--ease-out), fill var(--timing-base) var(--ease-out);
}

.car-action-btn--primary.is-primary .icon,
.car-hero__primary.is-primary .icon {
	color: var(--clr-fuel);
}

.pill {
	text-align: right;
	transition: transform var(--timing-base) var(--ease-spring);
}

.pill:hover {
	transform: scale(1.08);
}

.pill-label {
	font-size: 9px;
	color: var(--text-3);
	letter-spacing: 1.5px;
	margin-bottom: 1px;
	transition: color var(--timing-base) var(--ease-out);
	font-weight: 500;
	text-transform: uppercase;
}

.pill:hover .pill-label {
	color: var(--text-2);
}

.pill-value {
	font-size: 18px;
	font-weight: 700;
	font-family: var(--font-mono);
	line-height: 1;
	transition: all var(--timing-base) var(--ease-out);
}

.pill:hover .pill-value {
	text-shadow: 0 0 20px currentColor;
}

/* ==========================================================================
   Details / Logbook
   ========================================================================== */

details {
	border-top: 1px solid var(--border-subtle);
}

details[open] > summary {
	background: var(--scrim-sm);
}

details summary {
	cursor: pointer;
	padding: 9px 22px;
	background: var(--scrim-xs);
	list-style: none;
	user-select: none;
	transition: all var(--timing-base) var(--ease-out);
}

details summary::-webkit-details-marker {
	display: none;
}

details summary:hover {
	background: var(--scrim-sm);
	padding-left: 26px;
}
/* ==========================================================================
   Entry Table
   ========================================================================== */

.entry-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 12px;
}

.entry-table thead th {
	padding: 7px 14px;
	text-align: left;
	font-size: 9px;
	letter-spacing: 2px;
	color: var(--text-3);
	font-weight: 600;
	background: var(--scrim-md);
	border-bottom: 1px solid var(--border-subtle);
	text-transform: uppercase;
}

.entry-table tbody tr {
	border-bottom: 1px solid var(--border-subtle);
	transition: all var(--timing-base) var(--ease-out);
}

.entry-table tbody tr:hover {
	background: var(--tint-sm);
	transform: scale(1.005);
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.entry-table tbody td {
	padding: 8px 14px;
	transition: all var(--timing-base) var(--ease-out);
}

.entry-table tbody tr:hover td {
	color: var(--text);
}

.entry-date,
.entry-km {
	color: var(--text-2);
	font-family: var(--font-mono);
	white-space: nowrap;
}

.entry-desc {
	color: var(--text-2);
}
/* §11 energy fill quantity chip in the journal description cell */
.entry-energy-qty {
	display: inline-block;
	margin-left: 0.5rem;
	padding: 1px 6px;
	border-radius: 4px;
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--clr-fuel);
	background: var(--clr-fuel-bg);
	white-space: nowrap;
}

/* §12 driving-style slider on the car form */
.driving-style-slider {
	display: flex;
	align-items: center;
	gap: 0.75rem;
}
.driving-style-slider input[type="range"] { flex: 1; min-width: 0; }
.driving-style-slider .form-label-hint { white-space: nowrap; }

/* §11 charge-sources editor in settings */
.charge-source-list { display: flex; flex-direction: column; gap: 0.5rem; }
.charge-source-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.charge-source-edit { display: flex; align-items: center; gap: 0.5rem; flex: 1; min-width: 0; }
.charge-source-edit .form-input { min-width: 0; }
.charge-source-edit > .form-input:first-child { flex: 1; }
.charge-source-price { width: 6rem; flex: 0 0 auto; text-align: right; font-family: var(--font-mono); }
.charge-source-unit { color: var(--text-3); font-size: 11px; white-space: nowrap; }
.charge-source-del {
	width: 32px; height: 32px; flex: 0 0 auto;
	border: 1px solid var(--border); border-radius: var(--radius-control);
	background: var(--tint-sm); color: var(--text-3);
	font-size: 1.1rem; line-height: 1; cursor: pointer;
	transition: all var(--timing-base) var(--ease-out);
}
.charge-source-del:hover { background: var(--clr-repair-bg); color: var(--clr-repair); border-color: var(--clr-repair-border); }

/* §11 erfasst-vs-geschätzt fuel split, shown above the cost breakdown */
.energy-split {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.5rem 0.85rem;
	margin: 0 0 1rem;
	font-size: 12px;
	color: var(--text-2);
}
.energy-split__label { color: var(--text-3); text-transform: uppercase; letter-spacing: 1px; font-size: 9px; font-weight: 600; }
.energy-split__total { font-family: var(--font-mono); color: var(--text); font-weight: 600; }
.energy-split__part { font-family: var(--font-mono); }
.energy-split__part--actual { color: var(--clr-sell); }
.energy-split__part--est { color: var(--clr-fuel); }
.energy-split__cons { margin-left: auto; color: var(--text-3); font-family: var(--font-mono); }
.energy-split--mix { gap: 0.5rem 0.6rem; }
.energy-split__mixitem {
	font-family: var(--font-mono);
	color: var(--clr-upgrade);
	background: color-mix(in oklab, var(--clr-upgrade) 10%, transparent);
	border-radius: 4px;
	padding: 1px 7px;
}

.entry-amount {
	font-family: var(--font-mono);
	text-align: right;
	white-space: nowrap;
	color: var(--text);
}

.entry-amount--sell { color: var(--clr-tco); }
.entry-amount--fixed { color: var(--clr-fixed); }

/* Recurring-charge category swatch (§10), mirrors the cost-pie legend dot. */
.charge-swatch {
	display: inline-block;
	width: 10px;
	height: 10px;
	border-radius: 2px;
	margin-right: 7px;
	vertical-align: baseline;
}

/* ==========================================================================
   Summary Row
   ========================================================================== */

.summary-row {
	display: flex;
	gap: 16px;
	justify-content: flex-end;
	flex-wrap: wrap;
	padding: 10px 22px;
	border-top: 1px solid var(--border);
	font-size: 11px;
}

.summary-label {
	color: var(--text-2);
}

.summary-value--service { color: var(--clr-service); font-family: var(--font-mono); }
.summary-value--upgrade { color: var(--clr-upgrade); font-family: var(--font-mono); }
.summary-value--asset { color: var(--clr-asset); font-family: var(--font-mono); }
.summary-value--fixed { color: var(--clr-fixed); font-family: var(--font-mono); }
.summary-value--tco {
	color: var(--clr-tco);
	font-weight: 700;
	font-family: var(--font-mono);
}

/* ==========================================================================
   Charts
   ========================================================================== */

.chart-container {
	margin-top: 20px;
	padding: 0 10px;
}

tco-chart {
	display: block;
	width: 100%;
	height: 300px;
}

.comparison-chart {
	display: block;
	width: 100%;
	height: 250px;
}

/* ==========================================================================
   Comparison Panel
   ========================================================================== */

/* View Transitions: enable for same-origin nav (sort changes) */
@view-transition {
	navigation: auto;
}

/* Cross-document page transitions: the old content fades out fast, the new page
   fades in with a slight lift, so navigation feels like a soft settle rather than
   a hard swap. Card repositioning stays the focus in the comparison panel. */
::view-transition-old(root) {
	animation: vt-page-out 130ms ease-out both;
}
::view-transition-new(root) {
	animation: vt-page-in 260ms var(--ease-out, ease-out) both;
}
@keyframes vt-page-out { to { opacity: 0; } }
@keyframes vt-page-in {
	from { opacity: 0; transform: translateY(10px); }
	to { opacity: 1; transform: none; }
}

/* Hold the sidebar as its own group: its identical brand + primary nav cross-fade
   invisibly, so only the contextual per-section subnav actually animates. */
::view-transition-group(app-sidebar) {
	animation-duration: 220ms;
	animation-timing-function: ease-out;
}

/* Respect reduced-motion: skip the page fade/lift entirely (instant swap). */
@media (prefers-reduced-motion: reduce) {
	::view-transition-old(root),
	::view-transition-new(root) { animation: none; }
}

.comparison-panel {
	margin-bottom: 26px;
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	padding: clamp(1rem, 2.2vw, 1.5rem);
}

.comparison-header {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--text-4);
	margin-bottom: 14px;
	font-weight: 600;
}

.comparison-cards {
	display: grid;
	gap: clamp(0.6rem, 1.4vw, 0.9rem);
	grid-template-columns: repeat(auto-fill, minmax(clamp(210px, 24%, 280px), 1fr));
}

/* §24 vehicle-group separator in Vergleich panel */
.comparison-group { margin-top: 1.75rem; }
.comparison-group:first-child { margin-top: 0; }
.comparison-group__heading {
	display: flex;
	align-items: center;
	gap: 0.45em;
	margin: 0 0 0.75rem;
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 520;
	font-size: clamp(16px, 1.8vw, 19px);
	letter-spacing: -0.01em;
	line-height: 1.1;
	color: var(--ink);
	padding-bottom: 0.5rem;
	border-bottom: 1px solid var(--border-subtle);
}
.comparison-group__heading .icon { color: var(--text-3); }

/* ── Ranking card: photo band + instrument metrics, links to detail ─────── */
.cmp-card {
	display: flex;
	flex-direction: column;
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	overflow: hidden;
	text-decoration: none;
	color: inherit;
	transition:
		transform    var(--timing-base) var(--ease-out),
		box-shadow   var(--timing-base) var(--ease-out),
		border-color var(--timing-base) var(--ease-out);
}
.cmp-card:hover {
	transform: translateY(-3px);
	box-shadow: 0 12px 28px var(--scrim-md);
	border-color: var(--tint-lg);
}

.cmp-card__media {
	position: relative;
	aspect-ratio: 16 / 10;
	background: var(--surface-sunken);
	overflow: hidden;
}
.cmp-card__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform var(--timing-slow) var(--ease-out);
}
.cmp-card:hover .cmp-card__img { transform: scale(1.04); }
.cmp-card__img--ph {
	display: grid;
	place-items: center;
	color: var(--text-5);
}
/* Scrim only over the lower band, so the title stays legible without dulling the photo. */
.cmp-card__media::after {
	content: '';
	position: absolute;
	inset: 40% 0 0;
	background: linear-gradient(to bottom, transparent, color-mix(in oklab, #000 72%, transparent));
	pointer-events: none;
}
.cmp-card__title {
	position: absolute;
	left: 0.85rem;
	right: 0.85rem;
	bottom: 0.7rem;
	z-index: 1;
	font-family: var(--font-serif);
	font-weight: 540;
	font-size: 14px;
	line-height: 1.15;
	letter-spacing: -0.01em;
	color: #fff;
	text-shadow: 0 1px 4px rgba(0,0,0,0.5);
}
.cmp-card__rank {
	position: absolute;
	top: 0.6rem;
	left: 0.6rem;
	z-index: 1;
	display: inline-grid;
	place-items: center;
	min-width: 1.55rem;
	height: 1.55rem;
	padding: 0 0.4rem;
	border-radius: var(--radius-pill);
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 600;
	color: var(--ink);
	background: color-mix(in oklab, var(--surface-raised) 88%, transparent);
	backdrop-filter: blur(4px);
	box-shadow: 0 1px 3px var(--scrim-md);
}
.cmp-card__rank .icon { color: var(--accent); font-size: 0.95rem; }

.cmp-card--winner { border-color: color-mix(in oklab, var(--accent) 45%, transparent); }
.cmp-card--winner .cmp-card__rank {
	background: var(--accent);
	color: var(--accent-ink);
}
.cmp-card--winner .cmp-card__rank .icon { color: var(--accent-ink); }

.cmp-card__metrics {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	padding: 0.9rem 1rem 0.7rem;
}

/* Hero: the single all-in comparable number that the ranking sorts by. */
.cmp-hero {
	display: flex;
	align-items: baseline;
	gap: 0.4rem;
}
.cmp-hero__val {
	font-family: var(--font-mono);
	font-weight: 600;
	font-size: 27px;
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--text-1);
	font-variant-numeric: tabular-nums slashed-zero;
}
.cmp-hero__unit {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-4);
}
.cmp-hero__month {
	margin-left: auto;
	align-self: baseline;
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--text-3);
	font-variant-numeric: tabular-nums slashed-zero;
	white-space: nowrap;
}

/* Cost-DNA: one stacked bar whose segments sum to the hero, so the composition
   reads at a glance (a thirsty car shows a fat energy band, etc.). */
.cmp-bar {
	display: flex;
	height: 7px;
	gap: 1px;
	border-radius: var(--radius-pill);
	overflow: hidden;
	background: var(--surface-sunken);
}
.cmp-bar__seg {
	height: 100%;
	min-width: 2px;
	background: var(--seg-clr);
}

/* Legend carries each segment's *real* per-km value, so fuel/upkeep are legible
   on their own rather than hidden between two cumulative totals. */
.cmp-legend {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0.28rem 0.8rem;
	margin: 0;
	padding: 0;
	list-style: none;
}
.cmp-legend__item {
	display: flex;
	align-items: center;
	gap: 0.35rem;
	font-family: var(--font-mono);
}
.cmp-legend__dot {
	width: 7px;
	height: 7px;
	border-radius: 2px;
	flex: none;
	background: var(--seg-clr);
}
.cmp-legend__lbl {
	font-size: 9px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--text-4);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.cmp-legend__val {
	margin-left: auto;
	font-size: 11px;
	color: var(--text-2);
	font-variant-numeric: tabular-nums slashed-zero;
}

/* Shared per-segment colour, used by both the bar segment and the legend dot —
   both fills, so they take the brighter -fill hue (matching the charts). */
.cmp-seg--depreciation { --seg-clr: var(--clr-buy-fill); }
.cmp-seg--upkeep       { --seg-clr: var(--clr-service-fill); }
.cmp-seg--invest       { --seg-clr: var(--clr-upgrade-fill); }
.cmp-seg--fixed        { --seg-clr: var(--clr-fixed-fill); }
.cmp-seg--energy       { --seg-clr: var(--clr-fuel-fill); }
.cmp-seg--capital      { --seg-clr: var(--clr-asset-fill); }
.cmp-seg--appreciation { --seg-clr: var(--clr-sell-fill); } /* §71 lens pill (no bar segment) */
/* §71 Inc 3: a net-negative all-in (appreciation gain exceeds costs) reads as a gain. */
.cmp-hero__val--gain { color: var(--clr-sell); }
.cmp-hero__gain {
	display: block;
	margin-top: 0.15rem;
	font-size: 11px;
	color: var(--clr-sell);
	font-variant-numeric: tabular-nums;
}

/* Car-detail overview: a larger single-car cost-DNA header (all-in figure +
   monthly + the same stacked bar and legend as the comparison cards). */
.cost-dna {
	display: flex;
	flex-direction: column;
	gap: 0.7rem;
	max-width: 460px;
	margin: 0.25rem 0 1.4rem;
}
.cost-dna .cmp-hero__val { font-size: 34px; }
.cost-dna__bar { height: 9px; }
/* The four segments as a tidy 2×2 grid of tiles (detail always has exactly the
   four cash segments — capital is Vergleich-only). */
.cost-dna__legend { gap: 0.5rem; }
.cost-dna__legend .cmp-legend__item {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: baseline;
	gap: 0.5rem;
	padding: 0.5rem 0.7rem;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-control);
}
.cost-dna__legend .cmp-legend__dot { align-self: center; }
.cost-dna__legend .cmp-legend__val { margin-left: 0; font-size: 13px; }

/* Car-detail overview: cost-DNA+summary, pie, yearly breakdown, and cost/km
   trend as four tiles in a 2×2 grid instead of one long vertical stack. */
.overview-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: clamp(1rem, 2vw, 1.5rem);
}
.overview-tile {
	min-width: 0;
	padding: clamp(0.9rem, 1.8vw, 1.25rem);
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
}
.tile-head {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	margin-bottom: 0.75rem;
}
.tile-head__title {
	font-size: 0.95rem;
	font-weight: 600;
	line-height: 1.25;
	color: var(--text-1);
	margin: 0;
}
.tile-head__sub {
	font-size: 0.8rem;
	line-height: 1.3;
	color: var(--text-3);
	margin: 0;
}
/* §71 value tile: title block + a "+ Bewertung" action on one row. */
.tile-head--row {
	flex-direction: row;
	align-items: flex-start;
	justify-content: space-between;
	gap: 0.75rem;
}
.tile-head--row .tile-head__titles {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	min-width: 0;
}
/* §71 logged-valuations list under the value curve. */
.value-log {
	list-style: none;
	margin: 0.85rem 0 0;
	padding: 0;
}
.value-log__row {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.4rem 0;
	border-top: 1px solid var(--border-subtle);
	font-size: 0.85rem;
}
.value-log__date { color: var(--text-3); font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.value-log__val { font-weight: 600; color: var(--text-1); font-variant-numeric: tabular-nums; }
.value-log__src { color: var(--text-3); }
.value-log__row .btn { margin-left: auto; }
/* §71 Inc 2: equity / net-position scorecard in the value tile. */
.equity { margin: 0.6rem 0 0.9rem; }
.equity__stats {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 1.5rem;
	align-items: baseline;
}
.equity__stat { display: flex; flex-direction: column; gap: 0.1rem; }
.equity__label {
	font-size: 11px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--text-4);
}
.equity__val {
	font-family: var(--font-mono);
	font-size: 1rem;
	font-weight: 600;
	color: var(--text-1);
	font-variant-numeric: tabular-nums;
}
.equity__val--asset { color: var(--clr-asset); }
.equity__val--pos { color: var(--clr-sell); }
.equity__val--neg { color: var(--clr-repair); }
.equity__bar {
	margin-top: 0.6rem;
	height: 6px;
	border-radius: 999px;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	overflow: hidden;
}
.equity__bar-fill {
	display: block;
	height: 100%;
	background: var(--text-4);
	transition: width var(--timing-base) var(--ease-out);
}
.equity__bar-fill--pos { background: var(--clr-sell); }
.equity__hint {
	margin: 0.4rem 0 0;
	font-size: 0.78rem;
	line-height: 1.35;
	color: var(--text-3);
}
/* §71 Inc 5: collection worth in the Vergleich "Sammlung" section head. */
.collection__worth {
	margin-left: auto;
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
	text-align: right;
}
.collection__worth-label {
	font-size: 11px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--text-4);
}
.collection__worth-val {
	font-family: var(--font-mono);
	font-size: 1.35rem;
	font-weight: 600;
	color: var(--clr-asset);
	font-variant-numeric: tabular-nums;
}
.collection__yoy {
	font-family: var(--font-mono);
	font-size: 0.85rem;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}
.collection__yoy--pos { color: var(--clr-sell); }
.collection__yoy--neg { color: var(--clr-repair); }
.collection__subhead { font-size: 0.95rem; font-weight: 600; color: var(--text-1); margin: 1.2rem 0 0.15rem; }
/* §71 Inc 10: Serviceheft coverage timeline (documented span vs gaps). */
.booklet-tl { margin: 0.4rem 0 0.9rem; }
.booklet-tl__track {
	position: relative;
	height: 10px;
	border-radius: 999px;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	overflow: hidden;
}
.booklet-tl__covered { position: absolute; top: 0; bottom: 0; background: var(--clr-service); opacity: 0.5; }
.booklet-tl__covered--complete { background: var(--clr-sell); opacity: 0.65; }
.booklet-tl__gap { position: absolute; top: 0; bottom: 0; background: var(--clr-repair); opacity: 0.8; }
.booklet-tl__legend { display: flex; gap: 1rem; margin-top: 0.45rem; font-size: 0.75rem; color: var(--text-3); }
.booklet-tl__key { display: inline-flex; align-items: center; gap: 0.35rem; }
.booklet-tl__key::before { content: ""; width: 10px; height: 10px; border-radius: 3px; }
.booklet-tl__key--covered::before { background: var(--clr-sell); }
.booklet-tl__key--gap::before { background: var(--clr-repair); }
@media (max-width: 900px) {
	.overview-grid { grid-template-columns: 1fr; }
}

/* §34 per-car cost narrative: a quiet instrument note above the cost DNA. */
.cost-insight {
	max-width: 460px;
	margin: 0 0 1.4rem;
	padding: 0.7rem 0.9rem;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	border-left: 2px solid var(--accent);
	border-radius: var(--radius-control);
}
.cost-insight__eyebrow { margin: 0 0 0.3rem; }
.cost-insight__text {
	margin: 0;
	color: var(--text-secondary);
	font-size: 14px;
	line-height: 1.5;
}
.cost-insight__updating {
	margin-left: 0.4rem;
	color: var(--text-muted);
	font-style: italic;
	font-size: 13px;
}

.cmp-card__foot {
	margin-top: auto;
	padding: 0.6rem 1rem 0.85rem;
	border-top: 1px solid var(--border-subtle);
	font-family: var(--font-mono);
	font-size: 10.5px;
	color: var(--text-4);
	font-variant-numeric: tabular-nums slashed-zero;
}

.comparison-sort-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 14px;
	gap: 12px;
	flex-wrap: wrap;
	view-transition-name: comparison-sort-bar;
}

/* ==========================================================================
   Car List Sort Bar
   ========================================================================== */

.car-list-sort-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 6px 0;
	margin-bottom: 12px;
	border-bottom: 1px solid var(--border-subtle);
	flex-wrap: wrap;
}

.car-list-sort-label {
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-3);
	white-space: nowrap;
}

.comparison-sort-controls {
	display: flex;
	align-items: center;
	gap: 6px;
}

.sort-select-label {
	color: var(--text-3);
	white-space: nowrap;
}

.sort-select {
	font-size: 11px;
	padding: 3px 8px;
	border-radius: 6px;
	border: 1px solid var(--border-subtle);
	background: var(--tint-xs);
	color: var(--text-2);
	cursor: pointer;
	outline: none;
}

.sort-select:focus {
	border-color: var(--clr-accent);
}

.sort-dir-btn {
	font-size: 12px;
	padding: 3px 9px;
	border-radius: 6px;
	border: 1px solid var(--border-subtle);
	background: var(--tint-xs);
	color: var(--text-2);
	cursor: pointer;
	transition: background 0.15s;
	display: inline-flex;
	align-items: center;
	text-decoration: none;
}

.sort-dir-btn:hover {
	background: var(--tint-sm, var(--tint-xs));
}

/* ==========================================================================
   Comparison cost-DNA filter pills
   A labelled, colour-matched pill per cost segment; the row doubles as the
   legend for the stacked cost bar. On = filled with the segment colour; off =
   hollow + muted. Each pill carries a .cmp-seg--<key> class that sets --seg-clr.
   ========================================================================== */

.cmp-filters {
	display: flex;
	align-items: center;
	gap: 6px;
	flex-wrap: wrap;
	margin-bottom: 14px;
}

.cmp-filters__label {
	color: var(--text-3);
	margin-right: 2px;
	white-space: nowrap;
}

.cmp-filter {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 3px 10px 3px 8px;
	border-radius: 999px;
	border: 1px solid color-mix(in oklab, var(--seg-clr, var(--text-3)) 45%, transparent);
	background: color-mix(in oklab, var(--seg-clr, var(--text-3)) 12%, transparent);
	color: var(--text-1);
	font-size: 11px;
	font-weight: 600;
	line-height: 1.4;
	text-decoration: none;
	cursor: pointer;
	transition: opacity 0.15s, background 0.15s, border-color 0.15s;
}

.cmp-filter__dot {
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: var(--seg-clr, var(--text-3));
	flex: none;
}

.cmp-filter:hover {
	border-color: var(--seg-clr, var(--text-3));
}

.cmp-filter--off {
	border-color: var(--border-subtle);
	background: transparent;
	color: var(--text-3);
	opacity: 0.7;
}

.cmp-filter--off .cmp-filter__lbl {
	text-decoration: line-through;
	text-decoration-thickness: 1px;
}

.cmp-filter--off .cmp-filter__dot {
	background: transparent;
	border: 1.5px solid var(--text-3);
}

.cmp-filter--off:hover {
	opacity: 1;
	border-color: var(--seg-clr, var(--text-3));
}

.comparison-chart-wrapper {
	margin-top: 20px;
}

/* ==========================================================================
   Import Modal (native <dialog> element)
   ========================================================================== */

/* Import Modal - specific styles (uses form-modal base) */

.import-body {
	padding: 1.5rem 2rem 2rem;
}

.import-textarea {
	font-family: var(--font-mono);
	font-size: 0.875rem;
	resize: vertical;
	min-height: 160px;
}

.import-checkbox-label {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	color: var(--text-2);
	cursor: pointer;
	transition: all var(--timing-base) var(--ease-out);
	padding: 0.25rem;
	border-radius: 4px;
}

.import-checkbox-label:hover {
	color: var(--text-1);
	background: var(--tint-sm);
	transform: translateX(2px);
}

.import-checkbox-label input[type="checkbox"] {
	cursor: pointer;
	transition: transform var(--timing-fast) var(--ease-out);
}

.import-checkbox-label:active input[type="checkbox"] {
	transform: scale(0.9);
}

.import-preview-section {
	display: none;
	opacity: 0;
	transform: translateY(-10px);
}

.import-preview-section.is-visible {
	display: block;
	animation: fadeIn var(--timing-slow) var(--ease-out) forwards;
}

.import-preview-table-container {
	overflow-x: auto;
	margin-bottom: 1.5rem;
}

.import-preview-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.875rem;
}

.import-preview-table thead {
	background: var(--surface-2);
}

.import-preview-table th {
	padding: 0.75rem;
	text-align: left;
	border-bottom: 2px solid var(--surface-3);
	color: var(--text-2);
	font-weight: 600;
}

.import-preview-table th.align-right {
	text-align: right;
}

.import-preview-table tbody tr {
	border-bottom: 1px solid var(--surface-2);
	transition: all var(--timing-base) var(--ease-out);
}

.import-preview-table tbody tr:hover {
	background: var(--tint-sm);
	transform: scale(1.002);
}

.import-preview-table td {
	padding: 0.75rem;
	color: var(--text-1);
	transition: color var(--timing-fast) var(--ease-out);
}

.import-preview-table tr:hover td {
	color: var(--text);
}

.import-preview-table td.align-right {
	text-align: right;
	font-family: var(--font-mono);
}

.import-preview-table .preview-more-rows {
	text-align: center;
	color: var(--text-2);
	font-style: italic;
}

.import-preview-summary {
	padding: 1rem;
	background: var(--surface-2);
	border-radius: 4px;
	margin-bottom: 1rem;
	color: var(--text-1);
}

.import-preview-summary strong {
	color: var(--text);
}

.import-preview-summary .error-count {
	color: var(--clr-repair);
}

.import-errors {
	display: none;
	padding: 1rem;
	background: light-dark(
		color-mix(in oklab, var(--clr-repair) 8%, white),
		color-mix(in oklab, var(--clr-repair) 12%, #1c1b16)
	);
	border-left: 3px solid var(--clr-repair);
	border-radius: 4px;
	margin-bottom: 1.5rem;
	color: var(--ink);
}

.import-errors.is-visible {
	display: block;
}

.import-errors ul {
	margin: 0.5rem 0 0 0;
	padding-left: 1.5rem;
}

.import-errors li {
	margin-bottom: 0.25rem;
}

.import-errors .more-errors {
	font-style: italic;
	color: var(--text-2);
}

/* ==========================================================================
   Car Form Modal
   ========================================================================== */

.form-modal {
	border: none;
	border-radius: 16px;
	padding: 0;
	max-width: 600px;
	width: calc(100vw - 2rem);
	max-height: 90vh;
	background: transparent;
	opacity: 0;
	transform: scale(0.9) translateY(-20px);
	transition: opacity var(--timing-slow) var(--ease-spring),
	            transform var(--timing-slow) var(--ease-spring);
}

.form-modal[open] {
	opacity: 1;
	transform: scale(1) translateY(0);
	animation: popIn var(--timing-slow) var(--ease-spring);
}

/* §56 — styled dialog (window.__confirm/__prompt/__notify; replaces native
   confirm()/prompt()/alert()). The card surface/border/shadow come from
   .form-modal-content and the spring pop-in from .form-modal[open]; this layers
   on the "Editorial x Instrument" treatment -- a Playfair serif prompt over an
   Inter action row -- with generous, consistent padding and a flush, right-
   aligned footer (no hard separator) so the whole thing reads as one composed
   card. */
.confirm-dialog {
	max-width: 27rem;
	min-width: min(23rem, calc(100vw - 2rem));
}

/* Compound selector (both classes sit on the same element) so this beats the
   later `.form-modal-content { padding: 0 }` rule -- equal specificity would
   otherwise let the source-order-later zero win and flatten the padding. */
.form-modal-content.confirm-dialog__content {
	padding: 2rem;
}

/* An accent hairline eyebrow above the prompt -- a small editorial flourish
   that ties the card to the brand accent (the same green as the primary btn). */
.confirm-dialog__content::before {
	content: "";
	display: block;
	width: 2.25rem;
	height: 2px;
	margin: 0 0 1.15rem;
	border-radius: var(--radius-pill);
	background: var(--confirm-accent, var(--accent));
	opacity: 0.9;
}

/* §56 notice severity: recolour the eyebrow (and, for warn/error/success, swap
   the flourish for a tinted icon) from the callout tone tokens, so an error
   notice no longer reads like a neutral one. 'info' (the default, incl. every
   confirm/prompt) keeps today's accent hairline and shows no icon.
   The icon sits in a soft tone-tinted disc (the design system's .icon-chip
   pattern) so the severity reads as a coloured *area*, not a thin hairline
   stroke -- a bare stroke in the black-mixed light-mode callout tones is nearly
   indistinguishable at icon scale. Disc tint + solid-tone glyph per data-level. */
#ui-dialog .confirm-dialog__icon {
	display: none;
	place-items: center;
	width: 2.4rem;
	height: 2.4rem;
	margin: 0 0 1rem;
	border-radius: 50%;
	background: var(--confirm-accent, var(--accent)); /* solid tone disc -- reads as colour at a glance, unlike a faint tint or thin stroke */
}
/* #ui-dialog-scoped so the glyph's size/colour beat the base `.icon` rule
   (defined later in the sheet -- equal class specificity would let it win on
   source order and shrink the glyph to 1em / the inherited text colour). The
   glyph is --surface (the card/page colour): near-white on light, near-black on
   dark, so it always contrasts the solid tone disc in either theme. */
#ui-dialog .confirm-dialog__icon .icon {
	width: 1.25rem;
	height: 1.25rem;
	color: var(--surface);
}
#ui-dialog[data-level="warn"]    { --confirm-accent: var(--clr-service); }
#ui-dialog[data-level="error"]   { --confirm-accent: var(--critical); } /* --critical: the app's saturated alert red */
#ui-dialog[data-level="success"] { --confirm-accent: var(--clr-sell); }
/* Wash the whole card with a hint of the severity tone (and tint its border a
   touch more) so the colour extends past the badge. --modal-content-bg is a
   gradient, so the tone can't be color-mix'd into it directly; instead overlay a
   flat tone layer *above* the gradient via background-image (theme-correct via
   the light-dark tone tokens). 'info' is untouched. */
#ui-dialog:not([data-level="info"]) .confirm-dialog__content {
	background-image:
		linear-gradient(color-mix(in oklab, var(--confirm-accent) 8%, transparent), color-mix(in oklab, var(--confirm-accent) 8%, transparent)),
		var(--modal-content-bg);
	border-color: color-mix(in oklab, var(--confirm-accent) 24%, var(--modal-border));
}
/* When a severity icon is present it takes the eyebrow slot -- hide the hairline
   so the two accent marks don't stack. */
#ui-dialog:not([data-level="info"]) .confirm-dialog__content::before { display: none; }
#ui-dialog:not([data-level="info"]) .confirm-dialog__icon { display: grid; }

/* The prompt carries the editorial voice: high-contrast display serif at a
   headline scale, balanced wrapping so a short question keeps no orphan word. */
.confirm-dialog__msg {
	margin: 0 0 1.5rem;
	font-family: var(--font-serif);
	font-size: 1.3rem;
	font-weight: 500;
	line-height: 1.35;
	letter-spacing: -0.01em;
	color: var(--text);
	text-wrap: balance;
}

/* Prompt input: full-width well with room to breathe. CSS owns the spacing now
   (dialogs.ts only toggles display), so no inline margin fights this. */
.confirm-dialog__content .form-input {
	width: 100%;
	margin: 0 0 1.5rem;
}

/* §73 Inc: pick-one record-mode chooser rendered by __choose() into the shared
   dialog. Each option is a titled + described full-width button. */
.confirm-dialog__choices {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	width: 100%;
	margin: 0.25rem 0 1rem;
	text-align: left;
}
.record-choice {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	width: 100%;
	padding: 0.7rem 0.85rem;
	border: 1px solid var(--border);
	background: none;
	border-radius: var(--radius-control);
	text-align: left;
	font: inherit;
	color: var(--text);
	cursor: pointer;
}
.record-choice:hover,
.record-choice:focus-visible {
	background: var(--tint-sm);
	border-color: var(--accent);
}
.record-choice__title {
	font-weight: 600;
}
.record-choice__desc {
	font-size: 13px;
	line-height: 1.35;
	color: var(--text-2);
}

/* §73 named-locations manager in the Fahrten panel. */
.fahrten-places {
	margin-top: 1.5rem;
	padding-top: 1rem;
	border-top: 1px solid var(--border);
}
.places-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	margin-bottom: 0.5rem;
}
.place-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
}
.place-list__item {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.25rem 0;
}
.place-list__item .icon {
	width: 1.05em;
	height: 1.05em;
	color: var(--accent);
	flex: none;
}
.place-list__name {
	font-weight: 500;
}
.place-list__item .btn--icon {
	margin-left: auto;
}

/* §73 kept-track map: a tile-less, server-projected SVG polyline (no basemap). */
.trip-map-wrap {
	background: var(--surface-sunken, color-mix(in oklab, var(--surface) 94%, var(--ink)));
	border: 1px solid var(--border);
	border-radius: var(--radius-md, 8px);
	padding: 0.5rem;
}
.trip-map {
	display: block;
	width: 100%;
	height: auto;
}
.trip-map__line {
	stroke: var(--accent);
	stroke-width: 2.5;
	stroke-linejoin: round;
	stroke-linecap: round;
	vector-effect: non-scaling-stroke;
}
.trip-map__pt--start {
	fill: var(--surface);
	stroke: var(--accent);
	stroke-width: 2.5;
}
.trip-map__pt--end {
	fill: var(--accent);
}
.trip-map-meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 1.75rem;
	margin-top: 0.85rem;
}
.trip-map-meta div {
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
}
.trip-map-meta dt {
	font-size: 0.75rem;
	color: var(--ink-subtle, var(--muted));
	text-transform: uppercase;
	letter-spacing: 0.03em;
}
.trip-map-meta dd {
	font-weight: 500;
}

/* §73 Inc 5 trip billing */
.trip-billing {
	margin-top: 0.75rem;
	padding-top: 0.85rem;
	border-top: 1px solid var(--border);
}
.form-check {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	cursor: pointer;
	font-weight: 500;
}
.form-check input {
	width: 1.05rem;
	height: 1.05rem;
	accent-color: var(--accent);
}
.trip-bill-tag {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	margin-top: 0.25rem;
	font-size: 0.8rem;
	color: var(--ink-subtle, var(--muted));
	/* Stay one line — the trip table h-scrolls on mobile, so the client name must
	   not char-wrap inside the narrow route cell. */
	white-space: nowrap;
}
.trip-bill-tag .place-list__name,
.trip-bill-tag > span {
	white-space: nowrap;
}
.trip-bill-tag .icon {
	width: 0.85em;
	height: 0.85em;
}
.trip-bill-tag__done {
	color: var(--accent);
	font-weight: 500;
}

/* Footer flush with the card: drop .form-actions' separator + top inset so the
   dialog reads as one block; keep the buttons right-aligned with a snug gap. */
.confirm-dialog .form-actions {
	padding-top: 0;
	margin-top: 0;
	border-top: 0;
	gap: 0.6rem;
}

.form-modal::backdrop {
	background: rgba(0, 0, 0, 0);
	transition: background var(--timing-slow) var(--ease-out);
}

.form-modal[open]::backdrop {
	background: var(--modal-scrim);
	backdrop-filter: blur(4px);
	animation: fadeIn var(--timing-slow) var(--ease-out);
}

.form-modal--wide {
	max-width: 800px;
}

.form-modal-content {
	background: var(--modal-content-bg);
	border: 1px solid var(--modal-border);
	border-radius: 16px;
	padding: 0;
	max-height: 90vh;
	overflow-y: auto;
	box-shadow: var(--shadow-modal);
	/* Animate height changes when step content swaps */
	interpolate-size: allow-keywords;
	transition: height 0.38s cubic-bezier(0.4, 0, 0.2, 1);
	height: auto;
}

.form-body {
	padding: 1.5rem 2rem 2rem;
}

.form-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 1.5rem 2rem;
	border-bottom: 1px solid var(--border);
	background: var(--tint-xs);
}

.form-title {
	margin: 0;
	font-size: 1.5rem;
	font-weight: 600;
	color: var(--text);
	letter-spacing: -0.02em;
}
#car-form,
#charge-form {
	padding: 1.5rem 2rem 2rem;
}

.form-section {
	margin-bottom: 1.5rem;
}

.settings-profile-hint {
	font-size: 0.8rem;
	color: var(--text-muted);
	background: var(--accent-soft);
	border: 1px solid color-mix(in oklab, var(--accent) 22%, transparent);
	border-radius: 6px;
	padding: 0.5rem 0.875rem;
	margin-bottom: 1rem;
}

.form-section:last-of-type {
	margin-bottom: 0;
}

.form-section-title {
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--text-3);
	margin-bottom: 0.75rem;
	padding-bottom: 0.5rem;
	border-bottom: 1px solid var(--border-subtle);
}

/* Tabbed car form (§5 form-layout): underline tabs mirroring .car-tab, panels
   toggled by the $form_tab Datastar signal. All fields stay in one <form>. */
.form-tabs {
	display: flex;
	gap: 0.25rem;
	flex-wrap: wrap;
	margin-bottom: 1.5rem;
	border-bottom: 1px solid var(--border-subtle);
}

.form-tab {
	appearance: none;
	background: none;
	border: none;
	border-bottom: 2px solid transparent;
	margin-bottom: -1px;
	padding: 0.55rem 0.9rem;
	font: inherit;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.1px;
	color: var(--text-4);
	white-space: nowrap;
	cursor: pointer;
	transition: color var(--timing-fast) var(--ease-out), border-color var(--timing-fast) var(--ease-out);
}

.form-tab:hover {
	color: var(--text-2);
}

.form-tab--active {
	color: var(--ink);
	border-bottom-color: var(--accent);
}

@media (max-width: 640px) {
	.form-tabs {
		flex-wrap: nowrap;
		overflow-x: auto;
		scrollbar-width: none;
	}
}

/* §35 scanned-form intro: the source-image preview + the hint/notices summary,
   inset to match the form body's horizontal padding (the block sits between the
   header and the padding-0 modal content, so it must carry its own inset). */
.scan-intro {
	display: flex;
	flex-wrap: wrap;
	gap: 1.25rem 1.5rem;
	align-items: flex-start;
	padding: 1.5rem 2rem 0;
}

.scan-intro-text {
	flex: 1 1 260px;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

/* §35 source-image preview — the scanned Fahrzeugausweis the model saw, shown
   next to the prefilled form so the user can verify field-by-field. */
.scan-source {
	flex: 1 1 200px;
	max-width: 260px;
	margin: 0;
}

.scan-source-img {
	width: 100%;
	height: auto;
	max-height: 40vh;
	object-fit: contain;
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-control);
	background: var(--surface-sunken);
	display: block;
}

.scan-source-caption {
	margin-top: 0.4rem;
	font-size: 0.72rem;
	text-align: center;
	color: var(--text-3);
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.scan-hint {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 0.75rem;
	margin: 0;
}

.scan-hint .form-hint {
	margin: 0;
}

.scan-discard-confirm {
	align-items: center;
	gap: 0.75rem;
}

.scan-discard-confirm .form-hint {
	margin-right: auto;
}

/* §35 Phase 2: validator warnings + smart-default hints on the scanned form. */
.scan-notices {
	list-style: none;
	margin: 0;
	padding: 0.65rem 0.85rem;
	border: 1px solid color-mix(in srgb, var(--clr-service) 45%, transparent);
	border-radius: 8px;
	background: color-mix(in srgb, var(--clr-service) 10%, transparent);
	font-size: 0.85rem;
	color: var(--text-2);
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
}

.scan-notices li {
	padding-left: 1.1rem;
	position: relative;
}

.scan-notices li::before {
	content: "⚠";
	position: absolute;
	left: 0;
	color: var(--clr-service);
}

/* §35 per-field highlighting: an input prefilled from the Fahrzeugausweis scan
   (accent). Warned fields override this with .form-input--warn (see below). */
.form-input--scan {
	border-color: color-mix(in oklab, var(--clr-accent) 55%, transparent);
	background: color-mix(in oklab, var(--clr-accent) 6%, transparent);
}

.form-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 1rem;
}

.form-field {
	display: flex;
	flex-direction: column;
	gap: 0.375rem;
}

.form-field--full {
	grid-column: 1 / -1;
}

.form-label {
	font-size: 0.8rem;
	font-weight: 500;
	color: var(--text-2);
	display: flex;
	align-items: center;
	gap: 0.25rem;
}

.form-label-required {
	color: var(--clr-repair);
}

.form-label-hint {
	font-weight: 400;
	color: var(--text-2);
	font-size: 0.8em;
}

.form-field--checkbox {
	display: flex;
	align-items: center;
}

.form-label--checkbox {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	cursor: pointer;
	font-weight: 500;
	color: var(--text-2);
}

.form-input {
	padding: 0.625rem 0.875rem;
	font-size: 0.9rem;
	border: 1px solid var(--border);
	border-radius: 8px;
	background: var(--scrim-md);
	color: var(--text);
	transition: all var(--timing-base) var(--ease-out);
	font-family: inherit;
}

.form-input::placeholder {
	color: var(--text-4);
}

.form-input:hover {
	border-color: var(--tint-lg);
	background: var(--scrim-lg);
}

.form-input:focus {
	outline: none;
	border-color: var(--accent);
	background: var(--scrim-lg);
	box-shadow: 0 0 0 3px var(--accent-glow),
	            0 0 20px var(--accent-glow);
}

.form-input[type="number"] {
	font-family: var(--font-mono);
}

select.form-input {
	cursor: pointer;
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%239ca3af' d='M2.5 4.5L6 8L9.5 4.5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 0.75rem center;
	padding-right: 2.5rem;
}

.form-hint {
	font-size: 0.75rem;
	color: var(--text-4);
	margin-top: 0.25rem;
}

.form-hint__icon { color: var(--accent); }

.form-actions {
	display: flex;
	justify-content: flex-end;
	gap: 0.75rem;
	padding-top: 1.5rem;
	margin-top: 1.5rem;
	border-top: 1px solid var(--border);
}
/* Responsive */
@media (max-width: 480px) {
	.form-modal-content {
		padding: 0;
	}
	
	.form-header {
		padding: 1rem 1.25rem;
	}
	
	#car-form,
	#charge-form {
		padding: 1rem 1.25rem 1.5rem;
	}
	
	.form-grid {
		grid-template-columns: 1fr;
	}
	
	.form-actions {
		flex-direction: column-reverse;
	}
	
	.form-actions .btn,
	.modal__footer .btn {
		width: 100%;
		justify-content: center;
	}
}/* Inline entry editing */
.entry-row {
	position: relative;
	transition: all var(--timing-base) var(--ease-out);
}

.entry-row:hover {
	background: var(--tint-sm) !important;
}

.th-actions {
	width: 60px;
}

.entry-actions {
	text-align: center;
	white-space: nowrap;
}

.entry-actions--view {
	opacity: 0;
	transition: opacity var(--timing-base) var(--ease-out);
}

.entry-row:hover .entry-actions--view {
	opacity: 1;
}
/* §11 phase-3: synthetic gap-segment row — muted/dashed, never interactive
   (no edit button, so no hover affordance). */
.entry-row--gap {
	font-style: italic;
}

.entry-row--gap:hover {
	background: transparent !important;
}

.entry-row--gap td {
	color: var(--text-4);
	border-bottom-style: dashed;
}

.entry-amount--gap {
	font-family: var(--font-mono);
}
.entry-actions {
	white-space: nowrap;
	text-align: center;
}
/* ==========================================================================
   Cost Pie Chart Component
   ========================================================================== */

.cost-pie-container {
	display: flex;
	gap: 1.5rem;
	align-items: center;
	padding: 1rem;
	background: var(--tint-xs);
	border-radius: 8px;
	margin: 1rem 0;
}

.cost-pie-chart {
	width: 120px;
	height: 120px;
	flex-shrink: 0;
}

.cost-pie-chart path {
	transition: opacity 0.2s;
	cursor: pointer;
}

.cost-pie-chart path:hover {
	opacity: 0.8;
}

/* §13 two-ring comparison donut rendered via <tco-chart> (ECharts), so it shares
   the bar chart's styled hover tooltips. Sized squarer than the bar chart. */
.cost-pie-echarts { display: block; width: 100%; height: 210px; }

.cost-pie-legend {
	flex: 1;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
	gap: 0.5rem;
	font-size: 0.75rem;
}

.legend-item {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.legend-color {
	width: 12px;
	height: 12px;
	border-radius: 2px;
	flex-shrink: 0;
}

.legend-label {
	color: var(--text-2);
	flex: 1;
}

.legend-value {
	color: var(--text-1);
	font-family: var(--font-mono);
	font-weight: 600;
}

/* ==========================================================================
   Empty State (first-run welcome, §35 Fahrzeugausweis dropzone)
   ========================================================================== */

.empty-state {
	max-width: 640px;
	margin: clamp(2rem, 6vw, 4.5rem) auto;
	padding: clamp(1.75rem, 4vw, 3rem);
	text-align: center;
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	box-shadow: var(--shadow-lg);
	animation: fadeInScale var(--timing-slower) var(--ease-out);
}

.empty-state-icon {
	display: inline-grid;
	place-items: center;
	width: 4.25rem;
	height: 4.25rem;
	margin: 0 auto 1rem;
	border-radius: 50%;
	color: var(--accent);
	background: var(--accent-soft);
}
.empty-state-icon .icon { font-size: 1.9rem; stroke-width: 1.6; }

.empty-state .eyebrow { margin-bottom: 0.6rem; }

.empty-state-title {
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 560;
	font-size: clamp(1.6rem, 4vw, 2.15rem);
	letter-spacing: -0.015em;
	line-height: 1.15;
	color: var(--ink);
	margin-bottom: 0.85rem;
}

.empty-state-description {
	font-size: 1rem;
	color: var(--text-2);
	line-height: 1.65;
	max-width: 30rem;
	margin: 0 auto 2rem;
}

.empty-state-actions {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 1.1rem;
}

.empty-state-divider {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	width: 100%;
	max-width: 20rem;
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--text-4);
}
.empty-state-divider::before, .empty-state-divider::after {
	content: "";
	flex: 1;
	height: 1px;
	background: var(--border-subtle);
}

.empty-state-hint {
	font-size: 0.85rem;
	color: var(--text-4);
	font-style: italic;
	margin: 0;
}

/* ── §35 Fahrzeugausweis dropzone (the welcome screen's primary CTA) ────── */
.empty-dropzone {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.4rem;
	width: 100%;
	padding: clamp(1.75rem, 4vw, 2.5rem) 1.5rem;
	border: 1.5px dashed var(--border);
	border-radius: var(--radius-card);
	color: var(--text-3);
	cursor: pointer;
	transition: color var(--timing-base) var(--ease-out), border-color var(--timing-base) var(--ease-out), background var(--timing-base) var(--ease-out), transform var(--timing-base) var(--ease-out);
}
.empty-dropzone:hover, .empty-dropzone.is-dragging {
	color: var(--accent);
	border-color: var(--accent);
	background: var(--tint-sm);
}
.empty-dropzone.is-dragging { transform: scale(1.015); }
/* Children never intercept drag events — dragover/drop always hit .empty-dropzone. */
.empty-dropzone * { pointer-events: none; }
.empty-dropzone__prompt { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; }
.empty-dropzone__title { font-family: var(--font-serif); font-size: 1.1rem; color: var(--text); }
.empty-dropzone__hint { font-size: 0.85rem; }
.empty-dropzone__types { font-size: 0.72rem; color: var(--text-4); letter-spacing: 0.02em; margin-top: 0.15rem; }

/* Add-car modal: the same §35 dropzone, compacted to sit atop the manual form.
   Like .scan-intro, this block lives in the padding-0 modal content between the
   header and #car-form, so it carries its own inset to match the form body's
   horizontal padding (2rem); #car-form's own padding-top handles the gap below. */
.car-form-scan { padding: 1.5rem 2rem 0; }
.car-form-dropzone { padding: 1.1rem 1.25rem; }
.car-form-scan__divider {
	text-align: center;
	font-size: 0.74rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-4);
	margin-top: 0.55rem;
}

/* ── §35 scanner overlay: while the dropped Fahrzeugausweis is being OCR'd ──
   A skeleton card of the document with a sweeping "scanner beam", a live
   status line, and an indeterminate progress bar. Driven by $ausweisScan
   (set on drop/pick, released by the LiveSSE loop on done/error). */
.empty-dropzone.is-scanning {
	border-style: solid;
	border-color: color-mix(in oklab, var(--accent) 55%, transparent);
	background: var(--tint-xs);
	cursor: default;
	pointer-events: none; /* no second file while a scan is in flight */
	transform: none;
	min-height: 12rem;
	justify-content: center;
}

.ausweis-scan {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 1rem;
	width: 100%;
	animation: fadeIn var(--timing-slow) var(--ease-out);
}

.ausweis-scan__doc {
	position: relative;
	width: 9.5rem;
	height: 6rem;
	padding: 0.6rem;
	display: flex;
	flex-direction: column;
	gap: 0.42rem;
	border-radius: 7px;
	overflow: hidden;
	background: linear-gradient(180deg, color-mix(in oklab, var(--accent) 6%, var(--surface-raised)), var(--surface-raised));
	border: 1px solid color-mix(in oklab, var(--accent) 22%, transparent);
	box-shadow: 0 6px 18px color-mix(in oklab, var(--accent) 14%, transparent);
}
.ausweis-scan__chip {
	width: 1.5rem;
	height: 1.1rem;
	border-radius: 3px;
	background: color-mix(in oklab, var(--accent) 26%, transparent);
}
.ausweis-scan__line {
	height: 0.42rem;
	border-radius: 3px;
	background: linear-gradient(90deg, var(--tint-md), var(--tint-sm), var(--tint-md));
	background-size: 200% 100%;
	animation: shimmer 1.8s linear infinite;
}
.ausweis-scan__line--short { width: 62%; }

/* The beam: a soft accent band wiping top→bottom, clipped to the doc. */
.ausweis-scan__beam {
	position: absolute;
	left: -10%;
	right: -10%;
	top: 0;
	height: 40%;
	transform: translateY(-120%);
	background: linear-gradient(180deg,
		transparent,
		color-mix(in oklab, var(--accent) 30%, transparent) 42%,
		color-mix(in oklab, var(--accent) 65%, transparent) 50%,
		color-mix(in oklab, var(--accent) 30%, transparent) 58%,
		transparent);
	animation: ausweis-beam 1.9s var(--ease-in-out) infinite;
}
@keyframes ausweis-beam {
	0%   { transform: translateY(-120%); opacity: 0; }
	14%  { opacity: 1; }
	86%  { opacity: 1; }
	100% { transform: translateY(280%); opacity: 0; }
}

.ausweis-scan__copy { display: flex; flex-direction: column; align-items: center; gap: 0.2rem; text-align: center; }
.ausweis-scan__title {
	display: inline-flex;
	align-items: baseline;
	font-family: var(--font-serif);
	font-size: 1.05rem;
	color: var(--accent);
}
.ausweis-scan__hint { font-size: 0.82rem; color: var(--text-3); }

.ausweis-scan__dots { display: inline-flex; gap: 0.15rem; margin-left: 0.25rem; }
.ausweis-scan__dots i {
	width: 0.24rem;
	height: 0.24rem;
	border-radius: 50%;
	background: currentColor;
	opacity: 0.25;
	animation: ausweis-dot 1.4s ease-in-out infinite;
}
.ausweis-scan__dots i:nth-child(2) { animation-delay: 0.18s; }
.ausweis-scan__dots i:nth-child(3) { animation-delay: 0.36s; }
@keyframes ausweis-dot {
	0%, 80%, 100% { opacity: 0.25; transform: translateY(0); }
	40%           { opacity: 1;    transform: translateY(-0.14rem); }
}

.ausweis-scan__bar {
	position: relative;
	width: min(16rem, 82%);
	height: 3px;
	border-radius: 2px;
	overflow: hidden;
	background: var(--tint-sm);
}
.ausweis-scan__bar > span {
	position: absolute;
	top: 0;
	bottom: 0;
	width: 40%;
	border-radius: 2px;
	background: linear-gradient(90deg, transparent, var(--accent), transparent);
	animation: ausweis-indeterminate 1.4s var(--ease-in-out) infinite;
}
@keyframes ausweis-indeterminate {
	0%   { left: -42%; }
	100% { left: 100%; }
}

@media (prefers-reduced-motion: reduce) {
	.ausweis-scan__beam, .ausweis-scan__line, .ausweis-scan__dots i, .ausweis-scan__bar > span { animation: none; }
	.ausweis-scan__beam { opacity: 0.45; transform: translateY(75%); }
	.ausweis-scan__bar > span { left: 0; width: 100%; opacity: 0.6; }
	.ausweis-scan__dots i { opacity: 0.6; }
}

/* ==========================================================================
   App Footer
   ========================================================================== */

.app-footer {
	margin-top: 4rem;
	/* A quiet "plinth" band that closes the page. min-height + flex centering
	   keep the content vertically centred within the band instead of flush
	   against the very bottom edge on short pages (where #carlist's flex-grow pins
	   the footer to the viewport bottom). padding-block gives symmetric room. */
	min-height: 5rem;
	padding-block: 1.6rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border-top: 1px solid var(--border-subtle);
	background: var(--surface-sunken);
}

.footer-content {
	max-width: 980px;
	margin: 0 auto;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 0.15rem 0;
	text-align: center;
	font-size: 0.85rem;
	line-height: 1.6;
	color: var(--text-3);
}

.footer-version {
	color: var(--text-3);
	font-weight: 500;
}

/* §63 the version rendered as a quiet mono "build stamp" pill — leans into the
   Instrument half of the design language. */
.footer-badge {
	margin-left: 0.4rem;
	font-family: var(--font-mono);
	font-size: 0.68rem;
	letter-spacing: 0.02em;
	line-height: 1;
	color: var(--text-4);
	background: var(--tint-xs);
	border: 1px solid var(--border-subtle);
	padding: 0.14rem 0.45rem;
	border-radius: var(--radius-pill);
	vertical-align: middle;
}

.footer-divider {
	margin: 0 0.7rem;
	color: var(--text-5);
	opacity: 0.7;
}

.footer-link {
	color: var(--text-3);
	text-decoration: none;
	transition: all var(--timing-base) var(--ease-out);
	position: relative;
	display: inline-block;
}

.footer-link::after {
	content: '';
	position: absolute;
	bottom: -2px;
	left: 0;
	width: 0;
	height: 1px;
	background: var(--accent);
	transition: width var(--timing-base) var(--ease-out);
}

.footer-link:hover {
	color: var(--accent);
	transform: translateY(-1px);
}

.footer-link:hover::after {
	width: 100%;
}

/* §52 self-hosted update check: the badge replaces .footer-link's <a> with a
   <button> (it triggers the release-notes modal, not a navigation), so it
   needs its own reset -- plain browser button chrome would otherwise show. */
.footer-link--update {
	background: none;
	border: none;
	padding: 0;
	font: inherit;
	cursor: pointer;
	color: var(--accent);
	font-weight: 600;
}

.footer-link--update:hover {
	color: var(--accent);
}

.update-modal-entry {
	padding: 0.85rem 0;
	border-bottom: 1px solid var(--border-subtle);
}

.update-modal-entry:last-child {
	border-bottom: 0;
}

.update-modal-entry__head {
	display: flex;
	align-items: baseline;
	gap: 0.6rem;
}

.update-modal-entry__version {
	font-family: var(--font-mono);
	font-weight: 600;
	color: var(--accent);
}

.update-modal-entry__date {
	font-size: 0.8rem;
	color: var(--text-4);
}

.update-modal-entry__items {
	margin: 0.4rem 0 0;
	padding-left: 1.25rem;
	color: var(--text-3);
	font-size: 0.9rem;
}

.update-modal-entry__items li {
	margin-bottom: 0.2rem;
}

/* Reduce motion for users who prefer it */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}
}

/* ==========================================================================
   Import Column Mapping
   ========================================================================== */

.import-mapping-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.8rem;
	margin-bottom: 1rem;
}

.import-mapping-table th,
.import-mapping-table td {
	padding: 0.5rem;
	border: 1px solid var(--border);
	text-align: left;
}

.import-mapping-table th {
	background: var(--bg-2);
	font-weight: 600;
}

.import-mapping-table tr:nth-child(even) {
	background: var(--bg-2);
}

.mapping-select {
	width: 100%;
	padding: 0.25rem 0.5rem;
	font-size: 0.75rem;
	background: var(--bg);
	border: 1px solid var(--border);
	border-radius: 4px;
	color: var(--text);
}

.mapping-select:focus {
	outline: none;
	border-color: var(--accent);
}

.mapping-highlight {
	background: var(--accent-glow) !important;
	border-color: var(--accent) !important;
}

/* ==========================================================================
   TCO Wizard Modal
   ========================================================================== */

.wiz-subtitle {
	margin: 0.2rem 0 0;
	font-size: 0.8rem;
	color: var(--text-3);
}

/* Progress pills */
.wiz-progress {
	display: flex;
	align-items: center;
	gap: 0;
	padding: 1rem 2rem;
	border-bottom: 1px solid var(--border-subtle);
	background: var(--scrim-md);
}

.wiz-step-pill {
	padding: 0.3rem 0.9rem;
	border-radius: 20px;
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	background: var(--tint-sm);
	color: var(--text-4);
	border: 1px solid var(--border-subtle);
	transition: all var(--timing-base) var(--ease-out);
	white-space: nowrap;
}

.wiz-step-pill--active {
	background: var(--clr-buy-bg);
	color: var(--clr-highlight);
	border-color: var(--clr-buy-border);
}

.wiz-step-connector {
	flex: 1;
	height: 1px;
	background: var(--border-subtle);
	min-width: 0.5rem;
}

/* Body */
.wiz-body {
	padding: 1.5rem 2rem 0.5rem;
}

/* Finance type selector */
.wiz-fin-selector {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 0.75rem;
	margin-bottom: 0.5rem;
}

.wiz-fin-option {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.3rem;
	padding: 1rem 0.75rem;
	border-radius: 12px;
	border: 1px solid var(--border);
	background: var(--tint-xs);
	cursor: pointer;
	transition: all var(--timing-base) var(--ease-out);
	text-align: center;
}

.wiz-fin-option input[type="radio"] {
	display: none;
}

.wiz-fin-option:hover {
	border-color: color-mix(in oklab, var(--accent) 30%, transparent);
	background: color-mix(in oklab, var(--accent) 5%, transparent);
}

.wiz-fin-option--active {
	border-color: color-mix(in oklab, var(--accent) 50%, transparent) !important;
	background: color-mix(in oklab, var(--accent) 10%, transparent) !important;
	box-shadow: 0 0 16px color-mix(in oklab, var(--accent) 15%, transparent);
}

.wiz-fin-icon {
	font-size: 1.75rem;
	line-height: 1;
}

.wiz-fin-label {
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--text);
}

.wiz-fin-desc {
	font-size: 0.7rem;
	color: var(--text-3);
	line-height: 1.4;
}

/* Tips & Callouts */
.wiz-tip {
	margin-top: 0.75rem;
	padding: 0.6rem 0.9rem;
	border-radius: 8px;
	background: var(--tint-xs);
	border-left: 3px solid color-mix(in oklab, var(--accent) 40%, transparent);
	font-size: 0.775rem;
	color: var(--text-3);
	line-height: 1.5;
}

/* ── Residual value estimate hint ───────────────────────────────────────── */
.wiz-estimate-hint {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin-top: 0.3rem;
	flex-wrap: wrap;
}

.wiz-estimate-label {
	font-size: 0.73rem;
	color: var(--text-3);
	white-space: nowrap;
}
.wiz-callout {
	margin-top: 1rem;
	padding: 0.9rem 1rem;
	border-radius: 10px;
	font-size: 0.8rem;
	line-height: 1.6;
}

.wiz-callout--info {
	background: color-mix(in oklab, var(--accent) 7%, transparent);
	border: 1px solid color-mix(in oklab, var(--accent) 20%, transparent);
}

.wiz-callout-title {
	font-weight: 700;
	margin-bottom: 0.4rem;
	color: var(--text);
}

.wiz-callout-body {
	color: var(--text-2);
}

.wiz-callout-body ul {
	margin: 0.4rem 0 0 1rem;
	padding: 0;
}

.wiz-callout-body li {
	margin-bottom: 0.2rem;
}

/* Result header */
.wiz-result-header {
	display: flex;
	align-items: center;
	gap: 1rem;
	padding: 1rem 0 1.25rem;
	border-bottom: 1px solid var(--border-subtle);
	margin-bottom: 1.25rem;
}

.wiz-result-car-name {
	font-size: 1.35rem;
	font-weight: 700;
	color: var(--text);
	letter-spacing: -0.02em;
}

.wiz-result-fin-badge {
	padding: 0.25rem 0.75rem;
	border-radius: 20px;
	background: var(--clr-buy-bg);
	border: 1px solid var(--clr-buy-border);
	color: var(--clr-highlight);
	font-size: 0.75rem;
	font-weight: 600;
}

/* Result table */
.wiz-result-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.875rem;
}

.wiz-result-table tbody tr {
	border-bottom: 1px solid var(--border-subtle);
}

.wiz-result-table tbody td {
	padding: 0.6rem 0.5rem;
	color: var(--text-2);
}

.wiz-result-table tfoot tr {
	border-top: 1px solid var(--border);
}

.wiz-result-table tfoot td {
	padding: 0.65rem 0.5rem;
	font-weight: 600;
	color: var(--text);
}

.wiz-result-total-row--secondary td {
	color: var(--text-2);
	font-size: 0.85rem;
}

.wiz-result-total-row--highlight td {
	color: var(--clr-highlight);
	font-size: 1rem;
	font-weight: 700;
}

.wiz-result-amount {
	text-align: right;
	font-variant-numeric: tabular-nums;
}

/* ── Inline row edit controls ─────────────────────────────────────────────── */
.wiz-edit-cell {
	width: 1.75rem;
	text-align: center;
	padding: 0 0.15rem;
}

.wiz-edit-btn {
	background: none;
	border: none;
	cursor: pointer;
	color: var(--text-4);
	font-size: 0.75rem;
	padding: 0.2rem 0.25rem;
	border-radius: 4px;
	line-height: 1;
	opacity: 0.5;
	transition: opacity 0.15s, color 0.15s;
}

.wiz-result-table tbody tr:hover .wiz-edit-btn {
	opacity: 1;
}

.wiz-edit-btn:hover,
.wiz-edit-btn:focus-visible {
	color: var(--clr-highlight);
	opacity: 1;
	outline: none;
}

.wiz-amount-input {
	width: 5.5rem;
	text-align: right;
	font-size: 0.8rem;
	font-variant-numeric: tabular-nums;
	padding: 0.15rem 0.35rem;
	border: 1px solid var(--clr-highlight);
	border-radius: 4px;
	background: var(--bg-2);
	color: var(--text);
}

.wiz-result-extra-row td {
	color: var(--text-3);
	font-style: italic;
}

/* Step panel entry animation — @starting-style fires on display:none→block */
/* No allow-discrete = exit is instant, entry fades in. No double-animation. */
.wiz-step {
	opacity: 1;
	transform: translateY(0);
	transition: opacity 0.25s ease, transform 0.25s ease;
}

@starting-style {
	.wiz-step {
		opacity: 0;
		transform: translateY(10px);
	}
}

/* Comparison bars */
.wiz-comparison-list {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
}

.wiz-comparison-row {
	display: grid;
	grid-template-columns: 200px 1fr 80px;
	align-items: center;
	gap: 0.75rem;
	padding: 0.5rem 0;
	border-bottom: 1px solid var(--border-subtle);
}

.wiz-comparison-row--new {
	background: color-mix(in oklab, var(--accent) 5%, transparent);
	border-radius: 6px;
	padding: 0.5rem 0.5rem;
	border: 1px solid color-mix(in oklab, var(--accent) 15%, transparent);
	border-bottom-color: color-mix(in oklab, var(--accent) 15%, transparent);
	margin-bottom: 0.3rem;
}

.wiz-compare-name {
	font-size: 0.8rem;
	color: var(--text-2);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.wiz-comparison-row--new .wiz-compare-name {
	color: var(--clr-highlight);
	font-weight: 600;
}

.wiz-compare-bar-wrap {
	height: 12px;
	background: var(--tint-sm);
	border-radius: 6px;
	overflow: hidden;
}

@keyframes growBar {
	from { transform: scaleX(0); }
	to   { transform: scaleX(1); }
}

@keyframes fadeInRow {
	from { opacity: 0; transform: translateX(-6px); }
	to   { opacity: 1; transform: translateX(0); }
}

.wiz-compare-bar {
	height: 100%;
	border-radius: 6px;
	background: linear-gradient(90deg, color-mix(in oklab, var(--accent) 60%, transparent), color-mix(in oklab, var(--accent) 90%, transparent));
	width: var(--w, 0%);
	transform-origin: left center;
	animation: growBar 0.5s cubic-bezier(0.4, 0, 0.2, 1) both;
	animation-delay: var(--wiz-bar-delay, 0s);
}

.wiz-compare-bar--new {
	background: linear-gradient(90deg, color-mix(in oklab, var(--accent) 70%, transparent), color-mix(in oklab, var(--accent) 100%, transparent));
}

.wiz-comparison-row {
	animation: fadeInRow 0.3s var(--ease-out, ease-out) both;
	animation-delay: var(--wiz-bar-delay, 0s);
}

.wiz-compare-value {
	font-size: 0.8rem;
	font-variant-numeric: tabular-nums;
	text-align: right;
	color: var(--text-2);
}

.wiz-comparison-row--new .wiz-compare-value {
	color: var(--clr-highlight);
	font-weight: 700;
}

/* ── Tooltip (cost row info buttons) ──────────────────────── */
.wiz-tip-wrap {
	position: relative;
	display: inline-flex;
	align-items: baseline;
	gap: 0.3em;
}

.wiz-tip-btn {
	appearance: none;
	background: none;
	border: none;
	padding: 0;
	font-size: 0.7rem;
	line-height: 1;
	color: var(--text-4);
	cursor: help;
	transition: color 0.15s;
	vertical-align: middle;
}

.wiz-tip-btn:hover,
.wiz-tip-btn:focus-visible {
	color: var(--accent);
	outline: none;
}

/* Base tooltip — absolute fallback for non-supporting browsers */
.wiz-tooltip {
	position: absolute;
	bottom: calc(100% + 8px);
	left: 50%;
	transform: translateX(-50%) translateY(4px);
	z-index: 200;
	width: 220px;
	max-width: min(260px, 90vw);
	background: var(--tooltip-bg);
	border: 1px solid var(--tooltip-border);
	border-radius: 8px;
	padding: 0.55rem 0.75rem;
	font-size: 0.76rem;
	line-height: 1.5;
	color: var(--tooltip-text);
	box-shadow: var(--shadow-lg);
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.15s, transform 0.15s;
}

.wiz-tip-btn:hover + .wiz-tooltip,
.wiz-tip-btn:focus-visible + .wiz-tooltip {
	opacity: 1;
	pointer-events: auto;
	transform: translateX(-50%) translateY(0);
}

/* Modern CSS anchor positioning — Chrome/Edge 125+, overrides the absolute */
@supports (anchor-name: --x) {
	.wiz-tooltip {
		position: fixed;
		bottom: unset;
		left: unset;
		transform: translateY(4px);
		top: anchor(bottom);
		left: anchor(center);
		translate: -50% 8px;
		position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
	}

	.wiz-tip-btn:hover + .wiz-tooltip,
	.wiz-tip-btn:focus-visible + .wiz-tooltip {
		transform: none;
		translate: -50% 0;
	}
}

/* Navigation — reuses the general modal footer's horizontal/bottom padding
   tokens (see .modal__footer) so the wizard's footer isn't flush against the
   modal edges; keeps its own tighter top gap + subtle divider. */
.wiz-actions {
	border-top: 1px solid var(--border-subtle);
	padding: 1rem var(--modal-pad-x) var(--modal-pad-y);
}

/* Responsive */
@media (max-width: 600px) {
	.wiz-progress {
		padding: 0.75rem 1rem;
		gap: 0;
	}
	.wiz-step-pill {
		font-size: 0.62rem;
		padding: 0.25rem 0.5rem;
	}
	.wiz-body {
		padding: 1rem 1rem 0.5rem;
	}
	.wiz-fin-selector {
		grid-template-columns: 1fr;
	}
	.wiz-comparison-row {
		grid-template-columns: 130px 1fr 65px;
	}
}

/* ── OCR Invoice Scan ─────────────────────────────────────────────────────── */

.ocr-notice {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        flex-wrap: wrap;
        background: var(--surface-2);
        border: 1px solid var(--border-subtle);
        border-radius: var(--radius-control);
        padding: 0.5rem 0.75rem;
        margin-bottom: 1rem;
        font-size: 0.85rem;
}

.ocr-ai-label {
        font-weight: 600;
        color: var(--text-2);
}

.ocr-confidence {
        font-size: 0.8rem;
        padding: 0.15rem 0.5rem;
        border-radius: 999px;
        font-weight: 600;
}

.ocr-confidence--high  { background: var(--clr-sell-bg); color: var(--clr-sell); }
.ocr-confidence--medium { background: color-mix(in oklab, var(--clr-service) 14%, transparent); color: var(--clr-service); }
.ocr-confidence--low   { background: var(--clr-repair-bg); color: var(--clr-repair); }

/* §33 — shared inline AI transparency notice, rendered before every model call. */
.ai-disclaimer {
        display: flex;
        align-items: flex-start;
        gap: 0.5rem;
        flex-wrap: wrap;
        background: var(--surface-2);
        border: 1px solid var(--border-subtle);
        border-radius: var(--radius-control);
        padding: 0.5rem 0.75rem;
        margin-bottom: 1rem;
        font-size: 0.8rem;
        line-height: 1.5;
        color: var(--text-2);
}

.ai-disclaimer__icon { flex: none; font-size: 1.05rem; color: var(--accent); margin-top: 0.05rem; }

.ai-disclaimer__body { flex: 1 1 12rem; min-width: 0; }

.ai-disclaimer__warn { color: var(--clr-repair); font-weight: 600; }

.ai-disclaimer__link {
        flex: none;
        white-space: nowrap;
        text-decoration: underline;
        color: var(--accent);
}

/* Shown in place of an AI affordance when the master ai_enabled switch is off. */
.ai-disabled-hint {
        display: inline-flex;
        align-items: center;
        gap: 0.4rem;
        font-size: 0.8rem;
        color: var(--text-3);
}

.ocr-vendor {
        font-size: 0.9rem;
        color: var(--text-2);
        margin: 0 0 0.75rem;
}

.ocr-lineitems-table {
        width: 100%;
        border-collapse: collapse;
        font-size: 0.85rem;
        margin-top: 0.25rem;
}

.ocr-lineitems-table th,
.ocr-lineitems-table td {
        padding: 0.25rem 0.5rem;
        border-bottom: 1px solid var(--border-subtle);
        text-align: left;
}

.ocr-lineitems-table th {
        font-weight: 600;
        color: var(--text-2);
        font-size: 0.78rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
}

.ocr-lineitems-amount {
        text-align: right !important;
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
}

.ocr-usage {
        font-size: 0.8rem;
        color: var(--text-3);
        text-align: right;
        margin: 0.5rem 0 0;
}

.ocr-reconcile-warning {
        margin: 0.75rem 0 0;
        padding: 0.5rem 0.75rem;
        border-radius: var(--radius-control);
        background: color-mix(in oklab, var(--clr-service) 14%, transparent);
        color: var(--clr-service);
        border: 1px solid color-mix(in oklab, var(--clr-service) 45%, transparent);
        font-size: 0.82rem;
        font-weight: 600;
}

/* ── OCR two-pane modal layout ────────────────────────────────────────────── */

.ocr-modal-body {
        display: flex;
        gap: 1.5rem;
        align-items: flex-start;
        padding: 1.5rem 2rem 2rem;
}

.ocr-image-pane {
        flex: 0 0 42%;
        max-width: 42%;
}

.ocr-invoice-img {
        width: 100%;
        height: auto;
        max-height: 72vh;
        object-fit: contain;
        border: 1px solid var(--border-subtle);
        border-radius: var(--radius-control);
        background: var(--surface-sunken);
        display: block;
        position: sticky;
        top: 0.5rem;
}

.ocr-form-pane {
        flex: 1;
        min-width: 0;
}

/* ── OCR multi-invoice batch modal (§29) ─────────────────────────────────── */

.ocr-batch-list {
        display: flex;
        flex-direction: column;
        gap: 1rem;
        padding: 0 2rem;
        max-height: 64vh;
        overflow-y: auto;
}

.ocr-batch-card {
        border: 1px solid var(--border-subtle);
        border-radius: var(--radius-control);
        padding: 1rem 1.25rem;
        transition: opacity 0.15s ease;
}

.ocr-batch-card--excluded {
        opacity: 0.45;
}

/* ── §30 service-booklet confirm modal ────────────────────────────────────── */

.booklet-warnings {
        margin: 0 0 0.75rem;
        padding: 0.5rem 0.75rem 0.5rem 1.5rem;
        border-radius: var(--radius-control);
        background: color-mix(in oklab, var(--clr-service) 14%, transparent);
        color: var(--clr-service);
        border: 1px solid color-mix(in oklab, var(--clr-service) 45%, transparent);
        font-size: 0.8rem;
        font-weight: 600;
        list-style: disc;
}

.booklet-warnings li + li {
        margin-top: 0.25rem;
}

/* highlight the odometer input when the record carries a plausibility warning */
.form-input--warn {
        border-color: var(--clr-service);
        background: color-mix(in oklab, var(--clr-service) 8%, transparent);
}

.booklet-next {
        display: inline-flex;
        align-items: center;
        font-size: 0.9rem;
        font-weight: 600;
        color: var(--text-secondary);
}

/* ── §30 Serviceheft history on the Wartung tab ───────────────────────────── */

.booklet-section {
        margin-top: 2rem;
        padding-top: 1.5rem;
        border-top: 1px solid var(--border-subtle);
}

.section-head--sub {
        margin-bottom: 0.75rem;
}

.booklet-audit-head {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        flex-wrap: wrap;
        font-size: 1rem;
}

.booklet-audit-notes {
        margin: 0 0 1rem;
        padding: 0.5rem 0.75rem 0.5rem 1.5rem;
        border-radius: var(--radius-control);
        background: color-mix(in oklab, var(--clr-service) 8%, transparent);
        border: 1px solid color-mix(in oklab, var(--clr-service) 45%, transparent);
        font-size: 0.82rem;
        list-style: disc;
}

.booklet-audit-notes li + li {
        margin-top: 0.25rem;
}

.booklet-audit-flag {
        color: #b91c1c;
        font-weight: 600;
}

.booklet-audit-gap {
        color: var(--clr-service);
}

.booklet-late {
        display: inline-block;
        margin-left: 0.4rem;
        padding: 0.05rem 0.4rem;
        border-radius: 999px;
        background: color-mix(in oklab, var(--clr-service) 14%, transparent);
        color: var(--clr-service);
        border: 1px solid color-mix(in oklab, var(--clr-service) 45%, transparent);
        font-size: 0.72rem;
        font-weight: 600;
        white-space: nowrap;
}

.ocr-batch-card-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        margin-bottom: 0.75rem;
}

.ocr-batch-include {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
        cursor: pointer;
}

.ocr-batch-title {
        font-weight: 700;
        font-size: 0.95rem;
}

.ocr-batch-pages {
        color: var(--text-3);
        font-weight: 400;
        margin-left: 0.25rem;
}

.ocr-batch-card .ocr-modal-body {
        padding: 0;
        gap: 1rem;
}

.ocr-image-pane--sm {
        flex: 0 0 28%;
        max-width: 28%;
}

.ocr-image-pane--sm .ocr-invoice-img {
        max-height: 40vh;
        position: static;
}


/* ── OCR Setup Callout (settings page) ───────────────────────────────────── */

.ocr-setup-callout {
        background: var(--accent-soft);
        border: 1px solid var(--clr-accent-subtle);
        border-radius: var(--radius-control);
        padding: 1rem 1.25rem;
        margin-bottom: 1.25rem;
}

.ocr-setup-callout-title {
        font-weight: 700;
        font-size: 0.95rem;
        color: var(--accent);
        margin-bottom: 0.75rem;
}

.ocr-setup-steps {
        margin: 0 0 0.75rem 1.25rem;
        padding: 0;
        display: flex;
        flex-direction: column;
        gap: 0.4rem;
        font-size: 0.9rem;
        color: var(--text-2);
}

.ocr-setup-steps a {
        color: var(--accent);
        font-weight: 600;
}

.ocr-setup-steps a:hover { text-decoration: underline; }

.ocr-setup-callout-note {
        margin: 0;
        font-size: 0.8rem;
        color: var(--text-3);
}

.ocr-error-message {
        margin: 1rem 0;
        padding: 0.75rem 1rem;
        background: var(--clr-repair-bg);
        color: var(--clr-repair);
        border-radius: 6px;
        font-size: 0.9rem;
        line-height: 1.5;
        word-break: break-word;
}

@media (max-width: 680px) {
        .ocr-modal-body {
                flex-direction: column;
        }
        .ocr-image-pane {
                flex: none;
                max-width: 100%;
        }
        .ocr-invoice-img {
                max-height: 45vh;
                position: static;
        }
}

/* Entry positions badge (number indicator on description cell) */
.entry-positions-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.2em;
  padding: 0 0.35em;
  margin-left: 0.35rem;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.4;
  cursor: pointer;
  border: none;
  vertical-align: middle;
  transition: opacity 0.15s;
}
.entry-positions-badge:hover {
  opacity: 0.82;
}

/* §21 "view retained original" affordance — an eye icon-link on entries / booklet
   rows / the car hero (only shown when a source image was retained). */
.asset-view-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-left: 0.4rem;
  color: var(--text-4);
  vertical-align: middle;
  transition: color 0.15s;
}
.asset-view-link:hover {
  color: var(--color-primary);
}
.asset-view-link .icon {
  width: 1em;
  height: 1em;
}
.asset-view-link--labeled {
  font-size: 0.85rem;
}

/* Split form-actions (delete left, save/cancel right) */
.form-actions--split {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.form-actions-right {
  display: flex;
  gap: 0.5rem;
  margin-left: auto;
}
/* Car-detail tab strip (§20) — same visual language as the top nav, sits below
   the persistent hero + stat header; horizontally scrollable on small screens. */
.car-tabs {
	display: flex;
	gap: 0.25rem;
	margin: 1.5rem 0 1.25rem;
	flex-wrap: wrap;
	border-bottom: 1px solid var(--border-subtle);
}

/* Tab/view switchers are full-reload <a> links (car-detail tabs, settings rail,
   cockpit trend toggle); the #content-top fragment lands the reload on the switched
   content rather than the page top. scroll-margin clears the 56px sticky mobile
   topbar (+ a little breathing room) so the anchor isn't hidden under it. A cheap
   stopgap until these morph in place. */
#content-top {
	scroll-margin-top: 4.5rem;
}

.car-tab {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	padding: 0.55rem 0.9rem;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.1px;
	color: var(--text-4);
	text-decoration: none;
	border-bottom: 2px solid transparent;
	margin-bottom: -1px;
	white-space: nowrap;
	transition: color var(--timing-fast) var(--ease-out), border-color var(--timing-fast) var(--ease-out);
}

.car-tab .icon {
	width: 1.05em;
	height: 1.05em;
	color: var(--text-5);
	transition: color var(--timing-fast) var(--ease-out);
}

.car-tab:hover {
	color: var(--text-2);
}

.car-tab:hover .icon {
	color: var(--text-3);
}

.car-tab--active {
	color: var(--ink);
	border-bottom-color: var(--accent);
}

.car-tab--active .icon {
	color: var(--accent);
}

.car-tab__count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 1.25rem;
	height: 1.25rem;
	padding: 0 0.35rem;
	border-radius: 999px;
	background: var(--surface-3, var(--border-subtle));
	color: var(--text-3);
	font-size: 11px;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	line-height: 1;
}

.car-tab--active .car-tab__count {
	background: var(--accent);
	color: var(--surface-1);
}

@media (max-width: 640px) {
	.car-tabs {
		flex-wrap: nowrap;
		overflow-x: auto;
		scrollbar-width: none;
	}

	.car-tabs::-webkit-scrollbar {
		display: none;
	}
}

/* Vergleich chart sub-navigation */
.vergleich-subnav {
	display: flex;
	gap: 0.5rem;
	margin: 1rem 0;
	flex-wrap: wrap;
}

.section-hint {
	color: var(--text-4);
	font-size: 13px;
	padding: 1rem 0;
}

/* ───────────────────────── Übersicht (dashboard) ───────────────────── */

.dashboard {
	display: flex;
	flex-direction: column;
	gap: clamp(1.1rem, 2.4vw, 1.75rem);
}

/* Cheapest-car stat doubles as a link to its detail page. */
a.stat { text-decoration: none; }
a.stat:hover { border-color: color-mix(in oklab, var(--accent) 45%, transparent); }

.truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }

/* Inline "more →" link in section heads. */
.text-link {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.04em;
	color: var(--accent);
	text-decoration: none;
}
.text-link .icon { font-size: 0.95em; transition: transform var(--timing-base) var(--ease-out); }
.text-link:hover .icon { transform: translateX(3px); }

/* Quick-link cards under the dashboard. */
.quick-links {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: 0.75rem;
}
.quick-link {
	display: flex;
	align-items: center;
	gap: 0.85rem;
	padding: 0.9rem 1.1rem;
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	text-decoration: none;
	color: inherit;
	transition: border-color var(--timing-base) var(--ease-out), transform var(--timing-base) var(--ease-out);
}
.quick-link:hover {
	border-color: color-mix(in oklab, var(--accent) 40%, transparent);
	transform: translateY(-2px);
}
.quick-link__body { display: flex; flex-direction: column; gap: 0.05rem; flex: 1; min-width: 0; }
.quick-link__label { font-weight: 600; color: var(--ink); font-size: 14px; }
.quick-link__sub {
	font-family: var(--font-mono);
	font-size: 12px;
	letter-spacing: 0.02em;
	color: var(--text-4);
}
.quick-link > .icon { color: var(--text-5); transition: transform var(--timing-base) var(--ease-out); }
.quick-link:hover > .icon { color: var(--accent); transform: translateX(3px); }

.settings-content {
	padding: clamp(1.1rem, 2.4vw, 2.2rem);
}

/* ==========================================================================
   Design system additions  (icons, tabular figures, polish, a11y)
   Unlayered + appended last, so these win over earlier component rules.
   ========================================================================== */

/* Inline SVG icon from the Lucide sprite. Sized in em so it tracks font-size;
   stroke colour follows currentColor. */
.icon {
	width: 1em;
	height: 1em;
	flex: none;
	display: inline-block;
	vertical-align: -0.14em;
	color: currentColor;
	stroke-width: 2;
}
.icon--lg { font-size: 1.35em; }
.icon--xl { font-size: 2em; stroke-width: 1.75; }

/* Tabular, slashed-zero figures everywhere money/distance/dates are shown, so
   columns align. Zero specificity (:where) — purely additive. */
:where(
	.pill-value,
	[class*="summary-value"], .cost-pie-legend, .entry-table td,
	.entry-table-component td, .footer-version
) {
	font-variant-numeric: tabular-nums slashed-zero;
}
/* Respect the OS "reduce motion" setting — kill the decorative entrances. */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ==========================================================================
   Editorial × Instrument — shared component primitives + responsive system
   Appended last (unlayered) so it composes over the legacy component blocks.
   Vocabulary: .eyebrow / .section-head, .stat(-grid), .icon-chip,
   .activity-list/.activity-row, .segmented. Reused by every redesigned view.
   ========================================================================== */

/* ── Eyebrow + section header ───────────────────────────────────────────── */
.eyebrow {
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--text-4);
	margin: 0;
}

.section-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem 1.5rem;
	flex-wrap: wrap;
	margin-bottom: 1.1rem;
}

.section-head__titles { display: flex; flex-direction: column; gap: 0.3rem; }

.section-head__title {
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 520;
	font-size: clamp(18px, 2.4vw, 23px);
	letter-spacing: -0.012em;
	line-height: 1.1;
	color: var(--ink);
	margin: 0;
}

/* ── Stat block (instrument readout) ────────────────────────────────────── */
.stat-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	gap: clamp(0.6rem, 1.4vw, 1rem);
}

.stat {
	display: flex;
	flex-direction: column;
	gap: 0.45rem;
	padding: clamp(1rem, 2vw, 1.4rem) clamp(1rem, 2vw, 1.5rem);
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	transition: border-color var(--timing-base) var(--ease-out);
}

.stat__value {
	font-family: var(--font-mono);
	font-weight: 600;
	font-size: clamp(21px, 2.7vw, 29px);
	line-height: 1.05;
	letter-spacing: -0.01em;
	color: var(--ink);
	font-variant-numeric: tabular-nums slashed-zero;
}

.stat__unit {
	font-family: var(--font-mono);
	font-size: 0.5em;
	font-weight: 600;
	color: var(--text-4);
	letter-spacing: 0.04em;
	margin-left: 0.3em;
}

.stat__label {
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--text-4);
	line-height: 1.45;
}

/* ── Icon-chip (colored round category glyph) ───────────────────────────── */
.icon-chip {
	display: inline-grid;
	place-items: center;
	width: 2.3rem;
	height: 2.3rem;
	border-radius: 50%;
	flex: none;
	color: var(--chip-fg, var(--text-2));
	background: var(--chip-bg, var(--tint-sm));
}
.icon-chip .icon { font-size: 1.05rem; stroke-width: 2; }
.icon-chip--sm { width: 1.9rem; height: 1.9rem; }
.icon-chip--sm .icon { font-size: 0.95rem; }
.icon-chip--service { --chip-fg: var(--clr-service); --chip-bg: var(--clr-service-bg); }
.icon-chip--repair  { --chip-fg: var(--clr-repair);  --chip-bg: var(--clr-repair-bg); }
.icon-chip--accent  { --chip-fg: var(--accent);      --chip-bg: var(--accent-soft); }
.icon-chip--muted   { --chip-fg: var(--text-3);      --chip-bg: var(--tint-sm); }

/* ── Activity list (the mockups' "recent activity" pattern) ─────────────── */
.activity-list { display: flex; flex-direction: column; }

.activity-row {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: 0.85rem;
	padding: 0.7rem 0;
	border-bottom: 1px solid var(--border-subtle);
	text-decoration: none;
	color: inherit;
	transition: padding-left var(--timing-base) var(--ease-out);
}
.activity-row:last-child { border-bottom: 0; }
a.activity-row:hover { padding-left: 0.35rem; }

.activity-row__body { min-width: 0; }
.activity-row__title {
	font-weight: 600;
	color: var(--ink);
	font-size: 13.5px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.activity-row__meta {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--text-4);
	font-variant-numeric: tabular-nums slashed-zero;
	margin-top: 0.12rem;
}
/* §12 reminders: secondary car name on the title line + open-count badge */
.activity-row__sub { font-weight: 400; color: var(--text-3); }
.termine-open-badge {
	font-size: 11px;
	font-weight: 600;
	padding: 3px 10px;
	border-radius: 999px;
	color: var(--clr-service);
	background: var(--clr-service-bg);
	border: 1px solid var(--clr-service-border);
	white-space: nowrap;
}

/* ── Segmented control ──────────────────────────────────────────────────── */
.segmented {
	display: inline-flex;
	align-items: center;
	padding: 3px;
	gap: 2px;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-pill);
}
.segmented__item {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.42rem 0.95rem;
	font-size: 12px;
	font-weight: 600;
	color: var(--text-3);
	text-decoration: none;
	border: 0;
	background: transparent;
	cursor: pointer;
	border-radius: var(--radius-pill);
	white-space: nowrap;
	transition: background var(--timing-fast) var(--ease-out), color var(--timing-fast) var(--ease-out);
}
.segmented__item:hover { color: var(--text); }
.segmented__item--active {
	background: var(--surface-raised);
	color: var(--ink);
	box-shadow: 0 1px 2px var(--scrim-sm);
}
.segmented__item .icon { color: currentColor; }

/* ── Card surface primitive (panels around lists/tables) ─────────────────── */
.panel {
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	padding: clamp(1rem, 2.2vw, 1.5rem);
}

/* ==========================================================================
   §31 Streamlined Upload — Journal list-as-dropzone (Phase 1)
   The panel is the drop target; the annotated two-zone overlay is drag-only
   (data-show), and the resting hint is the at-rest affordance on an empty list.
   ========================================================================== */
.journal-panel { position: relative; }

/* Resting hint on an empty Journal list — subtle, discoverable without a drag. */
.journal-drop-hint {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.6rem;
	padding: clamp(1.5rem, 5vw, 2.75rem);
	margin-top: 0.5rem;
	border: 1.5px dashed var(--border);
	border-radius: var(--radius-card);
	color: var(--text-4);
	cursor: pointer;
	text-align: center;
	transition: color var(--timing-base) var(--ease-out), border-color var(--timing-base) var(--ease-out), background var(--timing-base) var(--ease-out);
}
.journal-drop-hint:hover {
	color: var(--accent);
	border-color: var(--accent);
	background: var(--tint-sm);
}
.journal-drop-hint__text { font-size: 0.9rem; }

/* Drag overlay — shown only while a file is dragged over the panel. */
.journal-dropzone {
	position: absolute;
	inset: 0;
	z-index: 5;
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	padding: clamp(0.75rem, 2vw, 1.25rem);
	border-radius: var(--radius-card);
	background: color-mix(in oklab, var(--surface-raised) 88%, transparent);
	backdrop-filter: blur(2px);
}
.journal-dropzone__meta {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 0.4rem;
	font-size: 0.8rem;
	color: var(--text-3);
}
.journal-dropzone__targets {
	flex: 1;
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0.75rem;
	min-height: 0;
}
.dz-target {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.35rem;
	padding: 1rem;
	border: 1.5px dashed var(--border);
	border-radius: var(--radius-control);
	color: var(--text-3);
	text-align: center;
	transition: color var(--timing-base) var(--ease-out), border-color var(--timing-base) var(--ease-out), background var(--timing-base) var(--ease-out);
}
.dz-target:hover {
	color: var(--accent);
	border-color: var(--accent);
	background: var(--tint-sm);
}
/* Children never intercept drag events — dragover/drop always hit .dz-target. */
.dz-target * { pointer-events: none; }
.dz-target__title { font-family: var(--font-serif); font-size: 1.05rem; color: var(--text); }
.dz-target__hint { font-size: 0.85rem; }
.dz-target__types { font-size: 0.72rem; color: var(--text-4); letter-spacing: 0.02em; }
.journal-dropzone__disabled {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	color: var(--text-4);
	text-align: center;
}

@media (max-width: 640px) {
	.journal-dropzone__targets { grid-template-columns: 1fr; }
}

/* ==========================================================================
   §31 Streamlined Upload — multi-file intake prepare modal (Phase 2)
   The dialog reuses the .form-modal chrome; these style the thumbnail rail, the
   per-file status chips, and the object-URL previews the client builds on drop.
   ========================================================================== */
.intake-remaining { margin-left: auto; font-size: 0.8rem; color: var(--text-3); }
/* §31: two footer states (progress+scan vs discard-confirm) toggled by
   $intakeConfirm; each is a full-width flex row so only one shows at a time. */
.intake-footer__main,
.intake-footer__confirm { display: flex; align-items: center; gap: 0.75rem; flex: 1 1 100%; }
.intake-progress { margin-right: auto; font-size: 0.8rem; color: var(--text-3); }
.intake-confirm-msg { margin-right: auto; font-size: 0.85rem; color: var(--text-2); }
.intake-rail {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
	gap: 0.75rem;
	max-height: 55vh;
	overflow-y: auto;
	padding: 0.25rem;
	margin-bottom: 1rem;
}
.intake-card {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	padding: 0.5rem;
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-control);
	background: var(--surface-sunken);
}
.intake-card__thumb {
	aspect-ratio: 4 / 3;
	display: grid;
	place-items: center;
	overflow: hidden;
	border-radius: calc(var(--radius-control) - 2px);
	background: var(--surface);
}
.intake-card__thumb img { width: 100%; height: 100%; object-fit: cover; }
.intake-card__thumb--pdf {
	font-size: 0.85rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	color: var(--text-4);
}
.intake-card__name {
	font-size: 0.72rem;
	color: var(--text-3);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.intake-chip {
	align-self: flex-start;
	font-size: 0.7rem;
	padding: 0.1rem 0.45rem;
	border-radius: var(--radius-pill);
	border: 1px solid var(--border);
	color: var(--text-3);
}
.intake-chip--uploading { color: var(--clr-buy);    border-color: color-mix(in oklab, var(--clr-buy) 40%, transparent); }
.intake-chip--ready     { color: var(--accent);     border-color: color-mix(in oklab, var(--accent) 45%, transparent); }

/* §31 Phase 3 — pre-scan editor: rail (left) + editor pane (right). */
.intake-body { display: flex; gap: 1rem; align-items: flex-start; padding: 1.5rem 2rem 0; }
.intake-body .intake-rail { flex: 1 1 52%; min-width: 0; margin-bottom: 0; }
.intake-card--editable { cursor: pointer; transition: border-color 0.12s ease; }
.intake-card--editable:hover { border-color: var(--accent); }
.intake-card--sel { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.intake-card__thumb { position: relative; }
.intake-card__edited {
	position: absolute; top: 0.25rem; right: 0.25rem;
	width: 1.2rem; height: 1.2rem; display: grid; place-items: center;
	font-size: 0.8rem; line-height: 1;
	border-radius: var(--radius-pill);
	background: color-mix(in oklab, var(--accent) 88%, black); color: #fff;
}
.intake-editor {
	flex: 1 1 44%; display: flex; flex-direction: column; gap: 0.75rem;
	padding: 0.75rem; border: 1px solid var(--border-subtle);
	border-radius: var(--radius-control); background: var(--surface-sunken);
}
.intake-edit-stage {
	position: relative; height: 46vh; overflow: hidden;
	touch-action: none; user-select: none;
	border-radius: calc(var(--radius-control) - 2px); background: var(--surface);
	/* faint checker so white rotation corners / margins read against the stage */
	background-image:
		linear-gradient(45deg, var(--border-subtle) 25%, transparent 25%),
		linear-gradient(-45deg, var(--border-subtle) 25%, transparent 25%),
		linear-gradient(45deg, transparent 75%, var(--border-subtle) 75%),
		linear-gradient(-45deg, transparent 75%, var(--border-subtle) 75%);
	background-size: 16px 16px; background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}
/* zoom/pan container fills the stage (transform driven by the editor controller); */
/* the image is centered inside and only rotates (that transform is Datastar-driven). */
.intake-edit-zoom { position: absolute; inset: 0; display: grid; place-items: center; will-change: transform; }
.intake-edit-img { max-width: 94%; max-height: 94%; object-fit: contain; transition: transform 0.08s linear; }
/* crop rectangle: a dashed frame whose big spread-shadow dims everything outside it. */
.intake-crop {
	position: absolute; pointer-events: none;
	border: 2px dashed var(--accent);
	box-shadow: 0 0 0 9999px color-mix(in oklab, #000 45%, transparent);
}
.intake-edit-controls { display: flex; flex-direction: column; gap: 0.6rem; }
.intake-edit-row { display: flex; align-items: center; gap: 0.5rem; }
.intake-edit-slider { flex: 1; min-width: 0; }
.intake-edit-nudge { padding: 0.25rem 0.6rem; font-variant-numeric: tabular-nums; }
.intake-edit-mode.is-active { background: var(--accent); color: #fff; border-color: var(--accent); }
.intake-edit-zoomlabel { min-width: 3rem; text-align: center; font-variant-numeric: tabular-nums; color: var(--text-2); }
.intake-edit-angle { min-width: 3.2rem; text-align: right; font-variant-numeric: tabular-nums; color: var(--text-2); }
.intake-edit-actions { display: flex; gap: 0.5rem; justify-content: flex-end; margin-left: auto; }
/* §64: per-file upload progress in a pending rail card renders as .progress-ring
   (see the reusable widget below); the LiveSSE loop morphs it by id. */
/* §31: scan-in-progress feedback — a spinner on the "Alle scannen" button label and
   a live per-file status line the batch handler streams into. */
.intake-scanprogress { margin-right: auto; font-size: 0.8rem; color: var(--accent); }
.intake-btn-busy::before {
	content: ""; display: inline-block; width: 0.8em; height: 0.8em;
	margin-right: 0.45em; vertical-align: -0.1em;
	border: 2px solid currentColor; border-right-color: transparent;
	border-radius: 50%; animation: intake-spin 0.7s linear infinite;
}
@keyframes intake-spin { to { transform: rotate(360deg); } }

/* §31: booklet review — each entry shows its source page; hover to magnify it in
   place (eBay-style inner zoom), so there is no overlay to fight the dialog's top
   layer. The scale is pure CSS; a one-line data-on:mousemove sets transform-origin
   to the cursor so it zooms toward that point. */
/* align-items: stretch so the photo fills the card's full height (matching the
   fields beside it); the flex stretch gives .booklet-photo a definite height that
   the image's height:100% resolves against. */
.booklet-card-body { display: flex; gap: 1rem; align-items: stretch; }
.booklet-card-body .ocr-form-pane { flex: 1 1 auto; min-width: 0; }
.booklet-photo {
	position: relative; flex: 0 0 auto; width: 240px; min-height: 220px; padding: 0; overflow: hidden;
	border: 1px solid var(--border-subtle); border-radius: var(--radius-control);
	background: var(--surface-sunken); cursor: crosshair;
}
.booklet-photo:hover { border-color: var(--accent); }
.booklet-photo img {
	display: block; width: 100%; height: 100%; object-fit: contain;
	transition: transform 0.12s ease; transform-origin: center; will-change: transform;
}
.booklet-photo:hover img { transform: scale(3.4); }
.booklet-photo__zoom {
	position: absolute; bottom: 0.3rem; right: 0.3rem;
	width: 1.5rem; height: 1.5rem; display: grid; place-items: center;
	border-radius: 50%; background: rgba(0, 0, 0, 0.55); color: #fff; font-size: 1rem; line-height: 1;
	transition: opacity 0.12s;
}
.booklet-photo:hover .booklet-photo__zoom { opacity: 0; }
@media (max-width: 640px) {
	.booklet-card-body { flex-direction: column; }
	.booklet-photo { width: 100%; height: 46vh; min-height: 0; }
}
@media (max-width: 720px) {
	.intake-body { flex-direction: column; padding: 1rem 1rem 0; }
	.intake-body .intake-rail, .intake-editor { flex-basis: auto; width: 100%; }
	.intake-edit-stage { height: 38vh; }
}

@media (max-width: 640px) {
	/* Leave room for the fixed bottom nav + iOS safe area. */
	body { padding: 18px 14px calc(76px + env(safe-area-inset-bottom)); }
	.profile-switcher { gap: 0.3rem; }
	.header-actions-right { margin-left: 0; width: 100%; }
	.header-actions-right .btn { width: 100%; }

	/* Cards collapse to a single comfortable column. */
	.stat-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Fahrzeuge list — scannable index rows (link to per-car detail)
   ========================================================================== */

.car-row {
	position: relative;
	display: flex;
	align-items: center;
	gap: clamp(0.85rem, 2vw, 1.25rem);
	padding: clamp(0.85rem, 1.8vw, 1.1rem) clamp(1rem, 2vw, 1.35rem);
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	margin-bottom: 0.7rem;
	transition: border-color var(--timing-base) var(--ease-out), transform var(--timing-base) var(--ease-out), box-shadow var(--timing-base) var(--ease-out);
}
.car-row:hover {
	border-color: var(--tint-lg);
	transform: translateY(-2px);
	box-shadow: 0 10px 28px var(--scrim-sm);
}

.car-row__photo {
	flex: none;
	width: 64px;
	height: 64px;
	border-radius: var(--radius-control);
	overflow: hidden;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
}
.car-row__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.car-row__img--ph { display: grid; place-items: center; color: var(--text-5); }

.car-row__main { flex: 1; min-width: 0; }
.car-row__name {
	display: inline-block;
	max-width: 100%;
	font-family: var(--font-serif);
	font-weight: 540;
	font-size: clamp(15px, 1.8vw, 18px);
	letter-spacing: -0.01em;
	color: var(--ink);
	text-decoration: none;
}
/* Stretched link: clicking anywhere on the row (except buttons) opens detail. */
.car-row__name::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.car-row__name:hover { color: var(--accent); }

/* Make/Model kept visible (smaller, muted) alongside a nickname (§14). */
.car-row__submodel {
	font-family: var(--font-sans);
	font-size: 0.6em;
	font-weight: 400;
	letter-spacing: 0;
	color: var(--text-4);
	margin-left: 0.5em;
}

.car-row__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.3rem 0.65rem;
	margin-top: 0.4rem;
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.01em;
	color: var(--text-3);
}
.car-row__journal { color: var(--text-4); }

.car-row__metrics {
	flex: none;
	gap: clamp(0.75rem, 1.6vw, 1.25rem);
	z-index: 1;
}

/* /fahrzeuge row: one all-in figure + a compact cost-DNA bar (no visible legend;
   the exact per-segment values are in the bar's hover title). Shares the .cmp-bar
   / .cmp-seg--* colours with the comparison cards. */
.cost-mini {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 0.4rem;
	min-width: 128px;
}
.cost-mini__hero { display: flex; align-items: baseline; gap: 0.35rem; }
.cost-mini__val {
	font-family: var(--font-mono);
	font-weight: 700;
	font-size: 22px;
	line-height: 1;
	letter-spacing: -0.01em;
	color: var(--text-1);
	font-variant-numeric: tabular-nums slashed-zero;
}
.cost-mini__unit {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-4);
}
.cost-mini__bar { width: 100%; }
/* Desktop: the foot wrapper is transparent so metrics + actions stay inline flex
   items of the row; on phones it becomes the bordered footer (see @640 below). */
.car-row__foot { display: contents; }
.car-row__actions { z-index: 1; }
.car-row__chevron { flex: none; color: var(--text-5); transition: transform var(--timing-base) var(--ease-out); }
.car-row:hover .car-row__chevron { color: var(--accent); transform: translateX(3px); }

/* ==========================================================================
   Per-car detail page
   ========================================================================== */

.car-detail { display: flex; flex-direction: column; gap: clamp(1.1rem, 2.4vw, 1.75rem); }

.back-link {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	align-self: flex-start;
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--text-4);
	text-decoration: none;
}
.back-link .icon { transition: transform var(--timing-base) var(--ease-out); }
.back-link:hover { color: var(--accent); }
.back-link:hover .icon { transform: translateX(-3px); }

.car-hero {
	display: grid;
	grid-template-columns: minmax(220px, 320px) 1fr;
	gap: clamp(1.1rem, 2.6vw, 2rem);
	align-items: stretch;
}
.car-hero__media {
	position: relative;
	/* align-self:start keeps the media at its aspect-ratio height for the column
	   width; without it the grid's stretch forces the height to match a taller
	   info column and the 16/10 ratio blows the width past the track, overlapping
	   the title (visible once the info column wraps on a narrower content area). */
	align-self: start;
	aspect-ratio: 16 / 10;
	border-radius: var(--radius-card);
	overflow: hidden;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
}
.car-hero__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.car-hero__img--ph { display: grid; place-items: center; color: var(--text-5); }

/* Empty-state silhouette doubling as the upload drop-zone (§14). */
.car-hero__img--dropzone {
	width: 100%;
	height: 100%;
	cursor: pointer;
	transition: color var(--timing-base) var(--ease-out), background var(--timing-base) var(--ease-out);
}
.car-hero__img--dropzone:hover {
	color: var(--accent);
	background: var(--tint-sm);
}

/* §64/§41: determinate upload ring scrimmed over the hero while a (possibly
   multi-MB phone) car photo uploads. data-show toggles it via $photoUp. */
.car-photo-progress {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 2;
	background: color-mix(in oklab, var(--surface-sunken) 74%, transparent);
	backdrop-filter: blur(2px);
	animation: fadeIn var(--timing-base) var(--ease-out);
}

.car-hero__info { display: flex; flex-direction: column; justify-content: center; gap: 0.55rem; min-width: 0; }
.car-hero__info .eyebrow { display: flex; align-items: center; gap: 0.35rem; }
.car-hero__name {
	margin: 0;
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 540;
	font-size: clamp(24px, 4vw, 38px);
	line-height: 1.05;
	letter-spacing: -0.018em;
	color: var(--ink);
}
.car-hero__name .car-make { font-weight: 400; color: var(--text-3); margin-right: 0.3em; }

/* Make/Model kept visible (smaller, muted) alongside a nickname (§14). */
.car-hero__submodel {
	margin: -0.35rem 0 0;
	font-family: var(--font-sans);
	font-size: 13px;
	color: var(--text-4);
}
.car-hero__meta {
	margin: 0;
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--text-3);
	font-variant-numeric: tabular-nums slashed-zero;
}
.car-hero__actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.4rem; align-items: center; }
/* §56 — keep the admin group (share + delete) together and push it to the right
   edge so the destructive action sits apart from the everyday ones. */
.car-hero__admin { display: flex; gap: 0.6rem; margin-left: auto; }
/* §56 — legible active state for the primary-vehicle toggle (was only the amber
   icon tint): soft accent fill + border when this car is the Hauptfahrzeug. */
.car-hero__primary.is-primary {
	background: var(--accent-soft);
	border-color: color-mix(in oklab, var(--accent) 30%, transparent);
}

/* Icon + label stat variant used on the detail at-a-glance row. */
.stat__label--icon { display: inline-flex; align-items: center; gap: 0.4rem; }
.stat__label--icon .icon { color: var(--text-5); font-size: 1.3em; }

/* Journal toolbar on the detail page. */
.journal-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }

/* ── §64 progress ring: a reusable "simple upload/download with progress" widget.
   A circle (r=15.915 → circumference exactly 100) whose stroke-dashoffset is
   100 − pct, with the percent inside. Server-baked per patch (intake rail cards)
   and morphed by id; the offset transitions smoothly between renders. ───────── */
.progress-ring { position: relative; width: 2rem; height: 2rem; margin: 0.35rem auto 0; }
.progress-ring__svg { width: 100%; height: 100%; transform: rotate(-90deg); display: block; }
.progress-ring__track { fill: none; stroke: color-mix(in oklab, currentColor 18%, transparent); stroke-width: 3; }
.progress-ring__bar {
	fill: none;
	stroke: var(--accent);
	stroke-width: 3;
	stroke-linecap: round;
	stroke-dasharray: 100;
	transition: stroke-dashoffset 0.25s var(--ease-out);
	filter: drop-shadow(0 0 2px color-mix(in oklab, var(--accent) 45%, transparent));
}
.progress-ring__num {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 0.62rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	color: var(--text);
	letter-spacing: -0.02em;
}
@media (prefers-reduced-motion: reduce) { .progress-ring__bar { transition: none; } }

/* §35 two-phase overlay: the upload ring is scaled up (dropzone-sized) and its
   number enlarged; each phase stacks the ring/beam + its label. */
.progress-ring--xl { width: 4rem; height: 4rem; }
.progress-ring--xl .progress-ring__num { font-size: 1.05rem; }
.ausweis-scan__phase { display: flex; flex-direction: column; align-items: center; gap: 1rem; width: 100%; }

/* §57 restore: a compact inline ring inside the "Wiederherstellen" button while
   the .db uploads. */
.progress-ring--sm { width: 1.15rem; height: 1.15rem; margin: 0; }
.progress-ring--sm .progress-ring__num { font-size: 0.5rem; }
.restore-progress { display: inline-flex; align-items: center; gap: 0.4rem; }

/* Scan dropzone: the invoice/booklet scan affordances are dashed drop targets that
   click-pick or accept a drop, both routed through the §31 intake pipeline. */
.btn.scan-drop {
	border: 1.5px dashed var(--border);
	background: transparent;
	color: var(--text-3);
	font-weight: 500;
}
.btn.scan-drop:hover, .btn.scan-drop.is-dragover {
	border-color: var(--accent);
	color: var(--accent);
	background: var(--tint-sm);
}

/* ── Mobile: list rows + hero stack ─────────────────────────────────────── */
@media (max-width: 720px) {
	.car-hero { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
	/* §63 — phone car card: photo + identity span the top, cost + actions share a
	   single bordered footer row. Keeps the action buttons from squeezing the name
	   into a 3-line wrap (the old flex-wrap layout). */
	.car-row {
		display: grid;
		grid-template-columns: 56px 1fr;
		grid-template-areas:
			"photo main"
			"foot  foot";
		align-items: center;
		column-gap: 0.85rem;
		row-gap: 0.7rem;
	}
	.car-row__photo { grid-area: photo; width: 56px; height: 56px; }
	.car-row__main { grid-area: main; }
	/* Truncate long identities to one line with an ellipsis instead of wrapping. */
	.car-row__name {
		display: block;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
	}
	.car-row__foot {
		grid-area: foot;
		display: flex;
		align-items: center;
		gap: 0.85rem;
		width: 100%;
		padding-top: 0.7rem;
		border-top: 1px solid var(--border-subtle);
	}
	.car-row__metrics { flex: 1; min-width: 0; }
	.car-row__actions { margin-left: auto; }
	.cost-mini { flex-direction: row; align-items: center; min-width: 0; }
	.cost-mini__bar { flex: 1; }
	.car-row__chevron { display: none; }
}

/* Calm the legacy row hover (no jiggle/shadow). */
.entry-table tbody tr:hover {
	transform: none;
	box-shadow: none;
	background: var(--tint-xs);
}
.entry-table thead th {
	font-family: var(--font-mono);
	letter-spacing: 0.12em;
	background: var(--surface-sunken);
}

/* Horizontal scroll instead of clipping on narrow screens. */
.table-scroll { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
@media (max-width: 640px) {
	.table-scroll > .entry-table { min-width: 480px; }
	.summary-row { padding-inline: 0; }
}

/* §63 — "Letzte Einträge": table on desktop, stacked activity cards on phones.
   The 5-column table wraps the car name to 4 lines at phone widths; the cards
   lead with vehicle + amount, then a muted date · category · description line. */
.recent-cards { display: none; }
@media (max-width: 640px) {
	.recent-table { display: none; }
	.recent-cards {
		display: flex;
		flex-direction: column;
		gap: 0.5rem;
		list-style: none;
		margin: 0;
		padding: 0;
	}
	.recent-card {
		border: 1px solid var(--border-subtle);
		border-radius: var(--radius-control);
		background: var(--surface-raised);
	}
	.recent-card__link {
		display: flex;
		flex-direction: column;
		gap: 0.3rem;
		padding: 0.7rem 0.85rem;
		text-decoration: none;
		color: inherit;
	}
	.recent-card__top {
		display: flex;
		align-items: baseline;
		justify-content: space-between;
		gap: 0.75rem;
	}
	.recent-card__car {
		min-width: 0;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
		font-family: var(--font-serif);
		font-weight: 540;
		font-size: 14px;
		letter-spacing: -0.01em;
		color: var(--ink);
	}
	.recent-card__amount {
		flex: none;
		font-family: var(--font-mono);
		font-variant-numeric: tabular-nums slashed-zero;
		font-size: 13px;
		color: var(--text-2);
	}
	.recent-card__meta {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 0.3rem 0.55rem;
		font-family: var(--font-mono);
		font-size: 11px;
		color: var(--text-4);
	}
	.recent-card__desc { color: var(--text-3); }
}

/* ==========================================================================
   Modals / forms — Editorial × Instrument polish (shared by car form,
   entry-detail modal, TCO wizard, import, OCR, settings)
   ========================================================================== */

.form-modal-content { border-radius: var(--radius-card); }
.form-header { background: var(--surface-sunken); }
.form-title {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 540;
	font-size: clamp(20px, 2.4vw, 26px);
	letter-spacing: -0.015em;
}
.form-section-title {
	font-family: var(--font-mono);
	font-weight: 600;
	letter-spacing: 0.16em;
}
.form-input {
	border-radius: var(--radius-control);
	background: var(--surface-sunken);
}
.form-input:hover { background: var(--surface-sunken); border-color: var(--tint-lg); }
.form-input:focus {
	background: var(--surface-raised);
	box-shadow: 0 0 0 3px var(--accent-glow);
}
.settings-profile-hint {
	color: var(--text-3);
	background: var(--accent-soft);
	border: 1px solid color-mix(in oklab, var(--accent) 22%, transparent);
	border-radius: var(--radius-control);
}
/* ── a11y utilities + small-text legibility ─────────────────────────────── */
.visually-hidden {
	position: absolute;
	width: 1px; height: 1px;
	padding: 0; margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap; border: 0;
}.cmp-legend__lbl { font-size: 10px; }

/* ==========================================================================
   §13 Cockpit app-shell — sidebar + top bar + dashboard grid.
   Layout only; reuses the Editorial × Instrument tokens/primitives.
   ========================================================================== */

body { padding: 0; }

.app-shell {
	display: grid;
	grid-template-columns: minmax(214px, var(--sidebar-w)) minmax(0, 1fr);
	min-height: 100vh;
}

/* ── Sidebar ─────────────────────────────────────────────────────────────── */
.sidebar {
	position: sticky;
	top: 0;
	align-self: start;
	height: 100vh;
	/* Held as its own view-transition group so the brand/nav don't flicker on
	   navigation — only the contextual subnav fades (see app-sidebar rules). */
	view-transition-name: app-sidebar;
	/* Scroll within the rail when the expanded subnav pushes the nav past the
	   viewport height (short laptops); the brand stays put via sticky. */
	overflow-y: auto;
	display: flex;
	flex-direction: column;
	gap: 1.4rem;
	padding: clamp(1.1rem, 1.6vw, 1.5rem) clamp(0.85rem, 1.1vw, 1.15rem);
	/* Tighter bottom padding: the privacy chip sat too high above the base now
	   that the footer plinth anchors the page bottom — let it settle lower. */
	padding-bottom: 0.8rem;
	background: var(--surface-raised);
	border-right: 1px solid var(--border-subtle);
	overflow-y: auto;
}

.sidebar__brand {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	padding: 0.3rem 0.55rem 0.2rem;
	text-decoration: none;
	container-type: inline-size; /* size .sidebar__tagline against the rail width (cqi) */
}
.sidebar__wordmark {
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 600;
	/* Scale with the brand container (which sets container-type: inline-size),
	   like .sidebar__tagline does — at the 260px rail this resolves to ~60px, but
	   it scales down (never overflows) if the rail narrows. 28cqi ≈ 60px against
	   the brand's ~213px content box (padding-excluded). */
	font-size: clamp(38px, 28cqi, 62px);
	letter-spacing: -0.015em;
	line-height: 1;
	color: var(--ink);
}
.sidebar__tagline {
	font-family: var(--font-serif);
	font-style: italic;
	/* Grow with the rail width but stay on one line. Measured against the
	   real Playfair-italic metrics: the longest language (FR "Le carnet
	   d'entretien qui compte") fits up to ~14.7px at the 260px rail, and
	   its cqi limit is 7.13 -- so 7cqi + a 14px ceiling keep a margin.
	   ellipsis is a safety net for future strings, not expected to trip. */
	font-size: clamp(11px, 7cqi, 14px);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	font-weight: 500;
	letter-spacing: 0;
	color: var(--text-4);
}

.sidebar__nav { display: flex; flex-direction: column; gap: 2px; }
.side-link {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	padding: 0.5rem 0.7rem;
	border-radius: var(--radius-control);
	color: var(--text-2);
	text-decoration: none;
	font-weight: 500;
	font-size: 13.5px;
	transition: background var(--timing-fast) var(--ease-out), color var(--timing-fast) var(--ease-out);
}
.side-link .icon { width: 1.15em; height: 1.15em; color: var(--text-4); flex: none; }
.side-link:hover { background: var(--tint-sm); color: var(--ink); }
.side-link:hover .icon { color: var(--text-2); }
.side-link--active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.side-link--active .icon { color: var(--accent); }
.side-link__label { min-width: 0; }

/* §20 layout prototype: contextual per-car subnav nested under the Fahrzeuge
   nav item (the car-detail sections live in the sidebar on desktop). */
.side-subnav {
	display: flex;
	flex-direction: column;
	gap: 1px;
	margin: 0.1rem 0 0.4rem 1.35rem;
	padding-left: 0.6rem;
	border-left: 1px solid var(--border-subtle);
}
.side-subnav__group {
	font-size: 10px;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--text-4);
	margin: 0.5rem 0 0.1rem 0.55rem;
}
.side-subnav__group:first-child { margin-top: 0.15rem; }
.side-sublink {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	padding: 0.38rem 0.55rem;
	border-radius: var(--radius-control);
	color: var(--text-2);
	text-decoration: none;
	font-weight: 500;
	font-size: 12.5px;
	transition: background var(--timing-fast) var(--ease-out), color var(--timing-fast) var(--ease-out);
}
.side-sublink .icon { width: 1em; height: 1em; color: var(--text-4); flex: none; }
.side-sublink:hover { background: var(--tint-sm); color: var(--ink); }
.side-sublink:hover .icon { color: var(--text-2); }
.side-sublink--active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.side-sublink--active .icon { color: var(--accent); }
.side-sublink__label { min-width: 0; flex: 1; }
.side-sublink__count {
	margin-left: auto;
	font-size: 11px;
	color: var(--text-4);
	font-variant-numeric: tabular-nums;
}
/* On desktop the section nav lives in the sidebar subnav, so hide the in-page
   car-detail tab strip and let the content span full width; below 900px the
   sidebar is hidden and the strip takes over. (The settings-rail equivalent lives
   next to its own base rule so it wins on source order — see .settings-shell.) */
@media (min-width: 901px) {
	.car-tabs { display: none; }
}

.sidebar__foot { margin-top: auto; display: flex; flex-direction: column; gap: 0.9rem; }
.sidebar__privacy {
	display: flex;
	gap: 0.55rem;
	align-items: flex-start;
	padding: 0.7rem 0.65rem;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
}
.sidebar__privacy .icon { color: var(--accent); width: 1.05em; height: 1.05em; margin-top: 1px; flex: none; }
.sidebar__privacy-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.sidebar__privacy-text strong { font-size: 12px; color: var(--ink); font-weight: 600; }
.sidebar__privacy-sub { font-size: 10.5px; color: var(--text-4); }

/* ── Main column + top bar ───────────────────────────────────────────────── */
.shell-main { min-width: 0; display: flex; flex-direction: column; min-height: 100vh; }

.topbar {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1rem 1.5rem;
	flex-wrap: wrap;
	padding: clamp(1.1rem, 2vw, 1.9rem) clamp(1.1rem, 2.4vw, 2.2rem) 0;
}
.topbar__eyebrow {
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--text-4);
	margin: 0 0 0.35rem;
}
.topbar__greeting {
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 500;
	font-size: clamp(24px, 3vw, 34px);
	letter-spacing: -0.015em;
	line-height: 1.05;
	color: var(--ink);
	margin: 0;
}
.topbar__sub { margin: 0.4rem 0 0; color: var(--text-3); font-size: 14px; }
.topbar__title {
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 520;
	font-size: clamp(22px, 2.6vw, 28px);
	letter-spacing: -0.012em;
	color: var(--ink);
	margin: 0;
}
.topbar__actions { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.avatar {
	display: inline-grid;
	place-items: center;
	width: 2.5rem;
	height: 2.5rem;
	border-radius: 50%;
	background: var(--accent-soft);
	color: var(--accent);
	font-family: var(--font-mono);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.03em;
	flex: none;
}

#carlist { flex: 1; padding: clamp(1.1rem, 2.4vw, 2.2rem); }
.shell-main > .app-footer { padding-inline: clamp(1.1rem, 2.4vw, 2.2rem); }

/* ── Cockpit dashboard grid ──────────────────────────────────────────────── */
.cockpit {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(288px, 340px);
	gap: clamp(1rem, 2vw, 1.5rem);
	align-items: start;
}
.cockpit__main { display: flex; flex-direction: column; gap: clamp(1rem, 2vw, 1.5rem); min-width: 0; }
.cockpit__rail { display: flex; flex-direction: column; gap: clamp(1rem, 2vw, 1.5rem); min-width: 0; position: sticky; top: 1rem; }

.cockpit__charts {
	display: grid;
	grid-template-columns: minmax(0, 1.7fr) minmax(240px, 1fr);
	gap: clamp(1rem, 2vw, 1.5rem);
	align-items: stretch; /* both chart panels share the taller one's height */
}
/* Let each panel fill its (now equal-height) grid cell and stack its content. */
.cockpit__charts > .panel { display: flex; flex-direction: column; }

/* ── KPI strip ───────────────────────────────────────────────────────────── */
.kpi-strip {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
	gap: clamp(0.6rem, 1.4vw, 1rem);
}
.kpi {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	padding: clamp(0.9rem, 1.8vw, 1.2rem) clamp(1rem, 2vw, 1.25rem);
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	text-decoration: none;
	color: inherit;
}
a.kpi--link { transition: border-color var(--timing-base) var(--ease-out); }
a.kpi--link:hover { border-color: color-mix(in oklab, var(--accent) 45%, transparent); }
.kpi__label {
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--text-4);
	line-height: 1.4;
}
.kpi__value {
	font-family: var(--font-mono);
	font-weight: 600;
	font-size: clamp(19px, 2.4vw, 26px);
	line-height: 1.05;
	letter-spacing: -0.01em;
	color: var(--ink);
	font-variant-numeric: tabular-nums slashed-zero;
}
.kpi__unit { font-size: 0.5em; font-weight: 600; color: var(--text-4); margin-left: 0.3em; letter-spacing: 0.04em; }
.kpi-delta {
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 600;
	font-variant-numeric: tabular-nums slashed-zero;
	display: flex;
	align-items: baseline;
	gap: 0.4rem;
	flex-wrap: wrap;
}
.kpi-delta__note { color: var(--text-4); font-weight: 500; }
.kpi-delta--good { color: var(--clr-sell); }
.kpi-delta--bad { color: var(--clr-repair); }
.kpi-delta--neutral { color: var(--text-3); }
.kpi-delta--warn { color: var(--clr-service); }
/* Cumulative line sparkline pinned to the tile bottom (aligned across tiles). */
.kpi-spark { margin-top: auto; padding-top: 0.5rem; height: 30px; }
/* Reveal the line + its endpoint dot with a left-to-right wipe. The settled state
   is inset(0) — geometry identical to the un-animated spark, so nothing looks
   different once it lands. The global prefers-reduced-motion block collapses it. */
@keyframes spark-wipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
.kpi-spark__svg {
	width: 100%; height: 100%; display: block; opacity: 0.85;
	animation: spark-wipe var(--timing-slower) var(--ease-out) both;
}
/* Hauptfahrzeug bar spark grows up from the baseline. */
@keyframes spark-grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.haupt-spark rect {
	transform-box: fill-box;
	transform-origin: bottom;
	animation: spark-grow var(--timing-slow) var(--ease-out) both;
}
/* Prior-period comparison curve (e.g. last year): a muted second line behind the
   live series on every cockpit spark. Colour/opacity are inlined on the element;
   this just fades it in so it doesn't pop while the bars grow / the line wipes. */
@keyframes spark-base-in { from { opacity: 0; } to { opacity: 1; } }
.spark__base { animation: spark-base-in var(--timing-slower) var(--ease-out) both; }

/* ── Year picker ─────────────────────────────────────────────────────────── */
.year-picker {
	font-family: var(--font-mono);
	font-size: 12px;
	font-weight: 600;
	color: var(--text-2);
	padding: 0.4rem 0.7rem;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-pill);
	cursor: pointer;
}
.haupt__name {
	font-family: var(--font-serif);
	font-weight: 540;
	font-size: 17px;
	letter-spacing: -0.01em;
	color: var(--ink);
	margin: 0;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.activity-empty { display: flex; align-items: center; gap: 0.85rem; padding: 0.35rem 0; }

/* Distribution donut sits in a narrow column: stack chart over a full-width
   legend so long category labels never overflow the panel. */
/* Drop the tinted box + wide gap: the donut sits directly in the panel like the
   bar chart, with only a small gap to its legend. */
.cockpit__charts .cost-pie-container { flex: 1; flex-direction: column; align-items: center; justify-content: center; gap: 0.5rem; margin: 0; padding: 0; background: none; border-radius: 0; }
/* Two concentric rings need more room than the single per-car pie. */
.cockpit__charts .cost-pie-chart { width: 168px; height: 168px; }
.cockpit__charts .cost-pie-legend { width: 100%; grid-template-columns: 1fr; gap: 0.4rem; }
.legend-amount {
	font-family: var(--font-mono);
	font-weight: 600;
	color: var(--text-2);
	font-variant-numeric: tabular-nums slashed-zero;
	white-space: nowrap;
}
.cost-pie-legend .legend-value { min-width: 3ch; text-align: right; }

/* ── Hauptfahrzeug rail card (enlarged, vertical) ────────────────────────── */
.haupt { display: flex; flex-direction: column; gap: 1rem; position: relative; transition: border-color var(--timing-base) var(--ease-out); }
.haupt:hover { border-color: color-mix(in oklab, var(--accent) 35%, transparent); }
.haupt > .eyebrow { margin: 0; }

/* The whole card is the affordance: a stretched link over the car name covers
   the panel. Interactive children (onboarding nudge CTA) are raised above it. */
.haupt__link { color: inherit; text-decoration: none; }
.haupt__link:hover { text-decoration: none; }
.haupt__link::after { content: ""; position: absolute; inset: 0; }
.haupt .onboarding-nudge { position: relative; z-index: 1; }
.haupt__media-lg { border-radius: var(--radius-control); overflow: hidden; background: var(--surface-sunken); }
.haupt__img-lg { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }
.haupt__img-lg--ph { display: grid; place-items: center; aspect-ratio: 16 / 10; color: var(--text-4); }
.haupt__head { display: flex; flex-direction: column; gap: 0.15rem; }
.haupt__name {
	font-family: var(--font-serif);
	font-weight: 560;
	font-size: 22px;
	letter-spacing: -0.015em;
	line-height: 1.12;
	color: var(--ink);
	margin: 0;
}
.haupt__submodel { margin: 0; font-size: 13px; color: var(--text-3); }
.haupt__vin { margin: 0; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em; color: var(--text-4); }

.haupt__status {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	padding: 0.7rem 0.8rem;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	text-decoration: none;
	color: inherit;
	transition: border-color var(--timing-base) var(--ease-out);
}
.haupt__status-body { flex: 1; min-width: 0; }
.haupt__status-title { font-weight: 600; font-size: 13.5px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.haupt__status-sub { font-family: var(--font-mono); font-size: 11px; color: var(--text-4); }
.haupt__status > .icon { color: var(--text-4); flex: none; }

.haupt__specs { margin: 0; display: flex; flex-direction: column; }
.haupt__spec { display: flex; justify-content: space-between; gap: 1rem; padding: 0.5rem 0; border-bottom: 1px solid var(--border-subtle); }
.haupt__spec:last-child { border-bottom: 0; }
.haupt__spec dt { font-size: 12.5px; color: var(--text-3); }
.haupt__spec dd {
	margin: 0;
	font-family: var(--font-mono);
	font-size: 12.5px;
	font-weight: 600;
	color: var(--ink);
	font-variant-numeric: tabular-nums slashed-zero;
	text-align: right;
}

.haupt__cost { border-top: 1px solid var(--border-subtle); padding-top: 0.9rem; display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; }
.haupt__cost-head { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.haupt-spark-wrap { width: 132px; height: 40px; flex: none; }
.haupt-spark { width: 100%; height: 100%; display: block; }

/* Profile rename affordance on the active profile pill. */
.profile-switcher-active { display: inline-flex; align-items: center; gap: 0.35rem; }
.profile-switcher-rename {
	display: inline-grid;
	place-items: center;
	padding: 2px;
	background: transparent;
	border: 0;
	color: var(--text-4);
	cursor: pointer;
	border-radius: var(--radius-control);
}
.profile-switcher-rename .icon { width: 0.85em; height: 0.85em; }
.profile-switcher-rename:hover { color: var(--accent); }

/* Top-bar year picker — a page-level control styled to match .btn--secondary
   (same height, radius, colours). Native appearance is dropped for a custom
   chevron so the padding is even and predictable across browsers (not a pill). */
.year-picker--topbar {
	appearance: none;
	-webkit-appearance: none;
	font-family: var(--font-mono, inherit);
	font-size: 0.8rem;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.01em;
	line-height: 1.2;
	padding: 0.5rem 1.85rem 0.5rem 0.85rem;
	border-radius: var(--radius-control);
	color: var(--accent);
	background-color: var(--accent-soft);
	border: 1px solid transparent;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23808080' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 0.6rem center;
	background-size: 13px;
	cursor: pointer;
}
.year-picker--topbar:hover { background-color: color-mix(in oklab, var(--accent-soft) 82%, var(--accent)); }

/* Avatar dropdown (profile chip → app-level backup actions). The summary IS the
   circular avatar: force grid centering (over the UA `list-item`), drop the
   disclosure marker, and keep it NEUTRAL grey so it doesn't clash with the green
   primary button beside it. */
/* Reset the legacy generic `details`/`summary` accordion styling (border-top,
   scrim background, 22px/26px padding) that would otherwise deform the avatar. */
.avatar-menu { position: relative; display: inline-flex; align-items: center; flex: none; border-top: 0; }
/* The summary is a bare, marker-less trigger; the circular avatar is an inner
   <span> so its shape/centering can't be disturbed by the disclosure marker. */
.avatar-menu > summary,
.avatar-menu > summary:hover,
.avatar-menu[open] > summary {
	display: flex;
	list-style: none;
	cursor: pointer;
	padding: 0;
	background: transparent;
	transition: none;
}
.avatar-menu > summary::-webkit-details-marker { display: none; }
.avatar-menu > summary::marker { content: ""; }
.avatar-menu > summary:focus-visible { outline: none; }
.avatar-menu > summary:focus-visible .avatar { outline: 2px solid var(--accent); outline-offset: 2px; }
.avatar-menu .avatar { transition: filter var(--timing-base) var(--ease-out); }
.avatar-menu > summary:hover .avatar { filter: brightness(0.96); }
.avatar-menu__panel {
	position: absolute;
	right: 0;
	top: calc(100% + 8px);
	z-index: 70;
	min-width: 220px;
	padding: 0.4rem;
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	box-shadow: 0 12px 32px var(--scrim-sm);
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.avatar-menu__name {
	padding: 0.45rem 0.6rem 0.5rem;
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--text-4);
	border-bottom: 1px solid var(--border-subtle);
	margin-bottom: 0.2rem;
}
.avatar-menu__item {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	width: 100%;
	padding: 0.55rem 0.6rem;
	border: 0;
	background: transparent;
	color: var(--text-2);
	font: inherit;
	font-size: 13.5px;
	text-align: left;
	text-decoration: none;
	border-radius: var(--radius-control);
	cursor: pointer;
}
.avatar-menu__item .icon { width: 1.05em; height: 1.05em; color: var(--text-4); flex: none; }
.avatar-menu__item:hover { background: var(--tint-sm); color: var(--ink); }
.avatar-menu__item:hover .icon { color: var(--text-2); }
/* forms wrap the switch buttons but must not disturb the flex column */
.avatar-menu__form { display: contents; }
.avatar-menu__divider { height: 1px; background: var(--border-subtle); margin: 0.3rem 0; }
.avatar-menu__section {
	padding: 0.5rem 0.6rem 0.25rem;
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--text-4);
}
.avatar-menu__langs { display: flex; gap: 4px; padding: 0 0.6rem 0.3rem; }
.avatar-menu__lang {
	flex: 1;
	padding: 0.35rem 0;
	border: 1px solid var(--border-subtle);
	background: transparent;
	color: var(--text-3);
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.06em;
	border-radius: var(--radius-control);
	cursor: pointer;
	transition: background var(--timing-base) var(--ease-out), color var(--timing-base) var(--ease-out);
}
.avatar-menu__lang:hover { background: var(--tint-sm); color: var(--ink); }
.avatar-menu__lang--active {
	background: var(--accent);
	border-color: var(--accent);
	color: var(--accent-ink);
	cursor: default;
}

/* ── §44 feedback widget ──────────────────────────────────────────────────
   A small fixed edge tab opens a centered .form-modal <dialog> -- the same
   overlay every other modal in the app uses (pop-in + backdrop blur), just
   narrower and a bit more intimate than the multi-tab car-edit form. */
/* §44 — feedback trigger lives inside the sidebar foot (above the privacy chip),
   a full-width soft-accent button rather than a fixed edge-tab: over the sidebar
   a fixed tab covered the nav, and outside it read as detached. On mobile the
   sidebar is hidden and the More sheet carries its own feedback item. */
.sidebar__feedback {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	width: 100%;
	padding: 0.55rem 0.7rem;
	border: 1px solid color-mix(in oklab, var(--accent) 28%, transparent);
	border-radius: var(--radius-control);
	background: var(--accent-soft);
	color: var(--accent);
	cursor: pointer;
	font: inherit;
	font-size: 13px;
	font-weight: 600;
	transition: background var(--timing-fast) var(--ease-out), border-color var(--timing-fast) var(--ease-out);
}
.sidebar__feedback .icon { width: 1.05em; height: 1.05em; flex: none; }
.sidebar__feedback:hover {
	background: color-mix(in oklab, var(--accent) 15%, var(--surface-raised));
	border-color: color-mix(in oklab, var(--accent) 45%, transparent);
}

.feedback-modal { max-width: 440px; }
.feedback-modal-body {
	padding: 0.5rem 2rem 2rem;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 0.25rem;
}
.feedback-modal-icon {
	display: inline-grid;
	place-items: center;
	width: 3.5rem;
	height: 3.5rem;
	margin-bottom: 0.5rem;
	border-radius: 50%;
	color: var(--accent);
	background: var(--accent-soft);
}
.feedback-modal-icon .icon { font-size: 1.6rem; stroke-width: 1.6; }
.feedback-modal-intro {
	color: var(--text-2);
	font-size: 0.9rem;
	line-height: 1.5;
	margin: 0 0 1rem;
	max-width: 34ch;
}
.feedback-modal-body > div { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 0.75rem; }
.feedback-modal-textarea,
.feedback-modal-body input[type="email"] { width: 100%; }
.feedback-modal-textarea { resize: vertical; min-height: 7rem; text-align: left; }
.feedback-modal-body .form-actions { width: 100%; justify-content: center; padding-top: 0.25rem; margin-top: 0; }
.feedback-modal-thanks { padding: 0.5rem 0 1rem; }
.feedback-modal-thanks p { color: var(--text-2); font-size: 0.95rem; }
/* §44 local (self-hosted) contact variant: stacked mailto / issue links in
   place of the submission form. */
.feedback-contact-actions { width: 100%; display: flex; flex-direction: column; gap: 0.5rem; }
.feedback-contact-actions .btn { width: 100%; justify-content: center; gap: 0.5rem; }
.feedback-contact-actions .icon { width: 1.05em; height: 1.05em; }

/* ── Cockpit responsive ──────────────────────────────────────────────────── */
@media (max-width: 1080px) {
	.cockpit { grid-template-columns: 1fr; }
	.cockpit__rail { position: static; }
	.cockpit__charts { grid-template-columns: 1fr; }
}

/* At/below the §63 mobile-chrome breakpoint (≤900px, tablet portrait and down)
   the desktop Sidebar is hidden (see the mobile chrome block below), so the
   shell is a single content column with tighter padding. The old horizontal
   sidebar-strip collapse that used to live here is gone — tablet portrait now
   gets the bottom-bar chrome, not a stacked masthead. */
@media (max-width: 900px) {
	.app-shell { grid-template-columns: 1fr; }
	.topbar { padding: 1.2rem 1rem 0; }
	#carlist { padding: 1.1rem 1rem; }
	.shell-main > .app-footer { padding-inline: 1rem; }
}

/* ==========================================================================
   §6 Auth pages — login / signup / forgot / reset / message
   Chrome-less, shell-less pages (reached before any tenant is resolved): a
   two-panel masthead with the wordmark on an accent field (left) and the form
   on paper (right). Collapses to a single column with a slim brand header
   below ~820px. Uses only design tokens, so it flips light/dark for free.
   ========================================================================== */
.auth-body {
	margin: 0;
	padding: 0;
	min-height: 100dvh;
	display: grid;
	grid-template-columns: 1.05fr 1fr;
}

/* ── Brand panel (left) ─────────────────────────────────────────────────── */
.auth-brand {
	position: relative;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: clamp(2.5rem, 6vw, 5rem);
	color: var(--accent-ink);
	background:
		radial-gradient(120% 90% at 12% 0%, color-mix(in oklab, #fff 16%, transparent) 0%, transparent 55%),
		linear-gradient(155deg, var(--accent) 0%, color-mix(in oklab, var(--accent) 70%, #000) 100%);
}
/* Oversized faint serif glyph, purely decorative. */
.auth-brand::after {
	content: "L";
	position: absolute;
	right: -0.12em;
	bottom: -0.3em;
	font-family: var(--font-serif);
	font-weight: 600;
	font-size: clamp(20rem, 34vw, 34rem);
	line-height: 1;
	color: color-mix(in oklab, var(--accent-ink) 9%, transparent);
	pointer-events: none;
	user-select: none;
}
.auth-brand__inner {
	position: relative;
	z-index: 1;
	max-width: 30rem;
}
.auth-brand__wordmark {
	display: block;
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 600;
	font-size: clamp(3.25rem, 6vw, 4.75rem);
	letter-spacing: -0.02em;
	line-height: 0.95;
	font-variant-ligatures: common-ligatures discretionary-ligatures contextual;
}
/* The wordmark links back to the marketing site; keep it looking like the
   wordmark, not a default link. */
a.auth-brand__wordmark { color: inherit; text-decoration: none; width: max-content; transition: opacity 0.15s ease; }
a.auth-brand__wordmark:hover { opacity: 0.85; }
.auth-brand__tagline {
	display: block;
	margin-top: 0.95rem;
	font-family: var(--font-serif);
	font-style: italic;
	font-size: 1.05rem;
	font-weight: 500;
	letter-spacing: 0;
	color: color-mix(in oklab, var(--accent-ink) 74%, transparent);
}
.auth-brand__lead {
	margin: 2.25rem 0 0;
	font-family: var(--font-serif);
	font-style: italic;
	font-size: clamp(1.25rem, 2vw, 1.6rem);
	line-height: 1.35;
	max-width: 24ch;
	color: color-mix(in oklab, var(--accent-ink) 94%, transparent);
}
.auth-brand__points {
	list-style: none;
	margin: 2rem 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.7rem;
}
.auth-brand__points li {
	position: relative;
	padding-left: 1.5rem;
	font-size: 0.9rem;
	line-height: 1.4;
	color: color-mix(in oklab, var(--accent-ink) 84%, transparent);
}
.auth-brand__points li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.5em;
	width: 0.45rem;
	height: 0.45rem;
	border-radius: 50%;
	background: currentColor;
	opacity: 0.5;
}

/* ── Form panel (right) ─────────────────────────────────────────────────── */
.auth-main {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	gap: 2.5rem;
	padding: clamp(2rem, 5vw, 4rem) clamp(1.25rem, 4vw, 3rem);
	background: var(--surface);
}
.auth-card {
	width: 100%;
	max-width: 24rem;
	animation: fadeIn var(--timing-slow) var(--ease-out) both;
}
.auth-card__head { margin-bottom: 1.75rem; }
.auth-card__title {
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 600;
	font-size: 2rem;
	letter-spacing: -0.01em;
	line-height: 1.1;
	color: var(--ink);
}
.auth-card__sub {
	margin-top: 0.5rem;
	font-size: 0.9rem;
	line-height: 1.45;
	color: var(--text-3);
}

.auth-form { display: flex; flex-direction: column; gap: 1.1rem; }
.auth-field { display: flex; flex-direction: column; gap: 0.4rem; }
.auth-label {
	font-size: 0.78rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	color: var(--text-2);
}
.auth-input {
	width: 100%;
	padding: 0.7rem 0.9rem;
	font: inherit;
	font-size: 0.95rem;
	color: var(--text);
	background: var(--surface-raised);
	border: 1px solid var(--border);
	border-radius: var(--radius-control);
	transition: border-color var(--timing-base) var(--ease-out),
	            box-shadow var(--timing-base) var(--ease-out),
	            background var(--timing-base) var(--ease-out);
}
.auth-input::placeholder { color: var(--text-4); }
.auth-input:hover { border-color: var(--tint-lg); }
.auth-input:focus {
	outline: none;
	border-color: var(--accent);
	box-shadow: 0 0 0 3px var(--accent-glow);
}
.auth-submit { margin-top: 0.4rem; }

.auth-divider {
	display: flex;
	align-items: center;
	gap: 0.9rem;
	margin: 1.4rem 0;
	color: var(--text-4);
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}
.auth-divider::before,
.auth-divider::after {
	content: "";
	flex: 1;
	height: 1px;
	background: var(--border-subtle);
}
.auth-passkey { gap: 0.5rem; }
.auth-passkey svg { flex: none; }

.auth-alert {
	margin-bottom: 1.25rem;
	padding: 0.7rem 0.9rem;
	border-radius: var(--radius-control);
	border: 1px solid color-mix(in oklab, var(--critical) 42%, transparent);
	background: color-mix(in oklab, var(--critical) 10%, transparent);
	color: var(--critical);
	font-size: 0.85rem;
	line-height: 1.4;
}

.auth-msg {
	font-size: 0.95rem;
	line-height: 1.55;
	color: var(--text-2);
}

.auth-links {
	display: flex;
	flex-direction: column;
	gap: 0.55rem;
	margin-top: 1.6rem;
	padding-top: 1.4rem;
	border-top: 1px solid var(--border-subtle);
	font-size: 0.875rem;
}
.auth-links .auth-link {
	color: var(--text-3);
	text-decoration: none;
	transition: color var(--timing-fast) var(--ease-out);
}
.auth-links .auth-link:hover { color: var(--accent); }
.auth-links .auth-link--em { color: var(--text-2); font-weight: 500; }

@media (max-width: 820px) {
	.auth-body { grid-template-columns: 1fr; }
	.auth-brand {
		padding: clamp(1.75rem, 7vw, 2.75rem);
		justify-content: flex-start;
	}
	.auth-brand__lead,
	.auth-brand__points { display: none; }
	.auth-brand__inner { max-width: none; }
	.auth-brand::after { font-size: 15rem; bottom: -0.4em; }
	.auth-main { gap: 2rem; }
}

/* ==========================================================================
   404 — "off the logbook" (chrome-less not-found page)
   Same token-only, chrome-less footing as the auth pages, but a single
   full-bleed accent field with an exaggerated editorial masthead: an oversized
   Playfair "404" over a decorative ghost glyph, plus an instrument-style mono
   readout of the missed route. Flips light/dark for free (tokens only). Served
   by router.Render404 for a logged-out / non-navigation miss; a logged-in
   page navigation is redirected to the app instead (see router notFoundHandler).
   ========================================================================== */
.nf-body {
	margin: 0;
	min-height: 100dvh;
	display: grid;
	place-items: center;
	padding: clamp(2rem, 6vw, 5rem);
	position: relative;
	overflow: hidden;
	color: var(--accent-ink);
	background:
		radial-gradient(130% 100% at 15% 0%, color-mix(in oklab, #fff 18%, transparent) 0%, transparent 55%),
		linear-gradient(155deg, var(--accent) 0%, color-mix(in oklab, var(--accent) 62%, #000) 100%);
}
/* Oversized faint serif glyph, purely decorative — echoes the auth field's "L". */
.nf-body::after {
	content: "?";
	position: absolute;
	right: -0.06em;
	bottom: -0.32em;
	font-family: var(--font-serif);
	font-weight: 600;
	font-size: clamp(24rem, 44vw, 46rem);
	line-height: 1;
	color: color-mix(in oklab, var(--accent-ink) 8%, transparent);
	pointer-events: none;
	user-select: none;
}
.nf-inner {
	position: relative;
	z-index: 1;
	max-width: 42rem;
	text-align: center;
	animation: fadeIn var(--timing-slow) var(--ease-out) both;
}
.nf-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 0.85rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.3em;
	text-transform: uppercase;
	color: color-mix(in oklab, var(--accent-ink) 72%, transparent);
}
.nf-eyebrow::before,
.nf-eyebrow::after {
	content: "";
	width: 2rem;
	height: 1px;
	background: color-mix(in oklab, var(--accent-ink) 38%, transparent);
}
.nf-code {
	margin: 1.5rem 0 0;
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 600;
	font-size: clamp(7rem, 27vw, 19rem);
	line-height: 0.92;
	letter-spacing: -0.045em;
	font-variant-ligatures: common-ligatures discretionary-ligatures contextual;
	text-shadow: 0 0 70px color-mix(in oklab, #000 24%, transparent);
}
.nf-lead {
	margin: clamp(1.9rem, 4vw, 3rem) 0 0;
	font-family: var(--font-serif);
	font-style: italic;
	font-weight: 500;
	font-size: clamp(1.4rem, 3.4vw, 2.15rem);
	line-height: 1.28;
	color: var(--accent-ink);
}
.nf-sub {
	margin: 0.95rem auto 0;
	max-width: 38ch;
	font-size: 0.98rem;
	line-height: 1.55;
	color: color-mix(in oklab, var(--accent-ink) 80%, transparent);
}
/* Instrument readout: the failed route on a mono "dashboard" strip. */
.nf-readout {
	margin: 1.9rem auto 0;
	display: inline-flex;
	align-items: center;
	gap: 0.7rem;
	max-width: 100%;
	padding: 0.5rem 0.95rem;
	border-radius: var(--radius-pill);
	border: 1px solid color-mix(in oklab, var(--accent-ink) 24%, transparent);
	background: color-mix(in oklab, #000 14%, transparent);
	font-family: var(--font-mono);
	font-size: 0.82rem;
	color: color-mix(in oklab, var(--accent-ink) 88%, transparent);
}
.nf-readout__lamp {
	flex: none;
	width: 0.55rem;
	height: 0.55rem;
	border-radius: 50%;
	background: var(--accent-ink);
	animation: nfPulse 2.4s var(--ease-out) infinite;
}
.nf-readout__path {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	letter-spacing: 0.02em;
}
.nf-actions {
	margin-top: 2.4rem;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.8rem;
}
/* Paper-solid CTA tuned for the accent field (the token --primary would sink
   into it). */
.nf-btn--solid {
	background: var(--accent-ink);
	color: var(--accent);
	border-color: var(--accent-ink);
	font-weight: 600;
	box-shadow: 0 6px 22px color-mix(in oklab, #000 30%, transparent);
}
.nf-btn--solid:hover {
	transform: translateY(-1px);
	background: color-mix(in oklab, var(--accent-ink) 90%, #fff);
	box-shadow: 0 10px 28px color-mix(in oklab, #000 40%, transparent);
}

@keyframes nfPulse {
	0%   { opacity: 1;    box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent-ink) 55%, transparent); }
	70%  { opacity: 0.5;  box-shadow: 0 0 0 0.5rem transparent; }
	100% { opacity: 1;    box-shadow: 0 0 0 0 transparent; }
}

@media (max-width: 620px) {
	.nf-body::after { font-size: 22rem; bottom: -0.2em; }
	.nf-actions { flex-direction: column; align-items: stretch; }
	.nf-actions .btn { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
	.nf-inner { animation: none; }
	.nf-readout__lamp { animation: none; }
}

/* ── §36 Billing page ──────────────────────────────────────────────────────
   Shares the pre-tenant page shell (chrome-less, token-only) but is a
   post-login account surface -- so a single centered card widened for the
   plan/add-on rows, with a "remnant" of the auth brand field: the accent
   gradient + wordmark carried as a header band rather than a full panel. */
.bill-body {
	margin: 0;
	min-height: 100dvh;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: clamp(1.5rem, 5vw, 3.5rem) clamp(1rem, 4vw, 2rem);
	background: var(--surface);
}
.bill-card {
	width: 100%;
	max-width: 38rem;
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	box-shadow: var(--shadow-lg);
	overflow: hidden;
	animation: fadeIn var(--timing-slow) var(--ease-out) both;
}
/* Accent remnant of the two-panel brand field, as a masthead band. */
.bill-head {
	position: relative;
	overflow: hidden;
	padding: clamp(1.75rem, 4vw, 2.5rem);
	color: var(--accent-ink);
	background:
		radial-gradient(120% 130% at 8% 0%, color-mix(in oklab, #fff 16%, transparent) 0%, transparent 55%),
		linear-gradient(155deg, var(--accent) 0%, color-mix(in oklab, var(--accent) 70%, #000) 100%);
}
.bill-head::after {
	content: "L";
	position: absolute;
	right: -0.05em;
	bottom: -0.42em;
	font-family: var(--font-serif);
	font-weight: 600;
	font-size: clamp(9rem, 22vw, 13rem);
	line-height: 1;
	color: color-mix(in oklab, var(--accent-ink) 10%, transparent);
	pointer-events: none;
	user-select: none;
}
.bill-head__inner { position: relative; z-index: 1; }
.bill-head__wordmark {
	display: block;
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 600;
	font-size: clamp(2rem, 5vw, 2.6rem);
	letter-spacing: -0.02em;
	line-height: 0.95;
}
.bill-head__tagline {
	display: block;
	margin-top: 0.5rem;
	font-family: var(--font-mono);
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: color-mix(in oklab, var(--accent-ink) 74%, transparent);
}
.bill-content {
	padding: clamp(1.5rem, 4vw, 2.25rem);
	display: flex;
	flex-direction: column;
	gap: 1.4rem;
}
.bill-summary {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	padding-bottom: 1.4rem;
	border-bottom: 1px solid var(--border-subtle);
}
.bill-summary__plan {
	font-family: var(--font-serif);
	font-weight: 600;
	font-size: 1.35rem;
	line-height: 1.15;
	color: var(--ink);
}
.bill-summary__meta { font-size: 0.875rem; color: var(--text-3); }

.bill-note {
	padding: 0.7rem 0.9rem;
	border-radius: var(--radius-control);
	border: 1px solid var(--border-subtle);
	background: var(--surface-sunken);
	color: var(--text-2);
	font-size: 0.85rem;
	line-height: 1.45;
}
.bill-note a { color: inherit; font-weight: 500; }
.bill-note--ok {
	border-color: color-mix(in oklab, var(--accent) 42%, transparent);
	background: var(--accent-soft);
	color: var(--text-1);
}
.bill-note--danger {
	border-color: color-mix(in oklab, var(--critical) 42%, transparent);
	background: color-mix(in oklab, var(--critical) 10%, transparent);
	color: var(--critical);
}

.bill-section__label {
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--text-4);
	margin-bottom: 0.75rem;
}
.bill-rows { display: flex; flex-direction: column; gap: 0.6rem; }
.bill-row {
	display: flex;
	align-items: center;
	gap: 0.9rem;
	margin: 0;
	padding: 0.8rem 1rem;
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-control);
	background: var(--surface);
}
.bill-row--current {
	border-color: color-mix(in oklab, var(--accent) 45%, transparent);
	background: var(--accent-soft);
}
.bill-row__name { flex: 1; font-size: 0.95rem; color: var(--text); }
.bill-row__price {
	font-family: var(--font-mono);
	font-size: 0.88rem;
	color: var(--text-2);
	white-space: nowrap;
}
.bill-row__action { flex: none; }
.bill-row__badge {
	flex: none;
	padding: 0.3rem 0.6rem;
	border-radius: var(--radius-pill);
	background: color-mix(in oklab, var(--accent) 14%, transparent);
	color: var(--accent);
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}
.bill-action { margin-top: 0.9rem; }

/* Plan comparison: one card per tier, benefit bullets + cadence options. */
.bill-plans { display: flex; flex-direction: column; gap: 0.7rem; }
.bill-plan {
	padding: 1rem 1.1rem;
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-control);
	background: var(--surface);
}
.bill-plan--current {
	border-color: color-mix(in oklab, var(--accent) 45%, transparent);
	background: var(--accent-soft);
}
.bill-plan__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.75rem;
}
.bill-plan__name {
	font-family: var(--font-serif);
	font-weight: 600;
	font-size: 1.15rem;
	color: var(--ink);
}
.bill-plan__tag {
	margin: 0.15rem 0 0;
	font-size: 0.8rem;
	color: var(--text-3);
}
.bill-plan__benefits {
	list-style: none;
	margin: 0.85rem 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
}
.bill-plan__benefits li {
	position: relative;
	padding-left: 1.4rem;
	font-size: 0.875rem;
	line-height: 1.4;
	color: var(--text-2);
}
.bill-plan__benefits li::before {
	content: "";
	position: absolute;
	left: 0.15rem;
	top: 0.32em;
	width: 0.5rem;
	height: 0.28rem;
	border-left: 1.75px solid var(--accent);
	border-bottom: 1.75px solid var(--accent);
	transform: rotate(-45deg);
}
.bill-plan__offer {
	display: flex;
	align-items: center;
	gap: 0.9rem;
	margin: 0.7rem 0 0;
	padding-top: 0.7rem;
	border-top: 1px solid var(--border-subtle);
}
.bill-plan__price {
	flex: 1;
	font-family: var(--font-mono);
	font-size: 0.9rem;
	color: var(--text-2);
}
.bill-plan__cta { flex: none; }

/* Muted, non-purchasable teaser for the not-yet-available B2B tiers. */
.bill-plan--soon {
	border-style: dashed;
	background: transparent;
}
.bill-plan--soon .bill-plan__name { font-size: 1.05rem; color: var(--text-3); }
.bill-plan--soon .bill-plan__tag { color: var(--text-4); }
.bill-soon {
	flex: none;
	align-self: center;
	padding: 0.22rem 0.55rem;
	border-radius: var(--radius-pill);
	background: var(--tint-sm);
	color: var(--text-4);
	font-size: 0.64rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	white-space: nowrap;
}

.bill-foot {
	margin-top: 0.3rem;
	padding-top: 1.2rem;
	border-top: 1px solid var(--border-subtle);
	font-size: 0.875rem;
}
.bill-back {
	color: var(--text-3);
	text-decoration: none;
	transition: color var(--timing-fast) var(--ease-out);
}

/* ==========================================================================
   §41 Documents — Rows/Grid + by-car groups. Reuses .panel/.activity-list/
   .icon-chip/.section-head/.segmented; only what those primitives don't
   already cover lives here.
   ========================================================================== */
.documents__controls { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }

/* Kind filter (7 kinds): the shared pill-shaped .segmented capsule looks broken
   once it wraps to 2-3 lines, so drop the capsule and give each item its own
   independent chip. Rather than wrap, the strip stays on one line and scrolls
   horizontally at every width (all chips fit on a wide desktop; narrower
   viewports swipe) — a consistent, compact treatment instead of a variable-
   height header. Scrollbar hidden; the partly-clipped trailing chip is the
   scroll affordance. */
.documents__kind-filter {
	/* Block-level (not the inherited inline-flex): an inline-flex box shrink-wraps
	   to its content, so it would grow past the viewport and never scroll. As a
	   block it fills the column, and the nowrap overflow scrolls inside it. */
	display: flex;
	max-width: 100%;
	flex-wrap: nowrap;
	overflow-x: auto;
	scrollbar-width: none;
	height: auto;
	margin-top: 0.75rem;
	margin-bottom: 1rem;
	padding: 0;
	gap: 0.4rem;
	background: none;
	border: 0;
	border-radius: 0;
}
.documents__kind-filter::-webkit-scrollbar { display: none; }
.documents__kind-filter .segmented__item {
	flex: none;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
}
.documents__kind-filter .segmented__item--active {
	background: var(--accent-soft);
	color: var(--accent);
	border-color: var(--accent);
	box-shadow: none;
}

/* Phone: tighten the header spacing (the eyebrow now rides in the top bar), and
   drop the Upload button — its action lives in the tab-bar ＋ capture sheet on
   mobile (§63), reached via /dokumente?upload=1. */
@media (max-width: 640px) {
	.documents__head { margin-bottom: 0.75rem; }
	.documents__kind-filter { margin-top: 0.5rem; margin-bottom: 0.75rem; }
	.documents__upload { display: none; }
}

/* Tighter than the generic .panel padding — a car's own group is often a
   single row, so the shared clamp(1rem, 2.2vw, 1.5rem) reads as dead air. */
.documents__car-group { padding: clamp(0.7rem, 1.6vw, 1.1rem) clamp(0.85rem, 2vw, 1.35rem); }
.documents__car-group + .documents__car-group { margin-top: 0.55rem; }
/* Compact single-row header: small car avatar + ellipsised name + count on one
   line. The inherited section-head (baseline-align, flex-wrap, 23px serif title)
   pushed the photo, name and count each onto their own line — a tall header for
   what is often a single document. */
.documents__car-head {
	align-items: center;
	flex-wrap: nowrap;
	gap: 0.7rem;
	margin-bottom: 0.7rem;
}
.documents__car-head .section-head__titles { flex: 1; min-width: 0; }
.documents__car-name {
	font-size: clamp(15px, 1.9vw, 18px);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.documents__car-count {
	flex: none;
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 600;
	color: var(--text-4);
	white-space: nowrap;
}

.doc-group__photo {
	flex: none;
	width: 44px;
	height: 44px;
	border-radius: var(--radius-control);
	overflow: hidden;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
}
.doc-group__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.doc-group__img--ph { display: grid; place-items: center; color: var(--text-5); }

/* Row: two independent links (view the document / jump to its owning car
   object) rather than nested anchors — activity-row's grid-template-columns
   (auto 1fr auto) assumed one link with three children, so override to flex. */
.doc-row { display: flex; align-items: center; gap: 0.85rem; }
.doc-row__open {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	gap: 0.85rem;
	flex: 1;
	min-width: 0;
	text-decoration: none;
	color: inherit;
}
.doc-row__link {
	flex: none;
	display: inline-flex;
	color: var(--text-5);
	transition: color var(--timing-base) var(--ease-out), transform var(--timing-base) var(--ease-out);
}
.doc-row__link:hover { color: var(--accent); transform: translateX(3px); }

/* Rows mode (default): icon-chip glyph, no thumbnail. */
.doc-row__thumb { display: none; }

/* Grid mode: same markup, CSS-only relayout — bigger photographic thumbnails
   instead of the small glyph (every §21-retained kind has a real image
   behind OpenURL), icon-chip becomes the no-thumbnail fallback look. */
.activity-list.docs-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
	gap: 0.75rem;
}
.activity-list.docs-grid .doc-row {
	flex-direction: column;
	border-bottom: 0;
	padding: 0.75rem;
	background: var(--surface-sunken);
	border-radius: var(--radius-card);
	border: 1px solid var(--border-subtle);
}
.activity-list.docs-grid .doc-row__open {
	grid-template-columns: 1fr;
	justify-items: center;
	text-align: center;
	gap: 0.5rem;
}
.activity-list.docs-grid .icon-chip { display: none; }
.activity-list.docs-grid .doc-row__thumb {
	display: block;
	width: 100%;
	height: 120px;
	object-fit: cover;
	border-radius: var(--radius-control);
}
.activity-list.docs-grid .activity-row__title { white-space: normal; }
.activity-list.docs-grid .activity-row__sub { display: block; }
.activity-list.docs-grid .doc-row__link { margin-top: 0.2rem; }
.doc-row__delete { flex: none; } /* §56 — colour now owned by btn--danger */

/* File field: a dashed dropzone (same idiom as .journal-drop-hint) wrapping
   a visually-hidden native input — click-to-browse via the <label for>
   association, drag-and-drop via the inline handlers below. */
.doc-upload-drop {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.8rem 1rem;
	border: 1.5px dashed var(--border);
	border-radius: var(--radius-control);
	color: var(--text-3);
	cursor: pointer;
	transition: color var(--timing-base) var(--ease-out), border-color var(--timing-base) var(--ease-out), background var(--timing-base) var(--ease-out);
}
.doc-upload-drop:hover {
	color: var(--accent);
	border-color: var(--accent);
	background: var(--tint-sm);
}
.doc-upload-drop--filled {
	color: var(--ink);
	border-style: solid;
	border-color: var(--accent);
	background: var(--accent-soft);
}
.doc-upload-drop__name {
	font-weight: 600;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.doc-upload-cars { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.doc-upload-car {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.4rem 0.75rem;
	font-size: 13px;
	color: var(--text-2);
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	border-radius: 999px;
	cursor: pointer;
	transition: color var(--timing-fast) var(--ease-out), border-color var(--timing-fast) var(--ease-out), background var(--timing-fast) var(--ease-out);
}
.doc-upload-car:hover { border-color: var(--tint-lg); color: var(--ink); }
.doc-upload-car:has(input:checked) {
	background: var(--accent-soft);
	border-color: var(--accent);
	color: var(--accent);
}
.bill-back:hover { color: var(--accent); }

/* ==========================================================================
   §41 Phase 3.2 — "Papiere" glovebox carousel. Bypasses the shared app
   Layout entirely (GloveboxCarousel is its own standalone HTML document,
   not app-shell content) — a full-bleed, swipeable card-per-document view
   (Apple/Google Wallet idiom): tap the icon, see the paper you need
   immediately, swipe for the next one. Pure CSS scroll-snap drives the
   swipe; no JS beyond the mandatory service-worker registration.
   ========================================================================== */
.glovebox-body {
	margin: 0;
	background: var(--surface);
	overscroll-behavior-y: contain;
}
.glovebox-close {
	position: fixed;
	top: max(14px, env(safe-area-inset-top));
	left: max(14px, env(safe-area-inset-left));
	z-index: 10;
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	border-radius: var(--radius-pill);
	background: var(--tint-md);
	color: var(--ink);
	font-size: 22px;
	line-height: 1;
	text-decoration: none;
	backdrop-filter: blur(6px);
}
.glovebox-carousel {
	display: flex;
	gap: 12px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-padding-inline: 6vw;
	height: 100dvh;
	padding: 0 6vw;
	box-sizing: border-box;
	-webkit-overflow-scrolling: touch;
}
.glovebox-card {
	flex: 0 0 82vw;
	max-width: 460px;
	scroll-snap-align: center;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 16px;
	padding: max(24px, env(safe-area-inset-top)) 0 max(24px, env(safe-area-inset-bottom));
	box-sizing: border-box;
}
.glovebox-card__media {
	max-width: 100%;
	max-height: 72vh;
	border-radius: var(--radius-card);
	object-fit: contain;
	box-shadow: 0 12px 32px rgba(0, 0, 0, .18);
	background: var(--surface-sunken);
}
.glovebox-card__frame {
	width: 100%;
	height: 72vh;
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	background: var(--surface-sunken);
}
.glovebox-card__caption {
	margin: 0;
	font-family: var(--font-mono);
	font-size: 13px;
	color: var(--text-3);
	text-align: center;
}
.glovebox-empty {
	height: 100dvh;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 12px;
	text-align: center;
	padding: 0 24px;
	box-sizing: border-box;
}
.glovebox-empty a { color: var(--accent); }

/* ==========================================================================
   §60 Settings UI overhaul — editorial header, section rail, panel cards,
   toggle switch, setting rows, sticky save bar. Appended + unlayered so it
   wins over the legacy .form-section styling.
   ========================================================================== */

/* Two-column shell: sticky section rail + content column. Collapses to a
   horizontal scroll rail (the pre-§60 .car-tabs behaviour) below 720px. */
.settings-shell {
	display: grid;
	grid-template-columns: minmax(190px, 230px) minmax(0, 1fr);
	gap: clamp(1.25rem, 3vw, 2.5rem);
	align-items: start;
}

.settings-main {
	min-width: 0;
	max-width: 720px;
	display: flex;
	flex-direction: column;
	gap: clamp(1rem, 2vw, 1.4rem);
}
/* Top-level settings forms are flex columns with the SAME gap, so panels stacked
   inside a form (calc/AI/notifications/server) are spaced identically to panels
   that are direct .settings-main children (account) — one uniform panel margin
   everywhere. The `>` keeps this off nested password/charge-source forms. */
.settings-main > form {
	display: flex;
	flex-direction: column;
	gap: clamp(1rem, 2vw, 1.4rem);
}

/* ── Section rail (desktop vertical nav) ─────────────────────────────────── */
.settings-rail {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	position: sticky;
	top: 1.5rem;
}

/* Mirrors the sidebar .side-link so the two navs read as one system: tinted
   pill on active/hover, accent text — no left border. */
.settings-rail__item {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	padding: 0.5rem 0.7rem;
	border-radius: var(--radius-control);
	font-size: 13.5px;
	font-weight: 500;
	color: var(--text-2);
	text-decoration: none;
	transition: color var(--timing-fast) var(--ease-out), background var(--timing-fast) var(--ease-out);
}
.settings-rail__item .icon { width: 1.15em; height: 1.15em; color: var(--text-4); flex: none; transition: color var(--timing-fast) var(--ease-out); }
.settings-rail__item:hover { color: var(--ink); background: var(--tint-sm); }
.settings-rail__item:hover .icon { color: var(--text-2); }
.settings-rail__item--active { color: var(--accent); background: var(--accent-soft); font-weight: 600; }
.settings-rail__item--active .icon { color: var(--accent); }

/* ── Editorial header ────────────────────────────────────────────────────── */
.settings-header { margin-bottom: 0.25rem; }
.settings-header .eyebrow { margin-bottom: 0.5rem; }
.settings-header__title {
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 520;
	font-size: clamp(24px, 4vw, 34px);
	letter-spacing: -0.015em;
	line-height: 1.05;
	color: var(--ink);
	margin: 0;
}
.settings-header__desc {
	margin: 0.5rem 0 0;
	color: var(--text-3);
	font-size: 14px;
	max-width: 52ch;
}

/* ── Panel card head (serif, replaces the .form-section-title micro-label) ── */
.settings-panel__head { margin-bottom: 1rem; }
.settings-panel__title {
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 520;
	font-size: clamp(17px, 2.2vw, 20px);
	letter-spacing: -0.01em;
	line-height: 1.15;
	color: var(--ink);
	margin: 0;
}
.settings-panel__desc { margin: 0.3rem 0 0; color: var(--text-3); font-size: 13px; }
/* Sub-head inside a panel (e.g. a second grouping within one card). */
.settings-panel__subhead {
	font-family: var(--font-serif);
	font-weight: 520;
	font-size: 15px;
	color: var(--ink);
	margin: 1.4rem 0 0.6rem;
}

/* ── Setting row (label + hint left, control right) ──────────────────────── */
.setting-row {
	display: grid;
	grid-template-columns: 1fr auto;
	align-items: center;
	gap: 0.6rem 1.25rem;
	padding: 0.7rem 0;
	border-bottom: 1px solid var(--border-subtle);
}
.setting-row:last-child { border-bottom: 0; padding-bottom: 0; }
.setting-row__label { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.setting-row__label .form-label { margin: 0; }
.setting-row__label .form-hint { margin: 0; }
.setting-row__control { justify-self: end; }
.setting-row > .toggle { justify-self: end; }
/* Compact controls (select / number) sit right in a fixed-width column. */
.setting-row__control:where(select, input:not([type="range"])) { width: 11rem; max-width: 100%; }
/* Full-width variant: control drops beneath the label (wide inputs, sliders). */
.setting-row--stack { grid-template-columns: 1fr; }
.setting-row--stack .setting-row__control { justify-self: stretch; width: 100%; }
.setting-row--stack > .form-label { margin: 0; }
.setting-slider { display: flex; align-items: center; gap: 0.75rem; }
.setting-slider input[type="range"] { flex: 1; }
/* Theme every range slider to the brand accent instead of the UA blue (thumb +
   filled track + focus ring, both light and dark via the light-dark() token). */
input[type="range"] { accent-color: var(--accent); }
.setting-slider__value {
	min-width: 3.5rem;
	text-align: right;
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	color: var(--text-2);
	font-size: 13px;
}

/* ── Toggle switch (replaces yes/no <select>) ────────────────────────────── */
.toggle {
	appearance: none;
	border: 0;
	background: none;
	padding: 0;
	cursor: pointer;
	display: inline-flex;
	flex: none;
}
.toggle__track {
	position: relative;
	width: 2.6rem;
	height: 1.5rem;
	border-radius: 999px;
	background: var(--surface-3);
	border: 1px solid var(--border);
	transition: background var(--timing-base) var(--ease-out), border-color var(--timing-base) var(--ease-out);
}
.toggle__thumb {
	position: absolute;
	top: 50%;
	left: 0.18rem;
	transform: translateY(-50%);
	width: 1.05rem;
	height: 1.05rem;
	border-radius: 50%;
	background: var(--surface-raised);
	box-shadow: 0 1px 2px var(--scrim-sm);
	transition: transform var(--timing-base) var(--ease-out), background var(--timing-base) var(--ease-out);
}
.toggle--on .toggle__track { background: var(--accent); border-color: var(--accent); }
.toggle--on .toggle__thumb { transform: translate(1.1rem, -50%); background: var(--accent-ink); }
.toggle:focus-visible { outline: none; }
.toggle:focus-visible .toggle__track { outline: 2px solid var(--accent); outline-offset: 2px; }
.toggle[disabled] { cursor: not-allowed; opacity: 0.45; }

/* §60 server-driven save status inside the thumb: spinner while in flight
   ($svi_<key>), a brief tick on a confirmed save ($sv_<key>='ok'), ✕ on error.
   Never optimistic — these classes are toggled only by the server's response. */
.toggle__thumb::after {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	font-size: 0.62rem;
	font-weight: 700;
	line-height: 1;
}
.toggle.is-saving .toggle__thumb::after {
	content: "";
	width: 0.6rem;
	height: 0.6rem;
	border-radius: 50%;
	border: 2px solid color-mix(in oklab, var(--accent) 35%, transparent);
	border-top-color: var(--accent);
	animation: btn-spin 0.6s linear infinite;
}
.toggle.is-saved .toggle__thumb::after { content: "✓"; color: var(--accent); animation: settings-tick 1.4s ease forwards; }
.toggle.is-error .toggle__thumb::after { content: "✕"; color: var(--critical); }
@keyframes settings-tick { 0%, 65% { opacity: 1; } 100% { opacity: 0; } }

/* Inline save-error reason (data-show/data-text off $sv_/$svmsg_ signals). */
.setting-row__err { margin-top: 0.15rem; font-size: 12px; color: var(--critical); }

/* §60 value-field save status (server-driven, same signals as the toggle): a
   faint accent border while in flight, a brief outline flash on a confirmed
   save, a steady red outline on error. */
.form-input.is-saving { border-color: var(--accent); }
.form-input.is-saved { outline: 2px solid var(--accent); outline-offset: 1px; animation: settings-flash 1.3s ease forwards; }
.form-input.is-error { outline: 2px solid var(--critical); outline-offset: 1px; }
@keyframes settings-flash { 0%, 55% { outline-color: var(--accent); } 100% { outline-color: transparent; } }
/* Slider readout flashes accent on save (an outline round the number looks odd). */
.setting-slider__value.is-saving { color: var(--accent); }
.setting-slider__value.is-saved { animation: settings-readout-flash 1.3s ease forwards; }
.setting-slider__value.is-error { color: var(--critical); }
@keyframes settings-readout-flash { 0%, 55% { color: var(--accent); } 100% { color: var(--text-2); } }

/* Nested AI sub-switches under the master toggle. */
.setting-substack {
	margin-top: 0.5rem;
	padding-left: 1rem;
	border-left: 2px solid var(--border-subtle);
}

/* ── Save bar (non-sticky, sits just below the editorial header) ─────────── */
.settings-actions {
	display: flex;
	justify-content: flex-end;
	gap: 0.6rem;
}

/* ── Responsive: collapse the rail to a horizontal scroll strip ──────────── */
@media (max-width: 720px) {
	.settings-shell { grid-template-columns: 1fr; gap: 1rem; }
	.settings-rail {
		position: static;
		flex-direction: row;
		gap: 0.25rem;
		overflow-x: auto;
		scrollbar-width: none;
		border-bottom: 1px solid var(--border-subtle);
	}
	.settings-rail::-webkit-scrollbar { display: none; }
	.settings-rail__item { white-space: nowrap; }
}

/* §20: on desktop the settings sections live in the sidebar subnav, so drop the
   in-page rail and let the content span the full width. Placed after the base
   .settings-shell/.settings-rail rules so it wins on source order (below 900px
   the sidebar is hidden and the in-page rail above is the section nav). */
@media (min-width: 901px) {
	.settings-shell { grid-template-columns: 1fr; }
	.settings-rail { display: none; }
}

/* ── §25 Security panel (password + passkeys) ────────────────────────────── */
/* One shared column width so every field (change-password, remove-password,
   passkey label) lines up — replaces the old per-form max-width:360px that
   left the same "current password" field rendering at two different widths. */
.security-body { max-width: 26rem; display: flex; flex-direction: column; gap: 1.6rem; }
.security-section { display: flex; flex-direction: column; }
.security-section .settings-panel__subhead { margin-top: 0; }

.security-form { display: flex; flex-direction: column; gap: 0.9rem; }
/* The "remove password" form is a lighter sub-action under the change form,
   set off by a hairline rather than a heavy separator. */
.security-form--sub {
	margin-top: 1.1rem;
	padding-top: 1.1rem;
	border-top: 1px solid var(--border-subtle);
}
.security-form .form-input { width: 100%; }
/* Left-aligned actions sit directly under their field — no border-topped,
   right-floated bar that reads as detached from the form. */
.security-form__actions { display: flex; justify-content: flex-start; }

/* Passkey list: name + inline bare-icon delete. The name is plain text, not an
   input, so it is NOT wrapped in .form-input; the delete is an icon button with
   no box until hover. */
.security-passkey-list { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; flex-direction: column; }
.security-passkey {
	display: flex;
	align-items: center;
	gap: 0.65rem;
	padding: 0.55rem 0;
	border-bottom: 1px solid var(--border-subtle);
}
.security-passkey:first-child { border-top: 1px solid var(--border-subtle); }
.security-passkey__icon { width: 1rem; height: 1rem; color: var(--text-3); flex: none; }
.security-passkey__name {
	flex: 1;
	min-width: 0;
	font-size: 0.875rem;
	color: var(--text);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.security-passkey__del {
	flex: none;
	display: inline-grid;
	place-items: center;
	width: 1.9rem;
	height: 1.9rem;
	padding: 0;
	border: 0;
	background: none;
	color: var(--text-4);
	cursor: pointer;
	border-radius: var(--radius-control);
	transition: color var(--timing-base) var(--ease-out), background var(--timing-base) var(--ease-out);
}
.security-passkey__del .icon { width: 1rem; height: 1rem; }
.security-passkey__del:hover { color: var(--clr-repair); background: var(--clr-repair-bg); }

/* Add row: the label spans the full width on its own line (it is long — "e.g.
   «MacBook Touch ID»" — and shouldn't fight the input for horizontal space);
   below it the input grows and the add button sits beside it, so the button
   belongs to the passkeys section instead of floating below a divider. */
.security-passkey-add { display: flex; flex-direction: column; gap: 0.375rem; }
.security-passkey-add__row { display: flex; align-items: center; gap: 0.6rem; }
.security-passkey-add__input { flex: 1; min-width: 0; }
.security-passkey-add__btn { flex: none; white-space: nowrap; }

@media (max-width: 480px) {
	.security-passkey-add__row { flex-direction: column; align-items: stretch; }
	.security-passkey-add__btn { width: 100%; }
}

/* ==========================================================================
   §63 Mobile chrome — top app bar + fixed bottom tab bar + "Mehr" sheet
   Below --mobile-bp (700px) the desktop Sidebar is hidden and replaced by a
   slim sticky top bar (compact wordmark + avatar) and a thumb-reachable fixed
   bottom tab bar; the four secondary destinations move into a "Mehr" bottom
   sheet. Desktop (> breakpoint) is untouched: both bars are display:none. The
   scan-heavy standalone pages (glovebox, auth) render their own <body> class
   and keep their own chrome -- the body-padding reset is scoped via :has() to
   app-shell pages only.
   ========================================================================== */
.mobile-topbar,
.tabbar { display: none; }

/* ── Mobile top app bar ──────────────────────────────────────────────────── */
.mobile-topbar {
	position: sticky;
	top: 0;
	z-index: 40;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	height: 56px;
	padding: 0 clamp(1rem, 4vw, 1.25rem);
	background: var(--surface-raised);
	border-bottom: 1px solid var(--border-subtle);
}
.mobile-topbar__brand {
	font-family: var(--font-serif);
	font-optical-sizing: auto;
	font-weight: 600;
	font-size: 22px;
	letter-spacing: -0.015em;
	line-height: 1;
	color: var(--ink);
	text-decoration: none;
}

/* ── Bottom tab bar ──────────────────────────────────────────────────────── */
.tabbar {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 50;
	align-items: stretch;
	/* Items cap + centre so the bar doesn't stretch awkwardly wide on tablets
	   (up to the ≤900px breakpoint); on a phone they just fill the width. */
	justify-content: center;
	gap: clamp(2px, 2vw, 1.5rem);
	padding: 6px 6px calc(6px + env(safe-area-inset-bottom));
	background: var(--surface-raised);
	border-top: 1px solid var(--border-subtle);
}
.tabbar__item {
	flex: 1 1 0;
	max-width: 132px;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 3px;
	min-height: 48px;
	padding: 4px 2px;
	border: 0;
	background: none;
	border-radius: var(--radius-control);
	color: var(--text-3);
	text-decoration: none;
	font: inherit;
	font-size: 10.5px;
	font-weight: 500;
	line-height: 1;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
}
.tabbar__item .icon { width: 22px; height: 22px; color: var(--text-3); flex: none; }
.tabbar__item:active { background: var(--tint-sm); }
.tabbar__item--active { color: var(--accent); }
.tabbar__item--active .icon { color: var(--accent); }
.tabbar__label {
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* ── "Mehr" bottom sheet ─────────────────────────────────────────────────── */
.more-sheet {
	border: 0;
	padding: 0;
	background: transparent;
}
.more-sheet[open] {
	position: fixed;
	inset: auto 0 0 0;
	margin: 0;
	width: 100%;
	max-width: 100%;
	max-height: 85vh;
}
.more-sheet::backdrop { background: var(--sheet-scrim); }
.more-sheet__panel {
	background: var(--surface-raised);
	border-top: 1px solid var(--border-subtle);
	border-top-left-radius: var(--radius-card);
	border-top-right-radius: var(--radius-card);
	padding: 0.5rem clamp(1rem, 4vw, 1.25rem) calc(1.25rem + env(safe-area-inset-bottom));
	box-shadow: 0 -12px 32px -12px color-mix(in oklab, #000 40%, transparent);
}
.more-sheet__grabber {
	width: 36px;
	height: 4px;
	margin: 0.35rem auto 0.75rem;
	border-radius: 999px;
	background: var(--border-strong, var(--text-4));
	opacity: 0.4;
}
.more-sheet__nav { display: flex; flex-direction: column; gap: 2px; }
.more-sheet__link {
	display: flex;
	align-items: center;
	gap: 0.85rem;
	min-height: 48px;
	padding: 0.6rem 0.65rem;
	border-radius: var(--radius-control);
	color: var(--text-2);
	text-decoration: none;
	font-weight: 500;
	font-size: 15px;
}
.more-sheet__link .icon { width: 1.2em; height: 1.2em; color: var(--text-4); flex: none; }
.more-sheet__link:active { background: var(--tint-sm); }
.more-sheet__link--active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.more-sheet__link--active .icon { color: var(--accent); }
.more-sheet__privacy {
	display: flex;
	gap: 0.55rem;
	align-items: flex-start;
	margin-top: 0.75rem;
	padding: 0.7rem 0.65rem;
	background: var(--surface-sunken);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
}
.more-sheet__privacy .icon { color: var(--accent); width: 1.05em; height: 1.05em; margin-top: 1px; flex: none; }

/* ── Activate the mobile chrome ──────────────────────────────────────────── */
/* Up to 900px (tablet portrait — iPad 768/834 — and down). Above it the desktop
   Sidebar stands; below it the top app bar + bottom tab bar take over. */
@media (max-width: 900px) {
	/* Full-bleed app chrome; content padding comes from #carlist / .topbar. Scoped
	   to app-shell pages so the standalone glovebox/auth bodies keep their own
	   padding (incl. the glovebox's own fixed-nav gutter). */
	body:has(.app-shell) { padding: 0; }
	.sidebar { display: none; }
	.mobile-topbar { display: flex; }
	.tabbar { display: flex; }
	/* Clear the fixed bottom tab bar. */
	.shell-main { padding-bottom: calc(58px + env(safe-area-inset-bottom)); }
	/* The avatar lives in the mobile top bar now; drop the duplicate in the
	   per-page editorial header (this also ends the stranded-avatar wrapping). */
	.topbar .avatar-menu { display: none; }
	.topbar__actions { width: 100%; }
	/* Add-car / scan / TCO-estimator header buttons are covered by the capture
	   FAB on mobile — hide them so the page header isn't a wall of buttons. The
	   year picker (also in .topbar__actions) stays. */
	.header-actions-left,
	.header-actions-right { display: none; }
}

/* ── §63 center capture FAB + quick-capture sheet ────────────────────────── */
.tabbar__capture {
	flex: 0 0 auto;
	align-self: center;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	margin: 0 6px;
	border: 0;
	border-radius: 999px;
	background: var(--accent);
	color: var(--accent-ink);
	cursor: pointer;
	box-shadow: 0 6px 16px -4px color-mix(in oklab, var(--accent) 55%, transparent);
	-webkit-tap-highlight-color: transparent;
}
.tabbar__capture .icon { width: 26px; height: 26px; color: var(--accent-ink); flex: none; }
.tabbar__capture:active { transform: translateY(1px); }

.capture-sheet { border: 0; padding: 0; background: transparent; }
.capture-sheet[open] {
	position: fixed;
	inset: auto 0 0 0;
	margin: 0;
	width: 100%;
	max-width: 100%;
	max-height: 85vh;
}
.capture-sheet::backdrop { background: var(--sheet-scrim); }
.capture-sheet__panel {
	background: var(--surface-raised);
	border-top: 1px solid var(--border-subtle);
	border-top-left-radius: var(--radius-card);
	border-top-right-radius: var(--radius-card);
	padding: 0.5rem clamp(1rem, 4vw, 1.25rem) calc(1.25rem + env(safe-area-inset-bottom));
	box-shadow: 0 -12px 32px -12px color-mix(in oklab, #000 40%, transparent);
}
.capture-sheet__title {
	margin: 0 0 0.75rem;
	font-family: var(--font-serif);
	font-size: 19px;
	font-weight: 600;
	color: var(--ink);
}
.capture-sheet__carpick { display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: 0.6rem; }
.capture-sheet__carlabel { font-size: 12px; font-weight: 600; color: var(--text-3); }
.capture-sheet__scanform { margin: 0; }
.capture-sheet__file { display: none; }
.capture-sheet__action {
	display: flex;
	align-items: center;
	gap: 0.85rem;
	width: 100%;
	min-height: 52px;
	padding: 0.7rem 0.75rem;
	border: 0;
	background: none;
	border-radius: var(--radius-control);
	color: var(--text-2);
	text-align: left;
	text-decoration: none;
	font: inherit;
	font-size: 15px;
	font-weight: 500;
	cursor: pointer;
}
.capture-sheet__action .icon { width: 1.3em; height: 1.3em; color: var(--accent); flex: none; }
.capture-sheet__action:active { background: var(--tint-sm); }
.capture-sheet__divider { height: 1px; margin: 0.5rem 0; background: var(--border-subtle); }
/* §35 two-phase scan overlay hosted inside the sheet while a Fahrzeugausweis is
   uploading/OCR'ing — centered, with room for the XL ring and the scanner beam. */
.capture-sheet__scanstate {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 14rem;
	padding: 0.75rem 0 0.5rem;
}

/* ── §63 phone polish: compact car-detail hero actions + footer tap targets ── */
@media (max-width: 640px) {
	/* The car-detail hero action row is 6 buttons (odometer / MFK done / primary
	   / edit / share / delete). On a phone that wraps to 3 rows — collapse to
	   icon-only so it's one tidy row. Labels are visually-hidden (not removed),
	   so each button keeps its accessible name; button colour still encodes
	   intent (soft quick-actions, secondary neutral, danger delete). */
	.car-hero__actions .btn {
		padding: 0.55rem;
		gap: 0;
	}
	.car-hero__actions .btn > span {
		position: absolute;
		width: 1px; height: 1px;
		padding: 0; margin: -1px;
		overflow: hidden;
		clip: rect(0 0 0 0);
		white-space: nowrap;
		border: 0;
	}
	/* Give the small footer links a ≥24px tap target (Lighthouse target-size). */
	.footer-content .footer-link { padding: 0.4rem 0.3rem; }
	/* When the row wraps on a phone, drop the middot separators and let the
	   flex gap space the items — avoids a middot dangling at a line end. */
	.footer-content { gap: 0.1rem 0.35rem; }
	.footer-content .footer-divider { display: none; }
}

/* ============================================================================
   §27 Shareable TCO cards (Story teilen)
   The story sheet: a swipeable carousel of server-rendered card PNGs (1080×1920,
   tdewolff/canvas), shown as <img> scaled to fit. Rendering is server-side, so
   there is no on-screen rasterization target — the <img> IS the shared export.
   ============================================================================ */

.story-modal .form-body { padding-top: 0.75rem; }

.story-carousel {
	display: flex;
	gap: 20px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	padding: 8px 4px 12px;
	-webkit-overflow-scrolling: touch;
}
.story-slide {
	flex: 0 0 auto;
	scroll-snap-align: center;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
}
.story-slide__name {
	margin: 0;
	font-family: var(--font-mono);
	font-size: 12px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--text-3);
}
/* The card frame carries the size + a centered loading spinner; the <img> lays
   over it and, once its opaque PNG has loaded, covers the spinner — so no JS or
   load event is needed, and the amounts-toggle re-fetch shows the spinner too. */
.story-card-frame {
	position: relative;
	width: min(74vw, 300px);
	aspect-ratio: 1080 / 1920;
	border-radius: var(--radius-card);
	box-shadow: 0 12px 32px rgba(0, 0, 0, .18);
	background: var(--surface-sunken);
	overflow: hidden;
}
@media (min-width: 720px) { .story-card-frame { width: 340px; } }
.story-card-frame::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 34px;
	height: 34px;
	margin: -17px 0 0 -17px;
	border: 3px solid color-mix(in oklab, var(--ink) 15%, transparent);
	border-top-color: var(--accent);
	border-radius: 50%;
	animation: sc-spin 0.8s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .story-card-frame::before { animation: none; } }
@keyframes sc-spin { to { transform: rotate(360deg); } }
.story-card-img {
	position: relative;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}
.story-slide__share { align-self: stretch; justify-content: center; }
.story-toggle {
	display: flex;
	align-items: center;
	gap: 8px;
	font-family: var(--font-mono);
	font-size: 13px;
	color: var(--text-2);
	margin: 0 4px 10px;
	cursor: pointer;
}
.story-toggle input { accent-color: var(--accent); }

/* Toast — the app's shared non-blocking notification (see internal/ui/toast.templ).
   A small card pinned bottom-centre, above the mobile tab bar, that auto-dismisses
   and optionally carries a single action button. Distinct from window.__notify,
   which is a centred modal dialog. */
.toast {
	position: fixed;
	left: 50%;
	bottom: 20px;
	transform: translateX(-50%);
	z-index: 60;
	display: flex;
	align-items: center;
	gap: 12px;
	max-width: min(92vw, 460px);
	padding: 10px 12px 10px 18px;
	background: var(--surface-raised);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-card);
	box-shadow: 0 12px 40px rgba(0, 0, 0, .22);
	animation: toast-in 0.3s ease;
}
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 12px); } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }
.toast__icon { color: var(--accent); display: inline-flex; }
.toast__text { margin: 0; font-size: 14px; color: var(--text-1); flex: 1 1 auto; }
.toast__action, .toast__close { flex: 0 0 auto; }
/* Clear the fixed bottom tab bar (shown ≤900px). */
@media (max-width: 900px) { .toast { bottom: calc(72px + env(safe-area-inset-bottom)); } }

/* ── §73 Inc 6 Drive view (realtime GPS instrument) ─────────────────────────
   A full-screen dialog the driver looks at while a GPS-live trip records. Shell
   is server-rendered; trip-recorder.ts writes the live numerals. Token-driven so
   it flips with the OS theme — a cream day-instrument in light, a night HUD in
   dark. Mobile-first: safe-area insets, thumb-reachable controls at the bottom. */
.drive {
	position: fixed;
	inset: 0;
	margin: 0;
	padding: 0;
	width: 100vw;
	height: 100dvh;
	max-width: 100vw;
	max-height: 100dvh;
	border: 0;
	background: var(--surface);
	color: var(--text-1);
	overflow: hidden;
}
.drive::backdrop { background: var(--surface); }
.drive__inner {
	position: relative;
	isolation: isolate;
	display: flex;
	flex-direction: column;
	gap: 1rem;
	height: 100dvh;
	padding: max(0.9rem, env(safe-area-inset-top)) max(1.1rem, env(safe-area-inset-right)) max(1.1rem, env(safe-area-inset-bottom)) max(1.1rem, env(safe-area-inset-left));
}
.drive__map { position: absolute; inset: 0; z-index: -2; display: block; width: 100%; height: 100%; }
.drive__scrim {
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background:
		radial-gradient(130% 90% at 50% 4%, color-mix(in oklab, var(--accent) 12%, transparent), transparent 58%),
		radial-gradient(120% 70% at 50% 100%, color-mix(in oklab, var(--ink) 6%, transparent), transparent 60%);
}
.drive__bar { display: flex; align-items: center; gap: 0.6rem; flex-wrap: nowrap; }
.drive__rec { display: inline-flex; align-items: center; gap: 0.5rem; min-width: 0; }
.drive__rec-dot {
	width: 0.6rem;
	height: 0.6rem;
	border-radius: 50%;
	background: var(--clr-repair);
	animation: drive-pulse 1.9s ease-out infinite;
}
.drive__elapsed {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: 1.05rem;
	font-weight: 600;
	letter-spacing: 0.02em;
}
.drive__rec-label {
	font-size: 0.68rem;
	text-transform: uppercase;
	letter-spacing: 0.09em;
	color: var(--text-3);
	white-space: nowrap;
}
/* The dot + running clock already say "recording"; drop the label on narrow phones
   so the status bar never wraps or overflows. */
@media (max-width: 400px) { .drive__rec-label { display: none; } }
.drive__status { margin-left: auto; display: inline-flex; align-items: center; gap: 0.55rem; flex: 0 0 auto; }
.drive__signal {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: 0.74rem;
	padding: 0.16rem 0.55rem;
	border-radius: var(--radius-pill);
	border: 1px solid var(--border);
	color: var(--text-3);
	white-space: nowrap;
}
.drive__signal[data-state="good"] { color: var(--clr-sell); border-color: color-mix(in oklab, var(--clr-sell) 45%, transparent); }
.drive__signal[data-state="ok"] { color: var(--clr-fuel); border-color: color-mix(in oklab, var(--clr-fuel) 45%, transparent); }
.drive__signal[data-state="weak"] { color: var(--clr-repair); border-color: color-mix(in oklab, var(--clr-repair) 45%, transparent); }
.drive__wake { display: inline-flex; color: var(--text-5); }
.drive__wake.is-on { color: var(--accent); }
.drive__wake svg { width: 1rem; height: 1rem; }
/* Server-connectedness beacon: green when the /points link is up, amber when a gap
   is buffering. Distinct from the (satellite) GPS chip — link ≠ GPS. */
.drive__link {
	width: 0.5rem;
	height: 0.5rem;
	border-radius: 50%;
	background: var(--clr-fuel);
	transition: background 0.3s ease;
}
.drive__link.is-online { background: var(--clr-sell); }
.drive__offline-bar {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	margin-top: -0.35rem;
	padding: 0.35rem 0.6rem;
	border-radius: var(--radius-control);
	font-size: 0.78rem;
	color: var(--clr-fuel);
	background: color-mix(in oklab, var(--clr-fuel) 13%, transparent);
	border: 1px solid color-mix(in oklab, var(--clr-fuel) 32%, transparent);
}
.drive__offline-bar svg { width: 0.9rem; height: 0.9rem; flex: 0 0 auto; }
/* The server figures dim while offline so a frozen value reads as "paused", not broken. */
.drive .is-stale { opacity: 0.42; transition: opacity 0.3s ease; }
.drive__min {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.1rem;
	height: 2.1rem;
	border-radius: 50%;
	border: 1px solid var(--border);
	background: var(--surface-raised);
	color: var(--text-2);
	cursor: pointer;
}
.drive__min svg { width: 1.15rem; height: 1.15rem; }
.drive__hero { margin-top: auto; display: flex; flex-direction: column; align-items: flex-start; gap: 0.15rem; }
.drive__distance {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: clamp(4rem, 27vw, 8.5rem);
	font-weight: 600;
	line-height: 0.92;
	letter-spacing: -0.03em;
}
.drive__unit { font-size: 0.85rem; letter-spacing: 0.02em; color: var(--text-3); }
.drive__metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.55rem; }
.drive__metric {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	padding: 0.7rem 0.8rem;
	border-radius: var(--radius-card);
	background: color-mix(in oklab, var(--surface-raised) 72%, transparent);
	border: 1px solid var(--border-subtle);
}
.drive__metric-val {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: 1.35rem;
	font-weight: 600;
	white-space: nowrap;
}
.drive__metric-val small { font-size: 0.68rem; font-weight: 500; color: var(--text-3); }
.drive__metric-label { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-4); }
.drive__purpose {
	align-self: flex-start;
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.35rem 0.8rem;
	border-radius: var(--radius-pill);
	background: color-mix(in oklab, var(--accent) 15%, transparent);
	color: var(--accent);
	font-size: 0.82rem;
	font-weight: 550;
}
.drive__purpose svg { width: 0.95rem; height: 0.95rem; }
.drive__controls { display: grid; grid-template-columns: 1fr 1.7fr; gap: 0.7rem; }
.drive__controls .btn { justify-content: center; padding-block: 0.9rem; font-size: 1rem; }
@keyframes drive-pulse {
	0% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--clr-repair) 55%, transparent); }
	70% { box-shadow: 0 0 0 0.7rem transparent; }
	100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { .drive__rec-dot { animation: none; } }

/* §73 Inc C — auto night palette: the cockpit is always the dark instrument,
   regardless of the page theme (less glare on a dash-mounted phone). light-dark()
   tokens resolve dark under this; the <drive-map> accent probe follows in-context. */
.drive,
.drive-summary { color-scheme: dark; }

/* Entry flourish (reduced-motion gated). */
@media (prefers-reduced-motion: no-preference) {
	.drive[open] { animation: drive-enter 0.4s cubic-bezier(0.2, 0.8, 0.2, 1); }
	.drive::backdrop { animation: drive-backdrop 0.35s ease; }
	.drive-summary[open] { animation: drive-enter 0.42s cubic-bezier(0.2, 0.85, 0.2, 1); }
}
@keyframes drive-enter { from { opacity: 0; transform: translateY(1.6%); } to { opacity: 1; transform: none; } }
@keyframes drive-backdrop { from { opacity: 0; } to { opacity: 1; } }

/* Odometer-roll hero: mono/tabular digits -> uniform 0-9 strips that slide on change. */
odo-meter.drive__distance { display: inline-flex; align-items: flex-end; line-height: 1; }
.odo-col { display: inline-block; height: 1em; overflow: hidden; }
.odo-strip { display: block; will-change: transform; }
.odo-strip > span { display: block; height: 1em; line-height: 1em; text-align: center; }
.odo-static { display: inline-block; }
@media (prefers-reduced-motion: no-preference) {
	.odo-strip { transition: transform 0.55s cubic-bezier(0.2, 0.85, 0.25, 1); }
}

/* Stop summary — full-screen dark card with the final figures + kept-track map. */
.drive-summary {
	position: fixed;
	inset: 0;
	margin: 0;
	padding: 0;
	width: 100vw;
	height: 100dvh;
	max-width: 100vw;
	max-height: 100dvh;
	border: 0;
	background: var(--surface);
	color: var(--text-1);
	overflow: hidden;
}
.drive-summary::backdrop { background: var(--surface); }
.drive-summary__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	height: 100dvh;
	text-align: center;
	padding: max(1.4rem, env(safe-area-inset-top)) 1.4rem max(1.4rem, env(safe-area-inset-bottom));
}
.drive-summary__check {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 3.4rem;
	height: 3.4rem;
	border-radius: 50%;
	background: color-mix(in oklab, var(--clr-sell) 18%, transparent);
	color: var(--clr-sell);
}
.drive-summary__check svg { width: 1.8rem; height: 1.8rem; }
.drive-summary__title { font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--text-3); }
.drive-summary__map { width: min(88vw, 340px); }
.drive-summary__map .trip-map { width: 100%; height: auto; display: block; }
.drive-summary__hero { display: flex; flex-direction: column; align-items: center; gap: 0.15rem; margin-top: 0.3rem; }
.drive-summary__dist {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: clamp(3.4rem, 22vw, 6rem);
	font-weight: 600;
	line-height: 0.92;
	letter-spacing: -0.03em;
}
.drive-summary__unit { font-size: 0.9rem; color: var(--text-3); }
.drive-summary__meta { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem 1.1rem; color: var(--text-2); font-size: 0.9rem; }
.drive-summary__stat { display: inline-flex; align-items: center; gap: 0.35rem; }
.drive-summary__stat svg { width: 0.95rem; height: 0.95rem; color: var(--text-4); }
.drive-summary__done { margin-top: 1rem; min-width: 12rem; justify-content: center; padding-block: 0.9rem; }
@media (prefers-reduced-motion: no-preference) {
	.drive-summary[open] .drive-summary__check { animation: drive-check-pop 0.5s 0.08s backwards cubic-bezier(0.2, 1.3, 0.4, 1); }
}
@keyframes drive-check-pop { from { transform: scale(0.4); opacity: 0; } to { transform: scale(1); opacity: 1; } }
