/* ==========================================================================
   شاي بو حمد · Shai Bu Hamad

   Colours were measured from the brand assets, not estimated — tools/palette.py
   read the real pixels of the logo and the profile. See docs/brand.md.

   Three rules carried over from the al-zaman-al-jameel build, because they were
   learned the hard way there:

   1. No two adjacent sections get the same surface. A page of identical
      panels reads as a template no matter how good each panel is.
   2. A pattern tiled across a whole section reads as bathroom tile. Patterns
      belong in a dado across the lower third, with a rail closing it, and a
      smooth surface above for text to sit on.
   3. `background-attachment: fixed` is banned — it forces a full repaint every
      frame and makes scrolling stutter. Parallax goes through transform.

   Written RTL-first with logical properties so the Arabic layout is the source
   of truth and English is a direction flip, not a rewrite.
   ========================================================================== */

/* --------------------------------------------------------------- 1. tokens */
:root {
  --brown:        #654321;
  --brown-deep:   #422C13;
  --brown-dark:   #2A1C0C;
  --brown-soft:   #8B6739;
  --sand:         #D6CCB8;
  --sand-light:   #E6DFD2;
  --sand-dark:    #C3B69D;
  --ink:          #2E3739;
  --cream:        #FBF8F3;
  --accent:       #A33521;

  --bg:       var(--sand);
  --fg:       var(--ink);
  --fg-muted: #5C5247;
  --rule:     var(--sand-dark);

  /* Alexandria is the closest freely licensed match to the brand's URW
     Geometric Arabic: geometric, monoline, low contrast, and it carries the
     very light weights the identity depends on. Loaded from Google Fonts,
     which is the one third party this site allows — see docs/security.md for
     why that trade was made. */
  --font: "Alexandria", "URW Geometric Arabic", "Noto Kufi Arabic",
          "Dubai", Tahoma, system-ui, sans-serif;

  --t-display: clamp(2.6rem, 9vw, 7.5rem);   /* full-viewport type moments */
  --t-hero:  clamp(2.2rem, 6.5vw, 5.2rem);
  --t-h1:    clamp(1.9rem, 4.4vw, 3.4rem);
  --t-h2:    clamp(1.5rem, 3vw,   2.2rem);
  --t-h3:    clamp(1.1rem, 1.8vw, 1.4rem);
  --t-body:  clamp(1rem,   1.05vw, 1.1rem);
  --t-small: .82rem;

  --s-1: .25rem; --s-2: .5rem;  --s-3: .75rem; --s-4: 1rem;
  --s-5: 1.5rem; --s-6: 2rem;   --s-7: 3rem;   --s-8: 4rem;
  --s-9: 6rem;   --s-10: 9rem;

  --measure: 58ch;
  --page:    min(1320px, 100% - 2.5rem);

  --ease:  cubic-bezier(.22, .61, .36, 1);
  --dur:   .8s;
  --quick: .3s;

  /* The dome-topped frame that used to live here (--arch: 50% 50% 0 0 /
     30% 30% 0 0) is gone. It was a generic "Arabian arch" applied to photo
     frames, and the owner rejected it outright. Nothing in either branch is
     shaped like that: the real geometry is circles (the backlit mirrors),
     the pointed ogee of the perforated ledge light, and plain rectangles.
     Photo frames are now square-edged and the shaped forms come from the
     building itself. */
  --edge: 3px;
}

/* ------------------------------------------------------------ 2. baseline */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-block-start: 5.5rem;   /* the header is fixed */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: var(--t-body);
  font-weight: 300;
  line-height: 1.95;              /* Arabic needs more leading than Latin */
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 200;               /* the identity is a light monoline */
  line-height: 1.3;
  letter-spacing: -.01em;
}

p { margin: 0 0 var(--s-4); max-width: var(--measure); }
a { color: inherit; text-decoration: none; }
/* `height: auto` is load-bearing, not boilerplate.

   Every <img> on this page carries width and height attributes, which is
   right — they reserve the box and stop the layout jumping as photographs
   arrive. But those attributes also act as presentational hints, so an image
   whose CSS sets a width and no height keeps the attribute's pixel height and
   is squashed by whatever the two numbers disagree by.

   That is not hypothetical: .intro__logo sets `width: min(74vw, 460px)` and
   no height, so the curtain logo rendered 289x355 on a phone instead of
   289x85 — a 1200x355 wordmark crushed to a ratio of 0.81. The owner saw it
   and reported it. Fixing it here rather than only on that one rule means the
   next image styled by width alone cannot repeat it. */
img, svg, video { display: block; max-width: 100%; height: auto; }
ul { margin: 0; padding: 0; list-style: none; }
:focus-visible { outline: 2px solid var(--brown-soft); outline-offset: 4px; }

.lat { letter-spacing: .24em; font-weight: 200; }

.skip-link {
  position: absolute; inset-block-start: -100%;
  inset-inline-start: var(--s-4); z-index: 100;
  padding: var(--s-3) var(--s-5); background: var(--brown); color: var(--sand);
}
.skip-link:focus { inset-block-start: var(--s-4); }

/* A single film-grain plate over the whole page. It costs one composited
   layer and is what keeps large flat sand areas from looking like plastic. */
.grain {
  position: fixed; inset: 0; z-index: 200; pointer-events: none;
  opacity: .32; mix-blend-mode: multiply;
  background-image: url("../img/grain.svg");
  background-size: 180px;
}

/* -------------------------------------------------------------- 3. layout */
.shell { width: var(--page); margin-inline: auto; }

.sec {
  position: relative;
  padding-block: var(--s-9);
  scroll-margin-block-start: 4.5rem;
  overflow: hidden;
}

/* Surface variants. The page alternates between them — never two of the same
   kind back to back. */
.sec--sand   { background: var(--sand); }
.sec--cream  { background: var(--cream); }
.sec--brown  { background: var(--brown); color: var(--sand); }
.sec--darkest{ background: var(--brown-dark); color: var(--sand); }
.sec--brown h2, .sec--brown h3, .sec--darkest h2, .sec--darkest h3 { color: var(--cream); }
.sec--brown p, .sec--darkest p { color: color-mix(in srgb, var(--sand) 84%, transparent); }

.eyebrow {
  display: flex; align-items: center; gap: var(--s-3);
  margin-block-end: var(--s-5);
  font-size: var(--t-small); font-weight: 300;
  letter-spacing: .2em; color: var(--brown-soft);
}
.sec--brown .eyebrow, .sec--darkest .eyebrow { color: var(--sand-dark); }
.eyebrow::before {
  content: ""; flex: none; width: .85em; height: .85em;
  background: currentColor;
  -webkit-mask: url("../img/star.svg") center/contain no-repeat;
          mask: url("../img/star.svg") center/contain no-repeat;
}

.grid { display: grid; gap: var(--s-6); }
@media (min-width: 900px) {
  .grid--2     { grid-template-columns: repeat(2, 1fr); }
  .grid--3     { grid-template-columns: repeat(3, 1fr); }
  .grid--split { grid-template-columns: 1fr 1fr; gap: var(--s-8); align-items: center; }
  .grid--aside { grid-template-columns: 1.15fr .85fr; gap: var(--s-8); align-items: center; }
}

.statement { font-size: var(--t-h1); max-width: 26ch; }
.lede { font-size: clamp(1.05rem, 1.5vw, 1.25rem); color: var(--fg-muted); }
.sec--brown .lede, .sec--darkest .lede { color: color-mix(in srgb, var(--sand) 90%, transparent); }

/* ------------------------------------------------- 4. pattern as a dado */

/* The sadu rail, placed only across the lower third of a panel. Tiling a
   pattern over a whole panel was the mistake that got an earlier build called
   tile. `background-position-x: 50%` matters: with a fixed tile width, `0`
   crops the two edges unevenly and the panel looks off-centre. */
.dado {
  position: absolute; inset-block-end: 0; inset-inline: 0;
  height: 34%; pointer-events: none;
}
/* The tiling star field that used to fill this (lattice.svg) is gone with the
   arches. It was authored to match a panel in the profile PDF, which is to
   say it was invented — and the owner's reaction to invented ornament was the
   same both times. What is left is the one band that is actually in the
   building: the sadu rail.

   It is also much taller than before. At 40px the repeat rendered about 51px
   wide, which turned the comb-and-diamond motif into grey mush; the band read
   as a smudge rather than as a textile. At ~70px the motif is legible, which
   is the only reason to put a pattern on a page at all. */
/* The drawn SVG band is gone too. Redrawing it stripe-for-stripe off the real
   cloth still did not satisfy, and the reason is not the drawing — it is that
   a flat vector of a woven textile has none of the thread, slub and shadow
   that make the real thing read as cloth. So there is one sadu source in the
   project now, and it is the photograph of the owner's own piece.

   Sized the same way as .sadu: `auto 340%` makes each pass about 340px wide,
   big enough for the bead rows and black combs to be legible. `auto 100%`
   would squeeze a pass into ~100px and turn the motif back into grey mush,
   which is what the 40px version did. */
.dado::after {
  content: ""; position: absolute;
  inset-block-end: 0; inset-inline: 0;
  height: clamp(54px, 7vw, 78px);
  background-image: url("../../media/photos/sadu-textile.jpeg");
  background-size: auto 340%;
  background-position: 50% 50%;
  background-repeat: repeat-x;
  box-shadow:
    inset 0 1px 0 rgb(23 20 15 / .9),
    inset 0 -1px 0 rgb(23 20 15 / .9);
}
.dado--quiet::after { display: none; }

/* A lone star, used as a large quiet watermark */
.mark-star {
  position: absolute; inset-block-start: -4%; inset-inline-start: -6%;
  width: min(46vw, 460px); aspect-ratio: 1; pointer-events: none;
  background: var(--brown-soft); opacity: .07;
  -webkit-mask: url("../img/star.svg") center/contain no-repeat;
          mask: url("../img/star.svg") center/contain no-repeat;
}

/* -------------------------------------------------------------- 5. header */
.header {
  position: fixed; inset-block-start: 0; inset-inline: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5);
  padding: var(--s-5) max(var(--s-5), calc(50vw - var(--page) / 2));
  transition: padding var(--quick) var(--ease), background var(--quick) var(--ease),
              box-shadow var(--quick) var(--ease);
}
/* Two real files, swapped — not one file pushed through a CSS filter.
   `brightness(0) invert(1)` mangles the antialiased edges of a thin monoline
   mark, and both files are tiny and cached anyway.
   The header uses the Arabic-only variant: the full lockup's hairline Latin
   row stops being legible below roughly 240px. */
.header__logo img {
  height: clamp(22px, 2.6vw, 30px); width: auto;
  transition: height var(--quick) var(--ease);
}
.header__logo .on-dark  { display: block; }
.header__logo .on-light { display: none; }
.header.is-stuck .header__logo .on-dark  { display: none; }
.header.is-stuck .header__logo .on-light { display: block; }
.header.is-stuck {
  padding-block: var(--s-3);
  background: color-mix(in srgb, var(--sand) 94%, transparent);
  backdrop-filter: blur(12px);
  box-shadow: 0 1px 0 var(--rule);
}
.header.is-stuck .header__logo img { height: 22px; }

.nav { display: none; gap: var(--s-6); font-size: var(--t-small); letter-spacing: .08em; }
@media (min-width: 980px) { .nav { display: flex; } }
.nav a { position: relative; padding-block: var(--s-1); color: var(--cream); transition: color var(--quick); }
.header.is-stuck .nav a { color: var(--fg); }
.nav a::after {
  content: ""; position: absolute; inset-block-end: 0; inset-inline-start: 0;
  width: 100%; height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: inline-start;
  transition: transform var(--quick) var(--ease);
}
.nav a:hover::after, .nav a[aria-current="true"]::after { transform: scaleX(1); }

/* Scroll progress as tea filling a glass. transform-origin: inline-start
   handles RTL on its own — no sign flipping, unlike a translateX indicator. */
.pour {
  position: fixed; inset-block-start: 0; inset-inline: 0; height: 2px; z-index: 60;
  background: var(--brown-soft);
  transform: scaleX(var(--progress, 0)); transform-origin: inline-start;
  transition: transform .1s linear;
}

/* ---------------------------------------------------------------- 6. hero */
.hero {
  position: relative; min-height: 100svh;
  display: grid; align-items: end;
  padding-block: var(--s-10) var(--s-8);
  overflow: hidden; isolation: isolate;
}
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img {
  width: 100%; height: 100%; object-fit: cover;
  /* Framed low on purpose: the venue's own illuminated sign sits near the top
     of this photograph, and letting it share the frame with the overlaid
     wordmark put two versions of the logo on one screen. */
  object-position: 50% 62%;
  /* a very slow push-in, so the first screen is never completely still */
  animation: kenburns 26s var(--ease) infinite alternate;
}
@keyframes kenburns {
  from { transform: scale(1.04); }
  to   { transform: scale(1.14); }
}
/* Two overlays, not one: a warm wash to pull the photo into the palette, and
   a bottom-weighted scrim so the text has contrast wherever the photo is
   bright. A single flat overlay either kills the photo or fails the text. */
.hero__media::after {
  content: ""; position: absolute; inset: 0;
  background:
    /* bottom scrim: carries the headline */
    linear-gradient(to top, rgb(26 17 7 / .94) 0%, rgb(26 17 7 / .62) 40%, rgb(26 17 7 / .18) 72%),
    /* top scrim: carries the nav, and pushes the photo's own signage back */
    linear-gradient(to bottom, rgb(26 17 7 / .55), transparent 26%),
    /* warm wash: pulls the photograph into the brand palette */
    linear-gradient(rgb(101 67 33 / .36), rgb(101 67 33 / .36));
}

.hero__inner { position: relative; width: var(--page); margin-inline: auto; }

/* There is deliberately no wordmark in the hero any more. It was being shown
   at a size where the monoline strokes collapse, and it was competing with
   the venue's own illuminated sign inside the photograph. The mark now gets
   the intro curtain to itself, at a size that flatters it. */

.hero h1 {
  font-size: var(--t-hero); font-weight: 100;
  color: var(--cream); max-width: 18ch;
  margin-block-end: var(--s-5);
  text-wrap: balance;
}
.hero p { color: color-mix(in srgb, var(--cream) 88%, transparent); max-width: 42ch; }

/* On a phone the stack of mark + headline + line + meta was taller than the
   viewport, so the branch names fell below the fold. Everything tightens
   rather than anything being dropped. */
@media (max-width: 640px) {
  .hero { padding-block: var(--s-8) var(--s-6); }
  .hero h1 { font-size: clamp(1.85rem, 7.6vw, 2.5rem); margin-block-end: var(--s-4); }
  .hero p { font-size: .98rem; }
  .hero__meta { margin-block-start: var(--s-5); gap: var(--s-2) var(--s-4); font-size: .76rem; }
  .hero__scroll { display: none; }
}

.hero__meta {
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-6);
  margin-block-start: var(--s-7);
  font-size: var(--t-small); letter-spacing: .18em;
  color: color-mix(in srgb, var(--sand) 80%, transparent);
}
.hero__meta li { display: flex; align-items: center; gap: var(--s-3); }
.hero__meta li + li::before {
  content: ""; width: .5em; height: .5em; background: var(--brown-soft);
  -webkit-mask: url("../img/star.svg") center/contain no-repeat;
          mask: url("../img/star.svg") center/contain no-repeat;
}

/* Dropped on wide screens, where the pearl strand appears. Both sit in the
   inline-end gutter — the LEFT gutter, since the page is RTL — and they were
   measured overlapping each other at x≈13 and x≈28. The strand says the same
   thing better (how far down you are, not merely that down exists), so the
   word gives way to it rather than the two being nudged apart. */
@media (min-width: 1100px) {
  .hero__scroll { display: none; }
}

/* PHYSICAL insets here, deliberately, and this is the one place in the file
   that breaks the logical-properties rule.

   `writing-mode: vertical-rl` rotates this element's own axes, and logical
   insets resolve against the element's own writing mode — not the page's. In
   a vertical-rl box inside dir="rtl", the block axis runs horizontally and
   the inline axis runs bottom-to-top, so `inset-block-end` resolves to LEFT
   and `inset-inline-end` resolves to TOP. The cue was measured at top: 0
   because of exactly that. Physical left/bottom say what is meant.

   Mirrored by hand for LTR below, since physical properties cannot do it. */
.hero__scroll {
  position: absolute; bottom: var(--s-5); left: 0;
  font-size: var(--t-small); letter-spacing: .2em;
  color: color-mix(in srgb, var(--sand) 65%, transparent);
  writing-mode: vertical-rl;
}
[dir="ltr"] .hero__scroll { left: auto; right: 0; }

/* --------------------------------------------------------------- 7. media */
.arch { border-radius: var(--edge); overflow: hidden; }   /* kept as a plain clipped frame; the dome shape is gone */

.figure { position: relative; }
.figure img { width: 100%; height: 100%; object-fit: cover; }
.figure--tall  { aspect-ratio: 3 / 4; }
.figure--portrait { aspect-ratio: 4 / 5; }
.figure--wide  { aspect-ratio: 16 / 10; }
.figure__cap {
  margin-block-start: var(--s-3); font-size: var(--t-small);
  letter-spacing: .08em; color: var(--fg-muted);
}

/* Full-bleed band with transform parallax (never background-attachment) */
.band { position: relative; min-height: 76svh; display: grid; place-items: center; overflow: hidden; }
.band__media { position: absolute; inset: -12% 0; z-index: -2; will-change: transform; }
.band__media img { width: 100%; height: 100%; object-fit: cover; }
.band__media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(rgb(26 17 7 / .72), rgb(26 17 7 / .82));
}
.band__inner { position: relative; width: var(--page); text-align: center; }
.band h2 { color: var(--cream); font-size: var(--t-h1); margin-inline: auto; max-width: 24ch; }
.band p { color: color-mix(in srgb, var(--cream) 84%, transparent); margin-inline: auto; }

/* Asymmetric gallery — equal tiles would read as a stock grid */
.gallery { display: grid; gap: var(--s-4); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 900px) {
  .gallery { grid-template-columns: repeat(4, 1fr); grid-auto-rows: 180px; }
  .gallery > :nth-child(1) { grid-column: span 2; grid-row: span 2; }
  .gallery > :nth-child(2) { grid-column: span 2; grid-row: span 1; }
  .gallery > :nth-child(3) { grid-column: span 1; grid-row: span 1; }
  .gallery > :nth-child(4) { grid-column: span 1; grid-row: span 1; }
}
.gallery .figure { height: 100%; border-radius: 2px; overflow: hidden; }
.gallery img { transition: transform 1.2s var(--ease); }
.gallery .figure:hover img { transform: scale(1.06); }

/* The clip is 480x848 portrait, so it is framed vertically rather than
   stretched across a desktop hero where it would look soft. */
.reel {
  width: min(100%, 300px); aspect-ratio: 480/848; margin-inline: auto;
  border-radius: var(--edge); overflow: hidden; background: var(--brown-dark);
  box-shadow: 0 34px 70px -34px rgb(26 17 7 / .7);
}
.reel video { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------- 8. cards */
.card {
  position: relative;
  background: var(--cream); border: 1px solid var(--rule); border-radius: 2px;
  padding: var(--s-6);
  display: flex; flex-direction: column; gap: var(--s-2);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.sec--brown .card, .sec--darkest .card {
  background: color-mix(in srgb, var(--cream) 7%, transparent);
  border-color: color-mix(in srgb, var(--sand) 22%, transparent);
}
.card:hover { transform: translateY(-5px); box-shadow: 0 22px 46px -28px rgb(42 28 12 / .5); }
.card h3 { font-size: var(--t-h3); }
.card__en { font-size: var(--t-small); letter-spacing: .2em; color: var(--brown-soft); }
.card__price { margin-block-start: auto; padding-block-start: var(--s-3); color: var(--brown); letter-spacing: .06em; }
.sec--brown .card__price { color: var(--sand); }

.filters { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-block-end: var(--s-6); }
.filter {
  font: inherit; font-size: var(--t-small);
  padding: var(--s-2) var(--s-5);
  background: transparent; color: var(--fg-muted);
  border: 1px solid var(--rule); border-radius: 999px; cursor: pointer;
  transition: all var(--quick) var(--ease);
}
.filter:hover { border-color: var(--brown-soft); color: var(--brown); }
.filter[aria-pressed="true"] { background: var(--brown); border-color: var(--brown); color: var(--cream); }

.branch { overflow: hidden; }
.branch__media { aspect-ratio: 4/3; }
.branch__media img { width: 100%; height: 100%; object-fit: cover; }
.branch__body { padding-block-start: var(--s-5); }
.branch h3 { font-size: var(--t-h2); }
.branch dl { margin: var(--s-4) 0 0; font-size: var(--t-small); }
.branch dt { color: var(--brown-soft); letter-spacing: .12em; margin-block-start: var(--s-3); }
.branch dd { margin: 0; color: var(--fg-muted); line-height: 1.9; }
/* Friday is a separate line under the weekday range rather than a second
   <dt>: it is the same fact — when the branch is open — so it belongs to the
   same term. */
.branch__note { color: var(--brown-soft); }
/* The number is the one thing in this card a visitor acts on, so it is sized
   up and underlined on approach, and padded out to clear the 44px minimum tap
   height. At var(--s-1) of block padding it measured 39px — close enough to
   look fine and not close enough to be reliable under a thumb, so it is
   var(--s-2) and measured again at 47px. A phone number that is awkward to
   hit is a phone number that does not get dialled. */
.branch__tel {
  display: inline-block;
  margin-block-start: var(--s-1);
  padding-block: var(--s-2);
  font-size: var(--t-body);
  letter-spacing: .08em;
  color: var(--brown);
  border-block-end: 1px solid transparent;
  transition: border-color var(--quick) var(--ease);
}
.branch__tel:hover,
.branch__tel:focus-visible { border-block-end-color: currentColor; }

/* The two actions on a branch card: message it, or drive to it.
   Wrapping gap, so on a narrow phone they stack instead of being squeezed
   into one line of unhittable targets. */
.branch__actions {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s-3) var(--s-5);
  margin-block-start: var(--s-4);
}

/* WhatsApp, in the brand's brown rather than WhatsApp's green.
   The green is instantly recognisable and that is exactly the problem: on a
   page built out of sand, brown and cream it reads as something pasted on
   from another site. The mark itself is recognisable enough to carry the
   meaning without the colour, and the label says so in words as well. */
.branch__wa {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-5);
  border: 1px solid color-mix(in srgb, var(--brown) 40%, transparent);
  border-radius: 999px;
  font-size: var(--t-small); letter-spacing: .08em;
  color: var(--brown);
  transition: background var(--quick) var(--ease),
              border-color var(--quick) var(--ease);
}
.branch__wa svg { flex: none; }
.branch__wa:hover,
.branch__wa:focus-visible {
  background: color-mix(in srgb, var(--brown) 8%, transparent);
  border-color: var(--brown);
}

/* Directions. Secondary to the phone number, so it is a quiet link with an
   icon rather than a second button competing with it. */
.branch__dir {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding-block: var(--s-2);
  font-size: var(--t-small); letter-spacing: .08em;
  color: var(--brown-soft);
  border-block-end: 1px solid transparent;
  transition: color var(--quick) var(--ease),
              border-color var(--quick) var(--ease);
}
.branch__dir svg { flex: none; }
[dir="rtl"] .branch__dir svg { transform: scaleX(-1); }
.branch__dir:hover,
.branch__dir:focus-visible {
  color: var(--brown);
  border-block-end-color: currentColor;
}

/* ------------------------------------------------------------- 10c. the FAQ
   Native <details>/<summary>: it opens with no JavaScript, it is keyboard
   operable and announced correctly by screen readers without a single aria
   attribute, and find-in-page can reach inside closed sections in modern
   browsers. A hand-built accordion would have cost script and markup to end
   up worse. */
.faq {
  margin-block-start: var(--s-6);
  border-block-start: 1px solid color-mix(in srgb, var(--brown) 18%, transparent);
}
/* Clear the pearl strand, exactly as .menu-live has to.
   The +/- marker is pushed to the inline end of each row by margin-inline-
   start: auto, which lands it around 23px from the viewport edge — inside the
   14-43px band .strand occupies from 1100px up. .strand is position: fixed
   and vertically centred, so it does not overlap any one row permanently; it
   overlaps whichever row is scrolled to the middle of the screen, which is a
   worse bug than a static collision because it only appears while moving.
   Second time this has come up, so the strand's footprint is now written
   down in both places. */
@media (min-width: 1100px) {
  .faq { padding-inline-end: var(--s-6); }
}
.faq__item {
  border-block-end: 1px solid color-mix(in srgb, var(--brown) 18%, transparent);
}
.faq__item > summary {
  /* The default disclosure triangle is removed in favour of the +/- drawn
     below, because the native marker sits on the wrong side in RTL in some
     engines and cannot be repositioned. */
  list-style: none;
  cursor: pointer;
  display: flex; align-items: baseline; gap: var(--s-4);
  padding-block: var(--s-5);
  font-size: var(--t-h3); font-weight: 300;
  transition: color var(--quick) var(--ease);
}
.faq__item > summary::-webkit-details-marker { display: none; }
.faq__item > summary:hover { color: var(--brown); }
.faq__item > summary::after {
  content: "+";
  margin-inline-start: auto;
  font-size: var(--t-h3); font-weight: 200;
  color: var(--brown-soft);
  transition: transform var(--quick) var(--ease);
}
.faq__item[open] > summary::after { content: "−"; }
.faq__a {
  padding-block-end: var(--s-5);
  color: var(--fg-muted);
  max-width: 68ch;
}
.faq__a p + p { margin-block-start: var(--s-3); }
.faq__a a { border-block-end: 1px solid currentColor; }

/* ---------------------------------------------------------------- 9. CTAs */
.btn {
  display: inline-flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-6);
  border: 1px solid currentColor; border-radius: 999px;
  font-size: var(--t-small); letter-spacing: .12em;
  transition: all var(--quick) var(--ease);
}
.btn--solid { background: var(--brown); border-color: var(--brown); color: var(--cream); }
.btn--solid:hover { background: var(--brown-deep); border-color: var(--brown-deep); }
.btn--light { color: var(--cream); }
.btn--light:hover { background: var(--cream); color: var(--brown); }

/* The language switch sits beside the "visit us" button and must not compete
   with it: same pill, no fill, slightly tighter. It is also the one control
   in the header that has to stay legible against both header states — the
   transparent one over the hero photograph and the solid one after scroll —
   so it borrows the header's own colour rather than setting its own. */
.lang-switch {
  padding-inline: var(--s-5);
  letter-spacing: .1em;
  color: inherit;
  border-color: color-mix(in srgb, currentColor 45%, transparent);
}
.lang-switch:hover,
.lang-switch:focus-visible {
  background: color-mix(in srgb, currentColor 12%, transparent);
  border-color: currentColor;
  color: inherit;
}
@media (max-width: 760px) {
  /* The header is already tight on a phone; the switch keeps its place and
     the "visit us" button is the one that goes, since the branches section
     it points at is reachable from the nav anyway. */
  .header .btn--solid:not(.lang-switch) { display: none; }
}

.social { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.social a {
  font-size: var(--t-small); letter-spacing: .16em;
  padding: var(--s-2) var(--s-5);
  border: 1px solid color-mix(in srgb, var(--sand) 38%, transparent);
  border-radius: 999px; transition: all var(--quick) var(--ease);
}
.social a:hover { background: var(--sand); color: var(--brown); }

/* ------------------------------------------------------------- 10. footer */
.foot { background: var(--brown-dark); color: var(--sand); padding-block: var(--s-8) var(--s-6); position: relative; }
.foot a:hover { color: var(--cream); }
.foot__grid { display: grid; gap: var(--s-7); }
@media (min-width: 780px) { .foot__grid { grid-template-columns: 1.5fr 1fr 1fr; } }
/* The footer column titles are h3, not h4. They used to be h4 directly after
   an h2, and a document that jumps h2 -> h4 breaks heading navigation for
   anyone moving through the page with a screen reader — the level implies a
   parent heading that is not there. The size is set here, so demoting the tag
   changed nothing visually. */
.foot h3 { font-size: var(--t-small); letter-spacing: .2em; margin-block-end: var(--s-4); color: var(--sand-dark); }
.foot li, .foot p { font-size: var(--t-small); color: color-mix(in srgb, var(--sand) 76%, transparent); margin-block-end: var(--s-2); }
.foot__legal {
  margin-block-start: var(--s-7); padding-block-start: var(--s-5);
  border-block-start: 1px solid color-mix(in srgb, var(--sand) 16%, transparent);
  font-size: var(--t-small); color: color-mix(in srgb, var(--sand) 56%, transparent);
  display: flex; flex-wrap: wrap; gap: var(--s-4); justify-content: space-between;
}

/* Loud on purpose: placeholder data must never be mistaken for real data. */
.todo {
  display: inline-block; padding: 0 .5em; border-radius: 2px;
  background: #FFF3C4; color: #7A4B00; font-size: var(--t-small);
  border: 1px dashed #C89B2E;
}

/* ------------------------------------------- 10b. the link to the real menu
   The prices live on the owner's QR platform, so the page's job here is to
   hand the visitor over cleanly rather than to half-repeat a menu it cannot
   keep in sync. Generated by tools/build_menu.py whenever data/menu.json has
   a menuUrl — it is not hand-written in the HTML.

   Set apart from the cards above it with a rule and a tint rather than a
   fourth card, because a visitor scanning a grid skips anything shaped like
   the grid. This has to read as the end of the section, not as one more
   item in it. */
.menu-live {
  display: flex; flex-wrap: wrap;
  align-items: center; justify-content: space-between;
  gap: var(--s-5);
  margin-block-start: var(--s-7);
  padding-block-start: var(--s-6);
  border-block-start: 1px solid color-mix(in srgb, var(--brown) 20%, transparent);
}
/* Keep clear of the pearl strand.

   .strand is position: fixed at inset-inline-end: var(--s-5) and appears from
   1100px up. Its pearls are 9px wide and its blurred backing extends 10px
   past them, so it occupies roughly 14-43px in from the inline-end edge —
   while .shell leaves only about 20px of gutter at that width. Anything
   pushed flush to the inline-end edge therefore ends up underneath it, and
   `justify-content: space-between` pushes this button exactly there.

   Caught by hit-testing the button's three edge points with
   elementFromPoint: the inline-end edge returned .strand, not the button. It
   looked like a decorative dot sitting on top of a call to action, and it
   also stole a sliver of the tap target. */
@media (min-width: 1100px) {
  .menu-live { padding-inline-end: var(--s-6); }
}
.menu-live h3 { font-size: var(--t-h3); font-weight: 300; }
.menu-live p {
  margin-block-start: var(--s-2);
  color: var(--fg-muted); font-size: var(--t-small);
}
/* The arrow leans out along the inline axis, so in RTL it has to lean the
   other way or it points back into the sentence it came from. It is an inline
   SVG, not the "↗" character — that glyph is absent from some font stacks and
   renders as an empty box. */
.menu-live__arrow {
  display: inline-block; flex: none;
  transition: transform var(--quick) var(--ease);
}
.menu-live__cta:hover .menu-live__arrow { transform: translate(-2px, -2px); }
/* The glyph is drawn pointing up and to the right. "Outward" is up-right in
   English and up-left in Arabic, so the flip is scoped to the direction
   rather than baked into the rule — /en/ reuses this stylesheet verbatim and
   an unscoped scaleX would have it pointing back into its own sentence. */
[dir="rtl"] .menu-live__arrow { transform: scaleX(-1); }
[dir="rtl"] .menu-live__cta:hover .menu-live__arrow { transform: scaleX(-1) translate(2px, -2px); }
@media (max-width: 560px) {
  /* Full width on a phone: a pill floated beside a two-line heading ends up
     narrower than the thumb that has to hit it. */
  .menu-live__cta { width: 100%; justify-content: center; }
}

/* ------------------------------------------------ 11. motion / reveal */
[data-reveal] {
  opacity: 0; transform: translateY(26px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
[data-reveal].is-visible { opacity: 1; transform: none; }
[data-reveal][data-delay="1"] { transition-delay: .09s; }
[data-reveal][data-delay="2"] { transition-delay: .18s; }
[data-reveal][data-delay="3"] { transition-delay: .27s; }

/* The mouse-tilt rule (.tilt) is gone with its JavaScript. It only ever ran
   behind `(hover: hover) and (pointer: fine)`, so on a phone the page had no
   motion at all beyond these fades. Scroll-driven motion in cinematic.css
   replaces it and runs everywhere. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001s !important; transition-duration: .001s !important; }
  [data-reveal] { opacity: 1; transform: none; }
  .hero__media img { animation: none; transform: none; }
}
/* Content must survive with JavaScript switched off. */
.no-js [data-reveal] { opacity: 1; transform: none; }
.no-js .grain { display: none; }
