/* ---- theme ---------------------------------------------------------- */
:root {
  /* colour */
  --bg:     #F3EADF;   /* flat beige */
  --ink:    #141414;   /* black */
  --gray:   #6B6660;   /* the one gray */
  --white:  #FFFFFF;
  --accent: #FF8F00;   /* highlight */
  --lime:   #BFFF00;   /* second accent: neon lime. Low contrast on beige: fine for
                          brief flashes and highlights, not for text people read */
  --line:   #D8CFC4;   /* light gray: scrollbar, dividers */
  --on-accent: #141414;   /* text on orange/lime: stays dark in both modes */
  --rule-w: 1px;
  --rule:   var(--rule-w) solid var(--line);
  --glass:  color-mix(in srgb, var(--bg) 85%, transparent);   /* see-through beige: header, menu */

  /* type */
  --sans:    "helvetica-lt-pro", Helvetica, Arial, sans-serif;
  --display: "argent-pixel-cf", Georgia, serif;
  --mono:    "source-code-pro", ui-monospace, Menlo, monospace;

  --fs-title: clamp(2rem, 3.3vw, 3.25rem);     /* site title          */
  --fs-h:     clamp(2.25rem, 3.4vw, 3rem);     /* page + section heads */
  --fs-lede:  clamp(1.75rem, 2.5vw, 2.25rem);  /* big Argent text     */
  --fs-body:  1.2rem;                         /* 20px                */
  --fs-nav:   1.125rem;                        /* 18px                */
  --fs-small: 1rem;

  /* header */
  --gutter: clamp(1.25rem, 3vw, 2.5rem);
  --header-pad:   1.25rem;   /* top */
  --header-pad-b: 0.5rem;    /* bottom */
  --header-h: calc(var(--fs-title) * 1.2 + var(--header-pad) + var(--header-pad-b) + var(--rule-w));
  --sprite-cycle: 0.99s;   /* full 4-frame crow loop */

  /* info layout */
  --side-w:   40%;                        /* left panel width        */
  --body-pad: clamp(2rem, 5vw, 5rem);     /* text inset from divider */
  --measure:  46rem;                      /* max text line length    */

  /* left-panel artwork: big pixel crow + HOME's staggered title.
     Everything is measured in panel units (u): 1u = 1% of the panel's width,
     so the crow and title scale together and keep the same composition at
     every screen size. Plain numbers, no units. */
  --crow-size:  150;    /* crow width                        */
  --crow-top:   21;     /* crow's distance from panel top    */
  --crow-left:  32;     /* crow's distance from panel left   */
  --title-size: 20;   /* HOME title font size              */
  --title-top:  0;      /* HOME title's distance from top    */
  --title-em:   6.6;    /* width of the longest title line ("Community"),
                           in em — keeps the title inside the panel */
}

/* ---- night mode: set by js/theme.js, switched by the header toggle.
   Only the colours change; everything built on them follows. ---------- */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:   #0E0E0E;   /* near-black */
  --ink:  #E6E2DC;   /* very light warm gray */
  --gray: #9A948C;   /* lighter, to stay readable on black */
  --line: #3D3934;   /* dark gray dividers and scrollbar */
}

/* black pixel art would vanish on black: flip it to light gray (0.85
   rather than a full invert, so black becomes light gray, not white; the
   hue-rotate brings orange back toward orange). The big crow's canvas is
   recoloured by crow.js instead; this only covers its fallback image. */
[data-theme="dark"] :is(.pixel-crow img, .sprite img, .logos a[href*="princeton"] img) {
  filter: invert(0.85) hue-rotate(180deg);
}

/* ---- base ----------------------------------------------------------- */
* { box-sizing: border-box; }

html {
  scrollbar-color: var(--line) transparent;
  scrollbar-gutter: stable;   /* keep the scrollbar's space even on short pages, so layouts line up across pages */
}
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-thumb { background: var(--line); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--accent); color: var(--lime); }

img { max-width: 100%; }

/* ---- text ----------------------------------------------------------- */
h1, h2 {
  margin: 1.5em 0 0.5em;
  color: var(--accent);
  font-family: var(--display);
  font-style: italic;
  font-weight: 400;
  font-size: var(--fs-h);
  line-height: 1.1;
}

h1:first-child { margin-top: 0; }

h3 {
  margin: 1.5em 0 0.5em;
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--fs-lede);
  line-height: 1.2;
}

p, ul, ol { margin: 0 0 1em; }

/* bullets are a small orange pixel square, flush with the text edge above;
   the item text hangs indented after it */
ul { padding-left: 0; list-style: none; }
ul li { position: relative; padding-left: 1em; }
ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(0.5lh - 0.175em);   /* centred on the first line */
  width: 0.35em;
  height: 0.35em;
  background: var(--accent);
}

.lede {
  font-family: var(--display);
  font-size: var(--fs-lede);
  line-height: 1.3;
}

/* small 3x3-pixel plus sign, used as a bullet */
.pixel-plus {
  display: inline-block;
  width: 0.75em;
  height: 0.75em;
  margin-right: 0.5em;
  background: var(--accent);
  clip-path: polygon(33.3% 0, 66.7% 0, 66.7% 33.3%, 100% 33.3%, 100% 66.7%, 66.7% 66.7%,
                     66.7% 100%, 33.3% 100%, 33.3% 66.7%, 0 66.7%, 0 33.3%, 33.3% 33.3%);
}

/* ---- links ---------------------------------------------------------- */
a {
  color: inherit;
  font-family: var(--mono);
  font-weight: 600;
  font-size: 0.8em;   /* mono runs large next to Helvetica */
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

a:hover,
a:focus-visible {
  background: var(--accent);
  color: var(--lime);   /* 6.75:1 — white on orange fails */
  text-decoration-color: transparent;
}

/* links that sit inside running text: <a class="inline"> keeps the
   surrounding font, so it just flows with the sentence */
.inline {
  font-family: inherit;
  font-weight: inherit;
  font-size: inherit;
  text-transform: none;
  letter-spacing: normal;
}

/* small pixel icon links after a name (website, Mastodon, Bluesky, …) */
.icon-links {
  display: inline-flex;
  gap: 0.3em;
  margin-left: 0.4em;
  vertical-align: -0.1em;
}

.icon-links a {
  display: inline-flex;
  padding: 0.15em;
  text-decoration: none;
}

.icon-links svg {
  width: 0.9em;
  height: 0.9em;
  fill: currentColor;
  shape-rendering: crispEdges;
}

/* letters light up one at a time; site.js wraps each letter in span.letter */
.letter { transition: color 0.1s ease-out; }
.letter:hover { color: var(--accent); }
.letter.hover-lime:hover { color: var(--lime); }   /* site.js picks orange or lime at random on each hover */

/* orange page headers light up lime instead */
:is(h1, h2):not(.stagger) .letter:hover { color: var(--lime); }

/* letters in [data-flicker] titles now and then flash an accent (site.js) */
.letter.flash      { color: var(--accent); transition: none; }
.letter.flash-lime { color: var(--lime); transition: none; }

/* ---- buttons -------------------------------------------------------- */
/* orange block with stepped pixel corners; works on <a> and <button> */
.button {
  --px: 4px;   /* size of each corner step */
  display: inline-block;
  padding: 0.4em 1.2em 0.45em;
  border: 0;
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--display);
  font-style: italic;
  font-weight: 400;
  font-size: 1.75rem;
  line-height: 1.1;
  text-transform: none;
  letter-spacing: normal;
  text-decoration: none;
  cursor: pointer;
  clip-path: polygon(
    0 calc(var(--px) * 2), var(--px) calc(var(--px) * 2), var(--px) var(--px),
    calc(var(--px) * 2) var(--px), calc(var(--px) * 2) 0,
    calc(100% - var(--px) * 2) 0, calc(100% - var(--px) * 2) var(--px),
    calc(100% - var(--px)) var(--px), calc(100% - var(--px)) calc(var(--px) * 2),
    100% calc(var(--px) * 2),
    100% calc(100% - var(--px) * 2), calc(100% - var(--px)) calc(100% - var(--px) * 2),
    calc(100% - var(--px)) calc(100% - var(--px)), calc(100% - var(--px) * 2) calc(100% - var(--px)),
    calc(100% - var(--px) * 2) 100%,
    calc(var(--px) * 2) 100%, calc(var(--px) * 2) calc(100% - var(--px)),
    var(--px) calc(100% - var(--px)), var(--px) calc(100% - var(--px) * 2),
    0 calc(100% - var(--px) * 2));
}

.button:hover,
.button:focus-visible {
  background: var(--lime);
  color: var(--accent);
}

/* ---- header --------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  height: var(--header-h);
  display: flex;
  align-items: baseline;
  gap: 2rem;
  padding: var(--header-pad) var(--gutter) var(--header-pad-b);
  border-bottom: var(--rule);
}

/* see-through backing, drawn on a pseudo-element: blurring on the header
   itself would stop the narrow-screen menu inside it from blurring the page */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--glass);
  backdrop-filter: blur(4px);
}

.site-title {
  font-family: var(--display);
  font-style: italic;
  font-weight: 400;
  font-size: var(--fs-title);
  line-height: 1.2;
  white-space: nowrap;
  text-transform: none;
  letter-spacing: normal;
  text-decoration: none;
}

/* exception to the green link hover: the title stays put, and only the
   letter under the pointer lights up */
.site-title:hover,
.site-title:focus-visible {
  background: none;
  color: inherit;
}

#nav {
  display: flex;
  gap: 1.5rem;
  margin-left: auto;
}

#nav a { font-size: var(--fs-nav); }

#nav a[aria-current="page"] {
  background: var(--accent);
  color: var(--on-accent);
  text-decoration-color: transparent;
}

/* light / dark toggle: shows the moon in light mode, the sun in dark */
.theme-toggle {
  display: grid;
  place-items: center;
  align-self: baseline;   /* icon sits on the nav links' baseline */
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
}

.theme-toggle svg {
  width: 1.25rem;
  height: 1.25rem;
  fill: currentColor;
  shape-rendering: crispEdges;
}

.theme-toggle:hover { color: var(--accent); }
.theme-toggle .sun,
[data-theme="dark"] .theme-toggle .moon { display: none; }
[data-theme="dark"] .theme-toggle .sun { display: block; }

/* narrow-screen pieces */
.header-crow,
.menu-toggle { display: none; }

.header-crow:hover,
.header-crow:focus-visible { background: none; }

/* three pixel dots: the span is the middle dot, shadows are the outer two.
   Three dots when closed, an X when open. */
.menu-toggle {
  place-items: center;
  width: 2.75rem;
  aspect-ratio: 1;
  margin-left: auto;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.menu-toggle span {
  width: 6px;
  height: 6px;
  color: var(--ink);
  background: currentColor;
  box-shadow: -10px 0 currentColor, 10px 0 currentColor;
}

.menu-toggle:hover span { color: var(--accent); }

/* open: a 5x5 pixel X — the centre dot plus two pixels out along each diagonal */
.menu-toggle[aria-expanded="true"] span {
  color: var(--accent);
  box-shadow:
    -12px -12px currentColor, -6px -6px currentColor,
     12px -12px currentColor,  6px -6px currentColor,
    -12px  12px currentColor, -6px  6px currentColor,
     12px  12px currentColor,  6px  6px currentColor;
}

/* ---- footer --------------------------------------------------------- */
/* a thin line above small gray text */
.site-footer {
  margin-top: 6rem;
  padding: 1.25rem 0 2rem;
  border-top: var(--rule);
  color: var(--gray);
  font-size: var(--fs-small);
}

.site-footer p { margin: 0; }

/* ---- info layout: still left panel, scrolling right side ----------- */
.info {
  display: grid;
  grid-template-columns: var(--side-w) 1fr;
  grid-template-rows: 1fr auto;   /* footer sits at the bottom on short pages */
  grid-template-areas:
    "side body"
    "side foot";
  min-height: calc(100dvh - var(--header-h));
}

/* the right side is a sheet of see-through beige laid over the left panel,
   so artwork that overhangs the divider (the crow's tail) shows faintly
   through it */
.info::before {
  content: "";
  grid-column: 2;
  grid-row: 1 / -1;
  z-index: 1;
  background: color-mix(in srgb, var(--bg) 60%, transparent);   /* lower = more see-through */
  backdrop-filter: blur(3px);
}

.info-body,
.info .site-footer { z-index: 2; }

/* the page scrolls; the left panel holds still under the header */
.info-side {
  grid-area: side;
  position: sticky;
  top: var(--header-h);
  align-self: start;
  height: calc(100dvh - var(--header-h));
  display: flex;
  flex-direction: column;
  gap: 2rem;
  padding: var(--gutter);
  border-right: var(--rule);
}

.side-art {
  position: relative;
  flex: 1;
  min-height: 0;
  container-type: size;   /* lets artwork measure the panel (cqi / cqh units) */
  display: flex;
  flex-direction: column;
  align-items: flex-start;

  /* 1u = 1% of panel width — or smaller, if the title's longest line
     wouldn't fit across the panel, or the screen is too short for the
     crow to fit its full height */
  --u: min(
    1cqi,
    100cqi / (var(--title-size) * var(--title-em)),
    100cqh / (var(--crow-top) + var(--crow-size))
  );
}

.pixel-crow {
  position: relative;
  flex: none;
  width: calc(var(--crow-size) * var(--u));   /* may overhang the divider */
  aspect-ratio: 1;
  margin: calc(var(--crow-top) * var(--u)) 0 0 calc(var(--crow-left) * var(--u));
}

.pixel-crow img {
  display: block;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
}

/* crow.js redraws the crow pixel by pixel on a canvas for the scatter effect.
   The canvas overhangs the crow so pixels can fly past its edges; the img
   stays underneath as the fallback. */
.pixel-crow canvas {
  position: absolute;
  inset: -25%;
  width: 150%;
  height: 150%;
  pointer-events: none;
}

.pixel-crow.is-live img { visibility: hidden; }

.info-body {
  grid-area: body;
  max-width: calc(var(--measure) + var(--body-pad) * 2);
  padding: 4rem var(--body-pad) 0;
}

.info .site-footer {
  grid-area: foot;
  max-width: var(--measure);
  margin-inline: var(--body-pad);
}

.logos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
}

.logos a { text-decoration: none; }
.logos a:hover,
.logos a:focus-visible { background: none; opacity: 0.7; }
.logos img { display: block; height: 2.5rem; width: auto; }

/* ---- home ----------------------------------------------------------- */
/* the title lives in the left panel here; hidden (not removed) so the nav
   sits in exactly the same spot as on every other page */
.home .site-title { visibility: hidden; }

/* the site title, staggered: each line is indented (padding-left) and
   dropped a little below its natural spot (translate), in em so the
   stagger scales with the title */
.stagger {
  margin: 0;
  color: var(--ink);
  line-height: 1.05;
}

.stagger > span { display: block; white-space: nowrap; }
.stagger .smaller { font-size: 0.75em; }   /* "for an": 75% of the title size */

/* wide screens: five lines pinned to the top of the left panel. Taken out
   of the flow so the crow sits exactly where it does on ABOUT, and drawn on
   top of the crow. Sized in panel units (see :root), so it scales together
   with the crow. */
.side-art .stagger {
  position: absolute;
  top: calc(var(--title-top) * var(--u));
  left: 0;
  right: 0;
  z-index: 1;
  font-size: calc(var(--title-size) * var(--u));

  /* subtle pixel glow: a hard-edged, stepped beige outline so the letters
     stay readable where they cross the crow */
  --g: 0.04em;
  text-shadow:
    var(--g) 0 var(--bg), calc(var(--g) * -1) 0 var(--bg),
    0 var(--g) var(--bg), 0 calc(var(--g) * -1) var(--bg),
    var(--g) var(--g) var(--bg), calc(var(--g) * -1) var(--g) var(--bg),
    var(--g) calc(var(--g) * -1) var(--bg), calc(var(--g) * -1) calc(var(--g) * -1) var(--bg),
    calc(var(--g) * 2) 0 var(--bg), calc(var(--g) * -2) 0 var(--bg),
    0 calc(var(--g) * 2) var(--bg), 0 calc(var(--g) * -2) var(--bg);
}

.side-art .stagger > span:nth-child(1) { padding-left: 0.6em; translate: 0 -0.12em; }   /* Community */
.side-art .stagger > span:nth-child(2) { padding-left: 1.5em; translate: 0 0.08em; }    /* Rules */
.side-art .stagger > span:nth-child(3) { padding-left: 1.25em;   translate: 0 0.19em; }    /* for an */
.side-art .stagger > span:nth-child(4) { padding-left: 0;     translate: 0 0.29em; }    /* Open */
.side-art .stagger > span:nth-child(5) { padding-left: 1.8em; translate: 0 0.48em; }    /* Web */

/* narrow screens: the left panel is hidden, so a three-line copy sits atop
   the text */
.home-title { display: none; }
.home-title > span:nth-child(1) { padding-left: 0.6em; translate: 0 -0.12em; }   /* Community Rules */
.home-title .rules { display: inline-block; translate: 0 0.5em; }                /* Rules, relative to Community */
.home-title > span:nth-child(2) { padding-left: 1em;   translate: 0 0.19em; }     /* for an */
.home-title > span:nth-child(3) { padding-left: 2.2em; translate: 0 0.29em; }     /* Open Web */


/* "+ See our workshop calls and our CHI'26 paper" */
.see-also {
  margin: 2rem 0 2.5rem;
  font-family: var(--mono);
  font-weight: 600;
  font-size: var(--fs-small);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.see-also a { font-size: 1em; }

/* ---- animated crow sprite (4 stacked frames) ------------------------ */
.sprite {
  position: relative;
  width: var(--sprite, 3rem);
  aspect-ratio: 1;
}

.sprite img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
  opacity: 0;
  animation: sprite-cycle var(--sprite-cycle) infinite;
}

/* each frame owns one quarter of the loop */
/* --sprite-clock (set by theme.js) starts the loop where the wall clock says
   it should be, so the crow doesn't jump back to frame 1 on each new page */
.sprite img:nth-child(1) { animation-delay: var(--sprite-clock, 0s); }
.sprite img:nth-child(2) { animation-delay: calc(var(--sprite-clock, 0s) + var(--sprite-cycle) * -0.75); }
.sprite img:nth-child(3) { animation-delay: calc(var(--sprite-clock, 0s) + var(--sprite-cycle) * -0.5); }
.sprite img:nth-child(4) { animation-delay: calc(var(--sprite-clock, 0s) + var(--sprite-cycle) * -0.25); }

@keyframes sprite-cycle {
  0%,      25% { opacity: 1; }
  25.01%, 100% { opacity: 0; }
}

/* ---- narrow screens ------------------------------------------------- */
@media (width < 64rem) {
  :root {
    --header-pad: 0.5rem;   /* half the wide-screen top padding, to make room for the crow */
    --header-pad-b: 0px;
    --header-crow: 4rem;   /* size of the crow in the header */
    --header-h: calc(var(--header-crow) + var(--header-pad) + var(--rule-w));
  }

  /* the crow stands on the header line, like a bird on a wire */
  .site-header { align-items: flex-end; }

  .site-title { display: none; }

  .header-crow {
    --sprite: var(--header-crow);
    display: block;
    translate: 0 5.5%;   /* feet sit ~5.5% above the sprite's bottom edge */
  }

  .menu-toggle { display: grid; align-self: center; order: 2; margin-left: 0; }
  .theme-toggle {   /* sits just left of the dots, with a bigger tap area */
    order: 1;
    align-self: center;
    width: 2.75rem;
    aspect-ratio: 1;
    margin-left: auto;
  }

  /* the menu drops down under the header when the dots are clicked */
  #nav {
    display: none;
    position: absolute;
    top: calc(100% + var(--rule-w));   /* just below the header line, so the crow keeps its wire */
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.75rem;
    padding: 1rem var(--gutter) 1.25rem;
    background: var(--glass);
    backdrop-filter: blur(4px);   /* keeps the links readable over page text */
    border-bottom: var(--rule);
  }

  .site-header.is-open #nav { display: flex; }

  /* one column: text, footer, then the logos */
  :root { --body-pad: var(--gutter); }

  .info::before { display: none; }

  .info {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr auto auto;
    grid-template-areas: "body" "foot" "side";
  }

  .info-side {
    position: static;
    height: auto;
    padding: 0 var(--body-pad) 2rem;
    border-right: 0;
  }

  .side-art { display: none; }
  .home-title {
    display: block;
    margin-bottom: 1em;
    font-size: clamp(2.25rem, 9vw, 4.5rem);   /* big and dramatic; "Community Rules" still fits one line */
  }

  .info-body { padding-top: 2.5rem; }

  /* on tablet widths the screen is wider than a comfortable line of text:
     centre the column instead of leaving a gap on the right */
  .info-body,
  .info-side {
    justify-self: center;
    width: 100%;
    max-width: calc(var(--measure) + var(--body-pad) * 2);
  }

  .info .site-footer {
    justify-self: center;
    width: calc(100% - var(--body-pad) * 2);
  }
}

/* ---- motion --------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .sprite img { animation: none; }
  .sprite img:first-child { opacity: 1; }
}

/* ---- page transitions ----------------------------------------------- */
/* moving between pages cross-fades instead of flashing blank. Nothing is
   given a view-transition-name on purpose: the header and left panel are
   identical from page to page, so the fade leaves them still, whereas a
   named element is lifted above the page (losing the glass blur and the
   see-through sheet over the crow's tail) and pops back at the end */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}

::view-transition-group(root) { animation-duration: 0.2s; }
