Files
windwiderstand/src/app.css
T
Peter Meier d781b3140e
Deploy / verify (push) Successful in 1m4s
Deploy / deploy (push) Successful in 1m9s
feat(calendar-compact): polish + global not-prose opt-out support
CalendarCompact:
- denser layout (smaller padding/font/badge), header icon size-8
- icon stein-900 (black), subtle wald gradient background
- rounded-sm to match design tokens (was rounded-lg)
- list items link to linkTo + "#event-<slug>" anchor; <svelte:element>
  falls back to div when no linkTo is set
- not-prose on root so global content margins/list/link rules don't
  apply to the card subtree

blog-utils.resolveCalendarBlocks:
- when items array is empty, fall back to the full calendar_item pool
  (both default and compact variant get this) — saves editors from
  re-listing items on every page.

app.css: add `:where(:not(.not-prose *))` to .content p/h1-h4,
main a (link colour + underline), main ul/ol so subtrees marked
not-prose stop inheriting the global prose-like defaults.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 09:16:21 +02:00

675 lines
16 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Windwiderstand Design System Fonts
Nur erlaubte Gewichte (02-typography.md: 300/400/500/600/700). 800/900 entfernt.
@fontsource setzt font-display: swap als Default — Text sichtbar während Font-Load. */
@import "@fontsource/inter/latin-300.css";
@import "@fontsource/inter/latin-400.css";
@import "@fontsource/inter/latin-500.css";
@import "@fontsource/inter/latin-600.css";
@import "@fontsource/inter/latin-700.css";
@import "@fontsource-variable/aleo";
@import "tailwindcss";
/* ==========================================================================
Component Utilities
========================================================================== */
@layer components {
/* Shared card surface: border, background, shadow, radius */
.card-surface {
@apply rounded-sm border border-stein-200 bg-white shadow-sm;
}
/* Diagonal strikethrough for past calendar days */
.day-past::after {
content: '';
position: absolute;
inset: 2px;
background: linear-gradient(
to top right,
transparent calc(50% - 0.5px),
rgba(0, 0, 0, 0.12) calc(50% - 0.5px),
rgba(0, 0, 0, 0.12) calc(50% + 0.5px),
transparent calc(50% + 0.5px)
);
pointer-events: none;
}
}
/* ==========================================================================
Design Tokens Windwiderstand (01-colors, 02-typography, 06-tokens.json)
========================================================================== */
@theme {
/* Palette: Wald (Primary) */
--color-wald-50: #f0f5f1;
--color-wald-100: #d9e8dc;
--color-wald-200: #b3d1b9;
--color-wald-300: #7fb58a;
--color-wald-400: #4a9960;
--color-wald-500: #2d7a45;
--color-wald-600: #236335;
--color-wald-700: #1a4d28;
--color-wald-800: #12361c;
--color-wald-900: #0a2011;
/* Palette: Erde (Secondary) */
--color-erde-50: #faf6f1;
--color-erde-100: #f0e6d6;
--color-erde-200: #e0ccad;
--color-erde-300: #c9a87a;
--color-erde-400: #b08a52;
--color-erde-500: #8b6d3f;
--color-erde-600: #6e5530;
--color-erde-700: #524023;
--color-erde-800: #372b18;
--color-erde-900: #1c160c;
/* Palette: Himmel (Accent / Links) */
--color-himmel-50: #f2f5f7;
--color-himmel-100: #dce4ea;
--color-himmel-200: #b8c9d4;
--color-himmel-300: #8aaabb;
--color-himmel-400: #5e8ba2;
--color-himmel-500: #436e85;
--color-himmel-600: #34576a;
--color-himmel-700: #264150;
--color-himmel-800: #1a2c36;
--color-himmel-900: #0e181e;
/* Palette: Fire (Tertiary) */
--color-fire-50: #fdf2f1;
--color-fire-100: #fbe5e3;
--color-fire-200: #f7c9c5;
--color-fire-300: #f2a8a2;
--color-fire-400: #eb8078;
--color-fire-500: #e35651;
--color-fire-600: #d93d36;
--color-fire-700: #c82e27;
--color-fire-800: #b5231e;
--color-fire-900: #981b18;
--color-fire-950: #5d0f0b;
/* Palette: Stein (Neutrals) */
--color-stein-0: #ffffff;
--color-stein-50: #f7f8f7;
--color-stein-100: #eceeed;
--color-stein-200: #d5d8d6;
--color-stein-300: #b0b5b2;
--color-stein-400: #868c89;
--color-stein-500: #636966;
--color-stein-600: #4a4f4c;
--color-stein-700: #333735;
--color-stein-800: #1f2221;
--color-stein-900: #0f1110;
/* Semantic: Success, Warning, Error, Info */
--color-success: var(--color-wald-500);
--color-success-subtle: var(--color-wald-50);
--color-warning: #a6780a;
--color-warning-subtle: #fdf8ec;
--color-error: #b53629;
--color-error-subtle: #fdf2f1;
--color-info: var(--color-himmel-500);
--color-info-subtle: var(--color-himmel-50);
/* Button (Primary = Wald) für @apply bg-btn-bg, text-btn-txt, bg-btn-hover-bg */
--color-btn-bg: var(--color-wald-500);
--color-btn-hover-bg: var(--color-wald-600);
--color-btn-txt: #fff;
/* Link (Himmel) für @apply text-link */
--color-link: var(--color-himmel-500);
/* Fonts Tailwind-Utilities: font-sans (Inter, default), font-serif (Aleo, Zitate) */
--font-sans: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
--font-serif: "Aleo Variable", Aleo, Georgia, "Times New Roman", serif;
}
:root {
/* Typography Inter (primary), Aleo (Zitate) */
--font-body: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
--font-secondary: "Aleo Variable", Aleo, Georgia, "Times New Roman", serif;
/* Semantic (nur Light Theme) */
--bg-primary: #ffffff;
--bg-secondary: #f7f8f7;
--bg-tertiary: #eceeed;
--bg-elevated: #ffffff;
--text-primary: #1f2221;
--text-secondary: #636966;
--text-tertiary: #868c89;
--border-default: #d5d8d6;
--border-strong: #b0b5b2;
--accent: #2d7a45;
--accent-hover: #236335;
--link: #436e85;
/* Legacy / App-Aliase (weiterverwendet) */
--color-font: var(--text-primary);
--color-headings: var(--text-primary);
--color-font-highlight: var(--color-error);
--color-navigation: var(--color-stein-0);
--background-color: var(--bg-primary);
--color-text: var(--text-primary);
--color-link: var(--link);
--color-btn-bg: var(--accent);
--color-btn-hover-bg: var(--accent-hover);
--color-btn-txt: #fff;
/* Breakout-Bereich: Verlauf Wald-50 → Wald-100 */
--color-container-breakout: linear-gradient(
to bottom,
white,
var(--color-wald-50)
);
font-family: var(--font-body);
font-size: 1.125rem; /* 18px Body Large laut Design System */
line-height: 1.556;
color: var(--color-font);
}
html {
background: var(--background-color);
}
main {
background: var(--bg-primary);
}
/* ==========================================================================
Typography Type Scale (02-typography.md)
Erlaubte Gewichte: 300, 400, 500, 600, 700. Inter primary, Aleo nur Zitate.
========================================================================== */
h1,
h2,
h3,
h4 {
color: var(--color-headings);
}
/* Mobile first, dann Tablet (768px), Desktop (1024px) */
h1 {
font-size: 1.75rem;
line-height: 2.125rem;
font-weight: 700;
letter-spacing: -0.015em;
}
h2 {
font-size: 1.375rem;
line-height: 1.75rem;
font-weight: 700;
letter-spacing: -0.01em;
}
h3 {
font-size: 1.25rem;
line-height: 1.625rem;
font-weight: 600;
letter-spacing: -0.005em;
}
h4 {
font-size: 1.125rem;
line-height: 1.5rem;
font-weight: 600;
}
@media (min-width: 768px) {
h1 {
font-size: 2.125rem;
line-height: 2.625rem;
}
h2 {
font-size: 1.5rem;
line-height: 2rem;
}
h3 {
font-size: 1.375rem;
line-height: 1.875rem;
}
h4 {
font-size: 1.125rem;
line-height: 1.625rem;
}
}
@media (min-width: 1024px) {
h1 {
font-size: 2.5rem;
line-height: 3rem;
}
h2 {
font-size: 1.75rem;
line-height: 2.25rem;
}
h3 {
font-size: 1.5rem;
line-height: 2rem;
}
}
/* Page-Titel (wie www.windwiderstand.de) */
.pageTitle h1 {
font-size: 1.5rem;
line-height: 2rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.pageTitle h2 {
font-size: 1rem;
line-height: 1.5rem;
font-weight: 500;
text-transform: none;
letter-spacing: 0;
}
.pageTitle h1,
.pageTitle h2 {
text-wrap: balance;
word-break: break-word;
overflow-wrap: break-word;
}
.pageTitle strong {
font-weight: 700;
}
@media (min-width: 768px) {
.pageTitle h1 {
font-size: 2.25rem;
line-height: 2.5rem;
}
.pageTitle h2 {
font-size: 1.5rem;
line-height: 2rem;
padding-left: 0.25rem;
}
}
@media (min-width: 1024px) {
.pageTitle h1 {
font-size: 3.75rem;
line-height: 1.14;
font-weight: 700;
letter-spacing: -0.02em;
}
.pageTitle h2 {
font-size: 1.875rem;
line-height: 2.25rem;
padding-left: 0.25rem;
}
}
/* Content-Links: Himmel (Design System Links).
* `:where(:not(.not-prose *))` schließt jeden Subtree mit `.not-prose`
* aus — Card-Links etc. behalten ihre eigene Farbe + kein Underline. */
main a:not(.no-underline):not([class*="btn"]):where(:not(.not-prose *)) {
color: var(--color-link);
text-decoration: underline;
}
main a:not(.no-underline):not([class*="btn"]):where(:not(.not-prose *)):hover {
color: var(--color-himmel-600);
}
/* Lange URLs/Links umbrechen ohne mitten im Wort zu trennen.
* `overflow-wrap: anywhere` bricht nur wenn nötig (lange URL), während das
* frühere `word-break: break-all` jedes Wort hackte — sichtbar bei
* Card-Links wie PostCard, wo der ganze Card-Text in einem `<a>` liegt. */
main a,
.markdown a {
overflow-wrap: anywhere;
}
main strong {
font-weight: 600;
}
main ul:not(.not-prose):where(:not(.not-prose *)) {
margin-left: 1em;
margin-bottom: 1em;
}
main ul:not(.not-prose):where(:not(.not-prose *)) li {
list-style: disc;
}
main ol:not(.not-prose):where(:not(.not-prose *)) {
margin-left: 1.1em;
margin-bottom: 1em;
}
main ol:not(.not-prose):where(:not(.not-prose *)) li {
list-style-type: decimal;
}
/* Buttons gemeinsame Basis */
.btn-primary,
.btn-secondary,
.btn-tertiary,
.btn-outline {
@apply inline-flex items-center gap-1 no-underline whitespace-nowrap transition-colors duration-200 font-medium px-4 py-2 rounded-xs;
}
/* Buttons Wald (Primary) */
.btn-primary {
@apply shadow-sm bg-btn-bg text-btn-txt;
}
.btn-primary:hover {
@apply bg-btn-hover-bg;
}
/* Buttons Stein outline (Secondary) */
.btn-secondary {
@apply border border-stein-300 bg-white text-stein-700 shadow-sm;
}
.btn-secondary:hover {
@apply bg-stein-100 border-stein-400;
}
/* Buttons Himmel (Tertiary) */
.btn-tertiary {
@apply shadow-sm bg-himmel-700 text-white;
}
.btn-tertiary:hover {
@apply bg-himmel-800;
}
/* Buttons Stein-Border klein (Outline) */
.btn-outline {
@apply border border-stein-300 text-stein-700;
}
.btn-outline:hover {
@apply bg-stein-100;
}
/* Größen-Modifier — nach den btn-* definiert damit override greift */
.btn-sm {
@apply px-2 py-1 text-xs gap-1;
}
/* Dekorativer Hintergrund mit zwei verschwommenen Verlaufs-Blobs (Wald → Erde).
Nutzung: Container mit relativer Positionierung; Blobs sitzen in ::before/::after.
Inhalt sollte z-Index >= 0 haben (Standard); Blobs liegen unter Stacking-Kontext. */
.gradient-blob-bg {
@apply relative isolate overflow-hidden;
}
.gradient-blob-bg::before,
.gradient-blob-bg::after {
content: "";
position: absolute;
top: 50%;
z-index: -10;
width: 36rem;
aspect-ratio: 577 / 310;
transform: translate3d(0, -50%, 0);
background: radial-gradient(
ellipse at center,
var(--color-himmel-400) 0%,
var(--color-himmel-200) 45%,
transparent 70%
);
opacity: 0.35;
filter: blur(40px);
pointer-events: none;
}
.gradient-blob-bg::before {
left: max(-7rem, calc(50% - 52rem));
}
.gradient-blob-bg::after {
left: max(45rem, calc(50% + 8rem));
}
/* Globaler Focus-Ring wald-Akzent für Tastatur-Nutzer (a11y + Polish) */
*:focus-visible {
outline: 2px solid var(--color-wald-500);
outline-offset: 2px;
border-radius: 2px;
}
/* Lead-Paragraph: erstes <p> in einem Top-Level MarkdownBlock innerhalb
<article> größer + leichter (Editorial). Bewusst auf article gescopt
damit weder Cards (.markdown in Callouts) noch Footer-MarkdownBlocks
mit Copyright-Text getroffen werden. */
article [data-block-type="markdown"] .markdown > p:first-child {
font-size: 1.25rem;
line-height: 1.55;
font-weight: 300;
color: var(--text-secondary);
margin-bottom: 1.25em;
}
@media (min-width: 768px) {
article [data-block-type="markdown"] .markdown > p:first-child {
font-size: 1.375rem;
}
}
/* Content-Row-Trenner: subtiler wald-Verlauf zwischen content-rows (Forest-Identität) */
.content-row + .content-row {
position: relative;
margin-top: 2rem;
}
.content-row + .content-row::before {
content: "";
display: block;
height: 1px;
background: linear-gradient(
90deg,
transparent,
var(--color-wald-200),
transparent
);
margin: 0 auto 2rem;
max-width: 50%;
}
/* Content-Blöcke. `:where(:not(.not-prose *))` lässt jeden Subtree mit
* .not-prose komplett ausserhalb dieser Margin-Defaults — Components, die
* eigene Abstände setzen, müssen nur `not-prose` auf den Root packen. */
.content p:where(:not(.not-prose *)) {
@apply mb-4;
}
.content h1:where(:not(.not-prose *)),
.content h2:where(:not(.not-prose *)),
.content h3:where(:not(.not-prose *)),
.content h4:where(:not(.not-prose *)) {
@apply mb-2;
}
/* Markdown: Abstände, Listen, Bilder, Tabellen (Stein-Palette) */
.markdown {
@apply min-w-0 overflow-x-auto;
}
.markdown h1,
.markdown h2,
.markdown h3,
.markdown h4,
.markdown hr {
@apply mt-4 mb-3;
}
.markdown hr {
@apply border-stein-200 border-dotted mb-4;
}
.markdown li,
.markdown li p {
@apply mt-0 mb-0;
}
.markdown p {
@apply mb-4;
}
.markdown ul,
.markdown ol {
@apply mt-0 mb-4;
}
.markdown li ul,
.markdown li ol {
@apply mb-0;
}
/* Markdown-Bilder: /cms-images-Transform, max-height begrenzt Höhe; Link öffnet Bild in neuem Tab */
.markdown img {
@apply max-w-full w-full my-2 border border-stein-200 rounded-xs bg-stein-200 shadow-sm inline-block;
max-height: 30vh;
}
.markdown .markdown-image-link {
@apply inline-block;
}
.markdown table {
@apply w-full min-w-max border-collapse text-left text-sm mb-4;
}
.markdown thead {
@apply bg-stein-100;
}
.markdown th {
@apply px-3 py-2 font-medium border border-stein-200;
}
.markdown td {
@apply px-3 py-2 border border-stein-200;
}
.markdown tbody tr:nth-child(even) {
@apply bg-stein-50;
}
.markdown tbody tr:hover {
@apply bg-stein-100;
}
.markdown table a {
@apply text-link underline underline-offset-2 break-all;
}
.markdown table a:hover {
@apply text-himmel-600;
}
/* Code: Inline und Block (pre/code) lesbare Größe, Stein-Palette */
main code,
.content code,
.markdown code {
@apply font-mono bg-stein-100 text-stein-800 border border-stein-200;
@apply text-sm px-1.5 py-0.5;
}
main pre,
.content pre,
.markdown pre {
@apply mt-3 mb-4 overflow-x-auto rounded-xs border border-stein-200 bg-stein-100 px-4 py-3 text-stein-800 leading-normal;
}
main pre code,
.content pre code,
.markdown pre code {
@apply border-0 bg-transparent p-0 text-inherit;
}
/* Container */
.container-custom {
@apply w-full mx-auto px-4 md:px-6;
}
@media (min-width: 768px) {
.container-custom {
max-width: 768px;
}
}
@media (min-width: 1024px) {
.container-custom {
max-width: 1024px;
}
}
@media (min-width: 1280px) {
.container-custom {
max-width: 1280px;
}
}
/* Zitate: Aleo (Design System nur für Zitate) */
blockquote[data-block-type="quote"],
blockquote[data-block-type="quote"] p,
blockquote[data-block-type="quote"] cite {
font-family: var(--font-secondary);
}
/* Footer */
footer a,
.content-footer a {
color: var(--color-link);
}
footer a:hover,
.content-footer a:hover {
color: var(--color-himmel-600);
}
.container-breakout {
margin-left: calc(50% - 50vw + 0.01rem);
margin-right: calc(50% - 50vw + 0.01rem);
background: var(--color-container-breakout);
}
/* ── Print rules ────────────────────────────────────────────────────────────
Goal: print only the article. `print:hidden` on chrome (header/footer/
banner/breadcrumbs/comments) handles structural removal. The rules below
set page margins, force black-on-white, expand links, and keep images
inside the page break. */
@media print {
@page {
margin: 1.5cm;
}
html,
body {
background: white \!important;
color: black \!important;
font-size: 11pt;
}
/* Show the URL after each anchor inside the article so printed pages stay
useful when the screen-only links are gone. */
article a[href]:not([href^="#"])::after {
content: " (" attr(href) ")";
font-size: 0.85em;
color: #555;
word-break: break-all;
}
/* Don't break inside images, keep figures together with their captions. */
img,
figure {
break-inside: avoid;
max-width: 100% \!important;
height: auto \!important;
}
/* Keep headings with the next paragraph. */
h1,
h2,
h3,
h4 {
break-after: avoid;
}
}