/* ══════════════════════════════════════════════════════════════════
   STICKY TOP BAR
   ------------------------------------------------------------------
   The site's real header, shared by every page. It sits over the hero
   photograph with no ground of its own, then fades to a solid bar with
   a hairline once the page scrolls — so the hero art stays full-bleed
   but the menu is reachable everywhere.

   The previous menu lived inside the hero, which is a fixed-height
   composition of absolutely-positioned pieces; seven links could not
   fit between the language switcher and the host mark and wrapped to a
   second line. Out here the bar owns the full column width.
   ══════════════════════════════════════════════════════════════════ */
.topbar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  /* At rest the bar carries a very light scrim rather than nothing at all:
     a soft top-down wash plus a touch of blur, so the links stay legible
     over the brightest part of the tower photograph without putting a
     hard-edged band across the artwork. It fades out downwards, so there
     is no visible seam where the bar ends. */
  background: linear-gradient(to bottom,
              rgba(11, 20, 15, .42) 0%,
              rgba(11, 20, 15, .26) 55%,
              rgba(11, 20, 15, 0) 100%);
  backdrop-filter: blur(3px) saturate(105%);
  -webkit-backdrop-filter: blur(3px) saturate(105%);
  border-bottom: 1px solid transparent;
  transition: background .45s ease, border-color .45s ease, backdrop-filter .45s ease;
}
.topbar__inner {
  width: var(--col);
  margin-inline: auto;
  min-height: clamp(62px, 5.4vw, 78px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(16px, 2.2vw, 40px);
}

/* scrolled state — a quiet ground so the links never fight the photo */
.topbar.is-stuck {
  background: linear-gradient(rgba(18, 30, 23, .92), rgba(18, 30, 23, .92));
  border-bottom-color: var(--line-soft);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

/* ── live build: header is not sticky ──────────────────────────────
   The live site has no menu, so there is nothing in the bar worth
   keeping on screen while the reader scrolls. It sits at the top of the
   hero and leaves with it — no scrim, no scrolled state. */
.is-live .topbar {
  position: absolute;
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom: 0;
}
.is-live .topbar.is-stuck {
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
}
.is-live .topbar .lang { text-shadow: 0 1px 10px rgba(8, 16, 12, .7); }

/* ── brand mark ────────────────────────────────────────────────────
   The home hero already shows the lockup at full size, so the bar's
   copy stays hidden until the page scrolls and the hero one leaves.
   Inner pages have no hero lockup, so it shows from the start. */
.topbar__mark { display: flex; align-items: center; text-decoration: none; flex: none; }
.topbar__lockup {
  display: block;
  width: clamp(112px, 11vw, 152px);
  aspect-ratio: 1825 / 266;
  background: var(--cream);
  --m: url('../assets/img/ycsf-lockup-2027-white.png');
  -webkit-mask: var(--m) center / contain no-repeat;
  mask: var(--m) center / contain no-repeat;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity .45s ease, transform .45s ease;
}
.topbar.is-stuck .topbar__lockup,
.is-page .topbar__lockup { opacity: 1; transform: none; }

/* ── links ─────────────────────────────────────────────────────────*/
.sitenav { flex: 1 1 auto; display: flex; justify-content: center; }
.sitenav__list {
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.7vw, 30px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.sitenav__list a {
  position: relative;
  display: block;
  padding: 9px 2px;
  font-family: var(--f-body);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: .015em;
  white-space: nowrap;
  color: var(--ink);
  text-decoration: none;
  transition: color .3s ease;
}
.sitenav__list a::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 2px;
  height: 2px;
  background: linear-gradient(90deg, var(--green), var(--red));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .35s cubic-bezier(.4, .12, .2, 1);
}
.sitenav__list a:hover, .sitenav__list a:focus-visible { color: var(--ink-strong); }
.sitenav__list a:hover::after,
.sitenav__list a:focus-visible::after,
.sitenav__list a[aria-current="page"]::after { transform: scaleX(1); }
.sitenav__list a[aria-current="page"] { color: var(--ink-strong); }

/* ── right-hand end: language switcher, CTA, toggle ────────────────*/
/* margin-inline-start:auto so the group still sits at the far end on the
   Arabic and Chinese editions, where the menu is absent and there is no
   flexible middle to push against */
.topbar__end { display: flex; align-items: center; gap: clamp(12px, 1.4vw, 22px);
               flex: none; margin-inline-start: auto; }
.topbar .lang { position: static; top: auto; left: auto; }

/* ── header order, mirrored per language ───────────────────────────
   The switcher sits at the leading edge of the reading order in every
   language — the left in English and Chinese, the right in Arabic —
   and the host mark takes the opposite end. Ordering the flex children
   rather than positioning them means the whole bar mirrors itself from
   the document's own direction.

   space-between rather than an auto margin on the switcher, because the
   bar has to hold both shapes: staging's English edition has the menu in
   the middle (.sitenav is flex:1 1 auto, so it absorbs the slack and the
   ends stay put), while the Arabic and Chinese editions — and every LIVE
   page — have no menu at all, and space-between still parks the switcher
   and the mark on opposite edges with nothing flexible between them.
   An auto margin could not do both: auto margins eat free space before
   flex-grow does, so it would have collapsed the centred menu. */
.topbar__end { display: contents; }
.topbar .lang    { order: 1; }
.sitenav         { order: 2; }
.topbar__mark    { order: 3; }
.sitenav__toggle { order: 4; }

.sitenav__toggle { display: none; }

/* ── Downloads submenu ──────────────────────────────────────────────
   A nav item that opens a panel rather than navigating. The trigger is a
   <button>, not a link, because it goes nowhere — that also gives keyboard
   and screen-reader users the right affordance via aria-expanded.

   Positioned from the item, and mirrored by `inset-inline-start` rather than
   `left`, so the Arabic edition drops it from the correct edge without a
   second rule. */
.sitenav__has-sub { position: relative; }

.sitenav__sub-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  letter-spacing: inherit;
}

/* the caret follows the text colour and flips when the panel is open */
.sitenav__caret {
  width: 8px; height: 8px;
  border-inline-end: 1.6px solid currentColor;
  border-block-end: 1.6px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform .25s ease;
}
.sitenav__sub-toggle[aria-expanded="true"] .sitenav__caret {
  transform: translateY(1px) rotate(-135deg);
}

.sitenav__sub {
  position: absolute;
  inset-inline-start: 0;
  top: calc(100% + 14px);
  min-width: max(220px, 100%);
  margin: 0;
  padding: 8px 0;
  list-style: none;
  background: rgba(18, 30, 23, .97);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--line-soft);
  border-radius: 3px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, .45);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity .22s ease, transform .22s ease, visibility .22s;
  z-index: 60;
}
.sitenav__sub-toggle[aria-expanded="true"] + .sitenav__sub {
  opacity: 1; visibility: visible; transform: none;
}
.is-flat .sitenav__sub { transition: none; }

.sitenav__sub a {
  display: block;
  padding: 10px 18px;
  white-space: nowrap;
  transition: background .2s ease, color .2s ease;
}
.sitenav__sub a:hover,
.sitenav__sub a:focus-visible { background: rgba(255, 255, 255, .07); color: var(--ink-strong); }

/* the hero starts under the bar rather than behind its links */
.hero--page .hero__stage { padding-top: clamp(96px, 9vw, 132px); }

/* ── host mark vs the header ────────────────────────────────────────
   On LIVE the bar is transparent (.is-live drops its background and
   backdrop-filter), so the mark sits at the artboard's own top: 4.54%
   and nothing covers it.

   Where the bar DOES have a scrim — every build with a menu — that
   artboard position puts the mark underneath it: at 1440 the bar runs
   0–79px and the mark 43–93px, so 35 of its 50px sat behind a
   backdrop-blur and a dark gradient. It did not vanish; it was being
   painted over, which reads as a half-hidden logo. On a phone the bar
   is 62px tall and the mark 14–44px — hidden entirely.

   Clearing the bar's own height is the fix, not raising z-index: the
   mark must stay UNDER the bar once the page scrolls, or it would ride
   over the menu links. The value tracks .topbar__inner's min-height so
   the two cannot drift apart. */
body:not(.is-live) .hero__yasref { top: calc(clamp(62px, 5.4vw, 78px) + 14px); }

/* Below 1100 the hero is a flow column (responsive.css @media max-width:1099)
   and the lockup's margin-top was tuned — "clears the language switch and the
   host mark" — for a mark sitting at 14-44px. Moving the mark clear of the bar
   consumed that gap: the mark now ends at 106 and the lockup began at 110,
   four pixels apart, which reads as the two logos touching. In landscape it
   was worse, the bar clipping the lockup by 7px.

   The whole flow tier needs the same treatment, not just phones: at 1024 the
   lockup sat at 63px, exactly where the bar ends. (A `top:` floor does
   nothing here — the lockup is position:static in this tier, which is why
   the first attempt at 900+ had no effect.) LIVE has no bar and keeps the
   artboard spacing. */
@media (max-width: 1099px) {
  body:not(.is-live) .hero__lockup { margin-top: 116px; }
}


/* ── below 1100: the links move into a drop panel ──────────────────
   Seven English items + the switcher + the mark need ~927px of the bar's
   928px column at 1100. One pixel below that they do not fit, and the row
   used to overflow the bar rather than wrap or collapse — 59px out at
   1000, 128px at 900. Squeezing the gap and the type (the old 1099 tier)
   never recovered enough, so the panel now takes over at the first width
   where the row stops fitting instead of 200px later. */
@media (max-width: 1099px) {
  /* Only the inner pages need the bar's mark on a phone — the home
     hero already shows the lockup full size, and forcing the bar copy
     visible there put it straight on top of the YASREF mark. */
  .is-page .topbar__lockup { opacity: 1; transform: none; }
  .sitenav {
    position: absolute;
    left: 0; right: 0; top: 100%;
    background: rgba(18, 30, 23, .97);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--line-soft);
    max-height: 0;
    overflow: hidden;
    transition: max-height .4s cubic-bezier(.4, .12, .2, 1);
  }
  .sitenav.is-open { max-height: 70vh; }
  .is-flat .sitenav { transition: none; }
  .sitenav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    width: var(--col);
    margin-inline: auto;
    padding: 6px 0 14px;
  }
  .sitenav__list a { padding: 13px 0; border-bottom: 1px solid var(--line-soft); }
  .sitenav__list a::after { display: none; }

  /* Inside the burger panel the submenu is part of the list, not a floating
     card — a popover inside a popover is awkward on a touch screen. */
  .sitenav__sub-toggle {
    width: 100%;
    justify-content: space-between;
    padding: 13px 0;
    border-bottom: 1px solid var(--line-soft);
  }
  .sitenav__sub {
    position: static;
    opacity: 1; visibility: visible; transform: none;
    background: none; backdrop-filter: none; -webkit-backdrop-filter: none;
    border: 0; box-shadow: none; border-radius: 0;
    padding: 0;
    max-height: 0; overflow: hidden;
    transition: max-height .32s cubic-bezier(.4, .12, .2, 1);
  }
  .sitenav__sub-toggle[aria-expanded="true"] + .sitenav__sub { max-height: 320px; }
  /* The brochures are named after the forum and the language they are written
     in, which is longer than the panel is wide on a phone: the desktop card
     sizes itself to its longest item, but this list is the panel's width, so
     nowrap cut the name off mid-word. Let it run to a second line. */
  .sitenav__sub a { padding: 12px 0 12px 18px; opacity: .82; white-space: normal; }
  [dir="rtl"] .sitenav__sub a { padding: 12px 18px 12px 0; }

  /* the drop panel is position:absolute, so it is out of the flex flow and
     space-between would strand the mark in the middle of the bar. Push the
     mark and the burger together onto the trailing edge. Harmless on LIVE,
     where there is no burger and this is what space-between already did. */
  .topbar__mark { margin-inline-start: auto; }

  .sitenav__toggle {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 42px; height: 36px;
    padding: 0 9px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 2px;
    cursor: pointer;
  }
  .sitenav__toggle span { display: block; height: 2px; background: var(--ink); transition: transform .3s ease, opacity .3s ease; }
  .sitenav__toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .sitenav__toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .sitenav__toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
}

@media (max-width: 599px) {
  /* At 375 the bar wanted 357px of content in 316px — a 112px lockup, a
     175px language switcher and the 42px toggle — so the right-hand group
     ran off the screen. Everything is trimmed to fit, with nothing hidden. */
  .topbar__inner { gap: 10px; min-width: 0; }
  .topbar__end   { gap: 8px; min-width: 0; }
  .topbar__lockup { width: 92px; }
  .topbar .lang { gap: 4px; font-size: 11.5px; }
  .topbar .lang a { padding: 9px 5px; }    /* taller for the thumb, narrower on the page */
  .topbar .lang .div { margin: 0; }
  .sitenav__toggle { width: 40px; height: 34px; padding: 0 8px; }
}

@media (max-width: 359px) {
  /* 12px is the floor the rest of the phone layout keeps, so the switcher
     holds it and the lockup gives up the width instead */
  .topbar__lockup { width: 72px; }
  .topbar .lang { font-size: 12px; gap: 2px; }
  .topbar .lang a { padding: 9px 2px; }
  .topbar__inner { gap: 8px; }

  /* the sector card's inner box was still wider than its track — these
     have to live here rather than in responsive.css, which loads first
     and therefore loses to this file */
  .sector, .sector .zone__t, .sector .zone__rule, .sector .zone__body {
    max-width: 100%;
    min-width: 0;
  }
  .zones__grid { grid-template-columns: minmax(0, 1fr); }
}


/* ══════════════════════════════════════════════════════════════════
   INNER PAGES
   ------------------------------------------------------------------
   Conference · Exhibition · Networking · Attend · Plan Your Visit ·
   Media.

   Everything here is expressed in the tokens base.css already
   defines — --s-section, --t-display, --col, the brand ramp — so the
   inner pages inherit the home page's rhythm, type scale and colour
   rather than re-stating any of it. Where a component already exists
   on the home page (.goal, .zone, .nums__cell, .aud-item) the markup
   reuses that class and only the grid around it is new.
   ══════════════════════════════════════════════════════════════════ */


/* ── page hero ─────────────────────────────────────────────────────
   A shortened version of the home hero: same photograph, same glow,
   no countdown or lockup animation. */
/* The home hero is a fixed-height stage with absolutely-positioned
   children. The page hero is the same photograph and glow but sized by
   its content, so every piece is returned to normal flow. */
/* ── one banner on every inner page ─────────────────────────────────
   The banner used to be as tall as whatever copy it carried, and the
   photograph was cropped to fit: at 1440 the Exhibition banner showed 29% of
   the picture's height and Networking 67%, so the same image looked zoomed on
   some pages and not others (Kareem, 24 Sep 2026: "the banner is stretched
   horizontally and it looks different in some pages"). The photograph now has
   its own fixed height, so its crop is identical on every inner page at a
   given width; pages whose banner carries a lede and figures keep growing
   below it, over the page ground. */
.hero--page { --banner-h: clamp(240px, 28vw, 520px); height: auto; min-height: var(--banner-h); }
.hero--page .hero__bg { height: var(--banner-h); }
.hero--page .hero__stage {
  padding-top: clamp(58px, 6vw, 86px);
  padding-bottom: clamp(46px, 5.4vw, 88px);
  display: block;
}
.hero--page .hero__lockup,
.hero--page .hero__title { position: static; margin-inline: 0; }
.hero--page .hero__lockup {
  width: min(320px, 46vw);
  height: auto;
  aspect-ratio: 1825 / 266;
  display: block;
}
.hero__home { display: inline-block; text-decoration: none; }

.hero__title--page {
  font-size: var(--t-display);
  margin-top: clamp(28px, 3.4vw, 54px);
}
.hero__pagemeta {
  margin-top: var(--s-tight);
  max-width: 62ch;
  font-family: var(--f-body);
  font-size: var(--t-micro);
  line-height: 1.9;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}


/* ── generic page section ──────────────────────────────────────────
   Matches the home page's section rhythm exactly. */
.pg { padding-top: var(--s-section); padding-bottom: var(--s-section); }
.pg .h-section { text-align: center; }

.pg__prose {
  max-width: var(--measure);
  margin: var(--s-head) auto 0;
  text-align: center;
}
.pg__prose p {
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.95;
  color: var(--ink-soft);
}
.pg__prose p + p { margin-top: 1.15em; }
.page-lede {
  font-size: var(--t-lede) !important;
  line-height: 1.7 !important;
  color: var(--ink-strong) !important;
  font-weight: 600;
}
.page-lede + p { margin-top: 1.5em !important; }

.pg__cta { margin-top: var(--s-block); display: flex; justify-content: center; }

.pg__note {
  margin-top: var(--s-tight);
  text-align: center;
  font-family: var(--f-body);
  font-size: var(--t-micro);
  color: var(--ink-faint);
}


/* ── to-be-announced ───────────────────────────────────────────────
   The workbook marks these sections TBA. They are rendered as an
   honest placeholder rather than filled with invented copy. */
.pg--tba .pg__tba {
  margin: var(--s-head) auto 0;
  max-width: 46ch;
  padding: clamp(30px, 4vw, 54px) clamp(20px, 3vw, 40px);
  border: 1px dashed var(--line);
  border-radius: 2px;
  text-align: center;
  font-family: var(--f-display);
  font-size: var(--t-sub);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}


/* ── program at a glance ───────────────────────────────────────────
   The same bordered card as the Exhibition Zones, minus the coloured
   header. Two stacked rows, so every card in a row shares one grid and
   lines up exactly — which the earlier two-column split could not do. */
.prog__row {
  display: grid;
  gap: clamp(14px, 1.4vw, 20px);
  margin: 0;
  padding: 0;
  list-style: none;
  grid-template-columns: minmax(0, 1fr);
}
.prog__row--four { margin-top: var(--s-head); }
.prog__row--two  { margin-top: clamp(18px, 2vw, 26px); }
/* Two across rather than four, and the architecture pair full width.
   Measured at 1440: four across gave each title 237px of room when the
   longest needs 369, so every one of them broke — and the widest card
   wrapped for the sake of 5px. At these widths each title fits on a
   single line, and only genuinely long copy on a narrow screen wraps. */
@media (min-width: 640px) { .prog__row--four { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.prog__card {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 96px;
  padding: clamp(20px, 2.2vw, 30px) clamp(18px, 2vw, 26px);
  border-radius: 10px;
  transition: transform .45s cubic-bezier(.22, .61, .36, 1),
              filter .45s ease;
}
.prog__card:hover {
  transform: translateY(-5px);
  filter: drop-shadow(0 13px 24px var(--shadow));
}
.prog__card:hover .zone__border { filter: brightness(1.16) saturate(1.06); }
.prog__card-t {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--t-sub);
  line-height: 1.25;
  color: var(--ink);
  /* when a wrap is genuinely unavoidable, split the lines evenly rather
     than leaving one word stranded */
  text-wrap: balance;
  overflow-wrap: normal;
  hyphens: none;
}
.prog__card--wide { min-height: 78px; }

.prog__arch { margin-top: var(--s-block); }
.prog__arch-t {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--t-sub);
  line-height: 1.25;
  color: var(--ink);
  margin-bottom: 12px;
}

@media (prefers-reduced-motion: reduce) { .prog__card:hover { transform: none; } }


/* ── Why Participate — five of the home page's .goal cards ─────────*/
.obj__grid--five {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(24px, 2.6vw, 40px);
  margin-top: var(--s-head);
}
/* Five cards never fill a row evenly, so the last row is centred rather
   than left with a hole beside it. The grid is laid out in half-columns —
   six tracks for three cards, four for two — and the trailing cards are
   placed one half-column in, which centres them without breaking the
   subgrid rows the titles, rules and copy align on. */
@media (min-width: 700px) and (max-width: 1099px) {
  .obj__grid--five { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .obj__grid--five .goal { grid-column: span 2; }
  .obj__grid--five .goal:nth-child(5) { grid-column: 2 / span 2; }
}
@media (min-width: 1100px) {
  .obj__grid--five { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .obj__grid--five .goal { grid-column: span 2; }
  .obj__grid--five .goal:nth-child(4) { grid-column: 2 / span 2; }
  .obj__grid--five .goal:nth-child(5) { grid-column: 4 / span 2; }
}


/* ── Target Sectors ────────────────────────────────────────────────
   The zone card, but its icon sits inside the body rather than in a
   coloured header strip — these eight glyphs come from the client's
   Target Sectors deck and read better on the card's own ground. */
.sector { padding-top: 26px; }
.sector .zone__t { margin-top: 0; }
.sector .zone__body p { margin: 0; }

/* Each sector now carries its sub-sectors rather than a one-line blurb
   (Kareem's list of 29 Sep 2026: seven sectors, four to seven items each).
   They are set as a plain list inside the card, on the same type as the
   blurb they replace, so the card design is unchanged. */
/* Seven sectors in a four-across grid leave one empty cell, so the second
   row of three is centred and the gap reads as intended rather than as a
   missing card. Scoped to this section: the Exhibition Zones grid next to it
   still has eight cards and must stay flush. Only the four-column tier needs
   it — below 1100 the grid is two columns (a clean 4x2 with one gap at the
   end) and one column on a phone. */
@media (min-width: 1100px) {
  /* ⚠ eight columns, not twenty-four: a card spanning 2 of 8 tracks is
     exactly as wide as one of 4 tracks (the gap it swallows makes up the
     difference), while 24 tracks swallow more gaps and shrink every card. */
  /* ⚠ minmax(0,1fr), not 1fr: a card's min-content width pushed one
     track wider than the rest and the row stopped lining up. */
  #target-sectors .zones__grid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
  /* ⚠ `grid-column: span 2` sets the START to "span 2" and leaves the end
     auto, so overriding only grid-column-start left that card one track
     wide. Both ends are written out. */
  #target-sectors .sector { grid-column: auto / span 2; }
  #target-sectors .sector:nth-child(5) { grid-column: 2 / span 2; }
}

.sector__subs {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: .42em;
}
.sector__subs li {
  position: relative;
  padding-inline-start: 1em;
}
.sector__subs li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: .62em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  opacity: .55;
}
.sector__ico {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  margin-bottom: clamp(16px, 1.8vw, 24px);
  border-radius: 999px;
  background: linear-gradient(135deg, var(--a), var(--b));
  transition: transform .45s cubic-bezier(.22, .61, .36, 1),
              filter .45s ease;
}
.sector__ico .zone__ico { width: 28px; height: 28px; color: var(--cream); }
.sector:hover .sector__ico { transform: scale(1.08) rotate(-5deg); filter: brightness(1.12); }

@media (max-width: 599px) {
  .sector__ico { width: 46px; height: 46px; }
  .sector__ico .zone__ico { width: 24px; height: 24px; }
}
@media (prefers-reduced-motion: reduce) { .sector:hover .sector__ico { transform: none; } }


/* ── participation timeline ────────────────────────────────────────*/
.tl__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(26px, 3vw, 44px);
  margin-top: var(--s-head);
}
@media (min-width: 900px) { .tl__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.tl {
  padding: clamp(24px, 2.6vw, 38px);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: 2px;
}
.tl__when {
  margin-top: 6px;
  font-family: var(--f-body);
  font-size: var(--t-micro);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.tl__list { margin: 18px 0 0; padding: 0; list-style: none; }
.tl__list li {
  position: relative;
  padding: 0 0 0 20px;
  font-family: var(--f-body);
  font-size: var(--t-small);
  line-height: 1.9;
  color: var(--ink-soft);
}
.tl__list li + li { margin-top: 12px; }
.tl__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 12px;
  width: 8px;
  height: 2px;
  background: var(--red);
}


/* ── Who Attends ───────────────────────────────────────────────────*/
.who__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(24px, 2.6vw, 40px);
  margin: var(--s-head) 0 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 700px)  { .who__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .who__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.who__t {
  font-family: var(--f-display);
  font-size: var(--t-sub);
  line-height: 1.35;
  color: var(--ink-strong);
}
.who__p {
  margin-top: 14px;
  font-family: var(--f-body);
  font-size: var(--t-small);
  line-height: 1.9;
  color: var(--ink-soft);
}


/* ── attendance figures — the home page's .nums cells, four up ─────*/
.nums__grid--four {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(30px, 3.4vw, 56px);
  margin: var(--s-head) 0 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 900px) { .nums__grid--four { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* sections.css shrinks the first cell's halo, a value tuned for the home
   page's shorter "130+". All four figures here are full width, so the
   halo is returned to the standard height. */
.nums__grid--four .nums__cell:first-child .nums__glow { height: 110.16px; }


/* ── forum pillars, as static cards ────────────────────────────────*/
.pcard__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(26px, 3vw, 46px);
  margin-top: var(--s-head);
}
@media (min-width: 780px)  { .pcard__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1180px) { .pcard__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.pcard { position: relative; }
.pcard img {
  width: 100%;
  height: auto;
  aspect-ratio: 1120 / 685;
  object-fit: cover;
  border-radius: 2px;
  display: block;
}
.pcard__body { margin-top: clamp(18px, 2vw, 26px); }
.pcard__t {
  font-family: var(--f-display);
  font-size: var(--t-sub);
  line-height: 1.35;
  color: var(--ink-strong);
}
.pcard__p {
  margin-top: 14px;
  font-family: var(--f-body);
  font-size: var(--t-small);
  line-height: 1.9;
  color: var(--ink-soft);
}


/* ── media: channels and accreditation ─────────────────────────────*/
.chan__grid,
.acc__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(26px, 3vw, 46px);
  margin-top: var(--s-head);
}
@media (min-width: 780px) {
  .chan__grid, .acc__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.chan__t, .acc__t {
  font-family: var(--f-display);
  font-size: var(--t-sub);
  color: var(--ink-strong);
}
.chan__list, .acc__list { margin: 18px 0 0; padding: 0; list-style: none; }
.chan__list li, .acc__list li {
  padding: 11px 0;
  border-bottom: 1px solid var(--line-soft);
  font-family: var(--f-body);
  font-size: var(--t-body);
  color: var(--ink-soft);
}


/* ── responsive ────────────────────────────────────────────────────*/
@media (max-width: 899px) {
  /* the menu collapses behind a toggle; the CTAs stay visible */

  /* ?flat=1 is the site's QA mode: it kills transitions so geometry can be
     measured. The preview pane reports document.hidden, which freezes
     transitions mid-flight and made this menu measure 0px tall even when
     open, so the nav opts into flat mode too. */
}

@media (max-width: 599px) {
  .hero--page { padding-bottom: 40px; }
  .hero__title--page { font-size: 26px; line-height: 1.25; }
  .hero__pagemeta { font-size: 10px; letter-spacing: .05em; }
}



/* ══════════════════════════════════════════════════════════════════
   ALIGNMENT
   ------------------------------------------------------------------
   Every card grid uses the same device the home page's Exhibition
   Zones use: the card is itself a grid whose rows are `subgrid`, so
   the title, the rule and the body sit on shared rows across the
   whole row of cards. A two-line title can then no longer push its
   own rule and copy out of line with a one-line neighbour.
   ══════════════════════════════════════════════════════════════════ */

/* ── Why Participate (.goal cards) ─────────────────────────────────
   The home page's .goal floats its number beside a fixed-width title,
   which only stays aligned because those titles carry hand-placed
   <br>s. These titles come from the workbook and wrap freely, so the
   card becomes a two-column grid instead. */
.obj__grid--five { grid-auto-rows: auto; align-items: start; }
.obj__grid--five .goal {
  display: grid;
  grid-template-columns: 87.3px minmax(0, 1fr);
  grid-template-rows: subgrid;
  grid-row: span 3;
  align-content: start;
  column-gap: 0;
}
.obj__grid--five .goal__n { grid-column: 1; grid-row: 1; float: none; width: auto; }
.obj__grid--five .goal__t { grid-column: 2; grid-row: 1; width: auto; margin: 2.9px 0 0; }
.obj__grid--five .goal__rule { grid-column: 1 / -1; grid-row: 2; align-self: start; margin-top: 9.09px; }
.obj__grid--five .goal__p { grid-column: 1 / -1; grid-row: 3; align-self: start; }

/* ── Target Sectors ────────────────────────────────────────────────
   .zone reserves 70px of top padding for the coloured header strip,
   which these cards do not have. */
.sector { min-height: 0; padding-top: 26px; }
.sector .zone__body { align-self: start; }

/* ── Who Attends ───────────────────────────────────────────────────*/
.who__grid { grid-auto-rows: auto; align-items: start; }
.who {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;
  align-content: start;
}
.who .goal__rule { align-self: start; margin-top: 14px; }
.who__p { margin-top: 14px; align-self: start; }

/* ── Forum Pillars ─────────────────────────────────────────────────*/
.pcard__grid { grid-auto-rows: auto; align-items: start; }
.pcard {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 4;              /* image · title · rule · body */
  align-content: start;
}
.pcard__t { margin-top: clamp(18px, 2vw, 26px); align-self: start; }
.pcard .goal__rule { align-self: start; margin-top: 14px; }
.pcard__p { align-self: start; }

/* ── Participation Timeline ────────────────────────────────────────*/
.tl__grid { grid-auto-rows: auto; align-items: stretch; }
.tl {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 5;              /* number · title · date · rule · list */
  align-content: start;
}
.tl .goal__n { float: none; width: auto; }
.tl .goal__t { width: auto; margin: 6px 0 0; }
.tl .goal__rule { align-self: start; margin-top: 14px; }
.tl__list { align-self: start; }

/* ── Media channels and accreditation ──────────────────────────────*/
.chan__grid, .acc__grid { grid-auto-rows: auto; align-items: start; }
.chan, .acc {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;              /* title · rule · list */
  align-content: start;
}
.chan .goal__rule, .acc .goal__rule { align-self: start; margin-top: 12px; }
.chan__list, .acc__list { align-self: start; }


/* ══════════════════════════════════════════════════════════════════
   MOTION — the same reveal, stagger and rule-sweep as the home page
   ------------------------------------------------------------------
   sections.css defines the stagger delays and the shine only as far
   as the sixth child, which covers the home page's largest grid.
   Target Sectors and Who Attends carry eight, so the sequence is
   continued here on the same .09s step.
   ══════════════════════════════════════════════════════════════════ */
[data-reveal="stagger"].is-in > *:nth-child(7)  { transition-delay: .54s; }
[data-reveal="stagger"].is-in > *:nth-child(8)  { transition-delay: .63s; }
[data-reveal="stagger"].is-in > *:nth-child(9)  { transition-delay: .72s; }
[data-reveal="stagger"].is-in > *:nth-child(10) { transition-delay: .81s; }

[data-reveal="stagger"].is-in > *:nth-child(7)  .goal__rule::after { animation-delay: .84s; }
[data-reveal="stagger"].is-in > *:nth-child(8)  .goal__rule::after { animation-delay: .93s; }
[data-reveal="stagger"].is-in > *:nth-child(9)  .goal__rule::after { animation-delay: 1.02s; }
[data-reveal="stagger"].is-in > *:nth-child(10) .goal__rule::after { animation-delay: 1.11s; }

/* hover, matching .nums__cell and .zone on the home page */
.pcard, .who, .tl, .chan, .acc { transition: transform .45s cubic-bezier(.22, .61, .36, 1); }
.pcard:hover, .who:hover { transform: translateY(-4px); }
.tl:hover { transform: translateY(-4px); }
.pcard img { transition: filter .45s ease; }
.pcard:hover img { filter: brightness(1.08); }

@media (prefers-reduced-motion: reduce) {
  .pcard:hover, .who:hover, .tl:hover { transform: none; }
}


/* ══════════════════════════════════════════════════════════════════
   TYPOGRAPHY — measured against the home page
   ------------------------------------------------------------------
   Every value below is taken from its home-page counterpart rather
   than chosen here:
     running prose   .about__body   --t-lede  / 1.6
     card body       .goal__p       --t-body  / 1.5
     card title      .goal__t       --t-sub   / 1.25 / 600 Conthrax
     list copy       .zone__body p  --t-small / 1.5  / 300 Alexandria
   ══════════════════════════════════════════════════════════════════ */

/* running prose — .goal__p metrics, not the 1.95 leading used before */
.pg__prose p {
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--ink);
}
.pg__prose p + p { margin-top: 1.25em; }

/* the opening line of a section — .about__body */
.page-lede {
  font-size: var(--t-lede) !important;
  line-height: 1.6 !important;
  color: var(--ink) !important;
  font-weight: 400;              /* .about__body is 400 — size carries the hierarchy */
}

/* card titles — .goal__t */
.who__t, .pcard__t, .chan__t, .acc__t, .prog__arch-t {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--t-sub);
  line-height: 1.25;
  color: var(--ink);
}

/* card bodies — .goal__p */
.who__p, .pcard__p {
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--ink);
}

/* list copy — .zone__body p */
.tl__list li, .chan__list li, .acc__list li, .prog__list li {
  font-family: var(--f-alt);
  font-weight: 300;
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--ink);
}
.tl__list li + li { margin-top: 14px; }
.tl__list li::before, .prog__list li::before { top: 10px; }
.prog__list li { padding-top: 13px; padding-bottom: 13px; }




/* ══════════════════════════════════════════════════════════════════
   SUBGRID ROW GAPS
   ------------------------------------------------------------------
   A subgrid inherits its parent's gap between its own rows. The card
   grids need a wide gap BETWEEN cards, which was then also being
   applied between each card's number, title, date, rule and copy —
   up to 44px of dead space inside every card. The cards restate a
   row-gap of their own; the element margins, which already match the
   home page's, do the internal spacing.
   ══════════════════════════════════════════════════════════════════ */
.obj__grid--five .goal,
.who,
.pcard,
.tl,
.chan,
.acc { row-gap: 0; }

/* with the inherited gap gone, these carry the home page's own steps */
.tl .goal__t   { margin-top: 14px; }
.tl__when      { margin-top: 8px; }
.tl .goal__rule{ margin-top: 18px; }
.tl__list      { margin-top: 13px; }   /* lands on the home zone card's 36px rule-to-copy step */
.tl__list li + li { margin-top: 12px; }
.who .goal__rule, .pcard .goal__rule { margin-top: 12px; }
.who__p { margin-top: 12.43px; }              /* .goal__p's own margin */
.pcard__p { margin-top: 6px; }
.chan .goal__rule, .acc .goal__rule { margin-top: 12px; }
.chan__list, .acc__list { margin-top: 12px; }


/* Subgrid makes every card's rule share one row, so a one-line title in a
   row whose tallest title runs to three lines leaves slack somewhere. Left
   at the default it opens between the title and its rule, which is the one
   gap that reads as broken. Anchoring the title to the bottom of its row
   moves that slack above the title instead, where it sits against the
   image or the number and is invisible. */
/* Titles start on the same line across a row. Anchoring them to the bottom
   of their shared subgrid row kept the gap to the rule even, but pushed a
   two-line title down so its first line sat below a three-line neighbour's.
   Aligned to the top, every title in a row begins together — the slack from
   the differing lengths falls above the rule instead, where it is even
   across the row because the rules share their own row. */
.pcard__t, .who__t, .tl .goal__t, .chan__t, .acc__t { align-self: start; }
/* A one-line title in a row whose tallest runs to two lines was sitting on
   the second line, dragging its number down with it. Centred, it sits
   between the two — the rules still share their own subgrid row, so the
   alignment across the row is unaffected. */
.obj__grid--five .goal__t, .obj__grid--five .goal__n { align-self: center; }


/* the bar joins the site's ?flat=1 QA mode: the preview pane reports
   document.hidden, which freezes transitions mid-flight and makes the
   scrolled state read as transparent even when it is applied */
.is-flat .topbar,
.is-flat .topbar__lockup { transition: none; }


/* ── brochure viewer ────────────────────────────────────────────────
   A page whose job is to show one PDF. The bar carries the title and an
   explicit Download control; the object below fills whatever height is
   left. Exists because a bare .pdf link downloads silently on most
   browsers, and the Content-Disposition header that would fix that is not
   available on this host. */
.is-doc { min-height: 100vh; display: flex; flex-direction: column; }
.topbar--doc { position: static; background: rgba(18, 30, 23, .97); border-bottom: 1px solid var(--line-soft); }

.doc { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }

.doc__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(12px, 2vw, 28px);
  width: var(--col);
  margin-inline: auto;
  padding: clamp(16px, 2.4vw, 26px) 0;
  flex-wrap: wrap;
}
.doc__t {
  margin: 0;
  font-family: var(--font-display, inherit);
  font-size: clamp(19px, 2.4vw, 30px);
  line-height: 1.2;
  color: var(--ink-strong);
}
.doc__dl { flex: none; }

.doc__view {
  flex: 1 1 auto;
  width: 100%;
  min-height: 60vh;
  border: 0;
  background: rgba(0, 0, 0, .28);
}
.doc__fallback {
  width: var(--col);
  margin-inline: auto;
  padding: 48px 0;
  color: var(--ink);
}
.doc__fallback a { text-decoration: underline; text-underline-offset: 3px; }

/* on a phone the bar stacks so the download control keeps a full-width tap area */
@media (max-width: 599px) {
  .doc__bar { flex-direction: column; align-items: stretch; gap: 14px; }
  .doc__dl { text-align: center; }
  .doc__view { min-height: 70vh; }
}

/* ── exhibiting companies ───────────────────────────────────────────
   Grouped by exhibition zone, every company visible at once. An earlier
   version scrolled each zone sideways to keep the section short — but that
   hid most of the names behind a scrollbar, and a company list exists to be
   read, not swiped. The grid wraps to four columns and steps down with the
   viewport instead. */
.exh__count {
  margin: 6px 0 0;
  color: var(--ink);
  opacity: .7;
  font-size: var(--t-micro, 13px);
  letter-spacing: .04em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.exh__shelves { margin-top: clamp(28px, 3.4vw, 48px); }
.exh__shelf + .exh__shelf { margin-top: clamp(30px, 3.4vw, 48px); }

.exh__zt {
  margin: 0 0 14px;
  font-size: var(--t-h3, clamp(15px, 1.4vw, 19px));
  line-height: 1.3;
  color: var(--ink-strong);
}

.exh__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(12px, 1.2vw, 18px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.exh__card {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: clamp(15px, 1.4vw, 19px);
  background: rgba(255, 255, 255, .035);
  border: 1px solid var(--line-soft);
  border-radius: 3px;
  transition: background .25s ease, border-color .25s ease;
}
.exh__card:hover { background: rgba(255, 255, 255, .065); border-color: var(--line); }

/* the logo band is always present, so artwork arriving later cannot reflow
   the grid. Until a company sends its own, the YCSF mark stands in, muted
   hard so nobody mistakes it for the exhibitor's logo. */
.exh__band { display: flex; align-items: center; height: 30px; }
.exh__logo { max-width: 78%; max-height: 30px; width: auto; height: auto; object-fit: contain; }
.exh__logo--ph { opacity: .2; filter: grayscale(1); max-width: 52%; }

.exh__name {
  margin: 0;
  font-size: var(--t-body, 14.5px);
  line-height: 1.42;
  font-weight: 500;
  color: var(--ink-strong);
}

.exh__p { margin: 0; font-size: var(--t-micro, 13px); line-height: 1.6; color: var(--ink); opacity: .8; }

.exh__link {
  margin-top: auto;
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--t-micro, 13px);
  color: var(--ink-strong);
  transition: gap .2s ease;
}
.exh__link:hover { gap: 11px; text-decoration: underline; text-underline-offset: 3px; }
.exh__arrow {
  width: 7px; height: 7px;
  border-top: 1.5px solid currentColor;
  border-inline-end: 1.5px solid currentColor;
  transform: rotate(45deg);
}
[dir="rtl"] .exh__arrow { transform: rotate(-45deg); }   /* top + inline-end (the left, in RTL) corner, turned to point left */

@media (max-width: 1099px) { .exh__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 799px)  { .exh__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 519px)  { .exh__grid { grid-template-columns: 1fr; } }


/* ── banner preview options, in the main menu (staging only) ─────────
   app.js adds a Banner preview item to the nav on pages that carry the
   banner videos, so the client switches options from the menu itself and
   the banner stays clean. The same markup serves the burger panel. */
.sitenav__sub--opts { min-width: max(240px, 100%); }
.sitenav__opt {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 9px 18px;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: start;
  cursor: pointer;
}
.sitenav__opt:hover,
.sitenav__opt:focus-visible { background: rgba(255, 255, 255, .07); color: var(--ink-strong); }
.sitenav__opt[aria-pressed="true"] { color: var(--ink-strong); }
.sitenav__opt[aria-pressed="true"] .sitenav__opt-n { background: #1a6b3c; }
/* an option whose footage is not on the server yet: shown, but not offered */
.sitenav__opt.is-off { opacity: .38; cursor: not-allowed; }
.sitenav__opt.is-off:hover { background: none; }
.sitenav__opt-n {
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 700;
  background: rgba(255, 255, 255, .16);
}


/* ── Networking and Attend, rebuilt from the page decks (staging) ─────
   Rendered by the match / cards / steps / signing / band / days / ways
   kinds in build_pages.py from _src/pages_v2.py. Site vocabulary: the
   brand-ramp card border, Conthrax titles, the goal rule, the stat
   gradient. Logical properties throughout, so Arabic mirrors itself. */

/* page hero: lede, call to action and headline figures under the title */
.hero--intro .hero__stage { padding-bottom: clamp(40px, 4.6vw, 72px); }
.pghero__lede {
  max-width: 58ch;
  margin-top: clamp(16px, 1.8vw, 26px);
  font-family: var(--f-body);
  font-size: var(--t-lede);
  line-height: 1.7;
  color: var(--ink-soft);
}
.xcta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px clamp(16px, 1.8vw, 26px);
  margin-top: clamp(20px, 2.2vw, 32px);
}
/* may wrap: the Arabic "register MoU interest" is wider than a card on a
   360px phone, and a clipped label is worse than a two-line button */
.xcta .btn {
  height: auto;
  min-height: 44px;
  max-width: 100%;
  padding: 11px 26px;
  font-size: clamp(13px, 1vw, 15px);
  line-height: 1.3;
  white-space: normal;
  text-align: center;
}
.xcta__note { font-family: var(--f-body); font-weight: 700; font-size: var(--t-small); }
.xcta__note--red   { color: #e8837c; }
.xcta__note--green { color: #72c792; }
html[data-theme="light"] .xcta__note--red   { color: var(--red); }
html[data-theme="light"] .xcta__note--green { color: #1a6b3c; }

.kpis {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  row-gap: 18px;
  margin: clamp(26px, 3vw, 44px) 0 0;
  padding: clamp(18px, 2vw, 26px) 0 0;
  list-style: none;
  border-top: 1px solid var(--line);
}
.kpi { padding: 4px clamp(12px, 1.6vw, 24px); border-inline-start: 1px solid var(--line); }
@media (max-width: 759px) {
  .kpi:nth-child(odd) { border-inline-start: 0; padding-inline-start: 0; }
  .kpis--5 .kpi:last-child { grid-column: 1 / -1; }
}
@media (min-width: 760px) {
  .kpis--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .kpis--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .kpi:first-child { border-inline-start: 0; padding-inline-start: 0; }
}
.kpi__val {
  display: inline-block;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(24px, 2.4vw, 38px);
  line-height: 1.1;
  background: linear-gradient(90deg, var(--num-a), var(--num-b));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* "20+" not "+20" in Arabic: same rule the home page's figures use (ar.css) */
[dir="rtl"] .kpi__val { direction: ltr; unicode-bidi: isolate; }
.kpi__cap {
  display: block;
  margin-top: 8px;
  font-family: var(--f-body);
  font-size: var(--t-small);
  line-height: 1.4;
  color: var(--ink-soft);
}

/* section chrome */
.pg--alt { background: #16221b; }
html[data-theme="light"] .pg--alt { background: var(--bg-2); }   /* the brand cream, as on the home page */
.xsec__eyebrow { margin-bottom: 10px; font-size: clamp(14px, 1.2vw, 18px); letter-spacing: .12em; }
.xsec__lede {
  max-width: var(--measure);
  margin: 16px auto 0;
  text-align: center;
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.8;
  color: var(--ink-soft);
}

/* the match: Saudi Arabia on the reading side, China opposite, the six
   shared sectors between them */
.match { max-width: 1040px; margin: var(--s-head) auto 0; }
.match__head {
  display: flex;
  justify-content: space-between;
  margin-bottom: 16px;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--t-micro);
  letter-spacing: .14em;
  text-transform: uppercase;
}
.match__side--sa { color: #72c792; }
.match__side--cn { color: #e8837c; }
html[data-theme="light"] .match__side--sa { color: #1a6b3c; }
html[data-theme="light"] .match__side--cn { color: var(--red); }
.match__rows { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.match__row {
  display: grid;
  grid-template-columns: 14px minmax(16px, 1fr) minmax(0, 440px) minmax(16px, 1fr) 14px;
  align-items: center;
}
.match__dot { width: 14px; height: 14px; border-radius: 50%; }
.match__dot--sa { background: #5fb07f; }
.match__dot--cn { background: #e07a72; }
.match__line { height: 1px; background: var(--line); }
.match__sector {
  padding: 12px 18px;
  text-align: center;
  font-family: var(--f-body);
  font-weight: 600;
  font-size: var(--t-small);
  line-height: 1.35;
  color: var(--ink);
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--line-soft);
  border-radius: 2px;
}
@media (max-width: 599px) {
  .match__row { grid-template-columns: 10px 12px minmax(0, 1fr) 12px 10px; }
  .match__dot { width: 10px; height: 10px; }
  .match__sector { padding: 10px 8px; }
}

/* cards: the brand-ramp border around a title, a rule and copy */
.xcards {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(14px, 1.4vw, 20px);
  margin-top: var(--s-head);
}
.xsec__lede + .xcards { margin-top: clamp(26px, 3vw, 44px); }
@media (min-width: 700px) {
  .xcards--2, .xcards--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xcards--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 1100px) { .xcards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.xcards--2 { max-width: 900px; margin-inline: auto; }
.xcard {
  position: relative;
  padding: clamp(22px, 2.4vw, 34px) clamp(20px, 2.2vw, 30px);
  border-radius: 10px;
  background: rgba(255, 255, 255, .03);
  transition: transform .45s cubic-bezier(.22, .61, .36, 1), filter .45s ease;
}
.xcard:hover { transform: translateY(-5px); filter: drop-shadow(0 13px 24px var(--shadow)); }
.xcard__t {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--t-sub);
  line-height: 1.3;
  color: var(--ink);
}
.xcard__rule { display: block; height: 1px; margin: 16px 0 14px; background: var(--line); }
.xcard__p {
  margin: 0;
  font-family: var(--f-body);
  font-size: var(--t-small);
  line-height: 1.75;
  color: var(--ink-soft);
}
.xday__list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.xday__list li {
  position: relative;
  padding-inline-start: 20px;
  font-family: var(--f-body);
  font-size: var(--t-small);
  line-height: 1.6;
  color: var(--ink-soft);
}
.xday__list li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: .5em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--a);
}
.xway { display: flex; flex-direction: column; }
.xway .xcard__p { flex: 1; }
.xway .xcta { margin-top: 22px; }

/* how matching works: four numbered steps beside the photograph */
.xsteps {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(28px, 3.4vw, 56px);
  align-items: center;
  margin-top: var(--s-head);
}
.xsec__lede + .xsteps { margin-top: clamp(26px, 3vw, 44px); }
@media (min-width: 960px) { .xsteps { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); } }
.xsteps__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(24px, 2.6vw, 38px) clamp(18px, 2.2vw, 32px);
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (max-width: 479px) { .xsteps__grid { grid-template-columns: minmax(0, 1fr); } }
.xstep__n { display: block; font-family: var(--f-display); font-weight: 600; font-size: var(--t-sub); color: #72c792; }
html[data-theme="light"] .xstep__n { color: #1a6b3c; }
.xstep__t { margin: 6px 0 0; font-family: var(--f-display); font-weight: 600; font-size: var(--t-sub); color: var(--ink); }
.xstep .goal__rule { margin-top: 12px; }
.xstep__p {
  margin: 12px 0 0;
  font-family: var(--f-body);
  font-size: var(--t-small);
  line-height: 1.7;
  color: var(--ink-soft);
}
.xsteps__pic { margin: 0; }
.xsteps__pic img { display: block; width: 100%; height: auto; border-radius: 10px; }

/* signings: four points and the call to action */
.xsign { max-width: 640px; margin: clamp(26px, 3vw, 44px) auto 0; }
.xsign__list { display: grid; gap: 14px; margin: 0; padding: 0; list-style: none; }
.xsign__list li {
  position: relative;
  padding-inline-start: 30px;
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--ink);
}
.xsign__list li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: .8em;
  width: 16px;
  height: 2px;
  background: #e07a72;
}
.xsign .xcta { margin-top: clamp(24px, 2.8vw, 38px); }

/* closing strip */
.xband { padding-block: clamp(34px, 4vw, 60px); background: #285038; }
.xband__in { text-align: center; }
.xband__t {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(20px, 2.2vw, 34px);
  line-height: 1.25;
  color: #f3eee2;
}
.xband__note { margin: 10px 0 0; font-family: var(--f-body); font-size: var(--t-small); color: rgba(243, 238, 226, .82); }

@media (prefers-reduced-motion: reduce) { .xcard:hover { transform: none; } }

/* Download Visitor Journey, under Around Yanbu's note on Attend (appears once
   the PDF is on the site; see pages_v2.JOURNEY) */
.ay__journey {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: clamp(18px, 2vw, 28px);
}
/* until the PDF is on the site: visible, but plainly not a link */
.ay__journey .is-soon { cursor: default; opacity: .6; filter: saturate(.7); }
.ay__journey .is-soon:hover { transform: none; }
.ay__journey .is-soon::after { display: none; }
.ay__journey-note { font-family: var(--f-body); font-size: var(--t-micro); color: rgba(243, 238, 226, .75); }
.ay__journey .btn { height: auto; min-height: 44px; padding: 11px 28px; font-size: clamp(13px, 1vw, 15px); }

/* ── exhibitor logos and websites (exhibitor_details.py) ──────────────
   Logos arrive on white, on transparency, wide and square, so each sits on
   the same white plate and is fitted inside it. A card with a website is a
   link as a whole: the company name carries the href and its ::after
   stretches over the card. */
.exh__card { position: relative; }
.exh__band--logo {
  justify-content: center;
  height: 76px;
  padding: 10px 14px;
  background: #fff;
  border-radius: 2px;
}
.exh__band--logo .exh__logo { max-width: 100%; max-height: 56px; }
.exh__hit { color: inherit; text-decoration: none; }
.exh__hit::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.exh__hit:focus-visible { outline: none; }
.exh__card--link { cursor: pointer; }
.exh__card--link:focus-within { outline: 2px solid var(--ink-strong); outline-offset: 2px; }
.exh__card--link:hover .exh__link { gap: 11px; text-decoration: underline; text-underline-offset: 3px; }

/* ── inner-page banner: the dusk harbour-and-refinery image (staging) ──
   From "Website Banner (1).pptx". Framed on the lit skyline and the
   harbour just below the horizon, so the short page banner shows the
   plant rather than empty sky or water. Below 1100
   the photograph's shading was written for the busy neon tower and all but
   blacked this image out on a phone; the title keeps its own shade band, so
   the wash here only has to meet the page ground at the bottom. */
.hero--aerial .hero__photo--inner { object-position: 50% 52%; }
@media (max-width: 1099px) {
  .hero--aerial .hero__bg::after {
    background: linear-gradient(to bottom,
      rgba(var(--scrim), .18) 0%, rgba(var(--scrim), .32) 50%,
      rgba(var(--scrim), .82) 88%, var(--bg) 100%);
  }
}

/* ── Sponsors & Partners, two marks only (staging) ─────────────────────
   Kareem kept Sinopec and aramco and held the rest with `hidden`. The cell
   rule sets display:grid, which would override the attribute, so hidden is
   restated here. Two marks cannot loop, so the rail stands still, centred,
   without the edge fade. */
.spons__cell[hidden] { display: none; }
.spons--pair .spons__rail { -webkit-mask: none; mask: none; }
.spons--pair .spons__track {
  width: auto;
  justify-content: center;
  animation: none;
  transform: none;
}

/* the two partner marks, larger (Kareem, 16 Sep 2026). Sources are 400px
   (Sinopec) and 760px (aramco, his new artwork), so they stay sharp. */
/* the divider cell keeps its zero padding; only the two marks get air */
.spons--pair .spons__cell:not(.spons__cell--sep) { padding-inline: clamp(28px, 3.6vw, 64px); }
.spons--pair .spons__logo--p1 { width: min(180.5px, 22.8vw); height: min(180.5px, 22.8vw); }   /* 5% smaller (Kareem) */
.spons--pair .spons__logo--p2 { width: min(361px, 45.6vw); height: auto; aspect-ratio: auto; }
.spons--pair .spons__sep { height: clamp(110px, 12vw, 170px); }
@media (max-width: 599px) {
  .spons--pair .spons__cell:not(.spons__cell--sep) { padding-inline: clamp(12px, 4vw, 20px); }
  .spons--pair .spons__logo--p1 { width: min(98.8px, 24.7vw); height: min(98.8px, 24.7vw); }
  .spons--pair .spons__logo--p2 { width: min(180.5px, 43.7vw); height: auto; }
  .spons--pair .spons__sep { height: 92px; }
}

/* ══ LIGHT MODE (staging) ══════════════════════════════════════════════
   The switch is staging-only markup (locales.LIVE_STRIP takes it and the
   theme-boot script out of the live cut), so none of this can apply on
   live: html[data-theme="light"] is only ever set by that switch.

   Pieces that stay on the dark palette in light mode. The banner photograph
   and video do not change with the theme, so everything on them keeps its
   light ink; the menu bar sits over the banner and must read the same; the
   patronage card and the Participating Companies strip carry the approved
   white logos, which have no dark versions; the feature cards' captions sit
   on their photographs. Re-declaring the tokens flips everything inside. */
html[data-theme="light"] :is(.topbar, .hero, .pat-card, .spons--pair, .feat__face--front) {
  --bg:            #1b2a21;
  --bg-2:          #16261d;
  --ink:           #f3eee2;
  --ink-strong:    #ffffff;
  --ink-soft:      rgba(243, 238, 226, .78);
  --ink-faint:     rgba(243, 238, 226, .55);
  --surface:       rgba(255, 255, 255, .05);
  --surface-2:     rgba(255, 255, 255, .10);
  --line:          rgba(255, 255, 255, .20);
  --line-soft:     rgba(255, 255, 255, .10);
  --hairline:      var(--ink);
  --shadow:        rgba(0, 0, 0, .38);
  --shadow-strong: rgba(0, 0, 0, .45);
  --glow-strength: 1;
  --scrim:         27, 42, 33;
  --muted:         #92aea3;
  --num-a: #2da15e;
  --num-b: #ff4a47;
  color: var(--ink);
}
/* in dark mode the banner shows the page ground wherever its photograph ends
   (the figures row at its foot); on a white page it has to paint that itself */
html[data-theme="light"] .hero { background: var(--bg); }
/* the card's own ground, cut to its chamfered frame; the glow comes back */
html[data-theme="light"] .pat-card {
  background: var(--bg);
  clip-path: var(--chamfer);
  box-shadow: none;
}
html[data-theme="light"] .pat-card__glow { opacity: 1; }
html[data-theme="light"] .spons--pair { background: var(--bg); }

/* secondary lines that sat just under 4.5:1 on white */
html[data-theme="light"] :is(.tl__when, .pg__tba) { color: var(--ink-soft); }

/* ── the switch ─────────────────────────────────────────────────────
   Bottom corner, clear of the page's content. The label is written by
   theme() in app.js in the page's language, and the button stays hidden
   until then, so a page without the script shows no dead control. */
.theme-switch {
  position: fixed;
  z-index: 60;
  inset-block-end: clamp(14px, 1.8vw, 26px);
  inset-inline-end: clamp(14px, 1.8vw, 26px);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding-block: 7px;
  padding-inline: 16px 7px;
  border: 1px solid rgba(243, 238, 226, .30);
  border-radius: 999px;
  background: rgba(18, 30, 23, .86);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: #f3eee2;
  font-family: var(--f-body);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .32);
  transition: background .3s ease, color .3s ease, border-color .3s ease, transform .3s cubic-bezier(.34, 1.3, .5, 1);
}
.theme-switch[hidden] { display: none; }
.theme-switch:hover { transform: translateY(-2px); border-color: rgba(243, 238, 226, .5); }
.theme-switch:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }
.theme-switch__track {
  position: relative;
  flex: none;
  width: 42px;
  height: 24px;
  border-radius: 999px;
  background: rgba(243, 238, 226, .24);
  transition: background .3s ease;
}
.theme-switch__knob {
  position: absolute;
  top: 3px;
  inset-inline-start: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #ffffff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
  transition: transform .3s cubic-bezier(.34, 1.3, .5, 1);
}
.theme-switch[aria-checked="true"] .theme-switch__track { background: var(--green); }
.theme-switch[aria-checked="true"] .theme-switch__knob { transform: translateX(18px); }
[dir="rtl"] .theme-switch[aria-checked="true"] .theme-switch__knob { transform: translateX(-18px); }
html[data-theme="light"] .theme-switch {
  border-color: rgba(31, 77, 58, .18);
  background: rgba(255, 255, 255, .94);
  color: #0c1410;
  box-shadow: 0 6px 20px rgba(31, 77, 58, .18);
}
html[data-theme="light"] .theme-switch:hover { border-color: rgba(31, 77, 58, .36); }
.is-flat .theme-switch, .is-flat .theme-switch * { transition: none; }
@media (max-width: 599px) {
  .theme-switch { gap: 8px; padding-inline: 12px 6px; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .theme-switch, .theme-switch * { transition: none; }
}

/* ── the banner overlay, light mode ──────────────────────────────────
   Kareem, 21 Sep 2026: "can you make hero overlay brighter?" → drawn in the
   brand green; "make overlay more transparent" → 40% lighter; then "remove
   the overlay". In light mode the film now plays with no shade over it and
   no band behind the headline. The fade at the bottom stays: the figures row
   sits on it. Legibility re-measured with _src/qa/hero-backdrop over all four
   banner films. */
html[data-theme="light"] .hero__video::after { background: none; }
html[data-theme="light"] .hero__title::before {
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* The hero date line and the countdown are hidden on the staging home page
   (Kareem's marked screenshot, 4 Oct 2026). Both carry `hidden` in the markup;
   their own rules set display, which beats the attribute, so it is restated
   here. The location line beside the date is untouched, and the live cut keeps
   its frozen hero, where neither element carries the attribute. */
.hero__meta .meta[hidden],
.countdown[hidden] { display: none !important; }

/* The footer's Exhibition Dates & Timings column is hidden (Kareem's marked
   screenshot, 6 Oct 2026). It keeps its markup and carries `hidden`; the
   column rule sets its own box, so the attribute is restated here, and the
   row drops to three tracks so the remaining columns spread evenly. Remove
   the attribute in index.html and both rules stand down on their own. */
.ftr__col[hidden] { display: none !important; }

/* ══ POSTPONEMENT POPUP (staging) ══════════════════════════════════════
   Kareem's artwork, 10 Oct 2026: it meets a first-time visitor on the home
   page and closes to let them browse. Staging-only markup, so none of this
   can apply on live. The sheet is the artwork plus a close button; the
   backdrop and the Escape key close it too (app.js). */
.popup {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(16px, 4vw, 48px);
  background: rgba(8, 14, 11, .72);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  opacity: 0;
  transition: opacity .32s ease;
}
.popup[hidden] { display: none; }
.popup.is-open { opacity: 1; }
.popup__sheet {
  position: relative;
  width: min(760px, 100%);
  border-radius: clamp(10px, 1vw, 16px);
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .55);
  transform: translateY(14px) scale(.985);
  transition: transform .32s cubic-bezier(.22, 1, .36, 1);
}
.popup.is-open .popup__sheet { transform: none; }
.popup__art { display: block; width: 100%; height: auto; }
.popup__close {
  position: absolute;
  top: clamp(8px, 1.4vw, 14px);
  inset-inline-end: clamp(8px, 1.4vw, 14px);
  z-index: 1;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid rgba(22, 38, 29, .18);
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  color: #16261d;
  font-family: var(--f-body);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  transition: background .25s ease, transform .25s ease;
}
.popup__close:hover { background: #fff; transform: scale(1.06); }
.popup__close:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .popup, .popup__sheet { transition: none; }
}
