/* Ours, not the theme's — loaded last so a fresh copy of the theme's CSS can be
   dropped in over it without losing anything we have written. Same arrangement
   as /members/css/csear-portal-overrides.css. */

/* The template's root layout stamps Tailwind utility names on <body>:
   `min-h-full flex flex-col font-inter`. Tailwind itself is deliberately not
   loaded on this surface, so those normally do nothing — but the theme's own
   style.css happens to define a `.flex` class of its own:

       .flex { display: flex; flex-direction: row; flex-wrap: wrap; }

   which turned <body> into a wrapping ROW. The black header bar shrank to its
   content width, the logo clipped, and every section below it laid out as a
   flex item rather than a block. `flex-col` does not undo it — Tailwind's class
   is not defined here, so the direction stays `row`.

   Named with the class so the intent is legible in devtools, and so it beats
   the theme's single-class rule on specificity without !important. */
body.flex {
  display: block;
}

/* Conference cards on the events archive.
   .image_event is a fixed 441px flex panel that the theme centres a small logo
   in — the ACF `image_conference` graphic, not a poster. What the conferences
   table has is the members-area flyer, which is 1198x1600, so unconstrained it
   burst out of the panel and covered the page heading. Scaled to fit instead,
   until the website's own conference image field exists (STAGE-2-PLAN §4). */
.event-conference-row .image_event > img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* Homepage "Latest from the journal" card images.
   functions.php:57 registers add_image_size('front-size', 358, 405, true) and
   front-page.php asks WordPress for that size, so the theme can afford
   `.front-latest-journal .post_frame .image { height: auto }` (style.css:3102)
   — the file it is handed is already cropped. We serve the original out of
   Supabase Storage, so the crop has to happen here instead, or a portrait
   original makes the card 160px taller than the live one. */
.front-latest-journal .post_frame .image img {
  width: 100%;
  height: auto;
  aspect-ratio: 358 / 405;
  object-fit: cover;
}

/* ── Skip link (WCAG 2.4.1 Bypass Blocks, Level A) ──────────────────────────
   Hidden until it takes keyboard focus, then it appears top-left above
   everything. Not display:none and not visibility:hidden — both remove an
   element from the focus order, which would make the link unreachable by the
   only people who need it. Clipped to a 1px box instead, the standard
   visually-hidden pattern.

   The header is fixed on this theme, so the z-index has to beat it or the link
   appears behind the navigation it exists to bypass. */
.vh-skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10000;
  padding: 12px 20px;
  background: #ffffff;
  color: #111111;
  font-weight: 700;
  text-decoration: underline;
  border: 2px solid #111111;
  border-radius: 0 0 4px 0;
}
.vh-skip-link:focus,
.vh-skip-link:focus-visible {
  left: 0;
}

/* The skip target takes focus programmatically; it is not an interactive
   control, so the focus ring would be noise. Removing it is safe ONLY because
   the element is reached by the skip link rather than by tabbing. */
#main-content:focus {
  outline: none;
}

/* ── Cookie banner on the website surface ───────────────────────────────────
   The banner component is shared with the admin and the template's public
   routes, and it is styled entirely in Tailwind. This surface deliberately does
   NOT load globals.css — front-end and admin CSS are kept apart — so not one of
   those classes resolves here. The result was a static, full-width block
   dumped at the foot of the page instead of a fixed overlay, which is what
   pushed the layout wide.

   These rules exist only in this stylesheet, which only the website loads, so
   the admin and (public) keep their Tailwind version untouched. Hooks are the
   vh-cookie* classes on the component; the Tailwind classes are left in place
   beside them and simply do nothing here. */
.vh-cookie {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* The banner must never be what makes the page scroll sideways. */
  max-width: 100vw;
  overflow: hidden;
}
.vh-cookie__scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
}
.vh-cookie__panel {
  position: relative;
  z-index: 10;
  display: flex;
  flex-direction: column;
  /* The theme's .flex (style.css) is `display:flex; flex-flow: wrap`, and the
     panel carries that class. The wrap is not harmless: once the three
     sections were taller than max-height, the FOOTER wrapped into a second
     column, 371px to the right on a 386px screen — so Decline All, Save
     Preferences and Accept All were off-screen and unreachable on a phone.
     A consent dialog you cannot answer. Measured 2026-10-19. */
  flex-wrap: nowrap;
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  overflow: hidden;          /* the body scrolls, not the whole panel */
  background: #fff;
  box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.18);
  font-family: sofia-pro, sans-serif;
}
/* !important, and a two-class selector, because of the collision described at
   the bottom bar below: the component is written in Tailwind, this surface has
   none, and the theme's Bootstrap defines .px-6 as `padding: 0 66px !important`.
   The panel's header, body and footer all carry px-6. */
.vh-cookie .vh-cookie__panel > div { padding: 18px 22px !important; }
/* Header and footer stay put; the middle section is the one that scrolls.
   min-height:0 is required — without it a flex item will not shrink below its
   content and the footer gets pushed out of the panel again. */
.vh-cookie .vh-cookie__panel > div:first-child,
.vh-cookie .vh-cookie__panel > div:last-child { flex: 0 0 auto; }
.vh-cookie .vh-cookie__panel > div:not(:first-child):not(:last-child) {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
.vh-cookie__panel h2 { font-size: 17px; font-weight: 700; margin: 0; }
.vh-cookie__panel p  { font-size: 14px; line-height: 1.55; color: #555; margin: 0 0 4px; }
.vh-cookie__panel button {
  min-height: 44px;              /* a real tap target */
  padding: 10px 18px;
  border-radius: 8px;
  border: 1px solid #1d1d1b;
  background: #fff;
  color: #1d1d1b;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
/* Accept is the primary action — the theme's blue, matching the site buttons. */
.vh-cookie__panel > div:last-child button:last-child {
  background: #2d55e8;
  border-color: #2d55e8;
  color: #fff;
}
.vh-cookie__panel > div:last-child {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  border-top: 1px solid #f0f0f0;
}
.vh-cookie__panel > div:last-child button { flex: 1 1 140px; }

@media (min-width: 576px) {
  .vh-cookie { align-items: center; }
  .vh-cookie__panel { border-radius: 14px; }
}

/* The bottom bar — the banner a visitor actually meets first.
   The .vh-cookie rules above cover the Preferences modal; this is the other
   branch of the same component, and the one that was breaking the layout:
   without Tailwind `fixed bottom-0 inset-x-0` does nothing, so it rendered as a
   static full-width block at the foot of the document.

   ⚠️ The class names in this component are Tailwind, and this surface has no
   Tailwind — but it is NOT true that they therefore do nothing. The theme's
   vendored Bootstrap 4 and style.css define some of the same names, several
   with !important, so they actively fight anything written here:

     .px-6   → padding-left/right: 66px !important   (a custom 66px spacer)
     .py-4   → padding-top/bottom: 1.5rem !important (21px at this root size)
     .flex   → display: flex; flex-flow: wrap        (style.css)

   `.px-6` is specificity (0,1,0), so a plain `.vh-cookiebar__inner` rule TIES
   with it and then loses on !important. Hence the doubled-up selectors and the
   !important on padding below — they have to out-specify Bootstrap, not just
   come later in the file. Measured on a 386px viewport before the fix: the bar
   was 411px tall, 49% of the screen. After: 190px.

   Written mobile-first on purpose. The previous version was desktop-first with
   a max-width:575px override, and that is what produced the worst of the bug:
   `flex: 1 1 260px` on the text block is a sensible WIDTH basis in a row, but
   the mobile rule flipped the container to `column` without resetting it, so
   260px became a HEIGHT — a 260px-tall box with the cookie icon and the
   paragraph stretched to opposite ends of it. The basis now only exists inside
   the min-width:576px block, where the row layout it was written for lives. */
.vh-cookiebar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 100;
  width: 100%;
  max-width: 100vw;
  background: #fff;
  border-top: 1px solid #e9ecef;
  box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.12);
  font-family: sofia-pro, sans-serif;
}
.vh-cookiebar__inner {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;   /* stacked by default; a row from 576px up */
  align-items: stretch;
  gap: 12px;
}
/* Beats .px-6 / .py-4 — see the note above. */
.vh-cookiebar .vh-cookiebar__inner { padding: 16px 22px !important; }
.vh-cookiebar .vh-cookiebar__inner > div { width: 100%; min-width: 0; }

/* Icon + text. `.flex` from style.css gives this display:flex with
   flex-flow:wrap, which put the paragraph on a second flex line; nowrap keeps
   it beside the icon, and flex-start stops the icon centring against a
   multi-line paragraph. */
.vh-cookiebar .vh-cookiebar__inner > div:first-child {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: 10px;
}
.vh-cookiebar .vh-cookiebar__inner > div:first-child > svg {
  flex: 0 0 auto;
  margin-top: 2px;          /* optically centred on the first line */
}

/* Actions. Nothing defines a gap for these on this surface, so without this the
   two buttons sit flush against one another. */
.vh-cookiebar .vh-cookiebar__inner > div:last-child {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
}

.vh-cookiebar p { margin: 0; font-size: 13px; line-height: 1.5; color: #555; }
.vh-cookiebar p span { font-weight: 700; color: #1d1d1b; }
.vh-cookiebar a { text-decoration: underline; }
.vh-cookiebar button {
  min-height: 44px;
  padding: 10px 16px !important;   /* .px-6 again — the Accept button carries it */
  width: 100%;
  border-radius: 8px;
  border: 1px solid #1d1d1b;
  background: #fff;
  color: #1d1d1b;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  white-space: normal;
}
/* Accept is the primary action, in the theme's blue. */
.vh-cookiebar button:last-child {
  background: #2d55e8;
  border-color: #2d55e8;
  color: #fff;
}

/* From small-tablet up there is room for the original single row. */
@media (min-width: 576px) {
  .vh-cookiebar .vh-cookiebar__inner {
    flex-direction: row;
    flex-wrap: wrap;        /* never forces the page wider */
    align-items: center;
    gap: 14px;
  }
  .vh-cookiebar .vh-cookiebar__inner > div { width: auto; }
  .vh-cookiebar .vh-cookiebar__inner > div:first-child { flex: 1 1 260px; }
  .vh-cookiebar .vh-cookiebar__inner > div:last-child {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: center;
    gap: 12px;
  }
  .vh-cookiebar p { font-size: 14px; }
  .vh-cookiebar button {
    width: auto;
    white-space: nowrap;
    padding: 10px 20px !important;
  }
}

/* ── Mobile menu: open and close immediately ────────────────────────────────
   The theme sets `transition: 0.8s` on .overlay (style.css, inside
   @media max-width: 1200px). Three things wrong with it, and none are ours —
   it came across with the theme:

     - 0.8s is very slow for a navigation menu. Nearly a second between tapping
       the icon and being able to use it reads as lag rather than polish.
     - No property is named, so it is `all`: every property change on the
       overlay animates, not just the one intended.
     - It animates HEIGHT, a layout property, on a full-screen element. That
       forces a re-layout every frame, which is what makes it feel rough on a
       phone as well as slow.

   Overridden here rather than edited in style.css, which is kept byte-identical
   to the WordPress theme — that is what let us prove earlier that no CSS was
   missing, and it stops being useful the moment we start editing it.

   If the snap ever feels too abrupt, the fix is a short opacity fade rather
   than a faster height animation: opacity is composited and does not re-layout. */
@media (max-width: 1200px) {
  .overlay {
    transition: none;
  }
}

/* ── Country → fee band picker ───────────────────────────────────────────────
   The membership page's "which band am I in?" control
   (components/site/country-band-picker.tsx).

   Every class is vh-cb-prefixed on purpose. This surface has no Tailwind, and
   the theme's vendored Bootstrap defines several names a utility-first
   component would reach for — `.px-6` as `padding: 0 66px !important` among
   them, which is what crushed the cookie bar. A prefix nothing else uses is
   the only way to be sure of what is applying. */
.vh-cb {
  position: relative;
  max-width: 420px;
  margin: 0 0 24px;
  font-family: sofia-pro, sans-serif;
}
.vh-cb__label {
  display: block;
  margin: 0 0 6px;
  font-size: 14px;
  font-weight: 700;
  color: #1d1d1b;
}
.vh-cb__field {
  position: relative;
  display: flex;
  align-items: stretch;
}
.vh-cb__input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 46px;            /* a real tap target */
  padding: 10px 40px 10px 14px;
  border: 1px solid #c9ced6;
  border-radius: 8px;
  background: #fff;
  font-size: 16px;             /* 16px or iOS zooms the page on focus */
  color: #1d1d1b;
}
.vh-cb__input:focus {
  outline: 2px solid #2d55e8;
  outline-offset: 1px;
  border-color: #2d55e8;
}
.vh-cb__toggle {
  position: absolute;
  right: 1px;
  top: 1px;
  bottom: 1px;
  width: 36px;
  border: 0;
  border-radius: 0 8px 8px 0;
  background: transparent;
  color: #6b7280;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}

.vh-cb__list {
  position: absolute;
  z-index: 50;
  left: 0;
  right: 0;
  margin: 4px 0 0;
  padding: 4px;
  max-height: 290px;
  overflow-y: auto;
  list-style: none;            /* the theme styles bare <ul> on this surface */
  background: #fff;
  border: 1px solid #c9ced6;
  border-radius: 8px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.14);
}
.vh-cb__option {
  padding: 10px 12px;
  border-radius: 6px;
  font-size: 15px;
  line-height: 1.3;
  color: #1d1d1b;
  cursor: pointer;
}
/* Highlight follows the keyboard as well as the pointer, so the two never
   disagree about which option Enter would take. */
.vh-cb__option.is-active {
  background: #2d55e8;
  color: #fff;
}
.vh-cb__more {
  padding: 8px 12px;
  font-size: 13px;
  color: #6b7280;
}

.vh-cb__status {
  margin: 10px 0 0;
  font-size: 15px;
  line-height: 1.5;
  color: #1d1d1b;
}
.vh-cb__hint { color: #6b7280; }
.vh-cb__verify {
  margin: 6px 0 0;
  font-size: 14px;
}
.vh-cb__verify a { text-decoration: underline; }

@media (max-width: 575px) {
  .vh-cb { max-width: none; }
  .vh-cb__list { max-height: 240px; }
}

/* Fee table, narrowed by country (components/site/membership-fees.tsx). */
.vh-fees__note {
  margin: 0 0 10px;
  font-size: 14px;
  line-height: 1.5;
  color: #1d1d1b;
  font-family: sofia-pro, sans-serif;
}
.vh-fees__all {
  border: 0;
  padding: 0;
  background: none;
  color: #2d55e8;
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}
/* The band a row belongs to, shown only while the table is unfiltered — two
   rows reading "Individual" at different prices is otherwise just confusing. */
.vh-fees__band {
  display: block;
  font-size: 12px;
  line-height: 1.3;
  color: #6b7280;
}

/* The "Join today" button scrolls here. Without the margin the fee section
   lands flush against the top of the window — and under the fixed header bar
   on a phone, which hides the very control the button exists to reach. */
#fees { scroll-margin-top: 100px; }
#fees:focus { outline: none; }

/* ---------------------------------------------------------------------------
   WordPress caption and alignment classes.

   wpContent() ports the [caption] shortcode, and the imported bodies still
   carry WordPress's own classes — alignleft, size-medium, wp-image-123. The
   theme never shipped the CSS for any of them: checked 2026-11-09, none of
   .wp-caption, .wp-caption-text or the four align* classes were defined in a
   single stylesheet, Bootstrap included. So on eight published articles a
   photo the author had placed beside the text rendered as an unfloated block
   and its caption as plain body copy — worse than no styling, because
   WordPress writes the box width inline (style="width: 210px"), leaving a
   narrow column stranded in the text.

   The names are WordPress's and nothing else here uses them, so these rules
   are global. Float containment cannot be: it needs the container, so
   #content_text — the article body, where all eight cases live — gets
   flow-root. Another wpContent container will need the same if floated
   content ever lands in it.
   --------------------------------------------------------------------------- */

/* Contain the floats so a tall picture cannot run past the end of the article
   and over whatever follows it. */
#content_text { display: flow-root; }

.alignnone {
  max-width: 100%;
  height: auto;
}
.aligncenter {
  display: block;
  margin: 1rem auto;
  max-width: 100%;
  height: auto;
}
.alignleft {
  float: left;
  margin: 0.35rem 1.5rem 1rem 0;
  max-width: 100%;
  height: auto;
}
.alignright {
  float: right;
  margin: 0.35rem 0 1rem 1.5rem;
  max-width: 100%;
  height: auto;
}

/* max-width rather than width: the inline width attribute stays authoritative
   on a wide screen, but cannot overflow a narrow one. */
.wp-caption {
  max-width: 100%;
  margin-bottom: 1rem;
}
.wp-caption img {
  display: block;
  max-width: 100%;
  height: auto;
}
.wp-caption-text {
  margin: 0.5rem 0 0;
  font-size: 14px;
  line-height: 1.4;
  color: #6b7280;
}

/* A float inside a phone-width column leaves a one-word gutter beside the
   picture, which reads as broken. Below the theme's small breakpoint the
   images stack and centre instead, and the inline width has to go with them. */
@media (max-width: 575.98px) {
  .alignleft,
  .alignright {
    float: none;
    margin: 1rem auto;
  }
  .wp-caption {
    width: auto !important;
    margin-left: auto;
    margin-right: auto;
  }
}
