/*
 * Halil İbrahim Sofrası — QR Menü · misafir menüsü stilleri
 *
 * Renk ve tipografi tanımları burada DEĞİL, tokens.css içindedir; o dosya iki
 * sayfada da ayrıca yüklenir.
 *
 * Yön (RTL) yalnızca mantıksal özelliklerle kurulur — margin-inline,
 * padding-inline, inset-inline, border-block-end. Yerleşim CSS'inde
 * left/right YOKTUR; <html dir="rtl"> tek anahtardır.
 */

/*
 * Layout is built with logical properties only — margin-inline, padding-inline,
 * inset-inline, border-block-end — so `dir` on <html> is the single switch that
 * turns the whole app right-to-left. No `left` / `right` in layout CSS.
 */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

html {
  /* Programmatic scroll is driven from JS so it can be suppressed; the CSS
     property would fight the observer and ignore prefers-reduced-motion here. */
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  /* The guest is holding the phone in one hand; nothing should rubber-band. */
  overscroll-behavior-y: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-heading);
  font-weight: 400;
  letter-spacing: -0.025em;
  margin: 0;
}

/*
 * Ana başlıklar daha kalın.
 *
 * Instrument Serif tek ağırlıkta (400) yayınlanıyor; bold varyantı YOK.
 * Gerçek kalın için ikinci bir font ailesi indirmek gerekirdi — sayfa hızı
 * bütçesi buna müsait değil. Bunun yerine harf konturunu bir tık
 * kalınlaştırıyoruz: bayt maliyeti sıfır, yazının karakteri korunuyor.
 *
 * Miktarı tek yerden ayarlanır; 0 yapmak eski inceliğe döndürür.
 */
.e-welcome,
.e-restaurantName,
.m-headerName,
.d-name,
.s-title,
.m-emptyTitle {
  -webkit-text-stroke: var(--heading-stroke) currentColor;
  paint-order: stroke fill;
}

[dir="rtl"] h1,
[dir="rtl"] h2,
[dir="rtl"] h3,
[dir="rtl"] h4,
[dir="rtl"] h5,
[dir="rtl"] h6 {
  /* Amiri's sidebearings do not want the Latin display tracking. */
  letter-spacing: 0;
}

p {
  margin: 0;
}

img {
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
}

/* Never the browser default. */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

:focus:not(:focus-visible) {
  outline: none;
}

/* Prices, grams, counts and clock figures — never running prose. */
.tabular {
  font-variant-numeric: tabular-nums;
}

/* Numbers stay in Latin figures inside right-to-left text. */
.ltr {
  direction: ltr;
  unicode-bidi: isolate;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------------------
 * Buttons — outlined only. Accent is a stroke, not a fill.
 * ------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 10px 16px;
  font-family: var(--font-heading);
  font-size: 15px;
  letter-spacing: -0.025em;
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  color: var(--color-text);
  cursor: pointer;
  text-align: center;
  transition: background-color var(--motion-fast) var(--ease-out);
}

[dir="rtl"] .btn {
  letter-spacing: 0;
}

.btn:active {
  background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}

.btn-accent {
  border-color: var(--color-accent);
  color: var(--color-accent-700);
}

/* The one "selected" treatment in the system: accent outline + 10% tint. */
.btn-selected {
  border-color: var(--color-accent);
  color: var(--color-accent-700);
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
}

.btn-block {
  display: flex;
  width: 100%;
}

/* ---------------------------------------------------------------------------
 * Motion
 * ------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------------------------------------------------------------------------
 * Page shell — desktop must work, but it is not a priority: the same
 * single-column composition, centred at a max width.
 * ------------------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: 460px;
  margin-inline: auto;
  min-height: 100dvh;
  background: var(--color-bg);
  position: relative;
}

@media (min-width: 560px) {
  body {
    background: var(--color-surface);
  }

  .shell {
    box-shadow: var(--shadow-md);
  }
}


/* ===== Giriş ekranı ===== */
/* Entry — "Kapıdan gir". The moment the brand lands, and where the guest
   picks a language before the menu. */

.e-screen {
  /*
   * İki ayrı ölçü:
   *
   *   --band-height    fotoğrafın nereye kadar uzandığı
   *   --content-offset yazıların başladığı yer
   *
   * Bunlar eskiden aynı sayıydı; fotoğraf yazının başladığı yerde kesiliyordu.
   * Ayrıldıklarında fotoğraf logonun ve karşılama yazısının ARKASINDAN devam
   * ediyor, solma da çok daha aşağıda başlıyor.
   */
  --band-height: clamp(520px, 88vh, 900px);
  --content-offset: clamp(250px, 36vh, 370px);

  /*
   * Solmanın başladığı nokta — bandın yüzdesi olarak. "Dilinizi seçin"
   * satırının hizasına denk gelir. Fotoğrafı daha erken kapatmak isterseniz
   * bu değeri düşürün (örn. %55), daha geç için yükseltin.
   */
  --band-fade-start: 72%;

  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  position: relative;
  background: var(--color-bg);
  overflow: hidden;
}

[dir="rtl"] .e-screen {
  /* Arapça kolonu daha uzun: içerik biraz yukarıdan başlıyor. */
  --band-height: clamp(470px, 82vh, 820px);
  --content-offset: clamp(220px, 31vh, 320px);
}

/* Full-bleed photo band anchored to the top. */
.e-band {
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: var(--band-height);
  z-index: 0;
  background: var(--color-surface);
}

.e-bandImage {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Bant uzadıkça `cover` fotoğrafı kırpar; kırpma alttan olsun ki binanın
     üstü ve gökyüzü kalsın — alt taraf zaten solmanın içinde kayboluyor. */
  object-position: center top;
}

/* Stand-in until the restaurant supplies a hero photograph: the same hairline
   texture the no-photo dish block uses, so it reads as intentional. */
.e-bandFallback {
  width: 100%;
  height: 100%;
  background:
    repeating-linear-gradient(
      135deg,
      color-mix(in srgb, var(--color-accent) 7%, var(--color-surface)) 0 9px,
      var(--color-surface) 9px 18px
    );
}

/* Dissolves the band into the page ground. */
.e-scrim {
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: var(--band-height);
  z-index: 1;
  pointer-events: none;

  /*
   * Ara duraklar bantlanmayı (gradient banding) önlüyor — üç duraklı geçişte
   * kâğıt renginin içinde gözle görülür halkalar oluşuyordu.
   *
   * Son durak `calc(100% - 20px)`: içerik bloğunun düz zemini tam orada
   * başlıyor. Geçiş bir önceki sürümde %100'e kadar sürdüğü için düz zemin
   * hâlâ yarı saydam bir noktada devralıyor ve fotoğraf "kesilmiş" gibi ince
   * bir çizgi bırakıyordu.
   */
  /*
   * Solma çok daha aşağıda başlıyor: fotoğraf üst üçte ikilik bölümde tam
   * netlikte duruyor, sonra kâğıt rengine karışıyor. Ara duraklar bantlanmayı
   * (banding) önlüyor — krem tonlarında az duraklı geçişte gözle görülür
   * halkalar oluşuyor.
   */
  background: linear-gradient(
    to bottom,
    transparent 0,
    transparent var(--band-fade-start),
    color-mix(in srgb, var(--color-bg) 32%, transparent)
      calc(var(--band-fade-start) + (100% - var(--band-fade-start)) * 0.22),
    color-mix(in srgb, var(--color-bg) 62%, transparent)
      calc(var(--band-fade-start) + (100% - var(--band-fade-start)) * 0.45),
    color-mix(in srgb, var(--color-bg) 84%, transparent)
      calc(var(--band-fade-start) + (100% - var(--band-fade-start)) * 0.68),
    color-mix(in srgb, var(--color-bg) 95%, transparent)
      calc(var(--band-fade-start) + (100% - var(--band-fade-start)) * 0.86),
    var(--color-bg) 100%
  );
}

/* Sits on solid ground, overlapping the scrim's last 20px. */
.e-content {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding: 0 34px 6px;
  margin-top: var(--content-offset);
  text-align: center;
  /*
   * Saydam: düz zemin verilirse fotoğrafı tam burada keser — "resim kesilmiş"
   * görüntüsünün asıl sebebi buydu. Zemin zaten .e-screen'den geliyor;
   * yazıların okunurluğunu üstteki solma katmanı sağlıyor.
   */
  background: transparent;
}

.e-logo {
  width: 168px;
  height: auto;
  /* Pulled up so the logo straddles the photo edge. */
  margin-top: -72px;
  position: relative;
  z-index: 2;
}

[dir="rtl"] .e-logo {
  width: 150px;
  margin-top: -64px;
}

.e-restaurantName {
  font-size: 27px;
  line-height: 1.3;
  margin-top: 14px;
}

.e-rule {
  width: 52px;
  height: 1px;
  background: var(--color-divider);
  margin: 26px 0;
}

.e-welcome {
  font-family: var(--font-heading);
  font-size: 23px;
}

[dir="rtl"] .e-welcome {
  font-size: 26px;
}

.e-sub {
  font-size: 13.5px;
  color: var(--color-neutral-700);
  margin-top: 8px;
  line-height: 1.6;
}

[dir="rtl"] .e-sub {
  font-size: 15px;
  line-height: 1.7;
}

.e-langGrid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  width: 100%;
  margin-top: 26px;
}

.e-langButton {
  min-height: 52px;
  font-size: 15px;
}

/* Arabic and Persian labels are set in their own script, one step larger. */
.e-langButtonArabic {
  font-family: var(--font-arabic);
  font-size: 19px;
}

.e-enter {
  min-height: 56px;
  font-size: 17px;
  letter-spacing: 0.02em;
  margin-top: 22px;
}

[dir="rtl"] .e-enter {
  font-family: var(--font-arabic);
  font-size: 20px;
  letter-spacing: 0;
}

.e-legal {
  position: relative;
  z-index: 2;
  flex: 0 0 auto;
  text-align: center;
  padding: 0 24px 26px;
  font-size: 11px;
  color: var(--color-neutral-700);
  line-height: 1.7;
  background: var(--color-bg);
}

[dir="rtl"] .e-legal {
  font-size: 12.5px;
  line-height: 1.8;
}


/* ===== Menü ===== */
/* One long scrolling page: header, sticky category bar, then every category
   stacked. There is no route change for the rest of the session. */

.m-page {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

.m-skipLink {
  position: absolute;
  inset-block-start: -100px;
  inset-inline-start: 8px;
  z-index: 20;
  background: var(--color-bg);
  border: 1px solid var(--color-accent);
  padding: 10px 14px;
  border-radius: var(--radius-md);
}

.m-skipLink:focus {
  inset-block-start: 8px;
}

/* --- Header ------------------------------------------------------------- */

.m-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px var(--gutter) 12px;
  border-block-end: 1px solid var(--color-divider);
  background: var(--color-bg);
  /* Stays above the dim so the language trigger reads as the panel's source. */
  position: relative;
  z-index: 12;
}

.m-headerBrand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.m-headerLogo {
  height: 42px;
  width: auto;
}

.m-headerName {
  font-size: 19px;
  line-height: 1.3;
  font-family: var(--font-heading);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.m-langTrigger {
  min-height: 44px;
  font-size: 13px;
  flex: 0 0 auto;
}

[dir="rtl"] .m-langTrigger {
  font-size: 16px;
}

/* --- Category bar ------------------------------------------------------- */

.m-categoryBar {
  position: sticky;
  /* The header may scroll away; the category bar must not. */
  inset-block-start: 0;
  z-index: 10;
  flex: 0 0 auto;
  background: var(--color-bg);
  border-block-end: 1px solid var(--color-divider);
  transition: box-shadow var(--motion-fast) var(--ease-out);
}

.m-categoryBarStuck {
  box-shadow: var(--shadow-sm);
}

.m-categoryScroller {
  display: flex;
  gap: 19px;
  padding-inline: var(--gutter);
  white-space: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  overscroll-behavior-inline: contain;
}

.m-categoryScroller::-webkit-scrollbar {
  display: none;
}

.m-tab {
  flex: 0 0 auto;
  /* Pad the anchor, not the label — the tap target has to clear 44px. */
  padding-block: 13px;
  font-family: var(--font-heading);
  font-size: 15px;
  line-height: 1.4;
  color: var(--color-neutral-600);
  border-block-end: 2px solid transparent;
  background: none;
  border-inline: 0;
  border-block-start: 0;
  cursor: pointer;
  scroll-margin-inline: var(--gutter);
}

[dir="rtl"] .m-tab {
  font-size: 17px;
  padding-block: 12px;
}

.m-tabActive {
  color: var(--color-text);
  border-block-end-color: var(--color-accent);
}

/* --- Sections ----------------------------------------------------------- */

.m-sections {
  flex: 1 1 auto;
  padding-inline: var(--gutter);
}

.m-section {
  /* Clears the sticky bar when a tab scrolls this section into view. */
  scroll-margin-block-start: var(--category-bar-height);
}

.m-sectionHeader {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-top: 22px;
}

.m-sectionTitle {
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  margin: 0;
  /* 12px'te Instrument Serif'in ince tırnakları kayboluyor. Newsreader zaten
     yüklü ve 500 ağırlığı var — ek bayt olmadan daha sağlam duruyor. */
  font-family: var(--font-body);
  font-weight: 500;
}

[dir="rtl"] .m-sectionTitle {
  font-size: 17px;
  letter-spacing: 0;
  text-transform: none;
  font-family: var(--font-arabic);
}

.m-sectionRule {
  flex: 1;
  height: 1px;
  background: var(--color-divider);
}

.m-sectionCount {
  font-size: 11px;
  color: var(--color-neutral-600);
}

/* --- Empty category ----------------------------------------------------- */

.m-empty {
  border: 1px dashed var(--color-neutral-400);
  border-radius: var(--radius-md);
  padding: 18px;
  text-align: center;
  margin-top: 14px;
}

.m-emptyTitle {
  font-family: var(--font-heading);
  font-size: 16px;
}

.m-emptyNote {
  font-size: 12.5px;
  color: var(--color-neutral-700);
  margin-top: 6px;
  line-height: 1.5;
}

/* --- Page footer -------------------------------------------------------- */

.m-footer {
  margin-top: 20px;
  border-block-start: 1px solid var(--color-divider);
  padding-top: 16px;
  padding-bottom: 26px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.m-footerCall {
  min-height: 48px;
}

.m-footerGrid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.m-footerLink {
  min-height: 44px;
  font-size: 14px;
}

.m-footerHours {
  font-size: 15px;
  text-align: center;
  padding: 10px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
}

.m-footerNote {
  font-size: 11.5px;
  color: var(--color-neutral-700);
  margin-top: 6px;
  line-height: 1.75;
}

/* --- Language panel ----------------------------------------------------- */

.m-dim {
  position: fixed;
  inset: 0;
  z-index: 11;
  background: var(--dim-panel);
  border: 0;
  padding: 0;
  cursor: default;
  animation: fade-in var(--motion-fast) var(--ease-out);
}

/* Viewport-anchored, not page-anchored: `.m-shell` is a positioned ancestor, so
   `absolute` would put the panel 66px from the top of the *document* and leave
   it off-screen for a guest who has scrolled. */
.m-panel {
  position: fixed;
  inset-inline-end: 14px;
  inset-block-start: 66px;
  z-index: 13;
  width: 238px;
  background: var(--color-bg);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  animation: panel-in var(--motion-fast) var(--ease-out);
}

@media (min-width: 560px) {
  .m-panel {
    /* Hug the centred column rather than the viewport edge. */
    inset-inline-end: calc(50% - 230px + 14px);
  }
}

.m-panelCaption {
  padding: 12px 16px 8px;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
  font-family: var(--font-heading);
}

.m-panelRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 13px 16px;
  border-block-start: 1px solid var(--color-divider);
  font-family: var(--font-heading);
  font-size: 17px;
  background: none;
  border-inline: 0;
  border-block-end: 0;
  text-align: start;
  cursor: pointer;
}

.m-panelRowArabic {
  font-family: var(--font-arabic);
  font-size: 20px;
  direction: rtl;
}

.m-panelRowActive {
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
}

.m-panelCheck {
  color: var(--color-accent-700);
  font-size: 15px;
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes panel-in {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .m-dim,
  .m-panel {
    animation: none;
  }
}


/* ===== Ürün satırı ===== */
/* Product row anatomy. Every field is optional — the row must not break when
   any of them is missing. One column, no nested cards. */

.d-row {
  position: relative;
  display: flex;
  gap: 14px;
  align-items: flex-start;
  width: 100%;
  padding-block: 17px;
  border-block-end: 1px solid var(--color-divider);
  cursor: pointer;
}

.d-row:last-child {
  border-block-end: 0;
}

.d-photo {
  flex: 0 0 92px;
  width: 92px;
  height: 92px;
  object-fit: contain;
}

/* Also the shape of the skeleton while an image loads. */
.d-placeholder {
  flex: 0 0 84px;
  width: 84px;
  height: 84px;
  border: 5px solid var(--color-surface);
  outline: 1px solid var(--color-divider);
  background: repeating-linear-gradient(
    135deg,
    var(--color-hatch-a) 0 6px,
    var(--color-hatch-b) 6px 12px
  );
}

/* Nothing is hidden when a dish sells out — it just goes quiet. */
.d-soldOutMedia {
  filter: grayscale(1) opacity(0.55);
}

.d-body {
  flex: 1 1 auto;
  min-width: 0;
}

.d-nameLine {
  display: flex;
  /*
   * `baseline` değil `center`.
   *
   * Taban çizgisi hizalaması rozetin kendi taban çizgisini ürün adınınkine
   * oturtuyordu; rozet 10,5 punto, ad 21 punto olduğu için rozetin gövdesi
   * adın epey altında kalıyor ve "aşağı kaçmış" görünüyordu. Ortalama, küçük
   * kutuyu adın satır kutusunun ortasına getiriyor.
   */
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* The row's only interactive element; its ::after covers the whole row. */
.d-name {
  font-family: var(--font-heading);
  font-size: 21px;
  line-height: 1.15;
  letter-spacing: -0.025em;
  color: var(--color-text);
  background: none;
  border: 0;
  padding: 0;
  text-align: start;
  cursor: pointer;
}

.d-name::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.d-name:focus-visible {
  outline: none;
}

.d-name:focus-visible::after {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
  border-radius: var(--radius-sm);
}

[dir="rtl"] .d-name {
  letter-spacing: 0;
  font-size: 22px;
  line-height: 1.3;
}

.d-nameSoldOut {
  color: var(--color-neutral-600);
}

.d-badge {
  font-family: var(--font-heading);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 2px 7px;
  border: 1px solid var(--color-accent-700);
  color: var(--color-accent-700);
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

[dir="rtl"] .d-badge {
  letter-spacing: 0.08em;
  text-transform: none;
}

.d-badgeSoldOut {
  border-color: var(--color-neutral-500);
  color: var(--color-neutral-500);
}

/* The name in the other script — Latin in the Arabic views, and the reverse. */
.d-translit {
  font-size: 13px;
  font-style: italic;
  color: var(--color-neutral-600);
  margin-top: 2px;
}

.d-translitArabic {
  font-family: var(--font-arabic);
  font-style: normal;
  font-size: 15px;
}

.d-translitLatin {
  font-family: Newsreader, "Newsreader Fallback", Georgia, serif;
  font-style: italic;
  font-size: 12.5px;
}

.d-desc {
  font-size: 13.5px;
  line-height: 1.5;
  margin-top: 5px;
  color: var(--color-neutral-800);
  text-wrap: pretty;
}

/* Arabic body copy needs more line-height than the Latin equivalent. */
[dir="rtl"] .d-desc {
  font-size: 15px;
  line-height: 1.7;
  margin-top: 4px;
}

.d-descSoldOut {
  color: var(--color-neutral-600);
}

.d-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 9px;
  flex-wrap: wrap;
}

.d-gram {
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--color-neutral-600);
}

.d-spacer {
  flex: 1 1 auto;
}

.d-price {
  font-family: var(--font-heading);
  font-size: 20px;
  color: var(--color-text);
  white-space: nowrap;
}

.d-priceSoldOut {
  color: var(--color-neutral-600);
}

/* --- Variant prices ----------------------------------------------------- */

.d-variants {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.d-variantRow {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.d-variantLabel {
  font-size: 12.5px;
  color: var(--color-neutral-700);
  white-space: nowrap;
}

[dir="rtl"] .d-variantLabel {
  font-size: 14px;
}

.d-variantLeader {
  flex: 1 1 auto;
  border-block-end: 1px dotted var(--color-neutral-400);
  transform: translateY(-3px);
}

.d-variantPrice {
  font-family: var(--font-heading);
  font-size: 18px;
  white-space: nowrap;
}

/* --- Allergen badge ----------------------------------------------------- */

.d-allergen {
  width: 21px;
  height: 21px;
  min-width: 21px;
  border: 1px solid var(--color-neutral-400);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-heading);
  font-size: 11px;
  color: var(--color-neutral-700);
  background: none;
  padding: 0;
  cursor: pointer;
}

/* Tap — never hover — reveals the allergen's name. */
.d-allergenPopover {
  position: relative;
  /* Above the name button's row-wide overlay, so a tap hits the badge. */
  z-index: 2;
}

.d-allergenTip {
  position: absolute;
  inset-block-end: calc(100% + 6px);
  inset-inline-start: 50%;
  transform: translateX(-50%);
  z-index: 5;
  white-space: nowrap;
  background: var(--color-bg);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 5px 9px;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--color-text);
}

[dir="rtl"] .d-allergenTip {
  transform: translateX(50%);
}


/* ===== Ürün detayı ===== */
/* Product detail sheet — a bottom sheet over the dimmed menu. */

.s-dim {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: var(--dim-sheet);
  border: 0;
  padding: 0;
  cursor: default;
  animation: dim-in var(--motion-base) var(--ease-out);
}

/* The dialog spans the viewport so the sheet and the close button — which
   sits above the sheet, over the dim — are both inside the focus trap. */
.s-container {
  position: fixed;
  inset: 0;
  z-index: 31;
  pointer-events: none;
}

.s-container > * {
  pointer-events: auto;
}

.s-sheet {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  width: 100%;
  max-width: 460px;
  margin-inline: auto;
  max-height: 90dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--color-bg);
  border-block-start: 1px solid var(--color-divider);
  border-start-start-radius: var(--radius-lg);
  border-start-end-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 12px 20px 26px;
  animation: sheet-in var(--motion-base) var(--ease-out);
  touch-action: pan-y;
}

.s-handle {
  width: 44px;
  height: 4px;
  border-radius: 2px;
  background: var(--color-neutral-400);
  margin: 0 auto 14px;
  border: 0;
  padding: 0;
  display: block;
  cursor: grab;
}

.s-photo {
  width: 100%;
  height: 200px;
  /* Tabak bilerek kırpılır: satırdaki küçük görsel tabağın tamamı gibi
     okunur, detay penceresi ise yakın plan gibi. Kırpma alttan yapılır ki
     tabağın üst kenarı ve sunum korunsun. */
  object-fit: cover;
  object-position: top;
}

.s-placeholder {
  width: 100%;
  /* Aynı yuvanın fotoğrafsız hâli — .s-photo ile aynı boyda durmalı. */
  height: 200px;
  border: 5px solid var(--color-surface);
  outline: 1px solid var(--color-divider);
  background: repeating-linear-gradient(
    135deg,
    var(--color-hatch-a) 0 6px,
    var(--color-hatch-b) 6px 12px
  );
}

.s-soldOutMedia {
  filter: grayscale(1) opacity(0.55);
}

.s-titleLine {
  display: flex;
  /* Satırdakiyle aynı gerekçe; 31 puntoluk başlıkta fark daha da belirgindi. */
  align-items: center;
  gap: 9px;
  margin-top: 16px;
  flex-wrap: wrap;
}

.s-title {
  font-size: 31px;
  line-height: 1.1;
}

[dir="rtl"] .s-title {
  font-size: 30px;
  line-height: 1.3;
}

.s-titleSoldOut {
  color: var(--color-neutral-600);
}

.s-badge {
  font-family: var(--font-heading);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 2px 7px;
  border: 1px solid var(--color-accent-700);
  color: var(--color-accent-700);
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

[dir="rtl"] .s-badge {
  letter-spacing: 0.08em;
  text-transform: none;
}

.s-badgeSoldOut {
  border-color: var(--color-neutral-500);
  color: var(--color-neutral-500);
}

.s-translit {
  font-size: 17px;
  color: var(--color-neutral-600);
  margin-top: 4px;
}

.s-translitArabic {
  font-family: var(--font-arabic);
}

.s-translitLatin {
  font-family: Newsreader, "Newsreader Fallback", Georgia, serif;
  font-style: italic;
  font-size: 15px;
}

.s-desc {
  font-size: 14px;
  line-height: 1.6;
  color: var(--color-neutral-800);
  margin-top: 10px;
  text-align: justify;
  hyphens: auto;
}

[dir="rtl"] .s-desc {
  font-size: 16px;
  line-height: 1.8;
  hyphens: none;
}

/* Allergen chips carry the word, not just the letter. */
.s-chips {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 16px;
  padding: 0;
  list-style: none;
}

.s-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 36px;
  padding-inline: 12px;
  border: 1px solid var(--color-neutral-400);
  border-radius: var(--radius-md);
  font-size: 12.5px;
}

.s-chipLetter {
  font-family: var(--font-heading);
  color: var(--color-accent-700);
}

.s-chipNeutral {
  color: var(--color-neutral-700);
}

.s-prices {
  margin-top: 18px;
  border-block-start: 1px solid var(--color-divider);
  padding-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.s-priceRow {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.s-priceLabel {
  font-size: 14px;
}

.s-priceLeader {
  flex: 1;
  border-block-end: 1px dotted var(--color-neutral-400);
  transform: translateY(-4px);
}

.s-priceValue {
  font-family: var(--font-heading);
  font-size: 22px;
  white-space: nowrap;
}

/* Above the sheet, over the dim. */
.s-close {
  position: absolute;
  inset-block-start: 70px;
  inset-inline-end: 18px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--color-bg);
  border: 1px solid var(--color-divider);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

@media (min-width: 560px) {
  .s-close {
    /* Keep it inside the centred column rather than at the viewport edge. */
    inset-inline-end: calc(50% - 230px + 18px);
  }
}

@keyframes dim-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes sheet-in {
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .s-dim,
  .s-sheet {
    animation: none;
  }
}
/* ===== Hareket =============================================================
 *
 * Giriş ekranı bir koreografi: arka plan yavaşça belirir, logo oturur,
 * karşılama yazılır, dil düğmeleri tek tek yanar, en sonda "Kapıdan gir"
 * çıkar. Toplam yaklaşık 2 saniye.
 *
 * Bu, tasarım brief'inin "yalnızca üç durumda animasyon, 300 ms altı" kuralını
 * bilerek aşıyor — restoranın isteği. Kuralın ARDINDAKİ gerekçe korunuyor:
 * hiçbir animasyon bir şeyi geciktirip aç bir misafiri bekletmiyor
 * (ekrana dokunmak diziyi anında bitirir), yalnızca `transform` ve `opacity`
 * oynatılıyor, bounce yok.
 *
 * Zaman ölçeği tek değişkenle yönetilir:
 *   --intro: 1     tam koreografi (ilk açılış)
 *   --intro: 0.3   kısa geçiş (dil değiştirince)
 *   --intro: 0     anında (tekrar ziyaret, ya da misafir ekrana dokundu)
 *
 * Bölümün tamamı `prefers-reduced-motion: no-preference` içinde. Hareketi
 * kapatmış misafirde hiçbir öğe gizlenmez; sadece animasyon olmaz.
 * ========================================================================= */

@media (prefers-reduced-motion: no-preference) {
  @keyframes hs-rise {
    from {
      opacity: 0;
      transform: translateY(10px);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }

  @keyframes hs-fade {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }

  /*
   * Giriş ekranı öğeleri için ayrı bir yükseliş.
   *
   * `pointer-events: none` kritik: dizi oynarken henüz belirmemiş öğe
   * `opacity: 0` olsa da tıklanabilir kalır. Bu olmadan, "Kapıdan gir"in
   * bulunduğu yere denk gelen bir dokunuş, misafirin göremediği bir düğmeyi
   * çalıştırırdı. `backwards` dolgusu sayesinde gecikme boyunca 0% durumu
   * geçerlidir; animasyon bitince öğe doğal (tıklanabilir) hâline döner.
   *
   * Menüdeki `hs-rise` bilerek ayrı tutuldu — orada satırların bir an
   * tıklanamaz olmasına gerek yok.
   */
  @keyframes hs-rise-gated {
    from {
      opacity: 0;
      transform: translateY(10px);
      pointer-events: none;
    }
    to {
      opacity: 1;
      transform: none;
    }
  }

  /* Arka plan: yavaşça belirirken hafifçe yerine oturur. */
  @keyframes hs-hero-in {
    from {
      opacity: 0;
      transform: scale(1.06);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }

  /* Logo aşağıdan gelip yerine oturur. */
  @keyframes hs-logo-in {
    from {
      opacity: 0;
      transform: translateY(18px) scale(0.96);
      pointer-events: none;
    }
    to {
      opacity: 1;
      transform: none;
    }
  }

  /* İnce çizgi ortadan iki yana açılır. */
  @keyframes hs-rule-in {
    from {
      opacity: 0;
      transform: scaleX(0);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }

  /*
   * Dil düğmesi "yanarak" çıkar: belirirken bir an vurgu rengiyle dolar,
   * sonra normal durumuna döner. `background-color` düzen hesabı gerektirmez,
   * dört küçük düğmede maliyeti yok denecek kadar az.
   */
  @keyframes hs-lang-in {
    0% {
      opacity: 0;
      transform: translateY(8px);
      pointer-events: none;
      background-color: transparent;
      border-color: var(--color-divider);
    }
    55% {
      opacity: 1;
      transform: none;
      background-color: color-mix(in srgb, var(--color-accent) 22%, transparent);
      border-color: var(--color-accent);
    }
    100% {
      opacity: 1;
      transform: none;
    }
  }

  /* --- Giriş ekranı koreografisi ---------------------------------------- */

  .js .e-screen {
    --intro: 1;
  }

  /* Dil değiştirince: aynı dizi, üçte bir sürede. */
  .js .e-screen.is-quick {
    --intro: 0.3;
  }

  /* Aynı oturumda tekrar görülüyorsa ya da misafir ekrana dokunduysa. */
  .js .e-screen.is-instant {
    --intro: 0;
  }

  .js .e-band {
    animation: hs-hero-in calc(900ms * max(var(--intro), 0.18)) var(--ease-out) backwards;
  }

  .js .e-scrim {
    animation: hs-fade calc(900ms * max(var(--intro), 0.18)) var(--ease-out) backwards;
  }

  .js .e-logo,
  .js .e-restaurantName {
    animation: hs-logo-in 520ms var(--ease-out) backwards;
    animation-delay: calc(350ms * var(--intro));
  }

  .js .e-rule {
    animation: hs-rule-in 380ms var(--ease-out) backwards;
    animation-delay: calc(680ms * var(--intro));
  }

  .js .e-welcome {
    animation: hs-rise-gated 440ms var(--ease-out) backwards;
    animation-delay: calc(780ms * var(--intro));
  }

  .js .e-sub {
    animation: hs-rise-gated 440ms var(--ease-out) backwards;
    animation-delay: calc(900ms * var(--intro));
  }

  /* Dört düğme sırayla, 110 ms arayla. */
  .js .e-langGrid > * {
    animation: hs-lang-in 420ms var(--ease-out) backwards;
  }

  .js .e-langGrid > *:nth-child(1) { animation-delay: calc(1050ms * var(--intro)); }
  .js .e-langGrid > *:nth-child(2) { animation-delay: calc(1160ms * var(--intro)); }
  .js .e-langGrid > *:nth-child(3) { animation-delay: calc(1270ms * var(--intro)); }
  .js .e-langGrid > *:nth-child(4) { animation-delay: calc(1380ms * var(--intro)); }

  .js .e-enter {
    animation: hs-rise-gated 480ms var(--ease-out) backwards;
    animation-delay: calc(1560ms * var(--intro));
  }

  .js .e-legal {
    animation: hs-fade 400ms var(--ease-out) backwards;
    animation-delay: calc(1740ms * var(--intro));
  }

  /* --- Giriş ekranından çıkış -------------------------------------------
   *
   * "Kapıdan gir" → yazılar geldikleri sıranın TERSİNE çekilir, en son arka
   * plan söner ve geriye düz kâğıt zemin kalır. Menü o zemin üzerine kurulur.
   */

  @keyframes hs-sink {
    to {
      opacity: 0;
      transform: translateY(-14px);
    }
  }

  .js .e-screen.is-exiting .e-legal { animation: hs-sink 260ms var(--ease-in) forwards; }
  .js .e-screen.is-exiting .e-enter { animation: hs-sink 280ms var(--ease-in) 60ms forwards; }
  .js .e-screen.is-exiting .e-langGrid > * { animation: hs-sink 280ms var(--ease-in) forwards; }
  .js .e-screen.is-exiting .e-langGrid > *:nth-child(1) { animation-delay: 120ms; }
  .js .e-screen.is-exiting .e-langGrid > *:nth-child(2) { animation-delay: 160ms; }
  .js .e-screen.is-exiting .e-langGrid > *:nth-child(3) { animation-delay: 200ms; }
  .js .e-screen.is-exiting .e-langGrid > *:nth-child(4) { animation-delay: 240ms; }
  .js .e-screen.is-exiting .e-sub { animation: hs-sink 260ms var(--ease-in) 260ms forwards; }
  .js .e-screen.is-exiting .e-welcome { animation: hs-sink 260ms var(--ease-in) 320ms forwards; }
  .js .e-screen.is-exiting .e-rule { animation: hs-sink 220ms var(--ease-in) 360ms forwards; }
  .js .e-screen.is-exiting .e-logo,
  .js .e-screen.is-exiting .e-restaurantName { animation: hs-sink 300ms var(--ease-in) 400ms forwards; }

  .js .e-screen.is-exiting .e-band,
  .js .e-screen.is-exiting .e-scrim {
    animation: hs-sink 420ms var(--ease-in) 300ms forwards;
  }

  /* Dil değişiminde arka plan sabit kalır, yalnızca yazılar tazelenir. */
  .js .e-screen.is-switching .e-band,
  .js .e-screen.is-switching .e-scrim {
    animation: none;
  }

  /* --- Menü kuruluşu -----------------------------------------------------
   *
   * Boş kâğıttan menü. CSS animasyonu — JavaScript ile gizleme YOK: bir
   * aksilikte menünün boş kalması, aç bir misafir için en kötü sonuç.
   * Animasyon her hâlükârda görünür durumda biter.
   */

  .js .m-header {
    animation: hs-rise 460ms var(--ease-out) backwards;
    animation-delay: 80ms;
  }

  .js .m-categoryBar {
    animation: hs-rise 460ms var(--ease-out) backwards;
    animation-delay: 220ms;
  }

  /*
   * İlk ekrandaki bölüm başlığı ve satırlar sırayla yerleşir.
   *
   * Sayım `nth-child` ile yapılır, `nth-of-type` ile DEĞİL: bölüm başlığı da
   * satırlar da <div>, dolayısıyla `nth-of-type` başlığı da sayıyor ve tüm
   * numaralar bir kayıyordu — dördüncü satır hiç gecikme almayıp diğerlerinden
   * önce beliriyordu.
   */
  .js .m-sections > .m-section:nth-of-type(1) > *,
  .js .m-sections > .m-section:nth-of-type(2) > .m-sectionHeader {
    animation: hs-rise 440ms var(--ease-out) backwards;
  }

  .js .m-sections > .m-section:nth-of-type(1) > *:nth-child(1) { animation-delay: 360ms; }
  .js .m-sections > .m-section:nth-of-type(1) > *:nth-child(2) { animation-delay: 470ms; }
  .js .m-sections > .m-section:nth-of-type(1) > *:nth-child(3) { animation-delay: 570ms; }
  .js .m-sections > .m-section:nth-of-type(1) > *:nth-child(4) { animation-delay: 660ms; }
  /* Uzun bir ilk kategoride kalanlar hep birlikte gelsin; dizi uzamasın. */
  .js .m-sections > .m-section:nth-of-type(1) > *:nth-child(n + 5) { animation-delay: 740ms; }
  .js .m-sections > .m-section:nth-of-type(2) > .m-sectionHeader { animation-delay: 820ms; }

  /*
   * Kaydırınca beliren satırlar. Gizleme sınıfını JavaScript koyar ve YALNIZCA
   * ilk ekranın altındakilere koyar; görünen içerik hiçbir zaman gizlenmez.
   */
  .will-reveal {
    opacity: 0;
    transform: translateY(12px);
    /* Kuruluş animasyonu ile çakışmasın. */
    animation: none !important;
  }

  .will-reveal.is-in {
    opacity: 1;
    transform: none;
    transition:
      opacity 320ms var(--ease-out),
      transform 320ms var(--ease-out);
  }

  /* --- Sayfadan ayrılırken ------------------------------------------------
     Yalnızca opacity: body'ye transform vermek `position: fixed` öğeler için
     kapsayıcı blok yaratır ve açık bir pencereyi yerinden oynatır. */

  .js.is-leaving body {
    opacity: 0;
    transition: opacity 200ms var(--ease-in);
  }

  /* Giriş ekranından çıkarken sönme kendi koreografisiyle yapılıyor. */
  .js.is-leaving-entry body {
    opacity: 1;
    transition: none;
  }
}

/* --- Dokunma geri bildirimi ------------------------------------------------
   Hareket tercihinden bağımsız: parmağın altındaki şeyin tepki vermesi
   süsleme değil, dokunmanın kaydedildiğinin tek işareti. */

.btn,
.m-tab,
.d-name,
.m-panelRow {
  transition:
    background-color 140ms var(--ease-out),
    color 160ms var(--ease-out),
    border-color 160ms var(--ease-out),
    transform 120ms var(--ease-out);
}

.btn:active {
  transform: scale(0.975);
}

.d-row:active .d-name {
  color: var(--color-accent-700);
}

/* Alerjen balonu: dokunulan yerden açılıyormuş gibi. */
@media (prefers-reduced-motion: no-preference) {
  .d-allergenTip {
    animation: hs-rise 160ms var(--ease-out);
  }
}
