/* Dunya Markt: the structure both designs share (docs/superpowers/specs/
   2026-10-14-two-designs-whole-site-design.md). One markup, two skins:
   assets/css/design-7.css ("Two Squares", warm) and design-8.css ("Shop
   Window", cool) fill the tokens this file declares as placeholders and
   add their own composition. This file writes no colour of its own: every
   colour is a token the design file sets. Only transform, opacity and the
   hero's clip-path animate. Logical properties throughout; --dir is 1 or -1
   for the few transforms that mirror. */

:root {
  /* Type: Plex. The sizes are shared; each design sets the display weight. */
  --fs-display: 44px;
  --fs-heading: 32px;
  --fs-title: 22px;
  --fs-price: 28px;
  --fs-hours: 20px;
  --fs-intro: 19px;
  --fs-body: 17px;
  --fs-small: 15px;
  --lh-display: 1.05;
  --lh-heading: 1.1;
  --lh-body: 1.47;
  --lh-intro: 1.4;
  --track-display: -0.02em;
  --track-heading: -0.015em;
  --display-max: 12ch;

  --gutter: 16px;
  --content: 1120px;
  --nav: 48px;
  --chapter: 64px;
  --dir: 1;

  --r-pill: 980px;
  --tap: 44px;
  --panel: min(78vw, 320px); /* a service or offer panel on a phone */
  --panel-small: min(60vw, 240px); /* a section panel on a phone */
  --rail-gap: 12px;
  /* The content axis: where the first panel of a rail, every heading and the
     status line start. The gutter on a phone, the content column's edge on
     a wide screen. */
  --axis: max(var(--gutter), calc((100% - var(--content)) / 2));

  --ease-arrive: cubic-bezier(0.2, 0.8, 0.2, 1);
}

@media (min-width: 40em) {
  :root {
    --fs-display: clamp(44px, 6.5vw, 80px);
  }
}

@media (min-width: 48em) {
  :root {
    --fs-heading: 48px;
    --fs-hours: 24px;
    --fs-intro: 21px;
    --fs-price: 32px;
    --gutter: 24px;
    --chapter: 96px;
    --rail-gap: 24px;
  }
}

@media (min-width: 64em) {
  :root {
    --display-max: 11ch;
  }
}

/* Arabic: the same sizes, taller lines, no tracking, widths in rem because
   ch is Latin-tuned. */
[dir='rtl'] {
  --lh-display: 1.25;
  --lh-heading: 1.3;
  --lh-body: 1.6;
  --lh-intro: 1.6;
  --track-display: 0;
  --track-heading: 0;
  --display-max: 18rem;
  --dir: -1;
}

@media (min-width: 64em) {
  [dir='rtl'] {
    --display-max: 26rem;
  }
}

/* Fonts: IBM Plex Sans (variable, weight 300 to 600, Latin subset) and IBM
   Plex Sans Arabic (300, 400, 500, 600), both OFL, under one family name so
   one rule serves all three languages and a mixed line falls back glyph by
   glyph. The Latin file is declared once per weight with the same
   descriptors as the Arabic faces: Chromium falls back across unicode-range
   only between faces whose weight descriptors are identical. The file is
   fetched once. The version query matches DUNYA_FONT_VERSION in
   inc/assets.php; bump both when a font file changes under its name. */
@font-face {
  font-family: Plex;
  font-weight: 300;
  font-display: swap;
  src: url('../fonts/plex-latin.woff2?v=20261014') format('woff2');
  unicode-range: U+0000-00FF, U+0100-017F, U+0218-021B, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122,
    U+2190-2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: Plex;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/plex-latin.woff2?v=20261014') format('woff2');
  unicode-range: U+0000-00FF, U+0100-017F, U+0218-021B, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122,
    U+2190-2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: Plex;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/plex-latin.woff2?v=20261014') format('woff2');
  unicode-range: U+0000-00FF, U+0100-017F, U+0218-021B, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122,
    U+2190-2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: Plex;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/plex-latin.woff2?v=20261014') format('woff2');
  unicode-range: U+0000-00FF, U+0100-017F, U+0218-021B, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122,
    U+2190-2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: Plex;
  font-weight: 300;
  font-display: swap;
  src: url('../fonts/plex-arabic-light.woff2?v=20261014') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-089F, U+08A0-08FF, U+200C-200F, U+FB50-FDFF, U+FE70-FEFF;
}

@font-face {
  font-family: Plex;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/plex-arabic-regular.woff2?v=20261014') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-089F, U+08A0-08FF, U+200C-200F, U+FB50-FDFF, U+FE70-FEFF;
}

@font-face {
  font-family: Plex;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/plex-arabic-medium.woff2?v=20261014') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-089F, U+08A0-08FF, U+200C-200F, U+FB50-FDFF, U+FE70-FEFF;
}

@font-face {
  font-family: Plex;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/plex-arabic-semibold.woff2?v=20261014') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-089F, U+08A0-08FF, U+200C-200F, U+FB50-FDFF, U+FE70-FEFF;
}

/* Base */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  color-scheme: only light;
  background: var(--ground);
  color: var(--text);
  font-family: Plex, system-ui, sans-serif;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  scroll-padding-block-start: calc(var(--nav) + 16px);
  scrollbar-color: var(--line) var(--ground);
}

body {
  margin: 0;
  min-block-size: 100vh;
}

h1,
h2,
h3,
p,
ul,
address,
figure {
  margin: 0;
}

ul {
  padding: 0;
  list-style: none;
}

address {
  font-style: normal;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
}

img,
video,
svg {
  display: block;
  max-inline-size: 100%;
  block-size: auto;
}

[hidden] {
  display: none !important;
}

::selection {
  background: var(--accent);
  color: var(--on-accent);
}

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

.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.nowrap {
  white-space: nowrap;
}

.skip {
  position: fixed;
  inset-block-start: 8px;
  inset-inline-start: 8px;
  z-index: 20;
  padding: 10px 16px;
  border-radius: var(--r-pill);
  background: var(--text);
  color: var(--ground);
  font-weight: 500;
  transform: translateY(-200%);
}

.skip:focus-visible {
  transform: none;
}

/* The content column: the axis every chapter starts on. */
.wrap {
  max-inline-size: calc(var(--content) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Type */
.display {
  max-inline-size: var(--display-max);
  font-size: var(--fs-display);
  font-weight: var(--fw-display);
  line-height: var(--lh-display);
  letter-spacing: var(--track-display);
  text-wrap: balance;
}

.heading {
  max-inline-size: 18ch;
  font-size: var(--fs-heading);
  font-weight: var(--fw-heading);
  line-height: var(--lh-heading);
  letter-spacing: var(--track-heading);
  text-wrap: balance;
}

[dir='rtl'] .heading {
  max-inline-size: 24rem;
}

.intro {
  max-inline-size: 36ch;
  color: var(--text-2);
  font-size: var(--fs-intro);
  line-height: var(--lh-intro);
  text-wrap: pretty;
}

[dir='rtl'] .intro {
  max-inline-size: 32rem;
}

.meta {
  color: var(--text-2);
  font-size: var(--fs-small);
  line-height: 1.4;
}

/* The chevron, Apple's "›", drawn as two strokes so it needs no glyph and
   mirrors by itself in RTL (the rotation flips with --dir). */
.chev {
  display: inline-block;
  flex-shrink: 0;
  inline-size: 0.5em;
  block-size: 0.5em;
  margin-inline-start: 0.1em;
  border-inline-end: 1.5px solid currentColor;
  border-block-start: 1.5px solid currentColor;
  transform: rotate(calc(45deg * var(--dir)));
  transition: translate 180ms var(--ease-arrive);
}

.chev--back {
  transform: rotate(calc(-135deg * var(--dir)));
}

/* The live dot: the accent when open, an outline when closed, so colour is
   never the only cue (the words carry the state anyway). */
.dot {
  display: inline-block;
  flex-shrink: 0;
  inline-size: 8px;
  block-size: 8px;
  border: 1.5px solid var(--accent);
  border-radius: 50%;
  background: var(--accent);
}

[data-open='false'] .dot {
  background: transparent;
}

/* Pills: the one filled pill per screen, ghost pills for the maps. */
.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4em;
  min-block-size: var(--tap);
  padding: 0 22px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color 180ms var(--ease-arrive),
    border-color 180ms var(--ease-arrive),
    transform 120ms var(--ease-arrive);
}

.pill:active {
  transform: scale(0.98);
}

.pill--fill {
  min-block-size: 48px;
  background: var(--accent);
  color: var(--on-accent);
}

.pill--ghost {
  border-color: var(--edge);
  background: transparent;
  color: var(--text);
}

/* A chevron link, 44px tall, in the accent. */
.more {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  min-block-size: var(--tap);
  color: var(--accent);
  font-weight: 500;
}

@media (hover: hover) and (pointer: fine) {
  .pill--fill:hover {
    background: color-mix(in srgb, var(--accent) 88%, var(--ground));
  }

  .pill--ghost:hover {
    border-color: var(--text);
  }

  .pill:hover .chev,
  .more:hover .chev,
  .row:hover .chev,
  .offers__flyer-link:hover .chev {
    translate: calc(2px * var(--dir)) 0;
  }

  .more:hover > span:first-child,
  .footer__links a:hover,
  .footer__copy a:hover,
  .prose a:hover {
    text-decoration: underline;
    text-underline-offset: 0.25em;
  }
}

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 20px;
}

.actions--start .pill {
  flex: 0 1 auto;
}

/* A glyph before a pill's words (the WhatsApp button on the Kontakt page). */
.pill__icon {
  flex: none;
  inline-size: 18px;
  block-size: 18px;
  margin-inline-end: 0.2em;
  fill: currentColor;
}

/* ------------------------------------------------------------------ */
/* The nav: the name (with design 7's mark), the pages' links, the live
   hours line, the language control. 48px, sticky, a hairline below. */
.nav {
  position: sticky;
  inset-block-start: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--ground) 85%, transparent);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav {
    background: color-mix(in srgb, var(--ground) 96%, transparent);
  }
}

.nav::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 1px;
  background: var(--line);
}

.nav__inner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  column-gap: 8px;
  block-size: var(--nav);
}

.nav__name {
  grid-area: 1 / 1;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-block-size: var(--tap);
  font-weight: 500;
  white-space: nowrap;
  transition:
    opacity 320ms var(--ease-arrive),
    visibility 320ms;
}

/* The live hours line. Hidden until site.js adds is-shown (once the hero's
   own status line has left the screen, or at once on a page without a
   hero); on a phone it then takes the name's place, from 56.25em it sits
   between the name and the links. Hidden means visibility hidden too, so it
   is never an invisible Tab stop. */
.nav .nav__hours {
  grid-area: 1 / 1;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-block-size: var(--tap);
  margin: 0;
  color: var(--text-2);
  font-size: var(--fs-small);
  font-weight: 500;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 320ms var(--ease-arrive),
    visibility 320ms;
}

.nav .nav__hours.is-shown {
  opacity: 1;
  visibility: visible;
}

.nav:has(.nav__hours.is-shown) .nav__name {
  opacity: 0;
  visibility: hidden;
}

/* On a page without a hero (site.js adds nav--static) the name stays and
   the hours line shows only where there is room for both, from 56.25em. */
.nav.nav--static:has(.nav__hours.is-shown) .nav__name {
  opacity: 1;
  visibility: visible;
}

@media (max-width: 56.24em) {
  .nav--static .nav__hours {
    display: none;
  }
}

.nav__toggle {
  grid-area: 1 / 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--tap);
  block-size: var(--tap);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

.nav__toggle[aria-expanded='true'] {
  background: var(--band);
}

.nav .lang {
  grid-area: 1 / 3;
  justify-self: end;
}

/* Below 56.25em the links open as rows under the bar (assets/js/nav.js). */
.nav__links {
  grid-area: 2 / 1 / 3 / -1;
}

.nav__panel {
  position: absolute;
  inset-inline: 0;
  inset-block-start: var(--nav);
  padding: 8px var(--gutter) 16px;
  background: var(--ground);
  border-block-end: 1px solid var(--line);
}

.nav__list {
  display: flex;
  flex-direction: column;
}

.nav__list a {
  display: flex;
  align-items: center;
  min-block-size: 48px;
  font-size: var(--fs-intro);
  font-weight: 500;
}

.nav__list a[aria-current='page'] {
  color: var(--accent);
}

/* From 56.25em the row is the name, the hours line, the links in the
   centre, the language control. The hours line comes right after the name
   in the markup (on a phone it takes the name's place), so it stays there
   on a wide screen too: Tab then visits the controls in the order they sit
   (WCAG 2.4.3), which a line drawn after the links would break. */
@media (min-width: 56.25em) {
  .nav__inner {
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    column-gap: 24px;
  }

  .nav__toggle {
    display: none;
  }

  .nav__links {
    grid-area: 1 / 3;
    justify-self: center;
  }

  .nav__panel {
    position: static;
    display: block !important;
    padding: 0;
    background: transparent;
    border: 0;
  }

  .nav__list {
    flex-direction: row;
    gap: 28px;
  }

  .nav__list a {
    min-block-size: var(--tap);
    font-size: var(--fs-body);
    font-weight: 400;
  }

  .nav__list a[aria-current='page'] {
    font-weight: 500;
  }

  .nav .nav__hours {
    grid-area: 1 / 2;
  }

  .nav .lang {
    grid-area: 1 / 4;
  }

  .nav:has(.nav__hours.is-shown) .nav__name {
    opacity: 1;
    visibility: visible;
  }
}

/* The mark: two squares, one filled, one turned. Design 7 shows it in the
   nav (the outline turning with the page's scroll) and at rest in the
   footer; design 8 hides it. */
.mark {
  position: relative;
  display: none;
  place-items: center;
  flex-shrink: 0;
  inline-size: 22px;
  block-size: 22px;
}

.mark__fill,
.mark__turn {
  grid-area: 1 / 1;
}

.mark__fill {
  inline-size: 13px;
  block-size: 13px;
  background: currentColor;
}

.mark__turn {
  inline-size: 19px;
  block-size: 19px;
  border: 1.5px solid var(--accent);
  transform: rotate(45deg);
}

.mark--done {
  inline-size: 28px;
  block-size: 28px;
}

.mark--done .mark__fill {
  inline-size: 16px;
  block-size: 16px;
}

.mark--done .mark__turn {
  inline-size: 24px;
  block-size: 24px;
}

/* The language control: a pill of three links, each a 44 by 44 target, the
   current one filled with the text colour. */
.lang {
  position: relative;
  display: inline-flex;
  flex-shrink: 0;
  isolation: isolate;
}

.lang::before {
  content: '';
  position: absolute;
  inset-block: 6px;
  inset-inline: 0;
  border: 1px solid var(--edge);
  border-radius: var(--r-pill);
  pointer-events: none;
}

.lang__seg {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--tap);
  block-size: var(--tap);
  border-radius: var(--r-pill);
  font-size: var(--fs-small);
  font-weight: 500;
  white-space: nowrap;
}

.lang__seg[aria-current='page']::before {
  content: '';
  position: absolute;
  inset-block: 8px;
  inset-inline: 2px;
  z-index: -1;
  border-radius: var(--r-pill);
  background: var(--text);
}

.lang__seg[aria-current='page'] {
  color: var(--ground);
}

/* ------------------------------------------------------------------ */
/* The hero: the words on the axis, then the picture. */
.hero {
  padding-block: 32px 0;
}

.hero__words > * + * {
  margin-block-start: 16px;
}

.hero__other {
  color: var(--text-2);
  font-size: var(--fs-small);
  font-weight: 500;
}

.hero__words .intro {
  margin-block-start: 20px;
}

.hero__words .actions {
  margin-block-start: 28px;
}

.status {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-block-size: var(--tap);
  margin-block-start: 20px;
  font-weight: 500;
}

.hero__where {
  margin-block-start: 0;
  color: var(--text-2);
}

/* The frame holds the film (or the owner's photograph). Each design gives
   it its shape: design 8 the 4:5 box that draws in on a phone, design 7 the
   square that turns into the star. */
.frame {
  position: relative;
  margin-block-start: 32px;
}

.frame__tilt {
  position: relative;
}

.frame__hair {
  display: none;
}

.frame__media {
  position: relative;
  overflow: hidden;
  background: var(--band);
}

.frame__media > img,
.frame__media > picture > img,
.frame__media > video {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.frame__media > picture {
  position: absolute;
  inset: 0;
}

/* The clip sits over the still and fades in once it really plays. */
.frame__video {
  opacity: 0;
  transition: opacity 600ms var(--ease-arrive);
}

.frame__video.is-playing {
  opacity: 1;
}

/* The pause control: a 44px disc inside the picture's lower inline-end
   corner, present only while a clip is attached. */
.frame__pause {
  position: absolute;
  inset-block-end: 12px;
  inset-inline-end: 12px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--tap);
  block-size: var(--tap);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ground);
  color: var(--text);
  cursor: pointer;
  transition: transform 120ms var(--ease-arrive);
}

.frame__pause:active {
  transform: scale(0.94);
}

.frame__pause svg {
  inline-size: 16px;
  block-size: 16px;
  fill: currentColor;
}

.frame__pause .icon-play,
.frame__pause[aria-pressed='true'] .icon-pause {
  display: none;
}

.frame__pause[aria-pressed='true'] .icon-play {
  display: block;
}

@media (min-width: 64em) {
  .hero {
    padding-block: 48px 0;
  }

  .hero__grid {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    align-items: center;
    column-gap: 64px;
  }

  .frame {
    margin: 0;
    justify-self: end;
    inline-size: 100%;
    max-inline-size: 560px;
  }
}

/* ------------------------------------------------------------------ */
/* Chapters */
.chapter {
  padding-block-start: var(--chapter);
}

.chapter__head {
  margin-block-end: 24px;
}

.chapter__head .intro {
  margin-block-start: 12px;
}

.chapter__head .more {
  margin-block-start: 8px;
}

.chapter__head--nav {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
}

.chapter__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 24px;
  margin-block-start: 16px;
}

/* The rail: the goods in one row. It runs the full width of the window, its
   first panel on the axis, the rest overflowing to the window's edge; swipe
   or wheel scrolls it, snapping to each panel. Reading order is the list's.
   Design 7 turns every rail into a grid. */
.rail {
  display: flex;
  gap: var(--rail-gap);
  padding-inline: var(--axis);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--axis);
  scrollbar-width: none;
  scroll-timeline-name: --rail;
  scroll-timeline-axis: inline;
}

.rail::-webkit-scrollbar {
  display: none;
}

/* The trailing padding of a scroll container is not kept by every browser;
   a last empty item keeps it. */
.rail::after {
  content: '';
  flex: 0 0 1px;
  margin-inline-start: calc(var(--axis) - var(--rail-gap) - 1px);
}

/* A grid of panels on the Angebote and Sortiment pages: two on a phone,
   three from 48em, four from 64em. */
.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px 12px;
}

@media (min-width: 48em) {
  .grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 32px 24px;
  }
}

@media (min-width: 64em) {
  .grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.panel {
  flex: 0 0 var(--panel);
  min-inline-size: 0;
  scroll-snap-align: start;
}

.panel--small {
  flex-basis: var(--panel-small);
}

.panel__link {
  display: block;
  color: inherit;
}

.panel__photo {
  position: relative;
  display: block;
  aspect-ratio: var(--photo-ratio);
  overflow: hidden;
  border-radius: var(--r-photo);
  background: var(--band);
}

.panel__photo img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform 320ms var(--ease-arrive);
}

/* A product or a section with no picture: the category's icon on the band. */
.panel__photo--icon {
  display: grid;
  place-items: center;
  color: var(--text-2);
}

.panel__photo--icon svg {
  inline-size: 34%;
  block-size: 34%;
}

.panel__title {
  margin-block-start: 14px;
  font-size: var(--fs-title);
  font-weight: 500;
  line-height: 1.2;
  text-wrap: balance;
}

.panel__line {
  margin-block-start: 6px;
  color: var(--text-2);
  text-wrap: pretty;
}

/* A section panel: the number and the name on one line. */
.panel__name {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-block-start: 12px;
  font-weight: 500;
  line-height: 1.3;
}

.panel__num {
  flex-shrink: 0;
  color: var(--text-2);
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
}

@media (hover: hover) and (pointer: fine) {
  .panel:hover .panel__photo img {
    transform: scale(1.03);
  }
}

/* The progress line under a rail (site.js sets --fill and --travel; the
   movement runs on the rail's scroll timeline where the browser has one, by
   the script elsewhere). */
.progress {
  position: relative;
  block-size: 2px;
  margin-block-start: 24px;
  background: var(--line);
  overflow: hidden;
}

.progress__fill {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: calc(var(--fill, 25) * 1%);
  background: var(--text);
}

.chapter {
  timeline-scope: --rail;
}

@supports (animation-timeline: scroll()) {
  .progress__fill {
    animation: travel linear both;
    animation-timeline: --rail;
  }
}

@keyframes travel {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(calc(var(--travel, 0) * 1px));
  }
}

/* The rail buttons beside a heading, for a rail that overflows on a wide
   screen (site.js hides them otherwise). */
.rail-nav {
  display: none;
  gap: 8px;
  padding-block-end: 6px;
}

.rail-nav__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--tap);
  block-size: var(--tap);
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: border-color 180ms var(--ease-arrive);
}

.rail-nav__btn .chev {
  margin: 0;
  inline-size: 9px;
  block-size: 9px;
  translate: calc(-1.5px * var(--dir)) 0;
}

.rail-nav__btn .chev--back {
  translate: calc(1.5px * var(--dir)) 0;
}

.rail-nav__btn:disabled {
  cursor: default;
}

.rail-nav__btn:disabled .chev {
  opacity: 0.35;
}

@media (hover: hover) and (pointer: fine) {
  .rail-nav__btn:not(:disabled):hover {
    border-color: var(--text);
  }
}

@media (min-width: 64em) {
  /* The four services fit the content width as a row: no rail there. */
  .rail--fit {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    padding-inline: var(--axis);
    overflow: visible;
  }

  .rail--fit::after {
    display: none;
  }

  .rail--fit .panel {
    flex: none;
  }

  .rail--range {
    --panel-small: 240px;
  }

  .rail--offers {
    --panel: 262px;
  }

  .rail-nav {
    display: inline-flex;
  }
}

/* ------------------------------------------------------------------ */
/* The offer panel (template-parts/offer/card.php) */
.offer__media {
  display: block;
}

.offer__badge {
  position: absolute;
  inset-block-start: 12px;
  inset-inline-end: 12px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: var(--badge);
  color: var(--on-badge);
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: 1.4;
}

.offer__body > * + * {
  margin-block-start: 6px;
}

/* A name longer than the panel ("Za'atar-Gewürzmischung" in two columns
   at 390px, "Haarentfernungspaste" at 320px) breaks at a syllable, four
   letters kept on each side, with overflow-wrap as the net where the
   browser has no dictionary; otherwise it overflows the panel and the
   screen (tools/smoke/rtl-overflow.mjs). */
.offer__name,
.panel__name {
  hyphens: auto;
  hyphenate-limit-chars: 10 4 4;
  overflow-wrap: break-word;
}

.offer__name {
  margin-block-start: 14px;
}

/* The pack line wraps at its spaces, never inside a figure: every quantity
   and amount is its own left-to-right run (dunya_ltr_run()), kept on one
   line. */
.offer__pack bdi bdi,
.offer__unit bdi bdi {
  white-space: nowrap;
}

.offer__price {
  margin-block-start: 10px;
  font-size: var(--fs-price);
  font-weight: var(--fw-price);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.offer__was s {
  text-decoration-color: var(--text-2);
}

.offer__was .offer__legal,
.offer__was .offer__reason {
  display: block;
}

.offer__edit {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--tap);
  margin-block-start: 8px;
  color: var(--accent);
  font-size: var(--fs-small);
  font-weight: 500;
}

.offers__vat {
  margin-block-start: 24px;
}

.offers__window {
  margin-block-start: 12px;
}

.offers__empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
}

/* The Prospekt panel: the cover beside the title and the dates, one link. */
.offers__flyer {
  margin-block-start: 48px;
}

.offers__flyer-link {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-block-start: 16px;
  max-inline-size: 36rem;
}

.offers__flyer-cover {
  flex: 0 0 96px;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: calc(var(--r-photo) / 2);
  background: var(--band);
}

.offers__flyer-cover img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.offers__flyer-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 4px;
}

.offers__flyer-title {
  font-weight: 500;
}

/* ------------------------------------------------------------------ */
/* The hours and the way (template-parts/visit.php) */
.visit {
  margin-block-start: var(--chapter);
  padding-block: var(--chapter);
  background: var(--visit-ground);
}

.visit__grid {
  display: grid;
  grid-template-areas: 'hours' 'where' 'map' 'rows';
  gap: 40px;
}

.visit__where {
  grid-area: where;
}

.visit__rows {
  grid-area: rows;
}

.visit__hours {
  grid-area: hours;
  min-inline-size: 0;
}

.visit__grid > .place {
  grid-area: map;
}

.visit__sub {
  display: block;
  margin-block-start: 8px;
  color: var(--text-2);
  font-size: var(--fs-intro);
  font-weight: 400;
  letter-spacing: 0;
  line-height: var(--lh-intro);
}

.hours {
  inline-size: 100%;
  margin-block-start: 28px;
  border-collapse: collapse;
}

.hours th,
.hours td {
  padding: 10px 0;
  font-size: var(--fs-hours);
  font-weight: 400;
  line-height: 1.25;
  vertical-align: baseline;
}

.hours th {
  position: relative;
  inline-size: 60%;
  padding-inline-start: 20px;
  padding-inline-end: 16px;
  text-align: start;
}

.hours td {
  text-align: end;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.hours__range {
  display: block;
}

.hours .closed {
  color: var(--text-2);
}

/* Today's group: the dot hanging before the day, the day at 500. */
.hours th .dot {
  display: none;
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: calc(10px + 0.625em - 4px);
}

.hours tr[aria-current] th {
  font-weight: 500;
}

.hours tr[aria-current] th .dot {
  display: inline-block;
}

.hours__holiday,
.hours__missing {
  margin-block-start: 16px;
}

/* The map: a picture panel with the pin and the label over its centre, the
   credit in the corner; one link to Google Maps. */
.place {
  position: relative;
  display: block;
  aspect-ratio: var(--photo-ratio);
  overflow: hidden;
  border-radius: var(--r-photo);
  background: var(--map-ground);
}

.place img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.place picture {
  display: block;
  block-size: 100%;
}

.place__pin {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: 14px;
  block-size: 14px;
  margin: -7px 0 0 -7px;
}

.place__dot,
.place__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
}

.place__dot {
  border: 1.5px solid var(--map-ground);
  background: var(--accent);
}

.place__ring {
  border: 1.5px solid var(--accent);
  opacity: 0.6;
}

.place__label {
  position: absolute;
  inset-block-start: calc(50% + 14px);
  inset-inline-start: 50%;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: var(--map-ground);
  color: var(--text);
  font-size: var(--fs-small);
  font-weight: 500;
  white-space: nowrap;
  transform: translateX(-50%);
}

.place__credit {
  position: absolute;
  inset-block-end: 10px;
  inset-inline-end: 12px;
  padding: 2px 6px;
  border-radius: 4px;
  background: color-mix(in srgb, var(--map-ground) 85%, transparent);
  color: var(--text-2);
  font-size: var(--fs-small);
}

.address {
  font-size: var(--fs-title);
  line-height: 1.3;
}

.address span {
  display: block;
}

.visit__where .actions {
  margin-block-start: 16px;
}

.visit__rows .rows {
  margin-block-start: 0;
}

.rows {
  margin-block-start: 20px;
}

.rows li + li {
  border-block-start: 1px solid var(--line);
}

.row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-block-size: 48px;
  padding-block: 4px;
}

.row > span:first-child {
  flex: 1;
  font-weight: 500;
}

.row bdi {
  color: var(--text-2);
}

@media (min-width: 64em) {
  .visit__grid {
    grid-template-columns: 5fr 6fr;
    grid-template-rows: auto auto 1fr;
    grid-template-areas: 'hours where' 'hours map' 'hours rows';
    column-gap: calc(100% / 12);
    row-gap: 32px;
    align-items: start;
  }

  .place {
    aspect-ratio: 16 / 10;
  }
}

/* ------------------------------------------------------------------ */
/* The pages: the title on the axis, the content under it. */
.page {
  padding-block: 40px 0;
}

.page__title {
  margin-block-end: 24px;
}

.page--short {
  padding-block-end: 0;
}

.page--reading {
  padding-block-end: var(--chapter);
}

/* The Kontakt page's head: the words and the buttons, then the contact
   rows; side by side from 64em with the rows at the inline-end, the
   buttons under the words. The hours band follows at a chapter's distance,
   not two (the band's own top margin is for the Startseite, where a
   chapter precedes it). */
.contact {
  display: grid;
  gap: 32px;
}

/* As a chapter under the Über uns chapter, the head keeps no page padding
   of its own: the chapter above ends at a chapter's distance. */
.contact--chapter {
  padding-block-start: 0;
}

.contact__words .prose {
  margin-block-end: 0;
}

.contact__actions {
  margin-block-start: 24px;
}

.contact__rows {
  margin-block-start: 0;
}

.visit--page {
  margin-block-start: 48px;
}

@media (min-width: 64em) {
  .contact {
    grid-template-columns: minmax(0, 1fr) minmax(0, 480px);
    column-gap: 64px;
    align-items: start;
  }

  .contact__rows {
    margin-block-start: 8px;
  }
}

.page--reading .page__title,
.page--reading .prose,
.page--reading .intro,
.page--reading .page__photo {
  max-inline-size: 42rem;
}

.page--reading > p + p {
  margin-block-start: 16px;
}

.page__photo {
  margin-block-end: 32px;
  aspect-ratio: 4 / 5;
}

@media (min-width: 48em) {
  .page {
    padding-block-start: 56px;
  }

  .page__title {
    margin-block-end: 32px;
  }

  .page__photo {
    aspect-ratio: 16 / 10;
  }
}

/* The Über uns chapter at the end of the Kontakt page: the heading, then
   the shop's photo and the owner's text, stacked on a phone and side by
   side from 64em with the photo at the inline-start. The photo takes the
   design's panel ratio (square in 7, 4:5 in 8) and corners. */
.chapter--about {
  padding-block-end: var(--chapter);
}

/* The chapter that opens a page (the Über uns chapter on the Kontakt page)
   sits where a page's title would, not a chapter's distance down. */
.chapter--first {
  padding-block-start: 40px;
}

@media (min-width: 48em) {
  .chapter--first {
    padding-block-start: 56px;
  }
}

.about__grid {
  display: grid;
  gap: 24px;
}

@media (min-width: 64em) {
  .about__grid {
    grid-template-columns: minmax(0, 480px) minmax(0, 1fr);
    column-gap: 64px;
    align-items: start;
  }
}

/* Running text the owner writes, and the legal pages. */
.prose {
  max-inline-size: 42rem;
}

.prose p,
.prose li {
  margin: 0 0 12px;
  text-wrap: pretty;
}

.prose h2,
.legal h2 {
  margin: 36px 0 8px;
  font-size: var(--fs-title);
  font-weight: 500;
  line-height: 1.2;
}

.prose h3 {
  margin: 24px 0 8px;
  font-size: var(--fs-body);
  font-weight: 500;
}

.prose a,
.legal a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.prose ul,
.legal ul {
  padding-inline-start: 1.2em;
  list-style: disc;
}

.legal p,
.legal li {
  margin: 0 0 12px;
  text-wrap: pretty;
}

.legal .placeholder {
  color: var(--accent);
  font-weight: 500;
}

.legal__note {
  margin-block-end: 24px;
  color: var(--text-2);
}

.legal__note a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* ------------------------------------------------------------------ */
/* The Sortiment (template-parts/catalogue/): the search and the filter
   button in one row, the filters as a sidebar from 56.25em and a drawer
   below, the result beside them. */
.catalogue {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
}

.catalogue__label {
  display: block;
  margin-block-end: 8px;
  font-weight: 500;
}

.catalogue__row {
  display: flex;
  gap: 12px;
}

.catalogue__search-field {
  position: relative;
  display: flex;
  flex: 1;
  align-items: center;
  min-inline-size: 0;
  border: 1px solid var(--edge);
  border-radius: var(--r-pill);
  background: var(--ground);
}

.catalogue__search-field > svg {
  flex-shrink: 0;
  inline-size: 20px;
  block-size: 20px;
  margin-inline-start: 16px;
  color: var(--text-2);
}

.catalogue__search-field input {
  flex: 1;
  inline-size: 100%;
  min-inline-size: 0;
  min-block-size: var(--tap);
  padding: 0 12px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
}

.catalogue__search-field input:focus-visible {
  outline: none;
}

.catalogue__search-field:focus-within {
  border-color: var(--accent);
  outline: 1px solid var(--accent);
}

.catalogue__search-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--tap);
  block-size: var(--tap);
  margin-inline-end: 2px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

.catalogue__search-submit svg {
  inline-size: 20px;
  block-size: 20px;
}

.catalogue__filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-block-size: var(--tap);
  padding: 0 18px;
  border: 1px solid var(--edge);
  border-radius: var(--r-pill);
  background: transparent;
  font-weight: 500;
  cursor: pointer;
}

.catalogue__filter-toggle svg {
  inline-size: 18px;
  block-size: 18px;
}

.catalogue__filter-count {
  color: var(--text-2);
}

/* The filters are a <dialog>. Closed, the browser hides it; without the
   script (no html.js) they stay open in the page. */
.catalogue__filters {
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
}

html:not(.js) .catalogue__filters {
  display: block;
  position: static;
}

/* Without the script the Filter button could open nothing. */
html:not(.js) .catalogue__filter-toggle {
  display: none;
}

.catalogue__drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.catalogue__drawer-title {
  font-size: var(--fs-title);
  font-weight: 500;
}

.catalogue__drawer-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--tap);
  block-size: var(--tap);
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

.catalogue__drawer-close svg {
  inline-size: 18px;
  block-size: 18px;
}

.catalogue__body {
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding-block: 24px;
}

.catalogue__group {
  margin: 0;
  padding: 0;
  border: 0;
}

.catalogue__choice,
.catalogue__check {
  display: flex;
  align-items: center;
  gap: 12px;
  min-block-size: var(--tap);
  cursor: pointer;
}

.catalogue__choice svg {
  inline-size: 20px;
  block-size: 20px;
  color: var(--text-2);
}

.catalogue__choice input,
.catalogue__check input {
  inline-size: 20px;
  block-size: 20px;
  margin: 0;
  accent-color: var(--accent);
}

.catalogue__choice:has(input:checked) {
  font-weight: 500;
}

.catalogue__select {
  min-block-size: var(--tap);
  padding: 0 12px;
  border: 1px solid var(--edge);
  border-radius: 12px;
  background: var(--ground);
  color: var(--text);
  font: inherit;
}

.catalogue__apply {
  align-self: flex-start;
}

/* With the script, "Anwenden" is hidden: in the drawer "Ergebnisse zeigen"
   applies, and on a wide screen a choice made with the mouse or a tap
   applies at once. A choice made with the keyboard waits for "Anwenden"
   (assets/js/catalogue.js marks the form data-pending), so the arrow keys
   can step through the choices without a reload on every step. */
.js .catalogue__apply {
  display: none;
}

.catalogue__drawer-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding-block-start: 16px;
  border-block-start: 1px solid var(--line);
}

/* The drawer, below 56.25em: open, the dialog lies against the inline-start
   edge (from the left in German, from the right in Arabic), the page dimmed
   behind it. */
@media (max-width: 56.24em) {
  .js .catalogue__filters[open] {
    position: fixed;
    inset: 0;
    inset-inline-end: auto;
    inline-size: min(100%, 22rem);
    block-size: 100%;
    max-inline-size: none;
    max-block-size: none;
    margin: 0;
    overflow: auto;
    background: var(--ground);
    border-inline-end: 1px solid var(--line);
  }

  .catalogue__filters::backdrop {
    background: rgb(0 0 0 / 0.4);
  }

  .catalogue__panel {
    padding: 16px var(--gutter) 24px;
  }
}

@media (min-width: 56.25em) {
  .catalogue {
    grid-template-columns: 16rem minmax(0, 1fr);
    column-gap: 48px;
    align-items: start;
  }

  .catalogue__search {
    grid-column: 1 / -1;
  }

  .catalogue__filter-toggle {
    display: none;
  }

  .catalogue__filters {
    display: block;
    position: sticky;
    inset-block-start: calc(var(--nav) + 24px);
  }

  .catalogue__drawer-head,
  .catalogue__drawer-foot {
    display: none;
  }

  .js .catalogue__form[data-pending] .catalogue__apply {
    display: inline-flex;
  }

  .catalogue__body {
    padding-block: 0;
  }
}

.catalogue__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 16px;
  margin-block-end: 24px;
}

.catalogue__heading {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-title);
  font-weight: 500;
}

.catalogue__heading svg {
  inline-size: 22px;
  block-size: 22px;
  color: var(--text-2);
}

.catalogue__description {
  margin-block-end: 24px;
}

/* ------------------------------------------------------------------ */
/* The footer */
.footer {
  position: relative;
  padding-block: 48px;
}

.footer::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  block-size: 1px;
  background: var(--line);
}

.footer__grid {
  display: grid;
  justify-items: start;
  gap: 24px;
}

.footer__names {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  font-weight: 500;
}

.footer__other {
  color: var(--text-2);
  font-weight: 400;
}

.footer__brand .meta {
  margin-block-start: 6px;
}

.footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 24px;
}

.footer__links a {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--tap);
  font-weight: 500;
}

.footer__links a[aria-current='page'] {
  color: var(--accent);
}

.footer__copy {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 8px;
}

.footer__copy a {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--tap);
}

@media (min-width: 48em) {
  .footer__grid {
    grid-template-columns: 1fr auto auto;
    align-items: center;
  }

  .footer__copy {
    grid-column: 1 / -1;
  }
}

/* ------------------------------------------------------------------ */
/* Motion. Every hidden start state is scoped to .motion, so without the
   class (reduced motion, or no script) the page is complete and still. */

/* On load the hero's parts rise 16px and fade in, 60ms apart. */
.motion [data-enter] {
  animation: enter 480ms var(--ease-arrive) both;
  animation-delay: calc(var(--n, 0) * 60ms);
}

@keyframes enter {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Reveals: a panel or the hours block rises 16px and fades in once as it
   enters (site.js lights it); --d staggers the panels of a rail. The
   transition exists only under .motion, so reduced motion has none. The
   hidden start state is for the screen only: print matches
   prefers-reduced-motion: no-preference too, and a printed Angebote page
   would keep every panel the visitor had not scrolled to blank, its price
   and legal lines missing (tools/smoke/motion-reduce.mjs prints /de/offers/
   to prove it does not). The design files scope their own start states the
   same way. */
.motion [data-reveal] {
  transition:
    opacity 560ms var(--ease-arrive),
    transform 560ms var(--ease-arrive);
  transition-delay: var(--d, 0ms);
}

@media screen {
  .motion [data-reveal]:not(.is-lit) {
    opacity: 0;
    transform: translateY(16px);
  }
}

/* The pin's ring breathes once the map is in view. */
.motion .place[data-reveal].is-lit .place__ring {
  animation: breathe 2.4s ease-in-out 600ms infinite;
}

@keyframes breathe {
  0%,
  100% {
    opacity: 0.6;
    transform: scale(1);
  }
  50% {
    opacity: 0.15;
    transform: scale(1.8);
  }
}

/* The status text cross-fades when its words change. */
[data-status],
[data-status-heading],
[data-status-sub] {
  transition: opacity 160ms var(--ease-arrive);
}

.is-swapping {
  opacity: 0;
}

/* Late load: if the script never runs, this lights every panel three seconds
   after the stylesheet applied, so no content can stay hidden. site.js adds
   "reveal-ready" first thing to switch it off. */
.motion:not(.reveal-ready) [data-reveal] {
  animation: fallback-light 1ms linear 3s both;
}

@keyframes fallback-light {
  to {
    opacity: 1;
    transform: none;
  }
}

/* Reduced motion: the stylesheet above already shows everything when .motion
   is absent. This block only guards the few transitions that run without it
   (the pills, the chevrons, the nav's name and line, the status text). They
   are switched off, not shortened: a near-zero duration on every property
   of every element still makes each style change a running transition, so
   a computed style read right after the change still returns the old value
   (tools/smoke/motion-reduce.mjs asks for no transition at all). Animations
   are only shortened, because the progress line's scroll-driven travel is
   an animation too and must keep following the rail. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation-duration: 0.01ms !important;
  }
}
