Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,17 @@ the snapshot copy, and line endings are fixed by `.gitattributes`. So
regenerating it on an unchanged checkout should produce no diff at all, on any
platform.

**Known exception:** a change that touches global CSS (anything that changes
Tailwind's output, not just adds an already-used utility class) can rebuild
with a different content hash on Windows than on Linux CI, even with
byte-identical source and zero actual style changes — a platform-dependent
1-ULP rounding difference in a generated color fallback has been observed
(`UPD-019` in `UPDATES-NEEDED.md`). If `npm run check:snapshot` is clean
locally on Windows but CI still reports drift after a CSS-touching change,
don't keep re-running the Windows build: trigger `workflow_dispatch` on the
branch, download the `static-site-linux` artifact CI uploads on that failure,
and commit that snapshot in place of the local one.

That makes drift easy to check. From a clean tree:

```powershell
Expand Down
47 changes: 47 additions & 0 deletions UPDATES-NEEDED.md
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,53 @@ both Windows and Linux, or the investigation concludes with a documented
reason it isn't reliable enough to use, so the next person does not repeat
this same multi-round-trip experiment from scratch.

### UPD-019 - Tailwind's generated `lab()` fallback colors differ by platform

**Priority:** Low

While regenerating `static-site/` on Windows for an unrelated, CSS-free footer
change (a new social link plus a copy edit — no new Tailwind utility was
introduced), the resulting global stylesheet chunk hashed differently than the
one CI produced from the identical commit. Diffing the two byte-for-byte
found exactly one differing value, four decimal places into a generated
`lab()` fallback: `--color-rose-500: lab(56.101% 79.4328 31.4532)` on Linux
vs. `lab(56.101% 79.4329 31.4532)` on Windows — a 1-in-100,000 rounding
difference in the sRGB→Lab conversion Tailwind v4/Lightning CSS performs for
wide-gamut color fallbacks. `--color-rose-500` is not used anywhere in this
codebase; this would affect any Tailwind v4 default-palette color whose
conversion happens to land near a rounding boundary.

Because Next.js names CSS chunks after a content hash, this single-ULP
difference was enough to rename the whole shared stylesheet, which in turn
touched every page's HTML (new `<link>` href) and RSC payload (new chunk
reference) — a large, misleading diff for a change that did not touch styles
at all. Likely root cause: a platform-dependent floating-point library
(libm/CRT) used by Lightning CSS's Rust color-math, same family of issue as
UPD-004 and UPD-018, but in the opposite direction — content byte-identical
except for one rounded value, rather than a path-shape or scan-visibility
difference.

**Workaround used:** rather than committing the Windows-built snapshot,
triggered `workflow_dispatch` on the branch, downloaded the `static-site-linux`
artifact CI uploads on failure, and committed that in place of the local
build. Reliable, but it only works because that artifact-upload step
(added for UPD-018's investigation) already exists, and it costs a CI
round trip per snapshot regeneration on Windows.

**Proposed update:** Confirm whether pinning `@tailwindcss/oxide-win32-*` /
`-linux-*` to matching Lightning CSS versions removes the discrepancy, or
whether it is inherent to the two platforms' floating-point math. If
inherent, consider whether Tailwind's generated color fallbacks can be
rounded to fewer decimal places (reducing the chance any platform's rounding
crosses a boundary), or accept that any Windows-built snapshot touching
global CSS must be verified against a Linux CI artifact before committing,
and say so in `CONTRIBUTING.md` section 4.

**Acceptance:** A snapshot regenerated on Windows with no real style changes
produces the same CSS chunk hash as one regenerated on Linux, or the
Windows→Linux-artifact workaround above is written into `CONTRIBUTING.md` as
the documented procedure.

### UPD-017 - Decide how UI symbols are drawn

**Priority:** Medium — **done.**
Expand Down
20 changes: 20 additions & 0 deletions src/components/SiteFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,25 @@ function GitHubIcon({ className }: IconProps) {
);
}

function LumaIcon({ className }: IconProps) {
return (
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.6"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden
className={className}
>
<rect x="3" y="4.5" width="18" height="16" rx="2.5" />
<path d="M3 9.5h18" />
<path d="M8 2.5v4M16 2.5v4" />
</svg>
);
}

function InstagramIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className={className}>
Expand Down Expand Up @@ -38,6 +57,7 @@ function LinkedInIcon({ className }: IconProps) {
const socials = [
{ key: "linkedin", href: site.linkedin, label: "LinkedIn", Icon: LinkedInIcon },
{ key: "github", href: site.social.github, label: "GitHub", Icon: GitHubIcon },
{ key: "luma", href: site.social.luma, label: "Events calendar (Luma)", Icon: LumaIcon },
{ key: "instagram", href: site.social.instagram, label: "Instagram", Icon: InstagramIcon },
{ key: "twitter", href: site.social.twitter, label: "X (Twitter)", Icon: XIcon },
].filter((s) => s.href);
Expand Down
3 changes: 2 additions & 1 deletion src/content/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ export const site = {
partnersLine: "NYU SPS · CGA · Microsoft · New York",
footerBlurb:
"Exploring intervention opportunities at the intersection of emerging technologies and the human condition.",
cohortRange: "Four cohorts · est. 2024-2026",
cohortRange: "Four cohorts · est. 2024",
// Social links. GitHub is the real org; instagram/twitter are placeholders —
// swap in the real handles once the accounts exist. Set to "" to hide a link.
social: {
github: "https://github.com/Ethical-Tech-CoLab",
luma: "https://luma.com/ethical-tech-colab",
// Hidden for now — the footer drops any social with an empty href. Restore
// by pasting the real handle back in.
instagram: "", // TODO: real Instagram handle (hidden until account exists)
Expand Down
2 changes: 1 addition & 1 deletion static-site/404.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion static-site/404/index.html

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions static-site/__next.__PAGE__.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
1:"$Sreact.fragment"
2:I[85437,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Image"]
3:I[25150,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"HeroField"]
4:I[82987,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Reveal"]
5:I[53675,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"StatementCarousel"]
e:I[23475,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Link"]
f:I[82987,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Stagger"]
10:I[82987,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"StaggerItem"]
11:I[35852,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"ProjectDiagram"]
12:I[12243,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Tilt3D"]
16:I[94376,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Magnetic"]
17:I[97367,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0d661ugsqhy3v.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js"],"OutletBoundary"]
2:I[85437,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Image"]
3:I[25150,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"HeroField"]
4:I[82987,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Reveal"]
5:I[53675,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"StatementCarousel"]
e:I[23475,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Link"]
f:I[82987,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Stagger"]
10:I[82987,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"StaggerItem"]
11:I[35852,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"ProjectDiagram"]
12:I[12243,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Tilt3D"]
16:I[94376,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js","/website/_next/static/chunks/19vp06bog18ae.js"],"Magnetic"]
17:I[97367,["/website/_next/static/chunks/402x-bnzu27si.js","/website/_next/static/chunks/0nd82-2dezawm.js","/website/_next/static/chunks/14mrh2-p_w84d.js","/website/_next/static/chunks/42slhzgb7dvh7.js"],"OutletBoundary"]
18:"$Sreact.suspense"
0:{"rsc":["$","$1","c",{"children":[[["$","section",null,{"className":"relative overflow-hidden border-b border-border","children":[["$","$L2",null,{"src":"/website/nyu-subway.jpg","alt":"","aria-hidden":true,"fill":true,"priority":true,"sizes":"100vw","className":"pointer-events-none object-cover object-center opacity-25"}],["$","div",null,{"aria-hidden":true,"className":"pointer-events-none absolute inset-0 bg-background/70"}],["$","span",null,{"className":"aura"}],["$","div",null,{"aria-hidden":true,"className":"pointer-events-none absolute inset-0","style":{"background":"radial-gradient(70% 60% at 20% 0%, color-mix(in oklab, var(--glow) 26%, transparent), transparent 65%)"}}],["$","$L3",null,{}],["$","div",null,{"className":"relative mx-auto max-w-6xl px-6 py-24 text-center sm:py-28","children":[["$","$L4",null,{"children":["$","p",null,{"className":"text-base uppercase tracking-[0.25em] text-accent sm:text-lg","children":"NYU CGA × Microsoft"}]}],["$","$L4",null,{"delay":0.15,"children":["$","$L5",null,{"statements":[{"lead":"Ethical Tech CoLab","headingClass":"text-[clamp(4.25rem,13vw,11rem)] leading-[0.88]","figure":["$","p",null,{"className":"font-serif uppercase leading-[0.95] tracking-tight text-foreground","style":{"fontSize":"clamp(1.9rem, 4vw, 3rem)"},"children":["Exploring technology to improve",["$","br",null,{"className":"hidden sm:block"}]," the"," ",["$","span",null,{"className":"display-em","children":"human condition"}],"."]}],"line":["$","p",null,{"className":"mx-auto mt-7 max-w-2xl leading-relaxed text-foreground/85","children":["A research collaboration between NYU's"," ",["$","a",null,{"href":"https://www.sps.nyu.edu/about/academic-divisions-and-departments/center-for-global-affairs.html","target":"_blank","rel":"noopener noreferrer","className":"link-underline text-accent hover:opacity-80","children":"Center for Global Affairs"}]," ","and Microsoft — changing the conversation on how people are informed, and how emerging technology can be used for good."]}]},{"lead":"Five questions. ","em":"One frontier.","figure":"18 projects in the portfolio","line":"Evacuation, cultural heritage, traceability, diplomacy — each question carried through to a fielded prototype, in the open.","cta":"Explore the portfolio","href":"/portfolio"},{"lead":"Run the ","em":"research","tail":".","figure":"25 demos you can open","line":"Not screenshots: the prototypes themselves, running in the browser with their source alongside.","cta":"Open the live demos","href":"/portfolio"},{"lead":"The research, ","em":"written up","tail":".","figure":"29 in the catalogue","line":"Every research question the CoLab takes on is written up academically, including what did not hold.","cta":"Read the publications","href":"/publications"},{"lead":"The people ","em":"building","tail":" this.","figure":"23 researchers across 3 cohorts","line":"Graduate researchers at NYU's Center for Global Affairs, with advisors and resident fellows alongside.","cta":"Meet the team","href":"/team"}],"label":"Statement","className":"mt-5"}]}]]}]]}],[["$","section",null,{"className":"border-b border-border bg-surface/40","children":["$","div",null,{"className":"mx-auto max-w-6xl px-6 py-16 text-center","children":[["$","$L4",null,{"children":["$","p",null,{"className":"text-xs uppercase tracking-wider text-muted","children":"Mission"}]}],["$","$L4",null,{"delay":0.05,"children":["$","p",null,{"className":"mx-auto mt-4 max-w-4xl fluid-h2 font-heading uppercase leading-[1.02]","children":["Achieving ",["$","span",null,{"className":"display-em","children":"full human potential"}]," ","through technology — changing how people are informed, and how tech is used for good."]}]}],["$","$L4",null,{"delay":0.1,"children":["$","p",null,{"className":"mx-auto mt-6 max-w-2xl text-lg leading-relaxed text-muted","children":"What are the circumstances of the human being, and how can technology improve them? We see technology as a tool — part of the solution."}]}]]}]}],["$","section",null,{"className":"mx-auto max-w-6xl px-6 py-24","children":[["$","$L4",null,{"children":["$","div",null,{"className":"flex items-end justify-between","children":["$L6","$L7"]}]}],"$L8"]}],"$L9","$La","$Lb"]],["$Lc"],"$Ld"]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"static-snapshot"}
6:["$","div",null,{"children":[["$","$Le",null,{"href":"/portfolio","className":"link-underline text-xs uppercase tracking-wider text-muted transition-colors hover:text-accent","children":"Current projects"}],["$","h2",null,{"className":"mt-3 fluid-h2 font-heading uppercase","children":"Building at the frontier."}]]}]
Expand Down
Loading
Loading