/* Sections below the hero. Ported from the designer's preview
   (ethindia2026-qf4g2l622-superark21s-projects.vercel.app), one section at a time.
   One module drives the layout: the graph-paper cell (--grid-size). Columns are
   one cell wide, boxes span whole cells, and sections.js rounds each block's
   height up to whole cells so everything below the hero sits on the grid lines.
   The grid itself is the body background (inline CSS), never repainted here. */

.more, .site-foot {
  --lead: 2;          /* cells from the left edge to the content */
  --span: 24;         /* content width in cells (12 cols x 2 cells) */
  --card-t: 2;        /* speaker card: text rows in cells (min; grows for long roles) */
  --per-row: 4;       /* speaker cards per row, a quarter cell apart */
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
/* the FAQ and the grid snap change heights in place; never let the browser shift
   the scroll position to compensate */
html { overflow-anchor: none; }

/* ---------- Layout ---------- */
.more { position: relative; }
.wrap {
  display: grid;
  grid-template-columns: repeat(var(--span), var(--grid-size));
  margin-left: calc(var(--grid-size) * var(--lead));
}
.wrap > * { grid-column: 1 / -1; min-width: 0; }

/* Rhythm: 2 cells above every title (1 cell of open grid, then 1 cell of the
   section's paper field), 1 cell between a title and its content, and 1 cell of
   field below the content. See "Paper fields". */
.sec {
  position: relative;
  /* edge motifs bleed off the side and get cut, like the hero band. Only x: the
     last box's 1px bottom border overlaps the next section and must stay visible. */
  overflow-x: clip;
  padding: calc(var(--grid-size) * 2) 0 var(--grid-size);
  scroll-margin-top: max(var(--nav-h), calc(var(--u) * 72));   /* clears the docked nav */
}

.sec-head { margin-bottom: var(--grid-size); }
.sec-title {
  margin: 0;
  font-family: var(--pixel-font);
  font-weight: 400;
  font-size: calc(var(--grid-size) * 1.2);
  line-height: calc(var(--grid-size) * 2);
}
/* Section marks: a charted motif (assets/charts/) before every title. 7×7 at 0.7em: Matrix Sans has a 7-pixel cap height, so one stitch
   is one pixel of the title and the mark stands cap-high on the baseline, two
   type pixels before the words. All in madder (--maroon):
     speakers  mic        7×8: larger by a stitch, still on the type's grid
     schedule  rudraksha  a bead of the mala, read like a clock dial
     faq       bubble     a speech bubble, 7×7, cap-high like the others
   About and the footer line have none. */
.sec-title::before, .foot-line::before {
  content: "";
  display: inline-block;
  width: var(--mw, 0.7em);
  height: var(--mh, 0.7em);
  margin-right: 0.2em;
  background: var(--mark) center / 100% 100% no-repeat;
}
#about-title::before, .foot-line::before { content: none; }   /* these two titles stand on their own */
#speakers-title { --mark: url("assets/charts/mark-mic.svg?v=2"); --mw: 0.7em; --mh: 0.8em; }
#schedule-title { --mark: url("assets/charts/mark-rudraksha.svg?v=1"); }
#faq-title      { --mark: url("assets/charts/mark-bubble.svg?v=1"); }

.sec p { text-wrap: pretty; }

.text-link {
  color: var(--ink);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.text-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 4px; }

/* one fact line under a title (schedule date + hall): one cell tall */
.sec-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
  min-height: var(--grid-size);
  margin: 0;
  font: 400 15px/1.2 var(--pixel-font);
}
.sec-meta-sub { color: color-mix(in oklab, var(--ink) 84%, var(--paper)); }
.sec-meta-sub::before { content: "/ "; }

/* secondary action: the ink pill stays reserved for tickets */
.btn--line {
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 999px;
}
.btn--line:hover { background: var(--ink); color: var(--paper); }


/* boxes: 1px border on the grid lines. A box spanning n cells is n*cell + 1px
   wide/tall (negative margin) so its right/bottom edge lands ON the next line. */
.empty, .soon-panel {
  border: 1px solid var(--rule);
  margin: 0 -1px -1px 0;
}


/* ---------- About ---------- */
.about-copy { grid-column: 1 / span 12; }
.about-copy p {
  margin: 0 0 1em;
  max-width: 36em;
  font-size: clamp(15px, 1.7vw, 21px);
  line-height: 1.42;
  color: color-mix(in oklab, var(--ink) 84%, var(--paper));
}
/* the facts under the copy: three boxes on the grid, 4 cells wide, 2 tall */
.facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: var(--grid-size) 0 0;
  border: 1px solid color-mix(in oklab, var(--ink) 22%, var(--paper));
}
.facts div {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;   /* top-aligned: labels and values line up across the row */
  gap: 6px;
  min-height: calc(var(--grid-size) * 2 - 2px);
  padding: calc(var(--grid-size) / 3);
}
.facts div + div { border-left: 1px solid color-mix(in oklab, var(--ink) 22%, var(--paper)); }
.facts dt {
  font: 400 12px/1 var(--pixel-font);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: color-mix(in oklab, var(--ink) 58%, var(--paper));
}
.facts dd { margin: 0; font: 400 clamp(15px, calc(var(--grid-size) * 0.46), 26px)/1.1 var(--pixel-font); white-space: nowrap; }
.facts .hl { color: var(--maroon); }
/* a quiet second line under a fact: the building under Where, the exact spot under Inside */
.facts .fact-sub { margin-top: 2px; font: 400 13px/1.4 var(--nav-font); color: color-mix(in oklab, var(--ink) 58%, var(--paper)); }
/* "Level 00" never splits */
.facts .fact-sub span { white-space: nowrap; }
@media (max-width: 620px) { .facts .fact-sub .cc { white-space: normal; } }   /* phones: too narrow to hold it */
@media (max-width: 620px) { .facts .fact-sub { font-size: 12px; } .yr-c { display: none; } }   /* phones: "04 Nov 26" */

/* The photo reel: ETHIndia 2024 photos in two columns beside the copy (cols
   14-24), drifting in opposite directions through the full height of the
   section's paper field. Photo first: each is a plain photo with a small paper
   tag for its label; the reel's ends are cut on the field's grid lines. */
.about .wrap { min-height: calc(var(--grid-size) * 9); }   /* room for the reel */
.reel {
  --gap: calc(var(--grid-size) / 2.5);
  position: absolute;
  top: calc(var(--grid-size) + 1px);           /* the paper field's top line */
  bottom: 1px;
  left: calc(var(--grid-size) * (var(--lead) + 13));
  width: calc(var(--grid-size) * 11);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gap);
  overflow: hidden;
}
.reel-track { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; align-self: start; }   /* own height: columns may hold different counts */
/* sections.js moves the columns (own drift plus page scroll) */
.reel-track { will-change: transform; }
.reel-card { position: relative; display: block; margin: 0; color: var(--ink); text-decoration: none; -webkit-tap-highlight-color: transparent; }
.reel-card:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
@media (hover: hover) {
  .reel-card:hover .reel-cap { background: var(--ink); color: var(--paper); }
  .reel-card:hover .reel-cap::after { content: " ↗"; color: var(--marigold); }
}
.reel-card img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
.reel-card .reel-cap {
  position: absolute;
  left: calc(var(--grid-size) / 5);
  bottom: calc(var(--grid-size) / 5);
  max-width: calc(100% - var(--grid-size) * 2 / 5);   /* the same inset on the right, so a long caption never meets the edge */
  padding: 5px 8px;
  background: var(--paper);
  font: 400 12px/1.2 var(--pixel-font);
  color: var(--ink);
}

/* ---------- Speakers ---------- */
/* Separate cards a quarter cell apart:
   a square photo over a white name panel, in a light outline. An explicit column
   count, not auto-fill: sub-pixel cells made auto-fill drop a column. */
.speakers {
  display: grid;
  grid-template-columns: repeat(var(--per-row), minmax(0, 1fr));
  gap: calc(var(--grid-size) / 4);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* coming-soon board: loom tiles only, exactly one row at every breakpoint.
   Only while no speaker is announced; after that sections.js counts the tiles. */
.speakers:not(:has(.speaker:not(.speaker--more))) .speaker--more:nth-child(n + 5) { display: none; }
.speaker {
  display: grid;
  grid-template-rows: auto minmax(calc(var(--grid-size) * var(--card-t)), 1fr);   /* a taller card in the row grows its text panel, never the photo slot */
  border: 1px solid color-mix(in oklab, var(--ink) 14%, var(--paper));
  background: var(--paper);
  overflow: hidden;
}
.speaker img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; object-position: center; }
/* name and role together at the top, the handle at the foot of the panel, in
   even padding, so every card reads the same way */
.speaker-meta {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 4px;
  padding: calc(var(--grid-size) / 3);
  border-top: 1px solid color-mix(in oklab, var(--ink) 14%, var(--paper));
  font-size: 14px;
  line-height: 1.3;
}
.speaker-name { margin: 0; font-size: 17px; font-weight: 500; line-height: 1.2; }
.speaker-role { margin: 0; color: color-mix(in oklab, var(--ink) 84%, var(--paper)); }
.speaker-x { color: var(--ink); font-weight: 500; text-underline-offset: 3px; }
/* The whole card opens the speaker's X profile: the handle's link is stretched
   over the card (one link, so keyboard and screen readers see it once).
   Restrained, after craft.gustavofior.com: hover is instant and only marks the
   handle; a press shrinks the card a touch (less than a button would, it is a
   big surface); keyboard focus gets a plain ring, never one left by a click. */
.speaker { position: relative; -webkit-tap-highlight-color: transparent; }
.speaker:has(.speaker-x) { cursor: pointer; }
.speaker-x {
  margin-top: auto;
  padding-top: 10px;
  align-self: flex-start;
  font: 400 13px/1.3 var(--pixel-font);
  color: color-mix(in oklab, var(--ink) 58%, var(--paper));
  text-decoration: none;
}
.speaker-x::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.speaker-x:focus { outline: none; }
@media (hover: hover) {
  .speaker:has(.speaker-x:hover) .speaker-x { color: var(--ink); text-decoration: underline 2px var(--marigold); text-underline-offset: 3px; }
}
@media (prefers-reduced-motion: no-preference) {
  .speaker:has(.speaker-x) { transition: scale 100ms ease-out; }
  .speaker:has(.speaker-x:active) { scale: 0.985; }
}
.speaker:has(.speaker-x:focus-visible) { outline: 2px solid var(--ink); outline-offset: 3px; }

/* an empty slot: the photo square is an ink panel like the schedule's "on the
   loom" one; the name panel below stays paper like the other cards */
.more-art { aspect-ratio: 1; padding: calc(var(--grid-size) / 2); background: var(--ink); color: var(--paper); }
.more-t { margin: 0; font: 400 calc(var(--grid-size) * 0.7)/1.15 var(--pixel-font); }
.more-t em { display: block; font-style: normal; color: var(--marigold); }
.speaker--more .speaker-name {
  font: 400 15px/1.2 var(--pixel-font);
  color: color-mix(in oklab, var(--ink) 84%, var(--paper));
}
/* one line under the board while the lineup grows (MORE_SPEAKERS_SOON) */
/* only when the rows are full: a "More voices" card already says it otherwise */
.speakers:has(.speaker--more) + .speakers-more { display: none; }
.speakers-more {
  margin: var(--grid-size) 0 0;
  text-align: center;
  font: 400 calc(var(--grid-size) * 0.5)/1.2 var(--pixel-font);
}

/* ---------- Empty states ---------- */
.empty {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--grid-size) / 2);
  min-height: calc(var(--grid-size) * 3 + 1px);
  padding: 0 calc(var(--grid-size) / 2);
  list-style: none;
}
.empty-t { margin: 0; font: 400 calc(var(--grid-size) * 0.6)/1.2 var(--pixel-font); }

/* ---------- Coming soon ----------
   An ink panel (the ticker's band, as a block) set INTO the real structure: a card
   slot in the speaker grid, a row on the schedule board. */
.soon-panel {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: calc(var(--grid-size) / 2);
  padding: calc(var(--grid-size) / 2);
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
  list-style: none;
}
.soon-t {
  margin: 0;
  font: 400 calc(var(--grid-size) * 0.7)/1.15 var(--pixel-font);
  text-wrap: balance;
}
.soon-t em { font-style: normal; color: var(--marigold); }
.soon-link {
  align-self: flex-start;
  color: var(--paper);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.soon-link:focus-visible { outline: 2px solid var(--paper); outline-offset: 4px; border-radius: 4px; }
/* schedule: the panel is one full-width board row */
.soon-panel--row {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  min-height: calc(var(--grid-size) * 2);
  padding-block: 0;
}
.soon-panel--row .soon-link { align-self: center; }
.soon-panel--row .soon-t { font-size: calc(var(--grid-size) * 0.6); }

/* ---------- Schedule ---------- */
.slots { margin: 0; padding: 0; list-style: none; }
.slots::after { content: ""; display: block; height: 1px; background: var(--rule); }
.slots:has(.empty, .soon-panel)::after { display: none; }   /* ghost rows fade out instead */
/* time | what (title, then who it's with) | kind. The speakers sit right after
   the title they belong to instead of in a far column of their own. */
.slot {
  display: grid;
  grid-template-columns: calc(var(--grid-size) * 4) 1fr calc(var(--grid-size) * 4);
  align-items: center;
  padding: 8px 0;
  border-top: 1px solid var(--rule);
}
.slot > * { padding-right: calc(var(--grid-size) / 4); }
.slot-time { font: 400 clamp(15px, 1.6vw, 20px)/1.3 var(--pixel-font); white-space: nowrap; }
.slot-what { line-height: 1.3; }
.slot-title { font-size: clamp(15px, 1.6vw, 20px); font-weight: 500; margin-right: 0.6em; }
.slot-who { font-size: 15px; color: color-mix(in oklab, var(--ink) 84%, var(--paper)); }
.slot-tag { justify-self: end; padding-right: 0; }
.slot-tag span {
  display: inline-block;
  padding: 5px 10px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  font: 400 13px/1 var(--pixel-font);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
/* breaks: lighter. Regular weight, muted, tag unboxed. */
.slot--break .slot-title { font-weight: 400; color: color-mix(in oklab, var(--ink) 84%, var(--paper)); }
.slot--break .slot-tag span { border-color: transparent; padding-left: 0; }
/* session types in the hero's folk colours; breaks stay quiet */
.slot--talk .slot-tag span     { background: var(--indigo); border-color: var(--indigo); color: var(--paper); }
.slot--panel .slot-tag span    { background: var(--maroon); border-color: var(--maroon); color: var(--paper); }
.slot--workshop .slot-tag span { background: var(--leaf);   border-color: var(--leaf);   color: var(--paper); }
/* coming-soon ghost rows: the board's shape, fading out under the panel */
.slot--ghost { color: color-mix(in oklab, var(--ink) 84%, var(--paper)); }
.slot--ghost .slot-title { font-weight: 400; }
.soon-panel + .slot--ghost { border-top-color: var(--ink); }
.slot--ghost:nth-child(3) > * { opacity: 0.7; }
.slot--ghost:nth-child(4) > * { opacity: 0.45; }
.slot--ghost:nth-child(5) > * { opacity: 0.25; }

/* ---------- FAQ ---------- */
/* title over a short "ask us on X" note on the left, questions on the right */
.faq .wrap { grid-template-rows: auto 1fr; }
.faq .sec-head { grid-column: 1 / span 7; margin-bottom: 0; }   /* the note sits right under the title */
.qas { grid-column: 9 / span 16; grid-row: 1 / span 2; }
.faq-aside {
  grid-column: 1 / span 6;
  grid-row: 2;
  align-self: start;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}
.faq-aside p {
  margin: 0;
  font-size: clamp(15px, 1.2vw, 18px);
  line-height: 1.45;
  color: color-mix(in oklab, var(--ink) 72%, var(--paper));
}
/* a top line that adds no height: a 1px background stripe (an inset box-shadow left a
   hairline down the right edge in some Android browsers) */
.qa { background: linear-gradient(var(--rule), var(--rule)) top / 100% 1px no-repeat; }
.qas:has(.qa)::after { content: ""; display: block; height: 1px; background: var(--rule); }
.qa summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--grid-size);
  min-height: var(--grid-size);
  padding: 10px 0;
  font-size: clamp(16px, 1.4vw, 20px);
  font-weight: 500;
  line-height: 1.3;
  cursor: pointer;
  list-style: none;
  /* a toggle, not text: quick or double clicks shouldn't select the question */
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.qa summary::-webkit-details-marker { display: none; }
/* row numbers in the pixel face; the open question's turns madder */
.qa summary { justify-content: flex-start; }
.qa-n {
  flex: none;
  width: var(--grid-size);
  margin-right: calc(var(--grid-size) * -1);   /* cancels the summary gap: the question starts one cell in */
  font: 400 14px/1 var(--pixel-font);
  color: color-mix(in oklab, var(--ink) 50%, var(--paper));
}
.qa[open]:not(.is-closing) .qa-n { color: var(--maroon); }
.qa-q { flex: 1; }
.qa summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* plus / minus on a 7x7 pixel grid in the ink colour: the vertical bar turns
   flat as a question opens, so the + becomes a − */
/* stitched like the section marks: a 5×5 chart, square stitches with a gap, in
   ink, each 3px with a 1px gap so it stays crisp. The vertical stitches turn and fade as a question opens: + becomes −. */
.pm { --st: 4px; position: relative; flex: none; width: calc(var(--st) * 5); height: calc(var(--st) * 5); }
.pm::before, .pm::after { content: ""; position: absolute; background: center / 100% 100% no-repeat; }
.pm::before { left: 0; right: 0; top: calc(var(--st) * 2); height: var(--st); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 1' shape-rendering='crispEdges' fill='%230a0a0a'%3E%3Crect x='0' y='0' width='0.75' height='0.75'/%3E%3Crect x='1' y='0' width='0.75' height='0.75'/%3E%3Crect x='2' y='0' width='0.75' height='0.75'/%3E%3Crect x='3' y='0' width='0.75' height='0.75'/%3E%3Crect x='4' y='0' width='0.75' height='0.75'/%3E%3C/svg%3E"); }
.pm::after {
  top: 0; bottom: 0; left: calc(var(--st) * 2); width: var(--st); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 5' shape-rendering='crispEdges' fill='%230a0a0a'%3E%3Crect x='0' y='0' width='0.75' height='0.75'/%3E%3Crect x='0' y='1' width='0.75' height='0.75'/%3E%3Crect x='0' y='3' width='0.75' height='0.75'/%3E%3Crect x='0' y='4' width='0.75' height='0.75'/%3E%3C/svg%3E");
  transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.2s ease;
}
.qa[open]:not(.is-closing) .pm::after { transform: rotate(90deg); opacity: 0; }
/* the answer eases in a beat after the row starts to open */
@media (prefers-reduced-motion: no-preference) {
  .qa-a { transition: opacity 0.3s ease 0.06s, transform 0.32s cubic-bezier(0.22, 1, 0.36, 1); }
  .qa:not([open]) .qa-a, .qa.is-opening .qa-a, .qa.is-closing .qa-a { opacity: 0; transform: translateY(-6px); }
  .qa[open]:not(.is-opening):not(.is-closing) .qa-a { opacity: 1; transform: none; }
}
/* hover only where there is one: a tap on a phone would leave the question grey */
@media (hover: hover) {
  .qa summary:hover { color: color-mix(in oklab, var(--ink) 70%, var(--paper)); }
}
.qa-a { padding: 0 0 calc(var(--grid-size) / 2) var(--grid-size); max-width: 40rem; }
.qa-a p {
  margin: 0 0 0.6em;
  font-size: clamp(15px, 1.2vw, 18px);
  line-height: 1.6;
  color: color-mix(in oklab, var(--ink) 84%, var(--paper));
}

/* ---------- Footer ---------- */
.foot-wrap {
  padding-top: calc(var(--grid-size) * 2);
  padding-bottom: var(--grid-size);
  align-items: center;
}
.foot-line {
  margin: 0;
  font: 400 calc(var(--grid-size) * 1.8)/calc(var(--grid-size) * 3) var(--pixel-font);
}
.foot-sub {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 0.6em;
  min-height: var(--grid-size);
  margin: 0;
  font: 400 clamp(15px, calc(var(--grid-size) * 0.38), 22px)/1.3 var(--pixel-font);
  color: color-mix(in oklab, var(--ink) 72%, var(--paper));
}
.foot-sub i { font-style: normal; color: var(--maroon); }
.foot-cta { grid-column: 1 / -1; justify-self: start; margin: calc(var(--grid-size) / 2) 0 calc(var(--grid-size) * 2); }
/* links left, signature right, across the full span; the links sit centred
   against the two-line signature */
.foot-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: calc(var(--grid-size) / 2);
}
.socials {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 28px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.socials li:has(a[href=""]) { display: none; }   /* render only links with a URL */
/* X logo + handle, as on the speaker cards: the logo sits on the text's baseline at
   cap height, so it lines up with the letters, not with the line box and underline */
.x-logo { display: inline-block; width: 0.7em; height: 0.7em; margin-right: 0.45em; vertical-align: -0.08em; }   /* a hair under the baseline: the handles are mostly lowercase */
/* the footer's X matches the Devfolio mark beside it (drawn X ~18px tall), centred on the handle */
.socials a, .foot-org a { color: var(--ink); font-weight: 500; text-underline-offset: 3px; }
/* handles and addresses read like the speakers' X handles: pixel face, soft grey, no
   underline; hover inks them and draws the marigold underline */
.socials .x-link, .px-link {
  font: 400 15px/1.3 var(--pixel-font);
  color: color-mix(in oklab, var(--ink) 58%, var(--paper));
  text-decoration: none;
}
.faq-aside .px-link { font-size: 0.95em; }   /* inline in the note: sized with the sentence */
.px-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 2px; }
.socials .x-link .x-logo, .px-link .x-logo { color: var(--ink); }
/* the X logo inside a pixel handle: cap height, on the baseline */
/* one size for every @ethindiaco: 15px pixel text, a 20px X centred on it */
.socials .x-logo, .px-link .x-logo { width: 20px; height: 20px; margin-right: 8px; vertical-align: -0.33em; }
/* the envelope before an email address */
.mail-line .i-mail { display: inline-block; width: 1.1em; height: 0.8em; margin-right: 0.5em; vertical-align: -0.05em; color: var(--ink); }
/* copy button after an email: an icon the size of the text, a tick once copied */
.copy-btn {
  position: relative;
  display: inline-grid; place-items: center;
  width: 28px; height: 28px; margin-left: 4px; padding: 0;
  vertical-align: middle;
  border: 0; border-radius: 6px; background: none; cursor: pointer;
  color: color-mix(in oklab, var(--ink) 58%, var(--paper));
  -webkit-tap-highlight-color: transparent;
}
.copy-btn svg { grid-area: 1 / 1; width: 14px; height: 14px; }
.copy-btn .i-done, .copy-btn.is-done .i-copy { display: none; }
.copy-btn.is-done .i-done { display: block; color: var(--ink); }
.copy-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.copy-note { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
@media (hover: hover) { .copy-btn:hover { color: var(--ink); background: color-mix(in oklab, var(--ink) 6%, var(--paper)); } }
@media (hover: hover) {
  .socials .x-link:hover, .px-link:hover { color: var(--ink); text-decoration: underline 2px var(--marigold); text-underline-offset: 3px; }
}
.socials a:focus-visible, .foot-org a:focus-visible, .foot-cta:focus-visible {
  outline: 2px solid var(--ink); outline-offset: 4px;
}
.foot-org {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 0;
  font-size: 15px;
  color: color-mix(in oklab, var(--ink) 84%, var(--paper));
}
.foot-org img { display: block; height: 18px; width: auto; }
.foot-org { justify-content: flex-end; }

/* the live teaser's bottom fringe (ethindia.co): the 1200x675 composition at full
   width, capped by height like the teaser's frame, motifs bleeding off the edges */
.foot-band {
  position: relative;
  height: min(56.25vw, 68vh);
  /* the composition's top ~30% is open grid: tuck it up under the sign-off */
  margin-top: calc(min(56.25vw, 68vh) * -0.3);
  overflow: hidden;
  pointer-events: none;
}
.foot-band-art { position: absolute; inset: 0; }
.foot-band-art .rug { position: absolute; left: var(--l); top: var(--t); width: var(--w); height: auto; }
.foot-band-art .rug { transition: scale 0.25s var(--ease), rotate 0.25s var(--ease); }

/* ---------- Pop the rugs (footer band mini game, sections.js; from the original teaser) ----------
   Animations use the individual scale/rotate/translate properties so they stack
   on top of the parallax `transform` instead of fighting it. */
html.over-motif, html.over-motif * { cursor: pointer; }
.rug.is-hover { scale: 1.05; rotate: -2deg; }
.rug:focus { outline: none; }
.rug:focus-visible { scale: 1.05; rotate: -2deg; outline: 2px dashed var(--ink); outline-offset: 4px; }
.rug.is-popping { animation: motifPop 0.45s cubic-bezier(0.3, 0.6, 0.4, 1) forwards; }
.rug.is-popped { opacity: 0; visibility: hidden; }
.rug.is-back { animation: motifBack 0.75s var(--ease) both; }
.rug.is-spin { animation: motifSpin 0.9s var(--ease) var(--d, 0ms) both; }
@keyframes motifPop {
  30%  { scale: 1.18; rotate: -6deg; }
  100% { scale: 0.2; rotate: 25deg; translate: 0 -40px; opacity: 0; }
}
@keyframes motifBack {
  0%   { scale: 0.3; translate: 0 50px; opacity: 0; }
  60%  { scale: 1.08; translate: 0 -6px; opacity: 1; }
  100% { scale: 1; translate: 0 0; opacity: 1; }
}
@keyframes motifSpin {
  0%   { scale: 0.3; rotate: -180deg; opacity: 0; }
  60%  { scale: 1.12; rotate: 12deg; opacity: 1; }
  100% { scale: 1; rotate: 0deg; opacity: 1; }
}
@keyframes motifFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes motifFadeOut { to { opacity: 0; } }

/* the secret under the rugs: hidden until all nine are lifted, then it
   swooshes up from the bottom; drops away again as the rugs spin back in */
.under-msg {
  position: absolute;
  left: 50%;
  top: 87%;
  margin: 0;
  translate: -50% -50%;
  font-family: var(--pixel-font);
  font-size: clamp(22px, 3.4vw, 48px);
  line-height: 1.05;
  text-align: center;
  white-space: nowrap;
  color: var(--ink);
  opacity: 0;
}
.under-msg .ch { display: inline-block; white-space: pre; }
/* in: the line eases up from below while its letters float in one after another */
.under-msg.is-revealed { animation: msgRise 1.1s cubic-bezier(0.16, 1, 0.3, 1) both; }
.under-msg.is-revealed .ch { animation: chRise 0.9s cubic-bezier(0.16, 1, 0.3, 1) calc(var(--i) * 32ms) both; }
@keyframes msgRise {
  from { opacity: 1; translate: -50% calc(-50% + 56px); }
  to   { opacity: 1; translate: -50% -50%; }
}
@keyframes chRise {
  from { opacity: 0; translate: 0 110%; }
  to   { opacity: 1; translate: 0 0; }
}
/* out: like cats hiding — each letter perks up, crouches and darts down behind
   the rugs, in a scattered order (--o) */
.under-msg.is-leaving { opacity: 1; }   /* stays behind the returning rugs — the letters duck under them */
.under-msg.is-leaving .ch {
  transform-origin: 50% 100%;
  animation: chDuck 0.55s calc(var(--o) * 28ms) both;
}
@keyframes chDuck {
  0%   { translate: 0 0; scale: 1; animation-timing-function: cubic-bezier(0.3, 0, 0.3, 1); }
  28%  { translate: 0 -22%; scale: 0.94 1.1; animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1); }
  45%  { translate: 0 8%; scale: 1.1 0.82; animation-timing-function: cubic-bezier(0.6, 0, 0.9, 0.4); }
  85%  { opacity: 1; }
  100% { opacity: 0; translate: 0 280%; scale: 0.9 1.15; }
}
.under-msg span { display: inline; }
/* phones: two lines, "Congrats!" over "You pulled all the rugs.", so it fits the screen */
@media (max-width: 620px) {
  .under-msg { font-size: clamp(20px, 6.4vw, 28px); line-height: 1.15; }
  .under-msg span { display: block; }
}

.pop-count {
  position: absolute;
  z-index: 5;
  bottom: var(--grid-size);
  right: calc(var(--grid-size) * var(--lead));
  padding: 6px 12px;
  border: 1px solid color-mix(in oklab, var(--ink) 16%, var(--paper));
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font: 400 15px/1 var(--pixel-font);
  pointer-events: none;
  opacity: 0;
  translate: 0 -6px;
  transition: opacity 0.3s var(--ease), translate 0.3s var(--ease), background 0.3s var(--ease), color 0.3s var(--ease);
}
.pop-count.is-on { opacity: 1; translate: 0 0; }
.pop-count.is-win { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.pop-count.bump { animation: popBump 0.3s var(--ease); }
@keyframes popBump { 40% { scale: 1.15; } }
.pop-bit {
  position: fixed;
  z-index: 5;
  width: 8px; height: 8px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  pointer-events: none;
}


/* ---------- Paper fields ----------
   The grid frames the content instead of running under it. Each section sits on a
   clean paper field cut into the graph paper on cell lines: the content span plus
   one cell each side (full-bleed on tablet and phone, where the margin is one cell),
   starting one cell above the title. The grid shows only in the margins and the
   one-cell bands between sections, so no line ever crosses text. The 1px inset
   keeps the field's top and left grid line drawn.
   Each section paints its own grid from its own top edge (on an opaque paper ground),
   not the page's: Safari rounds every repeat of a fractional cell (e.g. 32.5px) to
   device pixels, so a page-long grid drifts by half a cell near the footer and the
   bands' top and bottom lines slid under the fields. Restarting per section keeps
   the drift to nothing. */
.sec, .site-foot {
  --fx: calc(var(--grid-size) * (var(--lead) - 1));
  --fw: calc(var(--grid-size) * (var(--span) + 2));
  background:
    linear-gradient(var(--paper), var(--paper)) no-repeat
      calc(var(--fx) + 1px) calc(var(--grid-size) + 1px) /
      calc(var(--fw) - 1px) calc(100% - var(--grid-size) - 1px),
    linear-gradient(to right, var(--grid) 1px, transparent 1px) 0 0 / var(--grid-size) var(--grid-size),
    linear-gradient(to bottom, var(--grid) 1px, transparent 1px) 0 0 / var(--grid-size) var(--grid-size),
    var(--paper);
}
/* footer: the field stops where the motif band starts, so the art lands on grid */
.site-foot {
  background-size: calc(var(--fw) - 1px) calc(100% - min(56.25vw, 68vh) * 0.7 - var(--grid-size) - 1px),
    var(--grid-size) var(--grid-size), var(--grid-size) var(--grid-size);
}
/* ---------- Tablet ---------- */
@media (max-width: 900px) {
  .more, .site-foot { --lead: 1; --span: 21; --card-t: 3; --per-row: 3; }
  .faq-aside { grid-column: 1 / -1; grid-row: auto; order: 3; margin-top: calc(var(--grid-size) * 0.75); gap: 8px; }
  .faq .wrap { grid-template-rows: none; }
  .faq .sec-head, .qas { grid-column: 1 / -1; grid-row: auto; }
  .speakers:not(:has(.speaker:not(.speaker--more))) .speaker--more:nth-child(n + 4) { display: none; }
  .about-copy { grid-column: 1 / -1; }
  .about .wrap { min-height: 0; }
  .reel { position: relative; inset: auto; grid-column: 1 / -1; width: auto; height: calc(var(--grid-size) * 14); margin-top: var(--grid-size); }
}

@media (max-width: 620px) {
  .reel-card .reel-cap { padding: 4px 6px; font-size: 11px; }
  .qa summary { padding: 14px 0; }   /* rows take their natural height: the same space around one- and two-line questions */
  .qa-a { padding-bottom: 14px; }
  .more, .site-foot { --span: 10; --per-row: 1; }
  /* speakers: one card per row, the photo a 4-cell square on the left and the
     name, role and handle beside it, so long roles have room and every card is
     the same height. A full lineup needs no "More voices" filler at one per row. */
  .speaker {
    grid-template-rows: none;
    grid-template-columns: calc(var(--grid-size) * 4) minmax(0, 1fr);
    height: calc(var(--grid-size) * 4);
  }
  .speaker img, .more-art { width: 100%; height: 100%; }
  .speaker-meta {
    border-top: 0;
    border-left: 1px solid color-mix(in oklab, var(--ink) 14%, var(--paper));
    justify-content: center;
    padding: 0 calc(var(--grid-size) / 2);
    gap: 3px;
  }
  .speaker-x { margin-top: 0; padding-top: 4px; }
  .speaker-name { font-size: 17px; }
  .more-art { padding: calc(var(--grid-size) / 4); }
  .more-t { font-size: calc(var(--grid-size) * 0.42); }
  .foot-line { font-size: calc(var(--grid-size) * 0.94); line-height: calc(var(--grid-size) * 2); }   /* one line at 12 cells across */
  .empty { padding: calc(var(--grid-size) / 2); }
  .empty-t { font-size: 20px; }
  .soon-panel { padding: 12px; }
  .soon-panel--row { flex-direction: column; align-items: flex-start; justify-content: center; gap: 8px; padding-block: 12px; }
  .soon-panel--row .soon-t { font-size: 22px; }
  .soon-panel--row .soon-link { align-self: flex-start; }
  .slot--ghost .slot-what { grid-area: 1 / 2; }
  /* schedule: time + kind on one line, what below; a break is one line */
  .slot { grid-template-columns: auto 1fr auto; gap: 6px 12px; }
  .slot > * { padding-right: 0; }
  .slot-time { grid-area: 1 / 1; }
  .slot-tag { grid-area: 1 / 3; }
  .slot-what { grid-area: 2 / 1 / auto / -1; }
  .slot--break .slot-what { grid-area: 1 / 2; }
  .slot-who { font-size: 14px; }
  /* phone: the X link, then one ruled line with the organiser left and the © right */
  .foot-meta { flex-direction: column; align-items: stretch; gap: 16px; }
  .foot-sign {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-top: 14px;
    border-top: 1px solid color-mix(in oklab, var(--ink) 18%, var(--paper));
  }
  .foot-org { font-size: 14px; }
  .speakers:not(:has(.speaker:not(.speaker--more))) .speaker--more:nth-child(n + 2) { display: none; }
  .speakers-more { font-size: 18px; }
  .sec-title { font-size: var(--grid-size); line-height: calc(var(--grid-size) * 2); }
}
