/* ===========================================================================
   ProsperMinds design system — rebuild Phase 1 foundation
   ===========================================================================

   WHAT THIS IS
   ------------
   The shared visual layer for the rebuilt site. Every page built from Phase 2
   onwards loads this file and nothing else. It is the CSS half of the
   foundation described in REBUILD-PLAN.md section "Phase 1".

   WHAT THIS IS NOT
   ----------------
   This does NOT replace assets/css/style.css. The live pages (index.php,
   event.php, event-registration.php, sponsorship.php, service-*.php, 404.php)
   are still served by style.css and are deliberately untouched in Phase 1 —
   the site is live, taking real registrations and real money, and a foundation
   commit must not be able to change what a delegate sees today. The two
   stylesheets are never loaded on the same page.

   SOURCE OF TRUTH
   ---------------
   prototype/Prosperminds Site.dc.html (the approved Claude Design prototype)
   and prototype/uploads/WEBSITE-REDESIGN-PROMPT-dfed5000.md (the brief, with
   Revisions 3 and 4). The prototype sizes type with container-query units
   (cqw) against a fixed device frame; there is no build step here and no such
   frame, so every cqw scale below is restated as a viewport-based clamp().
   That is the one deliberate difference from the prototype file.

   THE RULES THIS FILE ENFORCES (from the brief, section 2 and section 5)
   ---------------------------------------------------------------------
     * Three brand colours only: #00BF63 green, #000000 black, #FFFFFF white,
       plus neutral greys for rules and secondary text. No other hue appears
       anywhere in this file.
     * Green is an ACCENT: rules, numerals, active states, primary buttons.
       It is a large background field in exactly one place, .pm-section--accent,
       which is the single closing CTA band per page.
     * Maharlika is the only typeface, and only its Regular weight exists.
       Hierarchy therefore comes from SIZE, LETTER-SPACING and COLOUR. Synthetic
       bold is switched off explicitly (font-synthesis: none) so a browser
       cannot smear the one real weight into a fake second one.
     * border-radius is 2px, everywhere, or 0. There is no other radius.
     * No shadows as decoration, no gradients, no glassmorphism, no emoji.
       Separation is done with hairline rules, not elevation.

   ORGANISATION
   ------------
     1.  Font face
     2.  Design tokens (:root)
     3.  Reset and baseline
     4.  Layout: container, sections, the light/dark system
     5.  Type scale
     6.  Eyebrow labels (the small green-ruled caps used throughout)
     7.  Buttons
     8.  Hairline grids and cards
     9.  Forms
     10. Tables
     11. Site header and navigation
     12. Site footer
     13. Utilities
     14. Accessibility and reduced motion
     15. The registration flow (Phase 4)
   =========================================================================== */


/* ---------------------------------------------------------------------------
   1. FONT FACE
   ---------------------------------------------------------------------------
   Self-hosted, not Google-Fonts-hosted: the brand licence covers the file we
   already hold, the site serves EU and Kenyan public-sector delegates, and a
   third-party font request is one more cross-border request to justify under
   GDPR / Kenya DPA 2019 for no benefit.

   Only the Regular weight exists. It is declared for weight 400 only; nothing
   in this file asks for another weight, and font-synthesis is disabled in the
   baseline so nothing can invent one.

   Format is TrueType because that is the file the brand supplied
   (prototype/fonts/Maharlika-Regular.ttf, copied byte for byte). A WOFF2
   build would be roughly a third of the size and is worth doing later; it
   needs a conversion tool this project does not currently have.
--------------------------------------------------------------------------- */
@font-face {
  font-family: 'Maharlika';
  src: url('../fonts/Maharlika-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  /* swap, not block: a government delegate on a slow connection should read
     the page in a fallback serif rather than stare at invisible text. */
  font-display: swap;
}


/* ---------------------------------------------------------------------------
   2. DESIGN TOKENS
   ---------------------------------------------------------------------------
   Every value used anywhere below is named here. Nothing outside this block
   should introduce a new literal colour.
--------------------------------------------------------------------------- */
:root {
  /* -- Brand colours. These three are the entire brand palette. ----------- */
  --pm-green: #00BF63;
  --pm-black: #000000;
  --pm-white: #FFFFFF;

  /* -- Neutrals. Surfaces, rules and secondary text only. ----------------- */
  --pm-surface: #f6f6f4;        /* warm off-white, alternating sections      */
  --pm-surface-alt: #fafafa;    /* a shade lighter, for nested panels        */
  --pm-border: #dcdcdc;         /* primary rule colour                       */
  --pm-border-light: #e2e2e2;   /* hairline grids between cards              */
  --pm-border-input: #cfcfcf;   /* form control borders on light surfaces    */
  --pm-text-muted: #5a5a5a;     /* secondary body text                       */
  --pm-text-tertiary: #5f5f5f;  /* captions, figure credits                  */
  --pm-text-quaternary: #4a4a4a;/* long-form body copy on light surfaces     */

  /* -- On-dark equivalents. Kept as tokens so the dark section system is
        adjustable in one place rather than by hunting rgba() literals. ---- */
  --pm-on-dark: rgba(255, 255, 255, 0.88);
  --pm-on-dark-muted: rgba(255, 255, 255, 0.72);
  --pm-on-dark-faint: rgba(255, 255, 255, 0.45);
  --pm-on-dark-rule: rgba(255, 255, 255, 0.14);
  --pm-on-dark-input: rgba(255, 255, 255, 0.32);

  /* -- Typography -------------------------------------------------------- */
  --pm-font: 'Maharlika', Georgia, 'Times New Roman', serif;

  /* Type scale. Restated from the prototype's container-query clamps as
     viewport clamps; see the header comment. */
  --pm-fs-hero: clamp(34px, 6vw, 86px);
  --pm-fs-h1: clamp(30px, 5vw, 64px);
  --pm-fs-h2: clamp(28px, 4.2vw, 58px);
  --pm-fs-h3: clamp(19px, 2.1vw, 26px);
  --pm-fs-h4: clamp(17px, 1.7vw, 21px);
  --pm-fs-body: clamp(15px, 1.5vw, 18px);
  --pm-fs-body-sm: 15px;
  --pm-fs-small: 14px;
  --pm-fs-label: 12px;          /* small caps labels: 11-13px               */
  --pm-fs-eyebrow: 11px;
  --pm-fs-stat: clamp(30px, 4vw, 52px);

  --pm-lh-display: 1.02;        /* very large type sets tight               */
  --pm-lh-heading: 1.14;
  --pm-lh-body: 1.65;

  /* Letter-spacing. These six values are the complete set used in the
     prototype; do not introduce a seventh. */
  --pm-ls-14: 0.14em;
  --pm-ls-16: 0.16em;
  --pm-ls-18: 0.18em;
  --pm-ls-20: 0.2em;
  --pm-ls-22: 0.22em;
  --pm-ls-24: 0.24em;
  --pm-ls-display: -0.005em;    /* the only negative tracking, on hero type  */

  /* -- Layout ------------------------------------------------------------ */
  --pm-container: 1180px;       /* the one content width in the prototype   */
  --pm-gutter: clamp(20px, 4vw, 56px);
  --pm-section-y: clamp(52px, 7vw, 108px);
  --pm-section-y-tight: clamp(36px, 4.5vw, 64px);

  /* -- Shape. 2px is the only radius in the design. ---------------------- */
  --pm-radius: 2px;
  --pm-rule: 1px solid var(--pm-border);
  --pm-rule-light: 1px solid var(--pm-border-light);
  --pm-rule-heavy: 2px solid var(--pm-black);

  /* -- Controls ---------------------------------------------------------- */
  --pm-control-h: 52px;         /* inputs and inline buttons               */
  --pm-tap-min: 44px;           /* minimum touch target                    */
  --pm-btn-pad: 18px 30px;      /* primary button padding                  */
  --pm-btn-pad-sm: 14px 22px;

  /* -- Motion. Short and functional; nothing decorative animates. -------- */
  --pm-transition: 140ms ease;
}


/* ---------------------------------------------------------------------------
   3. RESET AND BASELINE
--------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body.pm {
  margin: 0;
  background: var(--pm-white);
  color: var(--pm-black);
  font-family: var(--pm-font);
  font-size: var(--pm-fs-body);
  font-weight: 400;
  line-height: var(--pm-lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Only Maharlika Regular exists. Without this a browser will fake a bold
     for <h1>, <strong> and <th> and the page stops being the brand typeface. */
  font-synthesis: none;
  font-synthesis-weight: none;
  font-synthesis-style: none;
}

/* :where() again, for the same reason as the <a> and <button> resets: written
   as `.pm p { margin: 0 }` this is (0,1,1) and silently beats the .pm-mt-*
   spacing utilities, so `<p class="pm-lede pm-mt-lg">` would get no margin at
   all and every heading would sit flush against its paragraph. */
.pm :where(h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd, ul, ol) {
  margin: 0;
}

.pm h1,
.pm h2,
.pm h3,
.pm h4,
.pm h5,
.pm h6,
.pm strong,
.pm b,
.pm th {
  /* Regular is the only weight that exists. See body.pm above. */
  font-weight: 400;
}

.pm :where(ul, ol) {
  padding: 0;
  list-style: none;
}

/* :where() again, and for the fourth time the same trap. Written plainly as
   `.pm img { height: auto }` this is (0,1,1) and beats every single-class
   component that needs to SET a height: .pm-brand__logo, whose whole job is to
   scale the 713x183 logo file down to the header bar, came out at its intrinsic
   713px and pushed the navigation off the right of every page. The reset still
   does its job (an image with no sizing rule of its own stays inside its
   container and keeps its ratio); it just no longer outranks the components. */
.pm :where(img, svg, video) {
  max-width: 100%;
  height: auto;
  display: block;
}

/* The base <a> carries NO decoration.
   This is deliberate and worth stating, because the obvious alternative bites:
   giving `.pm a` a colour and a green underline makes a selector of specificity
   (0,1,1), which then beats every single-class component selector — .pm-btn,
   .pm-nav__link, .pm-brand — and quietly repaints anchor-based buttons and nav
   links. Decoration is opted into instead, by the prose contexts below and by
   the .pm-link class, so a component never has to fight the base rule. */
.pm a {
  text-decoration: none;
}

/* Links inside running copy: underlined in green, blackening on hover. */
.pm-body a,
.pm-lede a,
.pm-caption a,
.pm-quote__text a,
.pm-table a,
.pm-link {
  color: inherit;
  border-bottom: 1px solid var(--pm-green);
  transition: color var(--pm-transition), border-color var(--pm-transition);
}

.pm-body a:hover,
.pm-lede a:hover,
.pm-caption a:hover,
.pm-quote__text a:hover,
.pm-table a:hover,
.pm-link:hover,
.pm-body a:focus-visible,
.pm-lede a:focus-visible,
.pm-caption a:focus-visible,
.pm-quote__text a:focus-visible,
.pm-table a:focus-visible,
.pm-link:focus-visible {
  color: var(--pm-black);
  border-bottom-color: var(--pm-black);
}

/* :where() so this reset carries ZERO specificity beyond `.pm` itself. Written
   as a plain `.pm button` selector it would be (0,1,1) and would beat .pm-btn's
   own colour, repainting the primary button white wherever it sits inside a
   dark section. Same trap as the base <a> rule above. */
.pm :where(input, select, textarea, button) {
  font-family: inherit;
  font-size: inherit;
  font-weight: 400;
  color: inherit;
}

.pm ::selection {
  background: var(--pm-green);
  color: var(--pm-black);
}

.pm hr {
  border: 0;
  border-top: var(--pm-rule);
  margin: 0;
}

/* Visible focus, on every interactive thing, in the brand colour. The audience
   includes people using keyboards and screen readers in government offices
   with locked-down browsers; this is not optional decoration. */
.pm :focus-visible {
  outline: 2px solid var(--pm-green);
  outline-offset: 2px;
}

/* Screen-reader-only text. Used for form labels that are visually implied. */
.pm-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Skip link. Hidden until focused, then a real green block at top left. */
.pm-skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--pm-green);
  color: var(--pm-black);
  padding: 14px 22px;
  font-size: var(--pm-fs-label);
  letter-spacing: var(--pm-ls-14);
  text-transform: uppercase;
  border: 0;
  border-radius: var(--pm-radius);
}

.pm-skip-link:focus {
  left: 8px;
  top: 8px;
}


/* ---------------------------------------------------------------------------
   4. LAYOUT: CONTAINER, SECTIONS, THE LIGHT/DARK SYSTEM
   ---------------------------------------------------------------------------
   The prototype's treatment notes state the rule this implements verbatim:

     "Dark sections carry the brand voice: hero, proof, testimonials, closing
      calls to action. Light sections carry information the delegate has to
      read closely: agendas, pricing tables, forms, contact details. Green
      appears only as rules, numerals, active states and primary buttons,
      never as a large background field."

   So there are four section tones and no more:
     .pm-section              white, the default and the dominant surface
     .pm-section--surface     the warm off-white, for alternating rhythm
     .pm-section--dark        black, used sparingly as punctuation
     .pm-section--accent      green, for the ONE closing CTA band on a page
--------------------------------------------------------------------------- */
.pm-container {
  width: 100%;
  max-width: var(--pm-container);
  margin-inline: auto;
}

.pm-section {
  background: var(--pm-white);
  color: var(--pm-black);
  padding: var(--pm-section-y) var(--pm-gutter);
}

.pm-section--tight {
  padding-block: var(--pm-section-y-tight);
}

.pm-section--surface {
  background: var(--pm-surface);
}

.pm-section--ruled {
  border-top: var(--pm-rule-light);
}

/* -- Dark. Everything inside inverts, including form controls. ----------- */
.pm-section--dark {
  background: var(--pm-black);
  color: var(--pm-white);
}

.pm-section--dark .pm-lede,
.pm-section--dark .pm-body,
.pm-section--dark .pm-caption {
  color: var(--pm-on-dark-muted);
}

.pm-section--dark .pm-eyebrow {
  color: var(--pm-green);
  border-left-color: var(--pm-green);
}

.pm-section--dark .pm-rule,
.pm-section--dark hr {
  border-top-color: var(--pm-on-dark-rule);
}

/* -- Accent. The single green band. Black text on green, never white:
      #FFFFFF on #00BF63 is 2.2:1 and fails WCAG AA. Black on green is 8.6:1. */
.pm-section--accent {
  background: var(--pm-green);
  color: var(--pm-black);
}

.pm-section--accent .pm-lede,
.pm-section--accent .pm-body {
  color: rgba(0, 0, 0, 0.72);
}

/* A section header: eyebrow + heading on the left, an optional action on the
   right, closed with the 2px black rule the prototype uses to open a grid. */
.pm-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 20px;
  padding-bottom: 26px;
  border-bottom: var(--pm-rule-heavy);
  margin-bottom: 0;
}

.pm-section-head__action {
  margin-left: auto;
}

.pm-section--dark .pm-section-head {
  border-bottom-color: var(--pm-white);
}


/* ---------------------------------------------------------------------------
   5. TYPE SCALE
   ---------------------------------------------------------------------------
   Uppercase serif display type is the signature of this design. It is applied
   by class, never by element, so a page can use an <h2> at sub-heading size
   without lying about the document outline.
--------------------------------------------------------------------------- */
.pm-display {
  font-size: var(--pm-fs-hero);
  line-height: var(--pm-lh-display);
  letter-spacing: var(--pm-ls-display);
  text-transform: uppercase;
  max-width: 15ch;
}

.pm-h1 {
  font-size: var(--pm-fs-h1);
  line-height: 1.04;
  text-transform: uppercase;
  max-width: 18ch;
}

.pm-h2 {
  font-size: var(--pm-fs-h2);
  line-height: 1.05;
  text-transform: uppercase;
}

.pm-h3 {
  font-size: var(--pm-fs-h3);
  line-height: var(--pm-lh-heading);
}

.pm-h3--caps {
  text-transform: uppercase;
  line-height: 1.2;
}

.pm-h4 {
  font-size: var(--pm-fs-h4);
  line-height: 1.25;
}

/* Introductory paragraph under a heading. */
.pm-lede {
  font-size: var(--pm-fs-body);
  line-height: var(--pm-lh-body);
  color: var(--pm-text-quaternary);
  max-width: 58ch;
}

.pm-body {
  font-size: var(--pm-fs-body-sm);
  line-height: var(--pm-lh-body);
  color: var(--pm-text-muted);
  max-width: 62ch;
}

.pm-caption {
  font-size: 13px;
  line-height: 1.55;
  color: var(--pm-text-tertiary);
}

/* A large numeral. Black, never green — green numerals are used as ordinals
   (01, 02, 03), not as headline figures. */
.pm-stat__value {
  font-size: var(--pm-fs-stat);
  line-height: 1;
  color: inherit;
}

.pm-stat__label {
  margin-top: 10px;
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-16);
  text-transform: uppercase;
  color: var(--pm-text-muted);
}

.pm-section--dark .pm-stat__label {
  color: var(--pm-on-dark-muted);
}

/* Ordinal marker on a numbered card: 01 / 02 / 03. */
.pm-ordinal {
  font-size: var(--pm-fs-label);
  letter-spacing: var(--pm-ls-20);
  color: var(--pm-green);
}

/* A price. Smaller than .pm-stat__value, which is a headline figure, and larger
   than a heading, because on a pricing card the number IS the heading and the
   tier name above it is the label.

   Added in Phase 3 and used by both of its pricing blocks: the three delegate
   tiers on an event page and the four sponsorship tiers. Lower case rather than
   uppercase, because "USD 599" and "$15,000" are already set the way they are
   meant to read and .pm-h2 would only shout them. */
.pm-price {
  font-size: clamp(26px, 2.9vw, 36px);
  line-height: 1.05;
  color: var(--pm-black);
}

/* The qualifier under a price: "per delegate", "per event". */
.pm-price__note {
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-16);
  text-transform: uppercase;
  color: var(--pm-text-muted);
}

.pm-section--dark .pm-price {
  color: var(--pm-white);
}

.pm-section--dark .pm-price__note {
  color: var(--pm-on-dark-muted);
}


/* ---------------------------------------------------------------------------
   6. EYEBROW LABELS
   ---------------------------------------------------------------------------
   The small uppercase letter-spaced label, usually preceded by a short green
   rule. Used above almost every heading on the site and the most repeated
   single element in the prototype. Two variants: a left green border (used
   above section headings) and a detached green dash (used in heroes).
--------------------------------------------------------------------------- */
.pm-eyebrow {
  display: block;
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-24);
  text-transform: uppercase;
  color: var(--pm-black);
  border-left: 3px solid var(--pm-green);
  padding-left: 11px;
  margin-bottom: 14px;
}

.pm-eyebrow--dash {
  display: flex;
  /* flex-start, not center: on a phone the label wraps to two lines, and a
     vertically centred rule then floats beside the middle of the block instead
     of leading the first line. */
  align-items: flex-start;
  gap: 12px;
  border-left: 0;
  padding-left: 0;
}

.pm-eyebrow--dash::before {
  content: "";
  flex: 0 0 auto;
  width: 44px;
  height: 1px;
  /* Half the label's line box, so the rule sits on the first line's midline. */
  margin-top: 0.75em;
  background: var(--pm-green);
}

.pm-section--dark .pm-eyebrow--dash,
.pm-section--dark .pm-label {
  color: var(--pm-green);
}

/* A plain small-caps label with no rule: column headings in the footer, field
   labels, table headers. */
.pm-label {
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-22);
  text-transform: uppercase;
  color: var(--pm-black);
}

.pm-label--wide {
  letter-spacing: var(--pm-ls-18);
}

.pm-label--green {
  color: var(--pm-green);
}

/* A set of short standing labels: the job titles in the room on the
   sponsorship page. Not links, not filters, not removable, so they are plain
   <li> rather than buttons and carry no interactive affordance at all.

   Added in Phase 3. Kept in the label family rather than invented as a pill
   because the house shape is a 2px radius and a hairline, never a capsule.
   Reusable anywhere a short closed vocabulary has to be shown as a set:
   audiences, focus areas, accreditations. */
.pm-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pm-tag {
  display: inline-block;
  padding: 8px 13px;
  border: var(--pm-rule);
  border-radius: var(--pm-radius);
  font-size: var(--pm-fs-small);
  line-height: 1.3;
  color: var(--pm-text-quaternary);
}

.pm-section--dark .pm-tag {
  border-color: var(--pm-on-dark-rule);
  color: var(--pm-on-dark);
}


/* ---------------------------------------------------------------------------
   7. BUTTONS
   ---------------------------------------------------------------------------
   Four kinds, and no others:
     .pm-btn                  green fill, black text. The primary action.
     .pm-btn--secondary       black hairline outline, transparent fill.
     .pm-btn--invert          black fill, white text. On green or light bands.
     .pm-btn--link            text with a 2px green underline. Tertiary.

   Flat, letter-spaced, uppercase, 2px radius, no shadow, no gradient.
--------------------------------------------------------------------------- */
.pm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: var(--pm-btn-pad);
  min-height: 48px;
  background: var(--pm-green);
  color: var(--pm-black);
  border: 1px solid var(--pm-green);
  border-radius: var(--pm-radius);
  font-size: 13px;
  line-height: 1;
  letter-spacing: var(--pm-ls-14);
  text-transform: uppercase;
  text-align: center;
  cursor: pointer;
  transition: background var(--pm-transition), color var(--pm-transition),
              border-color var(--pm-transition);
}

.pm-btn:hover,
.pm-btn:focus-visible {
  background: var(--pm-black);
  border-color: var(--pm-black);
  color: var(--pm-white);
}

.pm-btn--secondary {
  background: transparent;
  color: var(--pm-black);
  border-color: var(--pm-black);
}

.pm-btn--secondary:hover,
.pm-btn--secondary:focus-visible {
  background: var(--pm-black);
  color: var(--pm-white);
}

.pm-btn--invert {
  background: var(--pm-black);
  color: var(--pm-white);
  border-color: var(--pm-black);
}

.pm-btn--invert:hover,
.pm-btn--invert:focus-visible {
  background: transparent;
  color: var(--pm-black);
}

.pm-btn--sm {
  padding: var(--pm-btn-pad-sm);
  min-height: var(--pm-tap-min);
  font-size: var(--pm-fs-label);
}

.pm-btn--block {
  width: 100%;
}

.pm-btn[disabled],
.pm-btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Secondary buttons on a dark section invert their outline. */
.pm-section--dark .pm-btn--secondary {
  color: var(--pm-white);
  border-color: var(--pm-white);
}

.pm-section--dark .pm-btn--secondary:hover,
.pm-section--dark .pm-btn--secondary:focus-visible {
  background: var(--pm-white);
  color: var(--pm-black);
}

/* Tertiary: the "Details" / "Read more" affordance from the prototype's cards.
   Not an <a> underline — a deliberate 2px green rule under uppercase caps. */
.pm-btn--link {
  display: inline-block;
  padding: 8px 0;
  min-height: 0;
  background: none;
  border: 0;
  border-bottom: 2px solid var(--pm-green);
  border-radius: 0;
  color: var(--pm-black);
  font-size: var(--pm-fs-label);
  letter-spacing: var(--pm-ls-14);
  text-transform: uppercase;
  cursor: pointer;
}

.pm-btn--link:hover,
.pm-btn--link:focus-visible {
  background: none;
  color: var(--pm-black);
  border-bottom-color: var(--pm-black);
}

.pm-section--dark .pm-btn--link {
  color: var(--pm-white);
}

.pm-section--dark .pm-btn--link:hover,
.pm-section--dark .pm-btn--link:focus-visible {
  color: var(--pm-white);
  border-bottom-color: var(--pm-white);
}

/* A row of buttons that wraps cleanly on a phone. */
.pm-btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}


/* ---------------------------------------------------------------------------
   8. HAIRLINE GRIDS AND CARDS
   ---------------------------------------------------------------------------
   The prototype does not use shadowed, rounded, floating cards. It uses a grid
   whose background is the rule colour with a 1px gap, so the cells are
   separated by a hairline that is the grid itself. That is what .pm-grid--ruled
   does. It is the reason the layout reads as a printed table of contents
   rather than a bento box of soft tiles.
--------------------------------------------------------------------------- */
.pm-grid {
  display: grid;
  gap: clamp(18px, 2vw, 28px);
}

/* Auto-fitting columns. --pm-col-min sets the point at which a column drops. */
.pm-grid--auto {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--pm-col-min, 280px)), 1fr));
}

.pm-grid--ruled {
  gap: 1px;
  background: var(--pm-border);
}

.pm-grid--ruled > * {
  background: var(--pm-white);
}

.pm-section--surface .pm-grid--ruled > * {
  background: var(--pm-white);
}

.pm-section--dark .pm-grid--ruled {
  background: var(--pm-on-dark-rule);
}

.pm-section--dark .pm-grid--ruled > * {
  background: var(--pm-black);
}

.pm-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.pm-grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.pm-grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }

/* A cell inside a ruled grid. */
.pm-cell {
  padding: clamp(22px, 2.5vw, 34px);
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* A standalone bordered card (testimonials, enquiry panels). Border, not
   shadow — flat surfaces only. */
.pm-card {
  background: var(--pm-white);
  border: var(--pm-rule);
  border-radius: var(--pm-radius);
  padding: clamp(24px, 2.6vw, 34px);
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.pm-card__foot {
  margin-top: auto;
  padding-top: 18px;
  border-top: var(--pm-rule);
}

/* A footer with something on each end: a price and a "Details" link, a label
   and a date. The prototype's event card does exactly this. */
.pm-card__foot--split,
.pm-cell__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}

.pm-cell__meta {
  align-items: baseline;
}

/* Pushes a card's action to the bottom edge regardless of how much copy sits
   above it, so a row of cards has its buttons on one line. */
.pm-cell__action {
  margin-top: auto;
  align-self: flex-start;
}

/* ONE cell in a ruled grid filled green, everything else left alone.

   Added in Phase 3 for the fact strip at the top of an event page, where the
   approved prototype fills only the early bird cell. That is the sanctioned use
   of green as an active state rather than as a background field: one cell in
   four, carrying the single time-limited fact on the page.

   The selector is scoped to .pm-grid--ruled > because the ruled grid paints its
   children white at that same specificity, and an unscoped .pm-cell--accent
   would lose to it. Black text on green, never white: 8.6:1 against 2.2:1. */
.pm-grid--ruled > .pm-cell--accent {
  background: var(--pm-green);
  color: var(--pm-black);
}

/* Body and caption text inside the green cell. .pm-body's default is
   --pm-text-muted, a grey chosen for white surfaces, and on green it drops to
   roughly 3:1. These put it back on black, which is 8.6:1 against the brand
   green and is the reason the accent band uses black text everywhere else. */
.pm-cell--accent .pm-label {
  color: var(--pm-black);
}

.pm-cell--accent .pm-body,
.pm-cell--accent .pm-caption {
  color: rgba(0, 0, 0, 0.78);
}

/* A band: heading on the left, one action on the right, wrapping on a phone.
   Used for the single accent CTA per page. */
.pm-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 28px;
}

.pm-section--dark .pm-card {
  background: var(--pm-black);
  border-color: var(--pm-on-dark-rule);
}

.pm-section--dark .pm-card__foot {
  border-top-color: var(--pm-on-dark-rule);
}

/* The banner tile that anchors an event card. The brief is explicit that the
   client's own designed event banners are the visual anchor and must not be
   replaced with stock photography, so the tile is a fixed 16:9 slot with a
   neutral placeholder behind it. */
.pm-banner {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--pm-surface);
  border-bottom: var(--pm-rule-light);
  overflow: hidden;
}

.pm-banner > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The stand-in when a cohort was listed as text and no banner was ever
   designed for it. Same 16:9 slot, so a row of cards keeps one height. */
.pm-banner--monogram {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background:
    linear-gradient(135deg, rgba(0, 191, 99, 0.07), rgba(0, 191, 99, 0) 62%),
    var(--pm-surface);
}

.pm-monogram {
  font-family: var(--pm-font);
  font-size: 34px;
  line-height: 1;
  letter-spacing: 0.06em;
  color: var(--pm-black);
}

.pm-tile .pm-monogram {
  font-size: clamp(38px, 5vw, 58px);
}

/* A tile: a full-bleed figure across the top edge, then a .pm-cell body that
   fills whatever height the tallest tile in the row sets.

   Added in Phase 2 rather than Phase 1 because the need only shows up once a
   row holds real data. The prototype's event cards carry titles between four
   and eleven words long, and without this the price and the Details link sit
   at a different height on every card in the row, which reads as three
   different components rather than one.

   Reusable, not a one-off: the homepage event grid uses it now, and Phase 3's
   events listing, banner library and the contact page's location panel all
   need the same shape. It composes with either .pm-grid--ruled (where the grid
   gap is the rule) or .pm-card (where the tile has its own border). */
.pm-tile {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.pm-tile > .pm-cell {
  flex: 1 1 auto;
}

/* A card holding a full-bleed first child. The padding moves off the card and
   onto a .pm-cell inside it, so the figure reaches the border on three sides
   the way the prototype's banner tiles do. */
.pm-card--flush {
  padding: 0;
  gap: 0;
  overflow: hidden;
}

/* A single dark panel inside a light section.

   Added in Phase 3 for the "Who will be in the room" panel on the sponsorship
   page, which the client asked for dark while the benefit list beside it stays
   light. .pm-section--dark cannot do that job: it is a section tone, and the
   descendant rules it carries only reach children of a whole section.

   The rules are restated here rather than by adding .pm-card--dark to ten
   existing selector lists, so that everything this modifier does is visible in
   one place. It is deliberately short: a dark panel is punctuation, and a panel
   that needed the full inverted form set would be a section. */
.pm-card--dark {
  background: var(--pm-black);
  border-color: var(--pm-black);
  color: var(--pm-white);
}

.pm-card--dark .pm-body,
.pm-card--dark .pm-caption,
.pm-card--dark .pm-quote__text {
  color: var(--pm-on-dark-muted);
}

.pm-card--dark .pm-label,
.pm-card--dark .pm-eyebrow {
  color: var(--pm-green);
  border-left-color: var(--pm-green);
}

.pm-card--dark .pm-tag {
  border-color: var(--pm-on-dark-rule);
  color: var(--pm-on-dark);
}

.pm-card--dark .pm-rule,
.pm-card--dark .pm-card__foot {
  border-top-color: var(--pm-on-dark-rule);
}

/* A card used as a sidebar rather than as another item in the main column: the
   services curriculum panel and the same panel on each of the three service
   detail pages. The alternate surface is what separates it from the white page
   without adding a border weight or a shadow. */
.pm-card--panel {
  background: var(--pm-surface-alt);
  border-color: var(--pm-border-light);
}

/* The office location map at the top of a tile: contact.php today.
   Markup and behaviour are in assets/js/pm-map.js.

   THE HEIGHT IS EXPLICIT AND HAS TO BE. MapLibre measures its container when it
   initialises and renders a zero-pixel canvas if that container has no height
   of its own yet, which is a blank frame rather than an error. An aspect-ratio
   would work too, but a fixed band is what the layout wants beside a form:
   tall enough to place a building, short enough that the directions beneath it
   are still on screen.

   This replaced the flat SVG schematic that stood here first. The reasoning
   that ruled out an embed has not changed, only the answer to it: a Google Maps
   iframe is a cross-border third-party request setting its own cookies, on the
   one page whose entire job is a form covered by the Kenya Data Protection Act
   2019 and GDPR, and this site already carries two Google tags it has to
   justify. OpenFreeMap needs no key, no signup and sets no tracking cookie, and
   its 'positron' style is grey enough not to break the three-colour palette. */
.pm-map {
  position: relative;
  height: clamp(240px, 30vw, 330px);
  background: var(--pm-surface);
  overflow: hidden;
}

/* The line the visitor sees when there is no map: script off, WebGL absent, or
   tiles.openfreemap.org unreachable. It is in the markup from the start and is
   hidden only once the map reports that it actually drew, so a failed tile
   request leaves a sentence rather than an empty grey box. */
.pm-map__fallback {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 24px;
  text-align: center;
  font-size: 13px;
  line-height: 1.55;
  color: var(--pm-text-tertiary);
}

.pm-map[data-pm-map-ready="true"] .pm-map__fallback {
  display: none;
}

/* MapLibre's own attribution is required by the OpenStreetMap licence and is
   never suppressed. It is only brought into the type system so it does not
   arrive in the browser default sans-serif on a page set entirely in
   Maharlika. */
.pm-map .maplibregl-ctrl-attrib {
  font-family: var(--pm-font);
  font-size: 11px;
}

/* A segmented switch: a row of sibling destinations sharing one rule, with the
   current one marked by a green 2px segment above its label.

   Added in Phase 2 for the three service detail pages, which are siblings a
   delegate compares rather than a hierarchy they descend. The approved
   prototype shows exactly this control at the top of its services screen; the
   only difference here is that each segment is a real link to a real page
   rather than a client-side tab, because these are separate URLs.

   Reusable, not a one-off. Phase 3's events listing needs the identical
   control for "Upcoming / Past", and it is the natural shape for any small,
   closed set of peer views. It is deliberately NOT the nav link component:
   .pm-nav__link marks the current page with a bottom rule inside the header,
   and reusing it here would tie two unrelated things together.

   Marked with aria-current="page" on the segment for the page you are on, the
   same contract .pm-nav__link uses, so the state is announced and not merely
   coloured. */
.pm-switch {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: clamp(14px, 2vw, 28px);
}

.pm-switch__link {
  display: block;
  padding-top: 14px;
  border-top: 2px solid var(--pm-border);
  color: var(--pm-text-muted);
  font-size: var(--pm-fs-body-sm);
  line-height: 1.4;
  transition: color var(--pm-transition), border-color var(--pm-transition);
}

.pm-switch__link:hover,
.pm-switch__link:focus-visible {
  color: var(--pm-black);
  border-top-color: var(--pm-black);
}

.pm-switch__link[aria-current="page"] {
  color: var(--pm-black);
  border-top-color: var(--pm-green);
}

/* The compact form of the same control: two or three short boxed segments
   sitting inline rather than a full-width row of columns.

   Added in Phase 3 for the events calendar's "Upcoming / Past cohorts" filter,
   which the approved prototype draws as a pair of small boxes with the current
   one filled black, not as the wide top-ruled segments the services pages use.
   The two are the same component because they are the same idea (a small,
   closed set of peer views, each a real URL, marked with aria-current), and
   splitting them would be two things to keep in step.

   Which variant to use is a question of scale: --boxed when the labels are one
   or two words and the control is a filter above a list, the base variant when
   each segment carries a sentence and is a destination in its own right. */
.pm-switch--boxed {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  grid-template-columns: none;
}

.pm-switch--boxed .pm-switch__link {
  padding: 13px 22px;
  min-height: var(--pm-tap-min);
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--pm-border);
  border-radius: var(--pm-radius);
  color: var(--pm-black);
  font-size: var(--pm-fs-label);
  letter-spacing: var(--pm-ls-14);
  text-transform: uppercase;
}

.pm-switch--boxed .pm-switch__link:hover,
.pm-switch--boxed .pm-switch__link:focus-visible {
  border-color: var(--pm-black);
}

.pm-switch--boxed .pm-switch__link[aria-current="page"] {
  background: var(--pm-black);
  border-color: var(--pm-black);
  color: var(--pm-white);
}

/* ---------------------------------------------------------------------------
   8b. THE LISTING: HAIRLINE-SEPARATED ROWS
   ---------------------------------------------------------------------------
   The calendar on events.php. Deliberately NOT the card grid: the approved
   prototype draws the schools as full-width rows divided by a hairline, which
   is the printed-timetable treatment, and a delegate comparing four schools
   reads a stack of rows far faster than a row of tiles. The card grid stays
   what the homepage and the service pages use, where a school is one item among
   other kinds of content rather than the whole page.

   Reusable rather than a one-off: events.php renders the same component twice
   (upcoming and past cohorts) and any future "everything of one kind, in date
   order" page wants exactly this. It is built from a grid rather than a table
   because nothing in the row is tabular data with column headings.

   The bar above it carries the filter on the left and the count on the right.
--------------------------------------------------------------------------- */
.pm-listing__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 18px;
  margin-bottom: 8px;
}

.pm-listing__count {
  margin-left: auto;
}

.pm-listing {
  margin: 0;
  padding: 0;
  list-style: none;
}

.pm-listing__row {
  display: grid;
  /* banner | date | title and meta | price, badge and action */
  grid-template-columns: minmax(160px, 220px) minmax(110px, 150px) minmax(0, 1fr) auto;
  gap: clamp(18px, 2.4vw, 34px);
  align-items: start;
  padding-block: clamp(24px, 2.8vw, 34px);
  border-top: var(--pm-rule-light);
}

.pm-listing > li:last-child .pm-listing__row {
  border-bottom: var(--pm-rule-light);
}

.pm-listing__date {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* The day range: the largest thing in the row after the title. Not .pm-h2,
   which is uppercase and would set a numeral in caps for no reason. */
.pm-listing__range {
  font-size: clamp(26px, 3vw, 38px);
  line-height: 1;
  color: var(--pm-black);
}

/* Location, length and focus tag on one wrapping line, separated by space
   rather than by a glyph, so nothing has to be read out as punctuation. */
.pm-listing__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
}

.pm-listing__side {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  min-width: 0;
}

@media (max-width: 900px) {
  /* On a phone the four columns become two: the banner keeps the date beside
     it, and the title, meta and actions run full width underneath. Collapsing
     to a single column instead would push the action four screens down. */
  .pm-listing__row {
    grid-template-columns: minmax(120px, 1fr) minmax(0, 1.2fr);
  }

  .pm-listing__row > :nth-child(3),
  .pm-listing__row > :nth-child(4) {
    grid-column: 1 / -1;
  }
}

/* Pull quote. The opening quotation mark is the only place green is used as
   a character rather than a rule. */
.pm-quote__mark {
  color: var(--pm-green);
  font-size: 30px;
  line-height: 0.6;
}

.pm-quote__text {
  font-size: 16px;
  line-height: 1.68;
  color: inherit;
}


/* ---------------------------------------------------------------------------
   9. FORMS
   ---------------------------------------------------------------------------
   Every control is 52px tall, 2px radius, hairline border, and carries a real
   <label>. Placeholder text is never a substitute for a label — the audience
   includes screen-reader users and the brief calls for "forms with real
   labels" explicitly.
--------------------------------------------------------------------------- */
.pm-field {
  display: flex;
  flex-direction: column;
  gap: 9px;
  min-width: 0;
}

.pm-field__label {
  font-size: var(--pm-fs-label);
  letter-spacing: var(--pm-ls-14);
  text-transform: uppercase;
  color: var(--pm-black);
}

.pm-field__hint {
  font-size: 13px;
  line-height: 1.5;
  color: var(--pm-text-muted);
}

.pm-input,
.pm-select,
.pm-textarea {
  width: 100%;
  height: var(--pm-control-h);
  padding: 0 15px;
  background: var(--pm-white);
  color: var(--pm-black);
  border: 1px solid var(--pm-border-input);
  border-radius: var(--pm-radius);
  /* 16px minimum: anything smaller makes iOS Safari zoom the viewport on
     focus, which on a phone reads as the form being broken. */
  font-size: 16px;
  transition: border-color var(--pm-transition);
}

.pm-textarea {
  height: auto;
  min-height: 132px;
  padding: 14px 15px;
  line-height: 1.55;
  resize: vertical;
}

.pm-select {
  padding: 0 12px;
}

.pm-input:hover,
.pm-select:hover,
.pm-textarea:hover {
  border-color: var(--pm-black);
}

.pm-input::placeholder,
.pm-textarea::placeholder {
  color: var(--pm-text-tertiary);
  opacity: 1;
}

.pm-input[aria-invalid="true"],
.pm-textarea[aria-invalid="true"] {
  border-color: var(--pm-black);
  border-width: 2px;
}

/* Controls on a dark section. Transparent fill, faint white rule. */
.pm-section--dark .pm-input,
.pm-section--dark .pm-select,
.pm-section--dark .pm-textarea,
.pm-footer .pm-input {
  background: var(--pm-black);
  color: var(--pm-white);
  border-color: var(--pm-on-dark-input);
}

.pm-section--dark .pm-field__label,
.pm-footer .pm-field__label {
  color: var(--pm-green);
}

.pm-section--dark .pm-input::placeholder,
.pm-footer .pm-input::placeholder {
  color: var(--pm-on-dark-faint);
}

/* A group of related controls. A set of checkboxes with only a paragraph above
   them announces as unrelated controls, so the group is a real <fieldset> with
   a real <legend>.

   The UA gives a fieldset a border, padding, and a min-width that stops it
   shrinking inside a grid or flex column. All three are removed: in this system
   a group is drawn by its legend and its spacing, not by a box, and a box round
   one group and not the others reads as an error state.

   Added in Phase 3 for the sponsorship enquiry's school picker; every future
   radio or checkbox group wants the same treatment. */
.pm-fieldset {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

.pm-fieldset > legend {
  padding: 0;
}

/* A consent / checkbox row. The box is a real checkbox, sized up to a legible
   target rather than replaced with a styled span, so it stays operable with a
   keyboard and announces correctly. */
.pm-check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: var(--pm-fs-small);
  line-height: 1.6;
  color: var(--pm-text-muted);
}

/* --pm-text-muted is a grey chosen against white and drops to about 3:1 on
   black. Checkbox labels on a dark section are real reading copy, so they take
   the on-dark token the rest of the dark system uses. */
.pm-section--dark .pm-check,
.pm-card--dark .pm-check {
  color: var(--pm-on-dark-muted);
}

.pm-check input[type="checkbox"] {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin: 2px 0 0;
  accent-color: var(--pm-green);
}

/* Inline form: a field plus a submit sitting on the same baseline. */
.pm-form-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-end;
}

.pm-form-inline .pm-field {
  flex: 1 1 200px;
}

.pm-form-inline .pm-btn {
  flex: 0 0 auto;
  height: var(--pm-control-h);
  min-height: var(--pm-control-h);
  padding: 0 26px;
}

/* Form-level feedback. Never a colour other than green/black — a red error
   state would put a fourth hue on the page. Errors are marked by a black
   rule and plain declarative wording instead. */
.pm-notice {
  padding: 14px 16px;
  border-left: 3px solid var(--pm-green);
  background: var(--pm-surface);
  font-size: var(--pm-fs-small);
  line-height: 1.6;
  color: var(--pm-text-quaternary);
  border-radius: var(--pm-radius);
}

.pm-notice--error {
  border-left-color: var(--pm-black);
}

.pm-section--dark .pm-notice,
.pm-footer .pm-notice {
  background: transparent;
  border-left-color: var(--pm-green);
  color: var(--pm-on-dark-muted);
}


/* ---------------------------------------------------------------------------
   10. TABLES
   ---------------------------------------------------------------------------
   Pricing tiers, agendas and sponsorship matrices. Rules only, no zebra fills,
   no rounded corners. Wide tables scroll inside their own container rather
   than making the page scroll sideways.
--------------------------------------------------------------------------- */
.pm-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.pm-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--pm-fs-body-sm);
  line-height: 1.55;
  text-align: left;
}

.pm-table th {
  padding: 14px 16px 12px;
  border-bottom: var(--pm-rule-heavy);
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-18);
  text-transform: uppercase;
  color: var(--pm-black);
  white-space: nowrap;
}

.pm-table td {
  padding: 16px;
  border-bottom: var(--pm-rule-light);
  color: var(--pm-text-quaternary);
  vertical-align: top;
}

.pm-table tbody tr:last-child td {
  border-bottom: 0;
}

.pm-table__num {
  color: var(--pm-black);
  white-space: nowrap;
}

.pm-section--dark .pm-table th {
  color: var(--pm-white);
  border-bottom-color: var(--pm-white);
}

.pm-section--dark .pm-table td {
  color: var(--pm-on-dark-muted);
  border-bottom-color: var(--pm-on-dark-rule);
}


/* ---------------------------------------------------------------------------
   11. SITE HEADER AND NAVIGATION
   ---------------------------------------------------------------------------
   Markup lives in includes/layout/header.php. White background, one hairline
   bottom rule, logo left, nav right, green primary action at the far right.

   The mobile menu is a full-screen white panel, not a dropdown, matching the
   prototype. It is driven by a `data-pm-nav-open` attribute on <html> set by
   a small vanilla script; with JavaScript off the toggle button is hidden and
   the nav list stays in normal flow, so the site is still navigable.
--------------------------------------------------------------------------- */
.pm-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--pm-white);
  padding-inline: var(--pm-gutter);
}

.pm-header__bar {
  display: flex;
  align-items: center;
  gap: clamp(14px, 3vw, 48px);
  min-height: 76px;
  border-bottom: var(--pm-rule);
}

.pm-brand {
  display: flex;
  align-items: center;
  gap: 11px;
  border: 0;
  flex: 0 0 auto;
}

.pm-brand:hover,
.pm-brand:focus-visible {
  border: 0;
}

.pm-brand__mark {
  flex: 0 0 auto;
}

/* The real logo lock-up (shield, neural head and wordmark are all one file).
   Sized by height so the 713x183 source keeps its aspect ratio; width:auto
   stops the intrinsic width attribute from stretching it. The width/height
   attributes stay on the <img> to reserve space and avoid layout shift. */
.pm-brand__logo {
  display: block;
  flex: 0 0 auto;
  height: clamp(30px, 3.4vw, 40px);
  width: auto;
}

.pm-footer .pm-brand__logo {
  height: clamp(28px, 3vw, 34px);
}

.pm-brand__word {
  color: var(--pm-black);
  font-size: clamp(15px, 1.5vw, 18px);
  letter-spacing: var(--pm-ls-16);
  text-transform: uppercase;
  white-space: nowrap;
}

.pm-nav {
  display: flex;
  align-items: center;
  gap: clamp(10px, 2.2vw, 32px);
  margin-left: auto;
  min-width: 0;
}

.pm-nav__link {
  padding: 6px 0;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--pm-text-muted);
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color var(--pm-transition), border-color var(--pm-transition);
}

.pm-nav__link:hover,
.pm-nav__link:focus-visible {
  color: var(--pm-black);
  border-bottom-color: var(--pm-border);
}

.pm-nav__link[aria-current="page"] {
  color: var(--pm-black);
  border-bottom-color: var(--pm-green);
}

.pm-nav__cta {
  flex: 0 0 auto;
  padding: 13px 20px;
  min-height: var(--pm-tap-min);
  font-size: var(--pm-fs-label);
  letter-spacing: 0.1em;
  white-space: nowrap;
}

/* The toggle exists only for small screens and only when JS is available. */
.pm-nav-toggle {
  display: none;
  margin-left: auto;
  padding: 12px 16px;
  min-height: var(--pm-tap-min);
  background: none;
  color: var(--pm-black);
  border: 1px solid var(--pm-black);
  border-radius: var(--pm-radius);
  font-size: var(--pm-fs-label);
  letter-spacing: var(--pm-ls-14);
  text-transform: uppercase;
  cursor: pointer;
}

/* Brand lock-up plus close control, shown only inside the open mobile panel. */
.pm-nav__panel-head {
  display: none;
  align-items: center;
  gap: 11px;
  min-height: 76px;
  border-bottom: var(--pm-rule);
}

.pm-nav__close {
  margin-left: auto;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--pm-black);
  border-radius: var(--pm-radius);
  cursor: pointer;
}

.pm-nav__panel-contact {
  display: none;
}

@media (max-width: 900px) {
  /* Only offer the toggle once the script has confirmed it can run. */
  html[data-pm-js="on"] .pm-nav-toggle {
    display: inline-flex;
  }

  /* display:none, not visibility or opacity: the closed panel must be out of
     the tab order and out of the accessibility tree, not merely invisible. */
  html[data-pm-js="on"] .pm-nav {
    display: none;
  }

  html[data-pm-js="on"][data-pm-nav-open="true"] .pm-nav {
    position: fixed;
    inset: 0;
    z-index: 80;
    display: flex;
    margin: 0;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    padding: 0 20px 28px;
    background: var(--pm-white);
    overflow-y: auto;
  }

  html[data-pm-js="on"] .pm-nav__panel-head {
    display: flex;
    order: -1;
  }

  html[data-pm-js="on"] .pm-nav__link {
    padding: 20px 0;
    min-height: 64px;
    display: flex;
    align-items: center;
    border-bottom: var(--pm-rule);
    color: var(--pm-black);
    font-size: 24px;
    line-height: 1.1;
    letter-spacing: 0.04em;
  }

  html[data-pm-js="on"] .pm-nav__link[aria-current="page"] {
    border-bottom-color: var(--pm-green);
  }

  html[data-pm-js="on"] .pm-nav__cta {
    margin-top: 28px;
    padding: 19px;
    min-height: 52px;
    font-size: 13px;
    letter-spacing: var(--pm-ls-14);
  }

  html[data-pm-js="on"] .pm-nav__panel-contact {
    display: block;
    margin-top: auto;
    padding-top: 32px;
    color: var(--pm-text-quaternary);
    font-size: var(--pm-fs-small);
    line-height: 1.8;
  }

  /* Stop the page scrolling behind an open menu. */
  html[data-pm-nav-open="true"],
  html[data-pm-nav-open="true"] body {
    overflow: hidden;
  }
}


/* ---------------------------------------------------------------------------
   12. SITE FOOTER
   ---------------------------------------------------------------------------
   Markup lives in includes/layout/footer.php. Black band: newsletter row on
   top, then brand + three link/detail columns, then the copyright rule.
--------------------------------------------------------------------------- */
.pm-footer {
  background: var(--pm-black);
  color: var(--pm-white);
  padding: clamp(46px, 6vw, 88px) var(--pm-gutter) clamp(28px, 3vw, 40px);
}

/* Footer links sit undecorated until hovered, so four columns of them do not
   read as a wall of rules. */
.pm-footer a {
  color: var(--pm-on-dark-muted);
  border-bottom: 1px solid transparent;
  transition: color var(--pm-transition), border-color var(--pm-transition);
}

.pm-footer a:hover,
.pm-footer a:focus-visible {
  color: var(--pm-white);
  border-bottom-color: var(--pm-green);
}

.pm-footer__newsletter {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(22px, 3vw, 56px);
  align-items: flex-end;
  padding-bottom: clamp(34px, 4vw, 52px);
  margin-bottom: clamp(34px, 4vw, 52px);
  border-bottom: var(--pm-rule);
}

.pm-footer__newsletter-copy {
  flex: 1 1 300px;
  min-width: 0;
}

.pm-footer__newsletter-copy p {
  color: var(--pm-white);
  font-size: clamp(18px, 2vw, 24px);
  line-height: 1.25;
  max-width: 32ch;
}

.pm-footer__newsletter form {
  flex: 1 1 300px;
  min-width: 0;
}

/* Result message under the newsletter field, on its own line. */
.pm-form-inline .pm-notice {
  flex: 1 1 100%;
  margin: 0;
}

/* The footer's own copy of the brand lock-up: white wordmark, smaller. */
.pm-footer .pm-brand {
  margin-bottom: 18px;
}

.pm-footer .pm-brand__word {
  color: var(--pm-white);
  font-size: 14px;
}

.pm-footer__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: clamp(28px, 4vw, 56px);
}

.pm-footer__col-head {
  display: block;
  color: var(--pm-green);
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-22);
  text-transform: uppercase;
  margin-bottom: 16px;
}

.pm-footer__links {
  display: flex;
  flex-direction: column;
  gap: 11px;
  align-items: flex-start;
}

.pm-footer__links a {
  font-size: var(--pm-fs-small);
}

.pm-footer__detail {
  color: var(--pm-on-dark-muted);
  font-size: var(--pm-fs-small);
  line-height: 1.8;
}

.pm-footer__tagline {
  color: rgba(255, 255, 255, 0.6);
  font-size: var(--pm-fs-small);
  line-height: 1.7;
  max-width: 32ch;
}

.pm-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
  margin-top: clamp(34px, 4vw, 56px);
  padding-top: 24px;
  border-top: 1px solid var(--pm-on-dark-rule);
  color: var(--pm-on-dark-faint);
  font-size: 12.5px;
}

.pm-footer__bottom a {
  color: var(--pm-on-dark-faint);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.pm-footer__bottom a:hover,
.pm-footer__bottom a:focus-visible {
  color: var(--pm-white);
  border-bottom-color: var(--pm-green);
}

/* Consent line under the newsletter field. Deliberately legible rather than
   fine print: consent is the lawful basis for this list, so the wording has to
   be readable at the point of giving it, not hidden at 9px. */
.pm-form-inline__consent {
  flex-basis: 100%;
  margin: 4px 0 0;
  max-width: 52ch;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--pm-on-dark-faint);
}

.pm-form-inline__consent a {
  color: var(--pm-on-dark-muted);
  border-bottom: 1px solid var(--pm-green);
  text-decoration: none;
}

.pm-form-inline__consent a:hover,
.pm-form-inline__consent a:focus-visible {
  color: var(--pm-white);
}


/* ---------------------------------------------------------------------------
   13. UTILITIES
   ---------------------------------------------------------------------------
   A short, closed list. If a page needs a spacing value that is not here, it
   belongs in a component class, not in a new utility.
--------------------------------------------------------------------------- */
.pm-stack     { display: flex; flex-direction: column; }
.pm-stack--xs { gap: 8px; }
.pm-stack--sm { gap: 14px; }
.pm-stack--md { gap: 22px; }
.pm-stack--lg { gap: clamp(28px, 3.5vw, 44px); }

.pm-row {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(20px, 3vw, 48px);
  align-items: flex-start;
}

.pm-row__main { flex: 1 1 320px; min-width: 0; }
.pm-row__side { flex: 1 1 280px; min-width: 0; }

/* A narrow leading column inside a .pm-row for an index: the "01 / DAY 1" mark
   beside each day of an event agenda. Fixed rather than flexible, so the
   numerals line up down the page however long the titles beside them are.
   Added in Phase 3; the same shape suits any numbered step list. */
.pm-row__index {
  flex: 0 0 78px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.pm-mt-0  { margin-top: 0; }
.pm-mt-sm { margin-top: 14px; }
.pm-mt-md { margin-top: 22px; }
.pm-mt-lg { margin-top: clamp(28px, 3.5vw, 44px); }
/* One step above lg, for separating major headings inside a long text page
   (privacy policy, terms, an event agenda) where lg is not enough to read as
   a real section break. */
.pm-mt-xl { margin-top: clamp(44px, 5vw, 72px); }

/* ---------------------------------------------------------------------------
   Lists in body copy
   Long-form pages (policy, agendas, package benefits) need a list that matches
   the body rhythm instead of the browser default. The marker is a green rule
   rather than a bullet glyph, consistent with the eyebrow rule elsewhere.
   --------------------------------------------------------------------------- */
.pm-list {
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

.pm-list > li {
  position: relative;
  padding-left: 26px;
  margin-bottom: 12px;
  font-size: var(--pm-text-body, clamp(15px, 1.5vw, 18px));
  line-height: 1.75;
  color: var(--pm-text-muted);
}

.pm-list > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 12px;
  height: 2px;
  background: var(--pm-green);
}

.pm-list > li:last-child { margin-bottom: 0; }

.pm-measure     { max-width: 62ch; }
.pm-measure--sm { max-width: 48ch; }

.pm-rule { border-top: var(--pm-rule); }

.pm-muted { color: var(--pm-text-muted); }
.pm-green { color: var(--pm-green); }

/* Background motif: the sanctioned neural-node SVG, positioned behind a hero.
   The brief permits the brand's own node/shield motif and forbids generic
   blurred blobs; this is the only decorative background in the system. */
.pm-motif {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0.75;
}

.pm-relative { position: relative; }
.pm-clip { overflow: hidden; }

/* A control that only works with JavaScript, hidden until JavaScript has said
   so. head.php stamps data-pm-js="on" on <html> before first paint, which is
   the same contract .pm-nav-toggle already uses.

   The rule this enforces: never show a visitor a button that will do nothing
   when they press it. The banner library's "Copy link" needs the clipboard API,
   so with scripts off it is absent and the "Download" link beside it, a plain
   <a href> that needs nothing, is still there. */
.pm-js-only { display: none; }

[data-pm-js="on"] .pm-js-only { display: inline-block; }


/* ---------------------------------------------------------------------------
   14. ACCESSIBILITY AND REDUCED MOTION
--------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .pm *,
  .pm *::before,
  .pm *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Windows high-contrast / forced-colours mode: let the OS palette through
   rather than fighting it, but keep the layout rules visible. */
@media (forced-colors: active) {
  .pm-btn,
  .pm-input,
  .pm-select,
  .pm-textarea,
  .pm-card {
    border: 1px solid;
  }
}

@media print {
  .pm-header,
  .pm-nav-toggle,
  .pm-footer__newsletter {
    display: none;
  }

  .pm-section--dark,
  .pm-footer {
    background: var(--pm-white);
    color: var(--pm-black);
  }
}


/* ---------------------------------------------------------------------------
   15. THE REGISTRATION FLOW
   ---------------------------------------------------------------------------
   The steps collapse only under [data-pm-steps="on"], which pm-register.js
   writes onto <html> after it has finished wiring itself up. NOT
   html[data-pm-js]: that flag would still be set if pm-register.js were itself
   the file that failed, leaving four hidden steps behind a dead Continue button
   on the page that takes the money. Undriven, the page is one long form that
   posts on its own, so everything below is state layered on a working document.
--------------------------------------------------------------------------- */

.pm-reg__head {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: baseline;
}

.pm-reg__stepcount {
  margin-left: auto;
  font-size: var(--pm-fs-label);
  letter-spacing: var(--pm-ls-16);
  text-transform: uppercase;
  color: var(--pm-text-tertiary);
}

.pm-reg__progress {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 120px), 1fr));
  gap: clamp(8px, 1.4vw, 20px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.pm-reg__progress-item {
  display: block;
  border-top: 3px solid var(--pm-border-light);
  padding-top: 12px;
  color: var(--pm-text-tertiary);
  text-align: left;
  background: none;
  border-left: 0;
  border-right: 0;
  border-bottom: 0;
  width: 100%;
}

.pm-reg__progress-item[data-pm-state="current"] {
  border-top-color: var(--pm-green);
  color: var(--pm-black);
}

.pm-reg__progress-item[data-pm-state="done"] {
  border-top-color: var(--pm-black);
  color: var(--pm-black);
}

.pm-reg__progress-num {
  display: block;
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-16);
  margin-bottom: 6px;
}

.pm-reg__progress-name {
  display: block;
  font-size: 13px;
  line-height: 1.35;
}

/* -- The two columns ------------------------------------------------------ */
.pm-reg__aside {
  flex: 0 1 340px;
  min-width: min(100%, 280px);
}

/* Clears the sticky site header. Only above the width where the aside still
   sits beside the form; stacked, it would pin itself over the fields. */
@media (min-width: 900px) {
  .pm-reg__sticky {
    position: sticky;
    top: 116px;
  }
}

/* -- The invoice summary panel -------------------------------------------- */
.pm-reg__summary {
  border: 1px solid var(--pm-black);
  border-radius: var(--pm-radius);
  padding: clamp(22px, 2.4vw, 30px);
  background: var(--pm-white);
}

.pm-reg__summary-head {
  display: block;
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-22);
  text-transform: uppercase;
  color: var(--pm-black);
  padding-bottom: 16px;
  border-bottom: var(--pm-rule-heavy);
}

.pm-reg__line {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding: 18px 0;
  border-bottom: var(--pm-rule-light);
}

.pm-reg__line-label {
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--pm-text-muted);
}

.pm-reg__line-value {
  font-size: 14.5px;
  color: var(--pm-black);
  white-space: nowrap;
}

.pm-reg__total {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  align-items: baseline;
  padding-top: 20px;
}

.pm-reg__total-label {
  font-size: var(--pm-fs-label);
  letter-spacing: var(--pm-ls-16);
  text-transform: uppercase;
  color: var(--pm-black);
}

.pm-reg__total-value {
  font-size: clamp(20px, 2.4vw, 28px);
  color: var(--pm-black);
  white-space: nowrap;
}

/* -- One step ------------------------------------------------------------- */
.pm-reg__panel {
  display: block;
  padding-top: clamp(28px, 3vw, 40px);
}

.pm-reg__panel:first-of-type {
  padding-top: 0;
}

/* -- The delegate counter ------------------------------------------------- */
.pm-reg__stepper {
  display: none;
  align-items: center;
  gap: 2px;
}

.pm-reg__stepper-btn {
  width: 52px;
  height: 52px;
  border: 1px solid var(--pm-black);
  border-radius: var(--pm-radius);
  background: var(--pm-white);
  color: var(--pm-black);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--pm-transition), color var(--pm-transition);
}

.pm-reg__stepper-btn:hover {
  background: var(--pm-black);
  color: var(--pm-white);
}

.pm-reg__stepper-btn[disabled] {
  border-color: var(--pm-border);
  color: var(--pm-border);
  cursor: default;
}

.pm-reg__stepper-btn[disabled]:hover {
  background: var(--pm-white);
  color: var(--pm-border);
}

.pm-reg__stepper-value {
  min-width: 72px;
  height: 52px;
  border-top: 1px solid var(--pm-black);
  border-bottom: 1px solid var(--pm-black);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;
  color: var(--pm-black);
}

/* -- One delegate ---------------------------------------------------------- */
.pm-reg__delegate-head {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: baseline;
}

.pm-reg__delegate-note {
  margin-left: auto;
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-16);
  text-transform: uppercase;
  color: var(--pm-text-tertiary);
}

/* -- Review rows ----------------------------------------------------------- */
.pm-reg__review {
  border: var(--pm-rule-light);
  border-radius: var(--pm-radius);
}

.pm-reg__review-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  padding: 20px clamp(18px, 2.2vw, 26px);
  border-bottom: var(--pm-rule-light);
}

.pm-reg__review-row:last-child {
  border-bottom: 0;
}

.pm-reg__review-label {
  flex: 0 0 120px;
  font-size: var(--pm-fs-label);
  letter-spacing: var(--pm-ls-16);
  text-transform: uppercase;
  color: var(--pm-text-muted);
}

.pm-reg__review-value {
  flex: 1 1 200px;
  font-size: 15px;
  line-height: 1.5;
  color: var(--pm-black);
}

/* -- Step navigation ------------------------------------------------------- */
.pm-reg__nav {
  display: none;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: clamp(30px, 3.4vw, 44px);
  padding-top: 26px;
  border-top: var(--pm-rule-light);
}

.pm-reg__nav-next {
  margin-left: auto;
}

/* -- Confirmation ---------------------------------------------------------- */
.pm-reg__done-head {
  display: flex;
  align-items: center;
  gap: 12px;
}

.pm-reg__done-mark {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  border: 1px solid var(--pm-green);
  color: var(--pm-green);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
}

.pm-reg__done-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
  gap: 1px;
  background: var(--pm-on-dark-rule);
}

.pm-reg__done-cell {
  background: var(--pm-black);
  padding: 18px;
}

.pm-reg__done-label {
  display: block;
  font-size: var(--pm-fs-eyebrow);
  letter-spacing: var(--pm-ls-16);
  text-transform: uppercase;
  color: var(--pm-on-dark-faint);
  margin-bottom: 8px;
}

.pm-reg__done-value {
  display: block;
  font-size: 20px;
  color: var(--pm-white);
}

.pm-reg__done-value--green {
  color: var(--pm-green);
}

/* -- The driven state ------------------------------------------------------ */
[data-pm-steps="on"] .pm-reg__panel {
  display: none;
}

[data-pm-steps="on"] .pm-reg__panel[data-pm-current] {
  display: block;
  padding-top: 0;
}

[data-pm-steps="on"] .pm-reg__nav,
[data-pm-steps="on"] .pm-reg__stepper {
  display: flex;
}

.pm-reg__undriven {
  display: block;
}

[data-pm-steps="on"] .pm-reg__undriven,
[data-pm-steps="on"] .pm-reg__driven-hide {
  display: none;
}

.pm-reg__stepcount {
  display: none;
}

[data-pm-steps="on"] .pm-reg__stepcount {
  display: block;
}

/* The UA's [hidden] rule is type-level, so .pm-card { display: flex } and its
   like beat it. The confirmation panel must stay hidden until the server has
   confirmed a commit, so this has to win. */
[hidden] {
  display: none !important;
}

.pm-footer__social {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}

.pm-footer__social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 2px;
  color: rgba(255, 255, 255, 0.72);
}

.pm-footer__social a:hover { border-color: var(--pm-green); color: var(--pm-green); }
