43944d8cc8
Bug fixes:
- Navbar login/logout state now updates immediately (custom ep-auth-changed
event) instead of requiring a hard reload
- Status-change email links were broken by an un-encoded "#" in the order
number; fixed for all 4 status emails
- Cart discount code: manual input field restored (was removed entirely)
- Quote-label underline now scales with the label's actual text width
- Number Ranges admin list now shows the invoice prefix/counter columns
Pricing & VAT:
- Prices show the real per-product VAT rate ("inkl. X% MwSt.") instead of
a generic disclosure
- Cart/checkout/confirmation totals show the actual € amount of VAT
included, broken down per rate when a cart spans more than one
(new lib/taxBreakdown.ts, shared with the invoice PDF's own math)
- Account order pages gained product thumbnails and the same VAT breakdown
Low-stock warning: a "Nur noch wenige verfügbar" badge/hint across the
shop grid, spotlight, and add-to-cart variant pickers, driven by the
existing lowStockThreshold field (still never exposes raw stock counts).
Invoice PDFs: product thumbnails on every line item, a plain "Netto"
label (rate was redundant, already stated on the MwSt. line below), no
more duplicate USt-IdNr. in the header, and — for a Stornorechnung
specifically — an explicit "Versand" line that was previously only
folded silently into the tax totals.
Checkout:
- Optional deviating shipping address (separate from the billing address
used for the invoice), with its own toggle + address form
- Full checkout draft persistence (name/address/shipping/payment
selections) survives navigating away and back, via localStorage
- Invoice PDF shows a third "Lieferadresse" block when the shipping
address differs from billing
Mobile navigation: fullscreen panel with a circular reveal animation from
the hamburger's corner, replacing the old in-flow accordion drawer; no
login CTA inside it (redundant with the always-visible header icon).
Admin-facing (Payload backend, mirrored where the frontend has a ported
copy of the same renderer): dashboard rebuilt as individual cards, split
into 3 task queues (received/processing/returns) instead of 2, revenue
and order counts now exclude cancelled/returned orders immediately, and
the low-stock alert links to the specific affected product(s) instead of
the unfiltered list. A new immediate email notifies the shop owner the
moment an order comes in, instead of only via the daily digest.
Testimonials admin list now groups by page instead of interleaving all
three grids' entries. ~45 English admin field descriptions translated to
German for consistency.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
161 lines
7.1 KiB
CSS
161 lines
7.1 KiB
CSS
@import "tailwindcss";
|
|
|
|
/*
|
|
* Fluid design tokens — every value below scales continuously via clamp()
|
|
* between the Tablet breakpoint (768px) and Desktop (1440px). Below 768px
|
|
* the clamp() floor freezes the value automatically (no separate mobile
|
|
* media query needed for sizing — only for structural layout changes,
|
|
* see the `md:` breakpoint usage in components).
|
|
*
|
|
* Spacing overrides Tailwind's own numeric scale (--spacing-4 etc.) at the
|
|
* exact numbers the styleguide already used (n times 0.25rem equals the
|
|
* desktop value), so every existing p-4, gap-6, px-20 (etc.) utility
|
|
* becomes fluid for free.
|
|
*/
|
|
@theme {
|
|
/* Fonts */
|
|
--font-sans: var(--font-inter), system-ui, sans-serif;
|
|
--font-display: var(--font-playfair), Georgia, serif;
|
|
--font-serif: var(--font-lora), Georgia, serif;
|
|
--font-script: var(--font-caveat), cursive;
|
|
|
|
/* Colors */
|
|
--color-brand: #f6a701;
|
|
--color-brand-hover: #cf8e01; /* verified against the live Figma NavButtonFilled/Hover variant */
|
|
--color-bg-base: #f8f5f1;
|
|
--color-bg-white: #ffffff;
|
|
--color-bg-muted: #f3efe9;
|
|
--color-bg-dark: #1a1a18;
|
|
--color-text-primary: #1a1a18;
|
|
--color-text-body: #2c2c2a;
|
|
--color-text-muted: #6b6b69;
|
|
--color-text-light: #9b9896;
|
|
--color-text-on-dark: #ffffff;
|
|
--color-border: #e5e0d8;
|
|
--color-overlay: rgba(134, 134, 134, 0.55);
|
|
--color-checkout-active: #f6a701;
|
|
--color-checkout-done: #1a1a18;
|
|
--color-toc-active-border: #f6a701;
|
|
--color-success: #2f8f4e;
|
|
--color-success-subtle: #e8f4ea;
|
|
/* Low-stock warning — distinct from --color-brand's golden yellow (used
|
|
for the discount badge) so the two pills never read as the same thing. */
|
|
--color-warning: #c2410c;
|
|
--color-warning-subtle: #fdf1e9;
|
|
|
|
/* Radius */
|
|
--radius-xs: 0.25rem;
|
|
--radius-sm: 0.5rem;
|
|
--radius-md: 0.75rem;
|
|
|
|
/* Shadows */
|
|
--shadow-card: 0 2px 12px rgba(26, 26, 24, 0.06);
|
|
--shadow-modal: 0 8px 40px rgba(26, 26, 24, 0.16);
|
|
--shadow-sidebar: 0 2px 8px rgba(26, 26, 24, 0.08);
|
|
|
|
/* Type scale (fluid 768->1440) */
|
|
--text-display: clamp(2.75rem, 1.3214rem + 2.9762vw, 4rem);
|
|
--text-display--line-height: 1.1;
|
|
--text-h-feature: clamp(1.875rem, 1.1607rem + 1.4881vw, 2.5rem);
|
|
--text-h-feature--line-height: 1.2;
|
|
/* New role, added for page-todo-karten's hero heading (48px Desktop) —
|
|
doesn't match any existing scale step (h-feature=40, h1=36), Figma's
|
|
own measured value takes priority over eyeballing it into a near
|
|
token (Why-point 4). Tablet floor via the styleguide's 80-85% ratio,
|
|
rounded to 40px. "Product/tool page hero H1" role, distinct from
|
|
--text-h1 (already spoken for: "Seiten-H1 (Blog-Detail, Warenkorb,
|
|
etc.)" per styleguide.md §2.2 — a different, smaller role). Also used
|
|
by page-weekly-impulses's hero heading — same 48px role, reused
|
|
rather than minting a near-duplicate token. */
|
|
--text-h-page: clamp(2.5rem, 1.9286rem + 1.1905vw, 3rem);
|
|
--text-h-page--line-height: 1.15;
|
|
--text-h1: clamp(1.75rem, 1.1786rem + 1.1905vw, 2.25rem);
|
|
--text-h1--line-height: 1.15;
|
|
--text-h2: clamp(1.625rem, 1.1964rem + 0.8929vw, 2rem);
|
|
--text-h2--line-height: 1.25;
|
|
--text-h-section: clamp(1.4375rem, 1.0804rem + 0.744vw, 1.75rem);
|
|
--text-h-section--line-height: 1.3;
|
|
--text-h-emphasis: clamp(1.25rem, 0.9643rem + 0.5952vw, 1.5rem);
|
|
--text-h-emphasis--line-height: 1.4;
|
|
--text-h3: clamp(1.1875rem, 0.9732rem + 0.4464vw, 1.375rem);
|
|
--text-h3--line-height: 1.35;
|
|
--text-h-small: clamp(1.125rem, 0.9821rem + 0.2976vw, 1.25rem);
|
|
--text-h-small--line-height: 1.4;
|
|
--text-h4: clamp(1rem, 0.8571rem + 0.2976vw, 1.125rem);
|
|
--text-h4--line-height: 1.4;
|
|
--text-body: 1rem;
|
|
--text-body--line-height: 1.6;
|
|
--text-body-sm: 0.875rem;
|
|
--text-body-sm--line-height: 1.55;
|
|
--text-label: 0.75rem;
|
|
--text-label--line-height: 1.4;
|
|
|
|
/* Spacing scale (fluid 768->1440) — overrides Tailwind's default n*0.25rem
|
|
at these exact steps, so p-4/gap-6/px-20/etc. become fluid automatically */
|
|
--spacing-1: clamp(0.25rem, 0.25rem + 0vw, 0.25rem);
|
|
--spacing-2: clamp(0.5rem, 0.5rem + 0vw, 0.5rem);
|
|
--spacing-3: clamp(0.625rem, 0.4821rem + 0.2976vw, 0.75rem);
|
|
--spacing-4: clamp(0.875rem, 0.7321rem + 0.2976vw, 1rem);
|
|
--spacing-5: clamp(1rem, 0.7143rem + 0.5952vw, 1.25rem);
|
|
--spacing-6: clamp(1.25rem, 0.9643rem + 0.5952vw, 1.5rem);
|
|
--spacing-8: clamp(1.5rem, 0.9286rem + 1.1905vw, 2rem);
|
|
--spacing-10: clamp(1.75rem, 0.8929rem + 1.7857vw, 2.5rem);
|
|
--spacing-12: clamp(2rem, 0.8571rem + 2.381vw, 3rem);
|
|
--spacing-16: clamp(2.5rem, 0.7857rem + 3.5714vw, 4rem);
|
|
--spacing-20: clamp(3rem, 0.7143rem + 4.7619vw, 5rem);
|
|
--spacing-24: clamp(3.5rem, 0.6429rem + 5.9524vw, 6rem);
|
|
--spacing-30: clamp(4rem, 0rem + 8.3333vw, 7.5rem);
|
|
|
|
/* Transitions */
|
|
--transition-fast: 150ms ease;
|
|
--transition-base: 250ms ease;
|
|
--transition-slow: 400ms ease;
|
|
}
|
|
|
|
:root {
|
|
/* Layout — not part of Tailwind's numeric spacing scale, referenced via
|
|
arbitrary-value syntax (e.g. px-[var(--layout-padding-x)]) */
|
|
--layout-max-width: 75rem; /* 1200px */
|
|
--layout-padding-x: clamp(2rem, -1.4286rem + 7.1429vw, 5rem);
|
|
--layout-grid-gap: clamp(1rem, 0.4286rem + 1.1905vw, 1.5rem);
|
|
--layout-grid-gap-lg: clamp(1.25rem, 0.3929rem + 1.7857vw, 2rem);
|
|
|
|
/* One-off fluid values that aren't part of a broader scale */
|
|
--hero-avatar-size: clamp(2.25rem, 1.6071rem + 1.3393vw, 2.8125rem);
|
|
/* Newsletter copy column — was a hard 38.25rem, which didn't leave enough
|
|
room for the form column at the 768px tablet floor (only 656px of
|
|
content width available for 612px column plus 56px gap), crushing the
|
|
input/button/privacy text to near-zero width and overflowing the page.
|
|
Scales down to 23rem at 768px instead. */
|
|
--newsletter-copy-width: clamp(23rem, 5.5714rem + 36.3095vw, 38.25rem);
|
|
|
|
/* Divider section icons (arrow separators, sparkle) — previously hard
|
|
rem values while the "Klarheit/Fokus/Entlastung" text next to them
|
|
used the fluid text-h2 token, so the icons visually stayed still
|
|
while the words scaled. Same fluid(minPx, maxPx) formula as the rest
|
|
of this file, floor ~82.5% of the Desktop value per the styleguide's
|
|
80-85% Mobile-ratio guidance. */
|
|
--divider-arrow-w: clamp(2.125rem, 1.5536rem + 1.1905vw, 2.625rem);
|
|
--divider-arrow-h: clamp(0.625rem, 0.4821rem + 0.2976vw, 0.75rem);
|
|
--divider-sparkle-w: clamp(1.5625rem, 1.1554rem + 0.8482vw, 1.91875rem);
|
|
--divider-sparkle-h: clamp(2.0625rem, 1.5554rem + 1.0565vw, 2.50625rem);
|
|
--divider-sparkle-inner-w: clamp(1.4375rem, 1.09875rem + 0.706vw, 1.734rem);
|
|
--divider-sparkle-inner-h: clamp(1.9375rem, 1.4375rem + 1.0417vw, 2.375rem);
|
|
}
|
|
|
|
html {
|
|
scroll-padding-top: 6.25rem; /* navbar height */
|
|
/* Reserves the scrollbar's width permanently, so any modal's
|
|
overflow:hidden scroll lock (NewsletterModal, VersandModal) never
|
|
removes/re-adds the scrollbar itself — without this, losing the
|
|
scrollbar on open widens the viewport by its width and every fixed/sticky
|
|
element (Navbar included) visibly snaps sideways for one frame. */
|
|
scrollbar-gutter: stable;
|
|
}
|
|
|
|
body {
|
|
background: var(--color-bg-base);
|
|
color: var(--color-text-body);
|
|
font-family: var(--font-sans);
|
|
}
|