/* ═══ Legal pages — shared stylesheet ═══════════════════════════════════
   Used by /impressum, /datenschutz, /en/legal-notice and /en/privacy.

   Why this is a file and not inline, when AGENTS.md says keep CSS inline in
   index.html: that rule exists so the *site* stays one self-contained page.
   These are four sibling documents with identical chrome. Inlining would mean
   four copies of the same rules drifting apart, and a legal page whose footer
   has silently stopped matching the others is exactly the failure this work is
   meant to prevent. vendor/psi-tokens/*.css already establishes <link> as an
   accepted pattern here. index.html is untouched by this file.

   Everything below resolves to a --psi-* token. No hardcoded colour or type
   value. Keep it that way. */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* ── Local semantic layer ────────────────────────────────────────────
     Muted metadata needs more alpha on platinum than on carbon to hold the
     same contrast, so the footer's copyright line reads from this rather than
     a fixed value. Restated here rather than imported so these pages stand
     alone.

     `--control-border` used to live here too, mirroring index.html. It is gone:
     its only consumer was the footer legal links' border, and those are plain
     text links now. There are no controls on a legal page — nothing to give a
     boundary to. */
  --muted-opacity: 0.5;
  /* Reading measure. Narrower than --psi-container-max on purpose: this is
     continuous prose, not a layout grid. */
  --measure: 68ch;
}

[data-psi-theme="light"] {
  /* psi's light theme ships neither the typefaces nor the zero radius, and
     the page identity has to survive the theme switch. Mirrors index.html. */
  --psi-font-sans: "Archivo", system-ui, sans-serif;
  --psi-font-serif: "IBM Plex Serif", Georgia, serif;
  --psi-font-mono: "IBM Plex Mono", "Courier New", monospace;
  --psi-font-display: "Archivo", system-ui, sans-serif;
  --psi-card-radius: 0;

  --muted-opacity: 0.75;
}

body {
  background: var(--psi-bg-primary);
  color: var(--psi-fg-primary);
  font-family: var(--psi-font-display);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: inherit; }

/* ═══ Nav ═══════════════════════════════════════════════════════════════ */

.legal-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--psi-space-16);
  flex-wrap: wrap;
  max-width: var(--psi-container-max);
  margin: 0 auto;
  padding: var(--psi-space-24) var(--psi-gutter);
  border-bottom: 1px solid var(--psi-border-faint);
}

.wordmark {
  font: var(--psi-display-32-32-extrabold);
  letter-spacing: 0.06em;
  text-decoration: none;
  text-transform: uppercase;
}
.wordmark span { color: var(--psi-fg-accent); }

.legal-nav .back {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font: var(--psi-text-mono-14-20-regular);
  text-decoration: none;
  color: var(--psi-fg-secondary);
  transition: color var(--psi-duration-200);
}
.legal-nav .back:hover { color: var(--psi-fg-accent); }

/* ═══ Document ══════════════════════════════════════════════════════════ */

.legal {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--psi-space-80) var(--psi-gutter) var(--psi-space-96);
}

.legal .eyebrow {
  font: var(--psi-text-mono-13-20-regular);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--psi-fg-accent);
  margin-bottom: var(--psi-space-12);
}

/* German compounds are the sizing constraint here, not the English ones.
   "DATENSCHUTZERKLÄRUNG" is one 20-character unbreakable word: at the 560px
   step it still measured 411px against a 327px box, pushing the document to
   435px at a 375px viewport and — because body sets overflow-x: hidden — being
   silently clipped rather than scrolled. hyphens:auto breaks it at the real
   German syllable boundaries (the <html lang> is what makes that work);
   overflow-wrap is the fallback for any word the hyphenation dictionary does
   not know. Applied at every width, not just the narrow step, because
   "Umsatzsteuer-Identifikationsnummer" is long enough to matter earlier. */
.legal h1,
.legal h2 {
  overflow-wrap: break-word;
  hyphens: auto;
}

.legal h1 {
  font: var(--psi-display-36-64-black);
  letter-spacing: -0.02em;
  text-transform: uppercase;
  margin-bottom: var(--psi-space-40);
}

/* psi has no bold display step between 20 and 32px, so h2 borrows the text
   ramp's top bold and takes the display family explicitly. Replace with the
   token once psi ships that step. */
.legal h2 {
  font: var(--psi-text-20-28-semibold);
  font-family: var(--psi-font-display);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-top: var(--psi-space-48);
  margin-bottom: var(--psi-space-16);
  padding-top: var(--psi-space-24);
  border-top: 1px solid var(--psi-border-faint);
}
/* The first section sits directly under the h1's own spacing. */
.legal h2:first-of-type { margin-top: 0; }

.legal p,
.legal li {
  font: var(--psi-text-serif-18-28-regular);
  color: var(--psi-fg-primary);
}
.legal p + p { margin-top: var(--psi-space-16); }

.legal ul { margin: var(--psi-space-16) 0 0 var(--psi-space-24); }
.legal li + li { margin-top: var(--psi-space-8); }
/* A paragraph after a list needs the same separation as one after a paragraph.
   Without this the prose closing a section butts straight against the last
   bullet — visible on the privacy pages, where several sections are a list
   followed by its legal-basis paragraph. */
.legal ul + p { margin-top: var(--psi-space-16); }

/* Postal / contact block. Preserves the line breaks an Impressum needs
   without a <pre>, which would drop out of the serif ramp. Leading is the
   token's own — a looser custom line-height was tried and removed, because it
   was the one hardcoded type value in this file and the 18/28 ramp already
   sets an address comfortably. */
.legal .address {
  font: var(--psi-text-serif-18-28-regular);
}

.legal a:not(.back):not(.wordmark) {
  color: var(--psi-fg-accent);
  text-underline-offset: 3px;
}

/* Literal identifiers the privacy pages have to quote exactly — the storage key,
   its two values, the deploy region, the mailto scheme. These are strings a
   reader may need to match character-for-character against their own browser
   storage, so they get the mono face rather than italics or quotation marks.

   Sized at 15px against the 18px serif body on purpose: IBM Plex Mono runs
   large on the x-height, so matching the number would make the identifier
   louder than the sentence carrying it. 15/24 is also the top of psi's mono
   ramp — there is no 16 or 18 step to reach for. The 24px line-height is
   shorter than the paragraph's 28 and so never expands the line box. No
   background or border: a tint block per identifier would stipple the page, and
   these appear mid-sentence rather than as code blocks. */
.legal code {
  font: var(--psi-text-mono-15-24-regular);
  color: var(--psi-fg-secondary);
  overflow-wrap: break-word;
}

.legal .note {
  font: var(--psi-text-mono-13-20-regular);
  color: var(--psi-fg-secondary);
  margin-top: var(--psi-space-32);
  padding-top: var(--psi-space-16);
  border-top: 1px solid var(--psi-border-faint);
}

/* ═══ TODO(owner) — must be impossible to miss ══════════════════════════ */

/* Same treatment as .unpublished below, deliberately: both mark "this is not
   finished", and one idea should not have two visual languages in one
   stylesheet. This started as a 3px left tab, which read as a different kind
   of object than the banner and is a tired pattern besides. A full hairline in
   the accent, over the accent tint, is louder than anything else on a page
   whose entire vocabulary is 1px neutral hairlines — and the accent-coloured
   "TODO(owner) —" prefix does most of the work regardless. */
.todo {
  display: block;
  margin: var(--psi-space-16) 0;
  padding: var(--psi-space-16) var(--psi-space-20);
  border: 1px solid var(--psi-fill-accent);
  background: var(--psi-fill-tint-accent);
  font: var(--psi-text-mono-14-20-regular);
  color: var(--psi-fg-primary);
  white-space: pre-wrap;
}
.todo::before {
  content: "TODO(owner) — ";
  color: var(--psi-fg-accent);
  font-weight: 500;
}

/* The whole-page unfinished banner on the two privacy scaffolds. */
.unpublished {
  margin-bottom: var(--psi-space-40);
  padding: var(--psi-space-20);
  border: 1px solid var(--psi-fill-accent);
  background: var(--psi-fill-tint-accent);
}
.unpublished p {
  font: var(--psi-text-mono-14-20-regular) !important;
  font-family: var(--psi-font-mono) !important;
}
.unpublished p + p { margin-top: var(--psi-space-12); }

/* ═══ Footer ════════════════════════════════════════════════════════════ */

footer {
  margin-top: var(--psi-space-96);
  border-top: 1px solid var(--psi-border-faint);
  background: var(--psi-bg-secondary);
}
.footer-inner {
  max-width: var(--psi-container-max);
  margin: 0 auto;
  padding: var(--psi-space-48) var(--psi-gutter) var(--psi-space-32);
  display: flex;
  flex-direction: column;
  gap: var(--psi-space-24);
}
/* Plain links, not bordered chips — matching index.html. The border these
   used to carry is the boundary this system reserves for controls, and these
   are destinations. Hit area is unchanged at 44px; the target just stops
   drawing itself, and the gap widens to carry the separation the border used
   to provide. */
/* Asymmetric: the 24px is column separation replacing the border. As a row gap
   it is dead space — each link already has padding inside a 44px box. */
.footer-legal { display: flex; gap: var(--psi-space-4) var(--psi-space-24); flex-wrap: wrap; }
.footer-legal a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: var(--psi-space-8) 0;
  color: var(--psi-fg-secondary);
  font: var(--psi-text-mono-14-20-regular);
  text-decoration: none;
  transition: color var(--psi-duration-200);
}
.footer-legal a:hover {
  color: var(--psi-fg-accent);
  text-decoration: underline;
  text-underline-offset: 4px;
}
/* Current page: full-strength ink rather than an accent box. Without the
   border there is nothing to tint, and promoting it out of the secondary ramp
   distinguishes it without spending the accent — which the Heat Rule reserves
   for what is alive or clickable, and the page you are on is neither. */
.footer-legal a[aria-current="page"] {
  color: var(--psi-fg-primary);
}

.footer-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--psi-space-16);
  flex-wrap: wrap;
  border-top: 1px solid var(--psi-border-faint);
  padding-top: var(--psi-space-24);
}
.footer-meta p {
  font: var(--psi-text-mono-13-20-regular);
  opacity: var(--muted-opacity);
}

/* ═══ Narrow ════════════════════════════════════════════════════════════ */

@media (max-width: 560px) {
  .legal { padding-top: var(--psi-space-48); }
  .legal h1 { font: var(--psi-text-30-36-bold); font-family: var(--psi-font-display); text-transform: uppercase; }
  .footer-meta { flex-direction: column; gap: var(--psi-space-8); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; }
}
