/*
 * Practice microsite -- Patientenseite density
 * (docs/plans/practice_microsites_plan.md §16; .claude/skills/praxista-design
 * ADOPTION.md §1: 18px body, >=48px controls, measure 620px).
 *
 * Token VALUES are GENERATED between the markers below, from design/ via
 * scripts/build_design_tokens.py, and CI fails if they drift (--check). Do
 * not edit inside the markers; everything below them is hand-written and
 * free to restyle (the visual pass happens in the design phase --
 * docs/plans/practice_microsites_release1_phase.md, UI deliverables).
 *
 * This file serves the PLATFORM pages -- the root, the 404 and the three
 * legal pages -- and is the sibling of
 * app/services/microsites/templates/styles.css, which serves each practice's
 * own page. That one was brought under the generator on 2026-09-23 and THIS
 * ONE WAS MISSED, one directory over: it was still serving
 * --paper-inset #FAF9F6 (retired 2026-09-22) and --line-inset #EAE8E4 (a
 * name in no token file at all) from mein.praxista.de on 2026-10-05, with
 * --check green throughout, because a generator only guards the files it is
 * pointed at. docs/findings.md F-42.
 *
 * No @import, no url() to another host, no web font fetch: this file must
 * stay free of third-party requests (§7.2). Hanken Grotesk is used when the
 * visitor has it; a self-hosted woff2 is a design-phase deliverable.
 */
/* >>> BEGIN GENERATED -- design tokens. Do not edit inside these markers. */
/* Source: design/tokens.json + design/bundle.css (hash 2ff9f31da520).
 * Regenerate: python3 scripts/build_design_tokens.py
 * The @font-face IS here, and no @theme: this file is served by a
 * static server that must make no third-party request, and has no
 * Tailwind. The microsite's own locals are below the end marker.
 *
 * The font moved into this generated half on 2026-10-07. It was
 * omitted on the premise that `the microsite fetches no font`, which
 * stopped being true when T14 gave the microsite host its own
 * /fonts/ route -- and the cost of the stale premise was paid twice:
 * the practice page carried a HAND-WRITTEN rule declaring
 * `font-weight: 100 900` where design/tokens.json says `200 700`,
 * and the four platform pages (Impressum, Datenschutz,
 * Nutzungsbedingungen, 404) had no rule at all and rendered in
 * Helvetica. Generated from one source, --check now holds both in
 * step with the vendored binary.
 *
 * Only the 38 tokens the hand-written CSS below actually
 * reads, plus what those reference. This is a public page the plan
 * keeps small; emitting all of them put ~95 unread declarations and a
 * grain data URI on it. To use another token, reference it in the
 * hand-written CSS below and regenerate -- nothing is listed twice.
 * (Deliberately no var() example here: this header is inside the
 * generated half, and a scanner reading the other half must not
 * find a token name in a comment.) */
:root {
  --font-hanken: "Hanken Grotesk","Helvetica Neue",Helvetica,Arial,sans-serif;
  --font-display: var(--font-hanken);
  --font-ui: var(--font-hanken);
  --font-data: var(--font-hanken);
  --type-title: 300 32px/1.2 var(--font-display);
  --type-section: 600 16px/1.4 var(--font-ui);
  --type-body: 400 18px/1.6 var(--font-ui);
  --type-data: 500 14px/1.4 var(--font-data);
  --type-data-tracking: 0.01em;
  --type-label: 500 11px/1.2 var(--font-data);
  --type-label-tracking: 0.1em;
  --blue-900: #1B3E9E;
  --blue-700: #2A56C8;
  --paper-page: #FCFCFA;
  --paper-white: #FFFFFF;
  --text-body: #0F2438;
  --text-secondary: #3E5060;
  --text-label: #6E6653;
  --line: #E3E7EB;
  --line-row: #EFF2F4;
  --focus: var(--blue-700);
  --heading: var(--blue-700);
  --link: var(--blue-700);
  --link-hover: var(--blue-900);
  --measure-patient: 620px;
  --page-w-patient: 684px;
  --space-0: 4px;
  --space-1: 8px;
  --space-2: 12px;
  --space-3: 20px;
  --space-4: 32px;
  --space-5: 52px;
  --radius-card: 16px;
  --control-min-patient: 48px;
  --focus-width: 2px;
  --focus-offset: 2px;
  --hl-1: inset 0 1px 0 rgba(255,255,255,0.7);
  --elev-card: 0 1px 1px rgba(20,40,94,0.04),0 2px 6px rgba(20,40,94,0.05);
}

/* The brand typeface, self-hosted. Praxista is EU-sovereign on OTC and
   serves German health data; a Google Fonts request transmits the
   visitor's IP to a US controller, which is the pattern LG Muenchen I
   ruled on (3 O 17493/20). SIL OFL 1.1 -- the licence ships beside the
   binary. One variable file, no subsetting: it carries 550 codepoints,
   a superset of the two subset files it replaced (latin 222 +
   latin-ext 199 = 409, nothing lost). */
@font-face {
  font-family: "Hanken Grotesk";
  src: url("/fonts/HankenGrotesk-wght.woff2") format("woff2");
  font-weight: 200 700;
  font-style: normal;
  font-display: swap;
}
/* <<< END GENERATED */

/* The four platform pages -- Impressum, Datenschutzerklärung,
   Nutzungsbedingungen and the 404 -- built to canvas B2 Version 8's twenty
   rules (plan §4.3.3, ruled 2026-10-07). Rule numbers below are that
   ruling's, so a reader can contradict any line by pointing at R-n.
   The practice page is a different document with a different stylesheet;
   nothing here styles it.

   R1: a platform page is ONE document card holding n named sections -- it
   was four separate cards until today, which said these were four unrelated
   things rather than one document. */
/* The density is declared ONCE, on <html>, and every rule below reads only
   the density-free names -- the same indirection the practice page uses.
   Entscheidung 1: never a measure with density in its name on an element of
   this page. `--type-data` IS the patient scale and naming it directly
   bypasses the indirection, which is what this file did in seven places
   until 2026-10-07. */
[data-density="patient"] {
  --type-title-d: var(--type-title);    /* 300 32/1.2 */
  --type-section-d: var(--type-section); /* 600 16/1.4, smaller than body */
  --type-body-d: var(--type-body);      /* 400 18/1.6 */
  --type-data-d: var(--type-data);      /* 500 14/1.4 */
  --control-min: var(--control-min-patient);  /* 48 */
  --measure: var(--measure-patient);    /* 620, the prose measure (R15) */
  --gap-block: var(--space-4);          /* 32, inside the card */
  --gap-section: var(--space-5);        /* 52, between sections */
}

* { box-sizing: border-box; }

html { color-scheme: light; }

body {
  margin: 0;
  background: var(--paper-page);
  color: var(--text-body);
  font: var(--type-body-d);
  -webkit-font-smoothing: antialiased;

  /* R6: a number keeps its value size and takes weight 500; the figures line
     up because of this, not because they were shrunk to --type-data. */
  font-variant-numeric: tabular-nums;
}

/* R15: the column is --page-w-patient (684) and NOT --measure-doc (720).
   684 = 620 + 2x32, so the prose measure already fills it exactly; a 720
   column would have needed a token that does not exist. Prose is capped at
   --measure separately, below. */
.page {
  padding: var(--space-4);
  display: flex;
  justify-content: center;
}
.column {
  width: 100%;
  max-width: var(--page-w-patient);
  display: flex;
  flex-direction: column;
  gap: var(--gap-section);
}

.doc {
  background: var(--paper-white);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--hl-1), var(--elev-card);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--gap-block);
}

/* R11: the title stands alone. No eyebrow above it and no explanatory
   sentence under it -- the scope of a document is a section, not a subtitle,
   and `Praxista` as an eyebrow was a second carrier of what the ANBIETER row
   already says (R12's reasoning, applied upward). */
.doc__title {
  margin: 0;
  font: var(--type-title-d);
  color: var(--heading);
}

/* components/Rechtstext §3/§4 (13.10.2026): Datenschutzerklärung and
   Nutzungsbedingungen show their Fassung under the title -- "Fassung vom
   TT.MM.JJJJ" in --type-data-d and --text-secondary, --space-2 (12) below
   the h1. The Impressum has none. */
.doc__kopf {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.doc__fassung {
  margin: 0;
  font: var(--type-data-d);
  letter-spacing: var(--type-data-tracking);
  color: var(--text-secondary);
}

/* components/Rechtstext §3, Silbentrennung (ruled 13.10.2026, „Befunde aus
   dem Bau" question 2): the TEXT breaks the title, at the joint of its
   compound, with a soft hyphen in the markup -- Datenschutz&shy;erklärung,
   Nutzungs&shy;bedingungen -- never where the browser would ("Datenschutz-
   erklä-rung" in Chrome). The text below is the browser's (hyphens: auto,
   lang="de" on <html>), section heads included, except a proper name and an
   address (.eigenname, .adresse, mailto:), which nobody hyphenates; an
   address that does not fit breaks without a hyphen and never gains a
   character; a number (tel:) never wraps. break-word is the last safeguard:
   a word never runs over the edge and the type never shrinks to make it
   fit. Scoped to the three legal documents -- the 404 is not one -- and not
   inherited by the foot, which sits outside the card and never hyphenates. */
.doc--rechtstext {
  -webkit-hyphens: auto;
  hyphens: auto;
  overflow-wrap: break-word;
}
.doc--rechtstext .doc__title,
.doc--rechtstext .eigenname,
.doc--rechtstext .adresse,
.doc--rechtstext a[href^="mailto:"] {
  -webkit-hyphens: manual;
  hyphens: manual;
}
.doc--rechtstext .adresse,
.doc--rechtstext a[href^="mailto:"] {
  overflow-wrap: anywhere;
}
.doc--rechtstext a[href^="tel:"] { white-space: nowrap; }

/* components/Rechtstext §3, Absätze (ruled 13.10.2026, question 1 -- B2's
   R9/R9' not adopted): one ladder at both addresses, 8 · 12 · 32 · 52 --
   head of a section → first paragraph 8, paragraph → paragraph 12, section
   → section 32, the document's head → first section 52. The largest seam
   of a legal text is between its head and its text. */
.doc--rechtstext { gap: var(--gap-section); }

.abschnitte {
  display: flex;
  flex-direction: column;
  gap: var(--gap-block);
}

.abschnitt > * + * { margin-top: var(--space-2); }
.abschnitt > .abschnitt__title + * { margin-top: var(--space-1); }

/* R1/R2: the section head carries by weight and colour, never by size -- it
   is SMALLER than the body text it heads (600/16 against 400/18). R2: a legal
   basis is a heading, verbatim, because the label register has exactly one
   level and the row-pairs below already use it; "§ 18 Abs. 2 MStV" is not a
   category, and 11px uppercase at 0.1em makes a paragraph sign unreadable. */
.abschnitt__title {
  margin: 0;
  font: var(--type-section-d);
  color: var(--heading);
}

.abschnitt p {
  margin-bottom: 0;
  max-width: var(--measure);
}
.abschnitt > p:first-child { margin-top: 0; }

/* components/Rechtstext §3, Verweise im Text (ruled 13.10.2026, question 1
   -- B2's R8 not adopted): a link stands where the text sets it, in the
   sentence. Its tap area is 48 px MEASURED (§3, corrected 13.10.2026): the
   padding above and below the word is computed from the word's height --
   the font's content area, 23.49 px at 18/1.6 -- not from the line box:
   (48 - 23.49) / 2 = 12.26 px, rounded up. Nothing left and right; the
   line box stays 28.8 px. No recess, no bold, no italics, no inline code
   anywhere in the three documents (§3, Hervorhebung). */
.abschnitt p a { padding: 12.26px 0; }

/* R16 / the 480px rule from 04.10 (and components/Rechtstext §2): page
   margin and document padding drop a rung below 480, exactly as on the
   practice page.
   ⚠️ This block must stay BELOW the .doc rule. It
   stood above them until 2026-10-13, and at equal specificity the later
   `padding: var(--space-4)` won: the page margin dropped to 20 and the card
   kept 32, so at 375 px the text was 269 px wide instead of the 293 the
   Rechtstext card computes. Measured in a browser, not seen in review. */
@media (max-width: 479px) {
  .page { padding: var(--space-3); }
  .doc { padding: var(--space-3); }
}

/* The row-pairs. R3: a section carries a dl when it carries more than one
   KIND of fact; carrying one, the value is the content and there is no
   label. R4: a row-pair never crosses a section boundary. */
.paare { margin: 0; }
.paar {
  display: flex;
  flex-direction: column;
  gap: var(--space-0);
  padding: var(--space-2) 0;
  border-top: 1px solid var(--line-row);
}
.paar:first-child { border-top: 0; padding-top: 0; }
.paar:last-child { padding-bottom: 0; }

.paar dt {
  font: var(--type-label);
  letter-spacing: var(--type-label-tracking);
  text-transform: uppercase;
  color: var(--text-label);
}
.paar dd {
  margin: 0;
  font: var(--type-body-d);
  color: var(--text-body);
}

/* R6 again: a register number, a VAT id or a telephone number keeps the
   value size and takes weight 500. NOT shrunk to --type-data, which is the
   carrier of a data column or a metaline -- the brand book says "weight
   500", not "14px". A name, an address and an e-mail stay 400. */
.wert--zahl { font-weight: 500; }

/* A line under a value, with no label of its own -- the practice page calls
   this a Beizeile (Entscheidung 19) and it is the same shape here. It carries
   the one thing the artboard does not have: the § 27 a UStG citation that the
   live page has always shown. Kept deliberately. Dropping legal text to match
   a composition is the error this whole round was opened to fix, so it stays
   until the design side rules otherwise -- flagged in the plan, not decided
   here. --type-data is its carrier because a metaline is exactly what
   --type-data is for (R6's own reasoning, used in the direction it allows). */
.wert--hinweis {
  display: block;
  margin-top: var(--space-0);
  font: var(--type-data-d);
  letter-spacing: var(--type-data-tracking);
  color: var(--text-secondary);
}

/* R5: contact gets one row per channel, and each value is its own link, so
   each can reach 48px. Two links in one dd share a line box and neither
   can. (A link in a sentence of the text stays in it -- .abschnitt p a.) */
.tap {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-min);
}

/* R12: the foot carries the three statutory links and no Praxista sentence
   -- on Praxista's own Impressum the ANBIETER row carries that fact, so the
   sentence would be a second carrier. No label and no accessible name: the
   three link texts name themselves.
   R13, as components/PatientPage's foot made it on 13.10.2026 (and
   OeffentlicheSeite Entscheidung 7's dated precision of the same day): a
   <footer> holding a list of three entries, each at least 48 px, never
   truncated, never a menu --
     below 748 px  one under the other, each on its own 48 px line, with NO
                   separator (the line separates them; a wrapped row would
                   leave a middot at a line end, separating nothing);
     from 748 px   one row, the middot in --text-secondary, hidden from
                   assistive technology, --space-1 either side.
   748 = --page-w-patient + 2 x --space-4: the width at which the column is
   complete. Written mobile-first so "below 748" is exact at a fractional
   zoom width too. */
.footer__nav {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer__nav li {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}
.footer__sep {
  display: none;
  color: var(--text-secondary);
}
@media (min-width: 748px) {
  .footer__nav {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
  }
  .footer__sep { display: inline; }
}

/* components/Rechtstext §5 (13.10.2026), which replaced R14 the same day:
   on one of the three documents its OWN entry keeps its place, as TEXT and
   not as a link -- --text-secondary, no underline, aria-current="page", not
   focusable (a <span>, so it is in no tab order), on the same 48 px line as
   the others via .tap. Order and count never change from page to page. */
.footer__current { color: var(--text-secondary); }

a {
  color: var(--link);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
a:hover { color: var(--link-hover); }
a:focus-visible {
  outline: var(--focus-width) solid var(--focus);
  outline-offset: var(--focus-offset);
}

