/* ═══════════════════════════════════════════════════════════════════
   QPEC 2026 — Queen's Pharmacy Education Conference
   Phone-first app, in the conference identity: charcoal ground,
   conference pink #CF7E9A and conference green #48B187.

   The two identity colours are light — pink is 2.96:1 on white and
   green 2.65:1, so neither is legible as body text. Each therefore
   has a darkened sibling that clears WCAG AA (4.5:1) for anything
   carrying words; the pure identity colours are kept for large type,
   fills and anything sitting on the charcoal ground.
   ═══════════════════════════════════════════════════════════════════ */

:root {
  /* Conference pink */
  --pink: #CF7E9A;        /* identity — on charcoal, or large display type */
  --pink-mid: #BE5177;    /* 4.53:1 on white — fills, borders, selected states */
  --pink-dark: #9E3C5E;   /* 6.44:1 — links and small text */
  --pink-ink: #5E2338;    /* text on a pink tint */
  --pink-soft: #F0B8CA;    /* small text on the charcoal ground — 7.5:1 */
  --pink-tint: #FCF4F7;
  --pink-tint-2: #F6E1E9;

  /* Conference green — reserved for the live/now state and primary actions */
  --green: #48B187;       /* identity */
  --green-mid: #358263;   /* 4.64:1 on white */
  --green-deep: #1F5F47;  /* text on a green tint */
  --green-ink: #12231C;   /* text on solid green, as on the splash button */
  --green-tint: #EEF8F3;
  --green-tint-2: #D8EFE5;

  /* Charcoal — the splash ground, carried into the chrome */
  --char: #333333;
  --char-2: #262626;
  --char-3: #1A1A1A;
  --hero-art: url("assets/brand/splash-bg.webp");

  /* Neutrals — Cool Grey ladder */
  --ink: #16181B;
  --ink-2: #2A2D31;
  --grey-11: #53565A;
  --grey-7: #63676B;   /* 5.2:1 on the canvas — was #6F7378 at 4.37 */
  --grey-5: #B1B3B3;   /* borders, dots and placeholders only — 1.9:1, never text */
  --grey-4: #C9CBCC;
  --grey-3: #DFE1E2;
  --grey-2: #EDEEEF;
  --grey-1: #F6F7F7;
  --paper: #FFFFFF;
  --canvas: #F4F5F6;

  /* One accent beyond the identity, for the snapshot format and
     provisional notices — everything else is pink, green or charcoal. */
  --amber: #8A5900;    /* 5.4:1 on its own tint — was #A66A00 at 4.07 */
  --amber-tint: #FDF3E2;

  /* Shape */
  --r-xl: 20px;
  --r-lg: 14px;
  --r-md: 10px;
  --r-sm: 7px;
  --r-pill: 999px;

  /* Shadow */
  --sh-xs: 0 1px 2px rgba(22,24,27,.05);
  --sh-sm: 0 1px 3px rgba(22,24,27,.07), 0 1px 2px rgba(22,24,27,.04);
  --sh-md: 0 8px 24px rgba(22,24,27,.08), 0 2px 6px rgba(22,24,27,.04);
  --sh-lg: 0 24px 60px rgba(22,24,27,.16), 0 6px 16px rgba(22,24,27,.08);
  --sh-brand: 0 6px 20px rgba(51,51,51,.22);

  /* Layout */
  --topbar-h: 64px;
  --tabbar-h: 62px;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --gutter: 18px;
  --max-w: 720px;

  /* Type — Brandon Text is the QUB brand face; Arial is the sanctioned fallback */
  --sans: "Brandon Text", "Brandon Grotesque", "Segoe UI", -apple-system,
          BlinkMacSystemFont, "Helvetica Neue", Arial, system-ui, sans-serif;
  --display: "Brandon Grotesque", "Brandon Text", "Segoe UI", -apple-system,
             BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* Several components below set an explicit `display`, which would otherwise
   beat the UA rule for the `hidden` attribute and leave invisible elements
   swallowing taps. This keeps `hidden` meaning hidden, everywhere. */
[hidden] { display: none !important; }

/* Text for screen readers only. `display: none` and `visibility: hidden` both
   remove it from the accessibility tree as well as the screen, so it has to be
   clipped to nothing instead while staying technically rendered. */
.vh {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink-2);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  /* --banner-h is measured in app.js: the banner stack is fixed, so without
     it a live banner sits on top of the first 40-odd pixels of the page.
     On the homepage that is the top of the hero and nobody notices; on a
     sub-page it is exactly where "‹ Back" is, and the banner swallows the
     tap. Content has to start below whatever is actually showing. */
  padding-top: calc(var(--topbar-h) + var(--safe-t) + var(--banner-h, 0px));
  padding-bottom: calc(var(--tabbar-h) + var(--safe-b) + 12px);
  transition: padding-top .18s ease;
  min-height: 100vh;
}
body.is-splash { overflow: hidden; }
body.modal-open { overflow: hidden; }

button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
a { color: var(--pink-dark); text-decoration: none; }
a:hover, a:focus-visible { text-decoration: underline; }

h1, h2, h3, h4 {
  font-family: var(--display);
  color: var(--ink);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.2;
  margin: 0 0 .4em;
}
p { margin: 0 0 .8em; }
:focus-visible { outline: 3px solid var(--pink-mid); outline-offset: 2px; border-radius: 4px; }

svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ═══════════════════════════════ Splash ═══════════════════════════════ */
/* Matches the QPEC conference identity as used on the website: charcoal
   ground, neon contour artwork, RL Folklor set left-aligned and uppercase,
   the wordmark in conference pink and the strapline in white.
   Sampled from the live site — pink #CF7E9A, green #48B187. */

.splash {
  --qpec-pink: #CF7E9A;
  --qpec-green: #48B187;
  position: fixed; inset: 0; z-index: 400;
  background-color: #333;
  background-image: url("assets/brand/splash-bg.webp");
  background-size: cover;
  background-position: center;
  color: #fff;
  text-align: left;
  overflow-y: auto;
  animation: fade-in .4s ease both;
}
/* Keeps type legible wherever the contour lines fall, without flattening them. */
.splash::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(26,26,26,.78) 0%, rgba(30,30,30,.35) 30%,
                    rgba(30,30,30,.35) 66%, rgba(26,26,26,.8) 100%);
}
.splash.is-gone { animation: splash-out .45s cubic-bezier(.4,0,.2,1) both; pointer-events: none; }
@keyframes splash-out { to { opacity: 0; transform: scale(1.04); visibility: hidden; } }
@keyframes fade-in { from { opacity: 0 } to { opacity: 1 } }

.splash-grid {
  position: relative; z-index: 1;
  min-height: 100%;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 22px;
  padding: calc(40px + var(--safe-t)) 28px calc(30px + var(--safe-b));
  max-width: 540px; margin: 0 auto;
  animation: rise .55s cubic-bezier(.2,.8,.2,1) both .06s;
}
@keyframes rise { from { opacity: 0; transform: translateY(16px) } to { opacity: 1; transform: none } }

/* ── Wordmark ── */
.splash-head { align-self: start; }
/* Now artwork, not type. Width-driven so it scales with the viewport the way
   the typeset version did, and capped so it never dwarfs the detail below. */
.splash-mark {
  margin: 0 0 10px;
  line-height: 0;
}
.splash-mark img {
  display: block;
  width: min(86%, 420px);
  height: auto;
  filter: drop-shadow(0 4px 34px rgba(0,0,0,.4));
}


/* ── Detail ── */
.splash-mid { align-self: center; }
.splash-date {
  font-family: var(--display); font-weight: 700;
  font-size: 13px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--qpec-green); margin: 0 0 5px;
}
.splash-where {
  font-size: 14.5px; color: rgba(255,255,255,.74); margin: 0 0 24px;
}
.splash-theme {
  font-family: var(--sans); font-weight: 600;
  font-size: clamp(17px, 4.7vw, 21px);
  line-height: 1.38; color: #fff;
  margin: 0 0 28px;
  padding-top: 22px; position: relative;
}
.splash-theme::before {
  content: ""; position: absolute; top: 0; left: 0;
  width: 60px; height: 3px; background: var(--qpec-green);
}
.splash-btn {
  background: var(--qpec-green); color: #12231C;
  font-family: var(--display); font-weight: 700; font-size: 16.5px;
  padding: 15px 32px; border-radius: var(--r-pill);
  box-shadow: 0 12px 32px rgba(0,0,0,.4);
  transition: transform .16s ease, box-shadow .16s ease, background .16s ease;
}
.splash-btn:active { transform: scale(.97); background: #3F9E78; }

/* ── School of Pharmacy lockup ── */
.splash-foot { align-self: end; padding-top: 10px; }
.splash-foot img {
  width: min(268px, 72%); height: auto; display: block;
  opacity: .95;
}

@media (max-height: 700px) {
  .splash-grid { gap: 14px; padding-top: calc(26px + var(--safe-t)); }
  .splash-mark img { width: min(92%, 320px); }
  .splash-where { margin-bottom: 16px; }
  .splash-theme { padding-top: 15px; margin-bottom: 20px; }
  .splash-foot img { width: min(232px, 62%); }
}

/* ═══════════════════════════════ Top bar ═══════════════════════════════ */
.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 90;
  height: calc(var(--topbar-h) + var(--safe-t));
  padding-top: var(--safe-t);
  background: linear-gradient(180deg, var(--char) 0%, var(--char-2) 100%);
  color: #fff;
  box-shadow: 0 1px 0 rgba(0,0,0,.06), 0 4px 16px rgba(0,0,0,.18);
}
.topbar-inner {
  height: var(--topbar-h);
  max-width: var(--max-w); margin: 0 auto;
  padding: 0 var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
/* "QPEC 2026" is still one lockup, but QPEC is now the artwork rather than
   type. The mark is sized by height so the year can be matched to it: 18px of
   mark, 18px of cap height, sitting on one baseline with a hairline between.
   align-items: center rather than baseline — an image has no baseline of its
   own, so aligning to one would hang the year off the bottom of the mark. */
/* min-height, because the button is only as tall as what is inside it and the
   mark is 18px — which left the tap target under the WCAG 2.2 minimum of
   24x24 the moment the typeset wordmark went. 44 is the comfortable size for
   a thumb; the bar has the room, and the row is centred so nothing moves. */
.topbar-brand {
  display: flex; align-items: center; gap: 10px; color: #fff;
  min-height: 44px;
}
.topbar-wordmark { display: block; line-height: 0; }
.topbar-wordmark img { display: block; height: 18px; width: auto; }
.topbar-sub {
  font-family: var(--display); font-weight: 700; font-size: 22px; line-height: 1;
  letter-spacing: .02em; color: #fff;
  border-left: 1px solid rgba(255,255,255,.32); padding-left: 10px;
}
/* A phone bar cannot hold the wordmark, the year, both icons and a lockup
   that is still legible. The year gives way below 520px — the splash, the
   hero and the page title all still say 2026 — and the lockup keeps the room,
   since that is the School branding the bar is there to carry. */
@media (max-width: 519px) { .topbar-sub { display: none; } }
.topbar-actions { display: flex; align-items: center; gap: 4px; }
.icon-btn {
  width: 38px; height: 38px; border-radius: var(--r-pill);
  display: grid; place-items: center; color: #fff; position: relative;
  transition: background .15s ease;
}
.icon-btn:active { background: rgba(255,255,255,.18); }
.icon-btn svg { width: 21px; height: 21px; }
#btn-stars.is-on svg { fill: #fff; }
.star-count {
  position: absolute; top: 2px; right: 1px;
  min-width: 17px; height: 17px; padding: 0 4px;
  background: var(--pink); color: var(--char-3);
  border-radius: var(--r-pill);
  font-size: 10.5px; font-weight: 700; line-height: 17px; text-align: center;
}

/* The School of Pharmacy lockup closes the bar. It only reads at a sensible
   size, so the bar is a little taller than a stock app bar. Below 380px there
   is not room for even the lockup, so the crest stands in. Decorative in both
   cases: the footer carries the described version with its alt text, so the
   bar does not repeat it to a screen reader. */
.topbar-logo {
  flex: none; display: flex; align-items: center;
  margin-left: 10px; padding-left: 12px;
  border-left: 1px solid rgba(255,255,255,.22);
}
/* Both selectors are class+element so neither can out-specify the other and
   quietly un-hide the variant that is meant to be off. */
.topbar-logo .tb-lockup { display: block; width: auto; height: 32px; }
.topbar-logo .tb-crest { display: none; width: auto; height: 30px; }
@media (max-width: 379px) {
  .topbar-logo .tb-lockup { display: none; }
  .topbar-logo .tb-crest { display: block; }
  .topbar-logo { margin-left: 6px; padding-left: 9px; }
}

/* ═══════════════════════════════ Banners ═══════════════════════════════ */
/* One stack, so two banners at once sit under one another rather than exactly
   on top of one another. The stack is fixed; content scrolls behind it, which
   is the same behaviour each banner had on its own. */
.banner-stack {
  position: fixed; left: 0; right: 0; z-index: 88;
  top: calc(var(--topbar-h) + var(--safe-t));
  display: flex; flex-direction: column;
}
.banner {
  padding: 10px var(--gutter);
  font-size: 14px; text-align: center;
  display: flex; align-items: center; justify-content: center; gap: 10px;
}
.banner-text { flex: 1; text-align: center; }
/* 17x22 as it stood, against a WCAG 2.2 minimum of 24x24 — a glyph sized to
   look right rather than a target sized to be hit. The box is now 32 square
   with the x centred in it, so the type is unchanged and only the tappable
   area grows. */
.banner-dismiss {
  background: none; font-size: 22px; line-height: 1; padding: 0;
  min-width: 32px; min-height: 32px;
  display: grid; place-items: center;
  opacity: .6; flex: none; color: inherit;
}
.update-banner { background: var(--ink); color: #fff; }
.update-banner button {
  background: var(--pink-mid); color: #fff; font-weight: 700; font-size: 13px;
  padding: 6px 14px; border-radius: var(--r-pill); flex: none;
}
.offline-banner { background: var(--amber-tint); color: var(--amber); font-weight: 600; }

/* An announcement is the organisers speaking to the room, so it takes the
   charcoal of the chrome rather than a status colour. */
.announce-banner { background: var(--char); color: #fff; text-align: left; }
.announce-banner .banner-text { text-align: left; font-weight: 600; line-height: 1.4; }
.announce-banner::before {
  content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%;
  background: var(--pink); margin-top: 5px; align-self: flex-start;
}

/* Feedback opening is the one thing the app announces unprompted, so it gets
   the conference green. */
.feedback-banner { background: var(--green); color: var(--green-ink); font-weight: 600; }
.feedback-banner button:not(.banner-dismiss) {
  background: var(--green-ink); color: #fff; font-weight: 700; font-size: 13px;
  padding: 6px 14px; border-radius: var(--r-pill); flex: none;
}
.closed-card { border-left: 4px solid var(--amber); }
/* Organiser switch — green while open, so its state reads before the words do. */
.org-switch { border-left: 4px solid var(--grey-4); }
.org-switch.is-open { border-left-color: var(--green); background: var(--green-tint); }
.org-switch .btn { margin-top: 12px; }

/* ═══════════════════════════════ Layout ═══════════════════════════════ */
#main { max-width: var(--max-w); margin: 0 auto; }
.view { padding: 0 var(--gutter) 40px; animation: view-in .26s ease both; }
@keyframes view-in { from { opacity: 0; transform: translateY(7px) } to { opacity: 1; transform: none } }

.view-head { padding: 22px 0 14px; }
.view-title { font-size: 29px; margin: 0 0 2px; }
.view-sub { color: var(--grey-7); font-size: 14.5px; margin: 0; }

.block { margin-top: 30px; }
.block-title {
  font-size: 12px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--grey-7); margin: 0 0 12px;
}

/* ═══════════════════════════════ Hero ═══════════════════════════════ */
.hero {
  margin: 18px 0 0;
  padding: 28px 22px 26px;
  /* The conference contour artwork, same file as the splash — it is preloaded
     for the splash anyway, so this costs no extra bytes. The scrim over it is
     heaviest at the left, where the type sits, and thins out to the right so
     the contours are legible in the space the copy leaves empty. */
  background:
    linear-gradient(100deg, rgba(22,22,22,.94) 0%, rgba(22,22,22,.87) 30%,
                    rgba(24,24,24,.6) 64%, rgba(24,24,24,.34) 100%),
    var(--hero-art) 78% 62% / cover no-repeat,
    linear-gradient(160deg, var(--char) 0%, var(--char-2) 55%, var(--char-3) 100%);
  color: #fff;
  border-radius: 26px;
  box-shadow: var(--sh-brand);
  position: relative; overflow: hidden;
}
/* The lockup at the head of the hero, capped so it never overpowers the
   theme line beneath it. */
.hero-mark { margin: 0 0 14px; line-height: 0; }
.hero-mark img { display: block; width: min(62%, 230px); height: auto; }

.hero-title {
  color: #fff; font-size: clamp(24px, 6.6vw, 31px); line-height: 1.15;
  margin: 0 0 14px; max-width: 17ch;
}
@media (min-width: 560px) { .hero-title { max-width: 24ch; } }
.hero-meta {
  display: flex; flex-wrap: wrap; gap: 7px; align-items: center;
  font-size: 14px; color: rgba(255,255,255,.9); margin: 0;
}
.hero-meta .dot { color: rgba(255,255,255,.5); }

.countdown {
  display: flex; gap: 8px; margin-top: 20px; position: relative; z-index: 1;
}
.cd-unit {
  flex: 1; background: rgba(255,255,255,.15);
  border: 1px solid rgba(255,255,255,.2);
  border-radius: var(--r-md); padding: 9px 4px; text-align: center;
  backdrop-filter: blur(6px);
}
.cd-num { font-family: var(--display); font-weight: 700; font-size: 23px; line-height: 1.1; color: #fff; }
.cd-lbl { font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: rgba(255,255,255,.78); }
.cd-live {
  margin-top: 18px; padding: 11px 15px; border-radius: var(--r-md);
  background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.24);
  font-size: 14.5px; font-weight: 600; color: #fff;
  display: flex; align-items: center; gap: 9px;
}
.pulse {
  width: 8px; height: 8px; border-radius: 50%; background: #fff; flex: none;
  animation: pulse 1.9s ease-in-out infinite;
}
@keyframes pulse { 0%,100% { opacity: 1; box-shadow: 0 0 0 0 rgba(255,255,255,.6) } 50% { opacity: .65; box-shadow: 0 0 0 7px rgba(255,255,255,0) } }

/* ═══════════════════════════════ Now card ═══════════════════════════════ */
.now-card {
  margin-top: 18px; padding: 16px 18px;
  background: var(--paper); border-radius: var(--r-lg);
  border-left: 4px solid var(--green); box-shadow: var(--sh-sm);
}
/* Anything live runs in the conference green, so "now" reads at a glance
   without competing with the pink used for navigation. */
.now-card .now-kicker {
  font-size: 11px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--green-deep); margin: 0 0 5px;
  display: flex; align-items: center; gap: 7px;
}
.now-card .pulse { background: var(--green-mid); }
.now-card h2 { font-size: 18px; margin: 0 0 3px; }
.now-card .now-meta { font-size: 13.5px; color: var(--grey-7); margin: 0; }
.now-next { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--grey-2); font-size: 13.5px; color: var(--grey-7); }
.now-next strong { color: var(--ink-2); }
.now-split { height: 1px; background: var(--grey-2); margin: 14px 0; }
.now-talk {
  display: block; width: 100%; text-align: left; margin-top: 10px;
  padding: 10px 12px; border-radius: var(--r-md); background: var(--green-tint);
  font-size: 13.5px; color: var(--green-deep); line-height: 1.45;
}
.now-talk strong { color: var(--green-deep); }

/* ═══════════════════════════════ Quick grid ═══════════════════════════════ */
/* Wrapping flex rather than a grid: with an odd number of tiles a grid leaves
   a hole in the last row, while flex items grow to share whatever is left.
   Two per row on a phone, three from 560px — see the Responsive block. */
.quick-grid {
  display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px;
}
.quick {
  flex: 1 1 calc(50% - 5px); min-width: 0;
  background: var(--paper); border-radius: var(--r-lg); padding: 15px 14px;
  text-align: left; box-shadow: var(--sh-sm);
  border: 1px solid var(--grey-2);
  display: flex; flex-direction: column; gap: 3px;
  transition: transform .14s ease, box-shadow .14s ease;
}
.quick:active { transform: scale(.975); box-shadow: var(--sh-xs); }
.quick-ico {
  width: 34px; height: 34px; border-radius: var(--r-sm);
  background: var(--pink-tint); color: var(--pink-dark);
  display: grid; place-items: center; margin-bottom: 7px;
}
.quick-ico svg { width: 19px; height: 19px; }
.quick-label { font-family: var(--display); font-weight: 700; font-size: 15.5px; color: var(--ink); }
.quick-sub { font-size: 12.5px; color: var(--grey-7); line-height: 1.35; }

/* ═══════════════════════════════ Welcome ═══════════════════════════════ */
/* The homepage button that opens the welcome. Pink tint so it reads as the
   one editorial item on a page that is otherwise navigation. */
.welcome-btn {
  display: flex; align-items: center; gap: 13px; width: 100%; text-align: left;
  margin-top: 18px; padding: 15px 16px;
  background: var(--pink-tint); border: 1px solid var(--pink-tint-2);
  border-radius: var(--r-lg); box-shadow: var(--sh-xs);
  transition: transform .14s ease, box-shadow .14s ease;
}
.welcome-btn:active { transform: scale(.985); box-shadow: none; }
.wb-ico {
  width: 38px; height: 38px; border-radius: var(--r-sm); flex: none;
  background: var(--pink-mid); color: #fff;
  display: grid; place-items: center;
}
.wb-ico svg { width: 21px; height: 21px; }
.wb-body { flex: 1; min-width: 0; }
.wb-label { display: block; font-family: var(--display); font-weight: 700; font-size: 15.5px; color: var(--ink); }
.wb-sub { display: block; font-size: 12.5px; color: var(--pink-dark); line-height: 1.35; }
.welcome-btn .chev { color: var(--pink-mid); }

/* The welcome itself, inside the modal. */
.welcome-body p { font-size: 15.5px; color: var(--ink-2); line-height: 1.62; margin: 0 0 14px; }
.welcome-body p:last-child { margin-bottom: 0; }
.welcome-sign {
  margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--grey-2);
}
.ws-from { display: block; font-family: var(--display); font-weight: 700; font-size: 15px; color: var(--ink); }
.ws-org { display: block; font-size: 13px; color: var(--grey-7); }
.avatar {
  width: 40px; height: 40px; border-radius: 50%; flex: none;
  background: linear-gradient(140deg, var(--pink-mid) 0%, var(--pink-ink) 100%);
  color: #fff; display: grid; place-items: center;
  font-family: var(--display); font-weight: 700; font-size: 14.5px; letter-spacing: .02em;
}

/* ═══════════════════════════════ Keynote / sponsor cards ═════════════════ */
.keynote-list, .sponsor-list { display: grid; gap: 11px; }
.keynote-card {
  background: var(--paper); border: 1px solid var(--grey-2); border-radius: var(--r-lg);
  padding: 15px 16px; box-shadow: var(--sh-xs); text-align: left; width: 100%;
  display: flex; gap: 13px; align-items: flex-start;
  transition: transform .14s ease;
}
.keynote-card:active { transform: scale(.985); }
.keynote-card .avatar { background: linear-gradient(140deg, var(--char) 0%, var(--char-3) 100%); }
.keynote-time {
  font-size: 11.5px; font-weight: 700; letter-spacing: .07em; color: var(--pink-dark);
  text-transform: uppercase; margin-bottom: 3px;
}
.keynote-name { font-family: var(--display); font-weight: 700; font-size: 16px; color: var(--ink); margin: 0 0 2px; }
.keynote-role { font-size: 13px; color: var(--grey-7); line-height: 1.4; margin: 0; }

.sponsor-card {
  background: var(--paper); border: 1px solid var(--grey-2); border-radius: var(--r-lg);
  padding: 15px 16px; box-shadow: var(--sh-xs);
}
.sponsor-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.sponsor-name { font-family: var(--display); font-weight: 700; font-size: 16.5px; color: var(--ink); }
.sponsor-card p { font-size: 14px; color: var(--grey-11); margin: 0 0 8px; line-height: 1.55; }

/* Engagement bars on the organiser dashboard. */
.eng-list { display: grid; gap: 12px; }
.eng-row { position: relative; }
.eng-bar { height: 5px; border-radius: var(--r-pill); background: var(--grey-2); margin-bottom: 6px; overflow: hidden; }
.eng-bar i { display: block; height: 100%; background: var(--pink-mid); border-radius: var(--r-pill); }
.eng-title { font-size: 13.5px; color: var(--ink-2); line-height: 1.35; }
.eng-n { font-size: 12px; color: var(--grey-7); margin-top: 2px; }
.org-switch textarea {
  width: 100%; margin-top: 12px; padding: 11px 13px; min-height: 76px;
  border: 1.5px solid var(--grey-3); border-radius: var(--r-md);
  font-size: 15px; line-height: 1.45; resize: vertical; background: var(--paper);
}
.org-switch textarea:focus { outline: none; border-color: var(--pink-mid); box-shadow: 0 0 0 3px var(--pink-tint); }

/* A saved-talk clash. Amber rather than pink: it is a heads-up about the
   delegate's own choices, not a conference status. */
.clash-note {
  background: var(--amber-tint); border: 1px solid #F0DDB4;
  border-left: 4px solid var(--amber);
  border-radius: var(--r-md); padding: 12px 14px; margin-bottom: 16px;
}
.clash-note strong { display: block; font-size: 14px; color: var(--amber); margin-bottom: 3px; }
.clash-note p { font-size: 13.5px; color: var(--ink-2); margin: 0; line-height: 1.5; }

/* ═══════════════════ After-conference homepage cards ═══════════════════ */
.after-cards { display: grid; gap: 12px; margin-top: 18px; }
.after-cards .info-card { margin-bottom: 0; }
.after-card { border-left: 3px solid var(--green-mid); }
.after-card.is-done { border-left-color: var(--grey-3); }
.after-card h2, .qs-card h2 {
  font-family: var(--display); font-size: 17px; font-weight: 700;
  color: var(--ink); margin: 0 0 6px;
}
.after-card .btn { margin-top: 12px; }
.qs-card { margin-top: 12px; }

/* ═══════════════════════════ Install prompt ═══════════════════════════ */
/* Shown only when it can be acted on, and only until it is waved away. */
.install-card {
  display: flex; gap: 13px; align-items: flex-start;
  margin-top: 22px; padding: 16px;
  background: var(--char); color: #fff;
  border-radius: var(--r-lg); box-shadow: var(--sh-brand);
}
.ic-ico {
  width: 38px; height: 38px; border-radius: var(--r-sm); flex: none;
  background: rgba(255,255,255,.12); color: var(--pink);
  display: grid; place-items: center;
}
.ic-ico svg { width: 21px; height: 21px; }
.ic-body { flex: 1; min-width: 0; }
.ic-title { font-family: var(--display); font-weight: 700; font-size: 15.5px; color: #fff; margin: 0 0 3px; }
.ic-sub { font-size: 13px; color: rgba(255,255,255,.75); margin: 0 0 12px; line-height: 1.45; }
.ic-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.ic-actions .btn { flex: 1; min-width: 116px; text-align: center; }
.ic-actions .btn-ghost { background: transparent; color: rgba(255,255,255,.82); border-color: rgba(255,255,255,.28); }

/* ═══════════════════════════ Contact buttons ═══════════════════════════ */
.contact-actions { display: grid; gap: 9px; margin-top: 4px; }
/* a.contact-btn, not .contact-btn. These carry .btn-sm too, which sets
   display:inline-block and width:auto — equal specificity, and it is defined
   further down the file, so it was silently winning and stacking the icon
   above the text. Element+class outranks it wherever either rule sits. */
a.contact-btn {
  display: flex; align-items: center; gap: 12px; width: 100%;
  text-align: left; text-decoration: none; padding: 12px 16px;
  /* The nowrap URL inside .cb-sub sets a min-content floor that no grid or
     flex item will shrink below by default, so at 320px the button refused
     to narrow, overflowed its card and pushed the whole page sideways — the
     ellipsis never got a chance to do its job. min-width has to be released
     at both levels: on the button as a grid item, and on the text column as
     a flex item. Releasing only one leaves the other holding the floor. */
  min-width: 0;
}
a.contact-btn:hover, a.contact-btn:focus-visible { text-decoration: none; }
a.contact-btn > span { min-width: 0; }
.cb-ico { flex: none; display: grid; place-items: center; }
.cb-ico svg { width: 19px; height: 19px; }
.cb-label { display: block; font-size: 14.5px; line-height: 1.25; }
.cb-sub {
  display: block; font-family: var(--sans); font-weight: 400;
  font-size: 12.5px; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--grey-11);
}
/* Set per variant rather than dimmed with opacity, so each is measured
   against the ground it actually sits on. */
.btn:not(.btn-ghost) .cb-sub { color: var(--green-ink); }

/* ═══════════════════════════════ Venue map ═══════════════════════════════ */
.map-card {
  background: var(--paper); border: 1px solid var(--grey-2); border-radius: var(--r-lg);
  box-shadow: var(--sh-xs); overflow: hidden; margin-bottom: 14px;
}
.map-frame {
  position: relative; height: 220px; background: var(--grey-2);
  display: grid; place-items: center;
}
.map-frame iframe {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0; z-index: 1;
  opacity: 0; transition: opacity .3s ease;
}
.map-frame iframe.is-ready { opacity: 1; }
/* Sits underneath the frame and shows through until the map has painted. */
.map-fallback { font-size: 13.5px; color: var(--grey-7); text-align: center; padding: 0 24px; line-height: 1.5; }
.map-actions { display: flex; gap: 9px; padding: 12px 14px; }
.map-actions .btn { flex: 1; text-align: center; }
.w3w {
  font-family: var(--display); font-weight: 700; font-size: 14px;
  color: var(--pink-dark); margin: 0;
}
.note-contact { margin-top: 4px; }

/* Two columns where there is room for two, one where there is not. Stating a
   minimum column width rather than a breakpoint lets the browser decide, so
   "Lezley-Anne Hanna" never ends up hyphenated down a 90px column on a small
   phone. */
/* A grid of faces rather than twelve rows of list. auto-fit with a minimum
   rather than a fixed column count, so it finds its own answer: three across
   on a phone, more on a tablet, and two at 320px where three would leave 80px
   for "Professor Lezley-Anne Hanna". */
.cttee {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(94px, 1fr));
  gap: 18px 10px;
}
.cttee li {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 7px;
}
/* 64, not 68. Sharon's original is a 135px thumbnail, and 68 would demand 136
   for a 2x screen — failing the sharpness check by a single pixel, which is
   noise rather than a finding. 64 is indistinguishable at this size and keeps
   the rule strict instead of bending it. A larger original would let this grow. */
.cttee-face {
  width: 64px; height: 64px; border-radius: 50%; flex: none; object-fit: cover;
  background: linear-gradient(140deg, var(--pink-mid) 0%, var(--pink-ink) 100%);
  color: #fff; display: grid; place-items: center;
  font-family: var(--display); font-weight: 700; font-size: 20px; letter-spacing: .02em;
}
.cttee-name { font-size: 12.5px; line-height: 1.35; color: var(--ink-2); }
/* The Chair caption sits on its own line under the name, where it cannot get
   caught mid-wrap the way "(Chair)" did when it was part of the name. */
.cttee-role {
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--pink-dark); margin-top: -3px;
}
/* Same reason as a.contact-btn above — .btn-sm would otherwise keep this
   inline-block, and `margin: auto` cannot centre an inline-block. */
/* Same width as the primary button above it. It used to carry .btn-sm and a
   320px cap, so the two stacked buttons were visibly different widths. */
a.intersim-link {
  display: block; width: 100%; margin: 12px 0 0;
  text-align: center; text-decoration: none;
}
a.intersim-link:hover, a.intersim-link:focus-visible { text-decoration: none; }
.tour-closed p { margin: 0 0 8px; }
.tour-closed p:last-child { margin-bottom: 0; }

/* ═══════════════════════════════ Provisional ═══════════════════════════════ */
.provisional {
  background: repeating-linear-gradient(135deg, #FDF3E2 0 12px, #FBEBD0 12px 24px);
  border: 2px solid var(--amber); color: var(--amber);
  border-radius: var(--r-md); padding: 12px 14px; margin-bottom: 16px;
  font-family: var(--display); font-weight: 700; font-size: 19px;
  letter-spacing: .16em; text-align: center; text-transform: uppercase;
}
/* Used for the shorter inline notices (e.g. changing an InterSim group). */
.provisional[style] {
  font-family: var(--sans); font-weight: 400; font-size: 13.5px;
  letter-spacing: 0; text-transform: none; text-align: left; line-height: 1.5;
  background: var(--amber-tint); border-width: 1px;
}

/* ═══════════════════════════════ Segmented ═══════════════════════════════ */
.seg {
  display: flex; gap: 4px; background: var(--grey-2); padding: 4px;
  border-radius: var(--r-pill); margin-bottom: 18px;
}
.seg-btn {
  flex: 1; padding: 8px 10px; border-radius: var(--r-pill);
  font-size: 14px; font-weight: 600; color: var(--grey-11);
  transition: background .16s ease, color .16s ease, box-shadow .16s ease;
}
.seg-btn.is-on { background: var(--paper); color: var(--ink); box-shadow: var(--sh-xs); }

/* ═══════════════════════════════ Timeline ═══════════════════════════════ */
.timeline { position: relative; padding-left: 62px; }
.timeline::before {
  content: ""; position: absolute; left: 54px; top: 12px; bottom: 12px;
  width: 2px; background: var(--grey-3);
}
/* Nothing timed to show: the rail is a time axis, so it goes too. */
.timeline.is-bare { padding-left: 0; }
.timeline.is-bare::before { display: none; }
.tl-item { position: relative; margin-bottom: 14px; }
.tl-time {
  position: absolute; left: -62px; top: 15px; width: 46px; text-align: right;
  font-family: var(--display); font-weight: 700; font-size: 13px; color: var(--ink);
  line-height: 1.25;
}
.tl-time small { display: block; font-weight: 500; font-size: 11px; color: var(--grey-7); }
.tl-dot {
  position: absolute; left: -12px; top: 19px;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--paper); border: 2.5px solid var(--grey-4); z-index: 1;
}
.tl-item[data-type="keynote"] .tl-dot,
.tl-item[data-type="panel"] .tl-dot { border-color: var(--char); background: var(--char); }
.tl-item[data-type="session"] .tl-dot { border-color: var(--pink-mid); background: var(--pink-mid); }
.tl-item.is-now .tl-dot { border-color: var(--green-mid); background: var(--green-mid); box-shadow: 0 0 0 5px var(--green-tint-2); }
.tl-item.is-past { opacity: .55; }

.tl-card {
  background: var(--paper); border: 1px solid var(--grey-2); border-radius: var(--r-lg);
  padding: 14px 15px; box-shadow: var(--sh-xs); width: 100%; text-align: left;
}
.tl-item.is-now .tl-card { border-color: var(--green-mid); box-shadow: 0 0 0 3px var(--green-tint), var(--sh-sm); }
.tl-item[data-type="break"] .tl-card { background: var(--grey-1); box-shadow: none; }
.tl-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.tl-title { font-family: var(--display); font-weight: 700; font-size: 16.5px; color: var(--ink); margin: 0; line-height: 1.28; }
.tl-sub { font-size: 13.5px; color: var(--pink-dark); font-weight: 600; margin: 3px 0 0; line-height: 1.4; }
.tl-meta { font-size: 12.5px; color: var(--grey-7); margin: 6px 0 0; display: flex; flex-wrap: wrap; gap: 5px 10px; }
.tl-meta span { display: inline-flex; align-items: center; gap: 4px; }
.tl-detail { font-size: 13.5px; color: var(--grey-11); margin: 9px 0 0; line-height: 1.5; }
.tl-people { margin: 8px 0 0; font-size: 13.5px; color: var(--ink-2); }
.tl-people .role { color: var(--grey-7); font-size: 12.5px; }
/* A speaker with their face beside their name, on the card itself. The circle
   is the same one used in the panel rows, and the initials stand in until a
   photo arrives, so the card is the same height either way. */
/* Two chairs sit side by side when the line has room for them and stack when
   it has not, rather than being pinned to one arrangement or the other. */
.tl-people { display: flex; flex-wrap: wrap; gap: 8px 22px; }
.tl-people-label {
  flex: 1 0 100%; margin: 0 0 -2px;
  font-size: 11px; font-weight: 700; letter-spacing: .11em;
  text-transform: uppercase; color: var(--grey-7);
}
.tl-person { display: flex; align-items: center; gap: 11px; }
.tl-person .avatar { width: 42px; height: 42px; font-size: 14px; }
.tl-person strong { font-weight: 700; }

.tl-toggle {
  margin-top: 11px; padding-top: 11px; border-top: 1px solid var(--grey-2);
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  font-size: 13.5px; font-weight: 700; color: var(--pink-dark);
}
.tl-toggle .chev { transition: transform .2s ease; font-size: 17px; line-height: 1; }
.tl-toggle[aria-expanded="true"] .chev { transform: rotate(90deg); }
.tl-items { display: grid; gap: 7px; margin-top: 11px; }
.tl-items[hidden] { display: none; }

.slot {
  display: flex; gap: 11px; align-items: flex-start; width: 100%; text-align: left;
  padding: 10px 11px; border-radius: var(--r-md); background: var(--grey-1);
  border: 1px solid transparent;
  transition: background .14s ease, border-color .14s ease;
}
.slot:active { background: var(--pink-tint); border-color: var(--pink-tint-2); }
.slot.is-now { background: var(--green-tint); border-color: var(--green-mid); }
.slot-time {
  font-family: var(--display); font-weight: 700; font-size: 12.5px; color: var(--pink-dark);
  flex: none; width: 40px; padding-top: 1px;
}
.slot-body { min-width: 0; flex: 1; }
.slot-title { display: block; font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.35; margin: 0 0 3px; }
.slot-who { display: block; font-size: 12.5px; color: var(--grey-7); line-height: 1.35; margin: 0; }
.slot-num {
  flex: none; font-family: var(--display); font-weight: 700; font-size: 11px;
  color: var(--grey-7); background: var(--grey-2); border-radius: var(--r-sm);
  padding: 2px 6px; align-self: flex-start;
}

/* Saved posters. They sit outside the timetable — viewable at either break —
   so they sit outside the timeline rail too, rather than being pinned to a
   time they do not have. Board number leads, because that is what you are
   looking for once you are in the room. */
.tl-posters { margin: 4px 0 14px; padding: 15px 16px 16px; background: var(--grey-1); border-radius: var(--r-lg); }
.tl-posters-title { font-family: var(--display); font-size: 17px; font-weight: 700; color: var(--ink); margin: 0; }
.tl-posters-sub { font-size: 13px; color: var(--grey-7); margin: 3px 0 12px; }
.tl-posters-list { display: grid; gap: 7px; }
.poster-row {
  display: flex; gap: 11px; align-items: flex-start; width: 100%; text-align: left;
  padding: 10px 11px; border-radius: var(--r-md); background: #fff;
  border: 1px solid transparent;
  transition: background .14s ease, border-color .14s ease;
}
.poster-row:active { background: var(--pink-tint); border-color: var(--pink-tint-2); }
.poster-board {
  flex: none; font-family: var(--display); font-weight: 700; font-size: 12px;
  background: var(--green-mid); color: #fff; border-radius: var(--r-sm);
  min-width: 26px; padding: 3px 7px; text-align: center;
}
.poster-body { min-width: 0; flex: 1; }
.poster-title { display: block; font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.35; margin: 0 0 3px; }
.poster-who { display: block; font-size: 12.5px; color: var(--grey-7); line-height: 1.35; margin: 0; }

/* ═══════════════════════════════ Search & chips ═══════════════════════════ */
.search-wrap { position: relative; margin-bottom: 12px; }
.search-ico {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px; color: var(--grey-5); pointer-events: none;
}
#abs-search {
  width: 100%; padding: 13px 40px 13px 40px;
  background: var(--paper); border: 1px solid var(--grey-3); border-radius: var(--r-pill);
  font-size: 15.5px; color: var(--ink); box-shadow: var(--sh-xs);
  -webkit-appearance: none; appearance: none;
}
#abs-search::placeholder { color: var(--grey-5); }
#abs-search:focus { outline: none; border-color: var(--pink-mid); box-shadow: 0 0 0 3px var(--pink-tint); }
.search-clear {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; border-radius: 50%; font-size: 21px; line-height: 1;
  color: var(--grey-7); display: grid; place-items: center;
}

.chips { display: flex; gap: 7px; overflow-x: auto; padding: 2px 0 10px; scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }
.chips-wrap { flex-wrap: wrap; overflow: visible; }
.chip {
  flex: none; padding: 7px 13px; border-radius: var(--r-pill);
  background: var(--paper); border: 1px solid var(--grey-3);
  font-size: 13.5px; font-weight: 600; color: var(--grey-11); white-space: nowrap;
  transition: background .14s ease, color .14s ease, border-color .14s ease;
}
.chip.is-on { background: var(--ink); border-color: var(--ink); color: #fff; }
.chip .n { font-weight: 500; margin-left: 4px; color: var(--grey-7); }
.chip.is-on .n { color: rgba(255,255,255,.85); }

/* ═══════════════════════════════ Abstract cards ═══════════════════════════ */
.card-list { display: grid; gap: 10px; }
.acard {
  background: var(--paper); border: 1px solid var(--grey-2); border-radius: var(--r-lg);
  padding: 14px 15px; box-shadow: var(--sh-xs); text-align: left; width: 100%;
  display: block; position: relative;
  transition: transform .14s ease, box-shadow .14s ease;
}
.acard:active { transform: scale(.985); box-shadow: var(--sh-sm); }
.acard-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; flex-wrap: wrap; }
.fmt {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  padding: 3px 8px; border-radius: var(--r-pill);
}
.fmt-poster { background: var(--green-tint); color: var(--green-deep); }
.fmt-snapshot { background: var(--amber-tint); color: var(--amber); }
.fmt-short { background: var(--pink-tint); color: var(--pink-dark); }
/* Presenter photo beside the title. The initials stand-in is exactly the same
   size as a photo, so cards do not reflow as photos start arriving. */
.acard-main { display: flex; gap: 12px; align-items: flex-start; }
.acard-text { flex: 1; min-width: 0; }
.pres-photo {
  flex: none; border-radius: 50%; object-fit: cover;
  background: var(--pink-tint); color: var(--pink-dark);
  display: grid; place-items: center;
  font-family: var(--display); font-weight: 700; letter-spacing: .01em;
  border: 1px solid var(--pink-tint-2);
}
.pres-sm { width: 46px; height: 46px; font-size: 15px; }
.pres-lg { width: 72px; height: 72px; font-size: 23px; }
/* The gap below the block lives here rather than on .m-affil, because the
   affiliations now sit inside the text column. If the avatar happened to be
   the taller of the two, a margin on the affiliations would be swallowed and
   the session panel would jump up against the text. */
.m-presenter { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 14px; }
.m-presenter > div { flex: 1; min-width: 0; }

/* Small inline glyphs that sit on the text baseline. */
.mini-ico { width: 14px; height: 14px; vertical-align: -2px; margin-right: 5px; flex: none; display: inline-block; }
.done-ico { width: 46px; height: 46px; color: var(--green-mid); margin: 0 auto 10px; display: block; stroke-width: 1.6; }

.acard-title { font-family: var(--display); font-weight: 700; font-size: 15.5px; color: var(--ink); line-height: 1.32; margin: 0 0 6px; padding-right: 30px; }
.acard-authors { font-size: 13px; color: var(--grey-11); margin: 0 0 7px; line-height: 1.45; }
.acard-insts { display: flex; flex-wrap: wrap; gap: 5px; }
.inst {
  font-size: 11.5px; font-weight: 600; color: var(--grey-7);
  background: var(--grey-1); border: 1px solid var(--grey-2);
  border-radius: var(--r-sm); padding: 2px 7px;
}
.acard-slot {
  margin-top: 9px; padding-top: 9px; border-top: 1px dashed var(--grey-3);
  font-size: 12.5px; color: var(--pink-dark); font-weight: 600;
  display: flex; align-items: center; gap: 6px;
}
.star-btn {
  position: absolute; top: 11px; right: 10px;
  width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center; color: var(--grey-4);
  transition: color .15s ease, transform .15s ease;
}
.star-btn svg { width: 19px; height: 19px; }
.star-btn.is-on { color: var(--pink-mid); }
.star-btn.is-on svg { fill: var(--pink-mid); }
.star-btn:active { transform: scale(.85); }

.empty { text-align: center; color: var(--grey-7); padding: 34px 20px; font-size: 15px; }

/* ═══════════════════════════════ Poster boards ═══════════════════════════ */
.board-note {
  background: var(--green-tint); border-radius: var(--r-md);
  padding: 11px 14px; font-size: 13.5px; color: var(--green-deep); margin-bottom: 14px; line-height: 1.5;
}
.board-badge {
  font-family: var(--display); font-weight: 700; font-size: 12px;
  background: var(--green-mid); color: #fff; border-radius: var(--r-sm); padding: 3px 8px; flex: none;
}

/* ═══════════════════════════════ More list ═══════════════════════════════ */
.more-list {
  display: grid; gap: 1px; background: var(--grey-2);
  border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--grey-2);
}
.more-item {
  display: flex; align-items: center; gap: 13px; width: 100%; text-align: left;
  padding: 14px 15px; background: var(--paper);
  transition: background .14s ease;
}
.more-item:active { background: var(--grey-1); }
/* Same stroked icon set as the homepage tiles, in the same tinted square —
   emoji rendered differently on every phone and read as decoration. */
.more-ico {
  width: 34px; height: 34px; border-radius: var(--r-sm); flex: none;
  background: var(--pink-tint); color: var(--pink-dark);
  display: grid; place-items: center;
}
.more-ico svg { width: 19px; height: 19px; }
.more-body { flex: 1; min-width: 0; }
.more-label { display: block; font-family: var(--display); font-weight: 700; font-size: 15.5px; color: var(--ink); }
.more-sub { display: block; font-size: 12.5px; color: var(--grey-7); line-height: 1.35; }
.chev { color: var(--grey-4); font-size: 22px; line-height: 1; flex: none; }
/* Shared footer. It sits outside #main so it closes every page, not just
   the homepage, and it is where the School of Pharmacy lockup lives. */
.foot {
  max-width: var(--max-w); margin: 8px auto 0;
  padding: 26px var(--gutter) 10px;
  border-top: 1px solid var(--grey-3);
  text-align: center; font-size: 13px; color: var(--grey-7); line-height: 1.6;
}
.foot p { margin: 0 0 8px; }
.foot-logo { display: block; margin: 0 auto 18px; width: fit-content; }
.foot-logo img { display: block; width: auto; height: auto; max-width: 232px; max-height: 58px; }
.foot-title {
  font-family: var(--display); font-weight: 700; font-size: 15px;
  color: var(--ink); letter-spacing: .04em;
}
.foot a { font-weight: 600; }
.foot-actions {
  display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;
  margin: 18px 0 6px;
}
.foot-contact, .foot-install { min-width: 170px; text-align: center; text-decoration: none; }
.foot-contact:hover, .foot-contact:focus-visible { text-decoration: none; }

.link-btn { display: block; width: 100%; padding: 11px; font-size: 14.5px; font-weight: 600; color: var(--pink-dark); }
.link-btn.subtle { color: var(--grey-7); font-size: 13px; font-weight: 500; }
.version { font-size: 11.5px; color: var(--grey-7); margin-top: 6px; }

/* Two links on one line, so `.link-btn`'s full-width block has to be undone —
   equal specificity and later in the file, which is the whole reason this
   sits here and not up beside the other footer rules. */
.foot-legal {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin-top: 6px; color: var(--grey-5);
}
/* Underlined because they are links in all but element name, and a row of
   grey text is not obviously tappable without it. */
.foot-legal .link-btn {
  display: inline; width: auto; padding: 8px 2px;
  font-size: 13px; color: var(--grey-7); text-decoration: underline;
}

/* ═══════════════════════════════ Sub-page shell ═══════════════════════════ */
.back-btn {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 14.5px; font-weight: 600; color: var(--pink-dark);
  padding: 16px 0 4px;
}
.panel-card, .info-card {
  background: var(--paper); border: 1px solid var(--grey-2); border-radius: var(--r-lg);
  padding: 16px 17px; box-shadow: var(--sh-xs); margin-bottom: 12px;
}
.info-card h2 { font-size: 16px; margin: 0 0 6px; }
.info-card p:last-child { margin-bottom: 0; }
.info-card p { font-size: 14.5px; color: var(--grey-11); line-height: 1.6; }

/* ═══════════════════════ Accessibility & privacy ═══════════════════════ */
/* Long prose, which the rest of the app deliberately has none of. Slightly
   looser than the cards elsewhere because these are read, not scanned. */
.policy h2 {
  font-family: var(--display); font-size: 15.5px; font-weight: 700;
  color: var(--ink); margin: 0 0 8px; line-height: 1.35;
}
.policy p { margin: 0 0 11px; }
.policy-note {
  background: var(--green-tint); border-left: 3px solid var(--green-mid);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  padding: 11px 13px; margin: 0 0 4px;
  font-size: 14.5px; color: var(--green-ink); line-height: 1.55;
}
.policy-list { margin: 0 0 11px; padding-left: 19px; }
.policy-list li { font-size: 14.5px; color: var(--grey-11); line-height: 1.6; margin-bottom: 7px; }
.policy-list li:last-child { margin-bottom: 0; }
.policy .contact-actions { margin-top: 13px; }
.policy-updated { text-align: center; font-size: 12.5px; color: var(--grey-7); margin: 14px 0 4px; }

/* The engagement opt-out. The native checkbox stays in the accessibility tree
   and keeps its own keyboard behaviour; only its rendering is replaced. */
.opt { margin: 4px 0 2px; }
.opt-input {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.opt-label {
  display: flex; align-items: flex-start; gap: 12px; cursor: pointer;
  padding: 12px 13px; border: 1.5px solid var(--grey-3); border-radius: var(--r-md);
  background: var(--paper); transition: border-color .14s ease, background .14s ease;
}
.opt-box {
  flex: none; width: 22px; height: 22px; margin-top: 1px;
  border: 1.5px solid var(--grey-4); border-radius: 6px; background: var(--paper);
  display: grid; place-items: center; transition: all .14s ease;
}
.opt-input:checked + .opt-label { border-color: var(--green-mid); background: var(--green-tint); }
.opt-input:checked + .opt-label .opt-box { border-color: var(--green-deep); background: var(--green-deep); }
.opt-input:checked + .opt-label .opt-box::after {
  content: ""; width: 11px; height: 6px; margin-top: -3px;
  border-left: 2.5px solid #fff; border-bottom: 2.5px solid #fff; transform: rotate(-45deg);
}
/* The ring belongs on the visible box, not on the clipped input nobody sees. */
.opt-input:focus-visible + .opt-label { outline: 3px solid var(--pink-mid); outline-offset: 2px; }
.opt-name { display: block; font-size: 14.5px; font-weight: 600; color: var(--ink); line-height: 1.4; }
.opt-sub { display: block; font-size: 12.5px; color: var(--grey-7); margin-top: 2px; line-height: 1.45; }
.opt-state { font-size: 12.5px; color: var(--grey-7); margin: 8px 2px 0; line-height: 1.5; }

.kv { display: grid; gap: 10px; }
.kv-row { display: flex; gap: 12px; align-items: baseline; font-size: 14.5px; }
.kv-k { flex: none; width: 76px; font-weight: 700; color: var(--grey-7); font-size: 12.5px; text-transform: uppercase; letter-spacing: .05em; }
.kv-v { flex: 1; color: var(--ink-2); }

.runsheet { display: grid; gap: 8px; }
.run-row {
  display: flex; gap: 12px; padding: 11px 12px; background: var(--grey-1);
  border-radius: var(--r-md); font-size: 14px;
}
.run-time { flex: none; width: 68px; font-family: var(--display); font-weight: 700; font-size: 12.5px; color: var(--pink-dark); }
.run-item { flex: 1; color: var(--ink-2); line-height: 1.45; }
.run-lead { font-size: 12.5px; color: var(--grey-7); margin-top: 2px; }

.pill-list { display: grid; gap: 9px; }
/* Top-aligned, not centred. Centring is invisible on a two-line row and wrong
   the moment a panellist has a bio — the avatar drifts to the middle of the
   paragraph and stops reading as belonging to the name above it. */
.pill-row {
  display: flex; align-items: flex-start; gap: 11px; padding: 12px 14px;
  background: var(--paper); border: 1px solid var(--grey-2); border-radius: var(--r-md);
}
.pill-row .avatar { width: 34px; height: 34px; font-size: 13px; }
/* An <img> with .avatar is a photo standing in for the initials circle. It
   inherits the size and the radius; it only needs telling not to stretch. */
img.avatar { object-fit: cover; background: var(--pink-tint); }
/* Bios arrive one at a time, so a row with one has to sit happily beside five
   without. Indented to the name above it rather than the avatar, so the block
   reads as belonging to that person. */
.pill-bio { margin-top: 7px; font-size: 13.5px; line-height: 1.55; color: var(--grey-8); }
.pill-bio p { margin: 0; }
.pill-bio p + p { margin-top: 7px; }
.pill-name { font-weight: 700; font-size: 14.5px; color: var(--ink); font-family: var(--display); }
.pill-sub { font-size: 12.5px; color: var(--grey-7); }

.inst-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; background: var(--paper);
  border: 1px solid var(--grey-2); border-radius: var(--r-md);
}
.inst-name { font-size: 14.5px; color: var(--ink-2); font-weight: 600; line-height: 1.35; }
.inst-bar { height: 5px; background: var(--grey-2); border-radius: var(--r-pill); margin-top: 6px; overflow: hidden; }
.inst-bar i { display: block; height: 100%; background: var(--pink-mid); border-radius: var(--r-pill); }
.inst-n {
  flex: none; font-family: var(--display); font-weight: 700; font-size: 15px;
  color: var(--pink-dark); min-width: 26px; text-align: right;
}

/* ═══════════════════════════════ Forms ═══════════════════════════════ */
.field { margin-bottom: 18px; }
.field label, .field .label {
  display: block; font-size: 14.5px; font-weight: 600; color: var(--ink); margin-bottom: 8px; line-height: 1.4;
}
.req { color: var(--pink-mid); }
.field input[type="text"], .field input[type="email"], .field textarea, .field select {
  width: 100%; padding: 12px 13px; background: var(--paper);
  border: 1px solid var(--grey-3); border-radius: var(--r-md); font-size: 15.5px; color: var(--ink);
  -webkit-appearance: none; appearance: none;
}
.field textarea { min-height: 92px; resize: vertical; line-height: 1.5; }
.field select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' fill='none' stroke='%236F7378' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; background-size: 12px; padding-right: 38px; }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none; border-color: var(--pink-mid); box-shadow: 0 0 0 3px var(--pink-tint);
}
.hint { font-size: 12.5px; color: var(--grey-7); margin: 6px 0 0; line-height: 1.45; }
/* Sits above the room cards, so it needs the body colour rather than the
   quieter hint grey — it is the sentence that stops somebody looking for the
   wrong building. */
.rooms-note { font-size: 14.5px; color: var(--ink-2); margin: -4px 0 14px; line-height: 1.55; }

.scale { display: flex; gap: 7px; }
.scale button {
  flex: 1; aspect-ratio: 1; max-height: 54px; border-radius: var(--r-md);
  background: var(--paper); border: 1.5px solid var(--grey-3);
  font-family: var(--display); font-weight: 700; font-size: 17px; color: var(--grey-7);
  transition: all .14s ease;
}
.scale button.is-on { background: var(--pink-mid); border-color: var(--pink-mid); color: #fff; box-shadow: var(--sh-brand); }
.scale-ends { display: flex; justify-content: space-between; font-size: 11.5px; color: var(--grey-7); margin-top: 6px; }

.choice-group { display: grid; gap: 7px; }
.choice {
  display: flex; align-items: center; gap: 11px; padding: 12px 14px;
  background: var(--paper); border: 1.5px solid var(--grey-3); border-radius: var(--r-md);
  font-size: 14.5px; text-align: left; width: 100%; color: var(--ink-2);
  transition: all .14s ease;
}
.choice.is-on { border-color: var(--pink-mid); background: var(--pink-tint); color: var(--pink-ink); font-weight: 600; }
.choice .tick {
  width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid var(--grey-4); flex: none;
  display: grid; place-items: center;
}
.choice.is-on .tick { border-color: var(--pink-mid); background: var(--pink-mid); }
.choice.is-on .tick::after { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #fff; }

/* Twelve months stacked would be most of a screen. Two columns on a phone,
   three from 420px — the tick stays, the target stays well over 24px. */
.choice-compact { grid-template-columns: 1fr 1fr; }
.choice-compact .choice { padding: 11px 12px; gap: 9px; font-size: 14px; }
@media (min-width: 420px) { .choice-compact { grid-template-columns: repeat(3, 1fr); } }

/* Primary actions repeat the splash's "Enter the conference" button —
   conference green with near-black type, which is both on-identity and
   the highest-contrast pairing in the palette (6.2:1). */
.btn {
  display: block; width: 100%; padding: 15px; border-radius: var(--r-pill);
  background: var(--green); color: var(--green-ink);
  font-family: var(--display); font-weight: 700; font-size: 16.5px;
  box-shadow: 0 6px 20px rgba(72,177,135,.32);
  transition: transform .14s ease, opacity .14s ease;
}
.btn:active { transform: scale(.98); }
.btn:disabled { opacity: .5; box-shadow: none; cursor: default; transform: none; }
.btn-ghost {
  background: var(--paper); color: var(--pink-dark); border: 1.5px solid var(--grey-3); box-shadow: none;
}
.btn-sm { padding: 10px 18px; font-size: 14.5px; width: auto; display: inline-block; }

.done-card {
  background: var(--green-tint); border: 1px solid var(--green-tint-2); border-radius: var(--r-lg);
  padding: 20px; text-align: center;
}
.done-card .big { font-size: 34px; line-height: 1; margin-bottom: 10px; }
.done-card h2 { color: var(--green-deep); font-size: 18px; margin: 0 0 6px; }
.done-card p { font-size: 14.5px; color: var(--green-deep); margin: 0; line-height: 1.55; }

/* ═══════════════════════════════ Slot booking ═══════════════════════════════ */
.slot-option {
  display: flex; align-items: center; gap: 13px; width: 100%; text-align: left;
  padding: 15px 16px; background: var(--paper);
  border: 1.5px solid var(--grey-3); border-radius: var(--r-lg); margin-bottom: 9px;
  transition: all .14s ease;
}
.slot-option.is-on { border-color: var(--pink-mid); background: var(--pink-tint); }
.slot-option.is-full { opacity: .5; cursor: not-allowed; }
.slot-option .tick { width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid var(--grey-4); flex: none; display: grid; place-items: center; }
.slot-option.is-on .tick { border-color: var(--pink-mid); background: var(--pink-mid); }
.slot-option.is-on .tick::after { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #fff; }
.slot-option .so-body { flex: 1; min-width: 0; }
.so-label { display: block; font-family: var(--display); font-weight: 700; font-size: 16px; color: var(--ink); }
.so-time { display: block; font-size: 13.5px; color: var(--grey-11); }
.so-left { display: block; font-size: 12.5px; font-weight: 600; margin-top: 3px; }
.so-left.ok { color: var(--green-deep); }
.so-left.low { color: var(--amber); }
.so-left.full { color: var(--pink-dark); }

/* Wi-Fi joining steps — read standing up, in a foyer, one-handed. */
.wifi-net { font-size: 16px; margin: 0 0 8px; color: var(--ink); }
.wifi-steps { margin: 0; padding-left: 20px; }
.wifi-steps li { font-size: 14.5px; color: var(--grey-11); line-height: 1.6; margin-bottom: 7px; }
.wifi-steps li:last-child { margin-bottom: 0; }
.wifi-steps strong { color: var(--ink); }

/* ═══════════════════════════════ Modal ═══════════════════════════════ */
.modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: flex-end; justify-content: center; }
.modal-scrim { position: absolute; inset: 0; background: rgba(22,24,27,.5); backdrop-filter: blur(3px); animation: fade-in .22s ease both; }
.modal-sheet {
  position: relative; width: 100%; max-width: var(--max-w);
  max-height: 92vh; background: var(--paper);
  border-radius: 22px 22px 0 0; box-shadow: var(--sh-lg);
  display: flex; flex-direction: column;
  animation: sheet-up .3s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes sheet-up { from { transform: translateY(100%) } to { transform: none } }
.modal-grab { width: 38px; height: 4px; border-radius: 2px; background: var(--grey-3); margin: 9px auto 0; flex: none; }
.modal-close {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  width: 34px; height: 34px; border-radius: 50%; background: var(--grey-1);
  color: var(--grey-11); font-size: 24px; line-height: 1; display: grid; place-items: center;
}
.modal-body {
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 16px var(--gutter) calc(30px + var(--safe-b));
}

.m-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; padding-right: 34px; }
.m-title { font-size: 21px; line-height: 1.24; margin: 0 0 10px; }
.modal-kicker {
  font-size: 11px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--pink-dark); margin: 0 0 8px;
  padding-right: 46px;   /* clear of the close button */
}
.modal-title { font-size: 23px; line-height: 1.2; margin: 0 0 16px; padding-right: 46px; }
.m-authors { font-size: 14.5px; color: var(--ink-2); margin: 0 0 5px; line-height: 1.5; }
/* Browsers give sup a raised baseline via vertical-align: super, which pushes
   the line box taller and makes a wrapped author list ragged. A fixed lift and
   zero line-height keeps every row the same height. */
.m-authors sup, .acard-authors sup, .m-affil sup {
  font-size: .72em; line-height: 0; vertical-align: baseline;
  position: relative; top: -.42em; font-weight: inherit;
}
.m-affil sup { top: -.3em; }

.m-affil { font-size: 13px; color: var(--grey-7); margin: 0; line-height: 1.5; }
.m-affil span { display: block; }
.m-affil span + span { margin-top: 2px; }
.m-slot {
  background: var(--pink-tint); border-radius: var(--r-md); padding: 12px 14px;
  font-size: 14px; color: var(--pink-ink); margin-bottom: 16px; line-height: 1.5;
}
.m-slot strong { display: block; font-family: var(--display); font-size: 15px; margin-bottom: 2px; }
.m-sec { margin-bottom: 16px; }
.m-sec h4 {
  font-size: 11.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--pink-dark); margin: 0 0 5px;
}
.m-sec p { font-size: 15px; color: var(--ink-2); line-height: 1.65; margin: 0; }
/* A biography can run to several paragraphs. Without a gap between them the
   separate <p> elements butt together and read as one block of text — the
   break is there in the markup but invisible on the page. Space every
   paragraph after the first, so a one-paragraph section is unchanged. */
.m-sec p + p { margin-top: 11px; }
.m-refs p { font-size: 12.5px; color: var(--grey-7); line-height: 1.55; }
.m-actions { display: flex; gap: 9px; margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--grey-2); }
.m-actions .btn { flex: 1; }

/* ═══════════════════════════════ Tab bar ═══════════════════════════════ */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 95;
  height: calc(var(--tabbar-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  background: rgba(255,255,255,.94);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-top: 1px solid var(--grey-2);
  display: flex; align-items: stretch;
}
.tabbar > * { max-width: var(--max-w); }
.tab {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  color: var(--grey-7); font-size: 10.5px; font-weight: 600; letter-spacing: .01em;
  transition: color .15s ease;
  position: relative;
}
.tab svg { width: 22px; height: 22px; }
.tab.is-on { color: var(--pink-dark); }
.tab.is-on::before {
  content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 26px; height: 2.5px; background: var(--pink-mid); border-radius: 0 0 3px 3px;
}

/* ═══════════════════════════════ Toast ═══════════════════════════════ */
.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--tabbar-h) + var(--safe-b) + 16px); z-index: 350;
  background: var(--ink); color: #fff; padding: 12px 20px;
  border-radius: var(--r-pill); font-size: 14.5px; font-weight: 600;
  box-shadow: var(--sh-lg); max-width: calc(100vw - 40px); text-align: center;
  animation: toast-in .26s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 14px) } to { opacity: 1; transform: translate(-50%, 0) } }
.toast.is-err { background: var(--pink-ink); }

/* ═══════════════════════════════ Organiser ═══════════════════════════════ */
.org-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-bottom: 18px; }
.org-stat { background: var(--paper); border: 1px solid var(--grey-2); border-radius: var(--r-md); padding: 14px; }
.org-stat .n { font-family: var(--display); font-weight: 700; font-size: 27px; color: var(--pink-dark); line-height: 1.1; }
.org-stat .l { font-size: 12.5px; color: var(--grey-7); }
.org-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.org-table th, .org-table td { text-align: left; padding: 9px 8px; border-bottom: 1px solid var(--grey-2); vertical-align: top; }
.org-table th { font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--grey-7); }
.org-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ═══════════════════════════════ Responsive ═══════════════════════════════ */
@media (min-width: 560px) {
  :root { --gutter: 24px; }
  .quick { flex-basis: calc(33.333% - 7px); }
  .modal { align-items: center; padding: 24px; }
  .modal-sheet { border-radius: var(--r-xl); max-height: 86vh; }
  .modal-grab { display: none; }
}
@media (min-width: 900px) {
  .tabbar { justify-content: center; }
  .tab { flex: 0 0 128px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}

@media print {
  .topbar, .tabbar, .splash, .quick-grid, .star-btn, .seg { display: none !important; }
  body { padding: 0; background: #fff; }
  .view[hidden] { display: none; }
  .tl-items { display: grid !important; }
}


/* ═══════════════════════════ Added in the July restructure ═══════════════ */

/* Format sub-buttons on Abstracts — four across, so tighter than the default */
.seg-formats .seg-btn { font-size: 13px; padding: 8px 4px; }
/* Opacity on text is a contrast failure waiting to happen — it lightens the
   ink against whatever is behind without anyone noticing. Colour instead. */
.seg-formats .seg-btn .n {
  display: block; font-size: 11px; font-weight: 500; margin-top: 1px; color: var(--grey-7);
}
.seg-formats .seg-btn.is-on .n { color: var(--grey-11); }

/* Happening Now — the whole session block is a target */
.now-session {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 2px 0;
}
.now-session-body { flex: 1; min-width: 0; }
.now-session h2 { margin: 0 0 2px; }
.now-session .now-meta { display: block; }
.now-session .chev { color: var(--grey-4); }

/* Sponsor billing on the homepage — logos, tapping through to the write-ups.
   Each logo is boxed to the same height so wildly different aspect ratios
   (a wordmark next to a stacked lockup) still read as one even row. */
.sponsor-panel {
  display: block; width: 100%; text-align: center;
  margin-top: 26px; padding: 18px 16px 16px;
  background: var(--paper); border: 1px solid var(--grey-2); border-radius: var(--r-lg);
  box-shadow: var(--sh-xs);
  transition: transform .14s ease;
}
.sponsor-panel:active { transform: scale(.99); }
.sp-label {
  display: block; font-size: 11px; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: var(--grey-7); margin-bottom: 14px;
}
/* A grid rather than a flex row, so the logos share the width evenly and stay
   on one line instead of orphaning the last one. Two abreast at every width:
   with four sponsors, one row of four splits 720px into 158px cells, and a
   logo capped at 38px tall in a cell that wide reads as small no matter how
   much room is going spare. Two columns give each logo half the panel, and
   above 560px the cap comes up with it so they actually use the space —
   the raster marks grow to 56px, and the Locate a Locum wordmark, ten times
   as wide as it is tall, fills the column instead of shrinking to a line of
   text. Revisit if the number of sponsors changes. */
/* Columns sized to their logos, not two equal halves. With 1fr columns the
   grid was centred to the pixel and still looked pushed right, because what
   the eye centres on is the ink: three of these sat around 150px wide inside
   their half while the Locate a Locum wordmark filled its own, putting the
   visible block about 24px right of the panel's middle. Sizing each column to
   what is in it makes the grid hug the ink, and centring that puts the ink
   itself in the middle. */
.sp-logos {
  display: grid; grid-template-columns: repeat(2, auto);
  justify-content: center; align-items: center; justify-items: center;
  gap: 16px 14px;
}
/* Sized by height, with width following. The columns above are sized to what
   is in them, so an item stretched to width:100% would set its own column
   width and defeat that. Aspect ratios are never touched.

   The per-logo heights below are optical, not arithmetic. Set to one common
   height these four look mismatched, because the eye weighs how much ink is
   on the page, not how tall the box is, and measured across the four files
   the ink coverage runs from 14% to 44%:

     osce toolbox   1.8:1   14.5% ink   a light mark, mostly air
     Numark         2.7:1   29.6% ink
     MSC            3.0:1   38.1% ink
     Locate a Locum 9.8:1   43.8% ink   a solid wordmark, all stroke

   At a shared 56px the sparse mark carried about a fifth of the ink of the
   dense one and read as an afterthought. Each is now scaled against the base
   so the four sit as a set. If a sponsor joins, measure rather than guess:
   trim to the ink box, take the coverage, and scale to match. */
.sp-logos { --logo-h: 40px; }
.sp-logo {
  display: block; width: auto; height: auto; object-fit: contain;
  max-width: 100%; max-height: var(--logo-h);
}
.sp-logo--osce-toolbox { max-height: calc(var(--logo-h) * 1.4); }
.sp-logo--medical-supply-company { max-height: calc(var(--logo-h) * 0.86); }
/* Ten times as wide as it is tall: at the shared height it would draw wider
   than the panel and set the column width for everyone else. */
.sp-logo--locate-a-locum { max-height: calc(var(--logo-h) * 0.45); }
/* After .sp-logo, not before it: same specificity, so the last rule wins. */
@media (min-width: 560px) {
  .sp-logos { --logo-h: 56px; gap: 24px 26px; }
}
.sp-name { font-family: var(--display); font-weight: 700; font-size: 14px; color: var(--ink); text-align: center; }
.sp-more {
  display: block; margin-top: 22px; padding-top: 16px;
  border-top: 1px solid var(--grey-2);
  font-size: 13px; font-weight: 600; color: var(--pink-dark);
}
.sp-more .chev { font-size: 17px; vertical-align: -1px; color: var(--pink-mid); }
@media (max-width: 359px) {
  .sp-logos { gap: 12px 8px; }
  .sp-logo { max-height: 30px; }
}

/* "Meet our sponsors" — the actionable card at the top of the sponsors page. */
.meet-card {
  background: var(--green-tint); border: 1px solid var(--green-tint-2);
  border-left: 4px solid var(--green);
  border-radius: var(--r-lg); padding: 18px 18px 16px; margin-bottom: 18px;
}
.meet-ico {
  width: 40px; height: 40px; border-radius: var(--r-sm);
  background: var(--green-mid); color: #fff;
  display: grid; place-items: center; margin-bottom: 12px;
}
.meet-ico svg { width: 22px; height: 22px; }
.meet-card h2 { font-size: 20px; margin: 0 0 4px; }
.meet-where { font-size: 14.5px; color: var(--green-deep); margin: 0 0 10px; }
.meet-card p { font-size: 14.5px; color: var(--ink-2); margin: 0 0 12px; line-height: 1.55; }
.meet-when { display: flex; flex-wrap: wrap; gap: 7px; }
.meet-slot {
  font-family: var(--display); font-weight: 700; font-size: 12.5px;
  background: var(--paper); color: var(--green-deep);
  border: 1px solid var(--green-tint-2);
  border-radius: var(--r-pill); padding: 4px 11px;
}
/* Sponsor cards end in a pill, matching every other action in the app. */
.sponsor-visit { margin-top: 4px; }

/* Logo on a sponsor's own card, on the sponsors page */
.sponsor-logo {
  display: block; max-width: 170px; max-height: 56px; width: auto; height: auto;
  margin-bottom: 13px; object-fit: contain;
}

/* References, one per line */
.ref-list { margin: 0; padding-left: 20px; }
.ref-list li { font-size: 12.5px; color: var(--grey-7); line-height: 1.5; margin-bottom: 7px; }
.ref-list li:last-child { margin-bottom: 0; }

/* Bulleted lists inside a modal section */
.m-list { margin: 0; padding-left: 20px; }
.m-list li { font-size: 15px; color: var(--ink-2); line-height: 1.55; margin-bottom: 6px; }

/* Keynote / panel tags reuse the format pill */
.fmt-keynote { background: var(--grey-2); color: var(--char); }
.fmt-panel { background: var(--grey-2); color: var(--char); }
.pill-focus { color: var(--pink-dark); font-weight: 600; }

/* InterSim booking actions */
.booking-actions { display: flex; gap: 9px; margin-top: 14px; }
.booking-actions .btn { flex: 1; padding: 12px; font-size: 14.5px; }
.btn-danger { color: var(--pink-dark); border-color: var(--pink-tint-2); }
