/* RSEF forum: the design system, in a file the browser can keep.
 *
 * These 34 KB of rules used to be an inline <style> block in base.html.
 * Inline CSS is never cached, so every navigation re-sent the whole
 * design system unchanged -- and a visitor reading the agenda, the
 * speakers and the FAQ paid for it three times.
 *
 * As a hashed {% static %} path it is immutable for a year: fetched on
 * the first page, free on every page after it.
 *
 * Rules that belong to ONE page stay in that page's {% block extra_css %},
 * which still renders inline. Those are small and genuinely per-page.
 */
/* ══════════════════════════════════════════════════════════════════════
   RSEF: one design system, defined once.

   The palette is the flag of Rwanda, used as a national palette rather than
   as bunting. The sky blue is taken down to 13% lightness at its own hue and
   becomes the dark ground; the yellow stays at full strength and is the one
   colour that means "act here"; the green is kept for what has gone right.

   Three saturated colours competing on one screen is a football kit, not a
   national platform, so the discipline is fixed and not negotiable per page:

     paper and ink hold the page   -- neutrals are still 90% of every screen
     blue holds the structure      -- ground, links, focus, active state
     yellow appears once           -- the single action that matters here
     green only confirms           -- success, and nothing else
     the flag rule brackets it     -- see --flag, used exactly twice

   No gradients that announce themselves, no glass, no card grids of cards.
   The page is held together by type, rule lines and space, not by boxes.
   ══════════════════════════════════════════════════════════════════════ */
:root{
  /* ── The flag, exactly as specified. ────────────────────────────────────
     These three are never touched in place. Where one of them cannot carry
     text, or cannot be seen against the dark ground, a DERIVED token below
     does that job and says so -- which is what keeps the real flag colours
     from being quietly muddied into approximations of themselves. */
  --rw-blue:#00a1de;      /* happiness and peace */
  --rw-yellow:#fad201;    /* economic development */
  --rw-green:#20603d;     /* hope of prosperity */

  --ink:#0b1220;          /* near black: headings */
  --ink-2:#1b2436;        /* body */
  --ink-3:#5a6478;        /* secondary */
  /* #8a93a6 measured 3.09:1 on white -- well under the 4.5 AA needs for the
     small bold text this token is used for (.eyebrow-quiet, table captions,
     the agenda's "where" line). Darkened to clear it on both the white and
     the off-white surface. Still reads as the quiet tone next to --ink-3. */
  --ink-4:#697285;        /* quiet */
  /* The flag blue at depth: same hue, 13% lightness. The dark ground of this
     site is the flag's own blue rather than a generic navy. 14.9:1 on white. */
  --deep:#062a3d;
  --deep-2:#0b3b53;
  --line:#e3e6ec;
  --line-2:#eef0f4;
  --paper:#ffffff;
  --paper-2:#f7f8fa;
  /* The blue that is allowed to carry text on paper. --rw-blue measures 2.9:1
     on white, under the 4.5:1 AA wants of an 11px eyebrow or a 14px link, so
     every blue that IS text uses this one at 4.9:1. Two blues means the flag
     blue itself stays at full strength wherever it is only a shape. */
  --blue-ink:#0079a8;
  --blue-soft:rgba(0,161,222,.10);
  /* What sits ON the yellow: 10.2:1. The yellow never carries white -- white
     on #fad201 is 1.5:1, which is not a contrast failure so much as an
     invisible button. */
  --on-yellow:#062a3d;
  --yellow-2:#e8c400;     /* the yellow pressed: hover only, never text */
  --ok:#20603d;           /* the flag green as it stands, 7.5:1 on paper */
  --ok-soft:rgba(32,96,61,.10);
  --warn:#8a5a00;
  --bad:#a8322b;
  /* ── The flag rule ──────────────────────────────────────────────────────
     The flag as a proportion rather than a picture: blue over half of it,
     yellow and green a quarter each, in flag order. This is the one piece of
     national decoration on the site and it is used exactly twice -- a 3px
     strip along the top of the sticky header and another along the top of the
     footer -- so that it brackets every page. Used a third time it stops
     being a signature and becomes a pattern; resist that. */
  --flag:linear-gradient(90deg,var(--rw-blue) 0 50%,var(--rw-yellow) 50% 75%,var(--rw-green) 75% 100%);
  --radius:4px;           /* almost square: rounded corners read as consumer */
  --shadow:0 1px 2px rgba(11,18,32,.05);
  --wrap:1160px;
  --font:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
}
*,*::before,*::after{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;}
body{margin:0;font-family:var(--font);color:var(--ink-2);background:var(--paper);
  font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased;}
img{max-width:100%;height:auto;display:block;}
a{color:inherit;text-decoration:none;}
h1,h2,h3,h4{margin:0;color:var(--ink);font-weight:700;letter-spacing:-.02em;line-height:1.15;}
p{margin:0 0 1rem;}
p:last-child{margin-bottom:0;}
hr{border:0;border-top:1px solid var(--line);margin:0;}
::selection{background:var(--blue-soft);}
:focus-visible{outline:2px solid var(--rw-blue);outline-offset:3px;}

/* Horizontal padding as longhand, never the `padding:0 1.5rem` shorthand:
   the shorthand also declares vertical padding 0, and elements that carry
   .wrap alongside a layout class (.hero-in) set their own vertical rhythm.
   With the shorthand, whichever rule came last silently flattened it. */
.wrap{max-width:var(--wrap);margin:0 auto;padding-left:1.5rem;padding-right:1.5rem;}
.skip{position:absolute;left:-9999px;top:0;background:var(--deep);color:#fff;padding:.7rem 1rem;z-index:200;}
.skip:focus{left:0;}

/* ── Type scale ── */
.display{font-size:clamp(2.4rem,6vw,4.2rem);line-height:1.03;letter-spacing:-.035em;font-weight:800;}
.h1{font-size:clamp(1.9rem,3.6vw,2.9rem);letter-spacing:-.03em;}
.h2{font-size:clamp(1.45rem,2.4vw,2rem);letter-spacing:-.025em;}
.h3{font-size:1.12rem;}
/* No measure, like every other text block: running text fills the content
   column and ends on the same right edge as the rules.

   text-wrap:pretty, NOT balance. Balance shortens every line to equalise them,
   which pulls the paragraph away from the right edge -- the opposite of what is
   wanted here. Pretty keeps lines full and only intervenes to stop the last
   line being a single stranded word, which is what made the full-width
   standfirst look broken in the first place. */
.lede{font-size:clamp(1.02rem,1.5vw,1.2rem);color:var(--ink-3);line-height:1.55;
  max-width:none;text-wrap:pretty;}
.eyebrow{font-size:.72rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--blue-ink);}
.eyebrow-quiet{color:var(--ink-4);}
.muted{color:var(--ink-3);}
.small{font-size:.85rem;}

/* ── Header ── */
.hdr{position:sticky;top:0;z-index:80;background:rgba(255,255,255,.94);
  backdrop-filter:saturate(1.4) blur(8px);}
.hdr::after{content:'';position:absolute;left:var(--edge);right:var(--edge);bottom:0;
  height:1px;background:var(--line);}
/* The flag rule, and the one thing on the page that is deliberately full
   bleed. Every other rule stops at the content edge (see --edge); this one is
   a ribbon across the top of the window, not a divider inside the column, and
   inset by a gutter it would read as a stray coloured line. The header is
   sticky, so it stays at the top of the screen for the whole visit. */
.hdr::before{content:'';position:absolute;left:0;right:0;top:0;height:3px;
  background:var(--flag);z-index:1;}
.hdr-in{display:flex;align-items:center;justify-content:space-between;gap:1.5rem;height:70px;}
.brand{display:flex;align-items:center;gap:.7rem;min-width:0;}
.brand img{width:30px;height:30px;}
.brand-name{font-weight:800;font-size:1.02rem;color:var(--ink);letter-spacing:-.01em;}
.nav{display:flex;align-items:center;gap:1.9rem;}
.nav a{font-size:.9rem;font-weight:500;color:var(--ink-2);padding:.4rem 0;position:relative;}
.nav a:hover{color:var(--ink);}
.nav a.is-on{color:var(--ink);font-weight:600;}
.nav a.is-on::after{content:'';position:absolute;left:0;right:0;bottom:-2px;height:2px;background:var(--rw-blue);}
.hdr-cta{display:flex;align-items:center;gap:.8rem;}

/* ── Buttons ── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  font:inherit;font-size:.9rem;font-weight:600;letter-spacing:.01em;
  padding:.78rem 1.4rem;border-radius:var(--radius);border:1px solid transparent;
  cursor:pointer;transition:background .15s ease,border-color .15s ease,color .15s ease;
  white-space:nowrap;}
.btn-primary{background:var(--deep);color:#fff;}
.btn-primary:hover{background:var(--deep-2);}
/* The flag yellow at full strength with deep-blue ink on it, 10.2:1. This is
   the only saturated fill on a light page and there should be one of it in
   view at a time: it is what "the thing to do here" looks like. */
.btn-accent{background:var(--rw-yellow);color:var(--on-yellow);}
.btn-accent:hover{background:var(--yellow-2);}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--line);}
.btn-ghost:hover{border-color:var(--ink-4);}
.btn-light{background:#fff;color:var(--ink);}
.btn-light:hover{background:#f1f2f5;}
.btn-outline-light{background:transparent;color:#fff;border-color:rgba(255,255,255,.34);}
.btn-outline-light:hover{border-color:#fff;}
.btn-sm{padding:.5rem .9rem;font-size:.83rem;}
.btn-block{width:100%;}
.link-more{color:var(--blue-ink);font-weight:600;font-size:.9rem;display:inline-flex;align-items:center;gap:.4rem;}
.link-more:hover{text-decoration:underline;}

/* ── Sections ── */
.sec{padding:clamp(3.4rem,7vw,6rem) 0;}
.sec-tight{padding:clamp(2.4rem,4vw,3.4rem) 0;}
/* ── Rules stop where the content stops ───────────────────────────────────
   Every horizontal rule used to be full-bleed while the page it divides is
   bounded by .wrap, so the lines were the only element that ignored the content
   column. --edge is the same arithmetic .wrap does -- half the leftover gutter
   plus .wrap's own padding -- so a rule now starts under the logo and ends
   under the header's primary button. Keep --edge in step with --wrap and with
   .wrap's padding, including the phone override further down. */
.hdr,.sec-line{--edge:max(1.5rem,calc((100% - var(--wrap)) / 2 + 1.5rem));}
.sec-line{position:relative;}
.sec-line::before{content:'';position:absolute;left:var(--edge);right:var(--edge);top:0;
  height:1px;background:var(--line);}
.sec-dark{background:var(--deep);color:#e8ecf3;}
.sec-dark h1,.sec-dark h2,.sec-dark h3{color:#fff;}
.sec-dark .muted{color:#9fb0c8;}
.sec-paper{background:var(--paper-2);}
/* No measure cap on running text. The page is a single column bounded by
   .wrap, and the section rules span all of it; a 60ch paragraph inside that
   stopped 512px short of the rule above it, so the block read as misaligned
   rather than as a comfortable measure. Every text block now ends on the same
   right edge as the rules and the figures. */
.sec-head{max-width:none;margin-bottom:2.6rem;}
.sec-head .eyebrow{display:block;margin-bottom:.8rem;}
.sec-head p{margin-top:.9rem;}

/* ── Quotation ──
   One statement of the national mandate, set large and given room. Not a card,
   not a decorative panel: a rule, the words, and who said them and when. The
   attribution carries the occasion and the date because a quotation from a head
   of state without its source is just a slogan. */
/* margin:0 is not cosmetic: <figure> carries a browser default of
   `margin:1em 40px`, which indented the whole quotation past the page
   gutter on every screen. */
.quote{margin:0;max-width:54rem;display:grid;grid-template-columns:clamp(6rem,10vw,7.5rem) minmax(0,1fr);
  gap:clamp(1.2rem,2.6vw,2rem);align-items:start;}
/* .3rem drops the top of the frame to the cap height of the first line. Without
   it the image aligns with the line BOX, which sits above the letters, and the
   portrait reads as floating a few pixels high. */
.quote-portrait{width:100%;height:auto;aspect-ratio:4/5;object-fit:cover;
  margin-top:.3rem;border:1px solid var(--line);}
/* Reading size, not display size. A pull quote set at 2rem shouts over the
   headline it sits beneath; at body-plus it reads as a statement of record,
   which is what a quotation from a head of state should look like. */
.quote blockquote{margin:0;
  font-size:clamp(1.05rem,1.5vw,1.22rem);line-height:1.6;letter-spacing:-.005em;
  font-weight:500;color:var(--ink);}
.quote figcaption{margin-top:1.6rem;font-size:.88rem;color:var(--ink-3);line-height:1.6;}
.quote .quote-who{display:block;font-weight:700;color:var(--ink);font-size:.95rem;}
.quote .quote-src{display:block;color:var(--ink-4);}
.quote .quote-src a{text-decoration:underline;}
/* The portrait keeps its place BESIDE the words on a phone. Stacking it put a
   band of face above a band of text and cost ~170px of scroll for a single
   sentence. It only fits because the quotation steps down to .92rem/1.5 here:
   at the desktop 1.05rem the line broke every three words against a 6rem
   portrait. The attribution rides in the same right-hand column (figure has two
   children -- the img and a div holding blockquote + figcaption -- so the grid
   is genuinely two columns, not three items wrapping). */
@media (max-width:700px){
  .quote{grid-template-columns:clamp(4.5rem,21vw,6rem) minmax(0,1fr);gap:.9rem;}
  .quote-portrait{width:100%;margin-top:.2rem;}
  .quote blockquote{font-size:.92rem;line-height:1.5;letter-spacing:0;}
  .quote figcaption{margin-top:.85rem;font-size:.78rem;line-height:1.5;}
  .quote .quote-who{font-size:.82rem;}
}

/* ── Hero ── */
/* A light hero. The first thing a visitor meets is daylight rather than a
   dark slab: the deep blue still carries the brand, but it arrives lower down
   in the footer and on the dark section rules, where it reads as weight rather
   than as a wall. The tint is the flag blue at its palest -- the sky end of
   the same colour the footer is the night end of -- so the page is bright
   without introducing a colour the identity does not already own. */
.hero{position:relative;overflow:hidden;color:var(--ink-2);
  background:linear-gradient(168deg,#fbfdff 0%,#eff7fc 48%,#dcedf8 100%);}
/* A single soft bloom of the flag blue, off to the side the text leaves
   empty. Depth without a gradient that announces itself. */
.hero::before{content:'';position:absolute;z-index:0;right:-12%;top:-30%;
  width:70%;padding-bottom:70%;border-radius:50%;
  background:radial-gradient(circle,rgba(0,161,222,.20) 0%,rgba(0,161,222,0) 68%);}
/* Holds the hero apart from the white section beneath it. */
.hero{border-bottom:1px solid rgba(0,161,222,.34);}
.hero-media{position:absolute;inset:0;z-index:1;}
.hero-media img{width:100%;height:100%;object-fit:cover;opacity:.5;}
/* The scrim belongs to the photograph, not to the hero. It used to be
   .hero::after, which painted over EVERYTHING at up to 97% opacity -- including
   the bars, which are a sibling at the same z-index and are drawn before a
   pseudo-element. That is why they looked like washed-out grey boxes: they were
   being covered by a sheet of near-white paper. Scoped here it only appears in
   the case it exists for, which is dark text over an uploaded image. */
.hero-media::after{content:'';position:absolute;inset:0;
  background:linear-gradient(90deg,rgba(250,253,255,.97) 0%,rgba(250,253,255,.9) 45%,rgba(250,253,255,.62) 100%);}
/* The identity's four bars, large and quiet, on the side the text leaves
   empty. Not an illustration and not stock conference photography: it is the
   one graphic device this brand has, and it steps aside the moment a real
   photograph is uploaded. */
/* The bars' right edge sits on the SAME line as the header's primary button,
   i.e. the .wrap content edge: half the leftover gutter
   plus .wrap's own 1.5rem. Below 1160px the leftover goes negative and max()
   falls back to the plain gutter, which is exactly what .wrap does. Keep this
   in step with --wrap (1160px -> 580px) and .wrap's padding. */
.hero-figure{position:absolute;bottom:0;z-index:1;height:auto;
  width:min(27.54%,340px);   /* = 34% / 420px scaled by the 162/200 viewBox trim */
  right:max(1.5rem,calc((100% - var(--wrap)) / 2 + 1.5rem));}
/* Vertical padding only. This element also carries .wrap, and a three-value
   `padding` shorthand would reset .wrap's horizontal padding to 0 -- which
   is what pinned the headline, the meta row and both buttons hard against
   the left edge of every phone. */
.hero-in{position:relative;z-index:2;width:100%;
  padding-top:clamp(2.6rem,7vw,4.2rem);padding-bottom:clamp(2.6rem,6vw,4rem);}

/* ── The fold ─────────────────────────────────────────────────────────────
   On a computer the hero is exactly one screenful: its bottom edge, and so the
   bottom edge of the bars anchored to it, lands on the fold. A visitor sees the
   whole proposition -- name, line, facts, both actions and the full mark --
   without scrolling, and the cut at the bottom of the screen reads as the end
   of a section rather than as content sliced in half.

   min-height rather than height, so a long headline or an extra venue row grows
   the section instead of spilling out of it. svh rather than vh because on a
   laptop with a chrome-heavy browser vh can exceed what is actually visible.
   The 70px is .hdr-in's height; keep the two in step.

   One screenful is right on a laptop and wrong on a desktop monitor. At
   1920x1080 the full viewport stretched the hero to ~1010px and the bars --
   anchored bottom:0 -- were dragged down with it, leaving a dead band of paper
   between the buttons and the mark. Above the laptop range the hero is
   therefore capped at 38rem (608px) and the bars come back up level with the
   meta row.

   The cap is gated on HEIGHT as well as width, because height is what actually
   causes the stretch: >=1200px wide AND >=940px tall. Every common laptop
   viewport (768, 800 and 900px tall) misses that gate and keeps precisely the
   one-screenful fold it had; 1080p and taller monitors get the cap. Move the
   940px only with a screenshot in hand. */
@media (min-width:901px){
  /* flex-start, not center. Centring split the spare height evenly and left a
     void above the headline as tall as the headline itself; starting high puts
     the words where the eye lands and gives the rest of the screen to the mark,
     which is the half that was invisible before. */
  .hero{display:flex;align-items:flex-start;min-height:calc(100svh - 70px);}
  .hero-in{padding-top:clamp(3rem,8vh,5.5rem);padding-bottom:clamp(2.5rem,5vh,4rem);}
}
@supports not (height:100svh){
  @media (min-width:901px){ .hero{min-height:calc(100vh - 70px);} }
}
/* Beyond the laptop range, stop chasing the bottom of the window. */
@media (min-width:1200px) and (min-height:940px){
  .hero{min-height:min(calc(100svh - 70px),38rem);}
}
@supports not (height:100svh){
  @media (min-width:1200px) and (min-height:940px){
    .hero{min-height:min(calc(100vh - 70px),38rem);}
  }
}
.hero h1{color:var(--ink);max-width:16ch;}
.hero-tag{margin-top:1.3rem;font-size:clamp(1.05rem,1.9vw,1.35rem);color:var(--ink-3);font-weight:400;max-width:34ch;}
.hero-meta{display:flex;flex-wrap:wrap;gap:2.2rem;margin-top:2.6rem;padding-top:1.7rem;
  border-top:1px solid rgba(11,18,32,.14);max-width:44rem;}
/* --ink-3, not the quieter --ink-4: at 11px uppercase on the warm hero the
   lighter grey measures 2.7:1, and AA wants 4.5:1. This is 5.2:1. */
.hero-meta dt{font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3);font-weight:600;margin-bottom:.35rem;}
.hero-meta dd{margin:0;font-size:1rem;font-weight:600;color:var(--ink);}
.hero-actions{display:flex;flex-wrap:wrap;gap:.8rem;margin-top:2.4rem;}

/* ── Pillars: numbered rules, not cards ── */
.pillars{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:0;}
.pillar{padding:1.9rem 1.6rem 1.9rem 0;border-top:1px solid var(--line);}
.pillar+.pillar{padding-left:1.6rem;border-left:1px solid var(--line);}
.pillar-n{font-size:.72rem;font-weight:700;letter-spacing:.16em;color:var(--blue-ink);margin-bottom:.9rem;}
.pillar h3{font-size:1.16rem;margin-bottom:.45rem;}
.pillar p{color:var(--ink-3);font-size:.93rem;margin:0;}

/* ── Speakers ── */
.people{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:2rem 1.6rem;}
.person{display:block;}
.person-img{aspect-ratio:4/5;background:var(--paper-2);border:1px solid var(--line);
  overflow:hidden;margin-bottom:.95rem;position:relative;}
.person-img img{width:100%;height:100%;object-fit:cover;transition:transform .5s ease;}
a.person:hover .person-img img{transform:scale(1.03);}
.person-ini{position:absolute;inset:0;display:grid;place-items:center;
  font-size:1.9rem;font-weight:700;color:var(--ink-4);letter-spacing:.04em;}
.person-name{font-weight:700;color:var(--ink);font-size:1rem;letter-spacing:-.01em;}
.person-role{font-size:.86rem;color:var(--ink-3);margin-top:.18rem;line-height:1.4;}
.person-org{font-size:.86rem;color:var(--ink);font-weight:600;margin-top:.1rem;}

/* ── Agenda ── */
.day-tabs{display:flex;gap:.4rem;flex-wrap:wrap;margin-bottom:2rem;}
.day-tab{padding:.6rem 1rem;border:1px solid var(--line);font-size:.86rem;font-weight:600;color:var(--ink-3);}
.day-tab.is-on{background:var(--deep);border-color:var(--deep);color:#fff;}
.agenda{border-top:1px solid var(--ink);}
.slot{display:grid;grid-template-columns:8.5rem 1fr;gap:1.6rem;padding:1.5rem 0;border-bottom:1px solid var(--line);}
.slot-time{font-variant-numeric:tabular-nums;font-weight:600;color:var(--ink);font-size:.92rem;padding-top:.1rem;}
.slot-kind{font-size:.7rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--blue-ink);margin-bottom:.4rem;}
.slot h3{font-size:1.08rem;margin-bottom:.3rem;}
.slot-desc{font-size:.92rem;color:var(--ink-3);margin:.4rem 0 0;max-width:none;}
.slot-people{margin-top:.6rem;display:flex;flex-wrap:wrap;gap:.4rem 1rem;font-size:.87rem;}
.slot-people a{color:var(--ink);font-weight:600;}
.slot-people a:hover{color:var(--rw-blue);}
.slot-where{font-size:.83rem;color:var(--ink-4);margin-top:.4rem;}

/* ── Partners ── */
.tier{margin-bottom:3rem;}
.tier-name{font-size:.72rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;
  color:var(--ink-4);padding-bottom:.8rem;border-bottom:1px solid var(--line);margin-bottom:1.6rem;}
.logos{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:1.6rem;align-items:center;}
.logo-cell{height:96px;display:grid;place-items:center;padding:1rem;border:1px solid var(--line-2);background:#fff;}
.logo-cell img{max-height:56px;width:auto;object-fit:contain;filter:grayscale(1);opacity:.82;transition:filter .2s ease,opacity .2s ease;}
.logo-cell:hover img{filter:none;opacity:1;}
.logo-word{font-weight:700;color:var(--ink-3);text-align:center;font-size:.95rem;letter-spacing:-.01em;}

/* ── Forms ── */
.form{max-width:44rem;}
.f-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));gap:1.1rem 1.4rem;}
.f{display:flex;flex-direction:column;gap:.42rem;min-width:0;}
.f-full{grid-column:1/-1;}
.f label{font-size:.82rem;font-weight:600;color:var(--ink);}
.f .req{color:var(--blue-ink);margin-left:.15rem;}
.f input[type=text],.f input[type=email],.f input[type=tel],.f input[type=url],
.f input[type=date],.f input[type=time],.f input[type=number],.f select,.f textarea{
  font:inherit;font-size:.94rem;color:var(--ink);background:#fff;
  border:1px solid var(--line);border-radius:var(--radius);padding:.72rem .85rem;width:100%;
  transition:border-color .15s ease,box-shadow .15s ease;}
.f input:focus,.f select:focus,.f textarea:focus{outline:none;border-color:var(--rw-blue);
  box-shadow:0 0 0 3px var(--blue-soft);}
.f textarea{resize:vertical;min-height:5.5rem;}
.f-help{font-size:.8rem;color:var(--ink-4);}
.f-err{font-size:.82rem;color:var(--bad);font-weight:500;display:flex;align-items:flex-start;gap:.35rem;}
.f-check{display:flex;gap:.7rem;align-items:flex-start;font-size:.9rem;color:var(--ink-2);}
.f-check input{margin-top:.25rem;width:1rem;height:1rem;accent-color:var(--rw-blue);flex:none;}
.f-trap{position:absolute!important;left:-9999px!important;width:1px!important;height:1px!important;opacity:0!important;}
.f-section{margin-top:2.4rem;padding-top:1.6rem;border-top:1px solid var(--line);}
.f-section:first-child{margin-top:0;padding-top:0;border-top:0;}
.f-section-title{font-size:.72rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-4);margin-bottom:1.2rem;}
.f-actions{margin-top:2rem;display:flex;gap:.8rem;align-items:center;flex-wrap:wrap;}
.alert{padding:.9rem 1.1rem;border:1px solid var(--line);border-left:3px solid var(--ink);
  background:var(--paper-2);font-size:.9rem;margin-bottom:1.6rem;}
.alert-bad{border-left-color:var(--bad);color:#7d241e;background:#fdf5f4;border-color:#f3d9d6;}
.alert-ok{border-left-color:var(--ok);background:#f4faf6;border-color:#d5e9dc;}

/* ── Confirmation ── */
.confirm{max-width:40rem;}
.confirm-mark{width:46px;height:46px;border-radius:50%;background:var(--ok-soft);
  color:var(--ok);display:grid;place-items:center;font-size:1.1rem;margin-bottom:1.5rem;}
.ref{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:1.15rem;font-weight:700;
  letter-spacing:.06em;color:var(--ink);}
.detail-rows{margin:2rem 0 0;border-top:1px solid var(--line);}
.detail-row{display:flex;justify-content:space-between;gap:2rem;padding:.9rem 0;
  border-bottom:1px solid var(--line-2);font-size:.94rem;}
.detail-row dt{color:var(--ink-3);}
.detail-row dd{margin:0;font-weight:600;color:var(--ink);text-align:right;}

/* ── Small pieces ── */
.tag{display:inline-flex;align-items:center;gap:.35rem;font-size:.7rem;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;padding:.3rem .6rem;border:1px solid var(--line);
  color:var(--ink-3);}
.tag-accent{border-color:rgba(0,161,222,.4);color:var(--blue-ink);background:var(--blue-soft);}
.empty{padding:3rem 0;text-align:center;color:var(--ink-3);border-top:1px solid var(--line);}
.empty h3{margin-bottom:.5rem;}
.prose{max-width:none;}
.prose h2{margin:2.2rem 0 .8rem;font-size:1.3rem;}
.prose h3{margin:1.6rem 0 .6rem;}
.prose ul{margin:0 0 1rem;padding-left:1.2rem;}
.prose li{margin-bottom:.4rem;}
/* Links inside running text have to look like links. The global `a` rule is
   color:inherit + no underline, which is right for navigation and cards, where
   the whole block is the target, and wrong inside a paragraph, where nothing
   else marks the word. Blue-ink, not the flag blue: 4.9:1 on paper, and this
   blue is carrying text. */
.prose a{color:var(--blue-ink);text-decoration:underline;text-underline-offset:.15em;
  text-decoration-thickness:1px;}
.prose a:hover{color:var(--ink);}

/* ── Footer ── */
.ftr{position:relative;background:var(--deep);color:#93a5bd;padding:3.4rem 0 2rem;font-size:.9rem;}
/* The other end of the bracket. Same strip, same proportions, closing the
   page the way the header opens it. */
.ftr::before{content:'';position:absolute;left:0;right:0;top:0;height:3px;
  background:var(--flag);}
.ftr-top{display:flex;flex-wrap:wrap;justify-content:space-between;gap:2.4rem;padding-bottom:2.4rem;
  border-bottom:1px solid rgba(255,255,255,.1);}
.ftr-brand{max-width:34rem;}
.ftr-brand .brand-name{color:#fff;}
/* The bars sit low inside their 64-unit tile, so an invisible plate leaves the
   mark optically below the word it stands beside. -2px puts them level. */
.ftr-lockup img{margin-top:-2px;}
.ftr-brand p{margin-top:.7rem;color:#93a5bd;font-size:.88rem;}
.ftr-cols{display:flex;flex-wrap:wrap;gap:3rem;}
/* #6f829c on the footer's #062a3d came to 3.8:1. These two are the only
   places the footer states anything a visitor has to read rather than click,
   so they get a tone that clears AA against the dark ground. */
.ftr-col h2{font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;color:#8fa0b6;margin-bottom:.9rem;font-weight:700;}
.ftr-col a{display:block;color:#c3cfdf;padding:.24rem 0;font-size:.9rem;}
.ftr-col a:hover{color:#fff;}
.ftr-btm{padding-top:1.6rem;display:flex;flex-wrap:wrap;gap:1rem;justify-content:space-between;font-size:.82rem;color:#8fa0b6;}
.ftr-social{display:flex;gap:1.1rem;}
.ftr-social a{color:#93a5bd;}
.ftr-social a:hover{color:#fff;}

/* ── Mobile ── */
.burger{display:none;width:42px;height:42px;border:1px solid var(--line);background:#fff;
  align-items:center;justify-content:center;cursor:pointer;color:var(--ink);border-radius:var(--radius);}
/* Visually hidden, not display:none: a checkbox that cannot be focused is a
   menu that cannot be opened from a keyboard. */
.mnav-toggle{position:absolute;opacity:0;width:1px;height:1px;}
/* Hidden at every width by default. Declared only inside the 900px query, it
   rendered as a second navigation row across every desktop page. */
.mnav{display:none;}
@media (max-width:900px){
  .hero-figure{width:51.84%;right:-6%;}   /* 64% scaled by the 162/200 viewBox trim */
  .hdr-in{height:62px;}
  .nav{display:none;}
  .hdr-cta .btn:not(.burger){display:none;}
  .burger{display:flex;}
  /* The menu is a checkbox and a label: no JavaScript, and it cannot be left
     open by a script that failed to load. */
  .mnav{border-top:1px solid var(--line);background:#fff;}
  .mnav-toggle:checked ~ .mnav{display:block;}
  .mnav a{display:block;padding:.95rem 0;border-bottom:1px solid var(--line-2);font-weight:500;}
  /* display must be restated: the `.mnav a{display:block}` rule above wins on
     display alone and flattens .btn's inline-flex, which is what centres the
     label. Without this the menu's call to action sits left-aligned. */
  .mnav .btn{display:inline-flex;margin:1.1rem 0 1.4rem;width:100%;}
  .pillar,.pillar+.pillar{padding:1.5rem 0;border-left:0;border-top:1px solid var(--line);}
  .pillar:first-child{border-top:1px solid var(--line);}
  .slot{grid-template-columns:1fr;gap:.5rem;}
  .slot-time{font-size:.86rem;color:var(--blue-ink);}
  .hero-meta{gap:1.6rem 2rem;}
  .detail-row{flex-direction:column;gap:.2rem;}
  .detail-row dd{text-align:left;}
}
/* ── Phones ───────────────────────────────────────────────────────────────
   The 900px query above turns a desktop layout into a tablet one. This query
   is about the things that only go wrong on a phone held in one hand: text
   that iOS zooms into, targets too small to hit, and rows of three that were
   never going to fit across 390px. */
@media (max-width:600px){
  /* Buy back ~14px of line length on the narrowest screens without ever
     letting content reach the edge, which is what the hero used to do. */
  .wrap{padding-left:1.15rem;padding-right:1.15rem;}
  /* .wrap's gutter narrows here, so the rules' inset has to narrow with it. */
  .hdr,.sec-line{--edge:max(1.15rem,calc((100% - var(--wrap)) / 2 + 1.15rem));}

  /* 16px is the threshold below which iOS Safari zooms the page when a field
     takes focus, then leaves the visitor scrolled sideways mid-form. Registering
     on a phone has to be the easy path, so every control is at least 16px and
     tall enough to hit. */
  .f input[type=text],.f input[type=email],.f input[type=tel],.f input[type=url],
  .f input[type=date],.f input[type=time],.f input[type=number],.f select,.f textarea{
    font-size:16px;padding:.8rem .9rem;}
  .f-check{gap:.85rem;font-size:.94rem;}
  .f-check input{width:1.32rem;height:1.32rem;margin-top:.05rem;}

  /* One column, one decision at a time. auto-fit would still try to pair the
     15rem fields at 390px minus padding. */
  .f-grid{grid-template-columns:1fr;gap:1rem;}
  .form{max-width:none;}

  /* A primary action on a phone is a full-width bar: it cannot be half-missed,
     and it reads as the end of the form. */
  .f-actions .btn,.mnav .btn{width:100%;}

  /* The two hero calls to action share one row and split it evenly, the
     secondary one on the left and the primary on the right: the reading order
     becomes understand-then-act, and the commitment sits under the thumb
     rather than above its alternative. Source order is left alone, so the
     desktop layout and the tab order still lead with the primary action.
     Note for future edits: do not name the button labels in this comment. The
     stylesheet is inlined into every page, so a label written here is a label
     present in the HTML, and the test that checks a draft event never offers
     registration reads the whole document. */
  .hero-actions{gap:.6rem;flex-wrap:nowrap;}
  .hero-actions .btn{flex:1 1 0;min-width:0;padding-left:.6rem;padding-right:.6rem;
    font-size:.86rem;}
  /* Long labels must wrap rather than push the button past the screen. */
  .btn{white-space:normal;min-height:44px;}

  /* All three facts on one line. At default size they overflowed and were cut
     off by the hero's overflow:hidden; the fix is to set them smaller rather
     than to wrap them, because Date / Location / Organised by read as one
     answer to "what is this and when" and a stacked cell breaks that. Values
     wrap inside their own column if a venue name is long. */
  .hero-meta{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem .7rem;}
  .hero-meta dt{font-size:.56rem;letter-spacing:.1em;margin-bottom:.25rem;}
  .hero-meta dd{font-size:.8rem;line-height:1.3;}
  .hero h1{max-width:none;}
  .hero-tag{max-width:none;}
  /* The chart figure is decoration; at this width it only crowds the words. */
  .hero-figure{display:none;}

  /* Three link columns become two, so nothing is a one-word-per-line stack. */
  .ftr-cols{gap:1.6rem 2.4rem;}
  .ftr-col{min-width:8.5rem;}
  /* ~44px of hit area per link without visibly loosening the list. */
  .ftr-col a{padding:.62rem 0;}
  .brand{min-height:44px;}
  .ftr-btm{flex-direction:column;align-items:flex-start;gap:1.1rem;}
  /* Icon-only links need a real box around them to be tappable. */
  .ftr-social a{display:inline-flex;align-items:center;justify-content:center;
    width:44px;height:44px;margin-left:-11px;}

  /* Comfortable targets in the drop-down menu. */
  .mnav a{padding:1.05rem 0;}

  .logos{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:1rem;}
  .logo-cell{height:84px;}
}
@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important;scroll-behavior:auto!important;}
}

/* The organisers' link in the footer. Quieter than its neighbours and it stays
   quieter on hover: it is a door for the three people who need it, not an
   invitation to the several thousand who do not. */
.ftr-staff{opacity:.55;}
.ftr-staff:hover{opacity:1;}

/* ── Cookie consent notice ──────────────────────────────────────────────
   Markup and behaviour are shared with trusted.rw and learn (see
   templates/analytics/cookie_consent.html); the paint is this site's.

   It obeys the palette rule rather than shouting over it: paper and ink
   hold the notice, blue is the structure and carries Accept, and the yellow
   is NOT used here. Yellow appears once per screen and it belongs to
   registering, not to a cookie prompt -- a bar that borrows it turns the
   page's one action into two. Green is not used either: it confirms what
   has gone right, and answering a cookie question is not a success.
   Square-ish corners and a single hairline, like every other surface. */
#ckc{
  position:fixed;bottom:24px;left:50%;z-index:9999;
  transform:translateX(-50%) translateY(24px) scale(.98);
  opacity:0;pointer-events:none;
  display:flex;align-items:center;gap:14px;
  width:calc(100% - 32px);max-width:560px;
  padding:.9rem 1rem;
  background:var(--paper);color:var(--ink-2);
  border:1px solid var(--line);border-radius:var(--radius);
  font-family:var(--font);font-size:.83rem;line-height:1.5;
  box-shadow:0 12px 40px rgba(11,18,32,.14),0 2px 8px rgba(11,18,32,.06);
  transition:opacity .34s ease,transform .42s cubic-bezier(.22,.68,0,1.10);
}
#ckc.ckc--on{opacity:1;pointer-events:auto;transform:translateX(-50%) translateY(0) scale(1)}
.ckc-ico{
  flex-shrink:0;width:36px;height:36px;border-radius:var(--radius);
  display:flex;align-items:center;justify-content:center;font-size:1.1rem;line-height:1;
  background:var(--blue-soft);
}
.ckc-msg{flex:1;min-width:0}
#ckc strong{display:block;color:var(--ink);font-weight:650;font-size:.87rem;margin-bottom:1px}
#ckc a{color:var(--blue-ink);font-weight:600;text-decoration:underline}
#ckc-btns{display:flex;gap:.5rem;flex-shrink:0;margin-left:auto}
.ckc-decline,.ckc-accept{
  padding:.5rem .9rem;border-radius:var(--radius);cursor:pointer;
  font-family:inherit;font-size:.79rem;font-weight:600;white-space:nowrap;
  border:1px solid transparent;
  transition:background .15s,border-color .15s,color .15s;
}
.ckc-decline{background:transparent;color:var(--ink);border-color:var(--line)}
.ckc-decline:hover{border-color:var(--ink-4)}
.ckc-accept{background:var(--deep);color:#fff;border-color:var(--deep)}
.ckc-accept:hover{background:var(--deep-2);border-color:var(--deep-2)}
.ckc-decline:focus-visible,.ckc-accept:focus-visible{outline:2px solid var(--rw-blue);outline-offset:2px}
/* Two rows and thumb-sized buttons once the three parts stop fitting side
   by side. */
@media (max-width:560px){
  #ckc{bottom:10px;left:10px;right:10px;width:auto;max-width:none;
    flex-wrap:wrap;gap:.75rem;padding:1rem;
    transform:translateY(24px) scale(.98);}
  #ckc.ckc--on{transform:translateY(0) scale(1)}
  #ckc-btns{width:100%;gap:.6rem}
  .ckc-decline,.ckc-accept{flex:1;min-height:44px;font-size:.83rem}
}
