/* ── CONTAINER-RELATIVE COMPONENT SCALE ──────────────────────────────────────
   The steps above are VIEWPORT-fluid, which is correct for a hero: a hero IS
   the viewport. It is wrong for a component. A card sized on vw renders at its
   1440px size inside a 320px panel, because vw knows the window and nothing
   about the box the component actually sits in — so the same partial is right
   in a hero and broken in a sidebar, and the failure only appears once the
   component is reused (SITE.FLUID-TYPE / the container-query finding).

   Every shared component below therefore declares `container-type: inline-size`
   and sizes on `cqi` (1cqi = 1% of the container's inline size). The hero keeps
   its vw clamps deliberately: it is full-bleed, so its container IS the
   viewport and cqi would be the same number by a longer route.

   THE FALLBACK IS THE STATIC STEP, NOT A vw VALUE. `clamp()` with a cqi term
   inside a non-container element resolves cqi against the nearest container or
   the small viewport; naming the static step as the floor means an old engine
   with no container support lands on the current type scale rather than on
   something narrower. Degrade to today, never to worse than today. */
:where(.panel, .signal, .metric, .layer-card, .contact-item, .legal-card, .hero-card) {
  container-type: inline-size;
}
@supports (container-type: inline-size) {
  .panel h3,
  .layer-card h3 { font-size: clamp(1.15rem, 0.95rem + 2.2cqi, 1.80rem); }
  .panel p,
  .layer-card p,
  .contact-item,
  .legal-card > p { font-size: clamp(0.92rem, 0.86rem + 0.7cqi, 1.06rem); }
  .signal strong,
  .metric strong,
  .contact-item strong { font-size: clamp(0.92rem, 0.86rem + 0.7cqi, 1.06rem); }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  /* The brand body stack, supplied by brand.css_tokens(); falls back to the
     previous system stack for any company with no pinned typeface. */
  font-family: var(--font-latin, system-ui), -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
  color: var(--ink);
  background: var(--surface-sunk);
  line-height: 1.6;
  font-size: var(--step-0);
}
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }
.page { min-height: 100vh; background: var(--page); }
.shell { width: min(1120px, calc(100% - 32px)); margin: 0 auto; }
.topbar {
  background: white;
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 10;
}
.topbar .shell,
.footer .shell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-3) 0;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: inherit;
}
.brand:hover { text-decoration: none; }
.brand-mark {
  width: 44px;
  height: 44px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--brand);
  color: white;
  font-weight: 800;
}
.brand-copy small {
  display: block;
  color: var(--ink-soft);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.brand-copy strong {
  display: block;
  font-family: var(--font-latin-display, Georgia), Georgia, "Times New Roman", serif;
  font-size: 1rem;
}
.nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
/* A nav link used to be styled with colour and weight only, so the anchor box
   was exactly the text: 60x26 on naya, 56x32 on metha. Padding to the shared
   control floor is what turns a line of text into a thing a thumb can hit. */
.nav a {
  color: var(--ink-soft);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  min-height: var(--control-min);
  padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
}
.nav a:hover { color: var(--brand); text-decoration: none; }
/* The hero was a FIXED 72/48 of padding that did not shrink on a phone, on top
   of a grid that stacks to one column under 900px — so the hero card's whole
   height was ADDED to the hero rather than sitting beside it. Measured result:
   naya's phone hero ran 1246px against an 844px fold (148% of the viewport,
   the next section 581px below it) and metha's ran 103%. A visitor had no cue
   that anything followed. The cap leaves the next band's edge in the fold. */
.hero {
  padding: var(--space-section) 0;
  background: linear-gradient(180deg, var(--surface), var(--surface-sunk));
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(280px, 0.9fr);
  gap: var(--space-6);
  align-items: start;
}
.eyebrow,
.mini-label {
  display: inline-block;
  color: var(--brand);
  font-size: var(--step-eyebrow);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.hero h1,
.section-header h2,
.legal-card h2 {
  font-family: var(--font-latin-display, Georgia), Georgia, "Times New Roman", serif;
  line-height: 1.1;
  margin: var(--space-3) 0;
}
/* EVERY heading on the scale, not just h1. h2/h3 previously had no size rule
   at all and inherited the UA default, fixed at both breakpoints — so the
   h1:h2 ratio was 1.47 on a phone and 2.67 on a laptop. */
.hero h1 { font-size: var(--step-4); }
.section-header h2,
.legal-card h2 { font-size: var(--step-3); }
.panel h3,
.layer-card h3 { font-size: var(--step-2); line-height: 1.3; }
/* .signal/.metric/.contact-item carry ONE-LINE labels, not section headings —
   they take the body step. Putting them on --step-2 grew naya's laptop hero
   846->1157px (the hero card is a list of 8 service labels), which pushed the
   next section 327px below the fold: a C1 regression caused by the C2 fix. */
.signal strong,
.metric strong,
.contact-item strong { font-size: var(--step-0); line-height: 1.35; }
.lead,
.hero .lead { font-size: var(--step-1); }
.lead,
.section-header p,
.legal-card > p,
.signal p,
.metric span,
.panel p,
.contact-item {
  color: var(--ink-soft);
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: var(--space-5) 0 0;
}
/* ONE button system. Height comes from the shared control floor so a CTA, a
   nav link and a form submit are the same size everywhere on the kit. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-min);
  padding: var(--control-pad-y) var(--control-pad-x);
  border-radius: var(--radius-pill);
  font-size: var(--step-0);
  font-weight: 700;
  border: 1px solid transparent;
}
.button.primary { background: var(--brand); color: white; }
.button.secondary { background: white; color: var(--brand); border-color: var(--line); }
.button:hover { text-decoration: none; filter: brightness(0.98); }
/* ONE card system: same ground, same rule, same radius, same padding for every
   card species on the kit. The species differ by CONTENT, never by chrome. */
.hero-card,
.metric,
.signal,
.panel,
.legal-card,
.contact-item,
.layer-card {
  /* `white` is a literal the hex/rgba scan cannot see, but it is the same
     defect: a component pointing at a value instead of a role, which is why a
     dark theme inherits a white card it never chose. */
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
}
.hero-card { padding: var(--space-5); box-shadow: var(--shadow-card); }
.signal-grid,
.metric-grid,
.panel-grid {
  display: grid;
  gap: var(--space-gap);
}
.signal-grid,
.metric-grid { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
/* INSIDE THE HERO CARD the column is ~290px, so a 180px floor admits exactly
   ONE column and every one-word feature ("الليز", "الشعر") got a full-width
   outlined box with its label pushed to the edge — a populated list that reads
   as a stack of empty fields. A container query, not a viewport one: the card
   already declares container-type: inline-size, so the chips pack two-up on the
   real available width instead of a guess about the window. */
@container (min-width: 240px) {
  .hero-card .signal-grid { grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); }
}
.hero-card .signal { padding: var(--space-2) var(--space-3); text-align: center; }
.panel-grid { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.signal,
.metric { padding: var(--space-3) var(--space-4); }
.panel { padding: var(--space-5); }
.signal strong,
.metric strong,
.panel h3,
.contact-item strong { display: block; margin-bottom: var(--space-2); }
/* A LABEL WITH NOTHING UNDER IT RESERVES SPACE FOR A VALUE THAT NEVER COMES.
   `.signal` renders one <strong> per feature point and no body text, so the
   label's bottom margin left a blank band inside every chip — eight outlined
   boxes that read as empty form fields beside the hero (reported as "an empty
   hero-side card" on naya and metha at 1440; the card was never empty, its rows
   were hollow). `:last-child` keeps the margin wherever a value DOES follow. */
.signal strong:last-child,
.metric strong:last-child,
.contact-item strong:last-child { margin-bottom: 0; }
/* ONE section rhythm, symmetric and fluid. Was 28px top / 44px bottom fixed —
   asymmetric for no reason and identical on a 390px phone and a 1440px desk. */
.section { padding: var(--space-section) 0; }
.section-header { max-width: 720px; margin-bottom: var(--space-5); }
/* A section whose collection came back empty must not paint its full rhythm
   and its background band anyway. Measured on tondro's laptop render: a
   Featured Projects heading, ~450px of empty paper, then a ~700px empty navy
   band. The guard belongs on the kit, not in one company's template. */
.section:empty,
.section-body:empty { display: none; }
.legal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 18px;
}
.legal-card { padding: var(--space-5); }
.faq-item + .faq-item {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}
.contact-list {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-4);
}
.contact-item { padding: var(--space-4); }
/* The email and website VALUES inside a contact card are links and were the
   last sub-24px targets on the kit (measured 174x20 and 190x20 on naya, 17px
   tall on metha): the card styled its label and left the anchor as a bare text
   box. WCAG 2.2 AA's floor is 24px for a non-primary target, so the anchor
   takes the height the row already has space for — it does not need the 44px
   CTA floor, because it is a reference value, not the page's action. */
.contact-item a,
.nap-item a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}
.footer {
  margin-top: var(--space-6);
  background: var(--footer-surface);
  color: var(--footer-ink);
  padding-block: var(--space-4);
}
.footer a { color: var(--footer-link); }
.footer nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
/* Footer links measured 177x20 and 178x17 — the smallest targets on the kit. */
.footer nav a,
.footer-meta a {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-min);
  padding: 0 var(--space-2);
}
.footer-meta p { margin: 0 0 6px; }
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; }
  .footer .shell {
    flex-direction: column;
    align-items: flex-start;
  }
  /* THE PHONE CHROME. The topbar used to become a column, so brand / nav /
     lang each took a row: 179px of header on naya, 138px on metha, against an
     844px fold. The nav now scrolls horizontally on one line instead of
     wrapping onto new ones — every link stays reachable with a thumb swipe and
     the header holds one row.

     ORDER MATTERS IN RTL. A scroll container starts at its inline START, which
     Chromium resolves to the LEFT edge under dir=rtl — so the first render
     showed the MIDDLE of the nav with the first link clipped off-screen and
     the lang switch unreachable. Reversing the visual order puts the first
     link at the right edge where an Arabic reader starts, and the rail then
     sits at its natural resting position with nothing cut. */
  .topbar .shell {
    flex-wrap: nowrap;
    gap: var(--space-2);
    padding: var(--space-2) 0;
  }
  /* The nav WRAPS to a second line rather than scrolling. A horizontal scroll
     rail was tried first and is wrong here for a measured reason: the language
     switch is markup-nested INSIDE .nav, so it scrolled out of reach, and a
     scroll container under dir=rtl starts at its inline START — which Chromium
     resolves to the LEFT edge — so the rail opened mid-list with the first
     link clipped. Wrapping keeps every link and the language switch visible
     with no hidden state, and the tighter link padding keeps the whole header
     to ~70px, well under the 138-179px it used to cost. */
  .topbar .nav {
    flex-wrap: wrap;
    justify-content: flex-end;
    row-gap: 0;
    min-width: 0;
  }
  .topbar .nav a { padding: 0 var(--space-2); }
  /* The brand block is the one element that must never wrap away from the
     top line; it also carries the tap target back to the home page. */
  .topbar .brand { flex: 0 0 auto; }
  /* Cap the hero against the visible fold so the next band's edge is always
     in view. min-height, not height: content longer than the cap still grows. */
  .hero { padding: var(--space-6) 0 var(--space-7); }
  .hero-grid { max-height: none; }
  .hero .hero-card { display: none; }
}

/* The hero card is a scannable index, not a content block: on a wide viewport
   it sits beside the copy, so its own height sets the hero's height once the
   list runs long (naya ships 8 service labels). Cap it and let it scroll. */
@media (min-width: 901px) {
  .hero .hero-card {
    max-height: calc(var(--hero-max) - var(--space-7));
    overflow-y: auto;
  }
}

/* The hero card is the single largest contributor to phone hero height (it is
   a full list of services stacked under the copy). On a phone it duplicates
   the services section further down the page, so it is hidden above rather
   than scrolled through twice — the copy and the CTAs are what the fold owes. */

/* ── bilingual chrome + modern inquiry form (founder-directed 2026-08-05) ── */
.lang-switch {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  min-height: var(--control-min);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: 0 var(--space-4);
  font-size: var(--step-0);
  color: var(--ink-soft);
}
.lang-switch:hover { border-color: var(--brand); color: var(--brand); text-decoration: none; }

.inq-form { margin-top: 18px; }
.inq-form .field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-gap);
}
@media (max-width: 640px) { .inq-form .field-row { grid-template-columns: 1fr; } }
.inq-form .field { margin-bottom: 14px; }
.inq-form label {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  margin-bottom: 6px;
}
.inq-form label .opt { font-weight: 400; opacity: 0.6; }
/* 16px floor is not taste: iOS Safari ZOOMS the page on focus of any input
   under 16px, and never zooms back out. --step-0 has a 0.95rem minimum, so the
   input floor is pinned at 1rem explicitly rather than riding the scale. */
.inq-form input,
.inq-form textarea {
  width: 100%;
  font: inherit;
  font-size: 1rem;
  min-height: var(--control-min);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-input);
  padding: var(--control-pad-y) var(--space-4);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.inq-form input::placeholder,
.inq-form textarea::placeholder { color: var(--placeholder-ink); }
.inq-form input:focus,
.inq-form textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}
.inq-form textarea { resize: vertical; min-height: 110px; }
.inq-form .submit { width: 100%; margin-top: var(--space-1); border: none; cursor: pointer; font-size: 1rem; min-height: var(--control-min); padding: var(--control-pad-y) var(--control-pad-x); }
.inq-form .submit:disabled { opacity: .55; cursor: default; }
.inq-note { margin-top: 10px; font-size: 0.9rem; min-height: 1.2em; color: var(--ink-soft); }
.inq-note.ok { color: var(--state-ok); }
.inq-note.err { color: var(--state-err); }

/* RTL: the engine emits dir=rtl on <html>; logical props do the rest.
   There is deliberately NO `[dir="rtl"] body { font-family: system-ui }` here.
   It used to sit on this line, live on the DEFAULT render of every
   minimal-theme site (they are all rtl at the root), and was beaten only
   because discovery_page.html.j2 re-asserts the Arabic stack in a LATER inline
   <style>. The brand face survived by source order, not by intent — delete
   that later block and both sites silently drop to system-ui. The Arabic stack
   belongs to the brand floor (--font-arabic), so no reset is correct here.

   `text-align: start` is the logical form and needs no [dir] selector at all:
   it resolves to right under rtl and left under ltr by definition. The old
   `[dir=rtl] … { text-align: right }` pair was the last physical property in
   this file (SITE.CSS-LOGICAL: 0 physical props outside a mirror allowlist). */
.inq-form input,
.inq-form textarea { text-align: start; }

/* ── THE SHARED CROSS-THEME BLOCK ────────────────────────────────────────────
   Arabic type metrics, bidi isolation, the icon-mirror allowlist, the CTA rail
   and the NAP block are NOT in this file: they live in
   partials/shared.css.j2 and the builder CONCATENATES them onto the end of
   this stylesheet at build time (site_build.py `styles.css` target).

   Why not simply write them here: corporate, cinematic and atelier inline
   their whole stylesheet and never <link> this file, so a rule that must hold
   on every theme would reach only the minimal one. The partial is the single
   source all four read. Read it beside this file — the built styles.css is
   this file plus that block, in that order.
   ───────────────────────────────────────────────────────────────────────── */

/* ── 404 ─────────────────────────────────────────────────────────────────────
   Cloudflare Pages serves /404.html with a real 404 status automatically, so a
   branded page here costs one file and replaces the generic host page. It
   carries the CTA rail: a visitor who mistyped a URL is a visitor who wanted
   to reach the business, and the rail is how they do. */
.notfound {
  min-height: 70svh;
  display: flex;
  align-items: center;
}
.notfound .code {
  font-size: var(--step-4);
  font-weight: 800;
  color: var(--brand);
  line-height: 1;
}
.notfound h1 { font-size: var(--step-3); margin: var(--space-4) 0 var(--space-2); }
.notfound p { color: var(--ink-soft); margin: 0 0 var(--space-5); max-width: 46ch; }

/* ---- THREE-LAYER BANDS (resources / production / growth) -------------------
   Rendered by partials/layer_bands.html, shared by every theme. Styling rides
   the brand tokens already on the page, so each company draws these in its own
   palette without a per-theme copy of the markup. Deliberately reuses the
   existing panel rhythm rather than inventing a second card system. */
.layer-grid { display: grid; gap: var(--space-gap);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.layer-card { padding: var(--space-5); }
.layer-card h3 { margin: 0 0 var(--space-2); line-height: 1.3; }
.layer-card p { margin: 0; font-size: var(--step-0); opacity: .82; line-height: 1.5; }
.layer-count { font-weight: 700; opacity: .65; margin-inline-start: .35em; }
.layer-meta { font-size: .85rem; opacity: .75; }
.layer-band + .layer-band { padding-top: 0; }
/* ── ARABIC TYPE (SITE.AR-TYPE) ──────────────────────────────────────────────
   Arabic sets differently from Latin and the difference is measurable, not
   aesthetic: a Latin body line-height (1.5-1.6) collides with the ascenders and
   the tashkeel, and a Latin tracking value breaks the joined script outright
   because Arabic letterforms CONNECT — adding space between them severs the
   word. Body 1.75, headings 1.35, letter-spacing normal, ≥16px.

   The FAMILY is not set here: it is the brand floor's (--font-arabic /
   --font-arabic-display, per-company pinned faces). This block owns the
   METRICS only, which is what keeps a company's face and the kit's rhythm from
   being one decision. */
:where(:lang(ar)) body,
:where(:lang(ar)) p,
:where(:lang(ar)) li {
  line-height: 1.75;
  letter-spacing: normal;
}
:where(:lang(ar)) h1,
:where(:lang(ar)) h2,
:where(:lang(ar)) h3,
:where(:lang(ar)) .hero h1 {
  line-height: 1.35;
  letter-spacing: normal;
}
/* The eyebrow is the one place Latin tracking is applied on purpose (an
   uppercase Latin kicker). Under RTL it must be neutralised or the Arabic
   kicker renders as disconnected letters. */
:where(:lang(ar)) .eyebrow,
:where(:lang(ar)) .mini-label,
:where(:lang(ar)) .brand-copy small {
  letter-spacing: normal;
  text-transform: none;
}

/* ── BIDI ISOLATION (SITE.BIDI) ──────────────────────────────────────────────
   A Latin run (a brand name, a URL, an email) or a digit run (a price, a phone
   number, a CR number) inside an Arabic paragraph REORDERS visibly without
   isolation: `+966 53 966 0608` renders with its segments transposed. The
   template wraps such runs in <bdi>, which isolates by default; this pins the
   behaviour explicitly so a future reset cannot unset it, and gives `.ltr-num`
   to any generated value that cannot be wrapped at the markup layer. */
bdi,
.ltr-num {
  unicode-bidi: isolate;
}
.ltr-num {
  direction: ltr;
  display: inline-block;
}

/* ── ICON MIRRORING (SITE.ICON-MIRROR) ───────────────────────────────────────
   An RTL page must mirror DIRECTION-CARRYING icons (an arrow pointing to the
   next step now points the other way) and must NOT mirror anything else. A
   blanket `[dir=rtl] svg { transform: scaleX(-1) }` reverses the logo, flips a
   clock face backwards and renders a phone handset upside-down — a real defect
   class, which is why this is an ALLOWLIST keyed on one class and never a
   blanket rule. Add `.icon-directional` to an arrow/chevron; add it to nothing
   else. The CTA rail's icons (phone, calendar, WhatsApp, menu) are deliberately
   absent from it. */
:where(:lang(ar)) .icon-directional {  /* keyed on the Arabic document, never [dir=rtl] (CSS.DIR-RTL-BLOCK) */
  transform: scaleX(-1);
}

/* ── THE CTA RAIL (SITE.CTA-RAIL / SITE.CTA-TAP) ─────────────────────────────
   Call · WhatsApp · Book|Menu|Enquire, above the fold on a phone and in the
   header on a laptop. Plain anchors, ≥44x44, zero JS. Shared by every theme
   through partials/cta_rail.html so the three assemblers cannot drift apart
   again (they held three different answers and no `tel:` at all).

   FLEX + LOGICAL PROPERTIES = ONE MARKUP FOR BOTH DIRECTIONS. A flex row's
   order follows the container's `direction`, so Call sits leftmost under ltr
   and rightmost under rtl with no per-direction markup and no [dir] selector.
   This is the same law the bilingual document tables obey (§1: COLUMN order is
   set by the container's direction, TEXT direction by the cell's). */
.cta-rail {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}
.cta-rail__item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-min);
  min-width: var(--control-min);
  padding: var(--control-pad-y) var(--control-pad-x);
  border-radius: var(--radius-pill);
  border: 1px solid var(--line, var(--rule));
  background: var(--surface);
  color: var(--ink);
  font-size: var(--step-0);
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
}
.cta-rail__item:hover { text-decoration: none; border-color: var(--brand); color: var(--brand); }
.cta-rail__item.is-lead,
.cta-rail__item--book,
.cta-rail__item--booking {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-surface);
}
.cta-rail__item.is-lead:hover,
.cta-rail__item--book:hover,
.cta-rail__item--booking:hover { color: var(--on-surface); filter: brightness(1.06); }
.cta-rail__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.cta-rail__icon svg { display: block; }
/* The HERO rail is the phone's primary surface: full-width tiles that divide
   the row evenly, so three CTAs are three equal thumb targets rather than
   three differently-sized words. */
.cta-rail--hero { margin-block: var(--space-5) 0; }
.cta-rail--hero .cta-rail__item { flex: 1 1 auto; min-width: 8.5rem; }
/* The HEADER rail is the laptop's: compact, icon-forward, still full height.
   Hidden on a phone because the hero rail already carries the same three
   targets and a duplicated CTA row is chrome, not conversion. */
.cta-rail--header { display: none; }
@media (min-width: 901px) {
  /* THE HEADER RAIL IS ICON-ONLY, AND THAT IS NOT A SIZE CHOICE.
     Rendered with labels it is three more word-blocks in a bar that already
     carries a logo, seven nav links and a language switch: measured on
     tondro's 1440px header, the rail WRAPPED to a second row and overlapped
     the nav. The hero rail twelve rows below carries the same three targets
     WITH their labels, so the header's job is persistence, not explanation —
     it is the thing still on screen after the visitor scrolls past the hero.

     The label stays in the DOM as the accessible name (`.cta-rail__label` is
     visually hidden, never `display:none`), so a screen reader still hears
     "Call" and the icon is not an unlabelled button. */
  .cta-rail--header { display: flex; flex-wrap: nowrap; gap: var(--space-2); }
  .cta-rail--header .cta-rail__item {
    padding: 0;
    width: var(--control-min);
    min-width: var(--control-min);
    flex: 0 0 auto;
  }
  .cta-rail--header .cta-rail__label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
/* Under ~430px three labelled tiles wrap to two rows. That is correct (every
   target keeps its 44px and its label) but the lead action should stay whole
   on the first row, so it takes the full width and the other two share. */
@media (max-width: 430px) {
  .cta-rail--hero .cta-rail__item.is-lead { flex: 1 1 100%; }
  .cta-rail--hero .cta-rail__item { flex: 1 1 40%; min-width: 0; }
}

/* ── NAP BLOCK (SITE.NOJS-USEFUL) ─────────────────────────────────────────
   Name / address / hours / phone, as text and anchors. No card chrome: it sits
   inside whatever card the theme placed it in, so it must not draw a second
   border around itself. */
.nap { display: grid; gap: var(--space-4); }
.nap-item { display: grid; gap: var(--space-1); }
.nap-name { font-size: var(--step-0); font-weight: 700; }
.nap-line { margin: 0; color: var(--ink-soft); font-size: var(--step-0); line-height: 1.55; }
.nap-key { font-weight: 600; }
.nap-sep { margin-inline: var(--space-2); opacity: 0.5; }
/* The phone row is two links side by side and both must clear the tap floor,
   so the row gets the control height rather than the anchors getting padding
   that would break the inline text flow. */
.nap-phone a {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-min);
}


/* ── THE TAP FLOOR ON EVERY CONTACT / FOOTER LINK ───────────────────────────
   WCAG 2.2 AA (2.5.8) wants 24x24 for any target; 44 is the kit's primary-CTA
   floor and the rail already enforces it. The gap this closes is the ORDINARY
   link: a phone number, an email, a policy link inside a footer or a contact
   block is a bare text box, so it inherits its line-height and lands at
   15-20px — measured on EVERY theme (naya 20, metha 17, elpanero 15). Each
   theme had styled the LABEL beside the link and left the link itself alone.

   `:where()` keeps specificity at ZERO, so a theme's own rule always wins:
   this is a floor, not an opinion, and a theme wanting a taller or differently
   shaped target gets it with no !important war.

   IT IS A HEIGHT, NOT PADDING. Padding on an inline anchor inside running text
   overlaps the line above it; inline-flex + min-height grows the box within
   its own line instead. */
:where(.info, .contact-item, .nap-item, .legal-links, .footer-meta, footer, .footer) a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

/* ── THE RAIL SUPERSEDES THE THEME'S OWN HERO BUTTONS ON A PHONE ────────────
   Every theme shipped its own hero action row before the rail existed, and on
   a phone the two now say the same thing twice: metha renders `أرسل استفساراً`
   as a theme button AND as the rail's flow tile (identical label, stacked);
   tondro's `تواصل مع توندرو` and the rail's `واتساب` are the same wa.me link;
   naya's `احجزي موعدك` and the rail's `احجز` are the same /book path. The
   landing contract's own rule is "never two same-intent CTAs".

   THE RAIL WINS, NOT THE BUTTONS. It is a strict superset: it carries `tel:`,
   which no theme's button row ever had, and every item is a plain anchor.

   `:has(+ .cta-rail)` keys on the RELATIONSHIP, not on a company or a theme —
   a hero that has no rail beneath it keeps its buttons untouched, so a company
   with no declared contact (which renders no rail) loses nothing. Baseline in
   every engine we target; an engine without `:has` simply keeps both rows,
   which is today's behaviour, so the degrade is to no-change.

   PHONE ONLY. On a laptop the fold is not scarce and the theme's longer labels
   ("Talk to Tondro", "Book your appointment") carry more meaning than the
   rail's compact ones, so both rows stay. */
@media (max-width: 900px) {
  .hero-actions:has(+ .cta-rail),
  .cta-row:has(+ .cta-rail) {
    display: none;
  }
}