@charset "utf-8";
/* ============================================================================
   MEZA NYC — meza.css
   Single source of truth for all seven pages. No page may ship its own CSS,
   no page may contain a <style> block. If something is missing here, it gets
   ADDED HERE — never inlined on a page.

   ----------------------------------------------------------------------------
   TABLE OF CONTENTS — every class the pages may use
   ----------------------------------------------------------------------------
   00  FONTS ................ Italiana 400 · Lato 300/400/700 (local, swap)
   01  TOKENS ............... :root custom properties (colour, space, type)
   02  RESET + BASE ......... html, body, img, picture, a, headings, focus ring,
                              [id]{scroll-margin-top} for the fixed header
   03  UTILITIES ............ .wrap  .wrap--wide  .wrap--narrow
                              .visually-hidden  .skip-link
                              .eyebrow  .eyebrow--blush  .eyebrow--rule
                              .rule  .lede  .display  .tint  .taglist
   04  BUTTONS + LINKS ...... .btn  .btn--solid  .btn--ghost
                              .btn-row  .btn-row--center  .link-arrow
   05  HEADER + NAV ......... .site-header (.is-stuck)  .site-header__in
                              .brand  .nav  .nav__list  .nav__link
                              .nav-toggle  .nav-sheet (.is-open)
                              .nav-sheet__top  .nav-sheet__list
                              .nav-sheet__close  .nav-sheet__foot
                              body.has-nav-open  (scroll lock)
   06  FOOTER ............... .site-footer  .site-footer__grid
                              .site-footer__brand  .site-footer__nav
                              .site-footer__end
   07  HERO A · GALLERY WALL  .hero-mosaic (.is-paused)  __wall  __row
                              __col (--far|--mid|--near)  __track  __set
                              __tile  __scrim  __body  __plate  __eyebrow
                              __lede  __cue     ·  h1 > span, h1 .amp
   08  HERO B · PLATE ....... .hero-plate (--compact|--tall)  __fill
                              __photo  __scrim  __body
                              >> blurred-fill: the whole photo (object-fit:
                                 contain) lies on a blurred, enlarged copy of
                                 itself — never a hard edge, never a crop.
   09  SECTIONS ............. .section (--soft|--cream|--flush)
                              .section__head  .section__head--split
                              .section__title  .section__intro
                              .band  .band__caption
   10  FIGURES + MEDIA ...... .figure  .figure--frame  .figure__caption
                              .media-duo  .media-offset
                              .gallery-masonry  .gallery-item
   11  LIGHTBOX ............. .lightbox (built by meza.js — do NOT hand-write)
                              __bar __count __stage __img __caption
                              __close __prev __next · body.has-lightbox-open
   12  CARDS ................ .card-grid (--2|--3|--4|--stagger)
                              .board-card (__no __title __text)
                              .occasion-card (__body __title __text)
                              .steps (--3|--4)  .step (__no __title __text)
                              .price-list  .price-row (__k __v __v--soft)
   13  FORM ................. .form  .form--two  .field  .field--wide
                              .field__label  .field__input
                              .form-note  .form-status
   14  FAQ .................. .faq  .faq--wide  .faq__item  .faq__q  .faq__a
   15  REVEAL ............... .reveal (.is-visible)  .reveal--d1 …--d3
   16  REDUCED MOTION ....... kills every animation and transition
   ----------------------------------------------------------------------------
   THE TWO INLINE CUSTOM PROPERTIES A PAGE MAY SET
   · style="--tone:#RRGGBB"  the photo's dominant colour from manifest.json.
     Put it on every image box (.figure, .hero-mosaic__tile, .gallery-item,
     .hero-plate) so nothing ever flashes as an empty hole.
   · style="--ar:1.4767"     the photo's TRUE ratio, ONLY on .hero-mosaic__tile.
     Nowhere else — every other image box takes its height from the photo.
   Anything else a page needs belongs in THIS file, not in a style attribute.
   ----------------------------------------------------------------------------
   IMAGE LAW (from BRIEF.md §7) — enforced by the classes above
   · Gallery + content figures: NO crop. Natural ratio, height:auto.
   · Cover crops only in .hero-mosaic__tile (box ratio == photo ratio, so the
     crop is 0px) and in .hero-plate (contain over blur, so the crop is 0px).
   · Every <img> carries width/height, srcset+sizes, alt from manifest.json,
     loading="lazy" (only the single topmost hero image is eager +
     fetchpriority="high") and object-position from manifest.json wherever
     object-fit: cover is in play.
   · Every image box sits on its dominant colour: style="--tone:#RRGGBB".
   ========================================================================== */


/* ============================================================================
   00 · FONTS
   ========================================================================== */
@font-face{
  font-family:"Italiana";
  src:url("../fonts/italiana-400.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap;
}
@font-face{
  font-family:"Lato";
  src:url("../fonts/lato-300.woff2") format("woff2");
  font-weight:300;font-style:normal;font-display:swap;
}
@font-face{
  font-family:"Lato";
  src:url("../fonts/lato-400.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap;
}
@font-face{
  font-family:"Lato";
  src:url("../fonts/lato-700.woff2") format("woff2");
  font-weight:700;font-style:normal;font-display:swap;
}


/* ============================================================================
   01 · TOKENS
   ========================================================================== */
:root{
  /* --- colour (measured from the original site) --- */
  --ink:#000000;
  --ink-soft:#0B0B0B;
  --ink-raise:#121110;
  --blush:#C9BBB4;
  --blush-lite:#E4DAD5;
  --sage:#949D7F;
  --sage-deep:#6E7A5C;
  --cream:#F4EFEA;
  --paper:#F4EFEA;          /* the cream GROUND — never re-pointed, see §09 */
  --line:rgba(201,187,180,.22);
  --line-soft:rgba(201,187,180,.12);
  /* readable ink on the cream ground (contrast > 12:1 / > 7:1)
     --sage-ink is the ONLY green that clears 4.5:1 on cream (6.7:1) — the
     lighter sages are for dark grounds and for large type on cream only. */
  --on-cream:#161514;
  --on-cream-soft:#4A4540;
  --sage-ink:#4C563C;
  --line-cream:rgba(22,21,20,.16);

  /* --- families --- */
  --font-display:"Italiana",Georgia,"Times New Roman",serif;
  --font-text:"Lato",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;

  /* --- type scale (clamp only — no fixed px headlines) --- */
  --fs-display:clamp(2.5rem,9vw,5.2rem);
  --fs-h1:clamp(2.1rem,6.4vw,4.2rem);
  --fs-h2:clamp(1.75rem,4.6vw,3.1rem);
  --fs-h3:clamp(1.28rem,2.4vw,1.72rem);
  --fs-lede:clamp(1.02rem,.5vw + .9rem,1.2rem);
  --fs-body:clamp(.95rem,.28vw + .88rem,1.02rem);
  --fs-small:clamp(.8rem,.2vw + .76rem,.88rem);
  --fs-eyebrow:clamp(.62rem,.28vw + .56rem,.72rem);
  --fs-btn:.73rem;

  /* --- space scale --- */
  --space-3xs:4px;
  --space-2xs:clamp(6px,.6vw,10px);
  --space-xs:clamp(10px,1.1vw,16px);
  --space-sm:clamp(16px,2vw,26px);
  --space-md:clamp(24px,3.2vw,44px);
  --space-lg:clamp(40px,5.4vw,76px);
  --space-xl:clamp(58px,8vw,116px);
  --space-2xl:clamp(78px,11vw,164px);

  /* --- layout --- */
  --gut:clamp(20px,5vw,64px);
  --maxw:1240px;
  --maxw-wide:1520px;
  --header-h:64px;
  --measure:66ch;

  --ease:cubic-bezier(.22,.61,.36,1);
  --dur:.45s;
}
@media (min-width:1024px){
  :root{ --header-h:84px; }
}


/* ============================================================================
   02 · RESET + BASE
   ========================================================================== */
*,*::before,*::after{box-sizing:border-box}

html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  background:var(--ink);
  overflow-x:clip;              /* never a horizontal scrollbar — 320px up */
}
body{
  margin:0;
  overflow-x:clip;
  background:var(--ink);
  color:var(--blush-lite);
  font-family:var(--font-text);
  font-weight:300;
  font-size:var(--fs-body);
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
h1,h2,h3,h4,p,figure,blockquote,ul,ol,dl,dd{margin:0;padding:0}
ul,ol{list-style:none}
img,svg,video{display:block;max-width:100%}
img{border-style:none}
/* <picture> must not become a box of its own. If it does, it sits between the
   sizing container and the <img>, height:100% has nothing to resolve against
   and object-fit / object-position quietly stop working. display:contents
   removes the box, so every <img> is laid out by the element that sizes it. */
picture{display:contents}
a{color:inherit;text-decoration:none}
button,input,textarea,select{font:inherit;color:inherit}
button{background:none;border:0;cursor:pointer}
strong,b{font-weight:400}

h1,h2,h3{
  font-family:var(--font-display);
  font-weight:400;
  letter-spacing:.025em;
  line-height:1.1;
  color:var(--cream);
  text-wrap:balance;
}

/* the brand's green accent — never italic, always the same weight */
em{font-style:normal;font-weight:inherit;color:var(--sage)}

:focus-visible{
  outline:2px solid var(--sage);
  outline-offset:3px;
  border-radius:1px;
}

/* Nur per Skript anspringbare Elemente bekommen KEINEN Rahmen.
   tabindex="-1" heisst: mit der Tabulatortaste nicht erreichbar. Wer so ein
   Element fokussiert, ist immer das Skript — es soll dem Screenreader den
   Wechsel ansagen, nicht dem Auge einen Kasten zeigen.
   Betrifft jede solche Stelle: die vier Bildschirm-Ueberschriften im
   Login-Bereich, die sieben Fragen des Anfrage-Trichters, den Danke-Bildschirm
   und das versteckte Spam-Feld — und jede kuenftige automatisch mit. */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible{outline:none}


/* the header is fixed, so anything jumped to by #id must keep clear of it */
[id]{scroll-margin-top:calc(var(--header-h) + var(--space-sm))}


/* ============================================================================
   03 · UTILITIES
   ========================================================================== */
.wrap{width:100%;max-width:var(--maxw);margin-inline:auto}
.wrap--wide{max-width:var(--maxw-wide)}
.wrap--narrow{max-width:74ch}

.visually-hidden{
  position:absolute!important;width:1px;height:1px;
  margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);
  white-space:nowrap;border:0;
}

.skip-link{
  position:fixed;top:-200px;left:var(--gut);z-index:300;
  background:var(--cream);color:var(--ink);
  padding:.85rem 1.3rem;
  font-size:var(--fs-eyebrow);letter-spacing:.16em;text-transform:uppercase;
  transition:top .25s var(--ease);
}
.skip-link:focus{top:12px}

.eyebrow{
  font-family:var(--font-text);font-weight:400;
  font-size:var(--fs-eyebrow);
  letter-spacing:.34em;text-transform:uppercase;
  color:var(--sage);
  line-height:1.5;
}
.eyebrow--blush{color:var(--blush)}
.eyebrow--rule{display:flex;align-items:center;gap:.9rem}
.eyebrow--rule::after{content:"";flex:1 1 auto;height:1px;background:var(--line);max-width:120px}

.rule{display:block;height:1px;border:0;background:var(--line);width:100%}

.lede{
  font-size:var(--fs-lede);
  line-height:1.75;
  color:var(--blush-lite);
  max-width:var(--measure);
}
.lede + .lede{margin-top:var(--space-sm)}

.display{
  font-family:var(--font-display);font-weight:400;
  font-size:var(--fs-display);
  line-height:1.04;letter-spacing:.02em;
  color:var(--cream);
}
.tint{color:var(--sage)}

/* small uppercase pill list — e.g. the five occasions */
.taglist{display:flex;flex-wrap:wrap;gap:.5rem}
.taglist li{
  font-size:var(--fs-eyebrow);letter-spacing:.2em;text-transform:uppercase;
  color:var(--blush);
  border:1px solid var(--line);
  background:var(--ink-raise);
  padding:.62rem 1rem;
}


/* ============================================================================
   04 · BUTTONS + LINKS   (touch target >= 48px on every one of them)
   ========================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:48px;
  padding:0 clamp(20px,2.6vw,32px);
  font-size:var(--fs-btn);font-weight:400;
  letter-spacing:.22em;text-transform:uppercase;
  color:var(--blush-lite);
  border:1px solid var(--line);
  background:transparent;
  text-align:center;
  transition:background-color var(--dur) var(--ease),
             color var(--dur) var(--ease),
             border-color var(--dur) var(--ease);
}
.btn:hover,.btn:focus-visible{background:var(--blush);border-color:var(--blush);color:var(--ink)}

.btn--solid{background:var(--blush);border-color:var(--blush);color:var(--ink)}
.btn--solid:hover,.btn--solid:focus-visible{background:var(--cream);border-color:var(--cream);color:var(--ink)}

.btn--ghost{background:transparent;color:var(--blush-lite);border-color:var(--line)}
.btn--ghost:hover,.btn--ghost:focus-visible{background:rgba(228,218,213,.08);border-color:var(--blush);color:var(--cream)}

.btn-row{display:flex;flex-wrap:wrap;gap:var(--space-xs)}
.btn-row .btn{flex:1 1 190px}
@media (min-width:560px){ .btn-row .btn{flex:0 0 auto} }
.btn-row--center{justify-content:center}

.link-arrow{
  display:inline-flex;align-items:center;gap:.8em;
  min-height:44px;padding:10px 0;
  font-size:var(--fs-eyebrow);letter-spacing:.24em;text-transform:uppercase;
  color:var(--blush);
}
.link-arrow::after{
  content:"";display:block;width:34px;height:1px;background:currentColor;
  transition:width var(--dur) var(--ease);
}
.link-arrow:hover::after,.link-arrow:focus-visible::after{width:54px}


/* ============================================================================
   05 · HEADER + NAVIGATION
   ========================================================================== */
.site-header{
  position:fixed;inset:0 0 auto 0;z-index:70;
  height:var(--header-h);
  display:flex;align-items:center;
  border-bottom:1px solid transparent;
  transition:background-color .5s var(--ease),border-color .5s var(--ease);
}
/* a soft scrim so the wordmark reads while the header floats over photos */
.site-header::before{
  content:"";position:absolute;inset:0 0 -70% 0;z-index:-1;pointer-events:none;
  background:linear-gradient(to bottom,rgba(0,0,0,.72),rgba(0,0,0,.30) 58%,rgba(0,0,0,0));
  transition:opacity .5s var(--ease);
}
.site-header.is-stuck{background:rgba(0,0,0,.95);border-bottom-color:var(--line-soft)}
.site-header.is-stuck::before{opacity:0}

.site-header__in{
  width:100%;max-width:var(--maxw-wide);margin-inline:auto;
  padding-inline:var(--gut);
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
}

.brand{display:flex;align-items:center;flex:0 0 auto;min-height:44px}
.brand img{
  width:auto;height:clamp(24px,3.4vw,36px);
  transition:height .45s var(--ease);
}
.site-header.is-stuck .brand img{height:clamp(21px,2.7vw,28px)}

.nav{display:none}
@media (min-width:1024px){
  .nav{display:block}
  .nav__list{display:flex;align-items:center;gap:clamp(14px,1.8vw,30px)}
  .nav__link{
    display:block;padding:14px 0;position:relative;
    font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;
    color:var(--blush-lite);
    transition:color var(--dur) var(--ease);
  }
  .nav__link::after{
    content:"";position:absolute;left:0;right:0;bottom:8px;height:1px;
    background:var(--blush);
    transform:scaleX(0);transform-origin:left;
    transition:transform .5s var(--ease);
  }
  .nav__link:hover,.nav__link:focus-visible{color:var(--cream)}
  .nav__link:hover::after,.nav__link:focus-visible::after{transform:scaleX(1)}
  .nav__link[aria-current="page"]{color:var(--blush)}
  .nav__link[aria-current="page"]::after{transform:scaleX(1)}
}

.nav-toggle{
  display:inline-flex;flex-direction:column;align-items:flex-end;justify-content:center;gap:6px;
  width:48px;height:48px;margin-right:-12px;flex:0 0 auto;
}
.nav-toggle span{
  display:block;height:1px;background:var(--blush-lite);
  transition:width .45s var(--ease);
}
.nav-toggle span:nth-child(1){width:26px}
.nav-toggle span:nth-child(2){width:18px}
.nav-toggle:hover span:nth-child(2){width:26px}
@media (min-width:1024px){ .nav-toggle{display:none} }

/* full-screen mobile overlay */
.nav-sheet{
  position:fixed;inset:0;z-index:90;
  background:var(--ink);
  display:flex;flex-direction:column;
  opacity:0;visibility:hidden;
  transition:opacity .42s var(--ease),visibility .42s var(--ease);
  overflow-y:auto;
}
.nav-sheet.is-open{opacity:1;visibility:visible}
.nav-sheet__top{
  flex:0 0 auto;height:var(--header-h);
  display:flex;align-items:center;justify-content:space-between;
  padding-inline:var(--gut);
}
.nav-sheet__top img{width:auto;height:clamp(24px,3.4vw,32px)}
.nav-sheet__close{
  width:48px;height:48px;margin-right:-12px;
  display:grid;place-items:center;position:relative;
}
.nav-sheet__close::before,.nav-sheet__close::after{
  content:"";position:absolute;width:24px;height:1px;background:var(--blush-lite);
}
.nav-sheet__close::before{transform:rotate(45deg)}
.nav-sheet__close::after{transform:rotate(-45deg)}

/* the <nav> is the flex child, so it — not the list — has to take the space */
.nav-sheet > nav{flex:1 1 auto;display:flex;align-items:center;min-height:0}
.nav-sheet__list{
  width:100%;display:flex;flex-direction:column;
  padding:var(--space-md) var(--gut) var(--space-lg);
}
.nav-sheet__list li{border-bottom:1px solid var(--line-soft)}
.nav-sheet__list li:first-child{border-top:1px solid var(--line-soft)}
.nav-sheet__list a{
  display:flex;align-items:baseline;gap:.9rem;
  min-height:56px;padding:14px 0;
  font-family:var(--font-display);
  font-size:clamp(1.5rem,7vw,2.3rem);letter-spacing:.05em;
  color:var(--blush-lite);
}
.nav-sheet__list a span{
  font-family:var(--font-text);font-size:.6rem;letter-spacing:.24em;color:var(--sage);
}
.nav-sheet__list a[aria-current="page"]{color:var(--blush)}
.nav-sheet__foot{
  flex:0 0 auto;
  padding:0 var(--gut) max(28px,env(safe-area-inset-bottom));
  display:flex;flex-wrap:wrap;gap:.4rem 1.4rem;
  font-size:var(--fs-eyebrow);letter-spacing:.22em;text-transform:uppercase;color:var(--sage);
}
.nav-sheet__foot a{
  display:inline-flex;align-items:center;min-height:44px;
  border-bottom:1px solid var(--line);
}

body.has-nav-open{overflow:hidden}


/* ============================================================================
   06 · FOOTER
   ========================================================================== */
.site-footer{
  background:var(--ink-soft);
  border-top:1px solid var(--line-soft);
  padding:var(--space-lg) var(--gut) var(--space-md);
}
.site-footer__grid{
  width:100%;max-width:var(--maxw);margin-inline:auto;
  display:grid;gap:var(--space-md);
}
@media (min-width:760px){
  .site-footer__grid{grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:var(--space-lg)}
}
.site-footer__brand{display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-sm);max-width:42ch}
.site-footer__brand img{width:auto;height:clamp(30px,5vw,42px)}
/* Das Logo im Footer ist ein Link zur Startseite. Ohne Zutun waere seine
   antippbare Flaeche nur so gross wie das Bild (114x30) — auf dem Handy zu
   klein. Die Innenabstaende vergroessern die Trefferflaeche auf ueber 44px,
   die gleich grossen Aussenabstaende nehmen den Platz wieder heraus, sodass
   sich am Aussehen NICHTS aendert. */
.site-footer__logo{
  display:inline-flex;align-items:center;
  padding:9px 8px;margin:-9px -8px;
  min-height:44px;
}
.site-footer__brand p{font-size:var(--fs-small);color:var(--blush-lite);opacity:.82}

.site-footer__nav ul{display:flex;flex-wrap:wrap;gap:2px clamp(18px,2.4vw,32px)}
.site-footer__nav a{
  display:flex;align-items:center;min-height:44px;
  font-size:var(--fs-eyebrow);letter-spacing:.2em;text-transform:uppercase;
  color:var(--blush-lite);
  transition:color var(--dur) var(--ease);
}
.site-footer__nav a:hover,.site-footer__nav a[aria-current="page"]{color:var(--blush)}

.site-footer__end{
  width:100%;max-width:var(--maxw);margin:var(--space-md) auto 0;
  padding-top:var(--space-sm);
  border-top:1px solid var(--line-soft);
  display:flex;flex-wrap:wrap;gap:.6rem clamp(18px,3vw,34px);
  justify-content:space-between;align-items:center;
  font-size:var(--fs-eyebrow);letter-spacing:.22em;text-transform:uppercase;
  color:var(--blush);
}
/* inline links in the two meta rows still have to be a 44px touch target */
.site-footer__end a{
  display:inline-flex;align-items:center;min-height:44px;
  border-bottom:1px solid var(--line);
}
.site-footer__end a:hover{color:var(--cream)}


/* ============================================================================
   07 · HERO A — THE GALLERY WALL   (home page)

   Markup shape:
   <section class="hero-mosaic">
     <div class="hero-mosaic__wall">
       <div class="hero-mosaic__row">
         <div class="hero-mosaic__col hero-mosaic__col--far" style="--speed:124s;--dir:normal;--delay:-31s;--off:-40px">
           <div class="hero-mosaic__track">
             <div class="hero-mosaic__set"> …4 tiles… </div>
             <div class="hero-mosaic__set" aria-hidden="true"> …the same 4 tiles, alt="" … </div>
           </div>
         </div>  …five columns…
       </div>
     </div>
     <div class="hero-mosaic__scrim"></div>
     <div class="hero-mosaic__body"> … .hero-mosaic__plate … </div>
   </section>

   Why the tiles can never look "cut off":
     the tile box carries --ar = the photo's TRUE ratio from manifest.json, so
     object-fit:cover has nothing left to cut. The two identical sets make the
     drift loop seamless WITHOUT JavaScript — no clone script, no empty column.
   Overlay discipline (Cyrill's note): the food stays appetising. Tiles are
   dimmed by at most 10%, the page-wide scrim is light, and the dark bed sits
   locally BEHIND the type only.
   ========================================================================== */
.hero-mosaic{
  position:relative;isolation:isolate;
  min-height:100vh;min-height:100svh;
  display:grid;align-items:end;
  overflow:clip;
  background:var(--ink);
  --gap:clamp(8px,1.1vw,18px);
}
@media (min-width:900px){
  .hero-mosaic{align-items:center}
}

.hero-mosaic__wall{
  position:absolute;inset:0;z-index:0;overflow:clip;
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 19%,#000 80%,transparent 100%);
          mask-image:linear-gradient(to bottom,transparent 0,#000 19%,#000 80%,transparent 100%);
}
.hero-mosaic__row{
  position:absolute;inset:0;
  display:flex;gap:var(--gap);justify-content:center;
}
.hero-mosaic__col{
  flex:1 1 0;min-width:0;
  transform:translate3d(0,var(--off,0px),0);
  display:none;
}
.hero-mosaic__track{
  display:flex;flex-direction:column;gap:var(--gap);
  animation:meza-drift var(--speed,120s) linear infinite;
  animation-direction:var(--dir,normal);
  animation-delay:var(--delay,0s);
  will-change:transform;
}
.hero-mosaic__set{display:flex;flex-direction:column;gap:var(--gap)}

/* track = [set][gap][set] → one loop = setHeight + gap = 50% + gap/2 */
@keyframes meza-drift{
  from{transform:translate3d(0,0,0)}
  to  {transform:translate3d(0,calc(-50% - (var(--gap) / 2)),0)}
}
.hero-mosaic.is-paused .hero-mosaic__track{animation-play-state:paused}

/* depth — brightness only. No blur/shadow over moving pixels (it stutters). */
.hero-mosaic__col--far{filter:brightness(.9)}
.hero-mosaic__col--mid{filter:brightness(.96)}
.hero-mosaic__col--near{filter:brightness(1)}

.hero-mosaic__tile{
  position:relative;margin:0;
  aspect-ratio:var(--ar);                 /* == the photo's ratio */
  background:var(--tone,var(--ink-raise));/* dominant colour, never a hole */
  overflow:hidden;
}
.hero-mosaic__tile img{width:100%;height:100%;object-fit:cover}
.hero-mosaic__tile::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  border:1px solid rgba(228,218,213,.10);
}

/* which columns are on stage — mobile shows the two portrait-led columns */
.hero-mosaic__col:nth-child(3),
.hero-mosaic__col:nth-child(4){display:block}
@media (min-width:640px){ .hero-mosaic__col:nth-child(2){display:block} }
@media (min-width:900px){ .hero-mosaic__col:nth-child(1){display:block} }
@media (min-width:1200px){ .hero-mosaic__col:nth-child(5){display:block} }

/* Der schwarze Verlauf — 1:1 aus dem freigegebenen Entwurf B. Nicht anfassen. */
.hero-mosaic__scrim{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(to bottom,
      rgba(0,0,0,.74) 0,
      rgba(0,0,0,.14) 24%,
      rgba(0,0,0,.16) 64%,
      rgba(0,0,0,.94) 100%),
    radial-gradient(130% 100% at 50% 50%,
      rgba(0,0,0,0) 48%,
      rgba(0,0,0,.38) 100%);
}
@media (min-width:900px){
  .hero-mosaic__scrim{
    background:
      linear-gradient(to right,
        rgba(0,0,0,.93) 0,
        rgba(0,0,0,.80) 27%,
        rgba(0,0,0,.34) 49%,
        rgba(0,0,0,0) 66%),
      linear-gradient(to bottom,
        rgba(0,0,0,.70) 0,
        rgba(0,0,0,.10) 22%,
        rgba(0,0,0,.14) 64%,
        rgba(0,0,0,.94) 100%);
  }
}

.hero-mosaic__body{
  position:relative;z-index:2;width:100%;
  padding:calc(var(--header-h) + var(--space-md)) var(--gut) clamp(72px,14vh,132px);
}
/* Die Platte — unveraendert aus dem freigegebenen Entwurf B uebernommen.
   Auf dem Handy eine echte, dunkle Karte mit weichem Auslauf ringsum;
   ab 900px loest sich die Karte auf und der Text steht links direkt auf
   dem Seitenverlauf des Scrims, damit die Fotos offen bleiben. */
.hero-mosaic__plate{
  position:relative;
  max-width:min(620px,100%);margin-inline:auto;
  background:rgba(0,0,0,.80);
  border:1px solid var(--line);
  padding:clamp(28px,4.6vw,56px) clamp(22px,4vw,52px);
  text-align:center;
}
.hero-mosaic__plate::before{
  content:"";position:absolute;inset:-14vw -8vw;z-index:-1;pointer-events:none;
  background:radial-gradient(closest-side,rgba(0,0,0,.86),rgba(0,0,0,0) 100%);
}
.hero-mosaic__meta{
  display:flex;align-items:center;justify-content:center;gap:14px;margin:0 0 4px;
}
.hero-mosaic__meta .rule{flex:1;max-width:54px;height:1px;background:var(--sage);opacity:.75}

/* die Wortmarke traegt den Hero — sie ist das Erste, was man liest */
.hero-mosaic__mark{
  display:block;width:min(100%,420px);height:auto;
  margin:clamp(16px,2.6vw,26px) auto clamp(18px,2.8vw,30px);
}

.hero-mosaic h1,
.hero-mosaic__lede{
  font-family:var(--font-display,"Italiana",Georgia,serif);font-weight:400;
  font-size:clamp(1.5rem,4.1vw,2.5rem);line-height:1.18;letter-spacing:.025em;
  color:var(--blush-lite);
  margin:0 0 clamp(20px,3vw,30px);
  text-wrap:balance;
  text-shadow:0 2px 20px rgba(0,0,0,.8);
}

@media (min-width:900px){
  .hero-mosaic__body{padding-inline:var(--gut);padding-bottom:clamp(60px,10vh,120px)}
  .hero-mosaic__plate{
    margin-inline:0;text-align:left;max-width:min(560px,46vw);
    background:none;border:0;border-top:1px solid var(--line);
    padding:clamp(22px,2.4vw,32px) 0 0;
  }
  .hero-mosaic__plate::before{display:none}
  .hero-mosaic__mark{margin-inline:0;width:min(100%,400px)}
  .hero-mosaic__meta{justify-content:flex-start}
  .hero-mosaic .btn-row{justify-content:flex-start}
}

.hero-mosaic__cue{
  position:absolute;z-index:3;left:50%;bottom:18px;transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:.55rem;
  font-size:.58rem;letter-spacing:.32em;text-transform:uppercase;color:var(--blush);
  opacity:.8;
}
.hero-mosaic__cue i{
  display:block;width:1px;height:34px;
  background:linear-gradient(to bottom,var(--blush),transparent);
  animation:meza-cue 3s var(--ease) infinite;
}
@keyframes meza-cue{
  0%{transform:scaleY(.15);transform-origin:top;opacity:0}
  35%{opacity:1}
  100%{transform:scaleY(1);transform-origin:top;opacity:0}
}
@media (min-width:900px){
  .hero-mosaic__cue{left:auto;right:var(--gut);transform:none}
}


/* ============================================================================
   08 · HERO B — THE PLATE   (every inner page)

   Markup shape (art direction: portrait motif on narrow screens):
   <section class="hero-plate" style="--tone:#907151">
     <div class="hero-plate__fill" aria-hidden="true">
       <img src="assets/img/SLUG-480.jpg" width="W" height="H" alt="" decoding="async">
     </div>
     <figure class="hero-plate__photo">
       <picture>
         <source type="image/webp" media="(min-width:900px)" srcset="…landscape…" sizes="100vw">
         <source type="image/webp" srcset="…portrait…" sizes="100vw">
         <img src="…" srcset="…" sizes="100vw" width="W" height="H"
              alt="…from manifest…" fetchpriority="high" decoding="async">
       </picture>
     </figure>
     <div class="hero-plate__scrim"></div>
     <div class="hero-plate__body"><div class="wrap"> … </div></div>
   </section>

   The photo is object-fit:CONTAIN — mathematically incapable of cropping.
   Whatever space it does not fill is filled by a blurred, enlarged copy of
   the very same photograph, so the frame is edge-to-edge image and there is
   never a hard border or an empty strip.
   ========================================================================== */
.hero-plate{
  position:relative;isolation:isolate;overflow:clip;
  background:var(--tone,var(--ink-raise));
  /* Der Titel steht MITTIG, nicht unten: ueber ihm sitzt nichts ausser dem
     Header, unten angeschlagen liess er die halbe Flaeche leer wirken. */
  min-height:clamp(440px,62svh,700px);
  display:grid;align-items:center;
}
.hero-plate--compact{min-height:clamp(380px,50svh,560px)}
.hero-plate--tall{min-height:clamp(520px,74svh,820px)}

/* Die frueher noetige zweite Fuell-Ebene entfaellt: das Hero-Foto IST jetzt der
   unscharfe Hintergrund. Eine Ebene weniger, ein Bild weniger zu laden. */
.hero-plate__fill{display:none}

.hero-plate__photo{
  position:absolute;inset:0;z-index:1;margin:0;
}
/* Innenseiten-Hero: randlos fuellend und BEWUSST stark unscharf.
   Zwei Fliegen: der Titel liegt ruhig lesbar darauf, und die Frage
   "ist das Bild angeschnitten?" stellt sich gar nicht mehr.
   scale() ist Pflicht — ohne sie wuerde der Weichzeichner an den
   Raendern durchsichtig ausfransen.
   Die Startseite nutzt diese Klasse NICHT, dort bleibt alles scharf. */
.hero-plate__photo img{
  width:100%;height:100%;
  /* IMMER randlos fuellend. Frueher gab es hier einen Schalter --fit, mit dem
     eine Seite auf "contain" umstellen konnte — about.html tat das und zeigte
     dadurch statt eines Hero-Bildes ein kleines Viereck mitten in der Flaeche.
     Der Schalter ist weg: ein Sonderfall weniger, ein Fehler weniger. */
  object-fit:cover;
  object-position:var(--focal,center 55%);
  filter:blur(15px) saturate(1.55) brightness(.95) contrast(1.06);
  transform:scale(1.16);
  will-change:transform;
}

.hero-plate__scrim{
  position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    /* die Textseite links leicht beruhigen, damit die Schrift traegt */
    linear-gradient(to right,
      rgba(0,0,0,.66) 0%,
      rgba(0,0,0,.42) 32%,
      rgba(0,0,0,.10) 62%,
      rgba(0,0,0,0) 88%),
    /* oben nur so viel wie die Navigation braucht */
    linear-gradient(to bottom,
      rgba(0,0,0,.56) 0%,
      rgba(0,0,0,.10) 26%,
      rgba(0,0,0,.10) 62%,
      /* unten weich nach Schwarz — kein harter Schnitt zum naechsten Abschnitt */
      rgba(0,0,0,.72) 88%,
      rgba(0,0,0,1) 100%);
}
.hero-plate__body{
  position:relative;z-index:3;width:100%;
  padding:calc(var(--header-h) + var(--space-md)) var(--gut) var(--space-md);
}
.hero-plate__body .eyebrow{margin-bottom:var(--space-xs)}
.hero-plate__body h1{
  font-size:var(--fs-h1);color:var(--cream);
  text-shadow:0 4px 34px rgba(0,0,0,.75);
}
.hero-plate__body h1 .amp{color:var(--sage)}
.hero-plate__body .lede{
  margin-top:var(--space-sm);
  text-shadow:0 2px 20px rgba(0,0,0,.8);
}


/* ============================================================================
   09 · SECTIONS
   ========================================================================== */
.section{
  position:relative;
  padding:var(--space-xl) var(--gut);
  background:var(--ink);
}
.section--soft{background:var(--ink-soft);border-top:1px solid var(--line-soft)}
.section--flush{padding-block:var(--space-lg)}

/* THE CREAM SECTION RE-POINTS THE TOKENS — it does not fight the components.
   Every component below is written against --blush / --cream / --sage / --line,
   so switching those four here flips the whole block to ink-on-paper at once.
   That is why there is not a single .section--cream .something colour rule:
   a per-component override would lose the next specificity war (an [open]
   state, a hover, a nested card) and turn text invisible. */
.section--cream{
  background:var(--paper);
  color:var(--on-cream-soft);
  border-top:1px solid var(--line-cream);

  --cream:var(--on-cream);        /* "brightest" text becomes darkest ink */
  --blush:var(--on-cream);
  --blush-lite:var(--on-cream-soft);
  --sage:var(--sage-ink);
  --sage-deep:var(--sage-ink);
  --ink:var(--paper);             /* text ON a blush button becomes paper */
  --ink-raise:rgba(255,255,255,.55);
  --line:var(--line-cream);
  --line-soft:var(--line-cream);
}
/* the one thing a token cannot express: a field wants real white paper */
.section--cream .field__input{background:#fff}

.section__head{
  display:grid;gap:var(--space-xs);
  margin-bottom:var(--space-lg);
}
@media (min-width:900px){
  .section__head--split{grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:var(--space-md)}
}
.section__title{font-size:var(--fs-h2);color:var(--cream)}
.section__intro{max-width:var(--measure);color:var(--blush-lite);opacity:.86}

/* the transparent occasions wordmark, on black only */
.band{
  padding:var(--space-lg) var(--gut);
  background:var(--ink);
  text-align:center;
}
.band img{
  width:min(760px,88%);height:auto;margin-inline:auto;opacity:.95;
}
.band__caption{
  margin-top:var(--space-sm);
  font-size:var(--fs-eyebrow);letter-spacing:.3em;text-transform:uppercase;color:var(--sage);
}


/* ============================================================================
   10 · FIGURES + MEDIA   (no crop anywhere in here)
   ========================================================================== */
.figure{
  margin:0;position:relative;
  background:var(--tone,var(--ink-raise));
}
.figure img{width:100%;height:auto}      /* natural ratio — nothing is cut */

.figure--frame{border:1px solid var(--line)}
.figure--frame::after{                    /* the hairline mat inside the print */
  content:"";position:absolute;inset:clamp(8px,1.4vw,16px);
  border:1px solid var(--line);pointer-events:none;
}

.figure__caption{
  margin-top:var(--space-xs);
  font-size:var(--fs-eyebrow);letter-spacing:.26em;text-transform:uppercase;
  color:var(--sage);
}

/* two photographs side by side, stacked on small screens.
   ACHTUNG — ein direktes Kind ist EINE Zelle: ein Bild mit Unterschrift ist
   immer <div><figure>…</figure><p class="figure__caption">…</p></div>.
   Warum, und was der Bruch dieser Regel angerichtet hat: siehe §26 am Ende. */
.media-duo{display:grid;gap:var(--space-md)}
@media (min-width:640px){
  .media-duo{grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}
}

/* editorial pair: the second frame steps down and in.

   WARUM `center` UND NICHT `start` (geaendert 09.08.2026, gemessen bei 1440px):
   Hier steht fast immer ein HOCHFORMAT-Foto neben einem kurzen Text — das Foto
   ist dann 500–800px hoch, der Text 300–450px. Mit `align-items:start` beginnen
   beide oben, und die ganze Differenz faellt als EIN Loch unter den Text.
   Gemessen als groesste zusammenhaengende Leerflaeche je Paar:

       Seite / Abschnitt        start   center
       Startseite                 176      121
       /boards 01 Classic         101      113
       /boards 02 Vegetarian      172      101
       /boards 03 Brunch          354      278
       /about (zwei Stellen)  304, 340  152, 271
       /grazing-tables            329      165

   Sechs von sieben werden besser, eines um 12px schlechter. Das ist keine
   Ausnahme fuer einen Abschnitt, sondern eine Voreinstellung, die von Anfang an
   zu hoch stand — deshalb ein GEAENDERTER Wert und keine neue Regel daneben.
   Der Versatz aus nth-child(2) bleibt und wirkt weiter: die zweite Zelle sitzt
   mittig PLUS ein Stueck tiefer, das versetzte Bild bleibt also versetzt.
   Unter 768px ist das Raster einspaltig, dort ist die Ausrichtung wirkungslos. */
.media-offset{display:grid;gap:var(--space-md)}
@media (min-width:768px){
  .media-offset{grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:center;gap:var(--space-lg)}
  .media-offset > :nth-child(2){margin-top:clamp(32px,7vw,110px)}
}

/* the gallery: CSS columns, natural ratio, zero crop */
.gallery-masonry{
  columns:1;
  column-gap:var(--space-sm);
}
@media (min-width:520px){ .gallery-masonry{columns:2} }
@media (min-width:1024px){ .gallery-masonry{columns:3} }
@media (min-width:1440px){ .gallery-masonry{column-gap:var(--space-md)} }
.gallery-masonry > *{
  break-inside:avoid;
  -webkit-column-break-inside:avoid;
  page-break-inside:avoid;
  margin:0 0 var(--space-sm);
  display:block;width:100%;
}

.gallery-item{
  position:relative;padding:0;border:0;width:100%;
  background:var(--tone,var(--ink-raise));
  cursor:zoom-in;
  transition:transform .5s var(--ease),filter .5s var(--ease);
}
.gallery-item img{width:100%;height:auto}
.gallery-item::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  border:1px solid rgba(228,218,213,.1);
  transition:border-color .5s var(--ease);
}
.gallery-item:hover,.gallery-item:focus-visible{filter:brightness(1.06)}
.gallery-item:hover::after,.gallery-item:focus-visible::after{border-color:var(--blush)}


/* ============================================================================
   11 · LIGHTBOX  — the element is created by meza.js. Pages must NOT write it.
   ========================================================================== */
.lightbox{
  position:fixed;inset:0;z-index:200;
  display:grid;grid-template-rows:auto 1fr auto;
  background:rgba(0,0,0,.96);
  opacity:0;visibility:hidden;
  transition:opacity .35s var(--ease),visibility .35s var(--ease);
}
.lightbox.is-open{opacity:1;visibility:visible}
.lightbox__stage{
  grid-row:2;
  display:grid;place-items:center;
  padding:0 clamp(12px,4vw,72px);
  min-height:0;
}
.lightbox__img{
  max-width:100%;max-height:100%;
  width:auto;height:auto;
  object-fit:contain;                 /* the lightbox never crops either */
  margin-inline:auto;
}
.lightbox__caption{
  grid-row:3;
  padding:var(--space-sm) var(--gut) max(20px,env(safe-area-inset-bottom));
  text-align:center;font-size:var(--fs-small);color:var(--blush);
  max-width:78ch;margin-inline:auto;
  overflow-wrap:anywhere;                /* ein langes Wort sprengt nichts —
                                            umbrechen, nie abschneiden */
}
.lightbox__bar{
  grid-row:1;
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:10px var(--gut);
}
.lightbox__count{font-size:var(--fs-eyebrow);letter-spacing:.24em;color:var(--sage)}
.lightbox__close{
  width:48px;height:48px;margin-right:-12px;position:relative;display:grid;place-items:center;
}
.lightbox__close::before,.lightbox__close::after{
  content:"";position:absolute;width:24px;height:1px;background:var(--blush-lite);
}
.lightbox__close::before{transform:rotate(45deg)}
.lightbox__close::after{transform:rotate(-45deg)}
.lightbox__prev,.lightbox__next{
  position:absolute;top:50%;transform:translateY(-50%);z-index:2;
  width:52px;height:52px;display:grid;place-items:center;
  color:var(--blush-lite);
  background:rgba(0,0,0,.4);
  border:1px solid var(--line-soft);
  font-size:1.4rem;line-height:1;
  transition:background-color var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
.lightbox__prev:hover,.lightbox__next:hover{background:rgba(0,0,0,.75);border-color:var(--blush)}
.lightbox__prev{left:max(6px,calc(var(--gut) / 2))}
.lightbox__next{right:max(6px,calc(var(--gut) / 2))}
body.has-lightbox-open{overflow:hidden}


/* ============================================================================
   12 · CARDS
   ========================================================================== */
.card-grid{display:grid;gap:var(--space-md)}
@media (min-width:640px){
  .card-grid--2{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (min-width:768px){
  .card-grid--3{grid-template-columns:repeat(3,minmax(0,1fr));align-items:start}
  .card-grid--4{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (min-width:1024px){
  .card-grid--4{grid-template-columns:repeat(4,minmax(0,1fr))}
}
/* the editorial stagger of the three boards */
@media (min-width:768px){
  .card-grid--stagger > :nth-child(2){margin-top:clamp(26px,5vw,74px)}
  .card-grid--stagger > :nth-child(3){margin-top:clamp(12px,2.4vw,36px)}
}

.board-card{display:flex;flex-direction:column}
.board-card .figure{order:-1}
.board-card__no{
  margin-top:var(--space-sm);
  font-size:var(--fs-eyebrow);letter-spacing:.3em;color:var(--sage);
}
.board-card__title{
  margin-top:var(--space-2xs);
  font-size:var(--fs-h3);color:var(--blush);
}
.board-card__text{
  margin-top:var(--space-xs);
  font-size:var(--fs-small);line-height:1.78;
  color:var(--blush-lite);opacity:.86;
  max-width:46ch;
}

.occasion-card{
  position:relative;display:block;
  background:var(--ink-raise);
  border:1px solid var(--line-soft);
  transition:border-color var(--dur) var(--ease);
}
.occasion-card:hover,.occasion-card:focus-visible{border-color:var(--blush)}
.occasion-card .figure{border:0}
.occasion-card__body{padding:var(--space-sm)}
.occasion-card__title{font-size:var(--fs-h3);color:var(--blush)}
.occasion-card__text{
  margin-top:var(--space-2xs);
  font-size:var(--fs-small);color:var(--blush-lite);opacity:.84;
}

/* numbered process steps */
.steps{display:grid;gap:var(--space-md);counter-reset:meza-step}
@media (min-width:768px){ .steps--3{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (min-width:768px){ .steps--4{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (min-width:1024px){ .steps--4{grid-template-columns:repeat(4,minmax(0,1fr))} }
.step{
  position:relative;
  padding-top:var(--space-sm);
  border-top:1px solid var(--line);
  counter-increment:meza-step;
}
.step__no{
  display:block;
  font-family:var(--font-display);font-size:clamp(1.5rem,3vw,2.1rem);
  letter-spacing:.08em;color:var(--sage);
}
.step__no::before{content:counter(meza-step,decimal-leading-zero)}
.step__title{margin-top:var(--space-2xs);font-size:var(--fs-h3);color:var(--blush)}
.step__text{margin-top:var(--space-xs);font-size:var(--fs-small);color:var(--blush-lite);opacity:.86;max-width:44ch}

/* prices — only two real numbers exist on this whole site */
.price-list{display:grid;border-top:1px solid var(--line)}
.price-row{
  display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;
  gap:.3rem 1.4rem;
  padding:var(--space-sm) 0;
  border-bottom:1px solid var(--line);
}
.price-row__k{font-size:var(--fs-small);letter-spacing:.22em;text-transform:uppercase;color:var(--blush)}
.price-row__v{font-family:var(--font-display);font-size:clamp(1.2rem,2.4vw,1.7rem);letter-spacing:.05em;color:var(--cream)}
.price-row__v--soft{
  font-family:var(--font-text);font-size:var(--fs-eyebrow);
  letter-spacing:.2em;text-transform:uppercase;color:var(--sage);
}


/* ============================================================================
   13 · FORM   (the field parts the inquiry funnel in §19 is built from)
   ========================================================================== */
.form{display:grid;gap:var(--space-sm);max-width:640px}
@media (min-width:640px){
  .form--two{grid-template-columns:repeat(2,minmax(0,1fr))}
  .field--wide{grid-column:1 / -1}
}
.field{display:flex;flex-direction:column;gap:.5rem}
.field__label{
  font-size:var(--fs-eyebrow);letter-spacing:.24em;text-transform:uppercase;color:var(--sage);
}
.field__input{
  width:100%;min-height:52px;
  padding:14px 16px;
  background:rgba(228,218,213,.05);
  border:1px solid var(--line);
  color:var(--cream);
  font-size:var(--fs-body);font-weight:300;
  transition:border-color var(--dur) var(--ease),background-color var(--dur) var(--ease);
}
textarea.field__input{min-height:150px;resize:vertical;line-height:1.7}
.field__input::placeholder{color:rgba(228,218,213,.4)}
.field__input:hover{border-color:var(--blush)}
.field__input:focus{outline:2px solid var(--sage);outline-offset:2px}

.form-note{
  font-size:var(--fs-small);color:var(--blush);opacity:.9;max-width:56ch;
}
.form-note a{border-bottom:1px solid var(--line);padding-bottom:1px}
.form-status{
  border:1px solid var(--sage-deep);
  background:rgba(148,157,127,.1);
  color:var(--cream);
  padding:var(--space-sm);
  font-size:var(--fs-small);
}
.form-status:empty{display:none}



/* ============================================================================
   14 · FAQ  (details / summary — works with JavaScript switched off)
   ========================================================================== */
.faq{display:grid;border-top:1px solid var(--line);max-width:var(--measure)}
.faq--wide{max-width:none}
.faq__item{border-bottom:1px solid var(--line)}
.faq__q{
  display:flex;align-items:center;justify-content:space-between;gap:1.2rem;
  min-height:56px;padding:var(--space-sm) 0;
  cursor:pointer;list-style:none;
  font-family:var(--font-display);font-size:var(--fs-h3);
  color:var(--blush);
  transition:color var(--dur) var(--ease);
}
.faq__q::-webkit-details-marker{display:none}
.faq__q::after{
  content:"";flex:0 0 auto;width:14px;height:14px;position:relative;
  background:
    linear-gradient(var(--sage),var(--sage)) center/14px 1px no-repeat,
    linear-gradient(var(--sage),var(--sage)) center/1px 14px no-repeat;
  transition:transform .4s var(--ease);
}
.faq__item[open] .faq__q{color:var(--cream)}
/* open = minus: drop the vertical stroke, keep the horizontal one horizontal */
.faq__item[open] .faq__q::after{
  transform:rotate(180deg);
  background:linear-gradient(var(--sage),var(--sage)) center/14px 1px no-repeat;
}
.faq__a{padding:0 0 var(--space-sm);font-size:var(--fs-small);color:var(--blush-lite);opacity:.88;max-width:62ch}


/* ============================================================================
   15 · SCROLL REVEAL
   Without JavaScript nothing is ever hidden: the hiding rule only exists
   inside .has-js, and meza.js sets that class on <html>.
   ========================================================================== */
.reveal{transition:opacity .9s var(--ease),transform .9s var(--ease);transition-delay:var(--d,0ms)}
.has-js .reveal{opacity:0;transform:translateY(20px)}
.has-js .reveal.is-visible{opacity:1;transform:none}
.reveal--d1{--d:110ms}
.reveal--d2{--d:220ms}
.reveal--d3{--d:330ms}


/* ============================================================================
   16 · REDUCED MOTION — every animation off, nothing hidden, nothing moving
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.001ms!important;
    animation-iteration-count:1!important;
    animation-delay:0s!important;
    transition-duration:.001ms!important;
    transition-delay:0s!important;
    scroll-behavior:auto!important;
  }
  .hero-mosaic__track{animation:none!important;transform:none!important}
  .hero-mosaic__cue i{animation:none!important;transform:none!important;opacity:.6}
  .hero-plate__fill img{animation:none!important;transform:scale(1.18)!important}
  .has-js .reveal{opacity:1!important;transform:none!important}
  .gallery-item:hover{filter:none}
}


/* ============================================================================
   17 · SEITENWECHSEL — weiche Uebergaenge zwischen den sieben Seiten

   Zwei Ebenen, beide ohne JavaScript:
   (a) View Transitions: moderne Browser blenden beim Navigieren weich um.
       Kein Skript, kein Klick-Abfangen — die Seite bleibt eine normale
       Multi-Page-Website und funktioniert auch ohne die Technik.
   (b) Fallback: jede Seite steigt beim Laden sanft auf. Greift ueberall,
       wo (a) fehlt, und stoert dort nicht, wo (a) laeuft.
   ========================================================================== */
@view-transition{ navigation:auto }

::view-transition-old(root){
  animation:meza-page-out .26s cubic-bezier(.4,0,1,1) both;
}
::view-transition-new(root){
  animation:meza-page-in .46s cubic-bezier(0,0,.2,1) both;
}
@keyframes meza-page-out{
  from{opacity:1;transform:translateY(0) scale(1)}
  to  {opacity:0;transform:translateY(-10px) scale(.994)}
}
@keyframes meza-page-in{
  from{opacity:0;transform:translateY(14px) scale(1.006)}
  to  {opacity:1;transform:translateY(0) scale(1)}
}

/* (b) Fallback fuer Browser ohne View Transitions */
@supports not (view-transition-name:none){
  body{animation:meza-page-in .5s cubic-bezier(0,0,.2,1) both}
}

/* Ruhebeduerfnis schlaegt Effekt — hier wird sauber alles abgeschaltet */
@media (prefers-reduced-motion:reduce){
  ::view-transition-old(root),
  ::view-transition-new(root){animation:none!important}
  @supports not (view-transition-name:none){
    body{animation:none!important}
  }
}


/* ============================================================================
   18 · BILD-VERZERRUNGS-SPERRE
   Ein <img> in einem Spalten-Flex oder Grid wird standardmaessig auf die volle
   Breite GEDEHNT (align-items:stretch) und verliert dabei sein Seitenverhaeltnis.
   Genau so war das Logo im Footer verzogen. Diese Regel schliesst die ganze
   Klasse, nicht nur den einen Fall.
   ========================================================================== */
img{align-self:start}
.hero-plate__photo img,
.hero-mosaic__tile img,
.gallery-item img,
.figure img{align-self:auto}


/* ============================================================================
   20 · LOGIN-BEREICH  (site/admin.html + assets/js/meza-admin.js)

   Alisa's login area. Same brand as the website — black ground, blush type,
   Italiana for the headings — but deliberately quiet: this is a tool, not a
   shop window. It is the ONLY page that uses these classes; nothing here can
   reach the seven public pages.

   .admin-bar ........ sticky top bar: wordmark, what this is, sign out
   .admin-main ....... the page body
   .admin-panel ...... one of the three screens (--narrow for the sign-in card)
   .admin-title  .admin-h2  .admin-head  .admin-count  .admin-block
   .admin-note ....... one honest sentence (--ok sage rule | --warn blush rule)
   .admin-drop ....... the big "Add photos" box (.is-over while dragging)
   .admin-queue ...... photographs waiting: preview, saved size, description
   .admin-progress ... the upload bar
   .admin-grid ....... what is in the gallery (.admin-tile, .is-hidden)
   .admin-confirm .... the written question before anything is removed
   .btn--sm .......... small button, still a 44px touch target
   .admin-foot ....... two links back to the website

   No photograph is ever cropped in here either: the tiles are square boxes and
   the picture sits inside them with object-fit:contain, so she always sees the
   whole frame she is deciding about.
   ========================================================================== */

/* [hidden] must win over the display rules below — one line for every element
   on this page instead of a :not() clause on each class */
.admin-page [hidden]{display:none!important}

.admin-page{background:var(--ink)}

/* --- bar ------------------------------------------------------------------ */
.admin-bar{
  position:sticky;top:0;z-index:60;
  background:rgba(0,0,0,.96);
  border-bottom:1px solid var(--line-soft);
}
.admin-bar__in{
  width:100%;max-width:var(--maxw);margin-inline:auto;
  padding:8px var(--gut);
  display:flex;align-items:center;gap:var(--space-xs);
}
.admin-bar .brand img{width:auto;height:clamp(22px,3vw,30px)}
.admin-bar__label{
  display:none;
  font-size:var(--fs-eyebrow);letter-spacing:.28em;text-transform:uppercase;color:var(--sage);
}
@media (min-width:560px){ .admin-bar__label{display:block} }
.admin-bar .btn{margin-left:auto}

/* --- page + panels -------------------------------------------------------- */
.admin-main{
  width:100%;max-width:var(--maxw);margin-inline:auto;
  padding:var(--space-lg) var(--gut) var(--space-xl);
}
.admin-panel--narrow{max-width:32rem;margin-inline:auto}

.admin-title{
  margin-top:var(--space-2xs);
  font-family:var(--font-display);font-weight:400;
  font-size:var(--fs-h2);line-height:1.1;letter-spacing:.03em;color:var(--cream);
}
/* (Fokusrahmen: siehe die klassenweite Regel bei :focus-visible ganz oben) */
.admin-panel .lede{margin-top:var(--space-sm)}
.admin-panel .form{margin-top:var(--space-md)}

.admin-head{
  display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;
  gap:var(--space-xs) var(--space-md);
}
.admin-count{
  font-size:var(--fs-eyebrow);letter-spacing:.24em;text-transform:uppercase;color:var(--blush);
}
.admin-block{
  margin-top:var(--space-lg);
  padding-top:var(--space-md);
  border-top:1px solid var(--line-soft);
}
.admin-h2{
  font-family:var(--font-display);font-weight:400;
  font-size:var(--fs-h3);letter-spacing:.06em;color:var(--blush);
}
.admin-empty{margin-top:var(--space-sm);font-size:var(--fs-small);color:var(--blush-lite);opacity:.8}

/* --- one honest sentence --------------------------------------------------
   Colour alone never carries the meaning (it also has to work for anyone who
   cannot tell sage from blush): the wording says what happened, the rule on
   the left only supports it. */
.admin-note{
  display:block;margin-top:var(--space-sm);
  padding:var(--space-xs) var(--space-sm);
  border:1px solid var(--line);border-left:3px solid var(--sage);
  background:rgba(228,218,213,.05);
  font-size:var(--fs-small);line-height:1.65;color:var(--blush-lite);
  max-width:78ch;
}
.admin-note--ok{border-left-color:var(--sage)}
.admin-note--warn{border-left-color:var(--blush);background:rgba(201,187,180,.10);color:var(--cream)}
.admin-note__link{
  display:inline-flex;align-items:center;min-height:44px;
  margin-left:.2em;
  color:var(--blush);border-bottom:1px solid var(--line);
}
.admin-note__link:hover,.admin-note__link:focus-visible{color:var(--cream)}

/* --- the add box ---------------------------------------------------------- */
.admin-drop{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.45rem;text-align:center;
  width:100%;min-height:160px;
  margin-top:var(--space-sm);
  padding:var(--space-md) var(--space-sm);
  border:1px dashed var(--line);
  background:var(--ink-raise);
  color:var(--blush-lite);
  transition:border-color var(--dur) var(--ease),background-color var(--dur) var(--ease);
}
.admin-drop:hover,.admin-drop:focus-visible{border-color:var(--blush);background:rgba(228,218,213,.07)}
.admin-drop.is-over{border-color:var(--sage);border-style:solid;background:rgba(148,157,127,.14)}
.admin-drop[aria-disabled="true"],
.admin-drop:disabled{opacity:.5;cursor:not-allowed}
.admin-drop__title{
  font-family:var(--font-display);font-size:var(--fs-h3);letter-spacing:.08em;color:var(--blush);
}
.admin-drop__hint{font-size:var(--fs-small);max-width:46ch}
.admin-drop__meta{
  font-size:var(--fs-eyebrow);letter-spacing:.18em;text-transform:uppercase;color:var(--sage);
}

/* --- the waiting list ----------------------------------------------------- */
.admin-queue{display:grid;gap:var(--space-sm);margin-top:var(--space-sm)}
.admin-queue__item{
  display:grid;grid-template-columns:72px minmax(0,1fr);
  gap:var(--space-xs) var(--space-sm);align-items:start;
  padding:var(--space-xs);
  border:1px solid var(--line-soft);
  background:var(--ink-raise);
}
@media (min-width:640px){
  .admin-queue__item{grid-template-columns:110px minmax(0,1fr)}
}
.admin-queue__item.is-error{border-color:var(--blush)}
.admin-queue__thumb{
  width:100%;height:auto;aspect-ratio:1;
  object-fit:contain;object-position:center center;
  background:var(--ink-soft);
}
.admin-queue__body{display:flex;flex-direction:column;gap:.5rem;min-width:0}
.admin-queue__name{
  font-size:var(--fs-small);color:var(--cream);
  overflow-wrap:anywhere;
}
.admin-queue__size{
  font-size:var(--fs-eyebrow);letter-spacing:.14em;text-transform:uppercase;color:var(--sage);
}
.admin-queue__status{font-size:var(--fs-small);color:var(--cream)}
.admin-queue__status:empty{display:none}
.admin-queue__actions{display:flex;flex-wrap:wrap;gap:.4rem}

.admin-progress{
  height:4px;width:100%;
  background:rgba(228,218,213,.14);
  overflow:hidden;
}
.admin-progress__bar{
  display:block;height:100%;width:0;
  background:var(--sage);
  transition:width .2s linear;
}

/* --- what is in the gallery ----------------------------------------------- */
.admin-grid{
  display:grid;gap:var(--space-sm);
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  margin-top:var(--space-sm);
}
@media (min-width:768px){
  .admin-grid{grid-template-columns:repeat(auto-fill,minmax(210px,1fr))}
}
.admin-tile{
  display:flex;flex-direction:column;min-width:0;
  border:1px solid var(--line-soft);
  background:var(--ink-raise);
}
.admin-tile.is-hidden{opacity:.62}
.admin-tile[aria-busy="true"]{opacity:.45}
.admin-tile__img{
  width:100%;height:auto;aspect-ratio:1;
  object-fit:contain;object-position:center center;   /* never a crop */
  background:var(--ink-soft);
}
.admin-tile__body{
  display:flex;flex-direction:column;gap:.5rem;
  padding:var(--space-xs);flex:1 1 auto;
}
.admin-badge{
  font-size:var(--fs-eyebrow);letter-spacing:.18em;text-transform:uppercase;color:var(--sage);
}
.admin-tile.is-hidden .admin-badge{color:var(--blush)}
/* Die Beschreibung steht in §29 — hier stand frueher ein Zeilendeckel
   (-webkit-line-clamp:3), also genau der Fehler, den §29 behebt. */
.admin-tile__actions{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:auto}

.admin-confirm{
  display:grid;gap:.6rem;
  margin-top:auto;padding-top:.6rem;
  border-top:1px solid var(--line);
}
.admin-confirm p{font-size:var(--fs-small);line-height:1.5;color:var(--cream)}
.admin-confirm__row{display:flex;flex-wrap:wrap;gap:.4rem}

/* --- small button, full-size touch target --------------------------------- */
.btn--sm{
  min-height:44px;
  padding:0 clamp(12px,2vw,18px);
  font-size:.66rem;letter-spacing:.16em;
}

/* --- foot ----------------------------------------------------------------- */
.admin-foot{
  border-top:1px solid var(--line-soft);
  padding:var(--space-sm) var(--gut) max(var(--space-sm),env(safe-area-inset-bottom));
  display:flex;flex-wrap:wrap;align-items:center;gap:.4rem clamp(18px,3vw,32px);
  font-size:var(--fs-eyebrow);letter-spacing:.22em;text-transform:uppercase;color:var(--sage);
}
.admin-foot a{
  display:inline-flex;align-items:center;min-height:44px;
  color:var(--blush);border-bottom:1px solid var(--line);
}
.admin-foot a:hover,.admin-foot a:focus-visible{color:var(--cream)}


/* ============================================================================
   19 · ANFRAGE-TRICHTER — the inquiry funnel on contact.html

   ONE question per screen, big tap targets, no typing until the last step.

   The whole progressive-enhancement trick lives in this section and nowhere
   else: the markup is an ORDINARY form. Everything in it is visible and
   usable, one step under the other, and it posts to /api/contact all by
   itself. Only the .has-js class that meza.js puts on <html> stacks the steps
   on top of each other and turns them into a funnel. Nothing is ever hidden
   from a visitor without JavaScript.

   Classes added here
     .funnel (.is-sent)  .funnel__progress  .funnel__count
     .funnel__bar  .funnel__bar-fill  .funnel__stage
     .funnel-step (.is-active|.is-out)  .funnel-step__q  .funnel-step__hint
     .opt-grid (--3)  .opt  .opt__input  .opt__label  .opt__big  .opt__sub
     .funnel__reveal (.is-shown)  .funnel__row  .funnel__jsonly
     .funnel__nav  .funnel__quiet  .funnel__spacer  .funnel__req
     .funnel__hp  .funnel__done  .funnel__done-lede  .funnel__done-copy
     .funnel__recap
     modifiers on existing components: .form-status--error, .btn[aria-pressed],
     .btn[disabled]
   ========================================================================== */

.funnel{display:grid;gap:var(--space-md);max-width:820px}
.funnel.is-sent{display:none}          /* replaced by the thank-you panel */

/* --- progress -------------------------------------------------------------
   Without JavaScript there are no steps to count, so it stays away. */
.funnel__progress{display:none}
.has-js .funnel__progress{display:grid;gap:.7rem}
.funnel__count{
  font-size:var(--fs-eyebrow);letter-spacing:.28em;text-transform:uppercase;
  color:var(--sage);
}
.funnel__bar{height:2px;background:var(--line)}
.funnel__bar-fill{
  display:block;height:100%;width:14.2857%;
  background:var(--sage);
  transition:width .42s var(--ease);
}

/* --- the steps ------------------------------------------------------------ */
.funnel__stage{display:grid;gap:var(--space-xl)}
.has-js .funnel__stage{gap:0;min-height:clamp(340px,42vh,460px);align-content:start}

.funnel-step{display:grid;gap:var(--space-sm);align-content:start}
.has-js .funnel-step{display:none}
.has-js .funnel-step.is-active{display:grid;animation:funnel-in .22s var(--ease) both}
.has-js .funnel-step.is-out{animation:funnel-out .12s var(--ease) both}
@keyframes funnel-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes funnel-out{from{opacity:1}to{opacity:0}}

.funnel-step__q{
  font-size:clamp(1.5rem,3.6vw,2.2rem);
  color:var(--cream);
  max-width:24ch;
}
.funnel-step__hint{
  margin-top:calc(var(--space-sm) * -1 + var(--space-3xs));
  font-size:var(--fs-small);color:var(--blush-lite);opacity:.8;max-width:52ch;
}
.funnel__req{
  margin-left:.5em;
  font-size:var(--fs-eyebrow);letter-spacing:.18em;color:var(--sage);opacity:.9;
}

/* --- the tap cards --------------------------------------------------------
   A real <input type="radio"> lies invisibly OVER its card. That buys three
   things for free and costs no script: it submits without JavaScript, arrow
   keys move between the cards, and Space selects — all native behaviour.
   The label is only the picture of the choice. */
.opt-grid{display:grid;gap:var(--space-xs);grid-template-columns:minmax(0,1fr)}
@media (min-width:560px){ .opt-grid{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (min-width:900px){ .opt-grid--3{grid-template-columns:repeat(3,minmax(0,1fr))} }

.opt{position:relative;display:block}
.opt__input{
  position:absolute;inset:0;z-index:2;
  width:100%;height:100%;margin:0;padding:0;
  opacity:0;cursor:pointer;
  -webkit-appearance:none;appearance:none;border:0;
}
.opt__label{
  position:relative;display:flex;flex-direction:column;justify-content:center;gap:.15rem;
  min-height:68px;                       /* touch target, far above 44px */
  padding:16px 54px 16px 20px;
  background:var(--ink-raise);
  border:1px solid var(--line);
  color:var(--cream);
  font-size:var(--fs-body);line-height:1.35;
  transition:border-color var(--dur) var(--ease),
             background-color var(--dur) var(--ease),
             color var(--dur) var(--ease);
}
.opt__label::after{                      /* the mark that shows the choice */
  content:"";position:absolute;top:50%;right:18px;transform:translateY(-50%);
  width:18px;height:18px;border-radius:50%;
  border:1px solid var(--line);
  transition:background-color var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
.opt__big{
  font-family:var(--font-display);font-weight:400;
  font-size:clamp(1.35rem,3vw,1.8rem);letter-spacing:.04em;line-height:1.1;
  color:var(--cream);
}
.opt__sub{
  font-size:var(--fs-eyebrow);letter-spacing:.22em;text-transform:uppercase;
  color:var(--sage);
}

/* on the cream ground a card wants real white paper — same reason as
   .section--cream .field__input in §09. Must stand BEFORE the states below,
   otherwise it would win against them on equal specificity. */
.section--cream .opt__label{background:#fff}

.opt__input:hover + .opt__label{border-color:var(--sage)}
.opt__input:checked + .opt__label{border-color:var(--sage);background:rgba(148,157,127,.14)}
.opt__input:checked + .opt__label::after{background:var(--sage);border-color:var(--sage)}
.opt__input:focus-visible + .opt__label{outline:2px solid var(--sage);outline-offset:3px}

/* --- the box one option opens (Somewhere else → where?) -------------------
   JavaScript only: without it the option is answered by the card alone and
   the detail belongs in the message field. */
.funnel__reveal{display:none}
.funnel__reveal.is-shown{display:grid;gap:.5rem;animation:funnel-in .22s var(--ease) both}

/* --- the date row --------------------------------------------------------- */
.funnel__row{display:flex;flex-wrap:wrap;gap:var(--space-xs);align-items:center}
.funnel__row .field__input{flex:1 1 200px;min-width:0}
.funnel__row .field__input:disabled{opacity:.45}

/* buttons that only mean something once a script is running */
.funnel__jsonly{display:none}
.has-js .funnel__jsonly{display:inline-flex}

/* --- step navigation (Back · Continue · Skip) ----------------------------- */
.funnel__nav{display:none}
.has-js .funnel__nav{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-xs);
  margin-top:var(--space-2xs);
}
.funnel__spacer{flex:1 1 auto}
.funnel__quiet{
  display:inline-flex;align-items:center;
  min-height:44px;padding:0 2px;
  font-size:var(--fs-eyebrow);letter-spacing:.22em;text-transform:uppercase;
  color:var(--sage);
  border-bottom:1px solid var(--line);
  transition:color var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
.funnel__quiet:hover,.funnel__quiet:focus-visible{color:var(--cream);border-bottom-color:var(--blush)}

.btn[aria-pressed="true"]{background:var(--blush);border-color:var(--blush);color:var(--ink)}
.btn[disabled]{opacity:.55;cursor:default}

/* --- the honeypot --------------------------------------------------------
   Off the screen instead of display:none, because a bot reads the stylesheet
   too — and a field that is merely hidden still gets filled in by one. */
.funnel__hp{
  position:absolute;left:-9999px;top:auto;
  width:1px;height:1px;overflow:hidden;
}

/* --- the thank-you panel -------------------------------------------------- */
.funnel__done{display:none}
.funnel__done.is-shown{display:grid;gap:var(--space-sm);max-width:820px;animation:funnel-in .34s var(--ease) both}
.funnel__done-lede{font-size:var(--fs-lede);color:var(--blush-lite);max-width:var(--measure)}
.funnel__done-copy{font-size:var(--fs-small);color:var(--blush-lite);max-width:var(--measure)}
.funnel__done-copy:empty{display:none}

.funnel__recap{display:grid;border-top:1px solid var(--line)}
.funnel__recap > div{
  display:grid;gap:2px;
  padding:12px 0;border-bottom:1px solid var(--line);
}
@media (min-width:560px){
  .funnel__recap > div{grid-template-columns:190px minmax(0,1fr);gap:1rem;align-items:baseline}
}
.funnel__recap dt{
  font-size:var(--fs-eyebrow);letter-spacing:.22em;text-transform:uppercase;color:var(--sage);
}
.funnel__recap dd{
  margin:0;color:var(--cream);font-size:var(--fs-small);line-height:1.6;
  white-space:pre-wrap;overflow-wrap:anywhere;
}

/* --- an inquiry that did NOT go out --------------------------------------- */
.form-status--error{border-color:var(--blush);background:rgba(201,187,180,.14)}
.form-status p{margin:0}
.form-status p + p{margin-top:.6rem}

/* --- nothing moves for anyone who asked for stillness ---------------------
   §16 already switches every animation off with !important; this only keeps
   the funnel from being invisible if a browser skips the fill mode. */
@media (prefers-reduced-motion:reduce){
  .has-js .funnel-step.is-active,
  .funnel__reveal.is-shown,
  .funnel__done.is-shown{animation:none!important;opacity:1!important;transform:none!important}
}


/* ============================================================================
   21 · LOGIN-LINK IN DER FUSSZEILE
   Alisa soll ihren Bereich ohne Lesezeichen wiederfinden. Fuer Besucher ist er
   bewusst zurueckhaltend, aber lesbar — nicht versteckt, nur leise.
   rel="nofollow" + noindex auf der Zielseite halten ihn aus Google heraus.
   ========================================================================== */
.site-footer__admin{
  color:var(--blush);opacity:.55;
  text-decoration:none;
  display:inline-flex;align-items:center;min-height:44px;
  padding:9px 8px;margin:-9px -8px;
}
.site-footer__admin:hover,
.site-footer__admin:focus-visible{opacity:1;color:var(--cream)}


/* ============================================================================
   22 · BEARBEITEN-MODUS  (assets/js/meza-edit.js)

   Alisa meldet sich an und oeffnet die normale Website. Erst dann baut
   meza-edit.js die Leiste unten — und nur dann, wenn der SERVER canEdit:true
   gesagt hat. Ein Besucher sieht von allem hier nichts: keine Klasse landet je
   auf seiner Seite, weil das Skript sie gar nicht erst setzt.

   .meza-edit ............ die Leiste (immer sichtbar, unten)
   .meza-edit__status .... ein ehrlicher Satz (.is-warn = der Server hat etwas
                           zu beanstanden)
   .meza-edit__actions ... Bearbeiten · Speichern · Verwerfen · Fotos
   .meza-edit-field ...... ein Text, der gerade angefasst werden kann
   html.meza-editing ..... waehrend des Bearbeitens: alles, was die Seite sonst
                           erst beim Scrollen oder beim Klicken zeigt, ist
                           sichtbar — sonst waeren die Fragen 2-7 des Trichters
                           und die eingeklappten Antworten nicht erreichbar.
   ========================================================================== */
.meza-edit{
  position:fixed;left:0;right:0;bottom:0;z-index:80;
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2xs) var(--space-sm);
  padding:10px var(--gut) max(10px,env(safe-area-inset-bottom));
  background:rgba(0,0,0,.94);
  border-top:1px solid var(--line);
  color:var(--blush-lite);
}
@supports (backdrop-filter:blur(8px)){
  /* kein Blur ueber bewegtem Inhalt — die Leiste steht still, der Hero nicht.
     Deshalb liegt der Weichzeichner NUR auf der Leiste selbst. */
  .meza-edit{background:rgba(0,0,0,.82);backdrop-filter:blur(10px)}
}
.meza-edit__status{
  flex:1 1 16rem;min-width:0;
  font-size:var(--fs-small);line-height:1.5;color:var(--blush-lite);
  max-width:64ch;
}
.meza-edit__status.is-warn{color:var(--cream)}
.meza-edit__status.is-warn::before{
  content:"";display:inline-block;vertical-align:middle;
  width:8px;height:8px;margin-right:.5rem;
  background:var(--blush);
}
.meza-edit__actions{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem}
/* .btn is display:inline-flex, and that beats the plain [hidden] attribute.
   Eine Zeile fuer alle Knoepfe der Leiste statt einer Sonderregel je Knopf —
   dasselbe Muster wie im Login-Bereich (§20). */
.meza-edit [hidden]{display:none!important}
.meza-edit__link{
  display:inline-flex;align-items:center;min-height:44px;padding:0 8px;
  font-size:var(--fs-eyebrow);letter-spacing:.2em;text-transform:uppercase;
  color:var(--blush);
}
.meza-edit__link:hover,.meza-edit__link:focus-visible{color:var(--cream)}

/* damit die Leiste nichts verdeckt, was ganz unten steht. Die Klasse setzt
   meza-edit.js, wenn es die Leiste baut — also nur bei gueltiger Sitzung. */
/* Die Hoehe misst die Leiste selbst und schreibt sie in --meza-bar-h: eine
   laengere Meldung macht sie hoeher, und dann rueckt auch die Seite nach.
   5.5rem ist nur der Wert fuer den Augenblick vor der ersten Messung. */
.meza-has-bar{padding-bottom:calc(var(--meza-bar-h,5.5rem) + 8px)}

/* --- ein Text, der angefasst werden kann ---------------------------------- */
.meza-edit-field{
  outline:1px dashed var(--line);
  outline-offset:4px;
  border-radius:2px;
  cursor:text;
}
.meza-edit-field:hover{outline-color:var(--blush)}
.meza-edit-field:focus{
  outline:2px solid var(--sage);
  outline-offset:4px;
  background:rgba(148,157,127,.10);
}
/* auf dem cremefarbenen Grund muss der Rahmen dunkel sein, sonst sieht sie ihn nicht */
.section--cream .meza-edit-field{outline-color:var(--line-cream)}
.section--cream .meza-edit-field:hover{outline-color:var(--on-cream-soft)}

/* Eine geleerte Zeile hat keine Hoehe mehr und waere nicht wieder antippbar.
   Der erzeugte Text gibt ihr eine — und sagt zugleich, was Speichern tut.
   Erzeugter Inhalt ist nicht bearbeitbar, kann also nie mitgespeichert werden. */
.meza-edit-field.is-empty{outline-color:var(--blush)}
.meza-edit-field.is-empty::after{
  content:"empty — Save puts back the wording the site ships with";
  font-family:var(--font-text);font-weight:400;font-size:var(--fs-small);
  font-style:normal;letter-spacing:0;text-transform:none;line-height:1.6;
  color:var(--blush);opacity:.75;
}

/* --- waehrend des Bearbeitens ist NICHTS versteckt ------------------------ */
.meza-editing .reveal{opacity:1!important;transform:none!important}
.meza-editing .funnel-step{display:grid!important;animation:none!important}
.meza-editing .funnel__reveal{display:grid!important;gap:.5rem;animation:none!important}


/* ============================================================================
   24 · BILDAUSWAHL  (assets/js/meza-edit.js)

   Alisa ist angemeldet und hat "Edit page" gedrueckt. Dann — und nur dann —
   setzt meza-edit.js die Klassen hier: jedes austauschbare Bild bekommt einen
   Rahmen und ein kleines Wort, ein Klick oeffnet die Auswahl. Ein Besucher
   sieht davon nichts, weil das Skript nichts davon setzt: keine Klasse, kein
   Rahmen, kein Wort. Der SERVER entscheidet das (canEdit), nicht der Browser.

   Das Bild im HERO ist nie dabei. Das ist keine Stilfrage: meza-edit.js
   verweigert jede Markierung in .hero-mosaic und .hero-plate.

   .meza-swap ........... ein Bild, das gerade getauscht werden kann
   .meza-swap__tag ...... das kleine Wort "Change photo" in der Ecke
   .meza-pick ........... die Auswahl (.is-open)
   .meza-pick__panel .... die Karte darin
   .meza-pick__head ..... Titel + Schliessen
   .meza-pick__reset .... "Use the original photo" — der Rueckweg, ganz oben
   .meza-pick__note ..... eine ehrliche Zeile (laedt · nichts da · Anzahl)
   .meza-pick__grid ..... das Raster
   .meza-pick__item ..... eine Kachel (.is-on = das Bild, das gerade gilt)
   body.has-pick-open ... Sperre gegen das Scrollen dahinter

   WARUM DER RAHMEN IMMER DA IST UND NICHT ERST BEIM UEBERFAHREN
   Auf dem Handy gibt es kein Ueberfahren. Waere der Rahmen nur auf :hover, saehe
   sie am Telefon ueberhaupt nicht, welches Bild antippbar ist. Der Rahmen ist
   deshalb immer da, aber leise — genau wie bei den Texten (§22) — und wird beim
   Ueberfahren und beim Tastatur-Fokus deutlich. Eine Regel, beide Geraete.
   ========================================================================== */

/* --- ein Bild, das angefasst werden kann ---------------------------------- */
/* outline statt border: eine Linie, die NICHTS verschiebt. Ein Rahmen mit
   border wuerde jedes Bild um 2px wachsen lassen und die Seite im
   Bearbeiten-Modus anders aussehen lassen als im Normalfall. */
.meza-swap{
  position:relative;
  outline:1px dashed var(--line);
  outline-offset:4px;
  cursor:pointer;
}
.meza-swap:hover,
.meza-swap:focus-visible{outline:2px solid var(--sage);outline-offset:4px}
/* auf dem cremefarbenen Grund muss die Linie dunkel sein, sonst sieht sie sie nicht */
.section--cream .meza-swap{outline-color:var(--line-cream)}

.meza-swap__tag{
  position:absolute;top:8px;left:8px;z-index:2;
  pointer-events:none;                 /* der Klick gehoert dem Bild darunter */
  padding:5px 9px;
  background:rgba(0,0,0,.72);
  color:var(--blush-lite);
  font-family:var(--font-text);font-weight:400;
  font-size:var(--fs-eyebrow);letter-spacing:.16em;text-transform:uppercase;
  line-height:1;
  opacity:.72;
  transition:opacity var(--dur) var(--ease),background-color var(--dur) var(--ease);
}
.meza-swap:hover .meza-swap__tag,
.meza-swap:focus-visible .meza-swap__tag{opacity:1;background:rgba(0,0,0,.88)}

/* --- die Auswahl ---------------------------------------------------------- */
/* z-index 210: ueber der Bearbeiten-Leiste (80) und ueber der Lupe (200). */
.meza-pick{
  position:fixed;inset:0;z-index:210;
  display:grid;place-items:center;
  padding:var(--space-sm) var(--gut);
  background:rgba(0,0,0,.92);
  opacity:0;visibility:hidden;
  transition:opacity .3s var(--ease),visibility .3s var(--ease);
}
.meza-pick.is-open{opacity:1;visibility:visible}
body.has-pick-open{overflow:hidden}

.meza-pick__panel{
  width:100%;max-width:960px;
  max-height:min(88vh,880px);
  display:flex;flex-direction:column;min-height:0;
  padding:var(--space-sm) var(--space-sm) max(var(--space-sm),env(safe-area-inset-bottom));
  background:var(--ink-soft);
  border:1px solid var(--line-soft);
}

.meza-pick__head{
  display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);
  flex:0 0 auto;
}
.meza-pick__title{
  font-family:var(--font-display);font-weight:400;
  font-size:var(--fs-h3);color:var(--cream);
  letter-spacing:.025em;line-height:1.2;
}
.meza-pick__close{
  width:48px;height:48px;margin-right:-10px;
  position:relative;display:grid;place-items:center;flex:0 0 auto;
}
.meza-pick__close::before,.meza-pick__close::after{
  content:"";position:absolute;width:22px;height:1px;background:var(--blush-lite);
}
.meza-pick__close::before{transform:rotate(45deg)}
.meza-pick__close::after{transform:rotate(-45deg)}

/* Der Rueckweg steht GANZ OBEN und ueber die ganze Breite: er ist keine
   Kachel unter vielen, sondern die eine Antwort auf "ich will es wieder wie
   vorher". Er braucht die Galerie nicht und funktioniert deshalb auch dann,
   wenn kein einziges Bild geladen werden konnte. */
.meza-pick__reset{
  flex:0 0 auto;
  margin-top:var(--space-xs);
  display:flex;align-items:center;justify-content:center;
  width:100%;min-height:48px;padding:0 var(--space-sm);
  border:1px solid var(--line);
  color:var(--blush-lite);
  font-size:var(--fs-btn);letter-spacing:.18em;text-transform:uppercase;
  transition:border-color var(--dur) var(--ease),color var(--dur) var(--ease);
}
.meza-pick__reset:hover,
.meza-pick__reset:focus-visible{border-color:var(--sage);color:var(--cream)}

.meza-pick__note{
  flex:0 0 auto;
  margin-top:var(--space-xs);
  font-size:var(--fs-small);line-height:1.55;color:var(--blush);
}
.meza-pick__note:empty{display:none}

/* Das Raster ist das Einzige, was scrollt — Titel, Rueckweg und Zeile bleiben
   stehen, damit der Rueckweg nie ausserhalb des Bildes liegt. */
.meza-pick__grid{
  flex:1 1 auto;min-height:0;overflow-y:auto;
  -webkit-overflow-scrolling:touch;
  margin-top:var(--space-xs);
  display:grid;gap:var(--space-xs);
  grid-template-columns:repeat(auto-fill,minmax(116px,1fr));
}
@media (min-width:768px){
  .meza-pick__grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
}

/* Dieselbe Kachel wie in der Startseiten-Auswahl (§23): das Foto liegt in
   einem quadratischen Kasten und wird HINEINGELEGT, nicht hineingeschnitten —
   sie soll das ganze Bild sehen, ueber das sie entscheidet. */
.meza-pick__item{
  position:relative;display:block;min-width:0;padding:0;text-align:left;
  border:1px solid var(--line-soft);
  background:var(--ink-raise);
  transition:border-color var(--dur) var(--ease);
}
.meza-pick__item:hover{border-color:var(--blush)}
.meza-pick__item.is-on{border-color:var(--sage)}
/* das Bild, das gerade gilt, traegt sein Haekchen sichtbar — nicht nur als
   Rahmenfarbe, denn Farbe allein ist keine Auskunft */
.meza-pick__item.is-on::before{
  content:"✓";
  position:absolute;top:8px;left:8px;z-index:2;
  width:26px;height:26px;
  display:flex;align-items:center;justify-content:center;
  background:var(--sage);color:var(--ink);
  font-size:.8rem;line-height:1;
}

.meza-pick__img{
  width:100%;height:auto;aspect-ratio:1;
  object-fit:contain;object-position:center center;   /* nie ein Schnitt */
  background:var(--ink-soft);
}
.meza-pick__name{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  padding:8px var(--space-2xs) 0;
  margin-bottom:10px;
  height:calc(2.9em + 8px);
  font-size:var(--fs-eyebrow);line-height:1.45;letter-spacing:.02em;
  color:var(--blush-lite);opacity:.85;
}


/* ============================================================================
   25 · WEICHE BILDECKEN

   Cyrill: "alle Bilder Ecken abrunden, nicht stark, einfach ein wenig, damit
   die Ecken nicht so hart sind."

   EIN Wert fuer die ganze Seite. Wer die Rundung spaeter aendern will, aendert
   --img-radius — nicht dreissig einzelne Regeln.

   Bewusst NICHT gerundet: der randlose Innenseiten-Hero (.hero-plate). Der
   laeuft von Bildschirmrand zu Bildschirmrand; eine Rundung an einer Kante,
   die es gar nicht gibt, saehe nach Fehler aus.

   overflow:hidden gehoert an den KASTEN, nicht ans Bild: ein Bild mit
   object-fit:cover ragt sonst mit eckigen Ecken ueber die runde Box hinaus.
   ========================================================================== */
:root{ --img-radius:6px }

.figure,
.figure img,
.figure--frame,
.gallery-item,
.gallery-item img,
.hero-mosaic__tile,
.board-card img,
.occasion-card img,
.media-duo img,
.media-offset img,
.band img,
.admin-tile,
.admin-tile img,
.admin-queue img,
.meza-pick__item,
.meza-pick__img{
  border-radius:var(--img-radius);
}

/* Kaesten, die ein Bild beschneiden, muessen selbst abschneiden — sonst
   stehen die eckigen Bildecken ueber der runden Box. */
.figure,
.gallery-item,
.hero-mosaic__tile,
.admin-tile,
.meza-pick__item{
  overflow:hidden;
}

/* Der Rahmen-Effekt der .figure--frame liegt als ::after darueber und muss
   dieselbe Rundung tragen, sonst schneidet er die Ecken wieder eckig. */
.figure--frame::after,
.gallery-item::after,
.hero-mosaic__tile::after{
  border-radius:var(--img-radius);
}

/* Das grosse Bild in der Lightbox ebenfalls — dort ist es am sichtbarsten. */
.lightbox__img{ border-radius:calc(var(--img-radius) + 2px) }


/* ============================================================================
   26 · EINE ZELLE, EIN BILD  (Abschnitts-Layouts .media-duo / .media-offset)

   BEFUND, gemessen auf boards.html bei 1440px:
     .media-duo lag zweimal falsch im HTML — <figure> und die dazugehoerige
     <p class="figure__caption"> standen als ZWEI Kinder nebeneinander statt
     zusammen in EINER Zelle. Ein Raster verteilt Kinder auf Zellen, also
     landete die Unterschrift in der zweiten Spalte NEBEN ihrem Bild, das
     zweite Detailfoto fiel aus dem Raster heraus (582px statt 269px), und das
     grosse Leitbild rutschte ganz aus .media-offset auf die volle Blattbreite
     (1238px — daher die 9331px lange Seite und die Ueberlappungen).

   Der Deckel ".section .figure--frame{max-width:560px}", der hier stand, war
   nur das Pflaster darauf: er verkleinerte ein Bild, das gar nicht zu gross
   war, sondern am falschen Ort stand. Mit dem reparierten HTML bestimmt
   wieder die Spalte die Groesse, und der Deckel ist ersatzlos GELOESCHT.

   DAS GESETZ, damit es nicht wiederkommt:
   Ein direktes Kind von .media-duo / .media-offset ist EINE Zelle. Ein Bild
   MIT Unterschrift ist deshalb immer

       <div>  <figure class="figure">…</figure>
              <p class="figure__caption">…</p>  </div>

   und niemals figure und p als Geschwister — und auch kein <figcaption>
   INNERHALB der figure: .figure ist der Abzug selbst (Dominantfarbe, Rahmen,
   Passepartout), eine Unterschrift darin saesse auf dem Braun des Fotos.
   Diese Regel braucht keine CSS-Zeile; sie steht hier, weil genau ihr Bruch
   der Fehler war.
   ========================================================================== */


/* ============================================================================
   27 · LOGIN-BEREICH: BESCHREIBUNG UND PASSWORT
   (site/admin.html + assets/js/meza-admin.js)

   Zwei Dinge, die vorher fehlten, und eine Zeile, die vorher falsch aussah.

   .admin-hint ....... EIN erklaerender Satz unter einer Ueberschrift. Frueher
                       war das eine Versalien-Zeile im Stil einer Kopfzeile —
                       fuer drei Woerter richtig, fuer einen ganzen Satz nicht:
                       gesperrte Grossbuchstaben liest niemand gern. Jetzt
                       normaler Fliesstext, hoechstens 68 Zeichen breit, wie
                       jeder andere Lesetext auf der Seite.

   .admin-tile__describe / __input / __said
                       Die Beschreibung eines Bildes, aenderbar dort, wo sie
                       steht. Sie ist das, was Blinden vorgelesen wird — also
                       gehoert sie auf die Karte, nicht in einen zweiten
                       Bildschirm.

   Das Passwort-Formular braucht KEINE eigenen Klassen: .form, .field,
   .field__label, .field__input und .admin-note gibt es laengst und sie
   bedeuten genau das Richtige. Neue Klassen fuer dieselbe Sache waeren nur
   ein zweiter Satz Regeln, der beim naechsten Umbau vergessen wird.
   ========================================================================== */
.admin-hint{
  margin-top:var(--space-2xs);
  max-width:68ch;
  font-size:var(--fs-small);line-height:1.65;
  color:var(--blush-lite);opacity:.85;
}

/* --- die Beschreibung auf der Bildkarte ------------------------------------
   Die Karte ist schmal (ab 150px), darum stapelt hier alles. Das Feld ist
   flacher als das grosse Formularfeld: es sitzt zu zwanzigst auf einer Seite
   und soll die Karte nicht zur Saeule machen. */
.admin-tile__describe{
  display:flex;flex-direction:column;gap:.4rem;
  min-width:0;
}
.admin-tile__input{
  min-height:44px;                 /* Fingerziel bleibt 44px */
  padding:10px 12px;
  font-size:var(--fs-small);
}
/* Der Knopf sitzt auf der eigenen Zeile und nimmt nur seine Breite —
   nicht die ganze Karte, sonst sieht er aus wie der Hauptknopf der Seite. */
.admin-tile__describe .btn{align-self:flex-start}

/* Die Antwort des Servers, unter dem Feld. Leer heisst weg — sonst stuende
   auf jeder Karte ein leerer Streifen. */
.admin-tile__said{
  font-size:var(--fs-eyebrow);line-height:1.5;letter-spacing:.02em;
  color:var(--sage);
}
.admin-tile__said:empty{display:none}


/* ============================================================================
   27 · LEISTE: ABMELDEN  (assets/js/meza-edit.js §6)

   "Sign out" steht als Knopf neben "Settings" und sieht genauso aus. Das ist
   Absicht: beides sind ruhige Nebenwege der Leiste, nicht die Hauptsache. Der
   Knopf braucht KEINE eigenen Farben — .meza-edit__link (§22) gilt fuer beide,
   und die Grundregeln (§02) nehmen dem <button> Hintergrund und Rahmen.
   Deshalb steht hier keine einzige Regel.

   Die Upload-Box, die frueher unter dieser Nummer stand (.meza-add), ist
   ersatzlos gestrichen: Fotos werden nur noch im Login-Bereich hochgeladen
   (admin.html "Photos", §20) — EINE Tuer fuer Uploads statt zwei.
   ========================================================================== */


/* ============================================================================
   30 · LEISTE: ANORDNUNG  (assets/js/meza-edit.js §6)

   "Sign out ganz nach rechts, nicht neben den Arbeitsknoepfen."
   Die Arbeitsknoepfe bleiben links beieinander, der Weg hinaus rueckt ganz
   nach aussen. Das braucht ZWEI Zeilen, nicht eine: `margin-left:auto`
   schiebt nur, wenn es Platz zu verteilen gibt — und den bekommt die
   Knopfgruppe erst dadurch, dass sie mitwaechst. Ohne die erste Zeile ist die
   Gruppe genau so breit wie ihr Inhalt, und die zweite bliebe wirkungslos.
   ========================================================================== */
.meza-edit__actions{flex:1 1 auto}
.meza-edit__out{margin-left:auto}


/* ============================================================================
   29 · BILDBESCHREIBUNG  (site/admin.html + assets/js/meza-admin.js)
   (steht hinter §30, weil neue Regeln ans Dateiende gehoeren — die Nummer
   sagt, wozu sie gehoert, nicht wo sie liegt.)

   DER BEFUND
   Die Beschreibung stand auf der Bildkarte in einer EINZEILIGEN Zeile. Eine
   Karte ist ab 150px breit; ein Satz von 160 Zeichen war darin zu ueber drei
   Vierteln unsichtbar und liess sich nur durch Wischen im Feld lesen. Dazu
   kam in der Nur-Lese-Ansicht ein harter Zeilendeckel (-webkit-line-clamp:3
   auf .admin-tile__alt, jetzt geloescht). Beides versteckte ausgerechnet den
   Teil, dessentwegen man die Seite ueberhaupt oeffnet.

   DIE REGEL
   Kein line-clamp, kein max-height, kein text-overflow, kein overflow:hidden
   auf dem Text. Drei Zeilen sind drei Zeilen. Auch das Schreib-Feld hat keine
   feste Hoehe: meza-admin.js setzt sie bei jedem Zeichen auf die Hoehe des
   Inhalts, deshalb steht hier nur eine MINDEST-Hoehe fuer das Fingerziel.

   .admin-alt .......... der ganze Block auf der Karte
   .admin-alt__text .... die Beschreibung zum Lesen. Als <button>, wenn ein
                         Speicher angebunden ist — sonst als stiller <p>, denn
                         ein Text, der antippbar aussieht und nichts tut, waere
                         eine kleine Luege. (.is-empty = es gibt noch keine)
   .admin-alt__edit .... dieselbe Beschreibung zum Schreiben (Feld · Save ·
                         eine Zeile, was Escape tut)
   .admin-alt__field ... waechst mit dem Text
   .admin-alt__said .... die Antwort des Servers; leer heisst weg

   GELIEHEN STATT VERDOPPELT
   Das gestrichelte Rechteck um einen antippbaren Text gibt es schon: es ist
   .meza-edit-field (§22), das Alisa auf allen sieben Seiten sieht. Hier steht
   dasselbe Muster, damit sie EINE Geste lernt statt zwei. Das Feld selbst ist
   ein .field__input (§13) und bekommt hier nur, was auf einer 150px-Karte
   anders sein muss.
   ========================================================================== */
.admin-alt{display:flex;flex-direction:column;gap:.4rem;min-width:0}

/* --- lesen ----------------------------------------------------------------- */
.admin-alt__text{
  display:flex;align-items:center;
  width:100%;min-height:44px;              /* Fingerziel, auch bei einer Zeile */
  padding:8px 0;
  border:0;background:none;
  text-align:left;
  font-family:inherit;font-weight:inherit;
  font-size:var(--fs-small);line-height:1.55;
  letter-spacing:normal;text-transform:none;
  color:var(--blush-lite);
  overflow-wrap:anywhere;                  /* ein langes Wort sprengt nichts */
}
/* nur die antippbare Fassung traegt das Muster aus §22 */
button.admin-alt__text{
  outline:1px dashed var(--line);
  outline-offset:4px;
  border-radius:2px;
  cursor:text;
}
button.admin-alt__text:hover{outline-color:var(--blush);color:var(--cream)}
.admin-alt__text.is-empty{color:var(--blush);opacity:.75}

/* --- schreiben -------------------------------------------------------------- */
.admin-alt__edit{display:flex;flex-direction:column;gap:.5rem;min-width:0}

/* Die Hoehe setzt meza-admin.js. resize:none ist deshalb keine Bevormundung:
   ein Griff, der eine Hoehe einstellt, die das naechste Zeichen ueberschreibt,
   waere ein Knopf, der nichts tut. Der Typ-Selektor ist noetig, weil
   textarea.field__input (§13) sonst 150px Mindesthoehe durchsetzt. */
textarea.admin-alt__field{
  min-height:44px;
  padding:10px 12px;
  font-size:var(--fs-small);line-height:1.55;
  resize:none;overflow:hidden;
}
.admin-alt__row{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem var(--space-2xs)}
.admin-alt__how{
  font-size:var(--fs-eyebrow);line-height:1.5;
  color:var(--blush-lite);opacity:.7;
}

/* --- was der Server gesagt hat --------------------------------------------- */
.admin-alt__said{
  font-size:var(--fs-eyebrow);line-height:1.5;letter-spacing:.02em;
  color:var(--sage);
}
.admin-alt__said:empty{display:none}


/* ============================================================================
   28 · LOGIN-MENUE  (site/admin.html + assets/js/meza-admin.js)

   (Die Nummer ist die zugeteilte, nicht die Reihenfolge im File — §19 steht
   auch hinter §20 und §27 gibt es zweimal. Gesucht wird hier per Klassenname,
   nicht per Nummer.)

   Nach dem Anmelden kam frueher sofort die Fotoliste. Das war eine Antwort auf
   eine Frage, die Alisa gar nicht gestellt hatte: sie hat drei Anliegen, nicht
   eines. Jetzt kommt ein Menue mit genau drei Kacheln, jede mit einem Satz in
   Alltagssprache, und die Bildschirme dahinter sind unveraendert.

   .admin-menu ......... die drei Kacheln, gestapelt
   .admin-menu__tile ... eine Kachel. <a> fuer die Webseite, <button> fuer die
                         zwei Bildschirme — sie sehen gleich aus, weil sie fuer
                         Alisa dasselbe sind: eine Tuer.
   .admin-menu__name ... zwei Woerter, gross
   .admin-menu__what ... derselbe Inhalt in einem Satz, klein

   .admin-bar__back / __out / __note
                         Die Leiste traegt jetzt ZWEI Knoepfe und eine Zeile.
                         §20 schob JEDEN Knopf der Leiste nach rechts — das war
                         richtig, solange es einen gab. Jetzt schiebt nur noch
                         der letzte, und der Weg zurueck steht links beim Namen.

   .field__eye-wrap / .field__eye
                         Das Auge im Passwortfeld. Gezeichnet wird es mit
                         ::before und ::after — genau wie das Kreuz der
                         Bildauswahl (§24) und die Striche des Menue-Knopfes
                         (§05). Diese Seite hat kein einziges <svg>, und dieses
                         Auge ist kein Grund, damit anzufangen.
   ========================================================================== */

/* --- die Leiste: zurueck links, hinaus ganz rechts -------------------------- */
.admin-bar .admin-bar__back{margin-left:0}
.admin-bar .admin-bar__out{margin-left:auto}

/* Die Antwort des Abmelde-Knopfes steht dort, wo der Knopf steht. Sie liegt
   unter der Knopfzeile und nimmt dieselbe Breite wie deren Inhalt. */
.admin-bar__note{
  width:min(100% - var(--gut) * 2, var(--maxw));
  margin:0 auto var(--space-2xs);
}

/* --- die drei Kacheln ------------------------------------------------------ */
.admin-menu{
  display:grid;gap:var(--space-sm);
  margin-top:var(--space-md);
}

/* Eine Kachel ist ein Textblock, kein Knopf mit Beschriftung: darum linksbuendig
   und ohne Versalien — das Gegenteil von .btn, und mit Absicht. */
.admin-menu__tile{
  display:flex;flex-direction:column;gap:.5rem;
  width:100%;min-height:96px;
  padding:var(--space-sm);
  border:1px solid var(--line);
  background:var(--ink-raise);
  color:var(--blush-lite);
  text-align:left;
  transition:border-color var(--dur) var(--ease),
             background-color var(--dur) var(--ease),
             color var(--dur) var(--ease);
}
.admin-menu__tile:hover,
.admin-menu__tile:focus-visible{
  border-color:var(--blush);
  background:rgba(228,218,213,.07);
  color:var(--cream);
}
.admin-menu__name{
  font-family:var(--font-display);font-weight:400;
  font-size:var(--fs-h3);letter-spacing:.06em;line-height:1.2;
  color:var(--blush);
}
.admin-menu__tile:hover .admin-menu__name,
.admin-menu__tile:focus-visible .admin-menu__name{color:var(--cream)}
.admin-menu__what{font-size:var(--fs-small);line-height:1.6;max-width:52ch}

/* --- das Auge im Passwortfeld ---------------------------------------------- */
/* Der Rahmen sitzt um das Feld, nicht um das ganze .field: die Beschriftung
   darueber soll nicht mitwandern. */
.field__eye-wrap{position:relative;display:block;width:100%}
/* Platz fuer das Auge, damit ein langes Passwort nicht darunter laeuft. */
.field__eye-wrap .field__input{padding-right:56px}

.field__eye{
  position:absolute;top:0;right:0;bottom:0;
  width:52px;min-height:44px;            /* Fingerziel, volle Feldhoehe */
  display:grid;place-items:center;
  color:var(--blush-lite);
}
.field__eye:hover,.field__eye:focus-visible{color:var(--cream)}
.field__eye:disabled{opacity:.4;cursor:not-allowed}

/* das Auge selbst */
.field__eye::before{
  content:"";
  width:22px;height:13px;
  border:1px solid currentColor;
  border-radius:50%;
}
/* die Pupille — und im offenen Zustand der Strich durch das Auge */
.field__eye::after{
  content:"";position:absolute;
  width:7px;height:7px;
  border:1px solid currentColor;border-radius:50%;
}
.field__eye.is-on::after{
  width:26px;height:0;
  border-width:0 0 1px 0;border-radius:0;
  transform:rotate(-45deg);
}


/* ============================================================================
   31 · GALERIE-BESCHRIFTUNG  (assets/js/meza.js §7)

   Cyrill: "Die Bildbeschreibungen sehe ich nirgends." Jede .gallery-item-
   Kachel traegt ihre Beschreibung laengst — im alt-Text ihres <img>. meza.js
   §7 legt daraus EINE Zeile ueber den unteren Rand des Fotos, fuer jeden
   Besucher. Eine Quelle (alt), deshalb kann die Zeile nie etwas anderes
   sagen als das, was vorgelesen wird — und deshalb ist sie aria-hidden.

   Sichtbar NUR beim Ueberfahren mit der Maus (hover:hover) und bei Tastatur-
   Fokus. Touch-Geraete haben kein Hover — dort bleibt die Zeile weg statt
   dauernd im Bild zu stehen; die Lightbox (§11) zeigt dieselbe Beschreibung
   beim Antippen. pointer-events:none, damit der Klick weiter die Kachel
   trifft; der Verlauf gibt dem Text seinen Grund, ohne das Foto zu rahmen.
   ========================================================================== */
.gallery-item__cap{
  position:absolute;left:0;right:0;bottom:0;z-index:1;
  padding:44px 14px 12px;
  background:linear-gradient(to top,rgba(0,0,0,.78),rgba(0,0,0,.5) 55%,rgba(0,0,0,0));
  color:var(--cream);
  font-size:var(--fs-small);line-height:1.5;text-align:left;
  overflow-wrap:anywhere;
  opacity:0;pointer-events:none;
  transition:opacity .4s var(--ease);
}
.gallery-item__cap:empty{display:none}
@media (hover:hover){
  .gallery-item:hover .gallery-item__cap{opacity:1}
}
.gallery-item:focus-visible .gallery-item__cap{opacity:1}
