/* Supercon 2026 - one page.

   Printed on the grit board's darkclassic preset: white stock inverted, so
   light toner on a near-black page. The prints - header, paper, portraits,
   band - are baked into img/ and header/ by tools/build_site.py; everything
   the page sets itself is matched to them - the same black, the same
   off-white ink, one red for the things you can press. */

:root{
  /* the page's paper, baked - see body::before - and twice the size for
     sharp screens, so the grain stays fine rather than blown up */
  --stock: -webkit-image-set(url(../img/stock.webp) 1x, url(../img/stock-2x.webp) 2x);
  --stock-light: -webkit-image-set(url(../img/stock-light.webp) 1x, url(../img/stock-light-2x.webp) 2x);
  --page: #232323;      /* the darkclassic print's own page, sampled */
  --page-2: #2b2b2a;
  --ink: #ecebe6;
  --ink-2: rgba(236, 235, 230, .74);
  --ink-3: rgba(236, 235, 230, .5);
  --rule: rgba(236, 235, 230, .2);
  --accent: #ff4433;
  --accent-ink: #140302;
  --paper-ink: #2e2e2e; /* toner on the torn sheets' light stock, sampled - the bar, over the hero */
  /* the torn sheets - the hero and the tickets band - print the other way
     round: their art inverted to dark toner on light stock, and this is the
     page colour inverted with it, for before the art lands */
  --negative: #dcdcdc;
  --sans: Inter, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;
  --bar: 64px;
  --tear: clamp(36px, 4vw, 56px);   /* how deep a torn edge bites */
  --tear-w: calc(var(--tear) * 3200 / 56);   /* one tile of it, tools/make_tear.py */
  --gutter: clamp(16px, 4vw, 48px);
}

*,*::before,*::after{ box-sizing: border-box; }
html{ scroll-behavior: smooth; scroll-padding-top: calc(var(--bar) + 12px); }
@media (prefers-reduced-motion: reduce){ html{ scroll-behavior: auto; } }
body{
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font: 400 17px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
/* the page itself: a blank sheet through the header's copier (img/stock.webp,
   baked by tools/build_site.py), held still behind the scroll so it reads as
   one sheet of paper. The flat colour is the same page, sampled, for before
   it lands. */
body::before{
  content: "";
  position: fixed; inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--page) var(--stock) center / cover no-repeat;
}
img{ display: block; max-width: 100%; }
a{ color: inherit; }
.defs{ position: absolute; width: 0; height: 0; }
.sr{
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
.wrap{ width: 100%; max-width: 1360px; margin: 0 auto; padding: 0 var(--gutter); }
:focus-visible{ outline: 2px solid var(--accent); outline-offset: 3px; }
/* the note index.html shows when js/site.js never got the program onto the page */
.load-fail{
  position: fixed; left: 16px; right: 16px; bottom: 16px; z-index: 100;
  margin: 0; padding: 14px 18px;
  background: var(--accent); color: var(--accent-ink);
  font: 600 16px/1.4 var(--sans);
}
.load-fail[hidden]{ display: none; }
.load-fail a{ margin-left: .5em; }

/* ---- bar ---------------------------------------------------------------- */
/* At the top of the page the bar has no ground of its own: the mark and the
   words are printed straight onto the hero sheet, dark toner like the art
   around them. Scrolled past the sheet (site.js sets .solid), a plain dark
   bar slides in under them and the ink turns light, the way the rest of the
   page prints. Fixed, so the hero runs up under it to the top of the screen. */
.bar{
  position: fixed; top: 0; left: 0; right: 0; z-index: 40;
  height: var(--bar);
  display: flex; align-items: center; gap: 24px;
  padding: 0 var(--gutter);
  --bar-ink: var(--paper-ink);
  --bar-ink-2: var(--paper-ink);   /* on the sheet, full strength: it has the art to read over */
  --bar-patch: var(--negative);
  /* on the sheet the bar's words go through the copier as hard as the art
     around them; on the dark bar, lightly */
  --bar-copy: url(#copy-bar);
  --bar-weight: 700;              /* enough ink in the letters for the speckle to show */
}
.bar.solid{ --bar-ink: var(--ink); --bar-ink-2: var(--ink-2); --bar-patch: transparent; --bar-copy: url(#copy-sm); --bar-weight: 500; }
.bar::before{
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  /* the page's own printed stock (--stock, viewport sized), but a strip cut
     from lower down it so its grain doesn't line up with the page around
     it, and a shade darker so it reads as a band laid over */
  background:
    linear-gradient(rgba(0, 0, 0, .22), rgba(0, 0, 0, .22)),
    var(--page) var(--stock) center -38vh / 100vw 100vh;
  border-bottom: 1px solid var(--rule);
  transform: translateY(-101%);
  transition: transform .25s ease-out;
  pointer-events: none;
}
.bar.solid::before{ transform: none; }
@media (prefers-reduced-motion: reduce){ .bar::before{ transition: none; } }
.bar-logo img{ height: 38px; width: auto; filter: invert(.15) var(--bar-copy); }   /* black and white to the sheet's toner and stock */
.bar.solid .bar-logo img{ filter: invert(1) var(--bar-copy); }
.bar-nav{ display: flex; align-items: center; gap: 8px; margin-left: 12px; }
.bar-nav a{
  font: var(--bar-weight) 13px/1 var(--mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 10px 12px;
  color: var(--bar-ink-2);
  /* on the sheet each word gets a patch of bare stock knocked out of the
     art behind it - the copier roughs the patch's edge along with the type */
  /* just around the letters, inside the padding that makes the click area */
  background: linear-gradient(var(--bar-patch), var(--bar-patch)) center / calc(100% - 16px) calc(100% - 14px) no-repeat;
  filter: var(--bar-copy);
  transition: color .25s;
}
.bar-nav a:hover, .bar-nav a:focus-visible{ color: var(--accent); }
/* the stamp again, small - see .btn - but inked solid, the one spot of
   colour on the sheet and on the bar. Always in the bar, at every width */
.bar-nav .bar-cta{ display: none; }   /* the menu's own copy, for phones */
.bar-cta{
  margin-left: auto;
  flex: none;
  font: 500 13px/1 var(--mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: var(--accent-ink);
  padding: 11px 16px 10px;
  position: relative; isolation: isolate;
  filter: var(--bar-copy);
  transition: color .12s;
}
/* its ink, behind the label: ragged and still like the other stamps (.btn),
   and on hover it lifts to an outline that boils */
.bar-cta::before{
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  background: var(--accent);
  border: 2px solid var(--accent);
  filter: url(#boil-0);
  transition: background-color .12s;
}
.bar-cta:hover, .bar-cta:focus-visible{ color: var(--accent); }
.bar-cta:hover::before, .bar-cta:focus-visible::before{
  background: transparent;
  animation: boil-box .36s steps(1) infinite;
}
@media (prefers-reduced-motion: reduce){
  .bar-cta:hover::before, .bar-cta:focus-visible::before{ animation: none; }
}
/* three bars sized to the mark beside it: as wide as it nearly, its stroke
   weight, filling most of its height */
.bar-toggle{
  display: none;
  margin-right: -8px;
  width: 48px; height: 48px;
  background: none; border: 0; padding: 0 8px;
  cursor: pointer;
}
.bar-toggle span{ display: block; height: 4px; background: var(--bar-ink); margin: 7px 0; transition: background-color .25s; }

@media (max-width: 860px){
  .bar-toggle{ display: block; }
  .bar-nav{
    position: absolute; top: var(--bar); left: 0; right: 0;
    margin: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: rgba(35, 35, 35, .98);
    border-bottom: 1px solid var(--rule);
    padding: 8px var(--gutter) 16px;
    display: none;
  }
  .bar-nav.open{ display: flex; }
  /* the bar keeps only the mark and the menu button; the ticket stamp
     moves into the menu */
  .bar > .bar-cta{ display: none; }
  .bar-toggle{ margin-left: auto; }
  .bar-nav .bar-cta{
    display: block; margin: 18px 0 4px; padding: 16px; text-align: center; font-size: 15px;
    color: var(--accent-ink); background: none;
  }
  .bar-nav .bar-cta:hover, .bar-nav .bar-cta:focus-visible{ color: var(--accent); }
  .bar-nav a{ padding: 14px 0; font-size: 15px; border-bottom: 1px solid var(--rule); }
}

/* ---- hero --------------------------------------------------------------- */
.hero{
  position: relative;
  /* 80% of the screen, whatever its shape, so the next section peeks in
     under the tear. svh, so a phone's address bar coming and going does
     not resize it mid-scroll */
  height: 80vh;
  height: 80svh;
  min-height: 300px;
  background: var(--negative);   /* a torn sheet */
  overflow: hidden;
}
/* the three stills, stacked; one is .on at a time - a hard cut, no fade.
   Cover crops the 16:9 frame to the screen's shape, keeping its bottom:
   the sheet is torn along there, so that is the edge that has to hold. */
.hero-stills{
  position: absolute; inset: 0;
  filter: invert(1);
  opacity: 0;
  transition: opacity .9s ease;
}
.hero.live .hero-stills{ opacity: 1; }
.hero-stills img{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center bottom;
  visibility: hidden;
}
.hero-stills img.on{ visibility: visible; }
/* the video after the stills, over them while it plays. A light-stock
   render, already the sheet's colours, so it is not inverted. Centred, like
   the stills marked so in tools/build_site.py (HEADER_CENTRED) */
.hero-video{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  visibility: hidden;
}
.hero-video.on{ visibility: visible; }

/* ---- torn edge ---------------------------------------------------------- */
/* The hero is a sheet torn off along the bottom: the printed face tears a
   little higher than the paper core, so a frayed strip of bare stock shows
   between them, and the sheet lies on the page with the content running in
   from under it. Both edges are one 3200 x 56 tile (tools/make_tear.py). */
.tear{
  position: relative;
  z-index: 2;
  /* a tight contact shadow where the edge meets the page, then the sheet's
     own, soft and short - it lies flat */
  filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, .3)) drop-shadow(0 6px 14px rgba(0, 0, 0, .28));
}
.tear::before{
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: var(--tear);
  background: url(../img/edges/tear-edge.svg) left bottom / var(--tear-w) 100% repeat-x;
}
.tear .hero{
  -webkit-mask:
    linear-gradient(#000 0 0) top / 100% calc(100% - var(--tear) + 1px) no-repeat,
    url(../img/edges/tear-face.svg) left bottom / var(--tear-w) var(--tear) repeat-x;
  mask:
    linear-gradient(#000 0 0) top / 100% calc(100% - var(--tear) + 1px) no-repeat,
    url(../img/edges/tear-face.svg) left bottom / var(--tear-w) var(--tear) repeat-x;
}
.tear + section{ margin-top: calc(var(--tear) * -1); }

/* ---- type --------------------------------------------------------------- */
.kicker{
  margin: 0 0 14px;
  font: 500 13px/1.2 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
}
.big{
  margin: 0;
  font: 800 clamp(40px, 7vw, 104px)/.9 var(--sans);
  letter-spacing: -.055em;
  text-transform: uppercase;
  filter: url(#copy);
  text-wrap: balance;
}
.big sup{
  font: 500 clamp(14px, 1.4vw, 18px)/1 var(--mono);
  letter-spacing: .04em;
  vertical-align: top;
  color: var(--ink-3);
  margin-left: .3em;
  filter: none;
}
.sec-head{ margin-bottom: clamp(32px, 5vw, 56px); }
.sec-intro{
  max-width: 62ch;
  margin: 22px 0 0;
  color: var(--ink-2);
  font-size: 18px;
}

section.wrap{ padding-top: clamp(72px, 10vw, 128px); }
/* the first section under the torn header: more room above, where the tear
   bites, and a clear break below before the program starts */
.about.wrap{
  padding-top: clamp(96px, 12vw, 168px);
  padding-bottom: clamp(48px, 7vw, 104px);
}
.about-head{ display: flex; flex-direction: column; gap: clamp(28px, 3.5vw, 44px); }
/* the blurb: set like copy on the sheets, small mono, the last line landing
   in full ink */
.manifesto{ max-width: 52ch; }
.manifesto p{
  margin: 0;
  font: 400 14px/1.75 var(--mono);
  color: var(--ink-3);
  text-wrap: pretty;
}
.manifesto .manifesto-end{
  margin-top: 14px;
  color: var(--ink);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}

/* ---- about -------------------------------------------------------------- */
.about-grid{
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(28px, 5vw, 72px);
  /* top, not bottom: when the copy runs taller than the headline (mid
     widths) the headline stays under its kicker instead of sinking */
  align-items: start;
}
.about-copy p{ margin: 0; color: var(--ink-2); font-size: 18px; }
.facts{ margin: 28px 0 32px; border-top: 1px solid var(--rule); }
.facts div{
  display: grid; grid-template-columns: 88px 1fr; gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}
.facts dt{
  font: 500 12px/1.9 var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3);
}
.facts dd{ margin: 0; font-weight: 600; }
@media (max-width: 860px){ .about-grid{ grid-template-columns: 1fr; } }
/* On a phone the display type is half its desktop size, and #copy's grit is
   sized for the big one - it wears small letters through. #copy-md there. */
@media (max-width: 760px){
  .big{ filter: url(#copy-md); }
}

/* Buttons are rubber stamps, set straight: a red outline, through the
   same copier as the type. Hover inks the stamp in. */
.btn{
  --edge: 2px;
  position: relative; isolation: isolate;
  display: inline-flex; align-items: center; gap: 12px;
  padding: calc(15px + var(--edge)) calc(22px + var(--edge)) calc(14px + var(--edge));
  color: var(--accent);
  font: 700 14px/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  text-decoration: none;
  filter: url(#copy-sm);
  transition: color .12s;
}
/* the stamp's frame - and on hover its ink - drawn behind the label through
   the rough line filters (#boil-0..2): ragged and still at rest, inked in and
   boiling on hover, like the card rules and the underlines */
.btn::before{
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  border: var(--edge) solid var(--accent);
  filter: url(#boil-0);
  transition: background-color .12s;
}
.btn:hover, .btn:focus-visible{ color: var(--accent-ink); }
.btn:hover::before, .btn:focus-visible::before{
  background: var(--accent);
  animation: boil-box .36s steps(1) infinite;
}
.btn:active::before{ background: #d9301f; border-color: #d9301f; }
.btn-big{ --edge: 3px; font-size: 16px; padding: calc(19px + var(--edge)) calc(28px + var(--edge)) calc(18px + var(--edge)); }
@keyframes boil-box{
  0%     { filter: url(#boil-0); }
  33.3%  { filter: url(#boil-1); transform: translate(-.5px, .3px); }
  66.6%  { filter: url(#boil-2); transform: translate(.5px, -.3px); }
}
@media (prefers-reduced-motion: reduce){
  .btn:hover::before, .btn:focus-visible::before{ animation: none; filter: url(#boil-0); }
}

/* ---- program cards ------------------------------------------------------ */
.grid{
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: 48px 28px;
}
.card{
  position: relative;
  border-top: 1px solid var(--rule);
  padding-top: 18px;
  display: flex; flex-direction: column; gap: 14px;
  transition: border-color .2s;
}
/* on hover the top rule inks red and boils: a thicker line laid over it,
   flipped between three rough, displaced copies of itself (#boil-0..2) a few
   times a second, and nudged about with them, like a line photocopied and
   copied again. Under reduced motion it just inks, rough and still. */
.card::before{
  content: "";
  position: absolute; left: 0; right: 0; top: -1px;
  height: 2px;
  background: var(--accent);
  filter: url(#boil-0);
  opacity: 0;
  transition: opacity .12s;
  pointer-events: none;
}
.card:hover::before, .card:has(.card-open:focus-visible)::before, .card:has(.card-bio:focus-visible)::before{
  opacity: 1;
  animation: boil .36s steps(1) infinite;
}
@keyframes boil{
  0%     { filter: url(#boil-0); transform: translate(0, 0) scaleY(1); }
  33.3%  { filter: url(#boil-1); transform: translate(-.5px, .3px) scaleY(1.1); }
  66.6%  { filter: url(#boil-2); transform: translate(.5px, -.3px) scaleY(.92); }
}
@media (prefers-reduced-motion: reduce){
  .card:hover::before, .card:has(.card-open:focus-visible)::before{ animation: none; }
}
/* the title is the button, and its hit area is the whole card */
.card-open{
  all: unset;
  cursor: pointer;
}
.card-open::after{ content: ""; position: absolute; inset: 0; }
.card:has(.card-open:focus-visible){ outline: 2px solid var(--accent); outline-offset: 6px; }
.card-meta{
  display: flex; justify-content: space-between; gap: 12px;
  font: 500 12px/1.2 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.card-meta b{ color: var(--accent); font-weight: 500; }
.card-photo{
  position: relative;
  aspect-ratio: 1;
  background: var(--page-2);
  overflow: hidden;
}
.card-photo img{ width: 100%; height: 100%; object-fit: cover; }   /* baked: img/portraits/ */
.card h3{
  margin: 0;
  font: 700 21px/1.22 var(--sans);
  letter-spacing: -.02em;
  text-wrap: pretty;
}
.card-who{
  margin: auto 0 0;
  font: 500 14px/1.4 var(--mono);
  color: var(--ink-2);
}
/* the name opens the same sheet on the speaker tab - lifted over the
   title's card-wide hit area so it gets its own clicks */
.card-bio{
  all: unset;
  position: relative; z-index: 1;
  cursor: pointer;
  transition: color .15s;
}
.card-bio:hover{ color: var(--ink); }
.card-bio:focus-visible{ outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---- one session, opened ------------------------------------------------ */
html:has(.sheet[open]){ overflow: hidden; }
.sheet{
  width: min(1120px, calc(100% - 32px));
  max-height: calc(100svh - 32px);
  padding: 0;
  /* a torn sheet, like the hero and the band: light stock, dark toner - see
     .paper for the colours, turned over so everything inside follows */
  border: 1px solid var(--rule);
  background: var(--negative);
  color: var(--ink);
  isolation: isolate;
  overflow: hidden;
  overscroll-behavior: contain;
  /* a sheet of paper, worn rough on every side: sheet-edge.svg as a
     nine-slice mask (tools/make_tear.py), its corners fixed and its sides
     repeating to any size, held still while the sheet scrolls. Where masks
     can't do that the plain ruled edge stays. */
  -webkit-mask-box-image-source: url(../img/edges/sheet-edge.svg);
  -webkit-mask-box-image-slice: 60 fill;
  -webkit-mask-box-image-width: 60px;
  -webkit-mask-box-image-repeat: round;
  mask-border: url(../img/edges/sheet-edge.svg) 60 fill / 60px round;
}
@supports (-webkit-mask-box-image-source: none) or (mask-border-source: none){
  .sheet{ border: 0; }
}
/* the page's printed stock, inverted with the sheet */
.sheet::before{
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  background: var(--page) var(--stock) center / cover;
  filter: invert(1);
  pointer-events: none;
}
/* Never taller than the screen. The title, the tabs and the way on stay
   put; only the talk or the speaker text scrolls, in its own panel, so a
   long one no longer pushes previous / next off the bottom */
.sheet[open]{ display: flex; flex-direction: column; }
.sheet::backdrop{
  background: rgba(10, 10, 10, .78);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.sheet[open]{ animation: sheet-in .22s ease-out; }
@keyframes sheet-in{ from{ opacity: 0; transform: translateY(12px); } }
@media (prefers-reduced-motion: reduce){ .sheet[open]{ animation: none; } }
.sheet-in{
  flex: 0 1 auto; min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  grid-template-rows: minmax(0, 1fr);
}
/* the photo set in from the sheet's top and left edges, like a print
   laid on the page rather than one bled off it */
.sheet-photo{ padding: clamp(20px, 3vw, 36px) 0 0 clamp(20px, 3vw, 36px); }
.sheet-photo img{
  width: 100%; aspect-ratio: 1; object-fit: cover;
  position: sticky; top: 0;
}
.sheet-body{
  padding: clamp(24px, 4vw, 48px);
  padding-top: clamp(56px, 5vw, 64px);
  display: flex; flex-direction: column; gap: 18px;
  min-height: 0; overflow: hidden;
}
.sheet-body > *{ flex: none; }
.sheet-body .card-meta{ margin: 0; }
.sheet-title{
  margin: 0;
  font: 800 clamp(28px, 3.3vw, 44px)/1.04 var(--sans);
  letter-spacing: -.035em;
  filter: url(#copy-md);
  text-wrap: balance;
}
.sheet-who{ margin: 0; font: 500 16px/1.4 var(--mono); color: var(--ink); }
.sheet-who + .sheet-when{ margin-top: -12px; }   /* who and when read as one line pair */
.sheet-when{
  margin: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  font: 400 14px/1.4 var(--mono); color: var(--accent);
  text-transform: uppercase; letter-spacing: .06em;
}
/* the talk and the speaker, a tab each - the day tabs, a size down - in
   the one panel that scrolls */
.sheet-tabs[hidden]{ display: none; }
.sheet-tabs button{ font-size: 13px; padding: 12px 16px 10px; }
.sheet-tabs button:first-child{ padding-left: 0; }
.sheet-body > .sheet-panels{
  flex: 0 1 auto; min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin-right: -14px; padding-right: 14px;   /* the scrollbar in the gutter, off the text */
  scrollbar-width: thin;
  scrollbar-color: var(--ink-3) transparent;
  /* the text fades out under the bottom edge, so a long one shows there is
     more; the padding lets its last line clear the fade at the end */
  padding-bottom: 28px;
  -webkit-mask-image: linear-gradient(#000 calc(100% - 32px), transparent);
  mask-image: linear-gradient(#000 calc(100% - 32px), transparent);
}
.sheet-panels > .off{ display: none; }
.sheet-about{
  border-top: 1px solid var(--rule);
  padding-top: 18px;
  max-width: 62ch;
}
.sheet-tabs:not([hidden]) + .sheet-panels > .sheet-about{ border-top: 0; padding-top: 4px; }
/* pre-line: the copy comes as the speakers wrote it, lists on their own lines */
.sheet-about p{ margin: 0 0 14px; color: var(--ink-2); font-size: 17px; line-height: 1.65; white-space: pre-line; }
.sheet-about p:last-child{ margin-bottom: 0; }
.sheet-about .sheet-none{ color: var(--ink-3); font-style: italic; }
.sheet-note{ margin: 4px 0 0; font: 400 13px/1.5 var(--mono); color: var(--ink-3); }
.sheet-note a{ color: var(--accent); text-underline-offset: 3px; }
.sheet-note a.boil-line:not(:hover):not(:focus-visible),
.foot-links a.boil-line:not(:hover):not(:focus-visible){ text-decoration: underline; padding-bottom: 0; }
.sheet-bar{
  display: flex; justify-content: space-between;
  border-top: 1px solid var(--rule);
}
/* Previous / next: a drawn arrow, heavy enough to read as the way out, and
   the neighbour's name so you know where it goes. */
.sheet-step{
  appearance: none; background: none; border: 0; cursor: pointer;
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: center; gap: 18px;
  padding: 18px clamp(16px, 3vw, 28px);
  color: var(--ink);
  text-align: left;
}
.sheet-step.next{
  justify-content: flex-end; text-align: right;
  border-left: 1px solid var(--rule);
}
.sheet-step .arrow{
  flex: none;
  width: 32px; height: 24px;
  fill: none; stroke: currentColor; stroke-width: 3.2; stroke-linecap: square;
  color: var(--ink-2);
  transition: transform .18s ease-out, color .15s;
}
.sheet-step.prev .arrow{ transform: scaleX(-1); }
.sheet-step.prev:hover .arrow{ transform: scaleX(-1) translateX(6px); }
.sheet-step.next:hover .arrow{ transform: translateX(6px); }
.step-txt{ display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.step-txt small{
  font: 500 11px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3);
}
.step-txt b{
  font: 600 15px/1.2 var(--sans); letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color .15s;
}
.sheet-step:hover .arrow{ color: var(--ink); }
.sheet-step:focus-visible{ outline: 2px solid var(--accent); outline-offset: -6px; }
/* Close: drawn like the arrows - the same stroke, the same small caps */
.sheet-close{
  appearance: none; background: none; border: 0; cursor: pointer;
  position: absolute; top: 0; right: 0;
  display: flex; align-items: center; gap: 12px;
  padding: 18px 22px;
  color: var(--ink-2);
}
.sheet-close small{
  font: 500 11px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3);
  transition: color .15s;
}
.sheet-close .cross{
  width: 20px; height: 20px;
  fill: none; stroke: currentColor; stroke-width: 3.2; stroke-linecap: square;
  transition: transform .18s ease-out, color .15s;
}
.sheet-close:hover{ color: var(--ink); }
.sheet-close:hover small{ color: var(--ink-2); }
.sheet-close:hover .cross{ transform: rotate(90deg); }
.sheet-close:focus-visible{ outline: 2px solid var(--accent); outline-offset: -6px; }
/* the arrows and the cross drawn rough like the stamps, held still, and
   boiling under the pointer - the filter alone steps, so the arrow's slide
   and the cross's turn carry on underneath */
.sheet-step .arrow, .sheet-close .cross{ filter: url(#boil-0); }
.sheet-step:hover .arrow, .sheet-step:focus-visible .arrow,
.sheet-close:hover .cross, .sheet-close:focus-visible .cross{ animation: boil-ink .36s steps(1) infinite; }
@keyframes boil-ink{
  0%    { filter: url(#boil-0); }
  33.3% { filter: url(#boil-1); }
  66.6% { filter: url(#boil-2); }
}
@media (prefers-reduced-motion: reduce){
  .sheet-step:hover .arrow, .sheet-step:focus-visible .arrow,
  .sheet-close:hover .cross, .sheet-close:focus-visible .cross{ animation: none; }
}
@media (max-width: 760px){
  /* the whole screen: no edge to wear */
  .sheet{
    width: 100%; max-width: none; max-height: 100svh; height: 100svh; border: 0;
    -webkit-mask-box-image-source: none; mask-border: none;
    padding-top: 49px;   /* under the close strip */
  }
  /* a phone has no room to split: photo and text scroll as one, between the
     close strip and the prev / next bar, which stay docked top and bottom
     however short the session is */
  .sheet-body, .sheet-body > .sheet-panels{
    overflow: visible; margin-right: 0; padding-right: 0; padding-bottom: 0;
    -webkit-mask-image: none; mask-image: none;
  }
  .sheet-in{
    flex: 1 1 auto; display: block;
    overflow-y: auto; overscroll-behavior: contain;
  }
  .sheet-photo{ padding: 0; }
  .sheet-photo img{ position: static; aspect-ratio: 4 / 3; }
  .sheet-body{ padding-top: 24px; }
  /* close in a strip across the top, the twin of the prev / next bar at the
     bottom: the same paper, the same rule, so the sheet is framed by the
     two and the photo starts below it */
  .sheet-close{
    position: fixed; top: 0; left: 0; right: 0;
    justify-content: flex-end;
    padding: 14px 18px;
    background: rgba(220, 220, 220, .96);
    border-bottom: 1px solid var(--rule);
    z-index: 2;
  }
  .sheet-bar{
    flex: none;
    padding-bottom: env(safe-area-inset-bottom);
    background: rgba(220, 220, 220, .96);
  }
  .sheet-step{ gap: 10px; padding: 14px 14px; }
  .sheet-step .arrow{ width: 27px; height: 20px; }
  .step-txt b{ font-size: 14px; }
}

/* ---- the floor plans ---------------------------------------------------- */
/* The session sheet again, wider, with a floor to a tab. The walls are an
   image of plain ink (tools/make_plans.py) drawn through #sketch like the
   venue map's streets, toned down to the sheet's toner; the words sit over
   them in the plan's own units, with a halo of paper so a label over a wall
   still reads. On a phone the plan keeps a readable size and scrolls
   sideways. */
.plan-sheet{ width: min(1440px, calc(100% - 32px)); }
.plan-body{
  flex: 0 1 auto; min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  padding: clamp(24px, 3.5vw, 44px);
  padding-top: clamp(56px, 5vw, 64px);
  display: flex; flex-direction: column; gap: 18px;
}
.plan-body .card-meta, .plan-body .sheet-title{ margin: 0; }
.plan-panels{ overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; }
.plan{ position: relative; }
.plan[hidden]{ display: none; }
.plan-walls{
  position: absolute; top: 0; left: 0;
  width: 100%; height: auto;
  filter: url(#plan-ink);
  opacity: .82;      /* black down to the sheet's toner */
}
.plan-signs{ fill: var(--ink); }
.plan-signs .knock, #plan-lift .knock{ fill: none; stroke: var(--negative); stroke-width: 6.5; stroke-linecap: round; stroke-linejoin: round; }
.plan-words{ position: relative; display: block; width: 100%; height: auto; overflow: visible; }
.plan-type{
  font: 500 30px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
  fill: var(--ink-2);
  paint-order: stroke; stroke: var(--negative); stroke-width: 10px; stroke-linejoin: round;
}
.plan-type .hot{ fill: var(--accent); font: 700 40px/1 var(--sans); letter-spacing: -.01em; text-transform: none; }
.plan-type .room{ font-size: 34px; }   /* each workshop room is one side of its partition */
.plan-type .zone{ font-size: 21px; letter-spacing: .02em; }   /* inside the zones' narrow outlines */
.plan-type .name{ fill: var(--ink); font: 700 42px/1 var(--sans); letter-spacing: -.01em; text-transform: none; }
.plan-type .name.small{ font-size: 34px; }   /* in a narrow room */
.plan-type .num{ font-size: 24px; fill: var(--ink-3); }
.plan-type .faint{ fill: var(--ink-3); }
/* the zones outside: inside ArtCenter's dashed outlines, hatched red like
   the venue map's campus */
.plan-zones rect{ fill: url(#planHatch); }
#planHatch path{ stroke: var(--accent); stroke-width: 3; stroke-opacity: .35; }
.plan-arrow{ fill: none; stroke: var(--accent); stroke-width: 6; stroke-linecap: round; stroke-linejoin: round; }
.plan-north{ fill: none; stroke: var(--ink-2); stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
.plan-hint{ display: none; margin: 0; font: 400 13px/1.5 var(--mono); color: var(--ink-3); }
/* the roof, in words: under the plans its name in red like a room's, then
   the way up; under the venue's links, in their small caps */
.plan-body .plan-roof{ margin: 0; font: 400 15px/1.5 var(--sans); color: var(--ink-2); }
.plan-body .plan-roof b{
  margin-right: 10px;
  font: 500 12px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent);
}
.plan-links .plan-roof{ text-transform: none; letter-spacing: .02em; color: var(--ink-2); max-width: 46ch; }
@media (max-width: 760px){
  .plan-sheet{ width: 100%; }
  .plan-body{ flex: 1 1 auto; padding-top: 24px; }
  .plan{ min-width: 1000px; }
  .plan-hint{ display: block; }
}

/* the way in, under the campus's address: the walk's small caps, a floor
   to a line */
.where .plan-links{ margin: 16px 0 0; display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.plan-links span{
  font: 500 12px/1.4 var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3);
}
.plan-links .map-cta{
  appearance: none; border: 0; cursor: pointer;
  margin: 0; padding: 0 0 5px;
  text-align: left;
}

/* a session in the timetable opens the same way */
.slot-open{
  all: unset;
  cursor: pointer;
}
.slot-open:focus-visible{ outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---- boiling underline ---------------------------------------------------- */
/* The card's hover rule, for underlines: a rough red line under the text,
   flipped between three hand-wobbled copies a few times a second. Drawn as a
   repeating background, not text-decoration, so it can be rough, and so it
   follows text that wraps onto a second line. The tiles carry the accent
   (#ff4433) baked in - change it here too if --accent changes. */
:root{
  --boil-a: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='6' viewBox='0 0 240 6'%3E%3Cpath d='M0 3.00 3 3.56 6 3.73 9 3.32 12 3.27 15 2.99 18 3.00 21 3.02 24 2.90 27 3.10 30 3.18 33 3.36 36 3.12 39 2.65 42 2.73 45 2.44 48 2.76 51 2.80 54 3.01 57 3.53 60 3.29 63 3.18 66 3.31 69 3.10 72 2.80 75 3.12 78 3.07 81 3.23 84 3.05 87 3.22 90 2.88 93 2.73 96 2.52 99 2.25 102 2.41 105 2.58 108 2.82 111 2.96 114 3.10 117 3.16 M120 2.81 123 3.03 126 2.95 129 3.10 132 3.51 135 3.53 138 3.49 141 3.43 144 3.26 147 2.73 150 2.90 153 2.46 156 2.85 159 3.06 162 2.90 165 3.28 168 3.07 171 3.02 174 2.66 177 2.63 180 2.76 183 3.26 186 3.18 189 3.56 192 3.64 195 3.49 198 2.99 201 2.72 204 2.60 207 2.66 210 2.47 213 2.87 216 3.00 219 3.04 222 2.62 225 2.84 228 2.38 231 2.49 234 2.76 237 3.15 240 3.00' fill='none' stroke='%23ff4433' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
  --boil-b: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='6' viewBox='0 0 240 6'%3E%3Cpath d='M0 3.00 3 3.21 6 3.16 9 3.54 12 3.84 15 3.67 18 4.06 21 3.74 24 3.29 27 3.22 30 2.86 33 2.86 36 2.65 39 2.73 42 3.05 45 3.12 48 3.18 51 3.33 54 3.16 M57 3.20 60 3.27 63 3.11 66 3.54 69 3.49 72 3.56 75 3.12 78 2.92 81 2.67 84 2.30 87 1.91 90 2.15 93 2.14 96 2.34 99 2.38 102 2.43 105 2.21 108 2.34 111 2.48 114 2.85 117 2.93 120 3.44 123 3.57 126 4.07 129 3.92 132 3.91 135 3.51 138 3.23 141 3.10 144 3.30 147 3.16 150 3.46 153 3.29 156 3.08 159 2.80 162 2.87 165 2.55 168 2.76 171 3.02 174 3.13 177 3.59 180 3.58 183 3.40 186 3.23 189 2.90 192 2.78 195 2.88 198 2.59 201 2.95 204 2.70 207 2.42 210 2.15 213 2.19 216 1.86 219 1.64 222 1.87 225 2.28 228 2.73 231 2.95 234 3.11 237 3.12 240 3.00' fill='none' stroke='%23ff4433' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
  --boil-c: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='6' viewBox='0 0 240 6'%3E%3Cpath d='M0 3.00 3 3.40 6 3.31 9 3.20 12 2.78 15 2.39 18 2.22 21 2.42 24 2.33 27 2.75 30 2.95 33 2.86 36 3.17 39 2.80 42 3.05 45 3.01 48 2.84 51 3.22 54 3.42 57 3.31 60 3.52 63 3.15 66 3.22 69 2.88 72 2.83 75 2.45 78 2.67 81 2.97 84 3.13 87 3.02 90 3.26 93 3.14 96 2.84 99 2.78 102 3.12 M105 3.22 108 3.54 111 3.60 114 3.54 117 3.22 120 3.00 123 2.86 126 2.79 129 2.62 132 2.81 135 2.83 138 3.03 141 2.90 144 2.64 147 2.42 150 2.29 153 2.31 156 2.82 159 3.09 162 3.32 165 3.25 168 3.51 171 3.19 174 3.32 177 3.06 180 3.01 183 2.99 186 3.02 189 3.30 192 3.37 195 2.99 198 2.89 201 2.81 204 2.67 207 2.58 210 2.77 213 3.23 216 3.22 219 3.35 222 3.57 225 3.30 228 3.39 231 3.03 234 3.24 237 3.08 240 3.00' fill='none' stroke='%23ff4433' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}
.boil-line{
  text-decoration: none;
  background: var(--boil-a) left bottom / 240px 6px repeat-x;
  background-size: 0 6px;            /* hidden until hover */
  padding-bottom: 5px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
.boil-line:hover, .boil-line:focus-visible{
  background-size: 240px 6px;
  animation: boil-line .36s steps(1) infinite;
}
@keyframes boil-line{
  0%    { background-image: var(--boil-a); }
  33.3% { background-image: var(--boil-b); }
  66.6% { background-image: var(--boil-c); }
}
@media (prefers-reduced-motion: reduce){
  .boil-line:hover, .boil-line:focus-visible{ animation: none; }
}

/* ---- weekend ------------------------------------------------------------ */
.days{
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--rule);
}
.days li{
  padding: 24px 24px 28px 0;
  border-bottom: 1px solid var(--rule);
}
.days li + li{ padding-left: 24px; border-left: 1px solid var(--rule); }
/* a step under the section's title, not over it: about half its size, so
   THE WEEKEND reads first and the days as its three parts */
.day-name{
  display: block;
  font: 800 clamp(28px, 4.4vw, 60px)/.85 var(--sans);
  letter-spacing: -.045em;
  text-transform: uppercase;
  filter: url(#copy-md);
}
.day-date{
  display: block; margin: 14px 0 16px;
  font: 500 13px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent);
}
.days p{ margin: 0; color: var(--ink-2); }
.note{
  margin: 20px 0 0;
  font: 400 13px/1.5 var(--mono);
  color: var(--ink-3);
}
.sched{ margin-top: clamp(48px, 7vw, 88px); }
.sched-head{ display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; margin-bottom: 20px; }
.sched-title{
  margin: 0;
  font: 800 clamp(28px, 3.6vw, 44px)/1 var(--sans);
  letter-spacing: -.04em; text-transform: uppercase;
  filter: url(#copy-md);   /* small display type: the full grit wears it through */
}
/* the stage filters, beside the title: small caps in a thin frame, the chosen
   one framed in red, rough like the chosen tab's marker */
/* to the right while they fit beside the title, flush left once they wrap
   under it: a spacer between the two takes the slack on the title's row and,
   with no width of its own, stays on that row when the filters drop */
.sched-head::after{ content: ""; flex: 1 0 0; order: 1; }
.sched-filter{ display: flex; flex-wrap: wrap; gap: 8px; order: 2; }
.sched-filter button{
  appearance: none; background: none; cursor: pointer;
  position: relative;
  border: 1px solid var(--rule);
  color: var(--ink-3);
  font: 500 12px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase;
  padding: 10px 12px 9px;
  transition: color .15s;
}
.sched-filter button:hover{ color: var(--ink); }
.sched-filter button[aria-pressed="true"]{ color: var(--ink); border-color: transparent; }
.sched-filter button[aria-pressed="true"]::after{
  content: "";
  position: absolute; inset: -1px;
  border: 2px solid var(--accent);
  filter: url(#boil-0);
  pointer-events: none;
}
.slot[hidden]{ display: none; }   /* filtered out - .slot's grid would show it */
.tabs{ display: flex; gap: 0; border-bottom: 1px solid var(--rule); }
.tabs button{
  appearance: none; background: none; border: 0; cursor: pointer;
  color: var(--ink-3);
  font: 600 14px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
  padding: 14px 18px 12px;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  position: relative;
}
.tabs button:hover{ color: var(--ink); }
.tabs button[aria-selected="true"]{ color: var(--ink); }
/* the chosen tab's marker, inked rough like the card rules (#boil-0) but
   held still - it marks, it doesn't call for attention */
.tabs button[aria-selected="true"]::after{
  content: "";
  position: absolute; left: 0; right: 0; bottom: -3px;
  height: 3px;
  background: var(--accent);
  filter: url(#boil-0);
}
.tabs small{ font-weight: 400; color: var(--ink-3); margin-left: 6px; }
.slots{ list-style: none; margin: 0; padding: 0; }
.slot{
  display: grid;
  grid-template-columns: 80px 150px minmax(0, 1fr) auto;
  gap: 8px 24px; align-items: baseline;
  padding: 16px 0;
  border-bottom: 1px solid var(--rule);
}
.slot-time{ font: 700 16px/1.3 var(--mono); }
.slot-room{ font: 400 13px/1.4 var(--mono); color: var(--ink-3); text-transform: uppercase; letter-spacing: .06em; }
.slot-what{ font-weight: 600; line-height: 1.35; }
.slot-what span{ display: block; font: 400 14px/1.5 var(--mono); color: var(--ink-2); margin-top: 2px; }
.slot.plain .slot-what{ font-weight: 400; color: var(--ink-2); }
.slot-kind{
  font: 500 11px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent);
}
@media (max-width: 760px){
  .slot{ grid-template-columns: 64px minmax(0, 1fr); gap: 4px 14px; }
  .slot-room{ grid-column: 2; grid-row: 1; }
  .slot-what{ grid-column: 2; }
  .slot-kind{ grid-column: 2; }
}

@media (max-width: 760px){
  .days{ grid-template-columns: 1fr; }
  .days li, .days li + li{ padding: 22px 0; border-left: 0; }
}

/* ---- venue -------------------------------------------------------------- */
/* the blurb and the two addresses, and beside them a sketch map of the
   streets between - drawn freehand on squared paper and copied like the rest:
   the lines wobble through #boil-0, the words wear through #copy-sm */
.venue-body{
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);   /* even halves: the sketch no bigger than the words */
  gap: clamp(32px, 5vw, 80px); align-items: center;
}
.venue-body .sec-intro{ margin-top: 0; }
.where{ margin: 32px 0 0; border-top: 1px solid var(--rule); }
.where > div{ padding: 16px 0 18px; border-bottom: 1px solid var(--rule); }
.where dt{
  font: 500 12px/1.4 var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent);
}
.where dd{ margin: 6px 0 0; font-weight: 600; font-size: 18px; }
.where dd + dd{ margin-top: 2px; font: 400 14px/1.5 var(--mono); }
.where a{ color: var(--ink-2); }
.where a:hover, .where a:focus-visible{ color: var(--ink); }

/* the sketch is the way there: a link to the walk in Google Maps, and on
   hover the dashes set off along the route */
.venue-map-link{
  display: block; justify-self: end;
  width: 100%; max-width: 560px;
  color: inherit; text-decoration: none;
}
.venue-map{ display: block; width: 100%; height: auto; overflow: visible; }
/* the same walk, as a line under the addresses */
.map-cta{
  display: inline-block; margin-top: 20px;
  font: 500 12px/1.4 var(--mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent); text-decoration: none;
}
.venue-map-link:hover .map-route path, .venue-map-link:focus-visible .map-route path{
  animation: map-walk .9s linear infinite;
}
@keyframes map-walk{ to{ stroke-dashoffset: -19; } }
@media (prefers-reduced-motion: reduce){
  .venue-map-link:hover .map-route path, .venue-map-link:focus-visible .map-route path{ animation: none; }
}
.map-grid{ stroke: var(--rule); stroke-width: 1; opacity: .5; }
.map-streets, .map-route, .map-marks{ fill: none; stroke-linecap: round; filter: url(#sketch); }
/* pencil, not paint: a step under the type in weight */
.map-streets{ stroke: var(--ink-3); stroke-width: 2; }
.map-streets .major{ stroke: var(--ink-2); stroke-width: 3; }
.map-streets .pass{ stroke: var(--ink-3); stroke-width: 1; opacity: .7; }
.map-route{ stroke: var(--accent); stroke-width: 2.5; stroke-dasharray: 10 9; }
.map-marks{ stroke: var(--accent); stroke-width: 3; }
.map-marks circle{ fill: var(--accent); }
.map-marks .campus{ fill: url(#mapHatch); }
#mapHatch path{ stroke: var(--accent); stroke-width: 2; }
.map-marks .north{ stroke: var(--ink-2); stroke-width: 2.5; }
/* the light rail: a line with its ties, dashed where it runs underground */
.map-rail{ fill: none; stroke: var(--ink-2); stroke-width: 2; filter: url(#sketch); }
.map-rail .ties{ stroke-width: 10; stroke-dasharray: 2 8; opacity: .7; }
.map-rail .tunnel{ stroke-dasharray: 6 6; }
.map-marks .stn{ fill: var(--page); stroke: var(--ink); stroke-width: 2.5; }
.map-type .stn-name{ font-size: 12px; letter-spacing: .04em; fill: var(--ink-2); }
.map-marks .knock{ fill: var(--page); stroke: none; }   /* the rail stops for a station's name */
.map-type{
  font: 500 14px/1 var(--mono); letter-spacing: .1em; text-transform: uppercase;
  fill: var(--ink-2);
  filter: url(#copy-sm);
}
.map-type .hot{ fill: var(--accent); font-size: 12px; }
.map-type .name{ fill: var(--ink); font: 700 17px/1 var(--sans); letter-spacing: -.01em; text-transform: none; }
.map-type .north-n{ fill: var(--ink-2); font-size: 15px; }
.map-type .faint{ font-size: 11px; }
/* under 1000px half the width is too little for the map's lettering: one
   column, the sketch under the words and lined up with them on the left */
@media (max-width: 1000px){
  .venue-body{ grid-template-columns: 1fr; align-items: start; }
  .venue-map-link{ justify-self: start; max-width: 640px; margin-left: -10px; }
}

/* ---- sponsors ----------------------------------------------------------- */
/* The last section on the dark page, before the torn band: a row of cells
   per tier, ruled like the days. The rules are the gaps - the tier's own
   ground is the rule's tint, each cell the page's printed stock again,
   pinned like it, so they meet without a seam however the cells wrap. */
.sponsor-tier{
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: 1px;
  background: var(--rule);
  border-block: 1px solid var(--rule);
  --cols: 6;
  --h: clamp(22px, 2.4vw, 30px);   /* a wordmark's height; --k scales it per logo */
  --cell: clamp(112px, 12vw, 152px);
}
.sponsor-tier.top{ --cols: 2; --h: clamp(40px, 5vw, 72px); --cell: clamp(168px, 19vw, 248px); }
.sponsor-tier + .sponsor-tier{ border-top: 0; }
.sponsor-tier li{ display: flex; background: var(--page) var(--stock) center / cover fixed; }
.sponsor{
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  min-height: var(--cell);
  padding: 24px;
}
/* in the page's light ink at rest; under the pointer inked red and boiling
   like the stamps (#fuzz-0..2) */
.sponsor img{
  filter: brightness(0) invert(1) url(#copy-sm);
  opacity: .88;      /* white down to --ink */
  height: calc(var(--h) * var(--k, 1)); width: auto; max-width: 100%;
  object-fit: contain;
}
.sponsor:hover img, .sponsor:focus-visible img{
  filter: url(#fuzz-0); opacity: 1;
  animation: fuzz .36s steps(1) infinite;
}
@keyframes fuzz{
  0%     { filter: url(#fuzz-0); }
  33.3%  { filter: url(#fuzz-1); transform: translate(-.5px, .3px); }
  66.6%  { filter: url(#fuzz-2); transform: translate(.5px, -.3px); }
}
@media (prefers-reduced-motion: reduce){
  .sponsor:hover img, .sponsor:focus-visible img{ animation: none; }
}
.sponsor:focus-visible{ outline-offset: -6px; }
/* the second tier two by two once six across is too tight for a wordmark,
   an odd one out taking the whole last row rather than leaving a hole */
@media (max-width: 1000px){
  .sponsor-tier{ --cols: 2; }
  .sponsor-tier li:last-child:nth-child(odd){ grid-column: 1 / -1; }
}
@media (max-width: 480px){ .sponsor{ padding: 16px; } }

/* ---- tickets band ------------------------------------------------------- */
/* The end of the page is one last sheet, torn along its top only: the band's
   collage, then "see you in Pasadena" and the footer on the same paper, down
   to the bottom. Its paper is the page's stock turned over
   (img/stock-light.webp, baked) pinned to the screen, so the grain runs on
   from the band through the footer without a seam; .paper turns the page's
   colours over for everything printed on it. */
.paper, .sheet{
  --ink: var(--paper-ink);
  --ink-2: rgba(46, 46, 46, .84);
  --ink-3: rgba(46, 46, 46, .62);
  --rule: rgba(46, 46, 46, .2);
}
.paper, .band-sheet{
  background: var(--negative) var(--stock-light) center / cover fixed;
  color: var(--ink);
}
.tickets{ margin-top: clamp(72px, 10vw, 128px); }
/* the same tiles as the hero's edge, upside down, shifted along the tile so
   the two tears don't match */
.band{
  --top-x: calc(var(--tear-w) * -.37);
  position: relative;
  height: clamp(220px, 34vw, 480px);
}
.band::before{
  content: "";
  position: absolute; left: 0; right: 0; top: 0;
  height: var(--tear);
  background: url(../img/edges/tear-edge-up.svg) var(--top-x) top / var(--tear-w) 100% repeat-x;
}
.band-sheet{
  position: relative; z-index: 1;
  height: 100%;
  -webkit-mask:
    url(../img/edges/tear-face-up.svg) var(--top-x) top / var(--tear-w) var(--tear) repeat-x,
    linear-gradient(#000 0 0) bottom / 100% calc(100% - var(--tear) + 1px) no-repeat;
  mask:
    url(../img/edges/tear-face-up.svg) var(--top-x) top / var(--tear-w) var(--tear) repeat-x,
    linear-gradient(#000 0 0) bottom / 100% calc(100% - var(--tear) + 1px) no-repeat;
}
/* baked at three shapes (img/band-*.webp) and cropped to the rest. Only its
   ink prints: turned over, its own paper pushed to white and multiplied onto
   the sheet's - so the band and the paper under the type are one paper, with
   no fade over the art and no edge where it ends */
.band picture, .band img{ display: block; width: 100%; height: 100%; }
.band img{
  object-fit: cover;
  filter: invert(1) contrast(1.35) brightness(1.1);
  mix-blend-mode: multiply;
  opacity: .83;      /* its black down to the header's toner, ~#262626 on this paper */
}
/* the display type on the last sheet: inked darker than --ink, since the
   copier filter thins its density - so it lands on the same toner as the art */
.paper .big{ color: #161616; }
/* the band is a fraction of a pixel tall at most widths, which leaves a
   hairline of dark page under it - the paper below tucks up over it */
.band + .paper{ position: relative; margin-top: -2px; }
.tickets-row{
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 24px 40px;
  padding-top: clamp(40px, 6vw, 72px);
  padding-bottom: clamp(40px, 6vw, 72px);
}

/* ---- footer ------------------------------------------------------------- */
.foot{
  border-top: 1px solid var(--rule);
  padding-top: 40px; padding-bottom: 48px;
  display: grid; grid-template-columns: auto 1fr auto; gap: 16px 32px; align-items: start;
  font: 400 14px/1.6 var(--mono);
  color: var(--ink-2);
}
.foot p{ margin: 0; }
.foot b{ color: var(--ink); font-weight: 500; }
.foot-mark{ width: 56px; opacity: .88; }   /* black, on the last sheet */
.foot-links{ display: flex; flex-direction: column; gap: 4px; text-align: right; }
.foot-links a{ color: var(--ink-2); text-decoration-color: var(--rule); text-underline-offset: 3px; }
.foot-links a:hover{ color: var(--accent); }
@media (max-width: 700px){
  .foot{ grid-template-columns: 1fr; }
  .foot-links{ text-align: left; }
}
