/* Renaissance Rodeo — the one stylesheet, shared by /, /es/ and /404.html.
   Two inks on cream, one 36rem column of copy, two media queries (a phone
   tweak at ≤519px; from 64rem up the poster gets a sticky column beside the
   copy, and --scale shrinks the whole page to .75). Bevan for the date and headings, Cormorant Garamond
   for everything else. Font files live in /fonts/ and are referenced ONLY here
   (plus the two preloads in each page); when a font file is replaced, bump its
   ?v= query here and in the preloads. The tree is on ?v=2 since 2026-10-14. */

@font-face {
  font-family: 'Bevan';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/bevan-latin-400-normal.woff2?v=2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/cormorant-garamond-latin-400-normal.woff2?v=2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/cormorant-garamond-latin-600-normal.woff2?v=2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

/* ---------- tokens ---------- */
:root {
  color-scheme: light;
  --cream: #f7edd8;
  --paper: #fffdf8;
  --ink: #0e1d2d;
  --muted: #3f4a58;
  --red: #c01102;
  --red-deep: #a30e02;
  --font-display: 'Bevan', Rockwell, 'Roboto Slab', Georgia, serif;
  --font-body: 'Cormorant Garamond', Cormorant, 'EB Garamond', Garamond, Georgia, serif;
  --text-body: clamp(1.25rem, 1.15rem + .4vw, 1.4375rem);
  --text-small: 1.125rem;
  --text-date: clamp(1.125rem, .95rem + 1vw, 1.5rem);
  --text-h2: clamp(1.625rem, 1.25rem + 1.8vw, 2.25rem);
  --text-button: 1.1875rem;
  --lh-body: 1.45;
  --gap-section: clamp(2.5rem, 7vw, 4.5rem);
  --control: 3rem;
  --border: 1.5px;
  --radius: 0;
  --ring: 3px solid var(--red);
  --ring-offset: 2px;
  /* Multiplies the root size, and with it every rem in this sheet. See "base". */
  --scale: 1;
}
/* Desktop reads at what 75% browser zoom used to show. Phones and tablets keep 1. */
@media (min-width: 64rem) {
  :root { --scale: .75; }
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { overflow-x: clip; }
body { margin: 0; }
html, body {
  background: var(--cream);
  color: var(--ink);
  font: var(--text-body) / var(--lh-body) var(--font-body);
}
/* A warm cream-to-sand wash behind the whole page, kept in the darker part of the range so
   it never reads as stark white (html keeps the flat --cream as the fallback). */
body {
  min-height: 100vh;
  background: linear-gradient(180deg, var(--cream) 0%, #ecdec2 55%, #e2cfa9 100%);
  background-attachment: fixed;
}
/* The root size is the body size (20–23px), not 16px, so 1rem here is 20–23px and every rem
   in this sheet (type, column widths, gaps, the poster) comes out about 1.3× its 16px-based
   value. At 100% zoom on a desktop that read too large. --scale shrinks the root, so all of
   it shrinks together; on the root itself rem means the browser's 16px, so this cannot feed
   back into itself. px sizes (icons, 44px tap targets, borders, the focus ring) stay put. */
html { font-size: calc(var(--text-body) * var(--scale)); }
img { display: block; max-width: 100%; height: auto; }
h1, h2, h3, p { margin: 0; }
strong { font-weight: 600; }
a {
  color: var(--ink);
  text-underline-offset: .15em;
  text-decoration-thickness: .08em;
}
:focus-visible { outline: var(--ring); outline-offset: var(--ring-offset); }
#signup-ok:focus, main:focus { outline: 0; }
/* The UA sheet's display:none for [hidden] loses to any display: set by a
   class; this keeps hidden meaning hidden whatever else matches. */
[hidden] { display: none !important; }

.sr-only, .skip:not(:focus) {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.wrap { max-width: 36rem; margin-inline: auto; padding-inline: 1rem; }

/* ---------- skip link (sr-only until focused, then an ink pill) ---------- */
.skip:focus {
  position: absolute;
  top: .75rem;
  left: .75rem;
  z-index: 1;
  padding: .75rem 1.125rem;
  background: var(--ink);
  color: var(--cream);
  border-radius: 999px;
  font: 600 var(--text-small) / 1 var(--font-body);
  text-transform: uppercase;
  letter-spacing: .06em;
  text-decoration: none;
}

/* ---------- header ---------- */
/* One bar on every page. Desktop: [mark] TEAM TICKETS SPONSORS [X][Instagram] ……… EN | ES.
   Below 64rem the links and icons do not fit beside the switch (Spanish alone is ~335px), so the
   bar is [mark][menu] ……… EN | ES and the menu button opens them in a panel under the bar
   (see "header below 64rem"). The mark (small bull-and-rider, leads home) is on the subpages
   only; / and /es/ open with the hero logo instead. */
.top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: .25rem;
  padding-block: .75rem;
}
.mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  margin-inline: -4px .5rem;   /* the 36px glyph, not its 44px tap box, lines up with the text */
}
.mark img { width: 36px; height: 36px; }
.lang {
  display: flex;
  align-items: center;
  margin-inline-start: auto;
  font: 600 1.0625rem / 1 var(--font-body);
  text-transform: uppercase;
  letter-spacing: .06em;
}
.lang a, .lang [aria-current] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
}
.lang [aria-current] { color: var(--muted); }
.lang .sep { color: var(--muted); }
/* nav.site holds the page links and the X / Instagram icons. It is a popover (the HTML
   attribute; no script): the browser hides it until the menu button opens it, which is what
   phones need. These rules undo the browser's popover box so that, wherever it is shown in the
   bar (desktop, or a browser without popovers), it is a plain row; display is left alone here
   so the browser can still hide it. */
.site[popover] {
  position: static;
  inset: auto;
  width: auto;
  height: auto;
  margin: 0 .5rem 0 0;
  padding: 0;
  border: 0;
  overflow: visible;
  color: inherit;
  background: none;
}
/* The page links, set like the language switch. Plain ink, underlined on hover; the page you
   are on is underlined (aria-current). The same list, in the same order, is in every page of a
   language and again in the footer (tested). */
.site-links {
  display: flex;
  flex-wrap: wrap;
  column-gap: 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font: 600 1.0625rem / 1 var(--font-body);
  text-transform: uppercase;
  letter-spacing: .06em;
}
.site a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
}
.site a:hover { color: var(--red); }
.site a[aria-current="page"], .foot-nav a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-thickness: .08em;
  text-underline-offset: .3em;
}
/* X and Instagram: inline-SVG icons in currentColor after the page links, so they take no row
   of their own and no image request (nothing new for img-src or the asset pipeline). */
.social { display: flex; margin: 0; padding: 0; list-style: none; }
.social a, .social button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  color: var(--ink);
}
.social button { padding: 0; background: none; border: 0; font: inherit; cursor: pointer; }
.social a:hover, .social button:hover { color: var(--red); }
.social svg { display: block; width: 20px; height: 20px; }

/* ---------- hero ---------- */
main { padding-top: clamp(.5rem, 3vw, 1.5rem); }
.hero h1 img { width: 100%; }
/* Phone and tablet poster: a thumbnail beside the activity list (see "activities"). The desktop
   column (.poster) is display:none here and takes over from 64rem up. */
.poster-thumb { display: block; }
.poster-thumb img { width: 100%; box-shadow: 0 6px 18px rgb(14 29 45 / .18); }
.poster { display: none; }
/* Date and place: a lockup under the logo, two centred lines of Bevan sized to the column (cqi,
   so it scales with the logo above it at every width; a browser without container units keeps
   --text-date). At 5.8cqi the longest line, the Spanish date, fills about 95% of the column. */
.hero { container-type: inline-size; }
.when {
  margin-top: .5rem;
  font: 400 var(--text-date) / 1.25 var(--font-display);
  font-size: 5.8cqi;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.when-date, .when-place { display: block; }
.after { margin-top: 1rem; text-align: center; }
/* Buy tickets, straight to the shop: centred under the date lockup, so it is on the first
   screen of every phone. "The day after…" follows it, centred too. */
.hero-buy { margin-top: 1.25rem; text-align: center; }
.hero-buy .buy { padding-inline: 2.25rem; }


/* ---------- sections ---------- */
.copy > section + section { margin-top: var(--gap-section); }
.about p { margin-block: 1.1em; overflow-wrap: break-word; }
.about p:first-of-type { margin-top: 0; }
.about p:last-of-type { margin-bottom: 0; }

/* ---------- activities ---------- */
/* The day's activities as a programme: uppercase like the nav, a small red diamond for each (a
   CSS shape: the font subset has no ✦). Words are written in sentence case and uppercased here,
   so screen readers read words, not letters. Home, phones and tablets: [poster | list], the list
   one column so its twelve lines stand about as tall as the thumbnail. Desktop (no thumbnail)
   and the about page: columns (see the desktop block). */
.activities {
  margin: 0;
  padding: 0;
  list-style: none;
  font: 600 1rem / 1.25 var(--font-body);
  text-transform: uppercase;
  letter-spacing: .06em;
}
.activities li { position: relative; padding: .2em 0 .2em 1.1em; break-inside: avoid; }
.activities li::before {
  content: "";
  position: absolute;
  left: .1em;
  top: .72em;
  width: .38em;
  height: .38em;
  background: var(--red);
  transform: rotate(45deg);
}
.lineup {
  display: grid;
  grid-template-columns: min(42%, 11rem) minmax(0, 1fr);
  align-items: center;
  gap: 1.5rem;
  margin-top: 1.5rem;
}
.about-page .activities { margin-top: 1.5rem; columns: 2; column-gap: 1.5rem; }
/* "Learn more about Renaissance Rodeo": a plain link in the copy, its arrow drawn inline (the
   font subset has no U+2192) and nudged right on hover. */
.about .more { margin-top: .5rem; }
.more a { font-weight: 600; text-underline-offset: .2em; }
.more svg { display: inline-block; width: .8em; height: .8em; margin-inline-start: .3em; vertical-align: -.05em; }

/* ---------- signup ---------- */
#signup { scroll-margin-top: 1.5rem; }
#signup h2 { font: 400 var(--text-h2) / 1.15 var(--font-display); }
#signup h2 + p { margin-top: .75rem; }
.signup { margin-top: 1.25rem; }
.signup label { display: block; margin-bottom: .5rem; font-weight: 600; }
.row { display: flex; flex-wrap: wrap; gap: .75rem; }
.signup input[type="email"] {
  flex: 1 1 16rem;
  min-width: 0;
  height: var(--control);
  padding: 0 .875rem;
  background: var(--paper);
  color: var(--ink);
  border: var(--border) solid var(--ink);
  border-radius: 6px;
  font: 400 max(1.25rem, 16px) / 1 var(--font-body);
}
.signup input::placeholder { color: var(--muted); opacity: 1; }
/* Full width under the input at every width. Side by side only fitted at some widths (rem
   follows the fluid body size, and the poster column narrows the copy from 64rem up), so the
   button kept wrapping onto a line of its own at its natural width; one layout everywhere. */
.signup button {
  flex: 1 0 100%;
  height: var(--control);
  padding: 0 1.5rem;
  background: var(--red);
  color: var(--cream);
  border: var(--border) solid var(--red);
  border-radius: 6px;
  font: 600 var(--text-button) / 1 var(--font-body);
  text-transform: uppercase;
  letter-spacing: .06em;
  cursor: pointer;
  box-shadow: 0 2px 6px rgb(163 14 2 / .28);
}
.signup button:hover { background: var(--red-deep); border-color: var(--red-deep); transform: translateY(-2px); box-shadow: 0 6px 16px rgb(163 14 2 / .32); }
.signup button:active { transform: translateY(0); box-shadow: 0 2px 6px rgb(163 14 2 / .28); }
.signup button:disabled { opacity: .6; cursor: default; }
/* Honeypot: off-screen, never display:none (bots skip fields they can see are
   hidden; humans and screen readers never reach it — tabindex=-1, aria-hidden). */
.hp {
  position: absolute !important;
  left: -9999px !important;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}
.cf-turnstile { margin-top: .5rem; }
.msg {
  min-height: 1.5em;
  margin-top: .5rem;
  color: var(--red);
  font-size: var(--text-small);
}
/* Empty, the error line takes no room (the share bar sits close under the form); a message
   opens it, which moves only what is below the form, never the input or the button. */
.msg:empty { min-height: 0; margin-top: 0; }
.success { margin-top: 1.25rem; font-weight: 600; }
/* Inside the form, straight under the input row: the reassurance sits by the field it is about. */
.fine { margin-top: .5rem; color: var(--muted); font-size: var(--text-small); }

/* ---------- share / follow ---------- */
/* The foot of the copy, like the end of an article: two thin rows of the header's icons
   (.social), each led by a small label. A two-column grid so both icon rows start on the same
   line whatever the label's length ("Compartir" vs "Seguir"); the rows are display:contents
   so their label and list land in the grid's columns. On phones each label sits above its row. */
/* Closer to the form than the standard section gap: it belongs to the signup's ending. */
.copy > section.share { margin-top: clamp(1.5rem, 4vw, 2.25rem); }
.share { display: grid; grid-template-columns: auto 1fr; align-items: center; column-gap: .75rem; }
.share-row { display: contents; }
.share .social { flex-wrap: wrap; }
.share-label {
  color: var(--muted);
  font: 600 var(--text-small) / 1 var(--font-body);
  text-transform: uppercase;
  letter-spacing: .06em;
}
/* Empty until "Copy link" is used, so it takes no room; the text clears itself after 3 s. */
.share-status { grid-column: 2; color: var(--muted); font-size: var(--text-small); }

/* ---------- partners ---------- */
/* Three marks in one row at every width. Each link is a two-row grid: a fixed-height logo
   slot (the mark fits inside it, centred, so three different aspect ratios sit on one line)
   and the caption. On phones the slot shrinks and the captions go screen-reader-only. */
.partners {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: center;
}
.partners a {
  display: grid;
  grid-template-rows: 8rem auto;
  justify-items: center;
  align-items: center;
  text-decoration: none;
}
.partners img {
  max-height: 8rem;
  max-width: 100%;
  width: auto;
  height: auto;
}
.partners .cap {
  display: block;
  align-self: start;
  margin-top: .75rem;
  font-size: var(--text-small);
  line-height: 1.45;
}
/* The "day before" tagline under Bitcoin Histórico's name: its own line, set in small
   caps with letter-spacing so it reads as a label rather than body copy. */
.partners .tagline {
  display: block;
  margin-top: .2em;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
}
/* Hide the <br> directly after the tagline: the tagline is already a block, so that break
   would only add a blank line before the date. Scoped to that one <br> so every other
   caption break still starts a new line — BitPoker SV's name above its description. */
.partners .cap .tagline + br { display: none; }
.partners a:hover .cap { text-decoration: underline; text-underline-offset: .15em; }
/* The second tier: under a hairline, two smaller marks side by side, no label (Cameron,
   2026-10-24). Each mark is capped by height and by its cell, so the wide BitDriver wordmark and
   the squarer Bitcoin Hardware Store lockup carry about the same weight. */
.partners.tier-2 {
  grid-template-columns: repeat(2, minmax(0, 14rem));
  justify-content: center;
  gap: 1.5rem 2.5rem;
  margin-top: 2.25rem;
  padding-top: 2.25rem;
  border-top: 1px solid rgb(14 29 45 / .18);
}
.partners.tier-2 a { grid-template-rows: 4.5rem auto; }
.partners.tier-2 img { max-height: 4.5rem; max-width: 92%; }

/* ---------- poster viewer (<dialog>) ---------- */
/* Scoped to [open]: a bare .lightbox{display:grid} would undo the UA's display:none on the
   closed dialog and put the poster into the page flow. */
.lightbox {
  width: 100vw;
  height: 100dvh;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
}
.lightbox[open] { display: grid; place-items: center; }
.lightbox::backdrop { background: rgb(14 29 45 / .92); }
.lightbox picture { display: contents; }
.lightbox img { max-width: 100vw; max-height: 100dvh; width: auto; height: auto; }
.lightbox-close {
  position: fixed;
  top: .75rem;
  right: .75rem;
  width: 44px;
  height: 44px;
  padding: 0;
  background: var(--ink);
  color: var(--cream);
  border: var(--border) solid var(--cream);
  border-radius: 999px;
  font: 600 1.125rem / 1 var(--font-body);
  cursor: pointer;
}
.lightbox-close:hover { background: var(--red); border-color: var(--red); }
body:has(dialog[open]) { overflow: hidden; }

/* ---------- team (the #team section of /about, /es/about) ---------- */
/* One list of cards: a square (the person's photo, or their initials until one exists), then the
   name, the organisation, an X link and a short bio. Phones: the square sits beside the name and
   the bio runs full width under both. From 520px: one card per row, the square on the left and the
   text beside it. From 64rem, where the team page leaves the poster grid and takes the full width
   (desktop block below): two columns of those cards, filled downwards. */
.page h1 { font: 400 var(--text-h2) / 1.15 var(--font-display); }
.team-lede, .lede { margin-top: .75rem; }
.team-grid {
  display: grid;
  gap: 1.75rem;
  margin: 2.25rem 0 0;
  padding: 0;
  list-style: none;
}
.member { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1.25rem; }
.avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 5.5rem;
  aspect-ratio: 1;
  border-radius: 12px;
  overflow: hidden;
  background: var(--ink);
  color: var(--cream);
  font: 400 1.75rem / 1 var(--font-display);
  letter-spacing: .04em;
  user-select: none;
  box-shadow: 0 4px 14px rgb(14 29 45 / .18);
}
/* A photo fills the square edge to edge; an initials square is left as the ink block. */
.avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Basis 0, not auto: a long name or org line must shrink beside the square, not wrap under it
   now that the card can wrap (the bio takes the next line). */
.member-body { flex: 1 1 0; min-width: 0; }
.member-name { font: 400 1.25rem / 1.2 var(--font-display); }
.member-org { margin-top: .25rem; }
/* The short bio, last in the card: on phones it drops under the square and name at full width. */
.member-bio { flex-basis: 100%; text-wrap: pretty; }
/* Pull the 44px tap target left so the X glyph lines up with the text above it. */
.member .social { margin-inline-start: -12px; }
@media (min-width: 520px) {
  /* Tablet and up: one card per row, the square on the left, the text beside it and the bio
     under the name, so the long bios read as left-aligned paragraphs, not centred slivers. */
  .team-grid { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
  .member {
    display: grid;
    grid-template-columns: 8rem minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    grid-template-areas: "avatar body" "avatar bio";
    gap: .75rem 2rem;
    align-items: start;
  }
  .avatar { grid-area: avatar; width: 100%; font-size: 3rem; }
  .member-body { grid-area: body; }
  .member-bio { grid-area: bio; max-width: 34rem; }
}

/* ---------- tickets and sponsors (/tickets, /sponsors and the /es/ twins) ---------- */
/* Text pages in the 36rem copy column. Tickets: the Bitcoin Histórico box, prices and the Buy link,
   the DUI notice, then the same signup form as the home page. (.soon is no longer used by any
   page.) Sponsors: the partner row, then how to become a sponsor. */
.soon {
  margin-top: .5rem;
  color: var(--red);
  font: 400 var(--text-date) / 1.3 var(--font-display);
  text-transform: uppercase;
  letter-spacing: .05em;
}
/* "Have a Bitcoin Histórico ticket?": a ruled box with the Bitcoin Histórico emblem beside the
   text (the partner-row image, so nothing new to build or allow). */
.included {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  margin-top: 1.75rem;
  padding: 1.25rem;
  background: var(--paper);
  border: var(--border) solid var(--ink);
}
.included img { flex: none; width: 4.5rem; height: auto; }
.included h2 { font: 400 clamp(1.125rem, 1rem + .6vw, 1.375rem) / 1.2 var(--font-display); }
.included p { margin-top: .5rem; }
/* Prices and the Buy link (README, "The tickets page"). The link repeats the signup button's look
   but is an <a>, so it sizes to its text instead of filling a flex row. */
#buy { margin-top: 1.75rem; }
#buy h2 { font: 400 clamp(1.125rem, 1rem + .6vw, 1.375rem) / 1.2 var(--font-display); }
.prices { list-style: none; margin: .75rem 0 0; padding: 0; }
.prices li { display: flex; justify-content: space-between; gap: 1rem; padding: .5rem 0; border-bottom: 1px solid var(--muted); }
.prices .price { font: 400 var(--text-date) / 1.3 var(--font-display); }
#buy p { margin-top: .75rem; }
/* Under the Buy button: how tickets arrive and where to write (hello@ reaches the team through the mail
   catch-all; the shop sends the same address as its Reply-To). Quieter than the copy above it. */
#buy .buy-note { font-size: var(--text-small); color: var(--muted); }
.buy {
  display: inline-flex;
  align-items: center;
  height: var(--control);
  padding: 0 1.5rem;
  background: var(--red);
  color: var(--cream);
  border: var(--border) solid var(--red);
  border-radius: 6px;
  font: 600 var(--text-button) / 1 var(--font-body);
  text-transform: uppercase;
  letter-spacing: .06em;
  text-decoration: none;
  box-shadow: 0 2px 6px rgb(163 14 2 / .28);
}
.buy:hover { background: var(--red-deep); border-color: var(--red-deep); box-shadow: 0 6px 16px rgb(163 14 2 / .32); }
/* "Free entry with a DUI": the .included box without the emblem, so text only. */
.dui {
  margin-top: 1.25rem;
  padding: 1.25rem;
  background: var(--paper);
  border: var(--border) solid var(--ink);
}
.dui h2 { font: 400 clamp(1.125rem, 1rem + .6vw, 1.375rem) / 1.2 var(--font-display); }
.dui p { margin-top: .5rem; }
.page #signup { margin-top: var(--gap-section); }
#signup .soon { margin-top: .25rem; }
#signup .soon + p { margin-top: .75rem; }
.page-section { margin-top: var(--gap-section); }
.page-section h2 { margin-bottom: 1.25rem; font: 400 clamp(1.25rem, 1.1rem + .8vw, 1.625rem) / 1.2 var(--font-display); }
.page-section p + p { margin-top: 1em; }

/* ---------- about (/about, /es/about) ---------- */
/* The event, the team and the sponsors, one section each, under a row of jump links that sticks
   to the top of the screen. A jump scrolls smoothly (html scroll-behavior, motion block) and
   lands the heading just under the row (scroll-margin-top). Where scroll markers exist (Chrome
   140+), the section in view fills its pill; elsewhere they are plain links. No script. */
.jump {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 1.25rem -1rem 0;
  padding: .5rem 1rem;
  /* The body's own wash, also fixed to the viewport, so the row is invisible against the page
     where it sits and still covers what scrolls under it once it sticks. */
  background: linear-gradient(180deg, var(--cream) 0%, #ecdec2 55%, #e2cfa9 100%) fixed;
  border-bottom: 1px solid rgb(14 29 45 / .18);
}
/* One row; if it cannot fit (the Spanish labels on a 320px phone) it slides sideways rather than
   wrapping. The 5px padding keeps the focus ring inside the scroll box, which clips. */
.jump ul {
  display: flex;
  gap: .5rem;
  margin: -5px;
  padding: 5px;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
  scroll-target-group: auto;
}
.jump ul::-webkit-scrollbar { display: none; }
.jump li { flex: 1 0 auto; scroll-snap-align: start; }
.jump a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 .65rem;
  border: var(--border) solid var(--ink);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font: 600 .875rem / 1 var(--font-body);
  white-space: nowrap;
  text-decoration: none;
}
.jump a:hover { border-color: var(--red); color: var(--red); }
.jump a:target-current { background: var(--ink); border-color: var(--ink); color: var(--cream); }
.about-page > section { scroll-margin-top: calc(44px + 2.5rem); }
.jump + .page-section { margin-top: 2rem; }
.page-section h2 + .team-lede { margin-top: 0; }
.become { margin-top: 2.25rem; }

/* ---------- footer ---------- */
/* Shorter on top than the section gap so the share bar is not stranded above it (404 has no
   footer). The page links again, then X and Instagram as words, then the copyright line. */
footer { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; padding-block: clamp(1.75rem, 4vw, 2.75rem) var(--gap-section); color: var(--muted); font-size: var(--text-small); }
footer a { color: inherit; }
.foot { display: grid; gap: .75rem; }
.foot-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.foot-nav a { display: inline-block; padding-block: .25rem; color: var(--ink); text-decoration: none; }
.foot-nav a:hover { color: var(--red); }

/* ---------- 404 ---------- */
.notfound { padding-block: var(--gap-section); }
.notfound .code { font: 400 clamp(4rem, 12vw, 6rem) / 1 var(--font-display); }
.notfound h1 { margin-top: .75rem; font-size: var(--text-h2); font-weight: 400; }
.notfound p + p { margin-top: 1.25rem; }

/* ---------- the menu button (below 64rem) ---------- */
/* Hidden on desktop, and in a browser without popovers (where the menu could not open). */
.menu-btn {
  display: none;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  background: none;
  color: var(--ink);
  border: 0;
  cursor: pointer;
}
.menu-btn:hover { color: var(--red); }
.menu-btn svg { display: block; }
.menu-btn .i-close, .top:has(.site:popover-open) .menu-btn .i-open { display: none; }
.top:has(.site:popover-open) .menu-btn .i-close { display: block; }

/* ---------- header below 64rem: one bar, links in a menu ---------- */
/* The bar is [mark][menu] ……… EN | ES on every page: the button sits right after the bull (at
   the left edge on / and /es/, which have no mark), the panel's links start under it, and the
   language switch keeps the right edge. The menu opens nav.site as a panel
   pinned under the bar, full width, its contents on the copy column's left edge: the page
   links one per line, then the icons. Tapping a link, outside the panel, the button again or
   Esc closes it (the browser's light dismiss, no script). The panel is positioned absolutely
   in the top layer, so it hangs from the top of the document, i.e. under the bar, wherever the
   page is scrolled; the bar is the header's 44px row plus .75rem above and below. */
@media (max-width: 63.99rem) {
  .top { column-gap: 0; }
  @supports selector(:popover-open) {
    .menu-btn { display: inline-flex; }
    /* Right against the mark: the bull's own 4px of box, then the button's 12px round its glyph. */
    .mark { margin-inline-end: 0; }
    /* On / and /es/ (no mark) the button starts the bar: pull its 44px tap box left so the glyph
       lines up with the page text and the panel's links below. */
    .top > .site:first-child + .menu-btn { margin-inline-start: -12px; }
  }
  .site:popover-open {
    position: absolute;
    inset: calc(44px + 1.5rem) 0 auto 0;
    margin: 0;
    padding: .25rem 1rem 1rem;
    background: var(--cream);
    border-block: var(--border) solid var(--ink);
    box-shadow: 0 12px 24px rgb(14 29 45 / .12);
  }
  .site:popover-open > ul { max-width: 34rem; margin-inline: auto; }
  .site:popover-open .site-links { flex-direction: column; }
  .site:popover-open .site-links a { min-height: 48px; }
  .site:popover-open .social { margin-top: .25rem; }
  /* Pull the first 44px tap box left so the X glyph lines up with the links above it. */
  .site:popover-open .social li:first-child a { margin-inline-start: -12px; }
  /* No popovers (older browsers): the menu cannot open, so the links and icons stay in the bar
     on a row of their own under it, as before. */
  @supports not selector(:popover-open) {
    .site[popover] { display: flex; flex-wrap: wrap; align-items: center; order: 1; flex-basis: 100%; margin-inline-end: 0; }
  }
}

/* ---------- desktop: the links and icons sit in the bar ---------- */
/* Author styles beat the browser's own, so this shows the popover nav in place even though no
   one has opened it, and the menu button stays hidden (above). */
@media (min-width: 64rem) {
  .site[popover] { display: flex; align-items: center; column-gap: .75rem; }
}

/* ---------- phones ---------- */
@media (max-width: 519px) {
  /* The emblem beside the heading only, a size down; the sentence takes the box's full width. */
  .included { display: grid; grid-template-columns: 3rem minmax(0, 1fr); align-items: center; gap: .75rem 1rem; padding: 1rem; }
  .included img { width: 3rem; }
  .included > div { display: contents; }
  .included p { grid-column: 1 / -1; margin-top: 0; }
  .dui { padding: 1rem; }
  .partners { gap: 1.5rem 1rem; }
  .share { display: block; }
  .share-row { display: block; }
  .share-row + .share-status + .share-row, .share-row + .share-row { margin-top: .75rem; }
  .share-label { display: block; margin-bottom: .125rem; }
  /* Pull the 44px tap targets left so the first glyph lines up with the label above it. */
  .share .social { margin-inline-start: -12px; }
  .partners a { grid-template-rows: 5.5rem auto; }
  .partners img { max-height: 5.5rem; }
  /* Three captions in ~6rem columns would wrap into a wall of text: on the home page the marks
     stand alone and the names stay readable to assistive tech (Bitcoin Histórico's "day before"
     is in the hero). The about and sponsors pages stack the three instead and keep every caption. */
  .page .partners { grid-template-columns: 1fr; gap: 2.25rem; }
  .partners.tier-2, .page .partners.tier-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem 1.25rem; }
  .partners.tier-2 a { grid-template-rows: 3.5rem auto; }
  /* The stacked TBHS lockup a size down, so it weighs about what the flat BitDriver wordmark does. */
  .partners.tier-2 img { max-height: 3rem; }
  /* Uppercase would wrap most items in a phone's narrow column and double the list's height:
     plain case, a size down, so each item keeps one line and the list stands as tall as the
     poster beside it. */
  .lineup { gap: 1rem; }
  .activities { font-size: .875rem; line-height: 1.15; text-transform: none; letter-spacing: 0; }
  .activities li { padding-block: .15em; }
  .activities li::before { top: .55em; }
  .copy .partners .cap {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* ---------- desktop: the poster gets a sticky column beside the copy ---------- */
@media (min-width: 64rem) {
  .wrap { max-width: 64rem; }
  main {
    display: grid;
    grid-template-columns: minmax(0, 36rem) 22rem;
    column-gap: 4rem;
    justify-content: space-between;
  }
  /* Everything but the poster stays in the copy track — the 404 page shares this sheet and
     has no .copy wrapper, so auto-placement would otherwise spill its heading into track 2. */
  main > :not(.poster) { grid-column: 1; }
  /* The about page has no poster: it takes the whole 64rem, the jump pills sit at their own
     width and the event text keeps a reading measure. The team: two columns of cards that fill
     downwards (James, Zack, Tom | Andrea, Cam, Will), not rows: the bios differ a lot in length,
     and rows would leave a hole under every short card. */
  main.about-page { display: block; }
  .jump { margin-inline: 0; padding-inline: 0; }
  .jump li { flex-grow: 0; }
  .jump a { padding: 0 1.1rem; font-size: 1.0625rem; }
  #event p { max-width: 38rem; }
  .team-grid { display: block; columns: 2; column-gap: 3rem; }
  .member { break-inside: avoid; margin-bottom: 3rem; }
  .member:last-child { margin-bottom: 0; }
  .poster-thumb { display: none; }
  .lineup { display: block; }
  /* Two columns in the 36rem home column (three would wrap the longer items, the Spanish above
     all); three across the about page's full width. */
  .activities { columns: 2; column-gap: 2rem; }
  .about-page .activities { columns: 3; }
  .poster {
    display: block;
    grid-column: 2;
    grid-row: 1;
    align-self: start;
    position: sticky;
    top: 1.5rem;
    margin: 0;
  }
  .poster a { display: block; }
  /* Both max-constraints together keep the 9:16 ratio: on a short laptop viewport the height
     cap wins and the width follows. */
  .poster img {
    max-width: 100%;
    max-height: calc(100vh - 3rem);
    width: auto;
    height: auto;
  }
}

/* ---------- motion, only where the visitor has not asked for less ---------- */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
  .signup button { transition: background-color .15s ease, border-color .15s ease, opacity .15s ease, transform .15s ease, box-shadow .15s ease; }
  .more svg { transition: transform .15s ease; }
  .more a:hover svg { transform: translateX(3px); }
  /* Team photos lift gently on hover. */
  .avatar img { transition: transform .35s ease; }
  .avatar:hover img { transform: scale(1.04); }
  /* Scroll fade-up: the sections of the copy column rise into place as they enter the view.
     Scroll-driven animation ranges need no script; where animation-timeline is unsupported
     the @supports block never matches and nothing changes. The hero sits above the fold on
     arrival, so it is left out — its logo must not fade in mid-read. The about page's sections
     are left out too: they are jump targets, and a section still translated when the browser
     scrolls to it lands 1.25rem off, under the sticky jump row. */
  @supports (animation-timeline: view()) {
    .copy > section:not(.hero) {
      animation: fade-up both ease-out;
      animation-timeline: view();
      animation-range: entry 0% entry 55%;
    }
  }
}

/* The scroll fade-up above. */
@keyframes fade-up {
  from { opacity: 0; transform: translateY(1.25rem); }
  to   { opacity: 1; transform: none; }
}
