/* "Atem & Berührung": the motion layer. The still site lives in styles.css; everything that moves or responds lives here.
   One tempo: a slow breath. Reduced motion: the global rule in styles.css stops all of it. */

:root {
  --atem: 6s;
  --ausatmen: 1.2s;
  --ease-atem: cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes aufsteigen { from { opacity: 0; transform: translateY(0.4em); clip-path: inset(0 -0.5em 100% -0.5em); } to { clip-path: inset(-0.5em); } }
@keyframes einblenden { from { opacity: 0; transform: translateY(1rem); } }
@keyframes aufgehen { from { clip-path: inset(14% 22% 0 22% round 50% 50% 0 0 / 30% 30% 0 0); } to { clip-path: inset(0 round 50% 50% 0 0 / 40% 40% 0 0); } }
@keyframes einatmen-bild { from { transform: scale(1.1); } }
@keyframes raum-setzen { from { transform: scale(1.06); } }
@keyframes atmen { 0%, 100% { opacity: 0.7; scale: 0.94; } 50% { opacity: 1; scale: 1.04; } }
@keyframes licht-an { from { opacity: 0; transform: scale(0.55); } }
@keyframes strich { from { transform: scaleX(0); } }
@keyframes verblassen { to { opacity: 0; } }
@keyframes auftauchen { from { opacity: 0; transform: translateY(1.5rem); } }

/* Page arrival: the head's heading rises out of a mask, the rest follows in 0.12 s steps, the arch opens like light rising. */
:is(.page-head, .hero-text) h1 { animation: aufsteigen var(--ausatmen) var(--ease-atem) 0.1s backwards; }
:is(.page-head, .hero-text) .lead { animation: einblenden var(--ausatmen) var(--ease-atem) 0.22s backwards; }
:is(.page-head, .hero-text) p:not(.lead) { animation: einblenden var(--ausatmen) var(--ease-atem) 0.34s backwards; }
:is(.page-head, .hero-text) .btn-row { animation: einblenden var(--ausatmen) var(--ease-atem) 0.46s backwards; }
.bogen { animation: aufgehen 1.6s var(--ease-atem) 0.1s backwards; }
.bogen img { animation: einatmen-bild 2s var(--ease-atem) backwards; }
.hero-bild img { animation: raum-setzen 2.4s var(--ease-atem) backwards; }
/* Start: the film walks into her room instead (atem.js). It shows only once it really plays, over its own first frame. */
.hero:has(.hero-film) .hero-bild img { animation: none; }
.hero-film:not(.laeuft) { opacity: 0; }

/* The lamp breathes. */
.lamp::before { animation: atmen var(--atem) ease-in-out infinite; }

/* "Licht an" on the home page: her logo in the header turns open, once. */
body:has(#hero-titel, #hero-title) .wordmark img { animation: aufbluehen 1.8s var(--ease-atem) both; }

/* The header slides away and back (menue.js); anchors and the back-to-top button glide. */
.site-header { transition: translate 0.5s var(--ease-atem); }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }

/* Page changes: the header and the contact bar stay; the page fades out and the next one rises in. */
@view-transition { navigation: auto; }
.site-header { view-transition-name: kopf; }
.contact-bar { view-transition-name: leiste; }
::view-transition-old(root) { animation: verblassen 0.3s var(--ease-atem) both; }
::view-transition-new(root) { animation: auftauchen 0.6s var(--ease-atem) both; }
/* Leaving through the open menu (menue.js adds .geht): the sheet is its own layer and sweeps back out to the right
   while the next page rises in beneath it, so it never lies over the new hero. Same in-out curve as the menu sweep. */
.nav.geht { view-transition-name: menue; }
::view-transition-old(menue) { animation: menue-raus 0.45s cubic-bezier(0.65, 0, 0.35, 1) both; }
@keyframes menue-raus { to { transform: translateX(100%); } }

/* Micro-interactions */
a { transition: text-decoration-color 0.2s, text-underline-offset 0.3s var(--ease-atem); }
a:hover { text-underline-offset: 0.32em; }
.btn { transition: background-color 0.2s, border-color 0.2s, transform 0.5s var(--ease-atem); }
.btn:active { transform: scale(0.97); transition-duration: 0.1s; }
.btn .icon { transition: transform 0.4s var(--ease-atem); }
.btn:hover .icon { transform: rotate(-8deg) scale(1.08); }

/* Menu sheet (below 77.5rem): menue.js draws it as an SVG path that sweeps in and back out, and fades the links with --auf.
   The path box repeats the sheet's own box (fixed, inherited insets and size), so it still covers it when the links scroll. */
.nav-form { display: none; }
@media (max-width: 77.49rem) {
  .nav.geformt:popover-open { background: none; animation: none; }
  .nav.geformt:popover-open .nav-form { display: block; position: fixed; z-index: -1; inset: inherit; width: inherit; height: inherit; max-width: none; fill: var(--field); pointer-events: none; }
  .nav.geformt:popover-open > :not(.nav-form) { opacity: var(--auf); translate: calc((1 - var(--auf)) * 2rem) 0; }
  .nav.geformt::backdrop { opacity: var(--auf, 1); }
}

.nav li a { position: relative; }
.nav li a::after { content: ""; position: absolute; inset: auto 0 0 0; height: 2px; background: var(--glow); transform: scaleX(0); transform-origin: left; transition: transform 0.5s var(--ease-atem); }
.nav li a:hover::after { transform: scaleX(1); }
.nav a[aria-current="page"] { text-decoration: none; }
.nav a[aria-current="page"]::after { transform: scaleX(1); animation: strich 0.9s var(--ease-atem) 0.3s backwards; }

.therapie-liste li { position: relative; }
.therapie-liste li::after { content: ""; position: absolute; inset: -1px 0 auto 0; height: 1px; background: var(--glow); transform: scaleX(0); transform-origin: left; transition: transform 0.6s var(--ease-atem); }
.therapie-liste li:is(:hover, :focus-within)::after { transform: scaleX(1); }
.therapie-liste a { transition: transform 0.4s var(--ease-atem); }
.therapie-liste a:hover { transform: translateX(0.5rem); }

/* Scroll arrivals: content exhales into view and settles back when you scroll up.
   Only where scroll-driven animations exist; elsewhere everything is simply there. */
@keyframes ankommen { from { opacity: 0; transform: translateY(2rem); } }

@supports (animation-timeline: view()) {
  .section :is(h2, .lead, .zitat, .preisliste > div, .therapie-liste li, .stimmen li) {
    animation: ankommen var(--ease-atem) both;
    animation-timeline: view();
    animation-range: entry 5% cover 25%;
  }
}

/* Arrival on their own time (atem.js): secondary photos settle out of a slight zoom and crop like the hero (2.2 s),
   paragraphs breathe in by half a rem. Each plays once as it scrolls into view; .wartet holds the first frame until .da. */
@keyframes einatmen-foto { from { clip-path: inset(6% 5% round var(--radius)); transform: scale(1.06); } to { clip-path: inset(0 round var(--radius)); } }
@keyframes hauch { from { opacity: 0; translate: 0 0.5rem; } }
.foto.wartet { animation: einatmen-foto 2.2s var(--ease-atem) both paused; }
p.wartet { animation: hauch var(--ausatmen) var(--ease-atem) both paused; }
.wartet.da { animation-play-state: running; }

/* Blooms breathe. The bloom is a drawing (frangipani-bluete.svg): in a page head it turns open on load;
   her logo at the foot of the menu sheet does the same each time the sheet opens (the sheet hides it while closed), in a section as it scrolls in. */
@keyframes bluehen { 50% { scale: 1.02; } }
@keyframes aufbluehen { from { opacity: 0; scale: 0.8; rotate: -30deg; } }
:is(.bluete, .nav-bluete) { animation: bluehen var(--atem) ease-in-out 3.5s infinite; }
:is(.page-head .bluete, .nav-bluete) img { animation: aufbluehen 2.4s var(--ease-atem) 0.3s both; }
@supports (animation-timeline: view()) {
  .section .bluete { view-timeline-name: --bluete; }
  .section .bluete img { animation: aufbluehen linear both; animation-timeline: --bluete; animation-range: entry 0% cover 50%; }
}

/* Touch-light (every hero): a warm pool over her room. At rest it sits on the lamp glowing at the right of each photo and breathes. */
@property --licht-x { syntax: "<percentage>"; inherits: true; initial-value: 86%; }
@property --licht-y { syntax: "<percentage>"; inherits: true; initial-value: 52%; }
.hero { --licht-x: 72%; --licht-y: 20%; }
@media (min-width: 48rem) { .hero { --licht-x: 88%; --licht-y: 52%; } }
.hero.bildnis { --licht-x: 88%; --licht-y: 14%; } /* her portrait: the bright wall behind her shoulder, never her face */
@media (min-width: 48rem) { .hero.bildnis { --licht-x: 94%; --licht-y: 12%; } }
.hero::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  background: radial-gradient(circle 40vmin at var(--licht-x) var(--licht-y), color-mix(in srgb, var(--glow-core) 55%, transparent), color-mix(in srgb, var(--glow-core) 18%, transparent) 45%, transparent);
  mix-blend-mode: screen; /* soft-light barely registered on the bright photo (+11 luminance); screen lifts it visibly (+34) */
  transform-origin: var(--licht-x) var(--licht-y);
  pointer-events: none;
  transition: --licht-x 0.9s var(--ease-atem), --licht-y 0.9s var(--ease-atem);
  animation: licht-an 1.6s var(--ease-out) 0.15s backwards, atmen var(--atem) ease-in-out 1.75s infinite;
}
