/*
 * Design foundation for every public page: color tokens, the locally
 * bundled Sora typeface, the page shell (skip link, nav, footer) and the
 * accessibility baseline (focus ring, reduced motion, input sizing).
 *
 * Sourced from _design/Musikschule Fleig-Stelzer.dc.html. THREE corrections
 * against that source. Two are from task-1-brief.md: --ink-muted replaces
 * both #7A756C and #9B958B, and every `outline: none` from the design is
 * replaced with a visible :focus-visible ring. The third was asked for by
 * the owner after looking at the running site: the tappable pills are padded
 * to clear the 44px minimum target size this file already keeps for every
 * input and button, which the design's own values do not. It affects
 * .site-nav__panel a.site-nav__cta and .post-filter__link, and each carries
 * the full argument at its own rule -- read it before reverting either to
 * the design's number.
 */

:root {
  --bg: #FAF9F7;
  --bg-soft: #F0EDE7;
  --surface: #fff;
  --ink: #1C1B1A;
  --ink-soft: #4B4842;
  --ink-muted: #6B665C;
  --line: #E8E5E0;
  --accent: #0F766E;
  --accent-dark: #0C5D57;
  --accent-bright: #4FD1C5;
  --dark: #14201E;
  --dark-soft: #1D2E2B;
  --on-dark: #F5F3EF;
  --on-dark-muted: #C9C4BB;
  --on-dark-faint: #8FA6A2;
  /* The enquiry form's validation messages, taken from the same colour the
     form's design draft uses for its error box (_design/ProbestundeFormular
     .dc.html). A token rather than a literal because the messages render on
     two dark surfaces and both pairings are checked by ContrastTests. */
  --warn-on-dark: #F5B8A8;
  /* The marker of a „Braucht Aufmerksamkeit“ hint on the admin Übersicht.
     Spec 2026-10-13 section 10: new colours only as tokens here. No rule in
     this file uses it, so ContrastTests does not see it;
     AdminShellContrastTests checks it against the white panel. */
  --warn: #9A5B00;

  --max-width: 1120px;
  /* Only consumer: the `scroll-margin-top` below, which keeps an in-page
     anchor target from landing underneath the sticky navigation bar. It has
     to track the bar's real height, and the bar is as tall as its tallest
     child plus its own 14px of vertical padding -- that child is the
     "Probestunde" button. Raised from 64px when the button's padding was
     corrected (see .site-nav__panel a.site-nav__cta): 14 + 14 + 46.4 = 74.4,
     rounded up. Left at 64 it would have been the change's own side effect,
     with every "#angebote"-style link scrolling ten pixels short. */
  --nav-height: 76px;
}

/* Sora, bundled locally under the SIL Open Font License. No network
   request ever leaves this origin for type — see wwwroot/fonts. */
@font-face {
  font-family: 'Sora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/sora-400.woff2') format('woff2');
}

@font-face {
  font-family: 'Sora';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/sora-600.woff2') format('woff2');
}

@font-face {
  font-family: 'Sora';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/sora-700.woff2') format('woff2');
}

@font-face {
  font-family: 'Sora';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/sora-800.woff2') format('woff2');
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: 'Sora', sans-serif;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

section,
header {
  scroll-margin-top: calc(var(--nav-height) + 12px);
}

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  color: var(--accent-dark);
}

::selection {
  background: var(--accent);
  color: #fff;
}

h1,
h2,
h3,
h4 {
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* Visible focus ring. The design turns `outline: none` on for every
   interactive element and relies on a border-color change instead — that
   loses keyboard users entirely. Every interactive element here keeps a
   clear focus-visible ring instead; nothing in this stylesheet sets
   `outline: none` without this rule providing the replacement. */
:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* Inputs and buttons inherit the page font and stay at a minimum tappable
   height across the site, matching the design's own `input, button { min-
   height: 44px; }` rule. */
input,
button,
select,
textarea {
  font-family: inherit;
  font-size: 16px;
  min-height: 44px;
}

button {
  cursor: pointer;
}

.skip-link {
  position: absolute;
  /* Fully above the top edge: the link is about 50px tall (2 x 12px padding
     plus one line), so -48px left a 2px sliver showing. */
  top: -80px;
  left: 12px;
  z-index: 100;
  background: var(--accent);
  color: #fff;
  padding: 12px 20px;
  border-radius: 8px;
  font-weight: 700;
  transition: top 0.2s ease;
}

.skip-link:focus {
  top: 12px;
}

/* ----- Navigation ----------------------------------------------------- */

.site-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

.site-nav__bar {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 14px 24px;
  display: flex;
  align-items: center;
  gap: 24px;
}

.site-nav__brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-weight: 800;
  font-size: 17px;
  color: var(--ink);
  letter-spacing: -0.02em;
  white-space: nowrap;
}

/* The mark (treble and bass clef) beside the word mark. 44px keeps the bar
   at --nav-height: 76px, which the CTA button sets (14 + 14 + 46.4). */
.site-nav__logo {
  display: block;
  height: 44px;
  width: auto;
}

.site-nav__brand:hover {
  color: var(--ink);
}

.site-nav__brand-accent {
  color: var(--accent);
}

/* Rendered unconditionally so the links stay reachable with scripting
   disabled and for screen readers; menu.js only collapses this behind the
   toggle button on narrow viewports once it has confirmed it is running
   (see the .js-enabled rules below). Without JavaScript this stays a plain,
   wrapping list of links regardless of viewport width. */
.site-nav__panel {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
  margin-left: auto;
  align-items: center;
  font-size: 14px;
  font-weight: 500;
}

.site-nav__panel a {
  color: var(--ink-soft);
  padding: 6px 0;
}

.site-nav__panel a:hover {
  color: var(--accent);
}

/* THE NAVIGATION CALL TO ACTION. TWO THINGS HERE ARE DELIBERATE AND BOTH
   LOOK WRONG IF YOU ONLY DIFF THEM AGAINST _design.

   1. THE SELECTOR carries the panel's own weight (`.site-nav__panel a`, one
      class plus one type) on purpose. The design's value was written here as
      a bare `.site-nav__cta`, which LOSES the cascade to `.site-nav__panel a`
      above: one class plus one type beats one class alone, whatever the
      source order. The declared `9px 18px` was therefore never once applied.
      What shipped was `padding: 6px 0` -- a pill with no horizontal padding
      at all, its rounded ends clipped against the word inside it. That is
      what the owner is looking at and reported as "too tight"; measuring the
      declaration rather than the computed style is why it read as faithful.
      The `color: #fff !important` this rule used to carry is the fingerprint
      of the same collision being noticed for the COLOUR and patched with a
      hammer instead of with specificity. With the selector corrected the
      colour wins on its own, and the `!important` is gone.

   2. THE VALUE departs from the design source, at the owner's request. Do
      not "correct" it back to `9px 18px` when diffing against
      _design/Musikschule Fleig-Stelzer.dc.html line 45. Two reasons:

      - Proportion. Every other pill in this stylesheet pads itself in
        proportion to its own text: the hero pair 14px/28px at 16px
        (0.88em / 1.75em), the event banner and the info panel 13px/26px at
        15px (0.87em / 1.73em). The design's 9px/18px at 14px is
        0.64em / 1.29em -- markedly tighter than its own siblings, which is
        why merely fixing the cascade still left it reading as cramped.
        12px/24px at 14px is 0.86em / 1.71em: the family's proportion.

      - Target size, and this is the binding reason. This stylesheet already
        commits every input, button, select and textarea to `min-height:
        44px` near the top of the file. An <a> is not covered by that rule,
        so the primary call to action of the entire site -- the most-tapped
        element on a phone -- was the one control on the page under the
        minimum: at 9px padding it stands 40.4px tall (9 + 9 + 14 x 1.6). At
        12px it is 46.4px and clears the bar the rest of the page keeps.

   NavigationSpacingTests holds both halves against the parsed stylesheet: it
   resolves the cascade to prove THIS rule's padding is the one that wins for
   the rendered element, and it fails for any pill-shaped link in this file
   that stands under 44px. */
.site-nav__panel a.site-nav__cta {
  background: var(--accent);
  color: #fff;
  padding: 12px 24px;
  border-radius: 999px;
  font-weight: 600;
}

.site-nav__panel a.site-nav__cta:hover {
  background: var(--accent-dark);
  color: #fff;
}

/* Hidden until menu.js proves it is running; see the brief: "Ohne
   JavaScript bleiben die Navigationslinks erreichbar (Panel serverseitig
   sichtbar, Button ausgeblendet)." */
.site-nav__toggle {
  display: none;
  margin-left: auto;
  background: none;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px 14px;
  font-family: 'Sora', sans-serif;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
}

@media (max-width: 899px) {
  .js-enabled .site-nav__toggle {
    display: inline-flex;
  }

  .js-enabled .site-nav__panel {
    display: none;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    padding: 8px 24px 20px;
    gap: 4px;
    border-top: 1px solid var(--line);
    margin-left: 0;
  }

  .js-enabled .site-nav__panel.is-open {
    display: flex;
  }

  .js-enabled .site-nav__panel a {
    padding: 12px 4px;
    font-size: 16px;
    font-weight: 600;
    color: var(--ink);
  }

  /* The mobile menu's copy of the same button, losing the same cascade one
     level deeper: `.js-enabled .site-nav__panel a` directly above sets
     `padding: 12px 4px` and `font-weight: 600`, and outranked the CTA's own
     rule exactly as the desktop pair did. The open menu was therefore showing
     a full-width pill with 4px of horizontal padding instead of the 13px/18px
     at weight 700 the design gives it (source line 61). The selector below
     matches the panel rule's weight and adds the button's own class, so the
     design's value is what applies. No 44px correction is wanted here and
     none is applied: 13 + 13 + 16 x 1.6 = 51.6px was always over the bar, so
     this variant is restored to the design rather than departing from it. */
  .js-enabled .site-nav__panel a.site-nav__cta {
    padding: 13px 18px;
    font-weight: 700;
    /* The colour has to be restated: `.js-enabled .site-nav__panel a` above
       sets `color: var(--ink)` at exactly the same specificity as the base
       button rule, and a tie is decided by source order, which this media
       block wins. The BACKGROUND is not overridden by anything and is
       restated only so the pairing stays derivable -- ContrastTests resolves
       a rule's background from the rule itself first, and without this line
       it walks out to .site-nav's --bg and reports white on off-white for a
       button that is in fact white on teal. */
    background: var(--accent);
    color: #fff;
    text-align: center;
    margin-top: 8px;
  }
}

/* ----- Footer ----------------------------------------------------------- */

.site-footer {
  border-top: 1px solid rgba(245, 243, 239, 0.12);
  background: var(--dark);
  color: var(--on-dark-faint);
}

.site-footer__bar {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 20px 24px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: space-between;
  font-size: 13px;
}

.site-footer__links {
  display: flex;
  gap: 20px;
}

.site-footer__links a {
  color: var(--on-dark-faint);
}

.site-footer__links a:hover {
  color: var(--accent-bright);
}

/* ----- Media (Task 3, image pipeline) ------------------------------------ */

/* THE FRAME. Every <Picture> renders one, photograph or placeholder
   alike, and the Picture component writes the class onto whichever element the
   slot turned out to be — a <picture> or the placeholder <div>. Together
   with the [data-aspect-ratio] rules below it, this is the box the design
   reserves for the picture (aspect-ratio: 16/10 for the
   event banner and a news card, 4/3 for a teacher, 21/10 for a post cover).

   position: relative is what the .media-image rule below positions against,
   so the two are one mechanism and neither works alone. A container may
   replace the box — .offering-tile__media does, because the design's
   instrument tile has the photograph fill the TILE rather than a ratio of
   its own — but nothing else may. */
.media-frame {
  display: block;
  position: relative;
  width: 100%;
}

/* THE CROP. The photograph fills the frame and the overflow is cut off,
   which is what the design does and what the site did not: a real image used
   to render at `width: 100%; height: auto`, its own shape, so the home page's
   1600×1067 landscape hero sat short and wide inside a slot reserved as tall
   4/5 portrait, and the event banner showed a whole photograph where the
   design showed a larger detail of one. Eight call sites passed a ratio that
   reached only the placeholder.

   object-position stays at its default, centre. There is no focal-point
   control in this application, so a 4/5 frame cuts the sides off a landscape
   photograph and a 16/10 frame cuts head and feet off a portrait one, and the
   only remedy for a bad crop is a better-framed upload — written down for the
   school in docs/betrieb/livegang-checkliste.md, section 6.

   The frame holding regardless of what is in it also removes the layout shift
   the placeholder alone used to hide: the page no longer reflows when the
   photographs arrive. */
.media-image {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Rendered by the Picture component in place of a null MediaImage (spec-2
   ledger, Ruling 3: the content seeder leaves every image reference empty
   until real photographs exist). A neutral block filling the same frame a
   photograph would -- never an empty or broken <img>. */
.media-placeholder {
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 12px;
}

/* The reserved space itself. This used to be an inline
   style="aspect-ratio: …" written by the tag helper, which is precisely what
   forced 'unsafe-inline' into the Content-Security-Policy's style-src
   directive — a nonce cannot cover a style ATTRIBUTE. The tag helper now
   writes data-aspect-ratio="16 / 10" and the ratio comes from here, one rule
   per value the views actually ask for, so the directive could be tightened
   to 'self' with no exception (SecurityHeadersMiddleware).

   Adding a new aspect-ratio="…" at a call site therefore means adding a rule
   here with the SAME text, spaces included — the selector matches the
   attribute value exactly. CspInlineStyleTests fails when one is missing,
   because the symptom otherwise is silent: the frame collapses to no height,
   its picture with it, and the page's layout shifts when the picture arrives,
   which is the opposite of what reserving the space was for. */
[data-aspect-ratio="21 / 10"] {
  aspect-ratio: 21 / 10;
}

[data-aspect-ratio="16 / 10"] {
  aspect-ratio: 16 / 10;
}

[data-aspect-ratio="4 / 3"] {
  aspect-ratio: 4 / 3;
}

[data-aspect-ratio="4 / 5"] {
  aspect-ratio: 4 / 5;
}

[data-aspect-ratio="1 / 1"] {
  aspect-ratio: 1 / 1;
}

/* ----- Home page: shared section scaffolding ------------------------------ */

/* Common eyebrow/heading pair reused above most sections (Offerings,
   Teachers, Posts, Process). Kept as a class rather than element selectors
   because Concept and FAQ combine their intro markup differently. */
.section-eyebrow {
  color: var(--accent);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.section-intro {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 40px;
}

.section-intro h2 {
  margin: 0;
  font-size: clamp(28px, 4.5vw, 36px);
}

/* ----- Notice banner ------------------------------------------------------ */

.notice-banner {
  background: var(--accent);
  color: #fff;
  text-align: center;
  padding: 10px 20px;
  font-size: 14px;
  font-weight: 500;
}

.notice-banner__link {
  color: #fff;
  text-decoration: underline;
  font-weight: 700;
  margin-left: 6px;
}

.notice-banner__link:hover {
  color: #fff;
}

/* ----- Hero ---------------------------------------------------------------- */

.hero {
  background: var(--dark);
  color: var(--on-dark);
  overflow: hidden;
}

.hero__inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: clamp(48px, 8vw, 88px) 24px clamp(56px, 9vw, 96px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
}

.hero__content {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.hero__badge {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  border: 1px solid rgba(245, 243, 239, 0.25);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 13px;
  color: var(--accent-bright);
}

.hero__title {
  margin: 0;
  font-size: clamp(34px, 5.5vw, 56px);
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

.hero__subtitle {
  margin: 0;
  font-size: 18px;
  color: var(--on-dark-muted);
  max-width: 480px;
  text-wrap: pretty;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 8px;
}

.hero__cta {
  background: var(--accent);
  color: #fff;
  padding: 14px 28px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 16px;
}

.hero__cta:hover {
  background: var(--accent-bright);
  color: var(--dark);
}

.hero__secondary {
  border: 1px solid rgba(245, 243, 239, 0.3);
  color: var(--on-dark);
  padding: 14px 28px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 16px;
}

.hero__secondary:hover {
  border-color: var(--accent-bright);
  color: var(--accent-bright);
}

.hero__media {
  width: 100%;
  display: flex;
  justify-content: center;
}

/* The slogan logo sits on a light disc: the dark blue of its lettering ring
   would vanish on --dark. The file is square and centred on the ring. */
.hero__logo-disc {
  width: min(100%, 460px);
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 14px rgba(245, 243, 239, 0.06);
}

/* The <picture> only picks the file (see HeroSection.razor); it must not
   become the box the logo's 82% is measured against. */
.hero__logo-disc > picture {
  display: contents;
}

.hero__logo {
  display: block;
  width: 82%;
  height: auto;
}

/* Below this width the hero stacks into one column and the disc would push
   the buttons a full screen down; the nav already carries the logo mark. */
@media (max-width: 899px) {
  .hero__media {
    display: none;
  }
}

/* ----- Offerings ------------------------------------------------------------ */

.offerings {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: clamp(56px, 9vw, 96px) 24px 48px;
}

.offerings__group-heading {
  margin: 0 0 16px;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink-muted);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.offerings__grid {
  display: grid;
  gap: 16px;
  margin-bottom: 40px;
}

.offerings__grid--early {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}

.offerings__grid--instruments {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  margin-bottom: 0;
}

.offering-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.offering-card:hover {
  border-color: var(--accent);
}

.offering-card__name {
  font-weight: 700;
  font-size: 17px;
}

.offering-card__desc {
  font-size: 14px;
  color: var(--ink-muted);
}

/* An instrument tile's photo (or, until real photos exist, its neutral
   media-placeholder) sits full-bleed behind the text and stays invisible
   until hovered/focused -- the CSS-only replacement for the design's
   onMouseEnter/onMouseLeave handlers (verbatim requirement). */
.offering-tile {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 24px;
  min-height: 96px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 8px;
  transition: border-color 0.25s, transform 0.25s;
}

.offering-tile:hover,
.offering-tile:focus-within {
  border-color: var(--accent);
  transform: translateY(-3px);
}

.offering-tile__media {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.4s ease, transform 4s ease;
}

/* THE ONE SLOT WHOSE SHAPE IS NOT A RATIO, and the only place allowed to
   replace .media-frame's box. The design's instrument tile has no ratio box
   at all: the photograph is a full-bleed background of the tile itself
   (background-size: cover on the tile), whose height comes from its text. So
   Site/OfferingsSection.razor declares no aspect-ratio, the frame carries no
   data-aspect-ratio, and the container supplies the box here instead. The
   cropping is unchanged from the general rule -- .media-image already fills
   whatever frame it is in, which is why this block no longer repeats it. */
.offering-tile__media .media-frame {
  position: absolute;
  inset: 0;
}

/* Full bleed: the tile's own border and radius are already drawn around it. */
.offering-tile__media .media-placeholder {
  border: none;
  border-radius: 0;
}

.offering-tile__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(20, 32, 30, 0.1) 20%, rgba(20, 32, 30, 0.82));
  opacity: 0;
  transition: opacity 0.4s ease;
}

.offering-tile__name,
.offering-tile__desc {
  position: relative;
  transition: color 0.3s;
}

.offering-tile__name {
  font-weight: 700;
  font-size: 17px;
}

.offering-tile__desc {
  font-size: 14px;
  color: var(--ink-muted);
}

.offering-tile:hover .offering-tile__media,
.offering-tile:hover .offering-tile__scrim,
.offering-tile:focus-within .offering-tile__media,
.offering-tile:focus-within .offering-tile__scrim {
  opacity: 1;
}

.offering-tile:hover .offering-tile__name,
.offering-tile:hover .offering-tile__desc,
.offering-tile:focus-within .offering-tile__name,
.offering-tile:focus-within .offering-tile__desc {
  color: #fff;
}

/* Touch fallback (verbatim requirement): there is no hover on a phone, so
   the photo and its scrim stay permanently visible instead of permanently
   hidden. */
@media (hover: none) {
  .offering-tile__media,
  .offering-tile__scrim {
    opacity: 1;
  }

  .offering-tile__name,
  .offering-tile__desc {
    color: #fff;
  }
}

/* ----- Concept -------------------------------------------------------------- */

.concept {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 48px 24px clamp(56px, 9vw, 96px);
}

.concept__panel {
  background: var(--bg-soft);
  border-radius: 28px;
  padding: clamp(28px, 5vw, 64px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: clamp(28px, 5vw, 56px);
  align-items: start;
}

.concept__intro {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.concept__intro h2 {
  margin: 0;
  font-size: clamp(26px, 4vw, 32px);
  text-wrap: balance;
}

.concept__text {
  margin: 0;
  color: var(--ink-soft);
  font-size: 16px;
  text-wrap: pretty;
}

.concept__services {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.concept__services-heading {
  margin: 0;
  font-weight: 700;
  font-size: 15px;
}

.service-item {
  display: flex;
  gap: 12px;
  align-items: center;
  background: var(--surface);
  border-radius: 14px;
  padding: 16px 20px;
}

.service-item__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
}

/* ----- Teachers -------------------------------------------------------------- */

.teachers {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 24px clamp(56px, 9vw, 96px);
}

.teachers__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
  gap: 20px;
}

.teacher-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 20px;
  overflow: hidden;
}

.teacher-card__body {
  padding: 20px 24px 24px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.teacher-card__name {
  font-weight: 700;
  font-size: 17px;
}

.teacher-card__subject {
  font-size: 14px;
  color: var(--accent);
  font-weight: 600;
}

/* ----- Music clubs ----------------------------------------------------------- */

.clubs {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 24px clamp(56px, 9vw, 96px);
}

.clubs__lead {
  margin: 0;
  color: var(--ink-soft);
}

.clubs__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 20px;
}

.club-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 20px 24px 24px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.club-card__name {
  font-weight: 700;
  font-size: 17px;
}

.club-card__place {
  font-size: 14px;
  color: var(--ink-muted);
}

.club-card__subject {
  font-size: 14px;
  color: var(--accent);
  font-weight: 600;
}

/* ----- Featured event -------------------------------------------------------- */

.event-banner {
  max-width: var(--max-width);
  margin: 0 auto clamp(40px, 6vw, 64px);
  padding: 0 24px;
}

.event-banner__inner {
  background: var(--accent);
  color: #fff;
  border-radius: 24px;
  padding: clamp(28px, 5vw, 48px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: clamp(24px, 4vw, 48px);
  align-items: center;
}

.event-banner__content {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.event-banner__badge {
  align-self: flex-start;
  background: rgba(255, 255, 255, 0.15);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 700;
}

.event-banner__title {
  margin: 0;
  font-size: clamp(26px, 4vw, 34px);
  text-wrap: balance;
}

/* Task 9's contrast audit computed --accent-bright on the accent banner
   background at 2.93:1 -- below AA even at the large-text threshold
   (--accent-bright reads correctly everywhere else it is used, always
   against --dark or --dark-soft; only this teal-on-teal pairing failed).
   Plain white matches the badge and CTA text already on this same
   banner and clears 5.47:1. */
.event-banner__meta {
  font-size: 16px;
  font-weight: 600;
  color: #fff;
}

.event-banner__text {
  margin: 0;
  font-size: 15px;
  color: #d8f0ec;
  text-wrap: pretty;
}

.event-banner__cta {
  align-self: flex-start;
  background: #fff;
  color: var(--accent);
  padding: 13px 26px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 15px;
  margin-top: 6px;
}

.event-banner__cta:hover {
  background: var(--dark);
  color: #fff;
}

.event-banner__media .media-placeholder {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.25);
}

/* ----- Posts (Aktuelles) ------------------------------------------------------ */

.posts {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 24px clamp(56px, 9vw, 96px);
}

.posts__header {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}

.posts__header .section-intro {
  margin-bottom: 0;
}

.posts__all-link {
  font-weight: 700;
  font-size: 15px;
  border-bottom: 2px solid var(--line);
  padding-bottom: 2px;
  margin-bottom: 40px;
}

.posts__all-link:hover {
  border-color: var(--accent);
}

.posts__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
  gap: 20px;
}

.post-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 20px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.post-card__body {
  padding: 20px 24px 24px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
}

.post-card__date {
  font-size: 13px;
  color: var(--ink-muted);
  font-weight: 600;
}

.post-card__title {
  font-weight: 700;
  font-size: 17px;
}

.post-card__teaser {
  font-size: 14px;
  color: var(--ink-muted);
}

.post-card__link {
  align-self: flex-start;
  margin-top: auto;
  padding-top: 10px;
  font-weight: 700;
  font-size: 14px;
}

.post-card__link:hover {
  color: var(--accent-dark);
}

/* ----- Process (Ablauf) -------------------------------------------------------- */

.process {
  background: var(--bg-soft);
}

.process__inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: clamp(56px, 9vw, 88px) 24px;
}

.process__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
  gap: 20px;
}

.process-step {
  background: var(--surface);
  border-radius: 20px;
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.process-step__number {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 17px;
}

.process-step__title {
  font-weight: 700;
  font-size: 18px;
}

.process-step__desc {
  font-size: 15px;
  color: var(--ink-muted);
}

/* ----- FAQ -------------------------------------------------------------------- */

.faq {
  max-width: 760px;
  margin: 0 auto;
  padding: clamp(56px, 9vw, 88px) 24px;
}

.faq__heading {
  margin: 0 0 32px;
  font-size: clamp(28px, 4.5vw, 36px);
  text-align: center;
}

.faq__list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.faq-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  overflow: hidden;
}

/* Native <details>/<summary> (verbatim requirement): no JavaScript, and
   keyboard-operable without any of it. The browser's default marker is
   replaced with a "+"/"−" indicator driven purely by the [open] attribute. */
.faq-item__summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 20px 24px;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}

.faq-item__summary::-webkit-details-marker {
  display: none;
}

.faq-item__summary::marker {
  content: '';
}

.faq-item__summary::after {
  content: '+';
  color: var(--accent);
  font-size: 20px;
  flex-shrink: 0;
}

.faq-item[open] .faq-item__summary::after {
  content: '\2212';
}

.faq-item__answer {
  margin: 0;
  padding: 0 24px 20px;
  font-size: 15px;
  color: var(--ink-soft);
}

/* ----- Contact ------------------------------------------------------------------ */

.contact {
  background: var(--dark);
  color: var(--on-dark);
}

.contact__inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: clamp(56px, 9vw, 88px) 24px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
}

.contact__content {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.contact__content h2 {
  margin: 0;
  font-size: clamp(30px, 4.5vw, 40px);
  text-wrap: balance;
}

.contact__text {
  margin: 0;
  color: var(--on-dark-muted);
  font-size: 17px;
}

.contact__details {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
  font-size: 15px;
  color: var(--on-dark-muted);
}

.contact__org {
  color: var(--on-dark);
  font-weight: 700;
}

.contact__details a {
  color: var(--accent-bright);
}

.contact__form-slot {
  background: var(--dark-soft);
  border: 1px solid rgba(245, 243, 239, 0.15);
  border-radius: 20px;
  padding: clamp(24px, 4vw, 40px);
  min-height: 200px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  align-items: center;
  justify-content: center;
  text-align: center;
}

/* Until plan 4 this slot held a placeholder sentence saying the form was
   still to come. The form exists now and has a page of its own, so what
   stands here is the way to it -- see _Contact.cshtml and ProbestundeModel. */
.contact__cta-text {
  margin: 0;
  color: var(--on-dark-muted);
  font-size: 15px;
}

/* The three steps standing where the design put the form. Left-aligned
   inside a centred slot on purpose: numbered steps are read down an edge,
   and centring them would cost the alignment that makes them scannable. */
.contact__steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 18px;
  text-align: left;
  width: 100%;
  max-width: 340px;
}

.contact__step {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}

.contact__step-number {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  border: 1px solid rgba(245, 243, 239, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  color: var(--accent-bright);
}

.contact__step-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.contact__step-title {
  color: var(--on-dark);
  font-weight: 700;
  font-size: 15px;
}

.contact__step-text {
  color: var(--on-dark-muted);
  font-size: 14px;
  line-height: 1.45;
}

.contact__cta {
  background: var(--accent);
  color: #fff;
  padding: 14px 28px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 16px;
}

.contact__cta:hover {
  background: var(--accent-bright);
  color: var(--dark);
}

/* ----- Trial-lesson enquiry (/probestunde) --------------------------------------- */

.inquiry-page__inner {
  max-width: 640px;
  margin: 0 auto;
  padding: clamp(48px, 8vw, 80px) 24px clamp(56px, 9vw, 88px);
  display: flex;
  flex-direction: column;
  gap: clamp(24px, 4vw, 32px);
}

.inquiry-page__intro {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.inquiry-page__intro h1 {
  margin: 0;
  font-size: clamp(32px, 5vw, 44px);
  text-wrap: balance;
}

.inquiry-page__text {
  margin: 0;
  color: var(--ink-soft);
  font-size: 17px;
  text-wrap: pretty;
}

.inquiry-form {
  background: var(--dark-soft);
  border-radius: 24px;
  padding: clamp(24px, 4vw, 40px);
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.inquiry-form__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.inquiry-form__row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: 16px;
}

.inquiry-form__label {
  color: var(--on-dark);
  font-size: 15px;
  font-weight: 600;
}

/* Hints live here and never inside the <label>: text inside a label becomes
   part of the control's accessible name, so a screen reader would read the
   whole sentence out again every time the field is reached. The control
   points at this paragraph with aria-describedby instead. */
.inquiry-form__hint {
  margin: 0;
  color: var(--on-dark-faint);
  font-size: 13px;
}

.inquiry-form__control {
  background: var(--dark);
  color: var(--on-dark);
  border: 1px solid #334844;
  border-radius: 12px;
  padding: 13px 16px;
  width: 100%;
}

.inquiry-form__control--message {
  resize: vertical;
  min-height: 92px;
}

/* The colour is declared on the box that also declares the background it
   renders on, and the two children inherit it. That is not tidiness:
   CssColorPairDerivation pairs a rule's colour with a background it can
   resolve, and a colour declared on a child would be resolved against the
   BEM block's background (--dark-soft) rather than against this box's own
   (--dark) -- both pass here, but only by luck, and the engine would have
   been checking the wrong pairing. */
.inquiry-form__errors {
  background: var(--dark);
  color: var(--warn-on-dark);
  border: 1px solid var(--warn-on-dark);
  border-radius: 12px;
  padding: 14px 18px;
  font-size: 15px;
}

.inquiry-form__errors-note {
  margin: 0;
}

.inquiry-form__errors-heading {
  margin: 0 0 6px;
  font-weight: 700;
}

.inquiry-form__errors-list {
  margin: 0;
  padding-left: 20px;
}

.inquiry-form__submit {
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 15px;
  font-weight: 700;
  margin-top: 4px;
}

.inquiry-form__submit:hover {
  background: var(--accent-bright);
  color: var(--dark);
}

.inquiry-form__note {
  margin: 0;
  color: var(--on-dark-faint);
  font-size: 13px;
}

.inquiry-form__note a {
  color: var(--accent-bright);
}

/* The honeypot wrapper (spec section 7). DELIBERATELY NOT display:none, and
   not visibility:hidden either. On several screen-reader/browser
   combinations a display:none field is still announced and offered, its user
   fills it in because nothing told them not to, and the submission is then
   refused as a bot -- which is precisely the group the decision against a
   captcha was taken to protect. Moved off-screen instead: it is out of the
   visual flow, while tabindex="-1" keeps it out of the tab order and
   aria-hidden="true" keeps it out of the accessibility tree, so nobody using
   the page any way at all is ever offered it.

   The 1px box with overflow:hidden rather than width:0 keeps some browsers
   from treating the field as having no layout, which is one of the
   heuristics an autofilling bot uses to spot exactly this trap. */
.form-honeypot {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.inquiry-confirmation {
  background: var(--dark-soft);
  border-radius: 24px;
  padding: clamp(32px, 5vw, 48px) clamp(24px, 4vw, 40px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
}

.inquiry-confirmation__mark {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
}

.inquiry-confirmation__title {
  margin: 0;
  color: var(--on-dark);
  font-size: clamp(26px, 4vw, 34px);
}

.inquiry-confirmation__text {
  margin: 0;
  color: var(--on-dark-muted);
  font-size: 16px;
  max-width: 34ch;
  text-wrap: pretty;
}

.inquiry-confirmation__again {
  border: 1px solid rgba(245, 243, 239, 0.3);
  color: var(--on-dark);
  padding: 12px 24px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 15px;
  margin-top: 6px;
}

.inquiry-confirmation__again:hover {
  border-color: var(--accent-bright);
  color: var(--accent-bright);
}

/* ----- Pricing (Preise) ---------------------------------------------------------- */

.pricing-header {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: clamp(48px, 8vw, 80px) 24px clamp(32px, 5vw, 48px);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.pricing-header h1 {
  margin: 0;
  font-size: clamp(32px, 5vw, 48px);
  font-weight: 800;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

.pricing-header p {
  margin: 0;
  font-size: 17px;
  color: var(--ink-muted);
  max-width: 560px;
  text-wrap: pretty;
}

.price-section {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 24px 24px clamp(48px, 7vw, 72px);
}

.price-section h2,
.group-section h2 {
  margin: 0 0 20px;
  font-size: clamp(24px, 3.5vw, 30px);
  font-weight: 800;
  letter-spacing: -0.02em;
}

.group-section {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 24px clamp(48px, 7vw, 72px);
}

.price-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
  gap: 16px;
}

.price-grid--group {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}

.price-card {
  border-radius: 20px;
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
}

.price-card--individual {
  background: var(--surface);
  border: 1px solid var(--line);
}

.price-card--group {
  background: var(--bg-soft);
}

/* Einzelunterricht: one card per instrument (Site/PriceCardsSection.razor). Wider
   minimum than the old lesson-length cards, because each card now holds a
   label AND an amount side by side; min(100%, ...) is what keeps a phone
   at one column with no horizontal scroll. */
.price-grid--instruments {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
}

.price-instrument {
  padding: clamp(20px, 4vw, 28px);
}

.price-instrument__name {
  margin: 0;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.price-list {
  margin: 0;
}

/* One dt/dd group per row: label (column 1) and amount (column 2) on the
   first line, the note under the label. minmax(0, 1fr) rather than 1fr, so
   a long label wraps instead of pushing the amount out of the card. */
.price-list__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 16px;
  row-gap: 2px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}

.price-list__row:first-child {
  border-top: 0;
  padding-top: 4px;
}

.price-list__label {
  grid-column: 1;
  font-weight: 700;
  overflow-wrap: anywhere;
}

.price-list__amount {
  grid-column: 2;
  grid-row: 1 / span 2;
  margin: 0;
  text-align: right;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* Under the amount rather than beside it: "/ Monat" and "einmalig" differ
   in length, and stacking keeps the amounts of one card aligned on the
   right edge whichever unit a row has. */
.price-list__unit {
  display: block;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--ink-muted);
}

.price-list__note {
  grid-column: 1;
  margin: 0;
  font-size: 14px;
  color: var(--ink-muted);
}

/* The "Beliebt" badge is the accessible marker -- real text inside the
   <dt>, see Site/PriceCardsSection.razor. The accent colour on the highlighted row's
   amount is a visual reinforcement only, never the sole signal. */
.price-list__badge {
  display: inline-block;
  margin-left: 8px;
  vertical-align: 2px;
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.4;
  padding: 2px 10px;
  border-radius: 999px;
}

.price-list__row--highlighted .price-list__amount {
  color: var(--accent);
}

.price-card__duration {
  font-weight: 700;
  font-size: 17px;
}

.price-card__amount {
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.02em;
}

.price-card__unit {
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-muted);
}

.price-card__note {
  font-size: 14px;
  color: var(--ink-muted);
}

.price-footnote {
  margin: 16px 0 0;
  font-size: 13px;
  color: var(--ink-muted);
}

.info-panel-section {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 24px clamp(56px, 8vw, 88px);
}

.info-panel {
  background: var(--dark);
  color: var(--on-dark);
  border-radius: 28px;
  padding: clamp(28px, 5vw, 56px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: clamp(28px, 5vw, 48px);
}

.info-panel__intro {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.info-panel__intro h2 {
  margin: 0;
  font-size: clamp(24px, 3.5vw, 30px);
  font-weight: 800;
  letter-spacing: -0.02em;
}

.info-panel__intro p {
  margin: 0;
  color: var(--on-dark-muted);
  font-size: 15px;
  text-wrap: pretty;
}

.info-panel__cta {
  align-self: flex-start;
  background: var(--accent);
  color: #fff;
  padding: 13px 26px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 15px;
  margin-top: 8px;
}

.info-panel__cta:hover {
  background: var(--accent-bright);
  color: var(--dark);
}

.info-panel__list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.info-item {
  display: flex;
  gap: 12px;
  align-items: baseline;
  background: var(--dark-soft);
  border-radius: 14px;
  padding: 14px 18px;
}

.info-item__icon {
  color: var(--accent-bright);
  font-weight: 700;
  flex-shrink: 0;
}

.info-item__text {
  font-size: 14px;
  color: var(--on-dark);
}

/* ----- Aktuelles (list & article pages) ------------------------------------ */

.news-header {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: clamp(48px, 8vw, 80px) 24px clamp(24px, 4vw, 40px);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.news-header h1 {
  margin: 0;
  font-size: clamp(32px, 5vw, 48px);
  font-weight: 800;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

.post-filter {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}

/* The year filter's chips. Vertical padding raised from the design's 9px
   (_design/Aktuelles.dc.html) to 12px for the SAME reason the navigation
   call to action was raised, and deliberately at the same time: at 9px these
   stood 42.4px tall (9 + 9 + 14 x 1.6 + 2px border) and were, after the
   navigation button, the only other tappable pill in this stylesheet under
   the 44px minimum the file already keeps for every input and button. Fixing
   one pill and leaving the other under the bar would have made the rule
   written above true of exactly one selector.

   The HORIZONTAL padding is the design's own 20px, untouched: these are
   filter chips sitting in a row, not a call to action, and 1.43em already
   reads as roomy at this weight. Only the height was wrong. */
.post-filter__link {
  background: var(--surface);
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 12px 20px;
  font-size: 14px;
  font-weight: 700;
}

.post-filter__link:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.post-filter__link.is-active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

.post-filter__link.is-active:hover {
  background: var(--accent-dark);
}

.posts__empty {
  margin: 0;
  color: var(--ink-muted);
}

.post-article {
  max-width: 760px;
  margin: 0 auto;
  padding: clamp(32px, 6vw, 56px) 24px clamp(56px, 9vw, 88px);
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.post-article__back-link {
  align-self: flex-start;
  font-weight: 700;
  font-size: 14px;
}

.post-article__back-link:hover {
  color: var(--accent-dark);
}

.post-article__media {
  border-radius: 20px;
  overflow: hidden;
}

.post-article__header {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.post-article__header h1 {
  margin: 0;
  font-size: clamp(26px, 4vw, 36px);
  font-weight: 800;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.post-article__date {
  font-size: 14px;
  color: var(--ink-muted);
  font-weight: 600;
}

.post-article__body {
  display: flex;
  flex-direction: column;
  gap: 16px;
  font-size: 16px;
  color: var(--ink-soft);
}

.post-article__body p {
  margin: 0;
  text-wrap: pretty;
}

.post-article__gallery {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.post-article__gallery h2 {
  margin: 0;
  font-weight: 700;
  font-size: 15px;
}

.post-article__gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr));
  gap: 12px;
}

/* No aspect-ratio of its own any more: the 16 / 10 the design gives a gallery
   picture is declared once, at the call site in Beitrag.cshtml, and reaches
   the frame from there. This used to state the same ratio a second time and
   clip the overflow of an uncropped image, which top-anchored every gallery
   photograph instead of centring it. overflow: hidden stays, for the radius. */
.post-article__gallery-item {
  border-radius: 12px;
  overflow: hidden;
}

/* ----- Legal pages (Impressum, Datenschutz) ------------------------------- */

.legal-page {
  max-width: 760px;
  margin: 0 auto;
  padding: clamp(32px, 6vw, 56px) 24px clamp(56px, 9vw, 88px);
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.legal-page h1 {
  margin: 0;
  font-size: clamp(28px, 4.5vw, 38px);
  font-weight: 800;
  letter-spacing: -0.02em;
}

.legal-page__section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.legal-page__section h2 {
  margin: 0;
  font-size: 19px;
  font-weight: 700;
}

.legal-page__section p {
  margin: 0;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.legal-page__lines {
  display: flex;
  flex-direction: column;
  gap: 2px;
  color: var(--ink-soft);
}

.legal-page__stand {
  margin: 0;
  font-size: 13px;
  color: var(--ink-muted);
}

/* ----- Error page (404, 500) ---------------------------------------------- */

/* Same column, spacing scale and type ramp as the legal pages, centred:
   there is one short message here rather than a document to read, and a
   centred column is what the design uses everywhere it has one thing to
   say. Deliberately no new colour: every declaration below reuses a token
   that already appears against this background elsewhere in this file, so
   ContrastTests derives the same pairings it already checks. */

.error-page {
  max-width: 640px;
  margin: 0 auto;
  padding: clamp(56px, 10vw, 104px) 24px clamp(64px, 11vw, 120px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
}

.error-page__code {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.error-page__title {
  margin: 0;
  font-size: clamp(28px, 4.5vw, 38px);
  font-weight: 800;
  letter-spacing: -0.02em;
}

.error-page__text {
  margin: 0;
  max-width: 46ch;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.error-page__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-top: 10px;
}

.error-page__cta {
  background: var(--accent);
  color: #fff;
  padding: 14px 28px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 16px;
}

.error-page__cta:hover {
  background: var(--accent-dark);
  color: #fff;
}

/* ----- Motion ------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.001ms !important;
    animation-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
