@charset "UTF-8";

/* ===========================================================================
   LAYOUT BREAKPOINTS

   Expressed in em, not px. 1em here is the reader's browser font-size
   setting, so someone who enlarges text reaches the roomier layout at the
   viewport width where they actually need it. At the 16px default these
   land on the familiar round pixel values shown below.

     <= 38.75em   (620px)   phone      tighter gutters, phone padding on the
                                       schedule cells, flyer divider
     <= 47.5em    (760px)   compact    sections collapse to one column and
                                       the desktop side images swap for the
                                       inline mobile figures
     >= 47.5001em (760px)   wide       two-column practice/about. The .0001
                                       is deliberate: it leaves no width that
                                       fails both this and the <= 47.5em
                                       query, which a plain 48em would
     <= 57.5em    (920px)   nav        hamburger replaces the inline nav
     <= 62.5em    (1000px)  schedule   schedule stacks. Three columns cannot
                                       hold the venue address on one line
                                       much below this, so it stacks before
                                       it is forced to wrap

   Three are mirrored by matchMedia() in index.html and must move together:
     sectionPhoneLayout      (max-width: 47.5em)
     compactNavigation       (max-width: 57.5em)
     scheduleStackedLayout   (max-width: 62.5em)

   Also in use, none of them layout: (hover: hover) and (pointer: fine),
   prefers-reduced-motion, print.

   Numbers inside min()/clamp() calls (640, 720, 980, 1120, 1180) are content
   measures, not breakpoints, and have nothing to do with this scale.
   =========================================================================== */

@font-face {
  font-family: "Comfortaa";
  src: url("fonts/Comfortaa-VariableFont_wght.woff2") format("woff2");
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
}

@font-face {
  font-family: "Yeseva One";
  src: url("fonts/YesevaOne-Regular.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}

:root {
  --ivory: #fff4ea;
  --ivory-deep: #efcdbb;
  --blush: #f8d7c4;
  --terracotta: #a24f39;
  --charcoal: #3b2925;
  --muted: #775047;
  --about-text: #684139;
  --footer-text: #6d4a41;
  --white: #fffaf5;
  --line: rgba(162, 79, 57, 0.22);
  --menu-background: rgba(255, 244, 234, 0.96);
  /* In rem so the measure grows with the reader's text size; otherwise
     enlarged type is squeezed into columns that never widen. 73.75rem is
     the same 1180px at the 16px default. */
  --max-width: 73.75rem;
  --serif: "Yeseva One", Georgia, serif;
  --sans: "Comfortaa", Arial, Helvetica, sans-serif;
  --section-title-gap: 39px;
  --primary-title-size: clamp(2.625rem, 4.3vw, 3.875rem);
  --secondary-title-size: clamp(1.6875rem, 2.55vw, 2.25rem);
  --header-height: 2.5625rem;
  --header-pad: clamp(18px, 4.5vw, 60px);
  --body-text-size: 1rem;
  --schedule-text-size: clamp(1rem, 1.35vw, 1.1875rem);
  --side-image-width: clamp(210px, 27.9vw, 329px);
  --hero-slide-interval: 5.2s;

  /* Photographic treatment. Two deliberate variants: the default warm wash,
     and a slightly darker one for the practice photograph. */
  --photo-filter: saturate(0.78) sepia(0.19) contrast(0.97) brightness(1.03) hue-rotate(350deg);
  --photo-filter-deep: saturate(0.78) sepia(0.20) contrast(1) brightness(0.96) hue-rotate(350deg);

  --glow-shadow:
    0 0 5px rgba(255, 224, 164, 0.92),
    0 0 10px rgba(239, 164, 112, 0.72),
    0 0 17px rgba(162, 79, 57, 0.36);
}

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-height);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  min-width: 320px;
  color: var(--charcoal);
  background:
    radial-gradient(circle at 7% 8%, rgba(221, 160, 127, 0.34), transparent 23rem),
    radial-gradient(circle at 93% 19%, rgba(248, 215, 196, 0.84), transparent 28rem),
    var(--ivory);
  font-family: var(--sans);
  font-weight: 400;
  line-height: 1.6;
}

img {
  display: block;
  width: 100%;
}

a {
  color: inherit;
}

button,
a {
  -webkit-tap-highlight-color: transparent;
}

.brand:focus-visible,
.header-instagram:focus-visible,
.site-nav a:focus-visible,
.menu-toggle:focus-visible,
.outline-button:focus-visible,
.privacy-trigger:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

/* The skip link receives programmatic focus, so no ring is needed here. */
#main:focus {
  outline: none;
}

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100%;
  height: var(--header-height);
  padding-top: 0;
  padding-bottom: 0;
  padding-left: max(var(--header-pad), env(safe-area-inset-left));
  padding-right: max(var(--header-pad), env(safe-area-inset-right));
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: var(--white);
  transition:
    color 0.35s ease,
    background-color 0.35s ease;
}

.site-header.is-scrolled,
.site-header.is-menu-open {
  color: var(--charcoal);
  background: var(--menu-background);
}

/* Sits over the brand wordmark, invisible until it takes keyboard focus. */
.skip-link {
  position: absolute;
  top: 50%;
  left: max(var(--header-pad), env(safe-area-inset-left));
  z-index: 110;
  padding: 7px 16px;
  color: var(--charcoal);
  background: var(--white);
  border-radius: 999px;
  box-shadow: 0 6px 20px rgba(59, 41, 37, 0.28);
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.085em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transform: translateY(-50%);
  opacity: 0;
  pointer-events: none;
}

.skip-link:focus-visible {
  opacity: 1;
  pointer-events: auto;
  outline: 2px solid var(--charcoal);
  outline-offset: 3px;
}

.brand,
.site-nav a {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.085em;
  -webkit-text-stroke: 0.2px currentColor;
}

/* The wordmark is uppercased in CSS, not in the markup. */
.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.brand-name {
  text-transform: uppercase;
}

.brand-cluster {
  display: inline-flex;
  align-items: center;
  gap: 13px;
}

.header-instagram {
  position: relative;
  top: -1px;
  flex: none;
  width: 15.3px;
  height: 15.3px;
  display: block;
  text-decoration: none;
  transition: opacity 0.2s ease;
}

.header-instagram::before,
.header-instagram::after {
  content: "";
  position: absolute;
  inset: 0;
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  transition: opacity 0.35s ease;
}

.header-instagram::before {
  background-image: url("pic/Instagram_Glyph_White.svg");
  opacity: 1;
}

.header-instagram::after {
  background-image: url("pic/Instagram_Glyph_Black.svg");
  opacity: 0;
}

.site-header.is-scrolled .header-instagram::before,
.site-header.is-menu-open .header-instagram::before {
  opacity: 0;
}

.site-header.is-scrolled .header-instagram::after,
.site-header.is-menu-open .header-instagram::after {
  opacity: 1;
}

@media (hover: hover) and (pointer: fine) {
  .header-instagram:hover {
    opacity: 0.68;
  }
}

.site-nav {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2.3vw, 34px);
}

.site-nav a {
  position: relative;
  padding: 5px 0;
  text-decoration: none;
  text-transform: uppercase;
}

.site-nav a::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 0;
  height: 1px;
  background: currentColor;
  transform: translateX(-50%);
  transition: width 0.25s ease;
}

.site-nav a.is-active::after {
  width: 100%;
}

@media (hover: hover) and (pointer: fine) {
  .site-nav a:hover::after {
    width: 100%;
  }
}

.menu-toggle {
  display: none;
  width: 44px;
  height: 44px;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.menu-toggle span {
  display: block;
  width: 22px;
  height: 1px;
  margin: 6px auto;
  background: currentColor;
  transition: transform 0.25s ease;
}

.menu-toggle.is-open span:first-child {
  transform: translateY(3.5px) rotate(45deg);
}

.menu-toggle.is-open span:last-child {
  transform: translateY(-3.5px) rotate(-45deg);
}

/* No element bleeds past the viewport any more, so this is only a guard.
   overflow-x: clip avoids creating a scroll container the way hidden does. */
main {
  overflow-x: clip;
}

.section-shell {
  width: min(calc(100% - 48px), var(--max-width));
  margin-inline: auto;
}

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  isolation: isolate;
  overflow: hidden;
  color: var(--white);
  background: var(--terracotta);
}

.hero-slides,
.hero-overlay,
.hero-slide {
  position: absolute;
  inset: 0;
}

.hero-slides {
  z-index: -3;
}

.hero-slide {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transform: scale(1.035);
  filter: var(--photo-filter);
  /* Outgoing slide: fade out, then snap the zoom back once it is invisible,
     so it is never seen shrinking mid-fade. */
  transition:
    opacity 1.5s ease,
    transform 0s linear 1.5s;
}

.hero-canvas {
  display: block;
}

.hero-slide.is-current {
  opacity: 1;
  transform: scale(1.08);
  /* Zoom finishes exactly as the next slide is due. */
  transition:
    opacity 1.5s ease,
    transform var(--hero-slide-interval) ease;
}

.hero-overlay {
  z-index: -2;
  background:
    linear-gradient(180deg, rgba(162, 79, 57, 0.10), rgba(59, 41, 37, 0.42)),
    linear-gradient(90deg, rgba(255, 250, 245, 0.14), rgba(221, 160, 127, 0.32) 48%, rgba(162, 79, 57, 0.18)),
    rgba(162, 79, 57, 0.10);
}

.hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  z-index: -1;
  height: 26%;
  background: linear-gradient(180deg, transparent, rgba(59, 41, 37, 0.31));
}

.hero-content {
  width: min(97%, 1360px);
  padding: 110px 12px 70px;
  text-align: center;
}

.hero h1,
.practice-copy h2,
.schedule-copy h2,
.about-copy h2,
.contact-heading h2 {
  font-family: var(--serif);
  font-size: var(--primary-title-size);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.018em;
}

.hero h1 {
  max-width: 1120px;
  margin-inline: auto;
  font-size: clamp(3.25rem, 5.6vw, 5.375rem);
  text-wrap: balance;
  text-shadow: 0 8px 34px rgba(59, 41, 37, 0.24);
}

.hero-subtitle,
.practice-body-copy h3 {
  font-family: var(--serif);
  font-size: var(--secondary-title-size);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.014em;
}

.hero-subtitle {
  max-width: 920px;
  margin: 0.72em auto 0;
  color: inherit;
  text-align: center;
  text-wrap: balance;
  text-shadow: 0 8px 34px rgba(59, 41, 37, 0.24);
}

.hero-body {
  margin-top: clamp(32px, 4vw, 48px);
}

.outline-button {
  min-width: 8.875rem;
  min-height: 2.875rem;
  padding: 0 24px;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  border: 1px solid rgba(255, 250, 245, 0.86);
  border-radius: 999px;
  text-decoration: none;
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition:
    background-color 0.25s ease,
    color 0.25s ease;
}

/* Prevent iOS long-press text-selection flash on button-like links while
   keeping the native link context menu available. */
.outline-button,
.location-link {
  -webkit-user-select: none;
  user-select: none;
}

@media (hover: hover) and (pointer: fine) {
  .outline-button:hover {
    color: var(--charcoal);
    background: var(--white);
  }
}

.practice-section {
  padding: 96px 0;
  background: var(--blush);
}

.practice-layout {
  display: grid;
  grid-template-columns: 0.82fr 1.18fr;
  gap: clamp(48px, 6vw, 80px);
  align-items: center;
}

.practice-image {
  position: relative;
  width: 100%;
  overflow: hidden;
}

.practice-image img {
  width: 100%;
  height: auto;
  object-fit: contain;
  filter: var(--photo-filter-deep);
  transition: transform 0.9s ease;
}

@media (hover: hover) and (pointer: fine) {
  .practice-image:hover img {
    transform: scale(1.015);
  }
}

.practice-copy h2,
.schedule-copy h2,
.about-copy h2,
.contact-heading h2 {
  margin-bottom: var(--section-title-gap);
}

.practice-body-copy {
  max-width: 640px;
  color: var(--muted);
  font-size: var(--body-text-size);
  line-height: 1.8;
  text-align: left;
  hyphens: none;
  -webkit-hyphens: none;
  word-break: normal;
  overflow-wrap: normal;
}

.practice-body-copy p + p {
  margin-top: 1.8em;
}

.practice-body-copy h3 {
  margin: clamp(38px, 4vw, 52px) 0 20px;
  color: var(--charcoal);
  text-align: left;
}

.practice-subsection + .practice-subsection {
  margin-top: clamp(38px, 4vw, 52px);
}

.schedule-section {
  padding: 105px 0 112px;
  background: var(--white);
}

.schedule-copy {
  max-width: 980px;
  text-align: center;
}

.schedule-details {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  font-family: var(--sans);
  font-size: var(--schedule-text-size);
  line-height: 1.35;
}

.schedule-details p {
  min-height: 7.75rem;
  margin: 0;
  padding: 20px clamp(24px, 3.2vw, 44px);
  display: flex;
  justify-content: center;
  align-items: center;
  color: var(--charcoal);
  font-family: inherit;
  font-size: inherit;
  font-weight: 400;
  line-height: inherit;
  text-align: center;
}

.schedule-details p + p {
  border-left: 1px solid var(--line);
}

.schedule-invitation {
  font-style: italic;
}

.schedule-time {
  flex-direction: column;
  gap: 0.3em;
}

/* Each of these is authored as one line and must stay that way. Measured
   against Comfortaa 400, the widest is "Im Westfeld 19, 4055 Basel" at
   13.32em, which clears every column width the layout produces. */
.schedule-time span,
.schedule-venue,
.schedule-address {
  white-space: nowrap;
}

/* Below roughly 17.5em of viewport the widest line genuinely cannot fit at
   the reader's own font size, so release it rather than overflow. The
   non-breaking spaces in the markup then decide where it splits. */
@media (max-width: 17.5em) {
  .schedule-time span,
  .schedule-venue,
  .schedule-address {
    white-space: normal;
  }
}

.schedule-levels {
  display: block;
  margin: 0 0 0.7em;
  color: var(--charcoal);
  font-family: var(--sans);
  font-size: var(--schedule-text-size);
  font-weight: 400;
  line-height: 1.35;
  text-align: center;
}

.schedule-price {
  margin: 30px 0 0;
  color: var(--charcoal);
  font-family: var(--sans);
  font-size: var(--schedule-text-size);
  font-weight: 400;
  line-height: 1.35;
  text-align: center;
}

.schedule-details p,
.schedule-details a,
.schedule-details span,
.schedule-details em {
  font-family: var(--sans);
  font-size: var(--schedule-text-size);
  line-height: 1.35;
}

.schedule-highlight {
  display: inline-block;
  color: inherit;
  text-decoration: none;
  font-weight: 400;
  text-shadow: none;
  transition: text-shadow 0.2s ease;
}

.schedule-location-link {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.18em;
}

.schedule-venue,
.schedule-address {
  display: block;
}


.schedule-highlight:focus-visible {
  outline: 2px solid var(--terracotta);
  outline-offset: 5px;
}

@media (hover: hover) and (pointer: fine) {
  .schedule-highlight:hover {
    text-shadow: var(--glow-shadow);
  }
}

/* Desktop class information is one five-step reveal sequence. Scrolling down:
   levels -> left -> center -> right -> price. Scrolling up reverses the order.
   The flyer is deliberately not part of this sequence; it uses the normal
   position-based [data-reveal] behavior on its own. */
@media (min-width: 62.5001em) {
  .schedule-levels.is-visible.reveal-from-bottom {
    transition-delay: 0s;
  }

  .schedule-details p:nth-child(1).is-visible.reveal-from-bottom {
    transition-delay: 0.08s;
  }

  .schedule-details p:nth-child(2).is-visible.reveal-from-bottom {
    transition-delay: 0.16s;
  }

  .schedule-details p:nth-child(3).is-visible.reveal-from-bottom {
    transition-delay: 0.24s;
  }

  .schedule-price.is-visible.reveal-from-bottom {
    transition-delay: 0.32s;
  }

  .schedule-price.is-visible.reveal-from-top {
    transition-delay: 0s;
  }

  .schedule-details p:nth-child(3).is-visible.reveal-from-top {
    transition-delay: 0.08s;
  }

  .schedule-details p:nth-child(2).is-visible.reveal-from-top {
    transition-delay: 0.16s;
  }

  .schedule-details p:nth-child(1).is-visible.reveal-from-top {
    transition-delay: 0.24s;
  }

  .schedule-levels.is-visible.reveal-from-top {
    transition-delay: 0.32s;
  }
}

.social-links a:nth-child(2) {
  --contact-reveal-delay: 0.08s;
}

.social-links a:nth-child(3) {
  --contact-reveal-delay: 0.16s;
}

.location-link[data-reveal] {
  --contact-reveal-delay: 0.24s;
}

.social-links a[data-reveal],
.location-link[data-reveal] {
  transition-property: opacity, transform, color, background-color, border-color;
  transition-duration: 0.85s, 0.85s, 0.25s, 0.25s, 0.25s;
  transition-timing-function: ease;
  transition-delay:
    var(--contact-reveal-delay, 0s),
    var(--contact-reveal-delay, 0s),
    0s,
    0s,
    0s;
}

.schedule-levels:not(.is-visible),
.schedule-details p:not(.is-visible),
.schedule-price:not(.is-visible),
.flyer-thumb-row:not(.is-visible) {
  transition-delay: 0s;
}

.social-links a[data-reveal]:not(.is-visible),
.location-link[data-reveal]:not(.is-visible) {
  --contact-reveal-delay: 0s;
}

.about-section {
  padding: 105px 0;
  background: var(--blush);
}

.about-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(210px, 0.574fr);
  gap: clamp(48px, 6vw, 80px);
  align-items: center;
}

.about-copy {
  text-align: right;
}

.about-copy p {
  color: var(--about-text);
  font-size: var(--body-text-size);
  line-height: 1.8;
  text-align: right;
  hyphens: none;
  -webkit-hyphens: none;
  word-break: normal;
  overflow-wrap: normal;
}

.about-body-copy p + p {
  margin-top: 1.8em;
}

.about-gallery {
  position: relative;
  width: min(100%, 329px);
  min-height: clamp(301px, 33.6vw, 413px);
  justify-self: start;
}

.about-main {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.about-main img {
  height: 100%;
  object-fit: cover;
  filter: var(--photo-filter);
}

.contact-section {
  padding: 90px 0 100px;
  background: var(--white);
}

.contact-heading {
  width: min(calc(100% - 48px), var(--max-width));
  margin: 0 auto var(--section-title-gap);
  text-align: center;
}

.contact-heading p {
  max-width: 640px;
  margin: var(--section-title-gap) auto 0;
  color: var(--muted);
  font-size: var(--body-text-size);
  line-height: 1.8;
}

.contact-methods {
  display: block;
  margin-top: 0.55em;
}

.contact-layout {
  max-width: 720px;
}

.contact-card {
  min-height: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 28px;
  color: var(--charcoal);
  text-align: center;
}

.social-links {
  width: 180px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.social-links a {
  position: relative;
  flex: 0 0 46px;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  color: var(--charcoal);
  background: transparent;
  border: 1px solid var(--charcoal);
  border-radius: 50%;
  transition:
    color 0.25s ease,
    background-color 0.25s ease,
    border-color 0.25s ease;
}

/* :active covers touch, where the fill appears on press and releases on
   lift. :hover is confined to pointer devices further down, because on
   touch it latches after a tap and has to be tapped away. */
.social-links a:focus-visible,
.social-links a:active {
  color: var(--white);
  background: var(--charcoal);
  border-color: var(--charcoal);
}

/* Two stacked pseudo-elements per link: ::before is the resting icon,
   ::after the lit one, cross-faded. Using background images rather than
   <img> keeps the browser's image handling (drag ghost, image context menu,
   selection box) away from them entirely. */
.social-links a::before,
.social-links a::after {
  content: "";
  grid-area: 1 / 1;
  width: 22px;
  height: 22px;
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  transition: opacity 0.25s ease;
}

.social-links a::after {
  opacity: 0;
}

.social-links a:focus-visible::before,
.social-links a:active::before {
  opacity: 0;
}

.social-links a:focus-visible::after,
.social-links a:active::after {
  opacity: 1;
}

/* Brand marks: two official files, swapped whole. Never recoloured. */
.social-whatsapp::before {
  background-image: url("pic/Digital_Glyph_Black_RGB_2026.svg");
}

.social-whatsapp::after {
  background-image: url("pic/Digital_Glyph_White_RGB_2026.svg");
}

.social-instagram::before {
  background-image: url("pic/Instagram_Glyph_Black.svg");
}

.social-instagram::after {
  background-image: url("pic/Instagram_Glyph_White.svg");
}

/* Generic icons carry no licence restrictions, so one file is tinted twice
   rather than shipping a second copy. */
.social-email::before,
.social-email::after {
  background-image: url("pic/email.svg");
}

.social-email::before,
.location-link::before {
  filter: brightness(0) invert(0);
}

.social-email::after {
  filter: brightness(0) invert(1);
}

.location-link {
  min-width: 11.25rem;
  min-height: 2.875rem;
  padding: 0 20px;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  color: var(--charcoal);
  background: transparent;
  border: 1px solid var(--charcoal);
  border-radius: 999px;
  text-decoration: none;
  font-size: var(--body-text-size);
  font-weight: 400;
  transition:
    color 0.25s ease,
    background-color 0.25s ease,
    border-color 0.25s ease;
}

.location-link:focus-visible,
.location-link:active {
  color: var(--white);
  background: var(--charcoal);
  border-color: var(--charcoal);
}

.location-link::before {
  content: "";
  flex: none;
  width: 20px;
  height: 20px;
  background-image: url("pic/location.svg");
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  transition: filter 0.25s ease;
}

/* invert(0) in the resting rule above is not redundant: a filter list only
   interpolates when both sides hold the same functions in the same order,
   so naming invert() twice is what makes this fade rather than snap. */
.location-link:focus-visible::before,
.location-link:active::before {
  filter: brightness(0) invert(1);
}

.social-links a:focus-visible,
.location-link:focus-visible {
  outline: 2px solid var(--charcoal);
  outline-offset: 4px;
}

/* A tap is usually shorter than the 0.25s fade, so the press state would
   barely begin before it was released. Snap it on, let it fade off. */
.social-links a:active,
.location-link:active,
.social-links a:active::before,
.social-links a:active::after,
.location-link:active::before {
  transition-duration: 0s;
}

/* Pointer devices only, matching .schedule-highlight and .flyer-thumb-trigger. */
@media (hover: hover) and (pointer: fine) {
  .social-links a:hover,
  .location-link:hover {
    color: var(--white);
    background: var(--charcoal);
    border-color: var(--charcoal);
  }

  .social-links a:hover::before {
    opacity: 0;
  }

  .social-links a:hover::after {
    opacity: 1;
  }

  .location-link:hover::before {
    filter: brightness(0) invert(1);
  }
}

.site-footer {
  height: var(--header-height);
  padding: 0 16px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: var(--footer-text);
  background: var(--ivory-deep);
  text-align: center;
  font-family: var(--sans);
  font-size: clamp(0.5rem, 1.7vw, 0.75rem);
  line-height: 1.15;
  letter-spacing: 0.035em;
}

.footer-content {
  max-width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 2px 10px;
}

.privacy-trigger {
  padding: 0;
  color: inherit;
  background: transparent;
  border: 0;
  font: inherit;
  letter-spacing: inherit;
  text-decoration: underline;
  text-underline-offset: 0.18em;
  cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
  .privacy-trigger:hover {
    color: var(--charcoal);
  }
}

[data-reveal] {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.85s ease,
    transform 0.85s ease;
}

.js.reveal-ready [data-reveal] {
  opacity: 0;
}

.js.reveal-ready [data-reveal].reveal-from-bottom {
  transform: translateY(28px);
}

.js.reveal-ready [data-reveal].reveal-from-top {
  transform: translateY(-28px);
}

.js.reveal-ready [data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

.mobile-inline-image {
  display: none;
}

@media (max-width: 57.5em),
       (pointer: coarse) and (orientation: landscape) and (max-height: 47.5em) {
  .menu-toggle {
    display: block;
  }

  .site-nav {
    position: fixed;
    top: var(--header-height);
    right: 0;
    left: 0;
    width: 100%;
    margin: 0;
    padding: 17px 16px 16px;
    flex-direction: column;
    gap: 0;
    color: var(--charcoal);
    background: var(--menu-background);
    box-shadow: 0 24px 55px rgba(59, 41, 37, 0.15);
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    transform: translateY(-10px);
    transition:
      opacity 0.25s ease,
      transform 0.25s ease,
      visibility 0s linear 0.25s;
  }

  .site-nav.is-open {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
    transform: none;
    transition-delay: 0s;
  }

  .site-nav a {
    width: max-content;
    padding: 12px 0;
    align-self: center;
    text-align: center;
  }

  /* Without JavaScript the toggle cannot open anything, so the panel would
     be unreachable. Hide the dead control and lay the links out as a static
     wrapping row instead. The .js class is set in <head> before first paint,
     so scripted visits never see this. */
  html:not(.js) .menu-toggle {
    display: none;
  }

  html:not(.js) .site-header {
    height: auto;
    min-height: var(--header-height);
    flex-wrap: wrap;
    padding-block: 8px;
    row-gap: 4px;
  }

  html:not(.js) .site-nav {
    position: static;
    width: auto;
    padding: 0;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0 clamp(10px, 3vw, 22px);
    color: inherit;
    background: none;
    box-shadow: none;
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
    transform: none;
  }

  html:not(.js) .site-nav a {
    padding: 4px 0;
  }
}

/* 760.02px rather than 761px so no fractional viewport width can fall
   between this query and the max-width: 760px one below. */
@media (min-width: 47.5001em) {
  .practice-layout,
  .about-layout {
    gap: clamp(32px, 5vw, 80px);
  }

  /* The image column simply stretches to the height of the copy column.
     This replaces the JavaScript measure-and-fit routine entirely. */
  .practice-layout {
    grid-template-columns: var(--side-image-width) minmax(0, 1fr);
    align-items: stretch;
  }

  .practice-image img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
  }

  .practice-copy,
  .practice-body-copy,
  .practice-subsection,
  .practice-subsection-text {
    width: 100%;
    max-width: none;
    min-width: 0;
  }

  .about-layout {
    grid-template-columns: minmax(0, 1fr) var(--side-image-width);
    align-items: stretch;
  }

  .about-gallery {
    width: 100%;
    min-height: 0;
    justify-self: end;
  }

  .about-main img {
    width: 100%;
    height: 100%;
    object-position: 44% center;
  }
}

@media (max-width: 47.5em),
       (pointer: coarse) and (orientation: landscape) and (max-height: 47.5em) {
  :root {
    --section-title-gap: 38px;
    --primary-title-size: clamp(2.375rem, 10vw, 2.75rem);
    --secondary-title-size: clamp(1.4375rem, 6.2vw, 1.6875rem);
  }

  .hero-content {
    width: 100%;
    padding-inline: 16px;
  }

  .hero h1 {
    max-width: 94vw;
    font-size: clamp(2.875rem, 11.5vw, 3.625rem);
    letter-spacing: -0.024em;
  }

  .hero-subtitle {
    max-width: 92vw;
    line-height: 1.1;
  }

  .practice-section {
    padding: 0;
    overflow: visible;
  }

  .practice-layout {
    position: relative;
    width: 100%;
    max-width: none;
    min-height: 0;
    margin-inline: 0;
    padding: 58px 22px 64px;
    display: block;
  }

  .practice-image,
  .about-gallery {
    display: none;
  }

  .practice-copy,
  .about-copy {
    display: block;
  }

  .practice-copy h2,
  .about-copy h2 {
    margin-bottom: 0;
  }

  .practice-body-copy,
  .about-copy p {
    margin-top: 0;
  }

  .practice-subsection + .practice-subsection {
    margin-top: 38px;
  }

  .mobile-inline-image {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 5 / 2;
    height: auto;
    margin: var(--section-title-gap) 0 26px;
    overflow: hidden;
    contain: paint;
    isolation: isolate;
    clip-path: inset(0);
    transform: translateZ(0);
  }

  .mobile-inline-image img {
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: cover;
    transform-origin: center;
    will-change: transform;
    backface-visibility: hidden;
  }

  .mobile-practice-image img {
    position: absolute;
    top: 50%;
    left: 0;
    height: auto;
    object-fit: initial;
    object-position: center;
    transform: translate3d(0, calc(-50% + var(--reverse-scroll-y, 0px)), 0);
    filter: var(--photo-filter-deep);
  }

  .about-section {
    padding: 0;
    overflow: visible;
  }

  .about-layout {
    position: relative;
    width: 100%;
    max-width: none;
    min-height: 0;
    margin-inline: 0;
    padding: 58px 22px 64px;
    display: block;
  }

  .about-copy p {
    color: var(--about-text);
  }

  .mobile-about-image img {
    object-position: 44% 30%;
    filter: var(--photo-filter);
    transform: translate3d(0, var(--reverse-scroll-y, 0px), 0) scale(1.02);
  }

  .contact-desktop-break {
    display: none;
  }
}

/* Below this width three columns cannot hold "Im Westfeld 19, 4055 Basel"
   on one line, so the schedule stacks instead of wrapping mid-address.
   Kept in sync with scheduleStackedLayout in index.html. */
@media (max-width: 62.5em),
       (pointer: coarse) and (orientation: landscape) and (max-height: 47.5em) {
  .schedule-details {
    grid-template-columns: 1fr;
  }

  .schedule-details p {
    min-height: auto;
    transition-delay: 0s !important;
  }

  /* In the stacked Classes layout, every content block is separated by the
     same short divider: levels | time | location | invitation | price | flyer. */
  .schedule-levels {
    margin-bottom: 0;
    padding-bottom: 20px;
  }

  .schedule-details p,
  .schedule-price,
  .flyer-thumb-row {
    position: relative;
  }

  .schedule-details p + p {
    border-left: 0;
  }

  .schedule-details p:first-child::before,
  .schedule-details p + p::before,
  .schedule-price::before,
  .flyer-thumb-row::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    width: 25%;
    height: 1px;
    background: var(--line);
    transform: translateX(-50%);
  }

  .schedule-price {
    margin-top: 0;
    padding: 20px 0;
  }

  /* Use the same vertical rhythm around the price-to-flyer divider as the
     dividers between the stacked schedule items above. */
  .flyer-thumb-row {
    margin-top: 0;
    padding: 20px 16px 0;
  }
}

@media (max-width: 38.75em),
       (pointer: coarse) and (orientation: landscape) and (max-height: 38.75em) {
  :root {
    --header-pad: 16px;
  }

  .schedule-copy,
  .contact-layout {
    width: min(calc(100% - 30px), var(--max-width));
  }

  .practice-layout,
  .about-layout {
    width: 100%;
  }

  .hero-content {
    padding-top: 95px;
  }

  .schedule-section,
  .contact-section {
    padding-top: 68px;
    padding-bottom: 75px;
  }

  .contact-heading {
    width: min(calc(100% - 30px), var(--max-width));
    margin-bottom: var(--section-title-gap);
  }

  .schedule-details p {
    padding: 22px 16px;
  }

  .contact-card {
    gap: 24px;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

@media print {
  .js.reveal-ready [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
  }

  .site-header {
    position: static;
    color: var(--charcoal);
    background: var(--white);
  }

  .menu-toggle,
  .skip-link {
    display: none !important;
  }
}


/* Privacy notice */
.privacy-dialog {
  position: fixed;
  top: 50%;
  left: 50%;
  width: min(90vw, 42rem);
  max-height: min(86vh, 44rem);
  max-height: min(86dvh, 44rem);
  margin: 0;
  padding: 0;
  border: 0;
  color: var(--charcoal);
  background: transparent;
  overflow: visible;
  transform: translate(-50%, -50%);
}

.privacy-dialog::backdrop {
  background: rgba(59, 41, 37, 0.44);
  -webkit-backdrop-filter: blur(10px) saturate(0.86);
  backdrop-filter: blur(10px) saturate(0.86);
}

.privacy-dialog-panel {
  position: relative;
  max-height: min(86vh, 44rem);
  max-height: min(86dvh, 44rem);
  padding:
    var(--privacy-panel-pad-top, clamp(32px, 5vw, 46px))
    clamp(24px, 5.5vw, 48px)
    var(--privacy-panel-pad-bottom, clamp(32px, 5vw, 46px));
  overflow: hidden;
  color: var(--charcoal);
  background: var(--ivory);
  border: 1px solid var(--line);
  box-shadow: 0 28px 90px rgba(59, 41, 37, 0.26);
  text-align: center;
}

.privacy-dialog h2,
.privacy-dialog h3 {
  font-family: var(--serif);
  font-size: var(--privacy-heading-size, clamp(1.35rem, 3.5vw, 1.75rem));
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.014em;
}

.privacy-dialog h2 {
  margin: 0 36px var(--privacy-title-gap, 24px);
}

.privacy-dialog h3 {
  margin-bottom: var(--privacy-subtitle-gap, 14px);
}

.privacy-dialog p {
  margin: 0;
  color: var(--muted);
  font-family: var(--sans);
  font-size: var(--privacy-body-size, var(--body-text-size));
  font-weight: 400;
  line-height: 1.8;
  text-align: center;
}

.privacy-divider {
  width: 25%;
  height: 1px;
  margin: var(--privacy-divider-gap, 26px) auto;
  background: var(--line);
}

/* Treat a short coarse-pointer landscape viewport as a phone too. Rotating a
   phone should not silently switch the page back to desktop-sized controls. */
@media (max-width: 38.75em),
       (pointer: coarse) and (orientation: landscape) and (max-height: 38.75em) {
  .privacy-dialog {
    width: min(calc(100vw - 40px), 42rem);
    max-height: calc(100vh - 20px);
    max-height: calc(100dvh - 20px);
  }

  .privacy-dialog-panel {
    max-height: calc(100vh - 20px);
    max-height: calc(100dvh - 20px);
    padding:
      var(--privacy-panel-pad-top, 34px)
      22px
      var(--privacy-panel-pad-bottom, 30px);
  }

  .privacy-dialog h2 {
    margin-bottom: var(--privacy-title-gap, 22px);
  }

  .privacy-divider {
    margin-block: var(--privacy-divider-gap, 22px);
  }
}

/* Shared flyer lightbox */
.flyer-dialog {
  position: fixed;
  top: 50%;
  left: 50%;
  width: fit-content;
  max-width: 94vw;
  max-height: 94vh;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: visible;
  transform: translate(-50%, -50%);
}

.flyer-dialog::backdrop {
  background: rgba(59, 41, 37, 0.44);
  -webkit-backdrop-filter: blur(10px) saturate(0.86);
  backdrop-filter: blur(10px) saturate(0.86);
}

.flyer-dialog-panel {
  position: relative;
  width: fit-content;
  max-width: 94vw;
  max-height: 92vh;
  padding: 0;
  overflow: hidden;
  background: transparent;
  box-shadow: 0 28px 90px rgba(59, 41, 37, 0.34);
}

.flyer-dialog-close {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  width: 31px;
  height: 31px;
  padding: 0;
  border: 1px solid rgba(255, 250, 245, 0.82);
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--white);
  background: rgba(59, 41, 37, 0.62);
  -webkit-appearance: none;
  appearance: none;
  box-shadow: none;
  font-size: 0;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

/* Draw the close mark instead of using a font glyph. Two crossing strokes are
   mathematically centered, so the X does not inherit a font's optical offset. */
.flyer-dialog-close::before,
.flyer-dialog-close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 13px;
  height: 1px;
  background: currentColor;
  transform-origin: center;
}

.flyer-dialog-close::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.flyer-dialog-close::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

@media (hover: hover) and (pointer: fine) {
  .flyer-dialog-close:hover {
    background: rgba(59, 41, 37, 0.88);
    border-color: var(--white);
  }
}

/* The box is derived from the flyer's aspect ratio, not from whichever
   source happens to be loaded, so swapping the placeholder for the full
   image cannot resize the dialog. */
.flyer-dialog-image {
  display: block;
  width: min(94vw, calc(92vh * 900 / 1274));
  height: auto;
  aspect-ratio: 900 / 1274;
  object-fit: contain;
  transition: filter 0.45s ease, transform 0.45s ease;
}

/* data-full-src is removed the moment the real image is swapped in, so it
   doubles as a "still showing the placeholder" flag. Blurring it makes the
   upscaled thumbnail read as deliberate rather than broken. */
.flyer-dialog-image[data-full-src] {
  filter: blur(5px);
  transform: scale(1.04);
}

.flyer-dialog-close:focus-visible,
[data-open-flyer]:focus-visible {
  outline: 2px solid var(--terracotta);
  outline-offset: 4px;
}

@media (max-width: 38.75em),
       (pointer: coarse) and (orientation: landscape) and (max-height: 38.75em) {
  /* Same visual treatment as desktop, only smaller. Whole-pixel dimensions
     keep the circular edge and the two X strokes centered symmetrically. */
  .flyer-dialog-close {
    top: 8px;
    left: 8px;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 1px solid rgba(255, 250, 245, 0.82);
    border-radius: 50%;
    color: var(--white);
    background: rgba(59, 41, 37, 0.62);
    box-shadow: none;
    -webkit-appearance: none;
    appearance: none;
    -webkit-tap-highlight-color: transparent;
  }

  .flyer-dialog-close::before,
  .flyer-dialog-close::after {
    width: 11px;
    height: 1px;
  }

  /* iOS may mark the first dialog control as focus-visible on opening, which
     otherwise draws a second circle around the actual close button. Touch
     users get the same single-circle appearance as desktop mouse users. */
  .flyer-dialog-close:focus-visible {
    outline: 0;
  }
}

/* Variant: centered full-flyer thumbnail */

.flyer-thumb-row {
  margin-top: 30px;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.flyer-thumb-trigger {
  padding: 0;
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 14px;
  color: var(--charcoal);
  background: transparent;
  border: 0;
  font-family: var(--sans);
  font-size: var(--schedule-text-size);
  font-weight: 400;
  line-height: 1.35;
  text-align: center;
  text-shadow: none;
  cursor: pointer;
  transition: text-shadow 0.2s ease;
}

.flyer-thumb-trigger img {
  display: block;
  width: clamp(108px, 11vw, 132px);
  height: auto;
  object-fit: contain;
  object-position: center;
  box-shadow: 0 12px 30px rgba(59, 41, 37, 0.18);
}

.flyer-thumb-trigger strong {
  display: block;
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
}

@media (hover: hover) and (pointer: fine) {
  .flyer-thumb-trigger:hover {
    text-shadow: var(--glow-shadow);
  }
}

@media (max-width: 38.75em),
       (pointer: coarse) and (orientation: landscape) and (max-height: 38.75em) {
  .flyer-thumb-trigger {
    gap: 12px;
  }

  .flyer-thumb-trigger img {
    width: 108px;
  }
}

/* Keep the stacked Classes dividers on one consistent vertical rhythm.
   This block intentionally comes after the base flyer styles so their
   desktop margin cannot override the stacked layout. */
@media (max-width: 62.5em),
       (pointer: coarse) and (orientation: landscape) and (max-height: 47.5em) {
  .schedule-levels {
    padding-bottom: 20px;
  }

  .schedule-details p,
  .schedule-price {
    padding-block: 20px;
  }

  .flyer-thumb-row {
    margin-top: 0;
    padding-top: 20px;
  }
}

@media (max-width: 38.75em),
       (pointer: coarse) and (orientation: landscape) and (max-height: 38.75em) {
  .schedule-levels {
    padding-bottom: 22px;
  }

  .schedule-details p,
  .schedule-price {
    padding-block: 22px;
  }

  .flyer-thumb-row {
    padding-top: 22px;
  }
}

/* Phone landscape: keep heading scale tied to the short viewport rather than
   the much wider landscape width. Body copy remains at its normal size. */
@media (pointer: coarse) and (orientation: landscape) and (max-height: 38.75em) {
  :root {
    --section-title-gap: 28px;
    --primary-title-size: clamp(2rem, 8vh, 2.375rem);
    --secondary-title-size: clamp(1.25rem, 5.5vh, 1.5rem);
  }

  .hero h1 {
    font-size: clamp(2.25rem, 10vh, 2.75rem);
  }

  .hero-content {
    padding-top: 62px;
    padding-bottom: 42px;
  }

  .hero-body {
    margin-top: 22px;
  }
}


/* iPhone landscape safe areas. viewport-fit=cover lets section backgrounds fill
   the full screen; these paddings keep interactive/text content clear of the
   notch and rounded corners without recreating white browser gutters. */
@media (pointer: coarse) and (orientation: landscape) and (max-height: 38.75em) {
  .hero-content {
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
  }

  .practice-layout,
  .about-layout {
    padding-left: max(22px, env(safe-area-inset-left));
    padding-right: max(22px, env(safe-area-inset-right));
  }

  .schedule-copy,
  .contact-layout,
  .contact-heading {
    width: min(
      calc(100% - 30px - env(safe-area-inset-left) - env(safe-area-inset-right)),
      var(--max-width)
    );
  }

  .privacy-dialog {
    width: min(
      calc(100vw - 24px - env(safe-area-inset-left) - env(safe-area-inset-right)),
      42rem
    );
  }

  .flyer-dialog {
    max-width: calc(100vw - 16px - env(safe-area-inset-left) - env(safe-area-inset-right));
  }

  .flyer-dialog-panel,
  .flyer-dialog-image {
    max-width: calc(100vw - 16px - env(safe-area-inset-left) - env(safe-area-inset-right));
  }
}
