/* SSBMT home hero — redesign. All classes start with .hx- so they never clash with Bootstrap or custom.css.
   Brand: maroon #800000 / #5a0000, green #228B22, system font (same as the site). */
.hx {
  --hx-maroon: #800000; --hx-maroon-dk: #3d0508; --hx-green: #228B22; --hx-green-dk: #1b6f1b;
  --hx-ink: #fff; --hx-soft: rgba(255,255,255,.78); --hx-line: rgba(255,255,255,.18);
  position: relative; isolation: isolate; overflow: hidden; color: var(--hx-ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  background: var(--hx-maroon-dk);
}
/* sizes include padding and borders (Bootstrap does this too; repeated so the hero never depends on it) */
.hx, .hx *, .hx *::before, .hx *::after { box-sizing: border-box; }
/* the photo: calm and in the background (no red flood over everything) */
/* SSBMT: the spec's img/hall.jpg is this site's own hero photograph. */
.hx__bg { position: absolute; inset: 0; z-index: -2; background: url("../images/Education3-2.jpg") center 40% / cover no-repeat; filter: saturate(.35) contrast(1.05) brightness(.85); }   /* the same hall photo on every slide (fixed), calmer */
.hx::before { content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(90deg, rgba(45,4,8,.97) 0%, rgba(70,6,10,.90) 42%, rgba(90,8,12,.62) 70%, rgba(90,8,12,.45) 100%),
    linear-gradient(0deg, rgba(25,2,4,.85) 0%, rgba(25,2,4,0) 35%); }

.hx__wrap { max-width: 1200px; margin: 0 auto; padding: 72px 24px 0; }
/* all slides sit in the same grid cell: the hero keeps the height of the tallest slide, so nothing jumps */
.hx__slides { display: grid; }
.hx__slide { grid-area: 1 / 1; display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 56px; align-items: center;
  opacity: 0; visibility: hidden; transform: translateY(8px); transition: opacity .5s ease, transform .5s ease, visibility .5s; }
.hx__slide.is-active { opacity: 1; visibility: visible; transform: none; }

.hx__eyebrow { display: inline-flex; align-items: center; gap: 10px; margin: 0 0 20px; padding: 7px 14px; border: 1px solid var(--hx-line); border-radius: 99px;
  background: rgba(255,255,255,.06); font-size: 13px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
.hx__eyebrow i { width: 8px; height: 8px; border-radius: 50%; background: #5BD16A; box-shadow: 0 0 0 4px rgba(91,209,106,.22); }
.hx__title { margin: 0 0 12px; font-size: clamp(30px, 3.6vw, 46px); line-height: 1.12; font-weight: 800; letter-spacing: -.015em; text-wrap: balance; }
.hx__sub { margin: 0 0 18px; font-size: 19px; line-height: 1.4; color: var(--hx-soft); }
.hx__meta { display: flex; flex-wrap: wrap; gap: 10px; margin: 0 0 26px; padding: 0; list-style: none; }
.hx__meta li { display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: 10px; background: rgba(255,255,255,.08); font-size: 16px; font-weight: 600; }
.hx__meta svg { width: 18px; height: 18px; opacity: .85; }

.hx__count { margin: 0 0 30px; }
.hx__count p { margin: 0 0 10px; font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--hx-soft); }
.hx__tiles { display: grid; grid-template-columns: repeat(4, 84px); gap: 10px; }
.hx__tile { padding: 12px 6px 10px; border: 1px solid var(--hx-line); border-radius: 12px; background: rgba(0,0,0,.22); text-align: center; }
.hx__tile b { display: block; font-size: 30px; line-height: 1; font-weight: 800; font-variant-numeric: tabular-nums; }
.hx__tile span { display: block; margin-top: 6px; font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--hx-soft); }

.hx__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.hx__btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 52px; padding: 0 24px; border-radius: 12px;
  font-size: 16px; font-weight: 700; text-decoration: none; white-space: nowrap; transition: background-color .2s, border-color .2s, transform .2s; }
.hx__btn svg { width: 20px; height: 20px; }
.hx__btn--main { background: var(--hx-green); color: #fff; box-shadow: 0 10px 24px -12px rgba(0,0,0,.6); }
.hx__btn--main:hover { background: var(--hx-green-dk); transform: translateY(-1px); }
.hx__btn--line { border: 1.5px solid rgba(255,255,255,.55); color: #fff; }
.hx__btn--line:hover { border-color: #fff; background: rgba(255,255,255,.08); }
.hx__btn--icon { width: 52px; padding: 0; border: 1.5px solid rgba(255,255,255,.55); color: #fff; }
.hx__btn--poster { display: none; }

/* the poster: the event's artwork, framed, with "View poster" */
.hx__poster { position: relative; display: block; border-radius: 16px; overflow: hidden; background: #000; text-decoration: none;
  box-shadow: 0 40px 70px -30px rgba(0,0,0,.85), 0 0 0 1px rgba(255,255,255,.14); aspect-ratio: 1600 / 1143; }
.hx__poster img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.hx__poster span { position: absolute; right: 14px; bottom: 14px; display: inline-flex; align-items: center; gap: 8px; padding: 9px 14px; border-radius: 99px;
  background: rgba(0,0,0,.62); color: #fff; font-size: 14px; font-weight: 700; backdrop-filter: blur(6px); }
.hx__poster:hover img { transform: scale(1.03); }

/* the event switcher: all three events visible, the active one with a running progress line */
.hx__nav { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; margin: 64px 0 0; border-top: 1px solid var(--hx-line); }
.hx__tab { position: relative; display: block; padding: 20px 22px 26px 0; border: 0; background: none; color: var(--hx-soft); text-align: left; cursor: pointer; font: inherit; }
.hx__tab + .hx__tab { padding-left: 22px; border-left: 1px solid var(--hx-line); }
.hx__tab small { display: block; margin-bottom: 6px; font-size: 13px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.hx__tab b { display: block; overflow: hidden; font-size: 16px; font-weight: 600; line-height: 1.35; white-space: nowrap; text-overflow: ellipsis; }
.hx__tab::before { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 3px; background: transparent; }
.hx__tab.is-active { color: #fff; }
.hx__tab.is-active::before { background: rgba(255,255,255,.25); }
.hx__tab i { position: absolute; left: 0; top: -1px; height: 3px; width: 0; background: #fff; }
.hx__tab.is-active i { animation: hx-run var(--hx-time, 8s) linear forwards; }
.hx.is-paused .hx__tab.is-active i { animation-play-state: paused; }
@keyframes hx-run { to { width: 100%; } }
.hx__tab:focus-visible { outline: 2px solid #fff; outline-offset: 4px; }
.hx__pager { display: none; }

/* ---------- tablet landscape / small laptop ---------- */
@media (max-width: 1199.98px) {
  .hx__wrap { padding-top: 56px; }
  .hx__slide { gap: 36px; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
  .hx__title { font-size: 36px; }
}
/* ---------- tablet portrait and phones: one column, the poster becomes a button ---------- */
@media (max-width: 991.98px) {
  .hx::before { background: linear-gradient(180deg, rgba(60,6,10,.88) 0%, rgba(45,4,8,.95) 60%, rgba(30,3,6,.98) 100%); }
  .hx__slide { grid-template-columns: minmax(0, 1fr); }
  .hx__poster { display: none; }
  .hx__btn--poster { display: inline-flex; }
  .hx__nav { display: none; }
  .hx__pager { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 36px 0 0; padding: 18px 0 22px; border-top: 1px solid var(--hx-line); }
  .hx__dots { display: flex; gap: 8px; }
  .hx__dots button { width: 28px; height: 4px; padding: 0; border: 0; border-radius: 2px; background: rgba(255,255,255,.3); cursor: pointer; }
  .hx__dots button.is-active { width: 44px; background: #fff; }
  .hx__arrows { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 700; color: var(--hx-soft); }
  .hx__arrows button { display: grid; place-items: center; width: 44px; height: 44px; border: 1.5px solid rgba(255,255,255,.45); border-radius: 50%; background: none; color: #fff; cursor: pointer; }
  .hx__arrows svg { width: 18px; height: 18px; }
}
@media (max-width: 575.98px) {
  .hx__wrap { padding: 36px 20px 0; }
  .hx__eyebrow { margin-bottom: 16px; font-size: 11px; }
  .hx__title { font-size: 28px; }
  .hx__sub { font-size: 16px; }
  .hx__meta li { font-size: 15px; padding: 7px 12px; }
  .hx__tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
  .hx__tile b { font-size: 26px; }
  .hx__tile span { font-size: 10px; letter-spacing: .1em; }
  .hx__actions { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 52px; }
  .hx__btn--main { grid-column: 1 / -1; }
  .hx__btn { padding: 0 14px; font-size: 15px; }
}
@media (prefers-reduced-motion: reduce) {
  .hx__slide, .hx__poster img { transition: none; }
  .hx__tab.is-active i { animation: none; width: 100%; }
}

/* ---------- nothing moves between slides ---------- */
/* laptop/desktop: title at the same top line, countdown + buttons at the same bottom line on every slide */
.hx__slide { align-items: stretch; }
.hx__text { display: flex; flex-direction: column; align-items: flex-start; }
.hx__count { margin-top: auto; }
.hx__poster { align-self: center; }
@media (max-width: 991.98px) {
  .hx__slide { align-content: start; }
  .hx__count { margin-top: 0; }
}
/* phones: the three small buttons share the row (text may wrap to two lines with large text) */
@media (max-width: 575.98px) {
  .hx__text { align-items: stretch; }
  .hx__eyebrow { align-self: flex-start; }
  .hx__meta { flex-direction: column; align-items: flex-start; }
  .hx__actions { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 48px; gap: 10px; }
  .hx__btn { min-height: 48px; padding: 0 10px; font-size: 14px; white-space: normal; line-height: 1.2; text-align: center; }
  .hx__btn--main { font-size: 16px; min-height: 52px; }
  .hx__btn--icon { width: 48px; padding: 0; }
}

/* ---------- big screens (full HD and 27" monitors) ---------- */
/* desktop: the hero fills the screen under the header (never taller than 1000 px), content centred, the switcher at the bottom.
   --hx-header = the height of the site header (set it to the real one; 96 px on the SSBMT site) */
@media (min-width: 992px) {
  .hx { --hx-header: 96px; display: flex; flex-direction: column; min-height: min(calc(100svh - var(--hx-header)), 1200px); }
  .hx__wrap { flex: 1; width: 100%; display: flex; flex-direction: column; padding-bottom: 0; }
  .hx__slides { margin-block: auto; }
  .hx__nav { margin-top: 48px; }
}
/* the countdown + buttons stay on one line across slides, but the gap under a shorter title is kept small:
   script.js measures the tallest title block and gives every slide that height (see .hx__head) */
.hx__head { display: flex; flex-direction: column; align-items: flex-start; }
.hx__count { margin-top: 0; }
.hx__meta { margin-bottom: 30px; }

@media (min-width: 1600px) {
  .hx__wrap { max-width: 1480px; padding: 88px 40px 0; }
  .hx__slide { gap: 80px; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
  .hx__eyebrow { font-size: 14px; padding: 8px 16px; margin-bottom: 24px; }
  .hx__title { font-size: 56px; }
  .hx__sub { font-size: 22px; }
  .hx__meta li { font-size: 18px; padding: 10px 16px; }
  .hx__meta svg { width: 20px; height: 20px; }
  .hx__count p { font-size: 13px; }
  .hx__tiles { grid-template-columns: repeat(4, 100px); gap: 12px; }
  .hx__tile { padding: 16px 6px 12px; }
  .hx__tile b { font-size: 38px; }
  .hx__tile span { font-size: 12px; }
  .hx__btn { min-height: 58px; padding: 0 30px; font-size: 17px; }
  .hx__btn--icon { width: 58px; padding: 0; }
  .hx__tab { padding-top: 24px; padding-bottom: 30px; }
  .hx__tab small { font-size: 14px; }
  .hx__tab b { font-size: 18px; }
}
@media (min-width: 2200px) {
  .hx__wrap { max-width: 1760px; padding-top: 110px; }
  .hx__slide { gap: 110px; }
  .hx__title { font-size: 68px; }
  .hx__sub { font-size: 26px; }
  .hx__meta li { font-size: 20px; }
  .hx__tiles { grid-template-columns: repeat(4, 116px); }
  .hx__tile b { font-size: 44px; }
  .hx__btn { min-height: 64px; font-size: 19px; padding: 0 34px; }
  .hx__btn--icon { width: 64px; padding: 0; }
  .hx__tab b { font-size: 20px; }
}

/* text flows naturally (no forced gap under a short title); the slide's content is centred against the poster */
@media (min-width: 992px) { .hx__slide { align-items: center; } }

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   SSBMT SITE OVERRIDES
   Everything above this line is the supplied hero.css, byte for byte except the photo path. These
   rules are appended rather than edited in, so the next drop of the spec file can be copied over
   the top and only this block needs re-applying. They win on SOURCE ORDER at equal specificity.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── 1. THE REAL HEADER HEIGHT ────────────────────────────────────────────────
   ⚠️ The spec hard-codes --hx-header: 96px, which is its mock header. MEASURED on this site the
      navbar is 85px, at 1280, 1440, 1920 and 2560 alike. Rather than swap one fixed number for
      another, this tracks --ssbmt-nav-h, which includes/footer.php measures from the real navbar
      and publishes on :root — so a change to the header carries through on its own.
   ⚠️ The 85px fallback matters: if that script has not run the hero is at worst 85px out, never
      collapsed. */
@media (min-width: 992px) {
  .hx { --hx-header: var(--ssbmt-nav-h, 85px); }
}

/* ── 2. THE POSTER STAYS ON SMALL SCREENS ─────────────────────────────────────
   The spec hides it below 992px behind a "View poster" button. On this site it was put back after
   the client asked for it twice, so it moves under the text instead of disappearing.
   ⚠️ Its SIZE is set by hero.js, which measures the room actually left — a media query cannot know
      how many lines this slide's title wrapped to. Where there is genuinely no room the script adds
      .hx--poster-off and the spec's button appears instead, so both are in the markup. */
@media (max-width: 991.98px) {
  /* ⚠️ aspect-ratio UNSET: the desktop frame is a fixed 1600:1143 box the image fills. Stacked under
     the text it must take its height from the image instead, or it forces a height of its own and
     the hero runs past the fold. */
  .hx__poster { display: block; width: fit-content; max-width: 100%; margin: 4px 0 0; align-self: start; aspect-ratio: auto; }
  .hx__poster img { width: auto; max-width: 100%; height: auto; }
  .hx__poster span { display: none; }                 /* the chip belongs to the desktop frame */
  .hx--poster-off .hx__poster { display: none; }      /* set by hero.js when there is no room */
  .hx--poster-off .hx__btn--poster { display: inline-flex; }
}
@media (max-width: 575.98px) {
  .hx__poster { margin-left: auto; margin-right: auto; }
}

/* ── 3 & 5. THE SIZE DAMPING ON SHORT SCREENS — REMOVED ───────────────────────
   ⚠️⚠️ THIS SPACE USED TO HOLD RULES THAT SHRANK THE HERO ON A SHORT SCREEN, AND THEY ARE GONE
      ON PURPOSE. DO NOT PUT THEM BACK WITHOUT ASKING.
      They trimmed the title, the countdown tiles and the buttons wherever the mock would have run
      past the fold — 1280x720, 1366x768, 1600x900, 1920x900 and the short phones. The reasoning
      was that a hero should end at the bottom of the screen. The client's instruction is the
      opposite and was given twice: FOLLOW THE MOCK. On an ordinary 1920x900 window the damping
      made the home page visibly smaller than the design they approved, and that is what they saw.
   📌 THE TRADE: at these sizes the hero is now taller than the viewport and the page scrolls, which
      is exactly what the mock does. Nothing is cut off or hidden — it continues below the fold.
      Measured against the mock afterwards: identical title, tiles and buttons at every size.
   ⚠️ What is NOT size damping stays: the button resets, the hover fix, the real header height, the
      poster on small screens and the photo path. Those are integration, not scale. */


/* ── 4. THE INSTALL APP BUTTON ────────────────────────────────────────────────
   ⚠️ Kept on the page because includes/footer.php uses its id to decide it is on the homepage. It
      sits under the hero and stays invisible until the browser says the app can be installed —
      footer.php does the showing. */
.hx-install-slot { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.hx-install-slot #pwaHeroInstallBtn { display: none; align-items: center; gap: 8px; margin: 14px 0 0;
  padding: 10px 18px; border: 1.5px solid rgba(128,0,0,.35); border-radius: 10px;
  background: #fff; color: #800000; font-size: .9rem; font-weight: 700; cursor: pointer; }


/* ── 6. NO ROW GAP UNDER THE TEXT ON SMALL SCREENS ────────────────────────────
   ⚠️⚠️ .hx__slide is a grid with `gap: 56px` (36px below 1200px). Stacked in one column that gap
      becomes a ROW gap between the wording and the poster — and hero.js, which measures the slide
      with the poster collapsed, could not see it. It showed up as the hero landing exactly 36px
      past the fold at 430x932 and 34px at 768x1024: the gap itself.
   📌 Set to 0 rather than taught to the script, because the poster already carries its own 4px of
      margin and a measured constant is one more thing to drift. */
@media (max-width: 991.98px) {
  .hx__slide { row-gap: 0; }
}

/* ── 7. REAL <button>s NEED THE BROWSER DEFAULT RESET ─────────────────────────
   ⚠️⚠️ Every button in the spec's markup is an <a>, which has no background of its own — so
      .hx__btn and .hx__btn--icon never set one. Two of ours are genuine <button> elements: the
      Share control (the site's own ssbmtShareButton() helper emits a <button> so it can carry an
      onclick) and "View poster" (it opens the lightbox rather than navigating). A <button> comes
      with the browser's own grey-white background and font, which is why Share rendered as a pale
      filled box beside an outlined link.
   ⚠️ font-family only, NOT the `font` shorthand: that would also clobber the size and weight
      .hx__btn sets, which this rule outranks.
   📌 .hx__btn--main is an <a>, so it is untouched and keeps its green. */
.hx button.hx__btn {
  background: none;
  font-family: inherit;
  color: #fff;
  cursor: pointer;
  -webkit-appearance: none;
          appearance: none;
}

/* ⚠️⚠️ AND THE MAIN BUTTON MUST KEEP ITS FILL. The reset above is `.hx button.hx__btn`, which is
   specificity (0,2,1) and therefore outranks `.hx__btn--main` at (0,1,0). On the home page that was
   harmless — the main action there is an <a>. On the registration page it is a real <button> (it
   calls regHeroJump() rather than navigating), so the reset stripped its accent colour and the
   primary action rendered as a transparent outline. Re-asserted at matching specificity, later in
   the file. */
/* ⚠️⚠️ `border: 0` AND IT IS NOT OPTIONAL. A <button> carries the browser's own
   `border: 2px outset ButtonBorder`, and the spec never clears it because its main action is an
   <a>, which has no border to clear. On the registration page this one is a real <button> (it
   calls regHeroJump()), so it rendered the accent fill inside a 2px black outset frame — a dark
   ring the sample does not have. MEASURED: sample `0px none`, ours `2px outset rgb(0,0,0)`.
   ⚠️ On THIS rule only, never on the generic `.hx button.hx__btn` reset above: that is (0,2,1) and
      would outrank `.hx__btn--line`'s own `border: 1.5px solid`, stripping the outline buttons of
      the very border that defines them. */
.hx button.hx__btn--main { background: var(--hx-green); color: var(--hx-on-accent, #fff); border: 0; }
.hx button.hx__btn--main:hover,
.hx button.hx__btn--main:focus { background: var(--hx-green-dk); color: var(--hx-on-accent, #fff); }

/* ── 8. THE HOST SITE'S LINK HOVER MUST NOT REACH THESE BUTTONS ───────────────
   ⚠️⚠️ css/custom.css line 73 is `a:hover { color: var(--clr-primary-dark); text-decoration:
      underline; }` — specificity (0,1,1). The spec sets the button's colour with `.hx__btn--main`
      and kills the underline with `.hx__btn`, both (0,1,0). So the moment the pointer touched a
      button its label turned MAROON AND UNDERLINED on top of the green fill. It never showed in the
      supplied demo because that page does not load custom.css, and it never showed in my own checks
      because I only ever measured the RESTING state — the fault lives entirely in :hover.
   ⚠️ Every state is named, not just :hover — :visited and :focus reach them the same way, and a
      keyboard user hitting Tab would otherwise see the same maroon underline.
   ⚠️ Specificity, not !important: `.hx a.hx__btn--main:hover` is (0,3,1) and beats (0,1,1)
      comfortably, while leaving the rules overridable by anything more specific later.
   📌 --hx-on-accent is why the main button's colour is a variable: on the event page event.js
      switches it to dark text when the event's accent colour is pale. */
.hx a.hx__btn,
.hx a.hx__btn:link,
.hx a.hx__btn:visited,
.hx a.hx__btn:hover,
.hx a.hx__btn:focus,
.hx a.hx__btn:active,
.hx a.hx__back,
.hx a.hx__back:hover,
.hx a.hx__back:focus,
.hx a.hx__poster,
.hx a.hx__poster:hover,
.hx a.hx__poster:focus,
.hx .hx__cue a,
.hx .hx__cue a:hover,
.hx .hx__cue a:focus { text-decoration: none; }

.hx a.hx__btn--main,
.hx a.hx__btn--main:link,
.hx a.hx__btn--main:visited,
.hx a.hx__btn--main:hover,
.hx a.hx__btn--main:focus,
.hx a.hx__btn--main:active { color: var(--hx-on-accent, #fff); }

.hx a.hx__btn--line,
.hx a.hx__btn--line:link,
.hx a.hx__btn--line:visited,
.hx a.hx__btn--line:hover,
.hx a.hx__btn--line:focus,
.hx a.hx__btn--line:active,
.hx a.hx__btn--icon,
.hx a.hx__btn--icon:link,
.hx a.hx__btn--icon:visited,
.hx a.hx__btn--icon:hover,
.hx a.hx__btn--icon:focus,
.hx a.hx__btn--icon:active { color: #fff; }

/* The poster chip and the scroll cue are links too. */
.hx a.hx__poster, .hx a.hx__poster:hover, .hx .hx__cue a, .hx .hx__cue a:hover { color: #fff; }
/* The back link keeps its own quieter colour, brightening on hover as event.css intends. */
.hx a.hx__back { color: rgba(255,255,255,.72); }
.hx a.hx__back:hover, .hx a.hx__back:focus { color: #fff; }

/* ── 9. PHONE LAYOUT — SUPPLIED FIX ───────────────────────────────────────────
   Added verbatim from the client brief: on a phone the hero was tall enough to push the buttons
   below the fold, especially with the system text size turned up. Date and venue become plain
   lines rather than boxes, the countdown is one slim row, the title drops to 25px, and the main
   button goes full width with the three smaller actions in a row beneath it.
   ⚠️ LAST IN THE FILE ON PURPOSE: it must outrank the earlier (max-width: 575.98px) blocks, which
      is how it replaces their spacing rather than fighting it.
   ⚠️ Phones only. Nothing here can reach a tablet, laptop or monitor — every rule is inside the
      575.98px query. */
@media (max-width: 575.98px) {
  .hx__wrap { padding-top: 22px; }
  .hx--event .hx__wrap { padding-top: 16px; }
  .hx__back { margin-bottom: 14px; font-size: 14px; }
  .hx__eyebrow { margin-bottom: 12px; padding: 5px 11px; font-size: 11px; letter-spacing: .1em; }
  .hx__title { margin-bottom: 8px; font-size: 25px; line-height: 1.15; }
  .hx__sub { margin-bottom: 10px; font-size: 15px; }
  .hx__meta { flex-direction: row; flex-wrap: wrap; gap: 4px 16px; margin-bottom: 16px; }
  .hx__meta li { padding: 0; background: none; font-size: 15px; }
  .hx__meta svg { width: 16px; height: 16px; }
  .hx__count { margin-bottom: 16px; }
  .hx__count p { margin-bottom: 6px; font-size: 11px; }
  .hx__tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
  .hx__tile { padding: 7px 4px 6px; border-radius: 10px; }
  .hx__tile b { font-size: 21px; }
  .hx__tile span { margin-top: 3px; font-size: 9px; }
  .hx__actions { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 44px; gap: 8px; }
  .hx__btn--main { grid-column: 1 / -1; min-height: 48px; font-size: 15px; }
  .hx__btn { min-height: 44px; font-size: 13.5px; }
  .hx__btn--icon { width: 44px; padding: 0; }
  .hx__pager { margin-top: 18px; padding: 12px 0 14px; }
  .hx__arrows button { width: 40px; height: 40px; }
  .hx__cue { margin: 18px 0 14px; }
}

/* ⚠️ A SHORT phone with the system text size turned up. Swept across twelve phone sizes, the only
   failures were 360x640 and 320x568 at 1.3x text, and only on the EVENT hero — it carries a back
   link and a scroll chevron the home hero does not. Those two are what gets trimmed here, not the
   wording or the buttons.
   ⚠️ Gated at 660px of height so it cannot reach 360x740, which is the size the brief targets. */
@media (max-width: 575.98px) and (max-height: 660px) {
  .hx--event .hx__wrap { padding-top: 10px; }
  .hx__back { margin-bottom: 8px; font-size: 13px; }
  .hx__cue { margin: 10px 0 8px; }
  .hx__cue a { width: 38px; height: 38px; }
  .hx__title { font-size: 22px; }
  .hx__sub { margin-bottom: 8px; }
  .hx__meta { margin-bottom: 12px; }
  .hx__count { margin-bottom: 12px; }
  .hx__count p { margin-bottom: 4px; }
  .hx__tile { padding: 5px 4px 5px; }
  .hx__tile b { font-size: 19px; }
}

/* ⚠️⚠️ ON A PHONE THE POSTER IS A BUTTON, NOT A PICTURE — which is what the supplied phone layout
   asks for: "Submit Abstract (or Add to calendar) | View poster | Share in one row below it".
   An earlier override brought the poster image back on small screens, from an older request. With
   the new phone layout both were showing at once: the View poster button AND, underneath it, the
   image — which on a 360x800 phone left a 262px band below the buttons. Measured: the poster box
   was 252x180 sitting in that gap.
   📌 Tablets are untouched: they keep the image, which is where there is room for it. This is the
      phone query only. */
@media (max-width: 575.98px) {
  .hx__poster { display: none; }
  .hx__btn--poster { display: inline-flex; }
}

/* ── 10. TABLET + PHONE: ONLY THE ACTIVE SLIDE TAKES SPACE ────────────────────
   Supplied fix. Two faults it addresses:
     1. All slides share one grid cell, so the hero was as tall as the TALLEST slide and a short
        slide left a dead band above the dots and arrows.
     2. On a tablet the event poster ran full width under the buttons, making the hero very long
        and cutting the poster off.
   ⚠️ The brief wrote these as .hx_poster and .hx_btn--poster (one underscore). Our classes are
      .hx__poster and .hx__btn--poster, so they are corrected here as the brief instructs — written
      with one underscore they would have matched nothing and the poster would still be there.
   ⚠️ Swapping display for the opacity fade means slides no longer cross-fade below 992px. That is
      the trade the fix requires: a slide that still occupies the cell is exactly what caused the
      gap. The carousel, dots, arrows and swipe are unaffected. */
@media (max-width: 991.98px) {
  .hx, .hx--event { min-height: 0 !important; }
  .hx__slides { display: block; }
  /* ⚠️⚠️ SCOPED TO THE HOME CAROUSEL. An unscoped `.hx__slide{display:none}` BLANKED THE WHOLE EVENT
     HERO on every phone and tablet — reported from the client's phone, only "Back to Homepage" and
     the arrow were left. The event hero renders ONE slide and `reg_hero_hx.php` does not put
     `is-active` on it (it does not need to — `event.css` makes it visible with opacity/visibility/
     transform, and never touches `display`), so `.hx__slide.is-active` matched nothing and there was
     nothing to put back. The `:not(.hx--event)` is what keeps this a carousel rule.
     ⚠️ My own check missed it because the probe toggled `is-active` onto each slide before measuring
        — it created the class the page lacks. Never let a probe write the attribute it is testing. */
  /* ⚠️⚠️ THE SLIDES SHARE ONE GRID CELL BELOW 992px, exactly as they already do above it (line 23).
     They were switched with `display:none` here, which fixed the gap under the buttons but made the
     hero a different height on every slide — so the dots, the arrows and everything below them
     jumped as it advanced. Reported from a phone with three screenshots.
     ⚠️ MEASURED before changing it: the slides are 338/369/367 tall at 390px and 346/429/384 at
        820px, so sharing a cell costs at most 31px of slack on a phone and 83px on a tablet. That
        is why this is worth doing and the earlier 310px version was not — the gap then came from a
        different cause, not from sharing a cell.
     ⚠️ opacity/visibility, NEVER display:none — `display` cannot be transitioned, so the fade below
        depends on this. The !important overrides the `.hx__slide { display: grid }` base only where
        a later rule might otherwise win. */
  .hx:not(.hx--event) .hx__slides { display: grid; }
  .hx:not(.hx--event) .hx__slide {
    display: grid !important;
    grid-area: 1 / 1;
    visibility: hidden;
    opacity: 0;
    transform: translateX(16px);
    transition: opacity .45s ease, transform .45s ease, visibility .45s;
  }
  .hx:not(.hx--event) .hx__slide.is-active { visibility: visible; opacity: 1; transform: none; }

  /* ⚠️⚠️ THE SLACK GOES ABOVE THE COUNTDOWN, so the countdown and the buttons sit in the same place
     on every slide. Left alone the space collects BELOW the text — which is a gap between the
     buttons and the dots, and is exactly what the client photographed on a tablet.
     ⚠️ `align-content: stretch` is the part that makes it work, and it is not optional. A rule
        further up sets `align-content: start` on the slide, which packs the single row to the top at
        its natural height — so `.hx__text` stayed 346px tall inside a 429px cell and `margin-top:
        auto` had no space to distribute and did nothing. Measured: text 346 / cell 429.
     ⚠️ `.hx__text` is already `display: flex; flex-direction: column` further up; it is repeated here
        only so this block reads on its own. */
  .hx:not(.hx--event) .hx__slide { align-content: stretch; }
  .hx:not(.hx--event) .hx__text { display: flex; flex-direction: column; align-self: stretch; }
  .hx:not(.hx--event) .hx__count { margin-top: auto; }
  .hx__pager { margin-top: 20px; }
  /* event page too: no big poster on tablet or phone, a "View poster" button instead, which opens
     the same lightbox as clicking the poster did. */
  .hx__poster, .hx--event .hx__poster { display: none !important; }
  .hx__btn--poster, .hx--event .hx__btn--poster { display: inline-flex !important; }
  .hx--event .hx__cue { margin: 20px 0 16px; }
}
/* tablets (576-991px): text a little smaller so it fits nicely */
@media (min-width: 576px) and (max-width: 991.98px) {
  .hx__wrap { padding-top: 32px; }
  .hx__title { font-size: 34px; }
  .hx__eyebrow { margin-bottom: 14px; }
  .hx__meta { margin-bottom: 20px; }
  .hx__count { margin-bottom: 22px; }
}

/* ── 11. SHORT DESKTOP WINDOWS: TRIM THE HERO SO IT CLEARS THE FOLD ─────────────────────────────
   The layout checker measured the hero running past the bottom of the screen by 142px at
   1024x640, 112px at 1280x720 and 64px at 1366x768, while 1440x900 and everything above was fine.

   ⚠️⚠️ THE TRIGGER IS VIEWPORT HEIGHT, NOT WIDTH. Every width that failed is a SHORT window, and
      every width that passed is a tall one — 1366x768 fails and 1440x900 passes not because 1366
      is narrow but because 768 is short. Writing this as a width query would have been the wrong
      fix twice over: it would miss a 1920x800 window (a laptop with a dock and a taskbar, which is
      extremely common) and it would needlessly shrink a 1366x1024 one. Keyed on height it fixes
      every short window at any width and touches no tall window at all.
   📌 This is why the laptop band keeps breaking: a 1920x1080 laptop at 150% Windows scaling reports
      1280x720, and 720px minus an 85px header leaves 555px for a hero that wants ~700.
   ⚠️ `min-width: 992px` on both blocks: phones and tablets have their own rules above and are
      already measured clean. Nothing below 992 is touched.
   ⚠️ The two blocks are cumulative — the 700px one lands on top of the 820px one. Keep that in mind
      before changing a number in either. Values are measured, not guessed; re-run
      `_layoutcheck/run.php` after any change and check the "HERO: does it clear the fold" table. */
@media (min-width: 992px) and (max-height: 820px) {
  .hx__wrap { padding-top: 32px; }
  .hx__eyebrow { margin-bottom: 14px; }
  .hx__meta { margin-bottom: 18px; }
  .hx__nav { margin-top: 24px; }
  .hx--event .hx__cue { margin-top: 18px; }
}
/* ⚠️ 760px, not 700: 1280x720 is a 1920x1080 laptop at 150% Windows scaling — the single most
   common laptop there is — and at 700 it fell just the wrong side of the line and stayed 30px past
   the fold. 768 (1366x768) clears the fold on the milder block alone and deliberately stays there,
   so the commonest laptop of all is not given the tightest layout for no reason. */
@media (min-width: 992px) and (max-height: 760px) {
  .hx__wrap { padding-top: 20px; }
  .hx__title { font-size: 34px; }
  .hx__sub { font-size: 16px; }
  .hx__eyebrow { margin-bottom: 8px; }
  .hx__meta { margin-bottom: 12px; }
  .hx__count { margin-bottom: 12px; }
  .hx__tile { padding: 8px 6px 6px; }
  .hx__tile b { font-size: 28px; }
  .hx__btn { min-height: 46px; }
  .hx__nav { margin-top: 12px; }
  .hx__tab { padding-top: 14px; padding-bottom: 16px; }
  .hx--event .hx__cue { margin-top: 10px; }
}
/* 1024x640 — a tablet held sideways — leaves only 555px under the header, the least room of any
   screen in the ladder. The last 21px come off here. */
@media (min-width: 992px) and (max-height: 660px) {
  .hx__wrap { padding-top: 12px; }
  .hx__title { font-size: 30px; }
  .hx__tile b { font-size: 24px; }
  .hx__btn { min-height: 44px; }
  .hx__nav { margin-top: 8px; }
  .hx__eyebrow { margin-bottom: 6px; }
  .hx__meta { margin-bottom: 8px; }
  .hx__count { margin-bottom: 8px; }
  /* the slide switcher along the bottom is the last 20px on the home carousel */
  .hx__tab { padding-top: 8px; padding-bottom: 10px; }
}

/* ── 13. PHONES: THE HOME HERO FILLS THE SCREEN UNDER THE MENU BAR (S68 §J, 18 Oct 2026) ─────────────
   Client: "cant we make it the size tall wise exact the mobile screen … like instagram, no matter which
   phone size it just fits exactly the screen". The phone hero was as tall as its tallest slide, so on a
   tall phone it ended early and the next section showed underneath.
   ⚠️ ONLY ADDS HEIGHT, never shrinks — the client's "follow the mock" rule (§3 above) stands. The hero is
      AT LEAST the screen minus the bar; a short phone or big system text simply makes it taller, exactly
      as before. Nothing is trimmed, hidden or cut.
   ⚠️ svh (the SMALL viewport: browser bars showing) so it fits exactly on first view and does not jump as
      the address bar slides away; the vh line before it is the fallback for browsers without svh.
      --ssbmt-nav-h is the REAL bar height measured by includes/footer.php (64px on a phone today).
   ⚠️ The extra space lands ABOVE THE COUNTDOWN (the existing `.hx__count{margin-top:auto}` of §10), so the
      countdown, buttons and pager sit low and in the same place on every slide; the pager is the last thing
      on the screen.
   ⚠️ Phones only (≤575.98px) and the home carousel only — the event page hero (.hx--event) is untouched,
      and so are tablets, laptops and monitors. Placed before §12 so §12 stays the last rule in the file. */
@media (max-width: 575.98px) {
  .hx:not(.hx--event) {
    display: flex;
    flex-direction: column;
    min-height: calc(100vh - var(--ssbmt-nav-h, 64px)) !important;
    min-height: calc(100svh - var(--ssbmt-nav-h, 64px)) !important;
  }
  .hx:not(.hx--event) .hx__wrap { flex: 1 0 auto; display: flex; flex-direction: column; width: 100%; }
  .hx:not(.hx--event) .hx__slides { flex: 1 0 auto; }
}
/* 13b. THE REGISTRATION PAGE'S EVENT HERO, TOO (client, same day: "same thing in registration hero"). A full-screen
   registration hero is what was asked for on the old hero as well — its main button jumps to the form (see the
   note in register.php). Same rule: at least the screen minus the bar, adds height only. The extra space goes
   above the countdown — or above the buttons when the event has no countdown (past/closed) — so the actions sit
   low and the "scroll down" arrow (.hx__cue) is the last thing on the screen. The one slide stays visible (§12). */
@media (max-width: 575.98px) {
  .hx--event {
    display: flex;
    flex-direction: column;
    min-height: calc(100vh - var(--ssbmt-nav-h, 64px)) !important;
    min-height: calc(100svh - var(--ssbmt-nav-h, 64px)) !important;
  }
  .hx--event .hx__wrap { flex: 1 0 auto; display: flex; flex-direction: column; width: 100%; }
  .hx--event .hx__slides { flex: 1 0 auto; display: grid; }
  .hx--event .hx__slide { align-content: stretch; }
  .hx--event .hx__text { display: flex; flex-direction: column; align-self: stretch; }
  .hx--event .hx__count { margin-top: auto; }
  .hx--event .hx__actions { margin-top: auto; }
  .hx--event .hx__count ~ .hx__actions { margin-top: 0; }
}

/* 13c. BIG SCREENS (27-inch and larger) FILL TOO (client, 18 Oct 2026: "and also 27 and bigger screens"). The supplied
   spec capped the desktop hero at min(screen − header, 1200px) for the home page and 1100px for the event page
   (css/event.css), so on 2560x1440 the home hero stopped 155px short and the event hero 255px short (875 / 975px on
   4K). Measured first; no client decision behind the caps was found. From 992px wide the cap is lifted: the hero is
   the screen minus the header, and the extra height only CENTRES the content, as the desktop hero already does.
   ⚠️ `.hx.hx--event` (two classes) so it outranks event.css, which loads after this file. Phones/tablets untouched. */
@media (min-width: 992px) {
  .hx:not(.hx--event) { min-height: calc(100vh - var(--hx-header)); min-height: calc(100svh - var(--hx-header)); }
  .hx.hx--event { min-height: calc(100vh - var(--hx-header)); min-height: calc(100svh - var(--hx-header)); }
}

/* 13d. THE POSTER CARD TAKES THE POSTER'S OWN SHAPE, IN A LIGHT GLASS FRAME (S68 §N, 18 Oct 2026). The spec frame is a
   fixed 1600:1143 box with object-fit:cover, which cut ~half off a portrait poster (625x893 on the 15th Annual
   Conference). A blurred fill (the S53 card treatment) was tried first and REJECTED by the client for the hero:
   "un professional, not clean — make the card orientation the same as the poster". So from 992px every poster card
   is exactly the poster's own shape (a landscape poster comes out as before; a portrait one gets a tall card),
   aligned to the content edge (left in Arabic), inside the see-through frame the pre-spec hero had (.hero-poster-card: 10px,
   white .1 + 1px white .25 + blur — client: "put like before a transparent border… indicator that it's clickable").
   ⚠️ HEIGHT BUDGET, so the hero still ends at the bottom of the screen (§13c): the image may use the screen minus the
      header minus the hero's own chrome minus the frame. Event chrome measured at 217px (40 top padding + back link
      22 + 28 + scroll cue 48+48+28) → 225 + 20 frame = 245. Home: wrap padding + switcher, budgeted 300 + 20 = 320.
      Capped at 640/560px so a portrait card never towers over the wording on a 27-inch screen; never UPSCALED past
      the image's own size.
   ⚠️ No zoom of the image on hover any more — inside a padded frame it would spill over the glass edge. The CARD
      lifts instead, the edge brightens and the chip darkens. cursor:zoom-in says "this opens bigger".
   ⚠️ .hx__poster--own (set in hero_hx.php / reg_hero_hx.php for a non-landscape poster) is kept in the markup as a
      hook; these rules do not need it. ≥992px only — below that the poster is its natural shape (§2) or a button. */
@media (min-width: 992px) {
  .hx__poster {
    aspect-ratio: auto; width: fit-content; max-width: 100%; justify-self: end;   /* flush with the content edge (left in Arabic) */
    padding: 10px; border-radius: 18px;
    background: rgba(255,255,255,.1);
    border: 1px solid rgba(255,255,255,.25);
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
    box-shadow: 0 40px 70px -30px rgba(0,0,0,.85);
    cursor: zoom-in;
    transition: transform .25s ease, border-color .25s ease, background-color .25s ease;
  }
  .hx__poster img {
    width: auto; height: auto; max-width: 100%; object-fit: fill; border-radius: 10px;
    max-height: min(calc(100vh - var(--hx-header) - 320px), 560px);
    max-height: min(calc(100svh - var(--hx-header) - 320px), 560px);
  }
  .hx--event .hx__poster img {
    max-height: min(calc(100vh - var(--hx-header) - 245px), 640px);
    max-height: min(calc(100svh - var(--hx-header) - 245px), 640px);
  }
  .hx__poster:hover, .hx__poster:focus-visible {
    transform: translateY(-4px);
    border-color: rgba(255,255,255,.5);
    background-color: rgba(255,255,255,.16);
  }
  .hx__poster:hover img { transform: none; }
  .hx__poster span { right: 22px; bottom: 22px; transition: background-color .25s ease; }
  .hx__poster:hover span { background: rgba(0,0,0,.82); }
  .hx__poster span .bi { font-size: 15px; line-height: 1; }
}
@media (min-width: 992px) and (prefers-reduced-motion: reduce) {
  .hx__poster, .hx__poster:hover { transition: none; transform: none; }
}

/* 13e. THE LAPTOP SIZE STEP, 1200–1599px (S68 §N, client: "this is empty space… only here in laptop, 27 and up is
   okay"). The spec has one size below 1600px — a 1200px column with the base type — and only scales up from 1600.
   So on 1280/1366/1440/1536 (incl. a 1920 laptop at 125–150%) the hero sat small in the middle with wide empty
   bands round it. This step uses more of the width (1400px, 40px gutters like the 1600 step), gives the poster
   the 1600 step's wider column, and lifts the type a little. 992–1199 and 1600+ are untouched.
   ⚠️ Measured at 1280x720, 1366x768, 1440x900, 1536x744, 1536x864: the hero bottom stays the screen bottom. */
@media (min-width: 1200px) and (max-width: 1599.98px) {
  .hx__wrap { max-width: 1400px; padding-left: 40px; padding-right: 40px; }
  .hx__slide { gap: 64px; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
  .hx__title { font-size: 50px; }
  .hx__sub { font-size: 20px; }
  .hx__meta li { font-size: 17px; }
}
/* 13f. THE EVENT SWITCHER IS ONE ROW, whatever the number of events (S68 §Z13). --hx-n is set on .hx__nav in hero_hx.php;
   without it (old markup) the spec's 3 columns stay. */
@media (min-width: 992px) {
  .hx__nav[style*="--hx-n"] { grid-template-columns: repeat(var(--hx-n), minmax(0, 1fr)); }
  .hx__nav[style*="--hx-n:5"] .hx__tab b, .hx__nav[style*="--hx-n:6"] .hx__tab b { font-size: 15px; }
}

/* 13g. A PORTRAIT (OWN-SHAPE) POSTER CLOSES THE GAP (S68 §Z14, client: "this space" — a dead band between the text and
   a narrow portrait card pinned to the far right of its 5fr column). The poster column shrinks to the card's own width,
   the text takes the rest, and on the homepage the card may stand a little taller (250px budget instead of 320).
   Only a poster taller than it is wide gets .hx__poster--tall (hero_hx.php / reg_hero_hx.php); a wide or landscape one is untouched. A browser without :has() keeps the old layout. */
@media (min-width: 992px) {
  .hx__slide:has(.hx__poster--tall) { grid-template-columns: minmax(0, 1fr) auto; }
  .hx:not(.hx--event) .hx__slide:has(.hx__poster--tall) .hx__poster img { max-height: min(calc(100svh - var(--hx-header) - 250px), 640px); }
}

/* 13h. THE PLACE CHIP NOW CARRIES VENUE + CITY/COUNTRY (S68 §Z15, hero_hx.php / reg_hero_hx.php ssbmtPlaceLine()), so
   on a SHORT laptop screen in the 1200–1599 step a long venue pushed the next chip ("16 CME Hours") to a third row and
   the registration hero 35px past the fold at 1280×720. 1px smaller chip text there keeps them on one row. */
@media (min-width: 1200px) and (max-width: 1599.98px) and (max-height: 800px) {
  .hx--event .hx__meta li { font-size: 16px; padding: 7px 12px; }
}

/* 13i. HOMEPAGE HERO ON A PHONE / IN THE APP — nothing breaks onto two lines (S68 §Z17, client: "look at the count 1/4
   and so on"). In the Android app with the phone's larger text: "1 / 4" split into "1 /" over "4", and "Submit
   Abstract" wrapped inside a third-of-a-row button.
   · Buttons: row 1 = View Conference Details + share icon, row 2 = Submit Abstract | View poster at HALF width each.
     Flex, not grid, so a slide without a poster (or without the share button) simply lets the others fill the row.
   · Pager: the counter never wraps; the dots give way first. Registration page (.hx--event) untouched. */
@media (max-width: 575.98px) {
  .hx:not(.hx--event) .hx__actions { display: flex; flex-wrap: wrap; gap: 10px; }
  .hx:not(.hx--event) .hx__actions > * { min-width: 0; }
  .hx:not(.hx--event) .hx__btn--main { order: 1; flex: 1 1 calc(100% - 60px); }
  .hx:not(.hx--event) .hx__btn--icon { order: 2; flex: 0 0 48px; }
  .hx:not(.hx--event) .hx__btn--line { order: 3; flex: 1 1 calc(50% - 5px); padding: 0 6px; }
  .hx__arrows [data-of] { white-space: nowrap; }
  .hx__arrows { flex-shrink: 0; }
  .hx__dots { min-width: 0; flex: 0 1 auto; }
  .hx__dots button { flex: 0 1 28px; min-width: 10px; }
  .hx__dots button.is-active { flex-basis: 44px; }
}

/* 13j. (REMOVED 19 Oct 2026, S68 §Z26) — the poster in the middle of the PHONE hero (§Z18, then §Z23 sizing and §Z25
   card) was tried and the client reversed it: "remove the poster… it really doesn't look good… later we will have a
   problem here… just adjust the background pictures and make the opacity a bit lighter". So on a phone the poster is
   a "View poster" button again (§10 / event.css), the countdown sits low as before, and the empty middle is filled
   by the event PHOTO showing through more (§13n). ⚠️ Read §Z18–§Z26 in CLAUDE-HISTORY before bringing a phone poster
   back — the client has now said no to it. */

/* 13k. NO GRADIENT — AN EVEN TONE OVER A SOFTLY BLURRED PHOTO, AT EVERY WIDTH (S68 §Z20, client: "that gradient doesn't
   look premium and modern"; chose option B from a side-by-side of now / flat / flat + soft photo). Replaces the spec's
   two gradients (dark-left fade + bottom fade) on the homepage AND the registration page; each event keeps its own
   colour via --reg-dark. The photo is blurred 7px and pulled 24px past every edge so the blur never shows a soft rim
   (.hx is overflow:hidden). `.hx.hx--event` outranks event.css's own ::before, which loads after this file.
   📌 event.css's @supports-not fallback (browsers without color-mix) is left as it was. */
.hx__bg { inset: -24px; filter: saturate(.3) brightness(.8) blur(7px); }
.hx::before { background: rgba(26,3,6,.78); }
.hx.hx--event::before { background: color-mix(in srgb, var(--reg-dark, #3d0508) 80%, transparent); }

/* 13l. REAL EVENT PHOTOS BEHIND THE HERO (S68 §Z21 — includes/hero_photos.php). The client's idea: each homepage slide
   shows a photo from the latest finished event, chosen with the ★ ticks in that event's gallery (admin). The markup only
   exists when photos are ticked; .hx--photos is added by its script. Without either, §13k's hall photo stays.
   · Soft, as chosen from the mock: 3px blur (people over screens — sharp slide text fought with the title), an even tone.
   · Crossfade 1.2s between photos; the active one drifts very slowly (24s, 4%) — the "alive" feel. No motion for
     prefers-reduced-motion. Pulled 24px past the edges so the blur never shows a soft rim. */
.hx__photos { position: absolute; inset: -24px; z-index: -2; overflow: hidden; }
.hx__photo { position: absolute; inset: 0; background: #1a0306 center / cover no-repeat; opacity: 0;
  filter: saturate(.55) brightness(.85) blur(3px); transform: scale(calc(var(--hz, 1) * 1.02));
  /* §Z45 — a photo that is not showing is SWITCHED OFF (visibility:hidden once its fade has finished) and no will-change:
     every photo used to stay a full-screen, blurred graphics layer even while invisible, so 4–5 starred photos weighed
     on a phone ("when I unselected one the app got better" — client). Now 5 photos cost about what 1 does. */
  visibility: hidden; transition: opacity 1.2s ease, visibility 0s linear 1.2s; }
.hx__photo.is-on { opacity: 1; visibility: visible; transition: opacity 1.2s ease, visibility 0s; animation: hx-drift 24s ease-out both; }
/* §Z27/§Z28 — --hz is the zoom the drift multiplies. It is 1 everywhere, and on PHONES ONLY (§13n) it becomes the admin's
   own zoom for that photo (--hzp, set inline with --hpx/--hpy by Gallery → ★ → move). Computers keep the centred photo. */
.hx__photo { --hz: 1; }
@keyframes hx-drift { from { transform: scale(calc(var(--hz, 1) * 1.02)); } to { transform: scale(calc(var(--hz, 1) * 1.06)); } }
.hx--photos .hx__bg { display: none; }
.hx.hx--photos::before { background: rgba(26,3,6,.70); }
/* §Z46 — deeper (client: "fix the opacity of the registration page"): the event colour darkened 40% toward black at 84%,
   so the photo is a calm backdrop rather than a bright colour wash behind the title. */
.hx.hx--event.hx--photos::before { background: color-mix(in srgb, color-mix(in srgb, var(--reg-dark, #3d0508) 60%, #000) 84%, transparent); }
@media (prefers-reduced-motion: reduce) {
  .hx__photo { transition: none; }
  .hx__photo.is-on { animation: none; }
}

/* 13m. THE REGISTRATION HERO ON A PHONE — BUTTONS (S68 §Z22). ⚠️ Its poster-in-the-middle half was REMOVED with §13j
   (§Z26, client reversed it); only the button rows below remain. Originally: same two fixes as §13i/§13j: the poster sits in the empty middle (between the details and the countdown /
   buttons, taking only the free space), and the buttons never squeeze — row 1 the main button + share, row 2 Add to
   Calendar | View poster at half width. No height cut-off (§Z23): the poster takes whatever room is free and its picture
   hides itself below 90px, where the View poster button does the job.
   ⚠️ `.hx.hx--event .hx__slides .hx__slide` (0,4,0) outranks §12's `.hx--event .hx__slide { display:grid !important }`
      — flex keeps the slide just as visible, which is all §12 guards. Without a poster the §13b layout is untouched. */
@media (max-width: 575.98px) {
  .hx--event .hx__actions { display: flex; flex-wrap: wrap; gap: 10px; }
  .hx--event .hx__actions > * { min-width: 0; }
  .hx--event .hx__btn--main { order: 1; flex: 1 1 calc(100% - 60px); }
  .hx--event .hx__btn--icon { order: 2; flex: 0 0 48px; }
  .hx--event .hx__actions > .cal-dropdown,
  .hx--event .hx__actions > .hx__btn--poster { order: 3; flex: 1 1 calc(50% - 5px); padding-left: 6px; padding-right: 6px; }
  .hx--event .hx__actions > .cal-dropdown { padding: 0; }
  .hx--event .cal-dropdown > .hx__btn { width: 100%; padding: 0 6px; }
}

/* 13n. ON A PHONE (AND IN THE APP) THE EVENT PHOTO SHOWS THROUGH MORE (S68 §Z26, client: "just adjust the background
   pictures and make the opacity a bit lighter on the application"). With the poster back to a button (§13j note), the
   middle of the phone hero is the photograph itself: a lighter tone, less blur, more colour. A soft shadow under the
   wording keeps it readable on the brighter picture (a shadow, not a gradient — the client rejected gradients, §Z20).
   Only with event photos (.hx--photos); the plain hall-photo fallback and tablets/desktop are unchanged. */
@media (max-width: 575.98px) {
  .hx.hx--photos::before { background: rgba(26,3,6,.50); }
  .hx.hx--event.hx--photos::before { background: color-mix(in srgb, color-mix(in srgb, var(--reg-dark, #3d0508) 60%, #000) 66%, transparent); }   /* §Z46 — same deeper colour, lighter on phones */
  .hx--photos .hx__photo { filter: saturate(.8) brightness(.95); }   /* §Z45 — no blur on phones: the costliest effect to draw at full screen, and barely visible under the tone */
  /* §Z35 — on phones the photo stands STILL: the slow 24-second drift of a large blurred layer kept the phone's graphics
     busy the whole time and made taps and scrolling feel heavy in the app. Changing photos still crossfades. */
  .hx__photo.is-on { animation: none; }
  .hx__photo { transition: opacity .8s ease, visibility 0s linear .8s; }
  .hx__photo.is-on { transition: opacity .8s ease, visibility 0s; }
  /* §Z28 — the admin's move / zoom for each photo applies HERE ONLY (phones and the app). */
  .hx__photo { --hz: var(--hzp, 1); background-position: var(--hpx, 50%) var(--hpy, 50%); transform-origin: var(--hpx, 50%) var(--hpy, 50%); }
  .hx--photos .hx__eyebrow, .hx--photos .hx__title, .hx--photos .hx__sub, .hx--photos .hx__meta li,
  .hx--photos .hx__count p, .hx--photos .hx__back, .hx--photos .hx__arrows {
    text-shadow: 0 1px 3px rgba(0,0,0,.55), 0 4px 18px rgba(0,0,0,.55);
  }
  .hx--photos .hx__eyebrow { background: rgba(0,0,0,.28); }
  .hx--photos .hx__tile { background: rgba(0,0,0,.38); }
}

/* 13o. ADD TO CALENDAR ON A PHONE: A BOTTOM SHEET (S68 §Z48, client: "fix the save calendar"). The menu opened downwards
   inside the hero, whose overflow is hidden, so it was cut in half (Apple / Outlook not reachable). On a phone it now
   rises from the bottom of the screen, above the app bar, with the page dimmed behind it (a 100vmax shadow — a tap
   there lands outside .cal-dropdown, which register.php's own click handler already treats as "close"). */
@media (max-width: 767.98px) {
  .hx--event #calDropHero .cal-dropdown-menu.open {
    position: fixed; left: 12px; right: 12px; top: auto; bottom: calc(16px + var(--app-tab-h, 0px) + env(safe-area-inset-bottom, 0px));
    transform: none; width: auto; min-width: 0; max-width: none; z-index: 100002; border-radius: 16px; border: 0;
    box-shadow: 0 0 0 100vmax rgba(15, 23, 42, .5), 0 -8px 30px rgba(0, 0, 0, .3);
    animation: hxSheet .22s ease-out;
  }
  .hx--event #calDropHero .cal-dropdown-menu.open a { padding: 16px 18px; }
}
/* Tablets and computers: the buttons sit low in a full-screen hero, so the menu opens UPWARDS from the button. */
@media (min-width: 768px) {
  .hx--event #calDropHero .cal-dropdown-menu { top: auto; bottom: calc(100% + 8px); }
}
@keyframes hxSheet { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .hx--event #calDropHero .cal-dropdown-menu.open { animation: none; } }

/* 13p. A BIGGER EVENT TITLE ON PHONES (S68 §Z49, client: "the title in the hero is too small — make it like the video
   hero"). 25px → 30px on the homepage and registration heroes; tighter line height so a long title does not tower.
   Short phones (≤660px tall) keep the smaller size set above, where the room is genuinely not there. */
@media (max-width: 575.98px) and (min-height: 661px) {
  .hx__title { font-size: 30px; line-height: 1.1; letter-spacing: -.02em; }
  .hx--event .hx__title { font-size: 28px; }   /* the registration hero also carries Back, a subtitle and the round arrow */
  .hx--event .hx__cue { margin: 12px 0 6px; }   /* room for the bigger title: measured 7px short on the 16th Annual page in the app */
}

/* 13q. PHONE HERO, TIDIED (S68 §Z50, client: "the title is still small… reduce the spacing of the date and venue… the
   Abstract and Poster buttons feel all over the place — remove the box and add an icon… the arrow on the registration
   page is useless and eats space").
   · Title 34px on the homepage, 31px on registration pages (overrides §13p).
   · Date / venue lines closer together.
   · ONE strong button (the green one) + the share circle; the secondary actions (Submit Abstract, Add to Calendar,
     View poster) become light text links with an icon — no box — still 44px tall to tap.
   · The round "scroll down" arrow on the registration hero is gone on phones (decorative; the green button does it). */
/* ⚠️ §Z51 — NO HEIGHT CONDITION and sized by WIDTH. The client's phone (display size enlarged) is ~320 × 650 CSS px in the
   app, so the "≥661px tall" rule never reached it and it got the 22px short-phone title. 8.4vw ≈ 27px at 320, 30px at 360,
   34px at 412+. Overrides the §5 short-phone 22px (this rule is later and has the same specificity). */
@media (max-width: 575.98px) {
  .hx__title, .hx--event .hx__title { font-size: clamp(26px, 8.4vw, 34px); line-height: 1.08; }
}
@media (max-width: 575.98px) {
  .hx__meta { gap: 2px 14px; }
  .hx__meta li { line-height: 1.3; }
  /* §Z51 — the secondary links sit in a LEFT-ALIGNED row (aligned with the title and the buttons above), each icon + text
     kept together on one line; they are not stretched into halves any more ("Submit Abstract" broke into two lines and
     its icon drifted away on a 320px-wide phone). With very large text the second simply wraps to its own line. */
  .hx .hx__actions .hx__btn--line,
  .hx .hx__actions > .cal-dropdown {
    flex: 0 0 auto !important; width: auto;
  }
  .hx .hx__actions .hx__btn--line {
    border: 0; background: none; box-shadow: none; min-height: 44px; padding: 0 2px; margin: 0;
    font-size: clamp(14px, 4.4vw, 15px); font-weight: 700; color: #fff; gap: 8px; justify-content: flex-start; white-space: nowrap;
  }
  .hx .hx__actions > .cal-dropdown > .hx__btn--line { width: auto; padding: 0 2px; }
  .hx .hx__actions > .hx__btn--poster { margin-left: 18px; }            /* the second link, spaced from the first */
  @media (max-width: 359.98px) {                                       /* 320-wide phones: 4px short of one line (measured) */
    .hx .hx__actions .hx__btn--line { gap: 6px; }
    .hx .hx__actions > .hx__btn--poster { margin-left: 8px; }
  }
  .hx .hx__actions .hx__btn--line:hover, .hx .hx__actions .hx__btn--line:active { background: rgba(255,255,255,.08); }
  .hx .hx__actions .hx__btn--line::before {
    font-family: "bootstrap-icons"; font-weight: normal; font-size: 17px; line-height: 1; opacity: .9;
    content: "\f358";                                     /* Submit Abstract */
  }
  .hx .hx__actions .hx__btn--poster::before { content: "\f42a"; }            /* View poster */
  .hx .hx__actions .cal-dropdown > .hx__btn--line::before { content: "\f1ef"; }   /* Add to Calendar */
  .hx--event .hx__cue { display: none; }

  /* §Z51 — COMPACT PHONE LAYOUT so the whole banner fits between the top bar and the app's bottom bar on SMALL phones
     too (measured on a 320 × 650 app window: content 613px for 508px of room). Everything here is spacing / size only. */
  .hx__wrap { padding-top: 14px; }
  .hx__eyebrow { margin-bottom: 8px; }
  .hx__title { margin-bottom: 6px; }
  .hx__sub { font-size: 13.5px; line-height: 1.35; margin-bottom: 6px; }
  .hx__meta { margin-bottom: 10px; }
  .hx__count p { margin-bottom: 6px; }
  .hx__tile { padding: 8px 4px 6px; }
  .hx__tile b { font-size: 24px; }
  .hx__actions { gap: 8px !important; }
  .hx__pager { margin-top: 10px !important; padding: 6px 0 4px; }
  .hx__arrows button { width: 36px; height: 36px; }
}

/* 13r. SHORT PHONE SCREENS (≤700px tall — small phones, phones with a large display size, and the app window with its
   bottom bar): one more compact step so the banner still ends above the app bar (S68 §Z51, measured 7–28px over at
   320 × 650 and 360 × 640). Taller phones keep §13q as it is. */
@media (max-width: 575.98px) and (max-height: 700px) {
  .hx__wrap { padding-top: 10px; }
  .hx__back { margin-bottom: 6px; }
  .hx__eyebrow { margin-bottom: 6px; padding: 4px 10px; }
  .hx__meta { margin-bottom: 8px; }
  .hx__count p { margin-bottom: 4px; }
  .hx__tile { padding: 6px 4px 5px; }
  .hx__tile b { font-size: 22px; }
  .hx__tile span { margin-top: 3px; }
  .hx__pager { margin-top: 6px !important; padding: 4px 0 2px; }
  .hx__arrows button { width: 32px; height: 32px; }
}

/* 13s. THE HERO SAYS WHERE THE EVENT STANDS (S68 §Z52, includes/hero_info.php). The badge's dot carries the status —
   green Registration open · amber Coming soon · red, pulsing, Happening now · grey Registration closed / Concluded —
   the venue becomes a link to Google Maps when the event has one (underlined, with ↗), and "Register by …" shows when
   a deadline is set. ⚠️ (0,3,1) — `.hx .hx__eyebrow--x i` was only (0,2,1), EQUAL to event.css's accent dot, which loads
   later and won (registration pages showed the event colour). All widths. */
.hx .hx__eyebrow.hx__eyebrow--open i      { background: #22c55e; box-shadow: 0 0 0 4px rgba(34,197,94,.28); }
.hx .hx__eyebrow.hx__eyebrow--soon i      { background: #f59e0b; box-shadow: 0 0 0 4px rgba(245,158,11,.28); }
.hx .hx__eyebrow.hx__eyebrow--ongoing i   { background: #ef4444; box-shadow: 0 0 0 4px rgba(239,68,68,.3); animation: hxLive 1.4s ease-in-out infinite; }
.hx .hx__eyebrow.hx__eyebrow--closed i,
.hx .hx__eyebrow.hx__eyebrow--concluded i { background: #94a3b8; box-shadow: 0 0 0 4px rgba(148,163,184,.25); }
@keyframes hxLive { 50% { box-shadow: 0 0 0 7px rgba(239,68,68,0); } }
.hx .hx__meta-map a { display: inline-flex; align-items: center; gap: inherit; color: inherit; text-decoration: underline;
  text-decoration-color: rgba(255,255,255,.45); text-decoration-thickness: 1px; text-underline-offset: 4px; }
.hx .hx__meta-map a:hover, .hx .hx__meta-map a:focus-visible { text-decoration-color: #fff; }
.hx .hx__out { width: 13px !important; height: 13px !important; opacity: .8; flex-shrink: 0; vertical-align: -1px; margin-left: 5px; }
.hx .hx__meta-map a > span { min-width: 0; }   /* the venue text + ↗ wrap together, so ↗ follows the last word */
.hx .hx__sep { margin: 0 6px; opacity: .6; }
.hx .hx__meta-dl { color: #fde68a; }
.hx .hx__meta-n { gap: 6px; }   /* §Z53 delegates · speakers — icons sized like the other meta icons */
.hx .hx__meta-n svg + * { margin-left: 0; }
/* §Z53 — short laptop screens: the busiest event (date · time · map · delegates · speakers · CME) wrapped to 3 rows and
   ran 24px past the fold at 1280×720; compact chips keep it inside. */
@media (min-width: 992px) and (max-height: 800px) {
  .hx .hx__meta { gap: 8px; margin-bottom: 18px; }
  .hx .hx__meta li { padding: 6px 11px; font-size: 15px; }
  .hx .hx__title { margin-bottom: 10px; }
}
@media (min-width: 1200px) and (max-width: 1599.98px) and (max-height: 760px) {
  .hx .hx__title { font-size: 44px; }   /* 1280×720: a 3-line title + the full details still ran 13px over at 50px */
}
@media (prefers-reduced-motion: reduce) { .hx .hx__eyebrow.hx__eyebrow--ongoing i { animation: none; } }

/* 13t. THE COMPUTER VIEW OF EACH HERO PHOTO (S68 §Z72, client: on desktop the face was cut). Gallery → ★ → move now
   has a Phone / Computer switch; the computer setting (--hdx/--hdy/--hzd, set inline) applies from 576px up. Without
   one, computers keep the centred photo as before. */
@media (min-width: 576px) {
  .hx__photo { --hz: var(--hzd, 1); background-position: var(--hdx, 50%) var(--hdy, 50%); transform-origin: var(--hdx, 50%) var(--hdy, 50%); }
}

/* ── 12. THE EVENT HERO'S ONE SLIDE IS ALWAYS SHOWN ─────────────────────────────────────────────
   LAST RULE IN THE FILE, DELIBERATELY. The event page is not a carousel: `reg_hero_hx.php` renders a
   single `.hx__slide` and nothing ever adds `is-active` to it. So any rule anywhere — here, in
   `event.css`, or in a future drop of the spec — that hides a slide and only restores the active one
   takes the whole event hero with it. That is precisely the fault this is here to make impossible.
   ⚠️ `!important` is the point of the rule, not laziness: it has to outrank a media query that has
      not been written yet.
   ⚠️ DO NOT "TIDY" THIS AWAY as a duplicate of the `:not(.hx--event)` scoping above. The scoping is
      the fix; this is the backstop for the next one. */
/* ⚠️ Somebody who has asked their device to reduce motion gets the change without the movement.
   The slide still swaps — only the animation goes. */
@media (prefers-reduced-motion: reduce) {
  .hx:not(.hx--event) .hx__slide { transition: none; transform: none; }
}

.hx--event .hx__slide {
  display: grid !important;
  opacity: 1 !important;
  visibility: visible !important;
  transform: none !important;
}
