/* Phone layout. Built from mobile-parts/ — do not edit directly. */

/* ===== base.css ===== */
/* base — phone foundations shared by all nine pages.
   The design ships desktop-only inline styles, so every override here needs
   !important to outrank them. Nothing outside a max-width query is touched:
   the approved desktop rendering must stay bit-identical. */

@media (max-width: 768px) {

  /* ---------------------------------------------------------------- gutters */

  /* 40px of side padding costs a fifth of a 390px screen. 20px is the widest
     gutter that still leaves a comfortable measure, and it matches the edge
     rhythm of native app UI. Only the horizontal sides are rewritten so the
     vertical spacing of each page stays with the page-level stylesheets. */
  [style*="padding: 0px 40px"],
  [style*="padding: 134px 40px 100px"],
  [style*="padding: 22px 40px"] {
    padding-left: 20px !important;
    padding-right: 20px !important;
  }

  /* Long unbreakable tokens (mail addresses, URLs) otherwise set the minimum
     width of their grid track and push the whole page sideways — this was the
     46px overflow on the imprint. */
  a[href^="mailto:"],
  a[href^="tel:"],
  [style*="ui-monospace"] {
    overflow-wrap: anywhere;
  }

  /* Grid and flex children default to a min-content floor, which lets one wide
     child widen the whole row past the viewport. Zero lets them shrink. */
  [style*="display: grid"] > *,
  [style*="display: flex"] > * {
    min-width: 0;
  }

  /* The label/value grid of the legal pages reserves up to 220px for the label,
     leaving 106px for the value on a 390px screen — narrower than a single
     German compound, which is where the imprint's 46px overflow came from. One
     column turns the label into a caption above its value. */
  [style*="grid-template-columns: minmax(160px, 220px) 1fr"] {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }

  /* ----------------------------------------------------------------- header */

  /* 74px is desktop proportion; 62px reads as a phone chrome bar and hands
     back 12px of content on every screen. max() keeps the content clear of the
     rounded corners and camera cut-out in landscape. */
  header[data-ref="nav"] > div {
    height: 62px !important;
    gap: 12px !important;
    padding-left: max(20px, env(safe-area-inset-left)) !important;
    padding-right: max(20px, env(safe-area-inset-right)) !important;
  }

  /* The wordmark is shrunk rather than hidden on purpose: site.js measures this
     span to fly the hero headline into the header, and a display:none span
     reports zero width, which silently kills that animation. Smaller type keeps
     both the brand and the effect. */
  [data-ref="navLogo"] {
    gap: 8px !important;
    min-height: 44px;
    min-width: 0;
  }
  [data-ref="navLogo"] span {
    font-size: 12.5px !important;
    letter-spacing: .1em !important;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Two 26px bars are a 26x25 target. The bars keep their position at the right
     gutter while the hit area grows around them to the 44px minimum. */
  #burger {
    min-width: 44px;
    min-height: 44px;
    align-items: flex-end !important;
    justify-content: center !important;
    padding: 0 !important;
  }

  /* ------------------------------------------------------------ menu overlay */

  /* The overlay is z-index 75 and the header 80/85, so the burger and wordmark
     stay painted on top of it. On the light pages they are near-black, which on
     the black overlay means an invisible close button. */
  body:has(#menu:not([hidden])) header[data-ref="nav"] {
    background: transparent !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  body:has(#menu:not([hidden])) [data-ref="navLogo"] {
    color: #fff !important;
    opacity: 1 !important;
  }
  body:has(#menu:not([hidden])) #burger span {
    background: #fff !important;
  }

  #menu {
    overscroll-behavior: contain;
  }

  /* "safe center" centres the panel while it fits and falls back to the top
     edge once it does not — plain centring would push the first link out of
     reach on a short screen. */
  #menu > div {
    justify-content: safe center !important;
    gap: 34px !important;
    padding: 78px max(20px, env(safe-area-inset-left)) calc(32px + env(safe-area-inset-bottom)) !important;
  }

  /* Full-bleed rows: the whole line width becomes the target, and the type gets
     the scale a phone menu deserves instead of the 30px clamp floor. */
  #menu nav {
    gap: 2px !important;
    align-self: stretch;
  }
  #menu nav a {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 52px;
    font-size: clamp(31px, 8.6vw, 44px) !important;
  }

  /* Contact pills: 11px padding gives a 38px row, four short of the minimum. */
  #menu a[href^="tel:"],
  #menu a[href^="mailto:"],
  #menu a[href*="wa.me"] {
    min-height: 44px;
    padding: 12px 20px !important;
    font-size: 14px !important;
  }
  #menu a[href="/impressum"],
  #menu a[href="/datenschutz"] {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* ----------------------------------------------------------- tap targets */

  /* WCAG 2.2 SC 2.5.8 sets 24px and Apple's HIG 44px; the 44px floor applies to
     standalone controls only. Links inside a sentence are explicitly exempt and
     stay untouched, because padding them would overlap neighbouring lines. */
  button,
  a[style*="display: flex"],
  a[style*="display: inline-flex"],
  a[style*="display: block"],
  a[style*="display: grid"],
  a[style*="display: inline-grid"] {
    min-height: 44px;
  }

  /* Footer navigation rows are standalone links written as bare <a>. */
  footer a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Contact links stacked in a column are standalone controls. Matching only
     direct children of a flex column deliberately spares the same href when it
     appears inside a running sentence. */
  [style*="flex-direction: column"] > a[href^="tel:"],
  [style*="flex-direction: column"] > a[href^="mailto:"] {
    display: flex;
    align-items: center;
    min-height: 44px;
  }

  /* ---------------------------------------------------------- typography */

  html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
  }

  /* Running copy, identified by the small size paired with a prose line-height
     — chips and labels use tight leading and are left alone. */
  [style*="font-size: 13px;"][style*="line-height: 1.75;"],
  [style*="font-size: 13.5px;"][style*="line-height: 1.8;"],
  [style*="font-size: 13.5px;"][style*="line-height: 1.75;"],
  [style*="font-size: 13.5px;"][style*="line-height: 1.7;"],
  [style*="font-size: 14px;"][style*="line-height: 1.85;"],
  [style*="font-size: 14px;"][style*="line-height: 1.8;"],
  [style*="font-size: 14px;"][style*="line-height: 1.75;"],
  [style*="font-size: 14px;"][style*="line-height: 1.6;"],
  [style*="font-size: 14.5px;"][style*="line-height: 1.85;"],
  [style*="font-size: 14.5px;"][style*="line-height: 1.8;"],
  [style*="font-size: 14.5px;"][style*="line-height: 1.65;"],
  [style*="font-size: 15px;"][style*="line-height: 1.8;"],
  [style*="font-size: 15px;"][style*="line-height: 1.85;"] {
    font-size: 16px !important;
  }

  /* Secondary copy keeps its step below the body text but clears the point
     where German prose stops being comfortable on a phone. */
  [style*="font-size: 11px;"][style*="line-height: 1.6;"],
  [style*="font-size: 11.5px;"][style*="line-height: 1.7;"],
  [style*="font-size: 12.5px;"][style*="line-height: 1.7;"],
  [style*="font-size: 12.5px;"][style*="line-height: 1.65;"] {
    font-size: 14px !important;
  }

  /* Hard floor for every micro-label. The design goes down to 9px, which is
     below the point where widely-spaced uppercase stays legible on a phone.
     Raised from 11px to 12.5px on 01.08.2026, and 11/11.5px pulled in with it.
     Reason, measured the same day: the home page carried over forty elements
     between 11 and 12.5px, while the reference site Sammy-Jo works against runs
     16px for its running text and barely uses anything smaller. A page built
     from six shades of small print reads as fine print, whatever the content
     says. The wordmark keeps its own floor further down — it is the one label
     whose width is load-bearing. */
  [style*="font-size: 9px;"],
  [style*="font-size: 9.5px;"],
  [style*="font-size: 10px;"],
  [style*="font-size: 10.5px;"],
  [style*="font-size: 11px;"],
  [style*="font-size: 11.5px;"],
  [style*="font-size: 12px;"] {
    font-size: 12.5px !important;
  }

  /* Mono labels follow the same floor. This block is narrower than the general
     rule above and therefore wins, so it has to carry the same number — while
     it said 11px it quietly undid the raise for every monospace label on the
     site. Letter-spacing stays trimmed so the label keeps its width and cannot
     break the chip it sits in. */
  [style*="ui-monospace"][style*="font-size: 9px;"],
  [style*="ui-monospace"][style*="font-size: 9.5px;"],
  [style*="ui-monospace"][style*="font-size: 10px;"],
  [style*="ui-monospace"][style*="font-size: 10.5px;"] {
    font-size: 12.5px !important;
    letter-spacing: .11em !important;
  }

  /* Under 16px iOS Safari zooms the page when a field takes focus and never
     zooms back out. */
  input,
  textarea,
  select {
    font-size: 16px !important;
  }

  /* Display headings stay large; break-word only fires when a single German
     compound genuinely cannot fit, so no hyphens appear in normal lines. */
  h1, h2, h3, h4 {
    overflow-wrap: break-word;
  }
  /* Prefix first: Safari, the actual target browser here, still needs it. */
  p {
    -webkit-hyphens: auto;
    hyphens: auto;
  }

  /* ------------------------------------------------------------------ dock */

  /* The chat dock exists on the home page only and home.css positions it there,
     including its expanded panel, which is sized to an exact margin. A second
     set of offsets here would fight those numbers, so base leaves it alone.
     The scroll progress rail needs nothing either: it is a 2px bar at top 0 on
     z-index 99, above the header and clear of all content. */
}

/* Small phones (430px and below): the gutter tightens again so the content
   column keeps its width instead of the padding eating into it. */
@media (max-width: 430px) {

  [style*="padding: 0px 40px"],
  [style*="padding: 134px 40px 100px"],
  [style*="padding: 22px 40px"] {
    padding-left: 16px !important;
    padding-right: 16px !important;
  }

  header[data-ref="nav"] > div {
    padding-left: max(16px, env(safe-area-inset-left)) !important;
    padding-right: max(16px, env(safe-area-inset-right)) !important;
  }

  /* Holds the 11px label floor; the width comes back out of the tracking
     instead, which keeps the wordmark clear of the menu button at 360px. */
  [data-ref="navLogo"] span {
    letter-spacing: .075em !important;
  }

  #menu > div {
    padding-left: max(16px, env(safe-area-inset-left)) !important;
    padding-right: max(16px, env(safe-area-inset-right)) !important;
  }
}


/* ===== home.css ===== */
/* home — phone layout for index.html (hero, leistungen, datenlage, projekte,
   ablauf, festpreis, über, kontakt, chat dock).

   The design ships every value as an inline style attribute, so most rules
   below need !important to win. Only vertical padding is touched on the
   <section> elements — the side gutter lives on the inner container and
   belongs to the global layout, not here.

   Everything is scoped to a section id so the project and misc pages, which
   reuse the same data-* attributes, stay untouched. */

@media (max-width: 768px) {

  /* ============================================= 0 · anchor jumps ======== */

  /* The header is fixed and 74px tall, so a jump from the menu to #leistungen
     or #kontakt would park the section label underneath it. */
  #leistungen,
  #datenlage,
  #projekte,
  #ablauf,
  #festpreis,
  #ueber,
  #kontakt { scroll-margin-top: 88px; }

  /* ==================================================== 1 · hero ========= */

  /* svh instead of vh: the mobile address bar shrinks the visual viewport, and
     100vh would push the buttons below the fold on first paint. */
  #hero,
  #hero > div:last-child { min-height: 100svh !important; }

  #hero > div:last-child {
    gap: 26px !important;
    padding-top: 104px !important;   /* clears the fixed header */
    padding-bottom: 40px !important;
  }

  /* The wordmark is the whole point of the hero, so it stays as large as the
     line "SOLUTIONS" allows. Tighter tracking and line-height turn the three
     words into one solid block instead of three thin lines. */
  #hero h1 span {
    font-size: clamp(44px, calc(17.2vw - 12px), 96px) !important;
    letter-spacing: -.055em !important;
    line-height: .88 !important;
  }

  #hero [data-ref="hero"] {
    grid-template-columns: 1fr !important;
    gap: 22px !important;
    align-items: stretch !important;
  }

  #hero [data-ref="hero"] > p {
    font-size: 17px !important;
    line-height: 1.55 !important;
    max-width: 30ch !important;
  }

  /* Side by side the two buttons are 267px and 198px wide on a 310px column —
     they never fit. Stacked full width they read as a proper app call to
     action and clear the 44px tap minimum by a wide margin. */
  #hero [data-ref="hero"] > div:last-child {
    display: grid !important;
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }

  #hero [data-ref="hero"] a {
    justify-content: space-between !important;
    min-height: 58px;
    padding: 16px 16px 16px 22px !important;
    font-size: 14px !important;
  }

  #hero [data-ref="hero"] a:last-child {
    justify-content: center !important;
    padding: 16px 22px !important;
  }

  /* ============================================== 2 · leistungen ========= */

  #leistungen { padding: 58px 0 62px !important; }

  #leistungen > div > div:nth-child(1) {
    grid-template-columns: 1fr !important;
    gap: 20px !important;
    margin-bottom: 28px !important;
  }

  /* Die beiden Bereiche stehen auf dem Handy untereinander. Bis zum 02.08.2026
     stand hier eine Tippliste mit drei Knöpfen und ein Panel, das sich unter
     den angetippten Knopf schob — mit zwei Bereichen trägt jeder seine eigene
     Karte, es gibt nichts mehr aufzuklappen. */
  #leistungen > div > div:nth-child(2) {
    grid-template-columns: 1fr !important;
    gap: 16px !important;
  }

  #leistungen > div > div:nth-child(2) > div {
    height: auto !important;
    border-radius: 14px !important;
  }

  /* Der Bildbereich behält das Seitenverhältnis der Aufnahmen, das der Desktop
     setzt — dieselbe Regel wie bei den Projektkarten der Übersicht. */
  #leistungen > div > div:nth-child(2) > div > div:first-child {
    height: auto !important;
  }

  #leistungen > div > div:nth-child(2) > div > div:last-child {
    padding: 22px 20px 24px !important;
    gap: 14px !important;
  }

  /* Der Bereichsname trägt auf dem Desktop 17 bis 21px. Auf dem Handy bleibt er
     bei 19px stehen, damit er sich von der Fließschrift darunter absetzt. */
  #leistungen > div > div:nth-child(2) > div > div:last-child > span:first-child {
    font-size: 19px !important;
    line-height: 1.2 !important;
  }

  /* 16px statt 14,5px: Sammy-Jos Vergleichsseite (Seibert Group) führt ihre
     Fließschrift auf einem 390px-Schirm bei 16px, gemessen am 01.08.2026. */
  #leistungen > div > div:nth-child(2) > div > div:last-child > p {
    min-height: 0 !important;
    font-size: 16px !important;
    line-height: 1.7 !important;
  }

  #leistungen > div > div:nth-child(2) > div > div:last-child > div:nth-child(3) {
    min-height: 0 !important;
    gap: 7px !important;
  }

  #leistungen > div > div:nth-child(2) > div > div:last-child a {
    width: 100% !important;
    min-height: 54px;
    padding: 16px 14px 16px 18px !important;
  }

  /* =============================================== 3 · datenlage ========= */

  #datenlage { padding: 58px 0 62px !important; }

  #datenlage > div {
    grid-template-columns: 1fr !important;
    gap: 30px !important;
  }

  /* Pinned, the intro block would occupy most of the screen while the four
     points scroll past behind it. */
  #datenlage > div > div:nth-child(1) {
    position: static !important;
    gap: 18px !important;
  }

  #datenlage [data-dl] {
    /* padding-left is pinned because site.js shifts it by 12px on mouseenter,
       which a touch tap also fires — the row would stay shifted. */
    padding: 26px 2px 26px 2px !important;
  }

  #datenlage [data-dl] h3 { font-size: 20px !important; line-height: 1.15 !important; }
  #datenlage [data-dl] p  { font-size: 16px !important; line-height: 1.6 !important; }

  /* ================================================ 4 · projekte ========= */

  #projekte { padding: 58px 0 0 !important; }

  #projekte > div > div:nth-child(1) {
    grid-template-columns: 1fr !important;
    gap: 18px !important;
    margin-bottom: 26px !important;
  }

  /* The stack is kept rather than unrolled: with the card down to ~560px it
     fits under the sticky offset, so each project is fully readable before the
     next one slides over it. That layered depth is the effect site.js scales,
     and it is what makes the section feel like an app rather than a list. */
  #projekte [data-stack] {
    grid-template-columns: 1fr !important;
    gap: 18px !important;
    padding: 20px !important;
    border-radius: 16px !important;
  }

  /* All three cards pin at the same height, exactly as on the desktop.
     A staggered offset was tried first, so the edge of the card underneath
     stayed visible — measured 78/88/98px. Sammy-Jo read the result as untidy,
     and he is right: the desktop gets its depth from the scale step alone,
     and a second, competing offset makes the stack look misaligned rather
     than layered. One height for all three. */
  #projekte [data-stack] { top: 78px !important; }

  #projekte [data-stack] > div:nth-child(1) { gap: 12px !important; }
  #projekte [data-stack] h3 { font-size: 25px !important; line-height: 1.02 !important; }
  #projekte [data-stack] p  { font-size: 16px !important; line-height: 1.55 !important; }
  #projekte [data-stack] > div:nth-child(2) { aspect-ratio: 16 / 10 !important; }

  /* --- the stack has to come apart in one piece ---------------------------
     Sammy-Jo, 30.07.2026: the cards pin cleanly, "aber wenn man weiter scrollt
     dann sind die wieder so komisch auseinander".

     Measured at 390px: the stack holds until scroll 4965, all three at y=78.
     From 5065 they separate into a staircase 23 and 26px apart and drift off
     screen out of step. The cause is height, not the pinning: a sticky element
     unpins once its own bottom edge reaches the bottom of its container, so a
     taller card unpins earlier — by exactly its extra height. Card one measured
     499px, the other two 476px, and 499-476 is the 23px staircase.

     The extra 23px is one line of heading: "Fenster- und Türenkonfigurator"
     wraps onto two lines, "Shooting-Planer" and "Coachmemory" do not. On the
     desktop this never shows, because there text and image sit side by side and
     the image sets the height for every card. Stacked on a phone the two add up,
     so the heading difference goes straight into the card.

     So every heading gets two lines of room whether it needs them or not. Equal
     cards, one unpin point, and a stack of equal cards is what the desktop shows
     anyway. The px value is the fallback for browsers without the lh unit (one
     line height); lh has shipped everywhere since 2023, Safari 16.4. */
  #projekte [data-stack] h3 {
    min-height: 51px;
    min-height: 2lh;
  }

  /* Same idea one element down, and the other half of the same fix. The three
     sentences were brought to a similar length in round2.py so none of them
     needs a fourth line; this floor holds the shortest one at three, so a text
     that later comes out a few characters under cannot shrink its card and set
     the stack off again. Only a floor — a longer text still grows, it just has
     to grow in step with the others. px value is the fallback where lh is
     missing (three line heights at 16px/1.55). */
  #projekte [data-stack] p {
    min-height: 74px;
    min-height: 3lh;
  }

  /* --- all three cards have to let go at the same moment ------------------
     Sammy-Jo, 01.08.2026: once the cards are stacked and you keep scrolling,
     the ones behind climb out and show above the last one. Phone only.

     Measured at 390px: they sit together at y=78 until scroll 5096, then the
     first two release while the third holds on, and a 26px gap stays for the
     rest of the way. 26px is not a coincidence — it is the bottom margin. The
     first two cards carry margin-bottom: 26px as the gap between them, the last
     one carries none, and a pinned element gives up when its own bottom edge
     PLUS its bottom margin reaches the end of the container. So the last card
     was pinned exactly 26px longer than the others, and stuck out by 26px.
       card 1+2:  5781 - 509 - 78 - 26 = 5168
       card 3:    5781 - 509 - 78 -  0 = 5194
     Same margin on all three, same release point, the stack leaves as one
     block. The extra room under the last card sits inside the tail spacer
     below and changes nothing visible. */
  #projekte [data-stack] { margin-bottom: 26px !important; }

  /* The other half of the same requirement: equal height. Two cards that let go
     at the same moment still show a step if one is taller than the other.
     From 390px up all three come out identical on their own — measured 509px at
     390, 511 at 393, 524 at 414, 534 at 430. Below that the text block jumps
     between 253, 295 and 319px depending on where each card's chips and heading
     happen to wrap, and no amount of shortening the sentences fixes it, because
     what wraps differs per card and per width.
     So the text block gets a floor, in two steps taken from the measurement:
     295px covers 344 to 389px, 320px covers the narrowest phones still in use.
     A floor, not a fixed height — a longer text still grows, it just cannot
     make one card shorter than its neighbours. */
  @media (max-width: 389px) {
    #projekte [data-stack] > div:first-child { min-height: 295px; }
  }
  @media (max-width: 335px) {
    #projekte [data-stack] > div:first-child { min-height: 320px; }
  }

  /* Tail room after the last card, so it can reach its sticky position. */
  #projekte > div > div:nth-child(2) > div:last-child { height: 26vh !important; }

  #projekte > div > div:nth-child(3) { padding: 34px 0 58px !important; }
  #projekte > div > div:nth-child(3) > a { min-height: 56px; }

  /* ================================================== 5 · ablauf ========= */

  #ablauf { padding: 0 0 62px !important; }
  #ablauf h2 { margin: 20px 0 28px !important; }

  #ablauf > div > div {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }

  /* 250px minimum height per card was there to line four columns up; stacked,
     each card only needs the room its own text takes. */
  #ablauf [data-build] {
    min-height: 0 !important;
    padding: 24px 22px 26px !important;
    border-radius: 14px !important;
    gap: 10px !important;
  }

  #ablauf [data-build] [data-ghost] {
    font-size: 74px !important;
    bottom: -16px !important;
  }

  /* =============================================== 6 · festpreis ========= */

  #festpreis { padding: 0 0 62px !important; }
  #festpreis h2 { margin: 20px 0 24px !important; }

  #festpreis > div > div:last-child {
    grid-template-columns: 1fr !important;
    gap: 30px !important;
    padding: 26px 20px 28px !important;
  }

  #festpreis > div > div:last-child > div:nth-child(1) {
    min-height: 0 !important;
    gap: 24px !important;
  }

  #festpreis > div > div:last-child > div:nth-child(1) h3 { font-size: 23px !important; }

  /* Label and value share one line until they no longer fit, then the value
     drops underneath instead of being cut off at the card edge. */
  #festpreis > div > div:last-child > div:nth-child(1) > div:nth-child(2) > div {
    flex-wrap: wrap !important;
    gap: 2px 14px !important;
    padding: 13px 0 !important;
  }

  #festpreis > div > div:last-child > div:nth-child(2) { gap: 22px !important; }
  #festpreis > div > div:last-child > div:nth-child(2) a { min-height: 54px; }

  /* ==================================================== 7 · über ======== */

  #ueber { padding: 0 0 62px !important; }

  /* Kicker and heading moved into the left cell of the grid on 02.08.2026, so
     the 28px that used to sit under the heading are now the grid's row gap —
     keeping both would stack them to 56px. Same split #leistungen already uses:
     top margin on the h2, the row gap does the rest. Measured before and after:
     20px from kicker to heading, 28px from heading to copy, unchanged. */
  #ueber h2 { margin: 20px 0 0 !important; }

  #ueber > div > div:last-child {
    grid-template-columns: 1fr !important;
    gap: 28px !important;
  }

  #ueber > div > div:last-child > div:nth-child(2) { gap: 24px !important; }

  #ueber > div > div:last-child > div:nth-child(2) > div {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }

  /* Number to the left of its label instead of above it. Two tiles side by
     side would squeeze the "Minuten Erstgespräch" pill onto three lines; this
     keeps one tile per row but takes about 60px less height each, and reads
     like a stat row in an app. */
  #ueber [data-lift] {
    display: grid !important;
    grid-template-columns: auto 1fr;
    column-gap: 16px;
    align-items: center;
    padding: 18px 16px !important;
  }

  #ueber [data-count] {
    grid-column: 1;
    grid-row: 1 / span 2;
    align-self: start;
    font-size: 42px !important;
    line-height: 1 !important;
  }

  #ueber [data-lift] > span {
    grid-column: 2;
    grid-row: 1;
    margin: 0 !important;
    justify-self: start;
  }

  #ueber [data-lift] p {
    grid-column: 2;
    grid-row: 2;
    margin-top: 8px !important;
    font-size: 14px !important;
    line-height: 1.6 !important;
  }

  /* ================================================== 8 · kontakt ======== */

  #kontakt { padding: 58px 0 62px !important; }

  #kontakt > div {
    grid-template-columns: 1fr !important;
    gap: 26px !important;
  }

  #kontakt > div > div:nth-child(1) { gap: 20px !important; }

  /* Full-width rows, not a 2x2 grid: "Nachricht schreiben" and "Profil
     ansehen" would break into two lines in a half-width tile and leave the
     four tiles at uneven heights. */
  #kontakt > div > div:nth-child(1) > div:nth-child(4) {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
  }

  #kontakt > div > div:nth-child(1) > div:nth-child(4) a {
    min-height: 58px;
    padding: 14px 16px !important;
  }

  /* An inline-flex link is only as tall as its text — 15px is far under the
     44px a finger needs. */
  #kontakt > div > div:nth-child(1) > a {
    min-height: 44px;
    align-items: center !important;
    padding: 10px 0 !important;
  }

  #formular {
    padding: 22px 18px 24px !important;
    border-radius: 16px !important;
  }

  #formular > div { gap: 14px !important; }
  #formular > div > div { grid-template-columns: 1fr !important; gap: 12px !important; }

  /* Anything under 16px makes iOS Safari zoom into the field on focus and
     leave the page scrolled sideways. */
  #formular input,
  #formular textarea {
    font-size: 16px !important;
    padding: 14px !important;
    min-height: 52px;
  }

  #formular textarea { min-height: 118px; }
  #formular button { min-height: 54px; padding: 17px 15px !important; }

  /* ================================================ 9 · chat dock ======== */

  /* Sits closer to the corner so it covers less of the page, and respects the
     home indicator area on iPhones. */
  [data-ref="dock"] {
    right: 14px !important;
    bottom: calc(14px + env(safe-area-inset-bottom, 0px)) !important;
    gap: 10px !important;
  }

  [data-ref="dock"] > button {
    gap: 10px !important;
    min-height: 48px;
    padding: 11px 12px 11px 14px !important;
  }

  /* The panel is built by site.js at min(420px, 100vw - 56px); on a phone it
     should use the full width between the two 14px margins instead. */
  [data-ref="dock"] > div {
    width: calc(100vw - 28px) !important;
    max-height: min(78svh, 560px) !important;
  }

  /* site.js builds the panel as a flex column, but its show() does
     panel.style.display = '' — which deletes that declaration again, leaving a
     plain block. The message list then keeps its own height instead of taking
     the leftover, the panel runs past its max-height and overflow:hidden eats
     the input row. Restoring the column only while the dock is open keeps the
     close path (display:none) intact. */
  [data-ref="dock"][data-open] > div { display: flex !important; }

  /* With the column back, the list can have whatever room is left over. */
  [data-ref="dock"] [data-body] { max-height: none !important; }

  [data-ref="dock"] [data-qrow] {
    min-height: 48px;
    padding: 13px 0 !important;
  }

  [data-ref="dock"] [data-close] { min-height: 44px; min-width: 44px; }
  [data-ref="dock"] [data-input] { font-size: 16px !important; }

  [data-ref="dock"] [data-send] {
    width: 40px !important;
    height: 40px !important;
  }

  /* ============================== 10 · sticky hover on touch ============= */

  /* site.js binds mouseenter/mouseleave without a pointer query. A tap fires
     mouseenter, so these elements would stay lifted or shifted until the next
     tap somewhere else. Pinning the animated property blocks that. */
  #ueber [data-lift],
  #kontakt [data-lift],
  #ablauf [data-build] { transform: none !important; }
}

/* Small phones (iPhone SE, 360px Android): the same layout, one step tighter
   so nothing has to be cut off. */
@media (max-width: 430px) {

  #hero > div:last-child { gap: 22px !important; }

  /* Same fix as the main breakpoint, one size down: nth-child(2) is the
     label now that the numeral column is gone, and the grid has two tracks
     left, not three. 17px rather than 18px — every phone up to 430px lands
     here, so this is the size actually seen on an iPhone. It was 14.5px, which
     is why the choice read as fine print on the very devices it is for. */
  #leistungen button > span:nth-child(2) { font-size: 17px !important; }
  #leistungen button { grid-template-columns: minmax(0, 1fr) 14px !important; }

  #projekte [data-stack] { padding: 18px !important; }
  #projekte [data-stack] h3 { font-size: 23px !important; }

  #festpreis > div > div:last-child { padding: 24px 18px 26px !important; }

  #ueber [data-count] { font-size: 38px !important; }
  #ueber [data-lift] { column-gap: 13px; }

  /* The mono kicker repeats what the sentence next to it already says and
     costs 60px of the bottom bar. */
  [data-ref="dock"] > button > span:nth-child(1) { display: none !important; }
}


/* ===== project.css ===== */
/* project — phone layout for the project index and the three case-study pages.
   Scoped through [data-sc-name] because the design reuses the same inline style
   strings on the home page; without the scope these rules would reach pages
   another agent owns. "Referenz " (with the space) hits only the three detail
   pages, "Referenzen" only the overview. !important is used where the design
   sets the value inline — nothing weaker can win against that. */

@media (max-width: 768px) {

  /* ============================================ project detail — hero head */

  /* 150px of air above the headline is a desktop luxury; on a phone it pushes
     the title off the first screen for no gain. */
  [data-sc-name^="Referenz "] section[data-nav-hero] {
    padding-top: 104px !important;
  }

  /* The clamp floor (38px) is what a phone actually gets, so the headline lands
     far below the weight it carries on desktop. Scaling with vw restores it.
     hyphens stays manual on purpose: automatic German hyphenation turned
     "TÜRENKONFIGURATOR" into "KONFIGURA-/TOR", a four-line headline with the
     last line reading "TOR". The soft hyphen the design already sets is the
     only break wanted here. break-word is the safety net for a longer title. */
  [data-sc-name^="Referenz "] section[data-nav-hero] h1 {
    margin: 22px 0 18px !important;
    font-size: clamp(32px, 11vw, 48px) !important;
    max-width: none !important;
    letter-spacing: -.035em;
    overflow-wrap: break-word;
    hyphens: manual;
  }

  /* "KONFIGURATOR" is 7.55em wide and has to survive as one piece; measured
     against 310px (390px screen) and 280px (360px screen) that caps this one
     headline at 10vw. The other two case studies keep the larger size. */
  [data-sc-name="Referenz Konfigurator"] section[data-nav-hero] h1 {
    font-size: clamp(30px, 10vw, 44px) !important;
  }

  [data-sc-name^="Referenz "] section[data-nav-hero] > div > p {
    margin-bottom: 34px !important;
    font-size: 16px !important;
    line-height: 1.72 !important;
  }

  /* ------------------------------------------------ hero fact tiles ------ */

  /* Styled in fixes.css ("Project facts stack as one spec column"). The
     label-left/value-right rows that lived here collapsed on real iPhones —
     WebKit sizes two competing text blocks in one flex row differently from
     Chromium — so the whole tile is defined in one place there now. */

  /* ------------------------------------------------ hero image ----------- */

  /* site.js animates this frame from 1180px to 1800px wide while scrolling. A
     390px screen is narrower than the starting value, so the animation can only
     ever render as an over-wide fixed frame. Pinning it to the full screen is
     the honest phone version until the script learns about small screens. */
  [data-sc-name^="Referenz "] [data-ref="heroWrap"] {
    width: 100% !important;
    /* max-width and padding are driven by site.js: the frame starts inset with
       rounded corners and grows edge to edge while scrolling — the phone version
       of the desktop widening. Pinning them here would kill that motion. */
  }

  /* 21:9 on a phone is a 167px letterbox strip — too little presence for the
     one image that opens the case study. */
  /* Der Rahmen nimmt seine Höhe vom Bild — siehe fixes.css, Kopfbild der
     Projektseiten. Ein festes Verhältnis hier würde ohnehin überschrieben
     und nur in die Irre führen. */

  /* The zoom-out and parallax stay: they are what makes the image feel alive
     while the frame grows. site.js writes the transform. */

  /* The light sheet slides over the image — less overlap now that the image
     reaches the screen edges. */
  [data-sc-name^="Referenz "] section[data-nav-hero] + section {
    margin-top: -56px !important;
    padding-top: 50px !important;
    border-radius: 22px 22px 0 0 !important;
  }

  /* ============================================ project detail — body ===== */

  /* Vorher / Nachher / Aufwand */
  [data-sc-name^="Referenz "] [style*="minmax(260px, 1fr)"] {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
    margin-bottom: 52px !important;
  }

  [data-sc-name^="Referenz "] [style*="minmax(260px, 1fr)"] > div {
    padding: 24px 22px !important;
    border-radius: 14px !important;
  }

  /* ---------------- "Das Problem" / "Die Herausforderung" / "Mein Vorgehen" */

  /* The heading column has a 250px floor and the text column takes the rest —
     on a 310px canvas that leaves about 12px, so the paragraph is forced out of
     the screen (measured: 110px wide, 58px past the edge). Stacking is the only
     layout that fits. */
  [data-sc-name^="Referenz "] [style*="minmax(250px, 370px)"] {
    grid-template-columns: 1fr !important;
    gap: 18px !important;
    padding-bottom: 52px !important;
  }

  [data-sc-name^="Referenz "] [style*="minmax(250px, 370px)"][style*="padding-top: 70px"] {
    margin-top: 52px !important;
    padding-top: 52px !important;
  }

  /* Sticky has nothing left to stick against once the columns are stacked; it
     would only detach the heading from its own text. */
  [data-sc-name^="Referenz "] [style*="minmax(250px, 370px)"] > h2 {
    position: static !important;
    font-size: clamp(24px, 7.4vw, 32px) !important;
  }

  [data-sc-name^="Referenz "] [style*="minmax(250px, 370px)"] > div {
    font-size: 16px !important;
    line-height: 1.8 !important;
  }

  /* ------------------------------------------------ solution cards ------- */

  /* A 430px minimum column on a 310px canvas: every card hung 80px over the
     edge and got clipped, which is why the ghost digit was cut in half. */
  [data-sc-name^="Referenz "] [style*="minmax(430px, 1fr)"] {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }

  /* 250px was sized for a 430px-wide card. Full width needs less height, but
     enough for the ghost digit to sit behind the text rather than crowd it. */
  [data-sc-name^="Referenz "] [data-build] {
    min-height: 168px !important;
    padding: 24px 22px 28px !important;
    border-radius: 14px !important;
  }

  [data-sc-name^="Referenz "] [data-build] [data-ghost] {
    bottom: -20px !important;
    font-size: 88px !important;
  }

  [data-sc-name^="Referenz "] [data-build] h3 {
    font-size: 18px !important;
  }

  [data-sc-name^="Referenz "] [data-build] p {
    max-width: none !important;
    font-size: 16px !important;
    line-height: 1.72 !important;
  }

  /* Block around the solution cards, plus its heading. */
  [data-sc-name^="Referenz "] div[style*="padding: 70px 0px"] {
    padding: 52px 0 !important;
  }

  [data-sc-name^="Referenz "] div[style*="padding: 70px 0px"] > div > h2 {
    font-size: clamp(26px, 8vw, 36px) !important;
  }

  /* ------------------------------------------------ image gallery -------- */

  /* min(52vw, 620px) is 203px on a phone, so the row reads as thumbnails rather
     than as a gallery. Breaking out to the full screen width lets one tile own
     the screen with the next one peeking — the shape a swipe is expected to
     have. The 50%/-50% pair is gutter-independent: it lands on the viewport
     edge whatever side padding the global rules end up using. */
  [data-sc-name^="Referenz "] [data-rail] {
    width: 100vw !important;
    margin-left: 50% !important;
    transform: translateX(-50%);
    /* No snap at rest. site.js walks this rail sideways while the page
       scrolls, and mandatory snapping yanks every one of those small steps to
       the nearest tile — measured: setting 200 lands on 340, so the rail never
       moves. swipe.js switches snapping on for the duration of a finger swipe
       and off again afterwards, so both behaviours coexist. */
    overscroll-behavior-x: contain;
    cursor: default !important;
  }

  [data-sc-name^="Referenz "] [data-ref="gal"] {
    gap: 12px !important;
    /* Symmetric 10vw rails so the first tile is already centred at rest and
       every snap position looks the same. */
    padding-right: 10vw !important;
    padding-left: 10vw !important;
  }

  /* snap-stop:always keeps a hard flick from skipping a picture — without it a
     fast swipe carried straight from the first tile to the third, because
     mandatory snapping only picks the nearest point after the momentum ends. */
  [data-sc-name^="Referenz "] [data-ref="gal"] > div {
    width: 80vw !important;
    scroll-snap-align: center;
    scroll-snap-stop: always;
  }

  [data-sc-name^="Referenz "] [data-rail] + p {
    margin-top: 16px !important;
    font-size: 12.5px !important;
  }

  /* ------------------------------------------------ screen recording ----- */

  [data-sc-name^="Referenz "] [style*="minmax(280px, 1fr)"] {
    grid-template-columns: 1fr !important;
    gap: 22px !important;
    padding: 26px 24px !important;
    border-radius: 18px !important;
  }

  /* ------------------------------------------------ closing call --------- */

  [data-sc-name^="Referenz "] section[style*="rgb(26, 26, 26)"] {
    padding: 64px 0 !important;
  }

  [data-sc-name^="Referenz "] section[style*="rgb(26, 26, 26)"] h2 {
    font-size: clamp(28px, 8.6vw, 42px) !important;
  }

  /* Full-width primary action instead of a shrink-wrapped desktop button. */
  [data-sc-name^="Referenz "] section[style*="rgb(26, 26, 26)"] a[data-hv="h22"] {
    justify-content: space-between;
    width: 100%;
    padding: 16px 16px 16px 22px !important;
  }

  /* Trim the outer section rhythm so the page is not one long scroll. */
  [data-sc-name^="Referenz "] section[style*="padding: 70px 0px 0px"],
  [data-sc-name^="Referenz "] section[style*="padding: 80px 0px 0px"] {
    padding-top: 56px !important;
  }

  [data-sc-name^="Referenz "] section[style*="padding: 80px 0px 110px"] {
    padding: 56px 0 72px !important;
  }

  /* ============================================ overview — referenzen ===== */

  [data-sc-name="Referenzen"] section[data-nav-hero] {
    padding: 104px 0 128px !important;
  }

  /* Four hairlines every 77px turn the hero into visual noise at phone width. */
  [data-sc-name="Referenzen"] section[data-nav-hero] > div:first-child {
    grid-template-columns: 1fr 1fr !important;
  }

  [data-sc-name="Referenzen"] [data-ref="hero"] {
    grid-template-columns: 1fr !important;
    gap: 24px !important;
  }

  [data-sc-name="Referenzen"] [data-ref="hero"] h1 {
    margin-top: 20px !important;
    font-size: clamp(42px, 13.4vw, 66px) !important;
  }

  [data-sc-name="Referenzen"] [data-ref="hero"] p {
    margin-bottom: 0 !important;
    font-size: 16px !important;
    line-height: 1.75 !important;
  }

  [data-sc-name="Referenzen"] section[data-nav-hero] + section {
    margin-top: -88px !important;
    padding-top: 28px !important;
    border-radius: 22px 22px 0 0 !important;
  }

  /* ------------------------------------------------ filter chips --------- */

  /* Measured 39px tall — under the 44px a thumb needs. min-height plus flex
     centring keeps that guaranteed regardless of the inherited line-height. */
  [data-sc-name="Referenzen"] button[data-hv="h23"] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: 0 17px !important;
    font-size: 14px !important;
    border-radius: 24px !important;
  }

  [data-sc-name="Referenzen"] button[data-hv="h23"]:first-child {
    padding: 0 21px !important;
  }

  /* Count moves to its own line rather than fighting the chips for space. */
  [data-sc-name="Referenzen"] section[data-nav-hero] + section > div > div:first-child {
    gap: 10px !important;
    padding-bottom: 18px !important;
  }

  /* ------------------------------------------------ project cards -------- */

  /* A 320px minimum column overflows the 280px canvas of a 360px phone — that
     was the 15px of clipped card image in the measurement. */
  [data-sc-name="Referenzen"] [style*="minmax(320px, 1fr)"] {
    grid-template-columns: 1fr !important;
    gap: 16px !important;
    padding-top: 26px !important;
  }

  /* 520px was a floor for a three-across grid; full width fills it anyway, and
     dropping it stops short cards from carrying dead space. */
  [data-sc-name="Referenzen"] [data-card] {
    min-height: 0 !important;
    border-radius: 16px !important;
  }

  [data-sc-name="Referenzen"] [data-card] > div:first-child {
    height: 208px !important;
  }

  [data-sc-name="Referenzen"] [data-card] > div:last-child {
    gap: 12px !important;
    padding: 22px !important;
  }

  /* "TÜRENKONFIGURATOR" measures 11.07em and gets 264px inside the card, which
     puts the ceiling at 5.7vw. hyphens:auto only ever fires if a future title
     is longer still — better a hyphen than a title running past the card. */
  [data-sc-name="Referenzen"] [data-card] h2 {
    font-size: clamp(20px, 5.7vw, 27px) !important;
    overflow-wrap: break-word;
    hyphens: auto;
  }

  [data-sc-name="Referenzen"] [data-card] p {
    font-size: 16px !important;
    line-height: 1.7 !important;
  }

  /* ------------------------------------------------ closing call --------- */

  [data-sc-name="Referenzen"] main > section:last-child {
    padding-bottom: 72px !important;
  }

  [data-sc-name="Referenzen"] main > section:last-child > div > div[data-reveal] {
    grid-template-columns: 1fr !important;
    gap: 24px !important;
    padding: 32px 24px !important;
    border-radius: 18px !important;
  }

  [data-sc-name="Referenzen"] main > section:last-child h2 {
    font-size: clamp(28px, 8.6vw, 42px) !important;
  }

  /* Two stacked full-width actions read as app buttons; side by side they would
     each be half a thumb wide. */
  [data-sc-name="Referenzen"] main > section:last-child > div > div[data-reveal] > div:last-child {
    gap: 10px !important;
    justify-content: stretch !important;
  }

  [data-sc-name="Referenzen"] main > section:last-child > div > div[data-reveal] > div:last-child a {
    flex: 1 1 100%;
  }

  /* The label needs about 200px and gets 178px next to its arrow, so it wraps on
     every phone. Pushing the arrow to the far edge makes that a deliberate
     two-line button instead of a centred label drifting away from its icon —
     and it matches the same button on the case-study pages. */
  [data-sc-name="Referenzen"] main > section:last-child a[data-hv="h24"] {
    justify-content: space-between;
    padding: 16px 16px 16px 22px !important;
  }

  [data-sc-name="Referenzen"] main > section:last-child a[data-hv="h25"] {
    justify-content: center;
    padding: 16px 20px !important;
    text-align: center;
  }
}

/* ---------------------------------------------------------- small phones */
@media (max-width: 430px) {

  /* Tighter leading so the long compound headlines still read as one block. */
  [data-sc-name^="Referenz "] section[data-nav-hero] h1 {
    line-height: .96 !important;
  }

  [data-sc-name^="Referenz "] [data-build] {
    padding: 22px 20px 26px !important;
  }
}


/* ===== misc.css ===== */
/* misc — phone layout for Zertifikate, Kontakt, Impressum, Datenschutz.
   Scoped per page through [data-sc-name] so nothing leaks into the other
   pages. !important is used only where the design sets the same property
   inline, because inline styles outrank any stylesheet. */

@media (max-width: 768px) {

  /* ---------------------------------------------------------------- touch
     Touch devices have no hover, so the design's hover feedback never fires.
     Pressed states give the same "it reacted" signal a native app has. */
  [data-sc-name="Zertifikate"] a,
  [data-sc-name="Zertifikate"] button,
  [data-sc-name="Zertifikate"] [role="button"],
  [data-sc-name="Kontakt"] a,
  [data-sc-name="Kontakt"] button,
  [data-sc-name="Impressum"] a,
  [data-sc-name="Datenschutz"] a {
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
  }

  /* Footer links sit at 16px tall, far below a comfortable thumb target. */
  [data-sc-name="Zertifikate"] footer a,
  [data-sc-name="Kontakt"] footer a,
  [data-sc-name="Impressum"] footer a,
  [data-sc-name="Datenschutz"] footer a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  [data-sc-name="Zertifikate"] footer > div,
  [data-sc-name="Kontakt"] footer > div,
  [data-sc-name="Impressum"] footer > div,
  [data-sc-name="Datenschutz"] footer > div {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px !important;
  }
  [data-sc-name="Zertifikate"] footer > div > span:last-child,
  [data-sc-name="Kontakt"] footer > div > span:last-child,
  [data-sc-name="Impressum"] footer > div > span:last-child,
  [data-sc-name="Datenschutz"] footer > div > span:last-child {
    flex-wrap: wrap;
    gap: 6px 20px !important;
  }


  /* ========================================================== ZERTIFIKATE */

  /* The desktop hero reserves 360px of empty vertical space; on a phone that
     is a whole screen of nothing before the headline arrives. */
  [data-sc-name="Zertifikate"] [data-nav-hero] {
    padding: 124px 0 150px !important;
  }

  /* The Claude mark is 300px wide, bleeds 16px off-screen and collides with
     the logo. Pulled fully inside, below the header band and dimmed, it reads
     as texture behind the headline instead of a second focal point. */
  [data-sc-name="Zertifikate"] [data-ref="mark"] {
    width: 190px !important;
    top: 84px !important;
    right: 4px !important;
  }
  [data-sc-name="Zertifikate"] [data-ref="mark"] img {
    opacity: .2 !important;
  }

  /* Bigger headline: the design language is oversized uppercase type, and the
     desktop clamp bottoms out at a timid 38px on a phone. */
  [data-sc-name="Zertifikate"] [data-ref="hero"] h1 {
    font-size: clamp(38px, 10vw, 52px) !important;
    margin-bottom: 18px !important;
  }
  [data-sc-name="Zertifikate"] [data-ref="hero"] p {
    font-size: 16px !important;
    line-height: 1.75 !important;
  }

  /* The white sheet slides under the dark hero — less overlap on a phone so
     the rounded edge stays visible instead of eating the hero padding. */
  [data-sc-name="Zertifikate"] main > section:nth-of-type(2) {
    margin-top: -72px !important;
    border-radius: 20px 20px 0 0 !important;
    padding-top: 46px !important;
  }

  /* One card per row. auto-fit still asks for 300px minimum, which overflows
     a 360px screen once the page padding is taken off. */
  [data-sc-name="Zertifikate"] [style*="minmax(300px"] {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 16px !important;
    padding-bottom: 70px !important;
  }
  [data-sc-name="Zertifikate"] [data-cert-slot] {
    border-radius: 16px !important;
    transition: transform .35s cubic-bezier(.2,.7,.3,1), box-shadow .35s cubic-bezier(.2,.7,.3,1);
  }
  /* Whole card is the tap target; the press state replaces the hover lift. */
  [data-sc-name="Zertifikate"] [data-cert-slot]:active {
    transform: scale(.985);
    box-shadow: 0 10px 26px rgba(0,0,0,.12);
  }
  [data-sc-name="Zertifikate"] [data-cert-slot] > div:first-child {
    padding: 14px !important;
  }
  [data-sc-name="Zertifikate"] [data-cert-slot] > div:last-child {
    padding: 20px 18px 22px !important;
    gap: 7px !important;
  }
  /* Issuer and date wrap to two lines on a phone and need leading to match. */
  [data-sc-name="Zertifikate"] [data-cert-slot] > div:last-child > span:nth-child(3) {
    line-height: 1.55;
  }
  /* The "Mehr dazu" line is the visible affordance — give it real height. */
  [data-sc-name="Zertifikate"] [data-cta] {
    min-height: 44px;
    align-items: center !important;
    margin-top: 4px !important;
    font-size: 12.5px !important;
  }

  /* Section intro and heading block */
  [data-sc-name="Zertifikate"] main > section:nth-of-type(2) > div > p:first-child {
    font-size: clamp(21px, 5.6vw, 26px) !important;
    margin-bottom: 16px !important;
  }
  [data-sc-name="Zertifikate"] main > section:nth-of-type(2) > div > p:nth-child(2) {
    font-size: 16px !important;
    margin-bottom: 40px !important;
  }

  /* Closing call to action: full-width button is the phone convention. */
  [data-sc-name="Zertifikate"] main > section:nth-of-type(3) {
    padding: 66px 0 !important;
  }
  [data-sc-name="Zertifikate"] main > section:nth-of-type(3) > div {
    align-items: stretch !important;
  }
  [data-sc-name="Zertifikate"] main > section:nth-of-type(3) a {
    justify-content: space-between;
    min-height: 56px;
    padding: 16px 18px 16px 24px !important;
  }
  [data-sc-name="Zertifikate"] main > section:nth-of-type(3) a:active {
    filter: brightness(1.12);
  }


  /* ============================================================ LIGHTBOX
     Zwei Inhalte teilen sich diese Hülle: die Zertifikats-Ansicht und die
     schlichte Bildansicht der Projektseiten. Alles hier unten ist das Layout
     der Zertifikats-Ansicht — ein Textdialog — und deshalb von der Bildansicht
     ausgenommen. Ohne diese Trennung traf es jedes neue Kind und hat die
     Bildansicht messbar zerlegt: 58px auf 20px auf 92px Innenabstand am
     Rollbereich, 16px Fliesstext auf der Bildunterschrift, ein Schliessen-Knopf
     über die volle Breite quer über dem Bild.
     Built by site.js and appended to <body>, so it sits outside the page
     scope. It only ever exists on the certificates page. */

  #lightbox:not([data-shotview]) > div {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 22px !important;
    /* The dialog covers the header, so it needs no clearance for it.
       Bottom padding clears the sticky close bar below. */
    padding: 58px 20px 92px !important;
    align-items: start !important;
  }
  #lightbox:not([data-shotview]) h3 {
    font-size: clamp(28px, 8vw, 40px) !important;
  }
  #lightbox:not([data-shotview]) p {
    font-size: 16px !important;
    line-height: 1.8 !important;
  }
  /* Close stays within thumb reach however far the text scrolls. */
  #lightbox:not([data-shotview]) [data-close] {
    display: flex !important;
    width: 100%;
    justify-content: center;
    min-height: 52px;
    font-size: 12.5px !important;
    background: #1E1E1E !important;
    border-color: #2E2E2E !important;
  }
  #lightbox:not([data-shotview]) [data-close]:active {
    background: #262626 !important;
  }
  #lightbox:not([data-shotview]) > div > div:last-child > div:last-child {
    position: sticky;
    bottom: 14px;
    margin-top: 14px !important;
    z-index: 2;
  }


  /* =============================================================== KONTAKT */

  [data-sc-name="Kontakt"] main {
    padding-top: 118px !important;
    padding-bottom: 70px !important;
  }
  [data-sc-name="Kontakt"] main h1 {
    font-size: clamp(36px, 10.5vw, 54px) !important;
  }
  [data-sc-name="Kontakt"] main > div > div:first-child {
    margin-bottom: 30px !important;
    gap: 14px !important;
  }
  [data-sc-name="Kontakt"] main > div > div:first-child p {
    font-size: 16px !important;
  }

  /* Form and contact rail stack; auto-fit still demands 330px per column. */
  [data-sc-name="Kontakt"] [style*="minmax(330px"] {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 16px !important;
  }
  /* Sticky belongs to a two-column desktop layout; stacked it would jam. */
  [data-sc-name="Kontakt"] [style*="position: sticky"] {
    position: static !important;
  }

  /* Card padding of 34px costs a fifth of the usable width on a phone. */
  [data-sc-name="Kontakt"] [style*="border-radius: 16px"] {
    border-radius: 14px !important;
  }
  [data-sc-name="Kontakt"] [data-rd="0.05"] {
    padding: 22px 18px !important;
    gap: 16px !important;
  }

  /* Topic picker: pills that wrap read as choices, a stack of five wide
     buttons reads as a form from 2010 and burns half a screen. */
  [data-sc-name="Kontakt"] [style*="minmax(150px"] {
    display: flex !important;
    flex-wrap: wrap;
    gap: 8px !important;
  }
  [data-sc-name="Kontakt"] [style*="minmax(150px"] > button {
    flex: 0 1 auto;
    min-height: 44px;
    border-radius: 999px !important;
    padding: 11px 15px !important;
    font-size: 14px !important;
    text-align: center !important;
  }
  [data-sc-name="Kontakt"] [style*="minmax(150px"] > button:active {
    transform: scale(.97);
  }

  /* Name/Firma and Mail/Telefon pairs stack. */
  [data-sc-name="Kontakt"] [style*="minmax(160px"] {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 14px !important;
  }

  /* 16px is the threshold below which iOS zooms into a focused field. */
  [data-sc-name="Kontakt"] input[type="text"],
  [data-sc-name="Kontakt"] input[type="email"],
  [data-sc-name="Kontakt"] input[type="tel"],
  [data-sc-name="Kontakt"] textarea {
    font-size: 16px !important;
    padding: 14px 15px !important;
    border-radius: 10px !important;
    width: 100%;
  }
  [data-sc-name="Kontakt"] textarea {
    min-height: 132px;
    line-height: 1.6 !important;
  }
  [data-sc-name="Kontakt"] input:focus,
  [data-sc-name="Kontakt"] textarea:focus {
    border-color: var(--acc, #5A7BAE) !important;
    background: #fff !important;
  }
  /* Field and group labels carry meaning, so they get read-size type rather
     than the 10.5px reserved for decorative eyebrows. */
  [data-sc-name="Kontakt"] label > span:first-child,
  [data-sc-name="Kontakt"] [data-rd="0.05"] > div > span:first-child,
  [data-sc-name="Kontakt"] [data-rd="0.05"] > div > span:first-child > span {
    font-size: 12.5px !important;
    letter-spacing: .08em !important;
  }

  /* Drop zone is a tap target first and a drag target second on a phone. */
  [data-sc-name="Kontakt"] [data-ref="drop"] {
    min-height: 128px;
    justify-content: center;
    padding: 22px 16px !important;
    border-radius: 12px !important;
  }
  [data-sc-name="Kontakt"] [data-ref="drop"] span {
    text-align: center;
  }
  [data-sc-name="Kontakt"] [data-ref="drop"]:active {
    border-color: var(--acc, #5A7BAE) !important;
    background: #F4F7FC !important;
  }

  /* Send button: the page's primary action deserves phone-button size. */
  [data-sc-name="Kontakt"] [data-hv="h21"] {
    min-height: 54px;
    font-size: 12.5px !important;
    border-radius: 10px !important;
  }
  [data-sc-name="Kontakt"] [data-hv="h21"]:active {
    filter: brightness(1.1);
    transform: scale(.99);
  }
  [data-sc-name="Kontakt"] [data-hv="h21"] + p {
    font-size: 16px !important;
    line-height: 1.65 !important;
  }

  /* Direct-contact rows become list items with a proper touch height. */
  [data-sc-name="Kontakt"] [data-ch] {
    min-height: 62px;
    padding: 13px 18px !important;
  }
  [data-sc-name="Kontakt"] [data-ch]:active {
    background: #F4F4F4;
  }
  [data-sc-name="Kontakt"] [data-ch] > span:last-child > span:first-child {
    font-size: 12.5px !important;
  }
  [data-sc-name="Kontakt"] [data-ch] > span:last-child > span:last-child {
    font-size: 16px !important;
  }

  /* "Was danach passiert" card */
  [data-sc-name="Kontakt"] [data-rd="0.08"] {
    padding: 24px 20px !important;
  }
  [data-sc-name="Kontakt"] [data-rd="0.08"] p {
    font-size: 16px !important;
  }
  /* Postal address under the signature line — real information, not a caption. */
  [data-sc-name="Kontakt"] [data-rd="0.08"] > div:last-child div > div:last-child {
    font-size: 14px !important;
    line-height: 1.5;
  }


  /* ================================================ IMPRESSUM + DATENSCHUTZ
     Both are duty texts: the job is calm reading, not decoration. */

  [data-sc-name="Impressum"] main,
  [data-sc-name="Datenschutz"] main {
    padding-top: 116px !important;
    padding-bottom: 64px !important;
  }
  [data-sc-name="Impressum"] main > h1 {
    font-size: clamp(40px, 11.5vw, 56px) !important;
    margin: 22px 0 34px !important;
  }
  [data-sc-name="Datenschutz"] main > h1 {
    font-size: clamp(32px, 8.8vw, 48px) !important;
    margin: 22px 0 16px !important;
    hyphens: auto;
    overflow-wrap: break-word;
  }
  [data-sc-name="Datenschutz"] main > p {
    font-size: 16px !important;
    margin-bottom: 34px !important;
  }

  /* Root cause of the horizontal overflow: the label column asks for at least
     160px and the content column cannot shrink below its widest word — the
     e-mail address. Together they demand 396px inside a 310px viewport.
     minmax(0,1fr) drops the intrinsic floor, anywhere lets the address wrap. */
  [data-sc-name="Impressum"] main section,
  [data-sc-name="Datenschutz"] main section {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 12px !important;
    padding-top: 22px !important;
  }
  [data-sc-name="Impressum"] main section > *,
  [data-sc-name="Datenschutz"] main section > * {
    min-width: 0;
    overflow-wrap: anywhere;
  }
  /* The label turns into the section's eyebrow instead of a side column. */
  [data-sc-name="Impressum"] main section > h2,
  [data-sc-name="Datenschutz"] main section > h2 {
    font-size: 12.5px !important;
    letter-spacing: .16em !important;
    color: var(--acc-ink, #4d6a96) !important;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  }
  /* Reading size: 14px across 62ch is a desktop measure; a phone wants larger
     glyphs and slightly tighter leading. */
  [data-sc-name="Impressum"] main section p,
  [data-sc-name="Datenschutz"] main section p,
  [data-sc-name="Impressum"] main section > div,
  [data-sc-name="Datenschutz"] main section > div {
    font-size: 16px !important;
    line-height: 1.75 !important;
  }
  [data-sc-name="Impressum"] main section a,
  [data-sc-name="Datenschutz"] main section a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    font-size: 16px !important;
    color: var(--acc-ink, #4d6a96) !important;
  }
  /* The 44px targets already carry the spacing; the design's own gap on top
     of them would tear the phone and mail line apart. */
  [data-sc-name="Impressum"] main section div:has(> a),
  [data-sc-name="Datenschutz"] main section div:has(> a) {
    gap: 0 !important;
  }
  /* Air between the duty paragraphs so the text does not read as a wall. */
  [data-sc-name="Impressum"] main > div:first-of-type,
  [data-sc-name="Datenschutz"] main > div:first-of-type {
    gap: 30px !important;
  }
  /* Draft notice box — its label wraps to two lines at this width. */
  [data-sc-name="Impressum"] main > div:last-of-type,
  [data-sc-name="Datenschutz"] main > div:last-of-type {
    margin-top: 40px !important;
    padding: 18px 16px !important;
  }
  [data-sc-name="Impressum"] main > div:last-of-type > div:first-child,
  [data-sc-name="Datenschutz"] main > div:last-of-type > div:first-child {
    line-height: 1.6;
    margin-bottom: 10px !important;
  }
}


/* Narrow phones: the same layout, one notch tighter. Type size stays put —
   only the padding gives way, so nothing drops below reading size. */
@media (max-width: 430px) {
  [data-sc-name="Zertifikate"] [data-ref="mark"] {
    width: 164px !important;
  }
  [data-sc-name="Kontakt"] [style*="minmax(150px"] > button {
    padding: 11px 13px !important;
  }
  [data-sc-name="Kontakt"] [data-ch] {
    padding-left: 16px !important;
    padding-right: 16px !important;
  }
}


/* ===== polish.css ===== */
/* polish — the last layer over base/home/project/misc.
   Two jobs: bring the scroll choreography of site.js down to phone size, and
   take the final pass over rhythm, focus and line breaking across all nine
   pages. Because this file is loaded last it also gets the closing word where
   an earlier part and a shared floor disagreed.
   Everything sits inside a max-width query — the approved desktop rendering
   must stay untouched. */

@media (max-width: 768px) {

  /* =========================================================== 1 · motion */

  /* --- home: the headline stops flying into the header ------------------ */

  /* site.js measures the header wordmark and flies the three words of the hero
     headline into it, word by word. That geometry needs the wide one-line
     wordmark of the desktop header. At 390px the words scatter diagonally
     instead and the last one lands under the menu button — measured at
     x 281..389 in a 390px viewport, with the burger drawn straight through
     "SOLUTIONS". Freezing both transforms ends the flight. */
  /* The transform is NOT pinned any more: site.js now runs a phone-specific
     version of the choreography (the headline shrinks back and fades as it
     leaves, instead of flying word by word into the header, which scattered at
     390px). Pinning it here would freeze that motion too. */

  /* The half of the choreography that still makes sense on a phone is kept:
     site.js takes the headline's opacity to zero between scroll 750 and 850,
     which is exactly where the header turns light and the wordmark fades in.
     Left alone that is a 100px jump; the transition turns the same hand-over
     into a dissolve. The motion is replaced, not removed — and unlike a
     scroll-driven animation this works in every browser. */
  /* opacity is scroll-driven in site.js now, so no CSS transition on top. */

  /* The gentle rise on top. `translate` is a separate property from
     `transform`, so it stays free while the line above pins the transform
     site.js writes. Where scroll-driven animations are missing the headline
     simply holds still and the dissolve above carries the moment alone. */
  @supports (animation-timeline: view()) {
    #hero > div:last-child {
      view-timeline-name: --hds-hero;
      view-timeline-axis: block;
    }
    /* The headline's own rise was a stand-in while the phone had no docking
       flight. Now that the real one runs here too, a second animation on the
       same element would fight it. */
    /* Certificates: the claude mark drifts a quarter of the scroll distance,
       which on a phone walks it straight through the headline. Pinned and
       re-driven at a sixth of the travel it stays a texture in the corner. */
    [data-sc-name="Zertifikate"] main > section:first-of-type {
      view-timeline-name: --hds-mark;
      view-timeline-axis: block;
    }
    [data-sc-name="Zertifikate"] [data-ref="mark"] {
      animation: hds-mark-drift linear both;
      animation-timeline: --hds-mark;
      animation-range: exit 0% exit 100%;
    }
  }

  /* --- certificates: the claude mark as a corner texture ---------------- */

  [data-sc-name="Zertifikate"] [data-ref="mark"] {
    transform: none !important;
    width: 148px !important;
    top: 30px !important;
    right: -22px !important;
  }
  /* Two tenths over black still reads as a brown blob behind white display
     type; at this weight the mark is felt rather than seen. */
  [data-sc-name="Zertifikate"] [data-ref="mark"] img { opacity: .13 !important; }

  /* --- the reveal on scroll --------------------------------------------- */

  /* site.js reveals with opacity, a 42px rise and a 7px blur. The blur is the
     one part that does not survive the transfer: a phone scrolls a screen
     height in a flick, so the blur is what the eye actually catches and the
     page reads as still loading. Opacity and rise stay and carry the reveal.
     Verified first: none of the 38 revealed elements carries an authored
     filter, so nothing else is lost here. */
  [data-reveal] { filter: none !important; }

  /* --- home: the stacked project cards ---------------------------------- */

  /* --- the fade behind the stack ---------------------------------------
     The cards were forced opaque here, because a translucent card let the one
     underneath shine through and that read as a rendering fault. The real
     cause was the staggered pin height above: with each card at a different
     top, the card below appeared beside its neighbour instead of behind it.
     With one shared height the fade does what it does on the desktop — the
     covered card sinks into the background, which is exactly the effect
     Sammy-Jo asked to keep ("als würden sie den Hintergrund verschwinden"). */

  /* ========================================================= 2 · rhythm */

  /* --- the ghost digit inside the step cards ---------------------------- */

  /* The oversized digit sits bottom right and the copy runs the full width, so
     the last line crosses it — measured 78px of horizontal and 32px of
     vertical overlap on every card of the process and solution lists. Extra
     bottom padding turns the lower strip into the digit's own space, and the
     smaller size keeps it inside that strip instead of behind the sentence.
     The condition the three numbers have to satisfy is padding >= size minus
     overhang; 48 >= 56 - 10 holds with two pixels to spare.
     Both selectors repeat the scope the earlier parts used, because a bare
     [data-build] loses to their #ablauf and [data-sc-name] prefixes. */
  #ablauf [data-build],
  [data-sc-name^="Referenz "] [data-build] { padding-bottom: 48px !important; }

  #ablauf [data-build] [data-ghost],
  [data-sc-name^="Referenz "] [data-build] [data-ghost] {
    font-size: 56px !important;
    line-height: 1 !important;
    bottom: -10px !important;
    right: 14px !important;
  }

  /* --- the one centred section head ------------------------------------- */

  /* "So läuft eine Zusammenarbeit" is centred in the design, and there it is
     right: it sits above a row of four cards spanning the full width. On a
     phone that row becomes one stacked column of left-aligned cards, so the
     centred head is the only section opener on the page that does not line up
     with what follows it. Aligning it left keeps the design's own logic —
     heading over its content — rather than its desktop coordinates.
     :has() picks the wrapper by what it contains, so the rule survives a
     change in the nesting depth around the heading — base already relies on
     the same selector for the open menu. */
  #ablauf div:has(> h2) {
    align-items: flex-start !important;
    text-align: left !important;
  }
  #ablauf h2 { text-align: left !important; }

  /* --- the footer ------------------------------------------------------- */

  /* Every footer link carries a 44px tap target from base, and the design adds
     another 12px between them. Together that is a 56px pitch, which pulls the
     link lists apart until they read as scattered items rather than a menu.
     Zeroing the gap leaves the 44px rows touching — the rhythm of a native
     list, and 60px less footer on every page. */
  footer [style*="flex-direction: column"] { gap: 0 !important; }

  /* Except the text block on the left. It is a column too, so the rule above
     caught it, and its two children — the description line and the company
     block underneath — ended up touching at 0px. That block holds prose, not
     tap targets, so the rhythm above does it no good. Identified by the reading
     width the link columns do not have. 24px rather than the 20 the design
     ships: the sentence got shorter on 01.08.2026 and the block reads tighter
     than before. Sammy-Jo asked for exactly this: "besseren Abstand zu Hoffmann
     Digital Solutions drunter". */
  footer [style*="flex-direction: column"][style*="max-width: 36ch"] {
    gap: 24px !important;
  }

  /* The label above each column needs its distance back, since the rows no
     longer bring any. */
  footer [style*="flex-direction: column"] > span:first-child {
    margin-bottom: 8px;
  }

  /* 48px between the four footer blocks was measured against a four-column
     desktop row; stacked they only need a clear step. */
  footer [style*="display: grid"] { gap: 30px !important; }

  /* --- the project gallery caption -------------------------------------- */

  /* project.css breaks the gallery out to the full screen width with 10vw
     rails, so the first tile starts at 39px while the caption below keeps the
     16px text gutter. Centring settles it under a centred carousel instead of
     inventing a third alignment. */
  [data-sc-name^="Referenz "] [data-rail] + p { text-align: center !important; }

  /* ===================================================== 3 · line breaks */

  /* Auto hyphenation is what keeps German compounds from tearing the column
     open, but unrestricted it also breaks three-letter tails off short words.
     Eight characters minimum with at least four before and three after the
     hyphen keeps the help and drops the noise. */
  p, li, dd, h1, h2, h3, h4 {
    -webkit-hyphenate-limit-before: 4;
    -webkit-hyphenate-limit-after: 3;
    -webkit-hyphenate-limit-chars: 8 4 3;
    hyphenate-limit-chars: 8 4 3;
  }

  /* Display headings run two to four lines on a phone. Balancing spreads the
     words evenly instead of leaving a single word on the last line; where the
     property is unknown the line breaks stay exactly as they are today. */
  h1, h2, h3 { text-wrap: balance; }

  /* Running copy wants the opposite rule: keep the measure, only forbid the
     one-word last line. */
  p { text-wrap: pretty; }

  /* The two legal pages are the longest uninterrupted reading on the site and
     their column is a plain single column, so the reading size can go up a
     step without touching any fitted layout. That pulls the longest lines from
     48 down to about 44 characters. */
  [data-sc-name="Impressum"] main section p,
  [data-sc-name="Datenschutz"] main section p,
  [data-sc-name="Impressum"] main section > div,
  [data-sc-name="Datenschutz"] main section > div {
    font-size: 16px !important;
    line-height: 1.72 !important;
  }

  /* The body paragraphs of those pages carry an inline 14px, which base lifts
     to its 15px floor through a two-attribute selector — that outranks the
     rule above and would leave one page with two different reading sizes. The
     extra [style] attribute puts this rule back on top. The quieter 13px
     editorial notes are deliberately not listed: they keep the smaller step so
     the hierarchy between statement and side note survives. */
  [data-sc-name="Impressum"] main section p[style*="font-size: 14px"],
  [data-sc-name="Datenschutz"] main section p[style*="font-size: 14px"] {
    font-size: 16px !important;
    line-height: 1.72 !important;
  }

  /* base sets an 11px floor for micro labels and gives the reason: below that,
     widely tracked uppercase stops being legible on a phone. Two later parts
     wrote 10.5px anyway. The floor wins — it is the documented decision.
     #leistungen button > span:nth-child(2) used to belong on this list — back
     when the button still carried a numeral span, nth-child(2) was that small
     caps kicker. Since extend.py dropped the numeral, nth-child(2) is the
     main service label ("Individualsoftware"), and an 11px floor written for
     a micro-label was silently shrinking the actual heading. Removed here;
     home.css now sizes that span on its own terms (15.5px / 14.5px). */
  [data-sc-name="Impressum"] main section > h2,
  [data-sc-name="Datenschutz"] main section > h2,
  [data-sc-name^="Referenz "] [style*="minmax(150px, 1fr)"] > div > span:first-child,
  [data-sc-name="Kontakt"] [data-ch] > span:last-child > span:first-child {
    font-size: 12.5px !important;
  }
  /* Measured before raising these: the fact rows of the project pages keep
     their exact heights (48/48/66/68px at both 390 and 360), the contact rows
     grow by two pixels on one of four, and no page gains any overflow. The
     floor costs nothing here, so every micro label on the site is now one
     size. */

  /* ================================================ 4 · touch and focus */

  /* Keyboard focus has to stay visible on a phone too — hardware keyboards,
     switch control and voice control all move focus. The accent ring sits on
     the brand colour and clears the element by 3px so it never touches the
     glyphs. :focus-visible keeps it away from plain taps. */
  a:focus-visible,
  button:focus-visible,
  input:focus-visible,
  textarea:focus-visible,
  select:focus-visible,
  [tabindex]:focus-visible {
    outline: 2px solid var(--acc, #5A7BAE) !important;
    outline-offset: 3px !important;
    border-radius: 6px;
  }

  /* On the dark hero and the dark cards the accent ring has too little
     contrast against black, so focus turns white there. */
  #hero a:focus-visible,
  #menu a:focus-visible,
  #menu button:focus-visible,
  [data-nav-hero] a:focus-visible,
  [data-dl]:focus-visible {
    outline-color: #fff !important;
  }

  /* The grey flash Android draws over every tapped link belongs to no design
     system on this page; the press states below replace it. */
  a, button, [role="button"], summary, [tabindex] {
    -webkit-tap-highlight-color: transparent;
  }

  /* A tap needs an answer within the same frame. Opacity is safe to use here:
     site.js drives transform and background on these rows, never opacity. */
  footer a:active,
  #menu a:active,
  [data-qrow]:active,
  [data-ch]:active { opacity: .55; }

  /* ===================================================== 5 · last checks */

  /* Long unbroken tokens inside headings — Produktkonfiguratoren,
     Datenschutzerklärung — may break rather than widen the line. */
  h1, h2, h3, h4 { overflow-wrap: break-word; }

  /* A fixed element on iOS needs the home indicator strip accounted for, or
     the last footer row ends up underneath it. */
  footer { padding-bottom: calc(28px + env(safe-area-inset-bottom, 0px)); }
}

/* Keyframes stay outside the query: they describe motion, they do not apply
   it. Only the rules above, all inside the query, ever reference them. */
@keyframes hds-hero-rise {
  from { translate: 0 0; }
  to   { translate: 0 -30px; }
}
@keyframes hds-mark-drift {
  from { translate: 0 0; }
  to   { translate: 0 46px; }
}

/* Small phones (360px and below): the same decisions, one step tighter. */
@media (max-width: 430px) {

  /* Less room for the digit to hide in, so it takes one size less. */
  #ablauf [data-build],
  [data-sc-name^="Referenz "] [data-build] { padding-bottom: 42px !important; }

  #ablauf [data-build] [data-ghost],
  [data-sc-name^="Referenz "] [data-build] [data-ghost] { font-size: 50px !important; }

  /* The mark moves further into the corner as the headline gets closer to the
     screen edge. */
  [data-sc-name="Zertifikate"] [data-ref="mark"] {
    width: 130px !important;
    right: -26px !important;
  }

  footer [style*="display: grid"] { gap: 26px !important; }
}


/* ===== fixes.css ===== */
/* Corrections after the swarm review. Loaded last, so these win.
   Each block states the finding it closes. */

/* --- Burger turns into a cross while the menu is open ----------------------
   Not a phone-only tweak: the design itself swaps the two bars for an X icon
   (<sc-if value="{{ menuOpen }}">), and only the closed state survived the
   capture. The full-screen overlay otherwise offers a close button that looks
   exactly like the open button. Rotating the existing bars keeps the markup
   untouched and animates, which the icon swap never did. */
#burger > span {
  transition: transform .32s cubic-bezier(.2,.7,.3,1), opacity .2s ease;
  transform-origin: center;
}
#burger[aria-expanded="true"] > span:first-of-type { transform: translateY(3.5px) rotate(45deg); }
#burger[aria-expanded="true"] > span:last-of-type { transform: translateY(-3.5px) rotate(-45deg); }
@media (prefers-reduced-motion: reduce) {
  #burger > span { transition: none; }
}

/* --- Gallery dot row: class-driven, so it lifts again on wide screens -------
   Was set as inline style by swipe.js. Inline styles are written once at load
   and survive a resize, so a phone rotated to landscape (or a window dragged
   wider) kept the dot row and the reordering on a desktop-width page. */
.hds-dots { display: none; }

@media (max-width: 768px) {
  /* the browser's own back-swipe must not fire while swiping through tabs */
  html.hds-touch { overscroll-behavior-x: contain; }

  .hds-rail-host { display: flex; flex-direction: column; }
  .hds-rail-host > .hds-rail-after { order: 2; }
  .hds-dots {
    order: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 7px;
    margin: 14px 0 0;
  }

  /* --- iOS zoom trap ------------------------------------------------------
     Safari zooms into any field below 16px on tap and never zooms back out.
     A body-copy rule elsewhere matches elements by the contents of their
     inline style ([style*="font-size: 14.5px"]) to lift small text to 15px —
     two attribute selectors, which outweighs a plain `textarea` rule and
     dragged the field back under the threshold. Matching the element AND an
     attribute AND an ancestor beats it without touching that rule. */
  [data-sc-name] textarea[style],
  [data-sc-name] input[style],
  [data-sc-name] select[style] { font-size: 16px !important; }

  /* --- Project hero: the light sheet slides over the image -----------------
     The desktop version widens the frame from 1180px to 1800px, so the image
     breaks out of the text grid. A phone has no width to spare — 20px of
     padding is not a movement anyone notices. The design already hints at the
     better idea: the light section below carries a negative offset, rounded top
     corners and an upward shadow, i.e. it is drawn as a sheet lying on top.
     Here that becomes the motion: the image holds still while the sheet travels
     up over it. Depth without needing width. */
  [data-sc-name^="Referenz "] section[data-nav-hero] {
    padding-bottom: 0 !important;
  }
  [data-sc-name^="Referenz "] [data-ref="heroWrap"] {
    /* Everything scrolls at page speed. Earlier versions pinned the image or
       moved it at half speed; both read as sluggish on a phone. */
    padding: 0 !important;
    max-width: none !important;
    transform: none !important;
  }
  [data-sc-name^="Referenz "] [data-ref="heroFrame"] {
    border-radius: 0 !important;
    /* Kein festes Seitenverhältnis mehr: Das Bild bestimmt die Höhe des
       Rahmens, damit object-fit:cover nichts mehr abzuschneiden hat — bei jedem
       Bild, das später hier landet. Gemessen bei 390px kostete 4:3 gegen das
       Bildformat 1,93 genau 175px an den Seiten (320px: 144, 430px: 193).
       Der Rahmen endet mit dem Bild. Bis zum 01.08.2026 standen hier 85px
       dunkles Polster, in das die helle Fläche darunter genau hineinrückte —
       sie verdeckte vom Bild nichts, dafür lag unter dem Bild ein schwarzer
       Streifen. Sammy-Jo dazu: das Bild soll hinter der hellen Fläche
       verschwinden. Ohne das Polster tut es das. */
    aspect-ratio: auto !important;
    background: #0A0A0A !important;   /* das Schwarz des Kopfbereichs */
  }
  [data-sc-name^="Referenz "] [data-ref="heroImg"] {
    height: auto !important;          /* 100% eines auto-hohen Rahmens wäre 0 */
    transform: none !important;
    filter: none !important;
  }
  /* The one piece of motion that stays: the light sheet is drawn as a layer on
     top — rounded top corners and a shadow it already carries in the design —
     and slides across the image as the page moves on. */
  [data-sc-name^="Referenz "] section[data-nav-hero] + section {
    /* Wie weit die helle Fläche über das Bild rückt. 28px trägt die
       26px-Rundung sichtbar und lässt bei 390px 174 der 202 Bildpixel stehen
       (86 Prozent). Die 84px von vorher wären jetzt, ohne das Polster
       darunter, 42 Prozent des Bildes. */
    margin-top: -28px !important;
    border-radius: 26px 26px 0 0 !important;
    box-shadow: 0 -22px 54px rgba(0,0,0,.30) !important;
    padding-top: 42px !important;
  }

  /* --- Gallery width ------------------------------------------------------
     100vw includes the scrollbar on browsers with classic (space-taking)
     scrollbars, which would push ~15px of horizontal overflow onto a narrow
     desktop window. The rail's parent already spans the full width. */
  [data-sc-name^="Referenz "] [data-rail] { width: 100% !important; }

  /* --- Project facts stack as one spec column ------------------------------
     Replaces the label-left/value-right rows. Two text blocks sharing one
     flex row forced a min-content negotiation that WebKit resolves
     differently from Chromium: on a real iPhone the value column collapsed
     and wrapped mid-word ("Fens/ter-/und/Türe/nbau"), and the min-width
     counter-fix then pushed the dashed box past the screen edge. Stacking
     removes the negotiation entirely — each value owns the full line, so no
     engine has a reason to shrink it below its longest word. It is also the
     desktop tile's own reading order (label above value), one fact per row;
     the grid's 1px gap keeps drawing the hairlines between the rows. */
  [data-sc-name^="Referenz "] section[data-nav-hero] [style*="minmax(150px, 1fr)"] {
    grid-template-columns: 1fr !important;
    margin-bottom: 40px !important;
  }
  [data-sc-name^="Referenz "] section[data-nav-hero] [style*="minmax(150px, 1fr)"] > div {
    flex-direction: column !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    gap: 6px !important;
    padding: 14px 18px 15px !important;
    min-height: 0 !important;
  }
  /* break-word instead of base.css's blanket `anywhere` for the monospace
     label: `anywhere` lowers min-content size and was one half of the iPhone
     failure; `break-word` still catches genuine overflow but leaves sizing
     alone. */
  [data-sc-name^="Referenz "] section[data-nav-hero] [style*="minmax(150px, 1fr)"] > div > span:first-child {
    flex: none !important;
    white-space: normal !important;
    overflow-wrap: break-word !important;
  }
  /* 15px because that is the site's own phone floor for running text
     (base.css lifts 14.5px body copy to 15px) and these values are the
     tile's main content. text-wrap: pretty balances the rare two-liner;
     engines without it wrap as usual. */
  [data-sc-name^="Referenz "] section[data-nav-hero] [style*="minmax(150px, 1fr)"] > div > span:last-child {
    flex: none !important;
    max-width: none !important;
    text-align: left !important;
    font-size: 15px !important;
    line-height: 1.5 !important;
    overflow-wrap: break-word !important;
    text-wrap: pretty;
  }
  /* The dashed placeholder chip hugs its text instead of stretching across
     the row, so it still reads as "will be replaced by a real name" and not
     as a design element. 11px honours the micro-type floor documented in
     polish.css; the :last-child bump lets this rule beat the 15px value rule
     above it. */
  [data-sc-name^="Referenz "] section[data-nav-hero] [style*="minmax(150px, 1fr)"] > div > span[style*="dashed"]:last-child {
    align-self: flex-start !important;
    font-size: 12.5px !important;
    line-height: 1.6 !important;
    padding: 6px 10px !important;
    white-space: normal !important;
    overflow-wrap: break-word !important;
  }
  /* From 480px up there is room for the desktop's two-up tile look again;
     minmax(0, 1fr) keeps the tracks at exactly half the row, so no cell can
     bargain for more. */
  @media (min-width: 480px) {
    [data-sc-name^="Referenz "] section[data-nav-hero] [style*="minmax(150px, 1fr)"] {
      grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    }
  }

  /* --- Footer -------------------------------------------------------------
     Two different footers exist. The sub-pages carry a single line (copyright
     plus three or four links) that squeezed four 60px links across the screen.
     The home page carries a full sitemap: an outer grid holding a column of
     four link blocks next to a contact block — measured 955px tall, a second
     screen of scrolling at the end of the page.
     Both get the same treatment: everything stacks, links become 44px rows,
     and the link lists run in two columns so they stay compact. */
  footer {
    padding-top: 26px !important;
    padding-bottom: max(22px, env(safe-area-inset-bottom)) !important;
  }
  footer a {
    min-height: 44px !important;
    display: flex !important;
    align-items: center !important;
    font-size: 14px !important;
  }

  /* Seit dem 02.08.2026 traegt jede Seite dieselbe Fusszeile wie die Startseite
     (block10.py). Vorher gab es zwei Bauarten -- die volle auf der Startseite,
     eine schmale Zeile auf den neun anderen -- und entsprechend zwei Saetze
     Regeln, jeder an den Abschnittsnamen der jeweiligen Seite gebunden. Beides
     ist zusammengefallen: Die Regeln haengen jetzt an `footer` selbst und
     gelten damit ueberall gleich.

     Aufbau der Fusszeile: ein Raster mit vier Bloecken -- Anschrift,
     Seitenverzeichnis, Rechtliches, Wortmarke -- darunter eine Trennlinie mit
     der Unterschrift. Auf dem Handy liegen die vier untereinander. */
  footer > div,
  footer > div > div {
    display: block !important;
  }

  /* Der Anschrift-Block braucht Abstand nach unten. Bis zum 02.08.2026 fehlte
     er: Das Raster wird hier zu `block`, und damit verfaellt sein `gap` --
     "55743 Idar-Oberstein" klebte direkt an der Ueberschrift "SEITE"
     (gemessen: 0 Punkte Abstand). Sammy-Jo dazu mit Bildschirmfoto: "Fusszeile
     noch nicht gut formatiert". Die 18 Punkte der Nachbarbloecke waren nie ein
     Raster-Abstand, sondern deren eigenes `margin-bottom` -- der erste Block
     hatte keines. */
  footer > div > div > div:nth-child(1) {
    margin-bottom: 30px !important;
  }

  /* Seitenverzeichnis und Rechtliches: Ueberschrift auf eigener Zeile, die
     Links darunter zweispaltig. Als Flex-Spalte standen sie sonst sechs Zeilen
     hoch untereinander. */
  footer > div > div > div:nth-child(2),
  footer > div > div > div:nth-child(3) {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap !important;
    margin-bottom: 18px !important;
    gap: 0 18px !important;
  }
  footer > div > div > div:nth-child(2) > :first-child,
  footer > div > div > div:nth-child(3) > :first-child {
    flex: 0 0 100% !important;
    margin-bottom: 2px !important;
  }
  footer > div > div > div:nth-child(2) > a,
  footer > div > div > div:nth-child(3) > a {
    flex: 0 0 calc(50% - 9px) !important;
  }

  /* Die Wortmarke: 15vw laeuft auf einem so schmalen Schirm in seine
     Untergrenze von 120px, und die war fuer eine Desktop-Spalte gedacht. */
  footer > div > div > div:last-child {
    margin-top: 8px;
  }
  footer > div > div > div:last-child img {
    width: 96px !important;
  }

  /* Die Unterschrift unter der Trennlinie. Auf dem Desktop stehen die beiden
     Angaben links und rechts auseinander; auf dem Handy rutschten sie in eine
     Zeile und lasen sich als ein Satz ("... 2026 Wiesbaden, Rhein-Main").
     Untereinander gesetzt ist wieder klar, dass es zwei Angaben sind. */
  footer > div > div:last-child {
    display: flex !important;
    flex-direction: column !important;
    gap: 4px !important;
  }
}
