/* ==========================================================================
   Abyat Al Sharq — base.css
   Typography, layout primitives, section tones, ornaments, utilities and the motion states used by
   /js/motion.js. Tokens live in /css/critical.css (inlined in <head>).
   ========================================================================== */

/* ---------------------------------------------------------------- typography */
h1, h2, h3, h4, .display-1, .h1, .h2, .h3, .h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: var(--lh-display);
  letter-spacing: 0;
  text-wrap: balance;
}
:lang(en) :is(h1, h2, h3, h4, .display-1, .h1, .h2, .h3, .h4) { font-weight: 600; }
h4, .h4 { font-family: var(--font-sans); font-weight: 600; line-height: 1.5; }
.display-1 { font-size: var(--fs-display); line-height: calc(var(--lh-display) - .05); }
h1, .h1 { font-size: var(--fs-h1); }
h2, .h2 { font-size: var(--fs-h2); }
h3, .h3 { font-size: var(--fs-h3); }
h4, .h4 { font-size: var(--fs-h4); }
p, li, dd { text-wrap: pretty; }
strong, b { font-weight: 600; }
small, .small { font-size: var(--fs-small); }
.xs { font-size: var(--fs-xs); }
.lead { font-size: var(--fs-lead); line-height: 1.8; color: var(--ink-soft); }
:lang(en) .lead { line-height: 1.65; }
.muted { color: var(--muted); }
.text-gold { color: var(--accent-ink); }
.line { display: block; }
.measure { max-width: 62ch; }
.measure-narrow { max-width: 44ch; }
.balance { text-wrap: balance; }
.nowrap { white-space: nowrap; }
.num { font-variant-numeric: lining-nums tabular-nums; }
/* a Latin/number run inside Arabic text that must keep its own direction */
.ltr { direction: ltr; unicode-bidi: isolate; }
.tag-latin { font-family: var(--font-sans); font-size: .72em; letter-spacing: var(--tracking-caps); text-transform: uppercase; }

/* Long-form text (privacy policy, letters) */
.prose { font-size: var(--fs-body); color: var(--ink-soft); }
.prose > * + * { margin-block-start: 1.1em; }
.prose h2 { font-size: var(--fs-h3); color: var(--ink); margin-block-start: 2.2em; }
.prose h3 { font-size: var(--fs-h4); color: var(--ink); margin-block-start: 1.8em; font-family: var(--font-sans); font-weight: 600; }
.prose ul, .prose ol { padding-inline-start: 1.4em; }
.prose li + li { margin-block-start: .4em; }
.prose li::marker { color: var(--gold-600); }
.prose a { color: var(--accent-ink); }
.prose strong { color: var(--ink); }

/* ---------------------------------------------------------------- layout primitives */
.section { position: relative; padding-block: var(--section-y); }
.section--tight { padding-block: calc(var(--section-y) * .6); }
.section--flush-top { padding-top: 0; }
.section--flush-bottom { padding-bottom: 0; }
.section + .section.tone-same { padding-top: 0; }

.stack { display: flex; flex-direction: column; }
.stack > * + * { margin-block-start: var(--stack, var(--space-m)); }
.stack--2xs { --stack: var(--space-2xs); }
.stack--xs { --stack: var(--space-xs); }
.stack--s { --stack: var(--space-s); }
.stack--l { --stack: var(--space-l); }
.stack--xl { --stack: var(--space-xl); }
.stack--center { align-items: center; text-align: center; }

.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cluster-gap, var(--space-s)); }
.cluster--tight { --cluster-gap: var(--space-2xs); }
.cluster--loose { --cluster-gap: var(--space-m); }
.cluster--center { justify-content: center; }
.cluster--between { justify-content: space-between; }

/* auto-fill grid: set --grid-min on the element (default 280px) */
.grid { display: grid; gap: var(--grid-gap, clamp(1.25rem, .8rem + 1.6vw, 2rem)); grid-template-columns: repeat(auto-fill, minmax(min(var(--grid-min, 280px), 100%), 1fr)); }
.grid--fit { grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min, 280px), 100%), 1fr)); }
.grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
@media (min-width: 700px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* media + text side by side; stacks under 900px (media first) */
.split { display: grid; gap: clamp(2rem, 1rem + 5vw, 6rem); align-items: center; }
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; }
  .split--media-wide { grid-template-columns: 7fr 5fr; }
  .split--text-wide { grid-template-columns: 5fr 7fr; }
  .split--flip > :first-child { order: 2; }
  .split--top { align-items: start; }
}

.center { text-align: center; }
.mx-auto { margin-inline: auto; }
.mt-0 { margin-block-start: 0 !important; }
.mt-s { margin-block-start: var(--space-s); }
.mt-m { margin-block-start: var(--space-m); }
.mt-l { margin-block-start: var(--space-l); }
.mt-xl { margin-block-start: var(--space-xl); }
.mb-l { margin-block-end: var(--space-l); }
.full-bleed { width: 100vw; margin-inline-start: calc(50% - 50vw); }

/* ---------------------------------------------------------------- section tones */
.tone-ivory { background: var(--ivory); }
.tone-sand { background: var(--stone-50); }
.tone-stone { background: var(--stone-100); }
.tone-surface { background: var(--surface); }
.tone-navy, .tone-deep, .tone-walnut { color: var(--on-dark); --line: var(--line-on-dark); --muted: var(--on-dark-muted); --ink-soft: var(--on-dark-soft); --accent-ink: var(--gold-400); --surface: rgba(247, 240, 227, .04); --line-strong: rgba(247, 240, 227, .28); }
.tone-navy { background: var(--navy-900); }
.tone-deep { background: var(--navy-950); }
.tone-walnut { background: var(--walnut-900); }
:is(.tone-navy, .tone-deep, .tone-walnut) :is(h1, h2, h3, .h1, .h2, .h3, .display-1) { color: var(--white); }

/* ---------------------------------------------------------------- ornaments & patterns */
/* mashrabiya lattice (8-point stars, after the gold screen in the hotel corridor) */
.pattern { position: relative; isolation: isolate; }
.pattern::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='56' viewBox='0 0 56 56'%3E%3Cg fill='none' stroke='%23c2a15f' stroke-width='1'%3E%3Cpath d='M19 19h18v18H19zM28 15.3 40.7 28 28 40.7 15.3 28z'/%3E%3Cpath d='M28 0v15.3M56 28H40.7M28 56V40.7M0 28h15.3M0 0l19 19M56 0 37 19M56 56 37 37M0 56l19-19'/%3E%3C/g%3E%3C/svg%3E");
  background-size: var(--pattern-size, 56px);
  opacity: var(--pattern-opacity, .07);
}
.pattern--fade::before { -webkit-mask-image: linear-gradient(to bottom, #000, transparent 85%); mask-image: linear-gradient(to bottom, #000, transparent 85%); }
.pattern--strong { --pattern-opacity: .13; }

/* line — diamond — line */
.ornament { display: flex; align-items: center; justify-content: center; gap: .7rem; color: var(--gold-500); width: min(100%, 220px); }
.ornament::before, .ornament::after { content: ""; flex: 1; height: 1px; background: linear-gradient(to var(--ornament-to, right), transparent, currentColor); }
.ornament::after { background: linear-gradient(to var(--ornament-to, right), currentColor, transparent); }
.ornament > i { width: 7px; height: 7px; flex: none; background: currentColor; transform: rotate(45deg); }
.ornament--start { margin-inline: 0; width: 120px; }
.ornament--start::before { display: none; }
.rule { height: 1px; border: 0; background: var(--line); margin-block: var(--space-xl); }
.rule--gold { background: linear-gradient(to right, transparent, var(--gold-500), transparent); }

/* ---------------------------------------------------------------- icons */
.icon { width: 1.25em; height: 1.25em; flex: none; fill: none; stroke: currentColor; stroke-width: var(--icon-stroke, 1.6); stroke-linecap: round; stroke-linejoin: round; vertical-align: middle; }
.icon--sm { width: 1em; height: 1em; }
.icon--lg { width: 1.75em; height: 1.75em; }
.icon--xl { width: 2.25em; height: 2.25em; }
/* arrows: .icon-dir points "forward" (reading direction), .icon-back points back — both flip with the language */
[dir="rtl"] .icon-dir { transform: scaleX(-1); }
.icon-back { transform: scaleX(-1); }
[dir="rtl"] .icon-back { transform: none; }

/* in-page anchors land below the sticky header */
[id] { scroll-margin-top: calc(var(--header-h) + 1rem); }

/* full-width photo band (optionally with [data-parallax] on the picture): <div class="media-bleed" style="--h: 70svh"> */
.media-bleed { position: relative; overflow: hidden; height: var(--h, clamp(320px, 62svh, 720px)); background: var(--navy-900); }
.media-bleed > picture, .media-bleed > img { position: absolute; inset: 0; width: 100%; height: 100%; }
.media-bleed img { width: 100%; height: 100%; object-fit: cover; object-position: var(--focus-pos, 50% 50%); }

/* ==========================================================================
   Motion — states driven by /js/motion.js (see docs/frontend-notes.md § Motion)
   Everything here animates transform-family properties (translate / scale / transform) and opacity only.
   html[data-motion="full"]  rich motion (default, or the «تشغيل الحركة» switch on a reduced-motion device)
   html[data-motion="calm"]  soft fades only (device asks for reduced motion, or the visitor switched motion off)
   ========================================================================== */
/* ---- scroll reveals: [data-reveal] = up (default) | fade | start | end | scale | curtain ---- */
html.js [data-reveal]:not(.is-in) { opacity: 0; }
html.js [data-reveal] { transition: opacity .7s var(--ease-out) var(--reveal-delay, 0ms); }
html.js[data-motion="full"] [data-reveal] {
  transition-property: opacity, translate, scale, transform;
  transition-duration: .9s, 1.15s, 1.15s, .5s;
  transition-timing-function: var(--ease-out), var(--ease-expo), var(--ease-expo), var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms), var(--reveal-delay, 0ms), var(--reveal-delay, 0ms), 0ms;
}
html.js[data-motion="full"] [data-reveal=""]:not(.is-in),
html.js[data-motion="full"] [data-reveal="up"]:not(.is-in) { translate: 0 var(--reveal-y, 36px); }
html.js[data-motion="full"] [data-reveal="start"]:not(.is-in) { translate: calc(var(--dir) * -48px) 0; }
html.js[data-motion="full"] [data-reveal="end"]:not(.is-in) { translate: calc(var(--dir) * 48px) 0; }
@media (max-width: 699px) { /* phones: a shorter slide, so nothing waiting to come in sits past the screen edge */
  html.js[data-motion="full"] [data-reveal="start"]:not(.is-in) { translate: calc(var(--dir) * -24px) 0; }
  html.js[data-motion="full"] [data-reveal="end"]:not(.is-in) { translate: calc(var(--dir) * 24px) 0; }
}
html.js[data-motion="full"] [data-reveal="scale"]:not(.is-in) { scale: .94; }
/* curtain: a stone panel slides off the media (the media itself doesn't fade) */
[data-reveal="curtain"] { position: relative; }
html.js[data-motion="full"] [data-reveal="curtain"]:not(.is-in) { opacity: 1; }
html.js[data-motion="full"] [data-reveal="curtain"]::after {
  content: ""; position: absolute; inset: -1px; z-index: 3; pointer-events: none; border-radius: inherit;
  background: var(--curtain, var(--stone-100)); transform-origin: var(--origin-end);
  transition: scale 1.25s var(--ease-in-out) var(--reveal-delay, 0ms);
}
html.js[data-motion="full"] [data-reveal="curtain"].is-in::after { scale: 0 1; }

/* ---- gold line motif: an eyebrow's line / an ornament's rules draw themselves in (scale only) ---- */
html.js[data-motion="full"] .eyebrow[data-reveal]::before,
html.js[data-motion="full"] [data-reveal] .eyebrow::before,
html.js[data-motion="full"] .eyebrow--center[data-reveal]::after { scale: 0 1; transition: scale 1.2s var(--ease-expo) calc(var(--reveal-delay, 0ms) + 150ms); }
html.js[data-motion="full"] .eyebrow[data-reveal]::before { transform-origin: var(--origin-end); }
html.js[data-motion="full"] .eyebrow--center[data-reveal]::after { transform-origin: var(--origin-start); }
html.js[data-motion="full"] .eyebrow.is-in::before, html.js[data-motion="full"] .is-in .eyebrow::before, html.js[data-motion="full"] .eyebrow--center.is-in::after { scale: 1 1; }
html.js[data-motion="full"] .ornament[data-reveal]::before, html.js[data-motion="full"] .ornament[data-reveal]::after { scale: 0 1; transition: scale 1.3s var(--ease-expo) calc(var(--reveal-delay, 0ms) + 120ms); }
html.js[data-motion="full"] .ornament[data-reveal]::before { transform-origin: var(--origin-end); }
html.js[data-motion="full"] .ornament[data-reveal]::after { transform-origin: var(--origin-start); }
html.js[data-motion="full"] .ornament[data-reveal] > i { scale: 0; transition: scale .8s var(--ease-spring) var(--reveal-delay, 0ms); }
html.js[data-motion="full"] .ornament.is-in::before, html.js[data-motion="full"] .ornament.is-in::after { scale: 1 1; }
html.js[data-motion="full"] .ornament.is-in > i { scale: 1; }

/* ---- photo settle: the image eases from a slight zoom when its frame is revealed ---- */
html.js[data-motion="full"] [data-settle] img { scale: 1.12; transition: scale 1.9s var(--ease-expo) var(--reveal-delay, 0ms), transform .9s var(--ease-out); }
html.js[data-motion="full"] [data-settle].is-in img { scale: 1; }

/* ---- word-by-word heading rise: [data-split] (motion.js wraps each word) ----
   Each word rises inside its own mask (.w). The mask has generous room on every side (taken back by negative margins,
   so the layout is unchanged): Amiri tails, swashes, dots and hamzas and Cormorant's overhangs reach well past the
   line box. It only clips while the words are moving: motion.js adds .split-done once the rise has ended and the
   clip is released, so a finished heading can never have a cut letter. A word waiting to rise sits fully below its
   mask (its own height + the mask's bottom room + the ink that can stand above the box) and is transparent too. */
[data-split] .w { display: inline-block; vertical-align: top; padding: .32em .4em .55em; margin: -.32em -.4em -.55em; }
[data-split] .wi { display: inline-block; }
html.js[data-motion="full"] [data-split]:not(.split-done):not(.split-static) .w { overflow: clip; }
html.js[data-motion="full"] [data-split]:not(.is-split) { opacity: 0; }
html.js[data-motion="full"] [data-split] .wi { transition: translate 1.15s var(--ease-expo) calc(var(--reveal-delay, 0ms) + var(--wi, 0) * 65ms), opacity .55s var(--ease-out) calc(var(--reveal-delay, 0ms) + var(--wi, 0) * 65ms); }
html.js[data-motion="full"] [data-split]:not(.is-in) .wi { translate: 0 calc(100% + .95em); opacity: 0; }
html.js[data-motion="calm"] [data-split]:not(.is-in) { opacity: 0; }
html.js[data-motion="calm"] [data-split] { transition: opacity .7s var(--ease-out) var(--reveal-delay, 0ms); }
/* first screen whose web fonts didn't arrive in time (motion.js): the heading fades in whole, no word rise */
html.js [data-split].split-static .wi { translate: none !important; transition: none !important; }
html.js [data-split].split-static:not(.is-in) { opacity: 0; }
html.js [data-split].split-static { transition: opacity .8s var(--ease-out) var(--reveal-delay, 0ms); }
/* keyboard focus landed inside something not yet revealed: show it at once (motion.js) */
.reveal-instant, .reveal-instant :is([data-reveal], [data-split], .wi, img), .reveal-instant::before, .reveal-instant::after,
.reveal-instant [data-reveal]::before, .reveal-instant [data-reveal]::after { transition: none !important; }

/* ---- parallax: [data-parallax] on a <picture>/<img> wrapper inside .frame / .page-hero__media / .media-bleed ----
   The frame names a view timeline and the photo follows it: a child of a clipped box can't use view() itself
   (an overflow box becomes its scroller). Runs on the compositor; motion.js scrubs translate where unsupported. */
:is(.frame, .page-hero__media, .media-bleed, .cta-band__media) > [data-parallax] { position: absolute; inset: calc(var(--parallax-bleed, 9%) * -1) 0; height: auto; }
:is(.frame, .page-hero__media, .media-bleed, .cta-band__media) > [data-parallax] img { width: 100%; height: 100%; object-fit: cover; }
@supports (animation-timeline: view()) {
  :is(.frame, .page-hero__media, .media-bleed, .cta-band__media):has(> [data-parallax]) { view-timeline: --abyat-px block; }
  html[data-motion="full"] [data-parallax] { animation: abyat-parallax linear both; animation-timeline: --abyat-px; animation-range: cover 0% cover 100%; }
  /* a hero starts at the top of the page: drift only as it leaves */
  html[data-motion="full"] .page-hero__media > [data-parallax] { animation-name: abyat-parallax-exit; animation-range: exit 0% exit 100%; }
}
@keyframes abyat-parallax-exit { from { translate: 0 0; } to { translate: 0 calc(var(--parallax-shift, 7%) * 1.6); } }
@keyframes abyat-parallax {
  from { translate: 0 calc(var(--parallax-shift, 7%) * -1); }
  to { translate: 0 var(--parallax-shift, 7%); }
}

/* ---- odometer digits (visitor counter, stats): only translate animates ---- */
.odo { display: inline-flex; direction: ltr; unicode-bidi: isolate; font-variant-numeric: lining-nums tabular-nums; line-height: 1.15; height: 1.15em; overflow: clip; vertical-align: bottom; }
.odo__d { display: inline-block; height: 1.15em; overflow: clip; }
.odo__strip { display: flex; flex-direction: column; translate: 0 calc(var(--n, 0) * -1.15em); }
.odo__strip > span { display: block; height: 1.15em; text-align: center; }
html[data-motion="full"] .odo__strip { transition: translate 1.7s var(--ease-expo) calc(var(--i, 0) * 80ms); }
html[data-motion="calm"] .odo__strip { transition: none; }

/* ---- safety nets: never leave content hidden ---- */
html.reveal-all [data-reveal], html.reveal-all [data-split], html.reveal-all [data-split] .wi { opacity: 1 !important; translate: none !important; scale: none !important; }
html.reveal-all [data-reveal]::after { display: none !important; }
@media print {
  [data-reveal], [data-split], [data-split] .wi { opacity: 1 !important; translate: none !important; scale: none !important; }
}

/* ---- page transitions (cross-document View Transitions; skipped in calm mode by /js/boot.js) ---- */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: abyat-vt-out .32s var(--ease-out) both; }
::view-transition-new(root) { animation: abyat-vt-in .5s var(--ease-out) both; }
@keyframes abyat-vt-out { to { opacity: 0; } }
@keyframes abyat-vt-in { from { opacity: 0; translate: 0 10px; } }
::view-transition-group(site-header) { animation-duration: 0s; }

/* shared keyframes for components */
@keyframes abyat-fade-up { from { opacity: 0; translate: 0 14px; } }
@keyframes abyat-fade-in { from { opacity: 0; } }
@keyframes abyat-pop { 0% { opacity: 0; scale: .6; } 70% { opacity: 1; scale: 1.06; } 100% { scale: 1; } }
@keyframes abyat-spin { to { rotate: 360deg; } }
html[data-motion="calm"] :not(.spinner), html[data-motion="calm"] ::before, html[data-motion="calm"] ::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
