/**
 * Framework candidates (DEMO-01, 2026-10-15). Generic sections built for the
 * restaurant demo that other forks can reuse with brand tokens only. Prefix
 * mvx- marks "not yet in framework core": once accepted upstream they move to
 * sections.css/components.css as mv-*. Colours come from the surrounding
 * .mv-section variables (--_mv-*) or tokens, never literals.
 *
 *   .mvx-pricelist   two-column price list, dotted leader to the price
 *                    (pattern after the 21st.dev "Restaurant Menu Block")
 *   .mvx-bento       asymmetric image grid with captions
 *   .mvx-hours       opening hours as a definition list
 *   .mvx-beats       caption steps over a scroll hero (.mv-hero-video
 *                    data-layout="scroll"), driven by mvx-beats.js
 *   .mvx-avail       availability calendar, static example months
 *                    (added for the holiday rental demo)
 */

/* --- price list ---------------------------------------------------------- */
.mvx-pricelist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: 1.75rem 3rem;
}
.mvx-pricelist__item { display: grid; gap: .35rem; }
.mvx-pricelist__row {
  display: flex;
  flex-wrap: wrap; /* a long name plus a long price ("1.900 € / Monat") moves the price below on small phones */
  align-items: baseline;
  gap: .6rem;
}
.mvx-pricelist__name {
  margin: 0;
  font-family: var(--mv-heading-font, var(--font-heading));
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--_mv-text, var(--text));
}
.mvx-pricelist__row::after {
  content: "";
  order: 1;
  flex: 1 1 2rem;
  min-width: 2rem;
  border-bottom: 2px dotted var(--_mv-border, var(--line-strong));
  transform: translateY(-.3em);
}
.mvx-pricelist__price {
  order: 2;
  margin: 0;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--_mv-text, var(--text));
}
.mvx-pricelist__desc {
  margin: 0;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--_mv-muted, var(--text-2));
}
.mvx-pricelist__tags { display: flex; flex-wrap: wrap; gap: .4rem; margin: .15rem 0 0; padding: 0; list-style: none; }
.mvx-pricelist__tag {
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: .15rem .55rem;
  border-radius: 999px;
  border: 1px solid var(--_mv-border, var(--line-strong));
  color: var(--_mv-text, var(--text));
}

/* --- bento gallery ------------------------------------------------------- */
.mvx-bento {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  grid-auto-rows: clamp(9rem, 16vw, 13rem);
  gap: clamp(.6rem, 1.4vw, 1rem);
  margin: 0;
  padding: 0;
  list-style: none;
}
.mvx-bento__item {
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius-lg, 14px);
  background: var(--panel-a);
  grid-column: span 2;
}
.mvx-bento__item[data-size="wide"] { grid-column: span 4; }
.mvx-bento__item[data-size="tall"] { grid-row: span 2; }
.mvx-bento__item[data-size="hero"] { grid-column: span 4; grid-row: span 2; }
.mvx-bento__item img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Badge top left, caption bottom right: on narrow tiles both at the bottom overlapped. */
.mvx-bento__item .ai-badge { top: 10px; bottom: auto; }
.mvx-bento__caption {
  position: absolute;
  right: .6rem;
  bottom: .6rem;
  max-width: calc(100% - 1.2rem);
  margin: 0;
  padding: .3rem .7rem;
  border-radius: 999px;
  font-size: .95rem;
  font-weight: 600;
  background: var(--surface);
  color: var(--text);
}
@media (max-width: 720px) {
  .mvx-bento { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 11rem; }
  .mvx-bento__item,
  .mvx-bento__item[data-size="wide"],
  .mvx-bento__item[data-size="hero"] { grid-column: span 2; }
  .mvx-bento__item[data-size="tall"] { grid-column: span 1; }
  .mvx-bento__item[data-size="hero"] { grid-row: span 2; }
}

/* --- opening hours ------------------------------------------------------- */
.mvx-hours {
  display: grid;
  /* A long label wraps at 60% instead of pushing the value off a phone screen. */
  grid-template-columns: fit-content(60%) minmax(0, 1fr);
  gap: .55rem 1.5rem;
  margin: 0;
}
.mvx-hours dt { font-weight: 700; color: var(--_mv-text, var(--text)); }
.mvx-hours dd { margin: 0; color: var(--_mv-muted, var(--text-2)); font-variant-numeric: tabular-nums; }

/* --- caption steps over the scroll hero ------------------------------------
   mvx-beats.js sets --mvx-p (0..1) on the hero and adds .mvx-beats-on only when
   the core scrub runs (data-scrub="on"): without it, without JS and with reduced
   motion the beats stay display:none and the core copy is the whole hero.
   Every step owns a window [data-from, data-to]; outside it the step is
   display:none (Safari keeps stale pixels of opacity-only layers). Only
   opacity and transform animate. */
.mvx-beats { display: none; }
.mvx-beats-on .mvx-beats {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}
.mvx-beats__step {
  display: none;
  position: absolute;
  left: 50%;
  bottom: clamp(5rem, 14vh, 9rem);
  width: min(40rem, calc(100% - 3rem));
  transform: translate(-50%, calc((1 - var(--mvx-a, 0)) * 14px));
  opacity: var(--mvx-a, 0);
  text-align: center;
}
.mvx-beats__step.is-live { display: block; }
.mvx-beats__kicker {
  display: inline-block;
  margin: 0 0 .6rem;
  padding: .25rem .8rem;
  border-radius: 999px;
  background: var(--mv-hero-video-eyebrow-bg, var(--surface));
  color: var(--mv-hero-video-eyebrow-text, var(--text));
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.mvx-beats__text {
  margin: 0;
  font-family: var(--mv-heading-font, var(--font-heading));
  font-size: clamp(1.6rem, 4.2vw, 2.8rem);
  line-height: 1.15;
  text-wrap: balance;
  color: var(--mv-hero-video-text, var(--text));
}
/* While a beat plays, the core copy steps back; the final beat hands the stage
   back to a call to action. */
.mvx-beats-on .mv-hero-video__copy {
  opacity: var(--mvx-copy, 1);
  transform: translateY(calc((1 - var(--mvx-copy, 1)) * -18px));
}
/* Faded copy stays in the accessibility tree and tab order; it reappears when it gets focus. */
.mvx-beats-on .mv-hero-video__copy.is-gone { pointer-events: none; }
.mvx-beats-on .mv-hero-video__copy:focus-within { opacity: 1; transform: none; pointer-events: auto; }
/* A focused copy owns the stage: hide the beat so the two never overlap. */
.mvx-beats-on:has(.mv-hero-video__copy:focus-within) .mvx-beats { visibility: hidden; }
.mvx-beats__cta { pointer-events: auto; margin-top: 1.4rem; }
@media (prefers-reduced-motion: reduce) {
  .mvx-beats-on .mvx-beats { display: none; }
}

/* --- availability calendar -----------------------------------------------
   Static example months (.mvx-avail): a table per month, Monday first, each
   day td[data-state="free|booked"]. The state is also spelled out for screen
   readers inside the cell; the legend repeats both swatches. */
.mvx-avail__legend { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; margin: 0 0 1.25rem; padding: 0; list-style: none; font-size: .95rem; color: var(--_mv-text, var(--text)); }
.mvx-avail__legend li { display: inline-flex; align-items: center; gap: .5rem; }
.mvx-avail__legend li::before { content: ""; width: 1.1rem; height: 1.1rem; border-radius: var(--radius-sm); border: 1px solid var(--line-strong); background: var(--surface); }
.mvx-avail__legend li[data-state="booked"]::before { background: var(--accent-soft); border-color: var(--accent); }
.mvx-avail__months { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr)); gap: 1.5rem 2.5rem; }
.mvx-avail__month { width: 100%; border-collapse: separate; border-spacing: 4px; font-variant-numeric: tabular-nums; }
.mvx-avail__month caption { text-align: left; padding: 0 4px .5rem; font-family: var(--mv-heading-font, var(--font-heading)); font-size: 1.15rem; font-weight: 700; color: var(--_mv-text, var(--text)); }
.mvx-avail__month th { padding: .2rem 0; font-size: .9375rem; font-weight: 700; color: var(--_mv-muted, var(--text-2)); }
.mvx-avail__month td { padding: .5rem 0; text-align: center; font-size: .95rem; border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--surface); color: var(--text); }
.mvx-avail__month td[data-state="booked"] { background: var(--accent-soft); border-color: transparent; color: var(--text-3); text-decoration: line-through; }
.mvx-avail__month td:empty { border: 0; background: none; }

/* One line per entry, a thin rule between rows, values aligned right (Olli 2026-10-16). */
.mvx-hours { gap: 0; }
.mvx-hours dd { padding-left: 1.5rem; text-align: right; }
.mvx-hours dt, .mvx-hours dd { padding-top: .65rem; padding-bottom: .65rem; border-top: 1px solid color-mix(in srgb, currentColor 16%, transparent); }
.mvx-hours dt:first-of-type, .mvx-hours dt:first-of-type + dd { border-top: 0; padding-top: 0; }
/* Narrow columns (phones): label above its value. */
@media (max-width: 520px) {
  .mvx-hours { grid-template-columns: minmax(0, 1fr); }
  .mvx-hours dd { text-align: left; padding-left: 0; padding-top: 0; border-top: 0; }
}

/* --- bento shift (mvx-bento-shift.js): tiles move between two layouts ------ */
.mvx-bento.is-shift { display: block; position: relative; }
.mvx-bento.is-shift > .mvx-bento__item { position: absolute; margin: 0; }
