
/* Instrument Serif is not bundled with the app; pull it in from the same
   Google Fonts host the site already uses for Inter and Tajawal. */
@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&display=swap');
/* ─────────── Ceramica Market shared styles ─────────── */
:root {
  /* ONE token block — the single colour authority for the public site. A second
     :root lower in this file used to redefine --line/--bg with different
     values; the two fought. These are the final editorial values. */
  --green: #222759;
  --green-deep: #1B1F4A;
  --green-darker: #11143A;
  --green-soft: #E9EAF3;
  --green-tint: #F4F5FA;
  --ink: #15183A;
  --ink-2: #232757;
  --ink-soft: #51556E;
  --line: #DCDEE8;           /* warm hairline */
  --line-strong: #C2C6D6;
  --bg: #F8F9FC;             /* "paper" */
  --bg-2: #EEF0F6;           /* "sand" */
  --gold: #D9A02A;
  /* Form/error family — one definition; templates must not restate the hexes. */
  --error: #ef4444;
  --error-ink: #991b1b;
  --error-bg: #fee2e2;
  /* Editorial shape: content surfaces (cards, panels, media, form boxes) sit on
     near-square 2px corners; only genuine controls (buttons, pills, dots,
     avatars) keep 999px/50%. */
  --radius-layout: 2px;
  --radius-cell: 4px;        /* countdown cells and other small tiles */
  --radius-input: 8px;       /* form inputs, small framed boxes */
  --radius-modal: 14px;      /* the modal sheet */
  /* Admin-selectable fonts (Typography panel). Overridden by the injected #cx-fonts block;
     html[dir="rtl"] gets the Arabic stacks. Defaults match the original look. */
  --font-head: 'Inter', system-ui, sans-serif;
  --font-body: 'Tajawal', system-ui, sans-serif;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  /* Keep anchor targets clear of the floating glass nav */
  scroll-padding-top: 88px;
  /* Stop non-Chrome mobile browsers (Mi, Samsung Internet, Firefox) from auto-
     inflating text, which blows the layout wider than the viewport and clips the
     right edge. Keeps rendering identical to Chrome on Android. */
  -webkit-text-size-adjust: 100%;
  -moz-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Clip horizontal overflow at the viewport root too, so no white gutter can
     appear. `clip` (not `hidden`) keeps the sticky nav working. */
  overflow-x: clip;
}
body {
  font-family: var(--font-body, 'Tajawal', system-ui, sans-serif);
  background: var(--bg);
  color: var(--ink);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Contain horizontal overflow from scroll-reveal transforms (translateX ±40px)
     so the page never scrolls/clips sideways. `clip` (not `hidden`) is used on
     purpose — it doesn't create a scroll container, so the sticky nav still works. */
  overflow-x: clip;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; border: none; background: none; }

.container { max-width: 1280px; margin: 0 auto; padding: 0 clamp(20px, 4vw, 48px); }

/* ─── Logo (Ceramica Market logo image) ─── */
.logo-img {
  height: clamp(36px, 3.2vw, 42px);
  width: auto;
  display: block;
  /* The global img{max-width:100%} inside the logo's auto-sized grid cell is a
     circular constraint: the cell wants the image's width, the image wants the
     cell's. Desktop happens to resolve it; on mobile the wordmark collapsed or
     squashed. The logo is 118px wide and can never overflow anything. */
  max-width: none;
}
/* logo-black.png is cropped tight (181x41 glyph) while logo-white.png has
   padding (156x37 glyph in 161x41) — shrink the black one so both render
   the wordmark at the same visual size. */
.logo-img-dark { height: calc(clamp(36px, 3.2vw, 42px) * .883); }
/* Both logos stack in the same grid cell and crossfade — a display: switch
   can't animate. On home the white one shows over the hero, then fades to
   the black one once scrolled past it. */
.logo .logo-img { grid-area: 1 / 1; justify-self: start; transition: opacity .35s ease; }
.logo-img-light { opacity: 0; }
body.nav-over-hero:not(.nav-scrolled) .logo-img-light { opacity: 1; }
body.nav-over-hero:not(.nav-scrolled) .logo-img-dark { opacity: 0; }

.logo {
  display: inline-grid;
  align-items: center;
  text-decoration: none;
}
.logo-mark {
  width: 44px; height: 44px;
  border: 2.5px solid var(--ink);
  border-radius: 50%;
  display: grid;
  place-items: center;
  position: relative;
  flex-shrink: 0;
}
.logo-mark::before {
  content: '';
  width: 8px; height: 8px;
  background: var(--ink);
  border-radius: 50%;
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
}
.logo-mark::after {
  content: '';
  width: 14px;
  height: 22px;
  border: 2.5px solid var(--ink);
  border-bottom: none;
  border-radius: 14px 14px 0 0;
  position: absolute;
  top: 4px;
  left: 50%;
  transform: translateX(-50%);
}
.logo-text {
  font-family: 'Inter', sans-serif;
  font-weight: 900;
  font-size: 26px;
  letter-spacing: -0.04em;
  color: var(--ink);
  line-height: 1;
}
.logo-text em {
  font-style: normal;
  /* nothing — kept simple */
}

/* ─── Nav — floating Apple-style liquid-glass bar ───
   Structure: .nav (invisible sticky wrapper, keeps its flow space so pages
   don't shift) > .container > .nav-pill (the glass capsule).
   Glass = 3 layers: ::before carries the backdrop blur/saturation (and, on
   Chromium, the SVG refraction filter — Safari/Firefox can't run SVG filters
   in backdrop-filter, so they keep the frosted fallback), the pill's own
   translucent background is the tint, ::after paints the specular rim. */
.nav {
  /* --p: 0 at the very top of the page (a flat, clear bar), 1 once scrolled ~120px (the
     floating glass pill). partials.js sets it from the scroll position every frame, so the
     bar morphs with the finger instead of snapping. Without JS it stays a pill. */
  --p: 1;
  position: sticky;
  top: 0;
  z-index: 80;
  padding-top: calc(var(--p) * 12px);
  pointer-events: none; /* wrapper spans full width; only the pill catches clicks */
}
.nav-pill, .nav-drawer { pointer-events: auto; }
.lg-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

.nav-pill {
  position: relative;
  isolation: isolate;
  border-radius: calc(var(--p) * 40px);
  /* at the top it reaches past the container gutter, like a full-width bar */
  margin-inline: calc((1 - var(--p)) * -12px);
  /* Smoky tint so the glass stays visible against white sections */
  background: rgba(58,64,72, calc(var(--p) * 0.28));
  border: 1px solid rgba(255,255,255, calc(var(--p) * 0.45));
  box-shadow:
    0 12px 32px rgba(26,24,18, calc(var(--p) * 0.18)),
    0 2px 8px rgba(26,24,18, calc(var(--p) * 0.09));
  transition: background-color .2s linear, border-color .2s linear, box-shadow .2s linear;
}
.nav-pill::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: 0;
  -webkit-backdrop-filter: blur(20px) saturate(1.8);
  backdrop-filter: blur(20px) saturate(1.8);
  opacity: var(--p);   /* the frosting fades in with the scroll */
}
html.lg-svg .nav-pill::before {
  backdrop-filter: url(#liquid-glass-nav);
}
.nav-pill::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 2;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.85),
    inset 0 14px 28px -18px rgba(255,255,255,0.9),
    inset 0 -1px 0 rgba(255,255,255,0.28);
  opacity: var(--p);
  transition: box-shadow .35s ease;
}
/* An open mobile menu always sits on the full pill. */
.nav:has(.nav-drawer.open) { --p: 1 !important; }

.nav-inner {
  position: relative;
  z-index: 3;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 28px;
  padding-block: 8px;
  padding-inline: 22px 10px;
}
.nav-links {
  display: flex;
  gap: 6px;
  justify-content: center;
  font-size: 15px;
  font-weight: 500;
}
.nav-links a {
  color: var(--ink-soft);
  padding: 8px 14px;
  border-radius: 999px;
  transition: color .2s, background-color .2s;
}
.nav-links a:hover { color: var(--ink); background: rgba(26,24,18,0.05); }
.nav-links a.active {
  color: var(--ink);
  font-weight: 700;
  background: rgba(255,255,255,0.7);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), 0 1px 4px rgba(26,24,18,0.08);
}
.nav-actions { display: flex; gap: 10px; align-items: center; }

/* Buttons inside the glass chrome become liquid-glass chips themselves:
   translucent tint + their own backdrop blur + specular top edge. */
.nav-pill .btn,
.nav-drawer .btn,
.nav-pill .lang-toggle {
  border-radius: 999px;
  -webkit-backdrop-filter: blur(12px) saturate(1.6);
  backdrop-filter: blur(12px) saturate(1.6);
  transition: background-color .3s ease, border-color .3s ease, color .3s ease, box-shadow .3s ease;
}
.nav-pill .btn-outline,
.nav-drawer .btn-outline {
  border: 1px solid rgba(26,24,18,0.1);
  color: var(--ink);
  background: rgba(255,255,255,0.45);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.8), 0 2px 8px rgba(26,24,18,0.06);
}
.nav-pill .btn-outline:hover,
.nav-drawer .btn-outline:hover {
  background: rgba(255,255,255,0.75);
  color: var(--ink);
}
.nav-pill .btn-green,
.nav-drawer .btn-green {
  background: rgba(34,39,89,0.78);
  border: 1px solid rgba(255,255,255,0.4);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 0 4px 14px rgba(34,39,89,0.3);
}
.nav-pill .btn-green:hover,
.nav-drawer .btn-green:hover { background: rgba(27,31,74,0.88); }
.nav-pill .lang-toggle {
  border: 1px solid rgba(34,39,89,0.35);
  background: rgba(255,255,255,0.4);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.7);
}
/* hover feedback only where a real pointer exists — on touch, :hover sticks
   after a tap (the toggle stayed solid green after switching language) */
@media (hover: hover) {
  .nav-pill .lang-toggle:hover {
    background: rgba(34,39,89,0.8);
    color: #fff;
  }
  .nav-burger:hover { background: rgba(26,24,18,0.06); }
}

/* On home, while over the dark hero: clear dark glass + white text.
   .nav-scrolled (toggled in partials.js) switches back to the light glass. */
body.nav-over-hero:not(.nav-scrolled) .nav-pill {
  background: rgba(14,16,18, calc(var(--p) * 0.32));
  border-color: rgba(255,255,255, calc(var(--p) * 0.18));
  box-shadow: 0 12px 32px rgba(0,0,0, calc(var(--p) * 0.35));
}
body.nav-over-hero:not(.nav-scrolled) .nav-pill::after {
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.3),
    inset 0 14px 28px -18px rgba(255,255,255,0.28),
    inset 0 -1px 0 rgba(255,255,255,0.08);
}
body.nav-over-hero:not(.nav-scrolled) .nav-links a { color: rgba(255,255,255,0.78); }
body.nav-over-hero:not(.nav-scrolled) .nav-links a:hover {
  color: #fff;
  background: rgba(255,255,255,0.12);
}
body.nav-over-hero:not(.nav-scrolled) .nav-links a.active {
  color: #fff;
  background: rgba(255,255,255,0.18);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.25);
}
body.nav-over-hero:not(.nav-scrolled) .nav-pill .btn-outline {
  border-color: rgba(255,255,255,0.28);
  color: #fff;
  background: rgba(255,255,255,0.12);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3);
}
body.nav-over-hero:not(.nav-scrolled) .nav-pill .btn-outline:hover {
  background: rgba(255,255,255,0.24);
  color: #fff;
}
/* the .in-nav variant outweighs the same rule injected later by i18n.js, so
   the toggle keeps the pill's glass idiom over the hero too */
body.nav-over-hero:not(.nav-scrolled) .nav-pill .lang-toggle,
body.nav-over-hero:not(.nav-scrolled) .nav-pill .lang-toggle.in-nav {
  border-color: rgba(255,255,255,0.28);
  background: rgba(255,255,255,0.12);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.25);
}
@media (hover: hover) {
  body.nav-over-hero:not(.nav-scrolled) .nav-burger:hover { background: rgba(255,255,255,0.12); }
}
/* i18n.js injects its own over-hero :hover for the toggle after this file;
   on touch that sticks after a tap — pin the resting look back down */
@media (hover: none) {
  body.nav-over-hero:not(.nav-scrolled) .nav-pill .lang-toggle.in-nav:hover {
    background: rgba(255,255,255,0.12);
    color: rgba(255,255,255,0.85);
  }
}
/* Pull hero up under the floating bar (12px gap + ~60px pill) */
body.nav-over-hero .hero { margin-top: -72px; padding-top: 72px; }

/* Mobile hamburger button (visible only on ≤720px) */
.nav-burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 999px;
  cursor: pointer;
}
.nav-burger span {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform .2s ease, opacity .2s ease, background-color .2s ease;
}
body.nav-over-hero:not(.nav-scrolled) .nav-burger span { background: #fff; }
.nav-burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Mobile drawer — floating glass panel below the pill */
.nav-drawer {
  display: none;
  position: absolute;
  top: calc(100% + 10px);
  left: clamp(20px, 4vw, 48px);
  right: clamp(20px, 4vw, 48px);
  border-radius: 24px;
  background: rgba(255,255,255,0.78);
  -webkit-backdrop-filter: blur(24px) saturate(1.8);
  backdrop-filter: blur(24px) saturate(1.8);
  border: 1px solid rgba(255,255,255,0.65);
  box-shadow:
    0 24px 60px rgba(26,24,18,0.25),
    inset 0 1px 0 rgba(255,255,255,0.9);
  padding: 6px 20px 18px;
  flex-direction: column;
  z-index: 60;
}
.nav-drawer.open { display: flex; }
.nav-drawer > a {
  color: var(--ink);
  font-weight: 600;
  font-size: 15px;
  padding: 14px 4px;
  border-bottom: 1px solid var(--line);
}
.nav-drawer > a.active { color: var(--green); }
.nav-drawer-actions {
  display: flex;
  gap: 10px;
  margin-top: 14px;
}
.nav-drawer-actions .btn { flex: 1; padding: 12px 14px; }
.lang-toggle {
  padding: 8px 12px;
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: 999px;
}

/* ─── Buttons ─── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 24px;
  border-radius: 999px; /* pill — matches the liquid-glass nav family */
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  transition: all 0.2s;
  white-space: nowrap;
  cursor: pointer;
}
.btn-green { background: var(--green); color: white; }
.btn-green:hover { background: var(--green-deep); }
.btn-dark { background: var(--ink); color: white; }
.btn-dark:hover { background: var(--ink-2); }
.btn-outline { border: 1.5px solid var(--ink); color: var(--ink); background: transparent; }
.btn-outline:hover { background: var(--ink); color: white; }
.btn-outline-light { border: 1.5px solid white; color: white; background: transparent; }
.btn-outline-light:hover { background: white; color: var(--ink); }
.btn-outline-green { border: 1.5px solid var(--green); color: var(--green); background: white; }
.btn-outline-green:hover { background: var(--green); color: white; }
.btn-lg { padding: 16px 32px; font-size: 15px; }

/* ─── Page heading block (used on inner pages) ─── */
.page-head {
  padding: clamp(48px, 6vw, 80px) 0 clamp(32px, 4vw, 48px);
  border-bottom: 1px solid var(--line);
  background: var(--bg-2);
}
.page-head h1 {
  font-size: clamp(32px, 4.5vw, 56px);
  font-weight: 900;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--ink);
  margin-bottom: 12px;
}
.page-head h1 .green { color: var(--green); }
.page-head p {
  font-size: 17px;
  color: var(--ink-soft);
  max-width: 640px;
  line-height: 1.7;
}
.crumbs {
  display: flex;
  gap: 8px;
  font-size: 13px;
  color: var(--ink-soft);
  margin-bottom: 20px;
  font-weight: 500;
}
.crumbs a:hover { color: var(--green); }
.crumbs span { opacity: 0.4; }

/* ─── Common section spacing ─── */
section.pad { padding: clamp(56px, 8vw, 100px) 0; }
.section-eyebrow {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--green);
  text-transform: uppercase;
  margin-bottom: 14px;
}
.section-title {
  font-size: clamp(32px, 4.4vw, 56px);
  font-weight: 900;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin-bottom: 18px;
}
.section-title .green { color: var(--green); }
.section-sub {
  font-size: 17px;
  color: var(--ink-soft);
  max-width: 600px;
  line-height: 1.75;
}

/* ─── Footer (shared, dark) ─── */
.site-footer {
  background: var(--ink);
  color: white;
  padding: 64px 0 28px;
  margin-top: clamp(60px, 8vw, 100px);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 56px;
  padding-bottom: 36px;
  border-bottom: 1px solid rgba(255,255,255,0.1);
}
.site-footer h3, .site-footer h4 {
  font-size: 14px;
  font-weight: 700;
  color: var(--green);
  margin-bottom: 18px;
}
.site-footer ul { list-style: none; display: flex; flex-direction: column; gap: 11px; }
.site-footer ul a, .site-footer .item {
  color: rgba(255,255,255,0.75);
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  transition: color 0.2s;
}
.site-footer ul a:hover { color: white; }
.site-footer .item .ico {
  width: 16px; height: 16px;
  color: var(--green);
  flex-shrink: 0;
}
.site-footer .social-links {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 10px;
}
.site-footer .social-link {
  min-height: 44px;
  padding: 10px 16px;
  border: 1px solid rgba(34,39,89,0.55);
  border-radius: 999px;
  background: rgba(34,39,89,0.1);
  color: rgba(255,255,255,0.92);
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  transition: background-color 0.2s, border-color 0.2s, color 0.2s, transform 0.2s;
}
.site-footer .social-link:hover {
  background: var(--green);
  border-color: var(--green);
  color: var(--ink);
  transform: translateY(-1px);
}
.site-footer .social-link:hover .ico { color: var(--ink); }
.site-footer .social-link:active { transform: translateY(1px); }
.site-footer .social-link:focus-visible {
  outline: 2px solid white;
  outline-offset: 3px;
}
.footer-meta {
  display: flex;
  justify-content: space-between;
  margin-top: 24px;
  font-size: 12px;
  color: rgba(255,255,255,0.5);
  flex-wrap: wrap;
  gap: 8px;
}

/* ─── Modal (shared) ─── */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.55);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 24px;
  backdrop-filter: blur(4px);
}
.modal-backdrop.open { display: flex; }
.modal {
  background: white;
  border-radius: var(--radius-layout);
  width: 100%;
  max-width: 920px;
  max-height: 92vh;
  overflow-y: auto;
  padding: 36px 40px;
  position: relative;
  box-shadow: 0 30px 80px rgba(0,0,0,0.3);
}
.modal-close {
  position: absolute;
  top: 22px;
  right: 22px;
  width: 32px; height: 32px;
  display: grid;
  place-items: center;
  color: var(--green);
  font-size: 24px;
  font-weight: 300;
  border-radius: 50%;
}
.modal-close:hover { background: var(--green-soft); }
.modal h2 {
  font-size: 22px;
  font-weight: 800;
  color: var(--ink);
  margin-bottom: 4px;
}
.modal .modal-sub {
  font-size: 14px;
  color: var(--ink-soft);
  margin-bottom: 28px;
}
body[dir="rtl"] .modal-close { right: auto; left: 22px; }

/* form */
.form-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  margin-bottom: 22px;
}
.field label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 8px;
}
.field label .req { color: #e11d48; }
.field input, .field textarea, .field select {
  width: 100%;
  padding: 12px 14px;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-layout);
  font: inherit;
  font-size: 14px;
  color: var(--ink);
  background: white;
  transition: border-color 0.2s;
}
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--green);
}
.field input.filled { border-color: var(--green); }
.field textarea { resize: vertical; min-height: 100px; }
.field-block { margin-bottom: 22px; }
.field-block > label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 12px;
}
.checks {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px 24px;
}
.check {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  font-size: 14px;
  color: var(--ink);
}
.check input { display: none; }
.check .box {
  width: 18px; height: 18px;
  border: 1.5px solid var(--line-strong);
  border-radius: 4px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  transition: all 0.15s;
}
.check input:checked + .box {
  background: var(--green);
  border-color: var(--green);
}
.check input:checked + .box::after {
  content: '';
  width: 5px;
  height: 9px;
  border-right: 2px solid white;
  border-bottom: 2px solid white;
  transform: rotate(45deg);
  margin-bottom: 2px;
}
.modal-actions {
  display: flex;
  gap: 12px;
  margin-top: 8px;
}
.btn-submit { background: var(--green); color: white; }
.btn-cancel { border: 1.5px solid var(--green); color: var(--green); background: white; }

@media (max-width: 720px) {
  .nav { padding-top: 10px; }
  /* Links are hidden, so drop to 2 columns and pin the actions (lang toggle +
     burger) to the end edge — auto-placement would leave them mid-pill. */
  .nav-inner { grid-template-columns: auto 1fr; gap: 14px; padding-block: 8px; padding-inline: 16px 8px; }
  .nav-actions { justify-self: end; }
  .nav-links { display: none; }
  /* Register button moves into the drawer on mobile; lang toggle stays.
     Specificity must beat `body a.btn.btn-register{display:inline-flex}` (0-2-2)
     from the register-CTA restyle below, or the button comes back and overflows the pill. */
  body .nav-actions .btn.nav-btn { display: none; }
  .nav-burger { display: inline-flex; }
  .form-row, .checks { grid-template-columns: 1fr 1fr; }
  .footer-grid { grid-template-columns: 1fr; gap: 32px; }
  .modal { padding: 28px 22px; }
}

/* Users who opt out of transparency get a near-solid bar instead of glass */
@media (prefers-reduced-transparency: reduce) {
  .nav-pill::before { -webkit-backdrop-filter: none; backdrop-filter: none; }
  html.lg-svg .nav-pill::before { backdrop-filter: none; }
  .nav-pill { background: rgba(255,255,255,0.96); }
  .nav-pill .btn, .nav-drawer .btn, .nav-pill .lang-toggle {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .nav-pill .btn-green, .nav-drawer .btn-green { background: var(--green); }
  .nav-drawer {
    background: rgba(255,255,255,0.97);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body.nav-over-hero:not(.nav-scrolled) .nav-pill { background: rgba(16,18,20,0.93); }
}

/* Admin Typography panel: generic headings follow --font-head. Page-specific heading rules
   (e.g. .hero-headline h1) have higher specificity and keep their bespoke fonts. */
h1, h2, h3, h4, h5, h6 { font-family: var(--font-head, 'Inter', system-ui, sans-serif); }

/* Section-reorder wrapper: a flex column so the editor's saved CSS `order` takes effect while the
   sections still stack full-width exactly as before. */
.cx-flow { display: flex; flex-direction: column; }


/* ==========================================================================
   HOMEX — "Editorial" design system applied to the LIVE site's own layout.

   This file is appended to the real styles.css. It changes nothing structural:
   no markup, no class names, no data-cx-* hooks, no Thymeleaf. It is purely a
   re-skin, which is exactly the shape a real merge would take.

   Everything below is either a token override or a restyle of a selector that
   already exists in styles.css.
   ========================================================================== */

/* ------------------------------------------------------------------ 1. TOKENS
   Consolidated into the single :root at the top of this file — one colour
   authority. (--green-bright is gone: the on-dark accent is --green-on-dark,
   mixed from --green so admin accent changes carry through. #3BA935 fails AA
   at ~2.9:1 wherever white text sits on it.) */

/* ------------------------------------------------------------- 2. TYPOGRAPHY
   Instrument Serif is Latin-only, so it is introduced through --font-head and
   immediately withdrawn for RTL. Arabic keeps Tajawal. The admin Typography
   panel still wins, because it injects #cx-fonts AFTER this file. */
:root{
  --font-head: 'Instrument Serif', Georgia, 'Times New Roman', serif;
  --font-body: 'Inter', system-ui, sans-serif;
}
html[dir="rtl"]{
  --font-head: 'Tajawal', system-ui, sans-serif;   /* no Arabic glyphs in the serif */
  --font-body: 'Tajawal', system-ui, sans-serif;
}

.hero-headline,
.section-title,
.page-head h1,
h1, h2{
  font-family: var(--font-head);
  font-weight: 400;
  letter-spacing: -0.015em;
  line-height: 1.04;
}
html[dir="rtl"] .hero-headline,
html[dir="rtl"] .section-title,
html[dir="rtl"] h1,
html[dir="rtl"] h2{ font-weight: 700; letter-spacing: 0; line-height: 1.25; }

/* the three-step rhythm: eyebrow / headline / body */
.section-eyebrow{
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--green);
}
.section-sub{
  font-family: var(--font-body);
  color: var(--ink-soft);
  max-width: 64ch;
  line-height: 1.62;
}

/* ------------------------------------------------------------------ 3. SHAPE
   Interactive elements become pills; containers keep soft corners; brand
   lockups stay hard-cornered. */
.btn, .btn-lg, .btn-submit, .nav-pill, .nav-btn, .lang-toggle{
  border-radius: 999px !important;
  font-family: var(--font-body);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-size: 12px;
  transition: transform .3s cubic-bezier(.22,1,.36,1),
              background-color .3s ease, box-shadow .3s ease, border-color .3s ease;
}
.btn-green{ background: var(--green); color: #fff; }
.btn-green:hover{
  background: #2F8B2B;
  transform: translateY(-1px);
  box-shadow: 0 12px 28px -12px rgba(34,39,89,.75);
}
.btn-dark{ background: var(--ink); color: #fff; }
.btn-dark:hover{ background: #2A261D; transform: translateY(-1px); }
.btn-outline, .btn-outline-green{
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
}
.btn-outline:hover, .btn-outline-green:hover{ border-color: var(--ink); }
.btn-outline-light{ border: 1px solid rgba(255,255,255,.4); color: #fff; }
.btn-outline-light:hover{ background: #fff; color: var(--ink); border-color: #fff; }

/* ------------------------------------------------------------- 4. STRUCTURE
   Depth via tonal layers and hairlines rather than shadows. */
/* NAV — deliberately left alone.
   `.nav` is a full-width TRANSPARENT wrapper with pointer-events:none; the
   visible bar is the floating `.nav-pill`. An earlier pass put
   `border-bottom` and a background on `.nav`, which drew a hairline straight
   across the viewport either side of the pill — the "extended lines". Worse,
   `.nav-scrolled` is a class on <body>, so styling it painted the whole page.
   The pill already has a tuned liquid-glass treatment and its own
   over-hero / scrolled states; the token swap recolours it for free.
   Only the link typeface is touched. */
.nav-links a{ font-family: var(--font-body); font-weight: 500; letter-spacing: .01em; }

/* .field and .field-block are layout wrappers around a label and its control,
   not cards. Rounding and bordering them drew a second box around every input,
   with the label sitting inside it like a fieldset legend — visible on every
   form on the site. Only the actual cards get the treatment. */
.card, .modal{
  border-radius: var(--radius-layout);
  border: 1px solid var(--line);
}
input, select, textarea{
  border-radius: var(--radius-layout) !important;
  background: var(--bg-2);
  border: 1px solid var(--line);
  font-family: var(--font-body);
}
input:focus, select:focus, textarea:focus{
  outline: none;
  border-color: var(--green);
  background: var(--bg);
}

/* Section rhythm.
   DO NOT use `section:nth-of-type(...)` here. It has specificity 0,1,1, which
   outranks a plain class like `.voices` (0,1,0) — that silently repainted a
   deliberately dark section as paper while its `color:white` stayed, leaving
   white text on a near-white field. The token changes above already re-tone
   every section that derives from --bg/--bg-2, so no blanket rule is needed.
   Anything that needs sand gets it by opting in, never by position. */
.section-sand,
[data-cx-item="fields"],
[data-cx-item="partners"]{ background: var(--bg-2); }

/* Sections that set their own dark field keep it, and get the warm ink.
   Listed explicitly so nothing is restyled by accident. */
.voices,
.stat-band{ background: var(--ink); color: #fff; }
.voices .section-title, .voices h2, .voices h3, .voices blockquote, .voices p,
.stat-band .section-title, .stat-band h2, .stat-band h3,
.stat-band .stat-num, .stat-band b, .stat-band strong{ color: #fff; }
.voices .section-eyebrow,
.stat-band .section-eyebrow{ color: var(--green-on-dark); }
.voices .section-sub, .voices figcaption, .voices cite,
.stat-band .section-sub, .stat-band small, .stat-band em{ color: rgba(255,255,255,.72); }

/* ------------------------------------------------------- 4b. BAKED-IN EMERALD
   The old #222759 is written into these gradients as rgba(34,39,89,…), so
   the --green token cannot reach it — this is why the page still read mint
   after the palette swap. Each is restated in the brand greens:
       #222759 = rgb(0,110,11)    #003502 = rgb(0,53,2)
       #3BA935 = rgb(59,169,53)                                            */
.closing{ background: var(--green); }
.closing::after{
  background: linear-gradient(135deg, rgba(34,39,89,.96) 0%, rgba(17,20,58,.94) 100%) !important;
}
.stat-band::before{
  background:
    radial-gradient(circle at 15% 30%, color-mix(in srgb, var(--green-on-dark) 20%, transparent), transparent 50%),
    radial-gradient(circle at 85% 70%, color-mix(in srgb, var(--green-on-dark) 10%, transparent), transparent 55%) !important;
}
.cd-cell::after{
  background: linear-gradient(120deg, transparent 30%, color-mix(in srgb, var(--green-on-dark) 18%, transparent) 50%, transparent 70%) !important;
}
.discover-img::before{
  background:
    radial-gradient(circle at 30% 30%, color-mix(in srgb, var(--green-on-dark) 18%, transparent), transparent 60%),
    linear-gradient(135deg, color-mix(in srgb, var(--green-darker) 55%, var(--ink)) 0%, color-mix(in srgb, var(--green-darker) 30%, #000) 100%) !important;   /* was teal-black */
}

/* ------------------------------------------------------------------ 5. FOOTER */
.site-footer{
  background: var(--ink);
  color: rgba(255,255,255,.78);
  border-top: none;
}
.site-footer a{ color: rgba(255,255,255,.82); }
.site-footer a:hover{ color: var(--green-on-dark); }
.footer-meta{ color: rgba(255,255,255,.45); }

/* ------------------------------------------------------------------ 6. DETAIL */
::selection{ background: var(--green-on-dark); color: var(--ink); }
.crumbs{ font-family: var(--font-body); font-size: 12px; letter-spacing: .12em;
         text-transform: uppercase; color: var(--ink-soft); }
.logo-text{ font-family: var(--font-head); letter-spacing: -.01em; }
hr{ border: none; border-top: 1px solid var(--line); }


/* ==========================================================================
   ADMIN — the same design system, applied to the back office.

   All 18 admin templates load /styles.css, and the admin markup already draws
   on the shared tokens (.side uses var(--ink), .panel borders use var(--line),
   .btn-ghost uses var(--bg-2)). So the palette lands on its own; what is left
   is the handful of values hardcoded in each page's own <style> block.

   SPECIFICITY: those page-level <style> blocks are parsed AFTER this file, so
   a bare `.panel` here would lose. Everything below is scoped under
   `.admin-shell` (0,2,0) to outrank the page rule (0,1,0) without !important.

   TYPOGRAPHY: the display serif is deliberately NOT applied to admin tables,
   forms or body copy. Instrument Serif is a display face — at 13px in a dense
   data grid it costs legibility for nothing. Admin keeps Inter and takes the
   serif only on page titles, where it signals "same product".
   ========================================================================== */

/* --- surfaces: paper, not pure white ------------------------------------- */
.admin-shell .panel,
.admin-shell .stat-card,
.admin-shell .ap-card{
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: none;
}
.admin-shell .main{ background: var(--bg-2); }

/* --- sidebar: warm ink, brand-green active state -------------------------- */
.admin-shell .side{ background: var(--ink); border-right: 1px solid rgba(255,255,255,.10); }
.admin-shell .side a{ color: rgba(255,255,255,.74); border-radius: 999px; }
.admin-shell .side a:hover{ color: #fff; background: rgba(255,255,255,.07); }
.admin-shell .side a.active,
.admin-shell .side a[aria-current="page"]{ color: var(--green-on-dark); background: rgba(255,255,255,.09); }

/* --- page titles carry the brand voice ------------------------------------ */
.admin-shell .page-h h1,
.admin-shell .page-h h2{
  font-family: var(--font-head);
  font-weight: 400;
  letter-spacing: -.015em;
  line-height: 1.06;
}
html[dir="rtl"] .admin-shell .page-h h1,
html[dir="rtl"] .admin-shell .page-h h2{
  font-family: 'Tajawal', system-ui, sans-serif; font-weight: 700; letter-spacing: 0;
}
.admin-shell .panel-h h2,
.admin-shell .panel-h h3{
  font-family: var(--font-body);
  font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft);
}

/* --- data tables ---------------------------------------------------------- */
.admin-shell table{ border-color: var(--line); }
.admin-shell th{
  font-family: var(--font-body);
  font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-soft);
  background: var(--bg-2);
  border-bottom: 1px solid var(--line);
}
.admin-shell td{ border-bottom: 1px solid var(--line); }
.admin-shell tbody tr:hover{ background: var(--green-tint); }

/* --- controls match the public site --------------------------------------- */
.admin-shell .btn-add,
.admin-shell .btn-ghost,
.admin-shell .btn-sm{
  border-radius: 999px;
  font-family: var(--font-body);
  font-weight: 700; font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  transition: background-color .3s ease, transform .3s cubic-bezier(.22,1,.36,1);
}
.admin-shell .btn-add{ background: var(--green); color: #fff; }
.admin-shell .btn-add:hover{ background: #2F8B2B; transform: translateY(-1px); }
.admin-shell .btn-ghost{ background: var(--bg-2); color: var(--ink); border: 1px solid var(--line); }
.admin-shell .btn-ghost:hover{ border-color: var(--ink); }

.admin-shell input,
.admin-shell select,
.admin-shell textarea{
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  font-family: var(--font-body);
}
.admin-shell input:focus,
.admin-shell select:focus,
.admin-shell textarea:focus{
  outline: none; border-color: var(--green); background: var(--bg);
}

/* --- status pills.
   The red/amber semantics in the page blocks are left alone on purpose: they
   carry meaning (rejected / pending), not brand. Only the neutral pill moves. */
.admin-shell .pill{
  font-family: var(--font-body);
  letter-spacing: .12em; text-transform: uppercase; font-size: 10px;
}

/* --- login: the first screen anyone sees ---------------------------------- */
body:has(.login-card){ background: var(--bg-2); }
.login-card{ background: var(--bg); border: 1px solid var(--line); border-radius: 18px; }


/* ==========================================================================
   EMERALD SWEEP — every hardcoded #222759 the --green token cannot reach.

   The old emerald is written into 52 places as rgba(34,39,89,…) or as a
   literal hex, so swapping the token misses all of them. Each rule below
   restates one of those, in the brand greens, at the same specificity plus
   one (or via a later @keyframes / same-selector redeclaration, which wins
   on order alone).

       #222759 = rgb(0,110,11)     deep — anything under white text
       #3BA935 = rgb(59,169,53)    logo — accents, glows, rings
       #003502 = rgb(0,53,2)       darkest — gradient ends

   Page-level <style> blocks parse AFTER this file, so rules that must beat
   them are scoped one level deeper rather than marked !important. Rules that
   only need to beat styles.css (same file, earlier) need nothing extra.
   ========================================================================== */

/* ---------------------------------------------------- index.html: keyframes
   `@keyframes pulseGreen` lives in index.html's own <style>, which parses
   AFTER this file — so redeclaring the same name loses on order. Instead we
   define a new set of frames and repoint the one rule that uses it. Beating
   `.hm-cta .btn-green` (0,2,0) needs one more class, hence the body scope. */
@keyframes pulseBrand{
  0%,100%{ box-shadow: 0 0 0 0 rgba(59,169,53,.5); }
  50%    { box-shadow: 0 0 0 14px rgba(59,169,53,0); }
}
body .hm-cta .btn-green{ animation: pulseBrand 2.6s ease-in-out infinite; }

/* ------------------------------------------------ index.html: tints & glows */
body .voice-item.active { background: rgba(59,169,53,.08); border-color: var(--green); }
body .stat-band .sb:hover { background: rgba(59,169,53,.08); }
body .discover-img .browser-frame {
  box-shadow: 0 30px 80px rgba(0,0,0,.4), 0 12px 30px rgba(34,39,89,.18);
}

/* ------------------------------------------------------ login.html: the art
   A photographic panel under a green wash — the wash carries white type, so
   it uses the deep green, not the bright logo green. */
body .auth-art {
  background-image:
    linear-gradient(135deg, rgba(34,39,89,.88), rgba(17,20,58,.94)),
    url('/img/hero-exhibition.jpg');
  background-size: cover;
  background-position: center;
}

/* focus rings — login, exhibitor portal, and anything else using the pattern */
body .input-wrap input:focus,
body .phone-row select.dial-select:focus,
body .phone-row input:focus,
body .field input:focus,
body .field select:focus,
body .field textarea:focus {
  border-color: var(--green);
  outline: none;
  box-shadow: 0 0 0 4px rgba(59,169,53,.14);
}
body .otp-grid input:focus {
  background: var(--bg);
  border-color: var(--green);
  outline: none;
  box-shadow: 0 0 0 3px rgba(59,169,53,.18);
}

/* ------------------------------------------------------- campaign.html */
body .ma-bubble { box-shadow: 0 4px 18px rgba(34,39,89,.20); }

/* --------------------------------------------------- styles.css: nav chrome
   Same stylesheet, declared earlier — order alone is enough.
   NOTE the original groups `.nav-pill .btn-green` WITH `.nav-drawer .btn-green`.
   `.nav-pill .btn-green` is the visible CONTACT US pill in the header, so both
   halves of the selector must be restated — and so must box-shadow, or the
   emerald glow survives underneath a corrected background. */
body .nav-pill .btn-green,
body .nav-drawer .btn-green {
  background: rgba(34,39,89,.88);
  border: 1px solid rgba(255,255,255,.4);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 4px 14px rgba(34,39,89,.32);
}
body .nav-pill .btn-green:hover,
body .nav-drawer .btn-green:hover { background: rgba(27,31,74,.94); }

/* Same liquid-glass chip idiom as the .btn-outline pills beside it (the blur
   itself comes from the shared `.nav-pill .lang-toggle` backdrop-filter rule):
   translucent tint, neutral hairline, specular top edge — instead of the flat
   green-bordered pill that never read as part of the glass bar. */
body .nav-pill .lang-toggle {
  border: 1px solid rgba(26,24,18,.1);
  background: rgba(255,255,255,.45);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.8), 0 2px 8px rgba(26,24,18,.06);
}
/* hover only for real pointers — on touch the green fill stuck after a tap */
@media (hover: hover) {
  body .nav-pill .lang-toggle:hover { background: rgba(34,39,89,.85); color: #fff; }
}

/* ------------------------------------------- cx-editor: the inline editor UI
   cx-editor.css is a separate file loaded after styles.css, so these need the
   extra weight. Scoped to body.cx-editing / #cx-bar, which are already the
   editor's own roots — nothing here can leak into the public site. */
body #cx-bar button.cx-primary,
body #cx-bar .cx-lang button.cx-on,
body #cx-bar .cx-toggle input:checked + .cx-switch { background: var(--green) !important; }

body.cx-editing [data-cx-key]{ outline-color: rgba(59,169,53,.55) !important; }
body.cx-editing [data-cx-key]:hover{
  outline-color: var(--green) !important;
  background: rgba(59,169,53,.06) !important;
}
body.cx-editing [data-cx-key][contenteditable="true"],
body.cx-editing [data-cx-key].cx-active,
body.cx-editing [data-cx-item].cx-dragging{ outline-color: var(--green) !important; }
body.cx-editing [data-cx-item]:hover{ outline-color: var(--green) !important; }


/* ==========================================================================
   SECTION CONTRAST + THE EXHIBITOR SLIDER

   Two problems this file exists to solve.

   1. GREEN AS TEXT ON DARK.
      --green moved from #222759 (a bright emerald that reads fine on ink) to
      #222759 (a deep green chosen so WHITE TEXT ON IT passes AA). That trade
      inverts on dark sections: anything using var(--green) as a *foreground*
      colour over .voices is now nearly invisible — the eyebrow, the quote
      mark, the slide counter. On dark fields those switch to --green-on-dark.
      Rule of thumb for this palette:
          #222759  background, with white on top
          --green-on-dark  foreground, on ink

   2. HARDCODED WHITE / GREY SURFACES.
      A few sections set `background: white` or `#F5F1EA` directly, so the
      paper and sand tokens never reach them and they read colder than the
      rest of the page.

   Page-level <style> parses after this file, so anything that must beat it is
   scoped one level deeper (`.voices .head-num`, `section.partners`) rather
   than marked !important.
   ========================================================================== */

/* ------------------------------------------------ 1. green text on dark ink */
body .voices .head-num,
body .voices .vn-count em,
body .voices .vr-nav .vn-count em { color: var(--green-on-dark); }

body .voices .vr-quote::before { color: var(--green-on-dark); }          /* the “ mark */

/* nav arrows: light hairline on ink, brand green on hover with white on top */
body .voices .vr-nav button {
  border-color: rgba(255,255,255,.28);
  color: rgba(255,255,255,.86);
}
body .voices .vr-nav button:hover {
  background: var(--green);
  border-color: var(--green);
  color: #fff;
}

/* the avatar keeps the deep green — white initials sit on it */
body .voices .vr-author .av { background: var(--green); color: #fff; }
body .voices .who { color: rgba(255,255,255,.66); }

/* the same section also carries a rule divider */
body .voices .voices-head { border-color: rgba(255,255,255,.14); }

/* the footer was already an ink field in the original, where the old emerald
   read fine. The deep green does not — same swap, same failure. */
body .site-footer h3,
body .site-footer h4,
body .site-footer .item .ico { color: var(--green-on-dark); }

/* the language toggle inherits --ink-soft, which is unreadable while the pill
   floats over the dark hero. The original sets its border and background for
   that state but never its text colour. */
body.nav-over-hero:not(.nav-scrolled) .nav-pill .lang-toggle{ color: #fff; }

/* --------------------------------------- 2. surfaces that hardcode white/grey */
body section.partners { background: var(--bg); }
body .discover-img { background: var(--bg-2); }

/* ------------------------------------------------ 3. the exhibitor slider */
/* card sits on sand inside a paper section — give it the paper field so the
   logo grid above and the card below read as one system */
body .preview-section .preview-card {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-layout);
}
body .preview-section .pc-role { color: var(--ink-soft); }
body .preview-section .pc-stars { color: var(--gold); }

/* dots: hairline by default, brand green when current, with a real hit area */
body .preview-dots .dot {
  background: var(--line-strong);
  width: 8px; height: 8px;
  transition: background-color .3s ease, transform .3s cubic-bezier(.22,1,.36,1);
}
body .preview-dots .dot:hover { background: var(--ink-soft); }
body .preview-dots .dot.active { background: var(--green); transform: scale(1.35); }

/* logo tiles: grey at rest, full colour on hover — brand-green hairline to
   show which cell you are on, instead of the old emerald wash */
body .partners-grid .partner-tile { border-color: var(--line); transition: background-color .3s ease; }
body .partners-grid .partner-tile:hover { background: var(--green-tint); }
body .partner-tile img { filter: grayscale(1) opacity(.55); transition: filter .4s ease, transform .4s ease; }
body .partner-tile:hover img { filter: none; transform: translateY(-2px); }

/* the "+ more" tile is an ink field — keep it warm and readable */
body .partner-tile.more { background: var(--ink); color: #fff; }


/* ==========================================================================
   EXHIBITORS — from a static 6-column grid to a continuous slider.

   The live markup is `.partners-grid` (a CSS grid) holding `.partner-tile`
   cells. Turning that into a marquee is a layout change, so it is kept in its
   own layer and driven by one small script that clones the tiles for a
   seamless loop (see the marquee block appended to partials.js).

   Nothing is required of the template: if the script does not run, the grid
   simply stays a grid and the page is unharmed.
   ========================================================================== */

/* ---- the track ---------------------------------------------------------- */
/* Only applies once the script has marked the container ready, so a failed
   script can never leave a broken half-marquee on screen. */
body .partners-grid.is-marquee{
  display: flex;
  flex-wrap: nowrap;
  width: max-content;
  gap: 0;
  border: none;
}
/* dead keyframes kept out: the strip now moves by scrollLeft (partials.js) */
@keyframes exhibitorSlide{
  from{ transform: translateX(0); }
  to  { transform: translateX(-50%); }   /* exactly one copy of the set */
}

/* the viewport that clips it, with the edges feathered so logos fade in/out
   rather than being chopped */
body .partners-marquee{
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  background: var(--bg);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
body .partners-marquee::-webkit-scrollbar{ display: none; }
/* hover/touch pause lives in partials.js now that the strip is a scroller */

/* ---- the cells ---------------------------------------------------------- */
/* borderless open strip: logos float on the page ground, no boxes */
body .partners-grid.is-marquee .partner-tile{
  flex: 0 0 auto;
  width: clamp(150px, 15vw, 210px);
  aspect-ratio: 16 / 9;
  border: none;
  background: var(--bg);
}
body .partners-grid.is-marquee .partner-tile:nth-child(6n){
  border: none;
}
/* the tile names clipped against the fixed 16:9 cell — the logo alt text
   already carries each name for assistive tech, so the visual label goes */
body .partners-grid.is-marquee .partner-tile .pt-name{ display: none; }
body .partners-grid.is-marquee .partner-tile:hover{ background: var(--green-tint); }
body .partners-grid.is-marquee .partner-tile img{
  filter: grayscale(1) opacity(.55);
  transition: filter .4s ease, transform .4s ease;
}
body .partners-grid.is-marquee .partner-tile:hover img{
  filter: none;
  transform: translateY(-2px);
}
/* clones are decorative duplicates — hidden from assistive tech */
body .partners-grid.is-marquee .partner-tile[data-clone]{ pointer-events: none; }

/* ---- motion preferences -------------------------------------------------- */
/* No animation: fall back to a real, swipeable scroller rather than a frozen
   strip, so the content is still reachable. */
/* reduced motion: partials.js skips the auto-advance; the strip stays a
   hand-swipeable scroller for everyone */

/* ---- small screens ------------------------------------------------------- */
@media (max-width: 620px){
  body .partners-grid.is-marquee .partner-tile{ width: 132px; }
}


/* ══════════════════ Audit fixes — 2026-08-13 ══════════════════
   Each rule closes a failure measured on the live site (contrast ratios
   computed from composited colours, focus-style deltas, clipped rects).
   Ratios quoted are what was measured before the fix. */

/* 1 · Focus. Only form inputs and the footer social links had a visible ring;
   every link, button and nav item was invisible under keyboard use (WCAG 2.4.7,
   39 elements on the homepage alone). currentColor inherits the band it sits on
   — ink on the light sections, white on the dark ones — so there is no
   per-section list to keep in sync. */
:where(a, button, [role="button"], input, select, textarea, summary,
       [tabindex]):focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
  border-radius: 4px;
}
/* The glass nav sits over both, so pin its ring to white while over the hero. */
body.nav-over-hero:not(.nav-scrolled) .nav-pill :focus-visible { outline-color: #fff; }

/* 2 · Accent text on the dark bands. The accent is admin-set
   (Settings.accentColor); the live value (#245d54) and the stylesheet default
   both land at 2.34–2.58:1 on the near-black bands. Lifting the same hue toward
   white keeps the brand colour and clears AA at whatever accent is saved. */
body .hero .hs-word,
body .field-card .field-meta .top .n,
body .discover .lbl,
body .stat-band .sb-head .num {
  color: var(--green-on-dark);
}

/* 3 · Muted text on dark measured 4.49:1 — one hundredth under AA. */
body .stat-band .sb .sub,
body .footer-meta,
body .footer-meta a { color: rgba(255,255,255,0.62); }

/* 4 · Review stars are a rating graphic (WCAG 1.4.11, 3:1) driven by --gold,
   which is admin-set too and is currently a near-white cream — 1.06:1, i.e.
   invisible. Mixing toward ink keeps it gold and keeps it readable. */
body .preview-section .pc-stars,
body .pc-stars { color: var(--gold-on-light); }

/* 5 · Exhibitor marquee, added with the restyle:
   a. the "+N more" tile lost its ink fill to the marquee's cell background and
      rendered white-on-cream at 1.04:1;
   b. the script re-parents the grid into .partners-marquee, which orphans it
      from the IntersectionObserver that clears the reveal state — on mobile the
      whole logo strip stayed at opacity 0. Content must never depend on an
      animation having fired. */
body .partners-grid.is-marquee .partner-tile.more { background: var(--ink); color: #fff; }
body .partners-grid.is-marquee .partner-tile.more:hover { background: var(--green); }
body .partners-grid.is-marquee,
body .partners-grid.is-marquee .partner-tile { opacity: 1; transform: none; }

/* 6 · Touch targets: footer nav and contact links were 22px tall, footer meta
   links 16px, breadcrumbs 19px — under the 24px minimum (WCAG 2.5.8). */
body .site-footer .footer-col li > a,
body .site-footer .footer-col .item { min-height: 24px; padding-block: 3px; }
body .footer-meta a { display: inline-block; min-height: 24px; padding-block: 4px; }
body .crumbs a { display: inline-block; min-height: 24px; padding-block: 3px; }

/* 7 · The mock browser bar's URL was #5B564C on white — 3.54:1. */
body .browser-frame .browser-bar .url { color: #6b6b6b; }

/* 8 · Skip link — first tab stop, only visible once focused. */
.skip-link {
  position: absolute; left: 50%; top: 0;
  transform: translate(-50%, -130%);
  z-index: 200;
  background: var(--ink); color: #fff;
  padding: 10px 18px; border-radius: 0 0 8px 8px;
  font-family: var(--font-head, system-ui, sans-serif);
  font-size: 14px; font-weight: 600; line-height: 1;
  transition: transform .2s cubic-bezier(.2,.7,.2,1);
}
.skip-link:focus-visible { transform: translate(-50%, 0); outline-offset: -4px; }

/* 9 · Mobile hero CTAs: laid out in a row with flex:1, their padding pushed the
   second button 23px past a 390px viewport, where overflow-x: clip hid half of
   "Become an Exhibitor". Wrapping gives it its own full-width line instead. */
@media (max-width: 430px) {
  body .hm-cta { flex-wrap: wrap; }
  body .hm-cta .btn { flex: 1 1 100%; padding-inline: 18px; }
}

/* ── Audit fixes, round 2 — the sweep the first pass missed ── */

/* 10 · One token for accent text that lands on a dark band, so the fix travels
   with the accent instead of being re-derived per page.

   Mix in sRGB, not oklab: oklab holds chroma as it lifts lightness, so a
   saturated accent lands outside the gamut and clips to a neon belonging to no
   palette. sRGB desaturates as it lightens, which is what a tint should do.
   45% white puts #222759 at 6.9:1 on --ink — comfortably past AA. */
:root {
  --green-on-dark: color-mix(in srgb, var(--green), #fff 45%);
  /* Gold sits on paper, where it is the weakest brand colour: #D9A02A alone is
     3.0:1, right on the 1.4.11 line for a rating star. A touch of ink buys
     margin (3.7:1) without turning it brown. */
  --gold-on-light: color-mix(in srgb, var(--gold), var(--ink) 12%);
  /* A photograph is a brighter, noisier bed than flat ink, and the only way to
     keep the accent legible over one is to darken the photo until it is murky
     — or to lighten the accent. This is the second option: one more step of
     white, used ONLY where the accent lands on the hero image. Still mixed from
     --green, so an admin accent change carries through. */
  --green-on-photo: color-mix(in srgb, var(--green), #fff 62%);
}
body .hero .hs-word { color: var(--green-on-photo); }
body .field-card .field-meta .top .n,
body .discover .lbl,
body .stat-band .sb-head .num,
body .reach-band h3,
body .reach-band .green,
body .voices .green,
body .ticker .green { color: var(--green-on-dark); }

/* 11 · Nav sitting on light sections: link text measured 4.26:1 and the
   language toggle 1.93:1 against the composited glass. Both read against a
   translucent pill, so they need the ink end of the ramp, not the soft one. */
body:not(.nav-over-hero) .nav-links a,
body.nav-scrolled .nav-links a { color: var(--ink); }
body:not(.nav-over-hero) .nav-pill .lang-toggle,
body.nav-scrolled .nav-pill .lang-toggle { color: var(--ink); }

/* 12 · Closing band: white at 0.7 over the green measured 4.0:1. */
body .closing .closing-meta .cm .lbl { color: rgba(255,255,255,0.88); }

/* 13 · Footer link touch targets — the earlier rule guessed a `.footer-col`
   class that isn't in the markup; the columns are bare divs in .footer-grid. */
body .site-footer .footer-grid li > a,
body .site-footer .footer-grid li > .item { min-height: 24px; padding-block: 3px; }

/* ── Audit fixes, round 3 — two selectors the page <style> blocks outranked ── */

/* 15 · Star ratings anywhere on a light surface: --gold is admin-set and lands
   between 1.06:1 (current homepage value) and 3.16:1 — under the 4.5:1 these
   need as text. Same mix as the homepage carousel, applied to every instance. */
body .t-card .stars,
body .stars,
body .pc-stars { color: var(--gold-on-light); }

/* 16 · Last sub-24px target: the map link on /contact. */
body .map-card .map-head a { display: inline-block; min-height: 24px; padding-block: 2px; }

/* ==========================================================================
   PARTNER WALL, STORY CAPTION, AND MOTION
   ========================================================================== */

/* ---- partner wall -------------------------------------------------------
   Logos arrive as whatever the partner sends. Half of them were flattened onto
   a white or black plate, which read as bright/dark rectangles once the section
   became warm paper. The plates are now lifted out of the assets themselves;
   the tile just has to stop painting its own white underneath them. */
body .partners-grid .partner-tile:not(.more) { background: transparent; }

/* .55 was tuned when every logo sat on its own white chip, which lent contrast
   the paper doesn't. Slightly stronger so the marks stay legible at tile size. */
body .partner-tile img,
body .partners-grid.is-marquee .partner-tile img { filter: grayscale(1) opacity(.62); }

/* ---- story caption ------------------------------------------------------
   Was a serif "No. 01" over a 25-word sentence. The number indexed nothing —
   there is no No. 02 anywhere, and the same block already opens with
   "01 / Origin" — so it read as decoration pretending to be structure. A short
   label earns the space instead. */
body .story-caption { max-width: 300px; }
body .story-caption .cap-label {
  font-size: 14px;   /* was 11px — owner wants the caption title more present */
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--green);
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 9px;
}
body .story-caption .cap-label::before {
  content: '';
  width: 22px;
  height: 2px;
  background: currentColor;
  flex: 0 0 auto;
}
body .story-caption .cap-text { font-size: 13.5px; line-height: 1.6; color: var(--ink-soft); }

/* ---- motion -------------------------------------------------------------
   Everything below is decorative. It is all disabled wholesale at the bottom
   of this block for anyone who asks for reduced motion. */

/* Cards lift instead of just changing colour — the page reads as responsive
   rather than static, at the cost of one transform. */
body .field-card,
body .t-card,
body .preview-card,
body .stat-band .sb,
body .offer-card {
  transition: transform .35s cubic-bezier(.2, .7, .3, 1), box-shadow .35s ease, background-color .3s ease;
  will-change: transform;
}
body .field-card:hover,
body .t-card:hover,
body .preview-card:hover,
body .offer-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 40px -22px rgba(26, 24, 18, .35);
}

/* A light sweep across the primary button on hover. Pure pseudo-element, no
   extra markup, and it cannot affect layout because it is clipped. */
body .btn-green { position: relative; overflow: hidden; }
body .btn-green::after {
  content: '';
  position: absolute;
  inset: 0 auto 0 -60%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .38), transparent);
  transform: translateX(-140%);
  pointer-events: none;
}
body .btn-green:hover::after { animation: btnSheen .75s ease-out; }
@keyframes btnSheen { to { transform: translateX(420%); } }

/* Nav links grow a rule from the centre rather than snapping to a pill. */
body .nav-links a { position: relative; }
body .nav-links a::after {
  content: '';
  position: absolute;
  left: 50%;
  right: 50%;
  bottom: 3px;
  height: 1.5px;
  background: currentColor;
  opacity: .55;
  transition: left .28s ease, right .28s ease;
}
body .nav-links a:hover::after { left: 14px; right: 14px; }
body .nav-links a.active::after { content: none; }

/* Counters animate up when scrolled into view (partials.js adds .counted).
   Tabular figures stop the width jitter that makes a ticking number wobble. */
body [data-count-to] { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  body .field-card,
  body .t-card,
  body .preview-card,
  body .stat-band .sb,
  body .offer-card { transition: none; }
  body .field-card:hover,
  body .t-card:hover,
  body .preview-card:hover,
  body .offer-card:hover { transform: none; box-shadow: none; }
  body .btn-green:hover::after { animation: none; }
  body .nav-links a::after { transition: none; }
}

/* ---- partner tiles: name + link ----------------------------------------
   The strip is now the only place partners appear, so a tile has to say who
   it is and, where we have a site, go there. Column layout: logo above a
   small caption, both centred in the 16/9 cell. */
body .partners-grid .partner-tile:not(.more),
body .partners-grid.is-marquee .partner-tile:not(.more) {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 14px 12px;
  text-decoration: none;
  color: inherit;
}
body .partner-tile img { max-height: 42px; }
body .partner-tile .pt-name {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-align: center;
  line-height: 1.25;
  max-width: 100%;
  /* two lines then ellipsis — long names must not push the logo out of the cell */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  transition: color .3s ease;
}
body .partner-tile.is-link { cursor: pointer; }
body .partner-tile.is-link:hover .pt-name,
body .partner-tile.is-link:focus-visible .pt-name { color: var(--green); }
body .partner-tile.is-link:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: -2px;
}
/* the linked ones get a little lift so the clickable half of the strip reads
   as clickable without shouting */
body .partner-tile.is-link:hover { transform: translateY(-2px); }
body .partners-grid .partner-tile.is-link { transition: transform .3s ease, background-color .3s ease; }

@media (prefers-reduced-motion: reduce) {
  body .partner-tile.is-link:hover { transform: none; }
}

/* ---- primary register CTA -----------------------------------------------
   A pill with a slow-pulsing dot, reserved for the one action the page is
   actually asking for. It wears the committed deep green — the site's single
   colour of intent — rather than an off-palette red: the editorial system
   earns emphasis through the pulsing bright-green indicator and the pill
   being the only solid-green button in the nav, not through a second hue. */
body a.btn.btn-register,
body button.btn.btn-register {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: var(--green);
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 13px 26px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: none;
  transition: background-color .3s ease, transform .32s cubic-bezier(.34, 1.56, .64, 1), box-shadow .3s ease;
}
body a.btn.btn-register:hover,
body button.btn.btn-register:hover {
  background: var(--green-deep);
  color: #fff;
  transform: translateY(-1px);
  box-shadow: 0 10px 26px -10px rgba(34,39,89, .6);
}
body .btn.btn-register .cta-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  /* the restrained indicator: lifted accent on the deep-green pill — it never
     drops below half opacity or it vanishes against the ground */
  background: var(--green-on-dark);
  opacity: 1;
  flex: 0 0 auto;
  animation: ctaPulse 2.4s ease-in-out infinite;
}
@keyframes ctaPulse {
  0%, 100% { opacity: .55; transform: scale(.8); }
  50%      { opacity: 1;   transform: scale(1.15); }
}
/* the sheen from the green buttons would fight the pulse */
body .btn.btn-register::after { content: none; }

@media (prefers-reduced-motion: reduce) {
  body .btn.btn-register .cta-dot { animation: none; opacity: 1; }
  body a.btn.btn-register:hover,
  body button.btn.btn-register:hover { transform: none; }
}

/* ---- mobile sticky register bar -----------------------------------------
   Injected by partials.js on the proof pages (gallery / campaign /
   testimonials / about / contact), where hiding the header Register button on
   ≤720px left phones with no visible CTA. Reuses the green .btn-register pill;
   inset-inline keeps it RTL-safe. Desktop never sees it. */
.stickybar {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 50;                        /* under the drawer (60) and modal (100) */
  display: none;                      /* shown only in the 720px block below */
  padding: 10px 14px;
  padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  background: rgba(255, 255, 255, .94);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--line);
}
/* (0-3-1) beats the inline-flex from `body a.btn.btn-register` (0-2-2) */
.stickybar a.btn.btn-register {
  display: flex;
  justify-content: center;
  width: 100%;
}
@media (max-width: 720px) {
  .stickybar { display: block; }
  /* keep the bar from sitting on the last of the footer */
  body.has-stickybar { padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
}

/* ══════════════════ Arabic (RTL) typography — 2026-08-18 ══════════════════
   Tracking on connected script pulls joined glyphs apart, which reads as
   stray kashida/tatweel marks inside every word — off in RTL.
   The !important is deliberate: it must beat every per-component
   letter-spacing (0.28em eyebrows, -0.03em display headings, etc.). */
html[dir="rtl"] body,
html[dir="rtl"] body * { letter-spacing: 0 !important; }

/* ══════════════════ One emphasis system, both languages ══════════════════
   Arabic has no italic convention, so italic-as-hierarchy gave EN and AR
   different voices for the same phrase. Sitewide rule: emphasis is weight and
   the accent colour, never a slant. em/i keep their semantics; the serif
   display faces stay — upright. */
em, i, blockquote { font-style: normal; }
h1 em, h2 em, h3 em, .story-display em { font-weight: inherit; color: var(--green); }

/* ══════════════════ Ceramica Market brand layer ══════════════════
   The logo is three colours: navy "Ceramica" (the --green token family now
   carries it, so every HOMEX surface turns navy), red "Market" and the lime
   diamond. Red is kept for the one action the page asks for (register) and for
   heading emphasis; lime is the accent that sits on navy and on photos. */
:root {
  --brand-red: #C83133;
  --brand-red-deep: #A8262A;
  --brand-lime: #94C742;
  --green-on-dark: #A6D35A;
  --green-on-photo: #B4DC6E;
}
/* The display face is Instrument Serif, which ships 400 and italic only. Display
   headings are already pinned to 400 above; small headings keep the body face, so a
   700/800 rule on them renders as a real bold instead of a synthesised one. */
h3, h4, h5, h6 { font-family: var(--font-body); }

h1 em, h2 em, h3 em, .story-display em { color: var(--brand-red); }
/* about / campaign / testimonials / contact mark the same emphasis with a span
   instead of an <em>; --green is navy since the rebrand, so on --ink headings it
   read as no emphasis at all. Light surfaces only — on dark, .green is lime. */
.page-head h1 .green, .section-title .green { color: var(--brand-red); }
body a.btn.btn-register,
body button.btn.btn-register { background: var(--brand-red); }
body a.btn.btn-register:hover,
body button.btn.btn-register:hover { background: var(--brand-red-deep); box-shadow: 0 10px 26px -10px rgba(200,49,51,.6); }
body .btn.btn-register .cta-dot { background: #fff; }
/* Accent icons that sat on HOMEX's ink as green now sit on navy as navy — lift them to lime. */
body .stat-band .sb .ico { color: var(--green-on-dark); border-color: rgba(166,211,90,.35); }
body .vr-cap .dot-live { background: var(--brand-red); }
/* HOMEX put a green button on a dark panel; navy on navy disappears, so the sister-show button is red. */
body .discover .btn-green { background: var(--brand-red); }
body .discover .btn-green:hover { background: var(--brand-red-deep); }
/* The smoky glass nav goes navy over the navy sections, and the navy "Ceramica" in the
   logo vanished there. A light frost keeps the dark logo readable on any section; the
   see-through hero state (nav-over-hero, not scrolled) keeps its own rule. */
body .nav-pill { background: rgba(255,255,255, calc(var(--p) * .72)); }  /* fades in with the scroll morph */
/* ...but keep the near-solid bar for people who opt out of transparency (the rule above
   outranks the earlier prefers-reduced-transparency fallback). */
@media (prefers-reduced-transparency: reduce) {
  body .nav-pill { background: rgba(255,255,255,.96); }
}

/* Tap targets: phone numbers rendered ~19px tall and the EN/AR switch ~25px, below the ~44px a
   thumb needs. Padding grows the hit area without moving the text. */
a[href^="tel:"] { display: inline-block; padding-block: 12px; margin-block: -12px; }
@media (hover: none) {
  #langToggle { position: relative; }
  #langToggle::after { content: ''; position: absolute; inset: -10px -4px; }
}
