@font-face {
  font-family: Inter;
  src: url('design-system/assets/assembly-row-map/fonts/Inter-variable.ttf') format('truetype');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: Oswald;
  src: url('design-system/assets/assembly-row-map/fonts/Oswald-Medium.ttf') format('truetype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* Breakpoints follow tulip.co's (Tailwind's): sm 40rem (640 px), md 48rem (768 px), lg 64rem (1024 px), written as
   tulip.co writes them, `not all and (min-width: …)` for below one. */
:root { color-scheme: light; font-family: Inter, Arial, sans-serif; color: #00263e; background: #fff; }
/* Buttons don't inherit the page font by default (the browser gives them Arial). */
button { font: inherit; }
* { box-sizing: border-box; }
body { margin: 0; }

.era-hero {
  --heading-top: clamp(105px, 18.5vh, 230px);
  --headline-size: clamp(44px, 5.1vw, 84px);
  isolation: isolate;
  position: relative;
  min-height: 680px;
  height: 100svh;
  overflow: hidden;
  background: #fff;
}

.atmosphere {
  /* the hero's back layer at every size: everything else in the hero stacks above it (1–4), and it takes no taps */
  position: absolute;
  z-index: 0;
  pointer-events: none;
  left: 50%;
  top: 0;
  width: min(1400px, 112vw);
  height: clamp(1000px, 104vw, 1600px);
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse closest-side,
    #91ccdf00 48%,
    #b6e4ef55 60%,
    #85c3d6cc 72%,
    #addbe899 82%,
    #b6e4ef00 100%);
  filter: blur(25px);
  animation: atmosphere-breathe 24s ease-in-out infinite alternate;
}

.hero-heading {
  position: relative;
  z-index: 2;
  text-align: center;
  padding: var(--heading-top) 32px 0;
}

h1 {
  margin: 0 auto;
  max-width: min(900px, 74vw);
  font-size: var(--headline-size);
  font-weight: 450;
  line-height: 1.11;
  letter-spacing: -.055em;
  text-wrap: balance;
}
h1 span { display: block; }

.keynote-logo {
  display: block;
  width: 280px;
  height: auto;
  margin: 0 auto 30px;
}

.hero-heading h1 { animation: heading-arrive 1.5s cubic-bezier(.2,.7,.2,1) both; }
.keynote-logo { animation: heading-arrive 1.5s .18s cubic-bezier(.2,.7,.2,1) both; }

.orbital-field {
  position: absolute;
  z-index: 1;
  inset: 0;
  pointer-events: none;
  animation: orbit-arrive 2s ease-out both;
}
.orbits { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.orbit { animation: orbit-trace var(--period) linear infinite; }
.orbit-outer { --period: 96s; }
.orbit-middle { --period: 76s; animation-direction: reverse; }
.orbit-inner { --period: 58s; }
.orbit-path { stroke: #476f81; stroke-opacity: .32; stroke-width: 1.2; stroke-dasharray: 6 8; }
.asset-orbit { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.asset-slab {
  will-change: transform;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: clamp(155px, 19vw, 250px);
  transform: translate(-50%, -52%);
}
.asset-slab img {
  display: block;
  width: 100%;
  height: auto;
  filter: grayscale(var(--slab-grayscale, 1)) drop-shadow(0 18px 16px #30383c16);
  transition: filter .3s;
  /* the pinned scroll pops each slab up as the ring's line reaches it (future.js, --slab-lift 0 → 1) */
  translate: 0 calc(var(--slab-lift, 0) * -10px);
  scale: calc(1 + var(--slab-lift, 0) * .04);
}
/* Harmony category ink tokens from design-system/tokens.json. */
.slab-apps { --accent: #003B61; }
.slab-edge { --accent: #6B0A17; }
.slab-connectors { --accent: #704001; }
.slab-tables { --accent: #174035; }

.is-away .orbit, .is-away .atmosphere, .is-away .asset-slab img { animation-play-state: paused; }

@keyframes orbit-trace { to { stroke-dashoffset: -280; } }
@keyframes atmosphere-breathe { from { transform: translate(-50%, -50%) scale(1); opacity: .9; } to { transform: translate(-50%, -50%) scale(1.04); opacity: 1; } }
@keyframes heading-arrive { from { opacity: 0; transform: translateY(15px); filter: blur(3px); } to { opacity: 1; transform: translateY(0); filter: blur(0); } }
@keyframes orbit-arrive { from { opacity: 0; } to { opacity: 1; } }

@media (min-aspect-ratio: 19/10) {
  .era-hero { --heading-top: 12vh; }
}
@media not all and (min-width: 48rem) {
  .era-hero { min-height: 620px; --heading-top: 18svh; --headline-size: clamp(38px, 7.5vw, 44px); /* no larger than the desktop headline starts at 768 px (44 px) */ }
  .hero-heading { padding: var(--heading-top) 22px 0; }
  h1 { line-height: 1.15; letter-spacing: -.055em; }
  .keynote-logo { width: 220px; margin: 0 auto 24px; }
  .atmosphere { width: 145vw; height: 960px; filter: blur(22px); }
  .asset-slab { width: 160px; }
}
@media not all and (min-width: 40rem) {
  .era-hero { --headline-size: 37px; --heading-top: 16svh; }
  h1 span:last-child { max-width: 340px; margin: auto; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

.asset-slab:focus-visible { outline: 2px solid var(--accent); outline-offset: -20px; border-radius: 24px; }
.asset-slab:is(:hover, :focus-visible, .is-connected) img {
  filter: grayscale(0);
}
.slab-connections { pointer-events: none; opacity: 0; transition: opacity .2s; }
.slab-connections.is-visible { opacity: 1; }
.slab-connections path { fill: none; stroke-linecap: round; }
.connection-line { fill: none; stroke: var(--connection-colour, #003B61); stroke-width: 1.2; stroke-dasharray: 6 8; }
.connection-reveal { stroke: white; stroke-width: 6; }
.slab-connections.is-visible .connection-reveal { animation: connection-draw 1s cubic-bezier(.2,.6,.3,1) both; }
@keyframes connection-draw { from { stroke-dasharray: 1; stroke-dashoffset: 1; } to { stroke-dasharray: 1; stroke-dashoffset: 0; } }

html { scroll-behavior: smooth; scroll-padding-top: 110px; }
.glass-nav {
  position: fixed;
  z-index: 10;
  top: 22px;
  left: 50%;
  transform: translateX(-50%);
  width: min(640px, calc(100% - 48px));
  height: 60px;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  border: 1px solid #ffffffcc;
  border-radius: 18px;
  background: #ffffff70;
  -webkit-backdrop-filter: blur(22px) saturate(1.15);
  backdrop-filter: blur(22px) saturate(1.15);
  box-shadow: inset 0 1px 0 #ffffffd9, 0 6px 22px #163a4d12, 0 2px 6px #163a4d06;
}
.nav-brand { display: flex; flex-shrink: 0; }
/* Spacing and sizes follow tulip.co's header: 60 px bar, 24 px ends, 76 px logo, 16 px links each padded 24 px
   either side and the full bar height. The font stays the keynote's (Inter), a design decision with Andrew, 2026-10-06. The links run into the end padding so the last word sits 24 px in. */
.nav-brand img { display: block; width: 76px; height: auto; }
.nav-links { display: flex; align-self: stretch; margin-right: -24px; }
.nav-links a { display: flex; align-items: center; padding: 0 24px; color: #244658; font-size: 16px; font-weight: 500; text-decoration: none; transition: color .2s; }
.nav-links a:hover { color: #00263e; text-decoration: underline; text-underline-offset: 6px; }
.glass-nav a:focus-visible { outline: 2px solid #577d90; outline-offset: -6px; border-radius: 8px; }
/* scrolling tucks the nav up out of view; a pause brings it back (future.js). It glides away
   (easing in, fading as it goes) and settles back (a long ease-out, fading in first), so neither move snaps */
.glass-nav { transition: translate .6s cubic-bezier(.16,1,.3,1), opacity .35s ease; }
.glass-nav.is-tucked { translate: 0 calc(-100% - 30px); opacity: 0; transition: translate .5s cubic-bezier(.55,0,.75,.35), opacity .3s ease .15s; }
.keynote-section { width: min(1120px, calc(100% - 64px)); margin: 0 auto; min-height: 45svh; padding: 60px 0; border-top: 1px solid #00263e16; }
.keynote-section h2 { margin: 0; font-size: clamp(32px, 4vw, 56px); font-weight: 450; letter-spacing: -.045em; }
/* Below 768 px the links fold into a menu, as tulip.co does (a three-line button, then a full-screen panel of rows
   with a close button where the button was), in this page's own styling */
.nav-toggle, .site-menu-close { display: none; place-items: center; width: 44px; height: 44px; margin-right: -10px; padding: 0; border: 0; border-radius: 10px; background: none; color: #244658; cursor: pointer; }
.nav-toggle svg, .site-menu-close svg { width: 24px; height: 24px; }
.nav-toggle:hover, .site-menu-close:hover { color: #00263e; }
.nav-toggle:focus-visible, .site-menu-close:focus-visible { outline: 2px solid #577d90; outline-offset: -4px; }
.site-menu[hidden] { display: none; }
.site-menu { position: fixed; z-index: 20; inset: 0; display: flex; flex-direction: column; background: #ffffffeb; -webkit-backdrop-filter: blur(22px) saturate(1.15); backdrop-filter: blur(22px) saturate(1.15); animation: menu-in .2s ease-out; }
.site-menu-bar { display: flex; align-items: center; justify-content: space-between; height: 52px; margin: 14px 14px 0; padding: 0 16px; }
.site-menu-bar .site-menu-close { display: grid; }
.site-menu-links { display: flex; flex-direction: column; margin-top: 20px; padding: 0 30px; }
.site-menu-links a { display: flex; align-items: center; min-height: 57px; border-bottom: 1px solid #00263e16; color: #00263e; font-size: 17px; font-weight: 500; text-decoration: none; }
.site-menu-links a:last-child { border-bottom: 0; }
.site-menu-links a:hover { color: #244658; }
.site-menu-links a:focus-visible { outline: 2px solid #577d90; outline-offset: 2px; border-radius: 4px; }
@keyframes menu-in { from { opacity: 0; } to { opacity: 1; } }
@media not all and (min-width: 48rem) {
  .glass-nav { top: 14px; width: calc(100% - 28px); height: 52px; padding: 0 16px; border-radius: 16px; gap: 12px; }
  .nav-brand img { width: 68px; }
  .nav-links { display: none; }
  .nav-toggle { display: grid; }
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

.keynote-video { width: calc(100% - 48px); margin: 0 auto; padding-bottom: 100px; }
/* each film's title, one small line above it at its left edge: hidden on the page for now (Bryan, 2026-10-07), kept
   for screen readers and search, since it names the film's section */
.video-head { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.video-head h2 { margin: 0; font-size: 12px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: #456574; }
.video-placeholder {
  transform-origin: top center;
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  background: #000;
  color: #f1f7f8;
  border: 1px solid #000;
}
.keynote-film { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: #000; }
.video-overlay { position: absolute; inset: 0; background: linear-gradient(0deg, #000000b3, #00000033 45%, #00000059); transition: opacity .3s ease; }
.video-placeholder.is-playing .video-overlay { opacity: 0; pointer-events: none; }
.video-play { color: inherit; cursor: pointer; padding: 0; transition: transform .2s ease, background-color .2s ease; }
.video-placeholder .video-play:hover { transform: scale(1.06); background-color: #1a1a1a; }
.video-play:focus-visible { outline: 2px solid #a8d8e5; outline-offset: 4px; }
.video-event-logo { position: absolute; top: 32px; left: 36px; width: 190px; height: auto; opacity: .8; }
.video-placeholder-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; }
.video-play { display: grid; place-items: center; width: 72px; height: 72px; border: 1px solid #ffffff50; border-radius: 50%; background: #ffffff08; }
.video-play svg { width: 26px; height: 26px; }
.video-placeholder-center p { margin: 0; font-size: 13px; color: #f1f7f8; letter-spacing: .02em; text-shadow: 0 1px 8px #000c; }
.video-placeholder h2 { position: absolute; bottom: 32px; left: 36px; right: 36px; max-width: 650px; margin: 0; font-size: clamp(18px, 2.3vw, 28px); line-height: 1.25; font-weight: 450; letter-spacing: -.025em; }
@media not all and (min-width: 48rem) {
  h1 { max-width: 100%; }
  .keynote-video { padding-bottom: 64px; }
  .video-placeholder { aspect-ratio: 4 / 3; border-radius: 8px; }
  .video-event-logo { top: 20px; left: 22px; width: 145px; }
  .video-play { width: 48px; height: 48px; }
  .video-placeholder-center { gap: 10px; padding-bottom: 20px; }
  .video-placeholder h2 { left: 22px; right: 22px; bottom: 20px; font-size: 17px; }
}

.slab-apps img { transform: rotate(14deg); transform-origin: 50% 52%; }
.slab-edge img { transform: rotate(-14deg); transform-origin: 50% 52%; }

.video-thumbnail { position: absolute; right: -9%; top: -24%; width: 88%; height: 160%; object-fit: contain; opacity: .85; }
.video-thumbnail-shade { position: absolute; inset: 0; background: linear-gradient(90deg, #092b3de6, #092b3d10 72%), linear-gradient(0deg, #092b3df2, transparent 45%); }
.video-placeholder .video-play { background: #000; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
@media not all and (min-width: 48rem) { .video-thumbnail { width: 125%; right: -35%; opacity: .65; } }

#top { position: relative; isolation: isolate; z-index: 1; }
.page-thread { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; z-index: 4; pointer-events: none; }
.page-thread-origin rect { fill: #f4fafc; stroke: #648593; stroke-width: 1; }
.page-thread-origin text { fill: #456574; font-family: Inter, Arial, sans-serif; font-size: 11px; font-weight: 450; letter-spacing: .04em; }
.page-thread-line { fill: none; stroke: #648593; stroke-width: 1.25; stroke-linecap: round; stroke-dasharray: 6 8; }
.page-thread-end { fill: #648593; opacity: 0; transform-box: fill-box; transform-origin: center; transform: scale(.4); transition: opacity .25s, transform .35s cubic-bezier(.2,.9,.25,1.3); }
.page-thread-end.is-visible { opacity: 1; transform: none; }
.page-thread-measure { visibility: hidden; }
/* The line is drawn once, in its five straight runs (each with the corner after it), and revealed by sliding each
   run's clipping box open: two transforms per run, so scrolling never repaints it (a mask on one page-tall drawing
   was redrawn every frame, which lagged on phones). The dashes run on across the joins (future.js). */
.page-thread-pieces { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.page-thread-piece, .page-thread-piece > div { position: absolute; will-change: transform; }
.page-thread-piece { overflow: hidden; }
.page-thread-piece > div { inset: 0; }
.page-thread-piece svg { position: absolute; inset: 0; overflow: visible; }
.slab-connections.is-scroll-reveal .connection-reveal { animation: none; stroke-dasharray: 1; stroke-dashoffset: var(--reveal-offset, 1); }

.hero-scroll-scene { height: 170svh; min-height: calc(680px + 70svh); }
.hero-scroll-scene .era-hero { position: sticky; top: 0; will-change: transform; } /* future.js zooms it in over the pinned scroll */
@media not all and (min-width: 48rem) { .hero-scroll-scene { min-height: calc(620px + 70svh); } }
/* below desktop: the title on top at its own size; under it, the desktop rings at their 1024 px proportions,
   smaller on narrow screens and cropped at the sides, the four slabs pulled in fully on screen and the scroll label
   at the bottom centre of the ring. future.js places them and sets the hero's height. No pinned scroll scene: the
   slabs colour in as the page scrolls, the ring drawn throughout; no hover or tap on the slabs. */
@media not all and (min-width: 64rem) {
  .hero-scroll-scene { height: auto; min-height: 0; }
  .hero-scroll-scene .era-hero { position: relative; min-height: 0; --heading-top: 130px; }
  .hero-scroll-scene .hero-heading { padding-top: calc(var(--heading-top) + var(--hero-extra, 0px)); }
  .era-hero .asset-slab { width: var(--slab-width, 160px); }
  /* the rings: their upper halves fade out, so they read as semicircles under the title, not full rings */
  .era-hero .orbital-field {
    -webkit-mask-image: linear-gradient(to bottom, transparent calc(var(--ring-cy, 0px) - var(--ring-ry, 0px) * .35), #000 calc(var(--ring-cy, 0px) + var(--ring-ry, 0px) * .15));
    mask-image: linear-gradient(to bottom, transparent calc(var(--ring-cy, 0px) - var(--ring-ry, 0px) * .35), #000 calc(var(--ring-cy, 0px) + var(--ring-ry, 0px) * .15));
  }
  /* the glow on the rings: centred on them, and sized so its brightest band (72 % out) traces the middle ring
     (1147 wide gives 413 against the ring's 410; 792 tall gives 285, the ring's height), scaled with them. Its upper
     half fades out like the rings', so it's a U under the title, never a full ring */
  .era-hero .atmosphere {
    top: var(--ring-cy, 0px);
    width: calc(1147px * var(--ring-scale, 1)); height: calc(792px * var(--ring-scale, 1));
    -webkit-mask-image: linear-gradient(to bottom, transparent 40%, #000 60%);
    mask-image: linear-gradient(to bottom, transparent 40%, #000 60%);
    /* no blur here: a mask clips at the glow's box, so blur spilling past its bottom would be cut into a hard line;
       the gradient already fades to nothing at its edge */
    filter: none;
  }
  .asset-slab .slab-hit { pointer-events: none; cursor: default; }
  .asset-slab .slab-label { display: none; }
}
@media not all and (min-width: 48rem) {
  .hero-scroll-scene .era-hero { --heading-top: 104px; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-scroll-scene { height: auto; min-height: 0; }
  .hero-scroll-scene .era-hero { position: relative; }
}

.era-hero.is-scroll-colouring .asset-slab img { transition: none; }

/* Press release excerpt under the vision film */
#top { overflow-x: clip; }
/* the logo slide's floor grid, full window width behind the release, fading out at the top and bottom, and kept
   faint behind the text column (about a third of its strength from the column's edge on) so it doesn't read through
   the words; the two masks multiply */
.release-floor { position: absolute; z-index: -1; top: 0; bottom: 0; left: 50%; width: 100vw; transform: translateX(-50%); pointer-events: none; opacity: .6;
  --grid-down: linear-gradient(to bottom, transparent, #000 35%, #000 75%, transparent);
  --grid-across: linear-gradient(to right, #000 30%, #0005 46%, #0005);
  -webkit-mask-image: var(--grid-down), var(--grid-across); -webkit-mask-composite: source-in;
  mask-image: var(--grid-down), var(--grid-across); mask-composite: intersect; }
/* one column below 1024 px: the text runs full width, so the grid is faint throughout */
@media not all and (min-width: 64rem) { .release-floor { --grid-across: linear-gradient(#0005, #0005); } }
.release-floor svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: hidden; }
.keynote-release { position: relative; isolation: isolate; width: min(1120px, calc(100% - 64px)); margin: 0 auto; padding: 24px 0 120px; display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 32px 72px; align-items: start; }
.release-eyebrow { grid-column: 1 / -1; margin: 0; font-size: 12px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: #456574; }
.keynote-release h2 { margin: 0; font-size: clamp(30px, 3.4vw, 48px); line-height: 1.08; font-weight: 450; letter-spacing: -.04em; position: sticky; top: 110px; }
.release-body { max-width: 640px; font-size: 17px; line-height: 1.6; color: #2b4a5a; }
.release-body p { margin: 0 0 20px; }
.release-body .release-lede { font-size: 20px; line-height: 1.5; color: #00263e; }
.release-body blockquote { margin: 36px 0; padding: 4px 0 4px 24px; border-left: 2px solid #a8d8e5; }
.release-body blockquote p { margin: 0 0 14px; font-size: 19px; line-height: 1.5; color: #00263e; letter-spacing: -.01em; }
.release-body cite { font-style: normal; font-size: 14px; color: #456574; }
.release-body cite strong { font-weight: 600; color: #00263e; }
.release-stages { list-style: none; margin: 0 0 32px; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.release-stages li { padding: 16px 16px 18px; border: 1px solid #00263e16; border-radius: 8px; background: #ffffffd9; -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); font-size: 14px; line-height: 1.45; }
.release-stages strong { display: block; margin-bottom: 6px; font-size: 16px; font-weight: 550; color: #00263e; letter-spacing: -.01em; }
/* the way on to the full release: a button on the column's left edge (with the stage cards and the quotes' rule),
   clear of the last quote; full width and finger-sized on phones */
.release-link { display: inline-flex; align-items: center; justify-content: center; gap: 8px; margin-top: 8px; min-height: 44px; padding: 0 20px; border-radius: 8px; background: #00263e; color: #fff; font-size: 15px; font-weight: 500; text-decoration: none; transition: background-color .2s ease, transform .2s ease; }
.release-link:hover { background: #003b61; }
.release-link:active { transform: scale(.98); }
.release-link:focus-visible { outline: 2px solid #577d90; outline-offset: 3px; }
@media not all and (min-width: 40rem) { .release-link { display: flex; width: 100%; min-height: 48px; font-size: 16px; } }
@media not all and (min-width: 64rem) {
  .keynote-release { grid-template-columns: 1fr; width: calc(100% - 44px); gap: 20px; padding-bottom: 80px; }
  .keynote-release h2 { position: static; }
  .release-body { font-size: 16px; }
  .release-body .release-lede { font-size: 18px; }
  .release-stages { grid-template-columns: 1fr; }
}

/* Speakers: the keynote lineup (design-system/speakers-overview.js). Its crops are on a 288 × 306 panel,
   kept here as percentages so they hold at any card width. */
.speakers-head { display: flex; align-items: baseline; justify-content: space-between; gap: 24px; margin-bottom: 40px; }
/* Rows that wrap: six cards across on desktop, four on tablets, two on phones. */
.speaker-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 32px 16px; }
.speaker-card { min-width: 0; }
.speaker-panel { position: relative; aspect-ratio: 288 / 306; overflow: hidden; border-radius: 5px; }
.speaker-photo { position: absolute; left: 0; top: 12.4%; width: 108%; height: auto; max-width: none; }
.speaker-card[data-id="natan-linder"] .speaker-photo { width: 440%; left: -155%; top: 3.9%; }
.speaker-card[data-id="kailey-crothers"] .speaker-photo { width: 230%; left: -54%; top: 9.8%; }
.speaker-card[data-id="paul-koschnitzke"] .speaker-photo { width: 100%; top: 14.4%; }
.speaker-card[data-id="sarath-krishnaswamy"] .speaker-photo { width: 120%; top: 13.1%; }
.speaker-card[data-id="les-karpas"] .speaker-photo { width: 96.4%; left: -3.3%; top: 13.7%; } /* face as large as the others', head top just under the logo */
.speaker-logo { position: absolute; z-index: 1; left: 6.25%; top: 6.5%; width: 37.5%; height: 10.5%; object-fit: contain; object-position: left center; }
.speaker-card:is([data-company="tiffany"], [data-company="smith-nephew"]) .speaker-logo { width: 54.9%; height: 11.8%; }
.speaker-card[data-company="smith-nephew"] .speaker-logo { filter: brightness(0); }
.speaker-card[data-company="avantor"] .speaker-logo { width: 66.7%; height: 15.7%; top: 4.6%; }
.speaker-card h3 { margin: 12px 2px 4px; font: 500 18px/1.1 Oswald, Inter, sans-serif; letter-spacing: -.2px; }
.speaker-card p { margin: 0 2px; font-size: 13px; font-weight: 500; line-height: 1.3; color: #4d6778; }
/* the keynote lineup's panel colours: mint, blue, celery, lavender, light blue, soft mint (tokens.json) */
.c-mint { background: #c8e6dc; } .c-blue { background: #c2e2ff; } .c-celery { background: #f2eea1; }
.c-lavender { background: #d9e0f2; } .c-lightBlue { background: #c5d9e7; } .c-softMint { background: #e3f7ee; }

/* Staggered reveal as in the keynote: each card rises while its panel wipes down. Only set up by future.js. */
.speaker-grid.will-reveal .speaker-card { opacity: 0; transform: translateY(28px) scale(.94); transition: opacity .7s, transform .7s; transition-timing-function: cubic-bezier(.22,1,.36,1); transition-delay: var(--delay); }
.speaker-grid.will-reveal .speaker-panel { clip-path: inset(0 0 100% 0 round 5px); transition: clip-path .75s cubic-bezier(.22,1,.36,1) var(--delay); }
.speaker-grid.is-revealed .speaker-card { opacity: 1; transform: none; }
.speaker-grid.is-revealed .speaker-panel { clip-path: inset(0 0 0% 0 round 5px); }
@media not all and (min-width: 64rem) { .speaker-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media not all and (min-width: 40rem) {
  .speakers-head { margin-bottom: 28px; }
  .speaker-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px 12px; }
  .speaker-card h3 { font-size: 16px; margin-top: 10px; }
  .speaker-card p { font-size: 12px; }
}

/* Features: the keynote's launch recap, one row per stage; each release a card with a thumbnail */
.keynote-features { min-height: 0; padding-bottom: 56px; }
.features-intro { margin: 14px 0 40px; font-size: 17px; color: #456574; }
.features-intro a { color: #003B61; text-decoration: none; border-bottom: 1px solid #003B6140; }
.features-intro a:hover { border-bottom-color: #003B61; }
.feature-stage { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 24px; padding: 32px 0; border-top: 1px solid #00263e16; }
.feature-stage h3 { align-self: start; justify-self: start; margin: 0; padding: 8px 14px; border-radius: 5px; background: #eef4f6; font: 500 15px/1.2 "Noto Sans Mono", ui-monospace, monospace; letter-spacing: .02em; color: #00263e; }
.feature-stage ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.feature-stage li { display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; gap: 0 10px; }
/* each feature is a card like the Events ones: a hairline border and 8 px corners round the tile and its text, and
   the card lifts on hover, so it reads as something to point at (the tile's clip plays then) */
.feature-stage li { min-width: 0; overflow: hidden; border: 1px solid #00263e16; border-radius: 8px; background: #fff; transition: translate .4s cubic-bezier(.22,1,.36,1), box-shadow .4s ease; }
.feature-stage li:hover { translate: 0 -4px; box-shadow: 0 18px 36px -18px #00263e40; }
.feature-stage li > div:last-child { display: flex; flex-direction: column; padding: 18px 22px 22px; }
/* each stage's cards fade in one after another, left to right, as the stage comes into view (future.js), as Events' do */
.feature-stage.will-reveal li { opacity: 0; transform: translateY(16px); }
.feature-stage.is-revealed li { opacity: 1; transform: none; transition: opacity .6s ease, transform .6s cubic-bezier(.22,1,.36,1), translate .4s cubic-bezier(.22,1,.36,1), box-shadow .4s ease; transition-delay: var(--delay), var(--delay), 0s, 0s; }
.feature-thumb { grid-column: 1 / -1; aspect-ratio: 16 / 9; border-bottom: 1px solid #00263e10; background: repeating-linear-gradient(135deg, #f3f7f8 0 14px, #eaf1f3 14px 28px); display: grid; place-items: center; }
.feature-thumb:has(img) { background: var(--thumb-bg, #f3f7f8); overflow: hidden; }
/* the render tiles, zoomed past the edges so their detail reads at card size */
/* set down and to the right, so the tile runs off the card's bottom-right corner over its badge colour (future.html sets --thumb-bg) */
/* the microsite renders (render/microsite) share one framing; this zoom and offset keeps the crop the tiles had before */
.feature-thumb :is(img, video) { grid-area: 1 / 1; width: 100%; height: 100%; object-fit: contain; transform: translate(16%, 9.9%) scale(1.732); }
/* hover motion (microsite/motion/, rendered from the tile's own scene by design-system/scripts/render-feature-motion.sh):
   the clip sits exactly over its still, frame 0 being the still, and shows once its first frame has loaded */
.feature-thumb video { opacity: 0; pointer-events: none; }
.feature-thumb video.is-ready { opacity: 1; }
.feature-thumb img.is-screen { object-fit: cover; object-position: left center; transform: none; }
.feature-thumb span { font: 500 11px/1 "Noto Sans Mono", ui-monospace, monospace; letter-spacing: .04em; text-transform: uppercase; color: #8aa1ab; }
/* the badges are hidden for now (Bryan, 2026-10-06); the page still draws them, for the thumbnails' --thumb-bg */
.feature-icon { display: none; width: 28px; height: 28px; margin-top: 0; }
/* the recap slide sizes its marks inline for 1920 px slides; shrink them for the page */
.feature-icon > span { width: 28px !important; height: 28px !important; }
.feature-icon svg { width: 16px; height: 16px; }
.feature-icon:empty { border-radius: 4px; background: #eef4f6; }
.feature-stage p { margin: 0; font-size: 14px; line-height: 1.5; color: #2b4a5a; }
.feature-stage .feature-name { margin-bottom: 4px; font-size: 17px; font-weight: 550; line-height: 1.3; letter-spacing: -.01em; color: #00263e; }
.feature-tag { display: inline-block; margin-left: 4px; padding: 2px 7px; border-radius: 999px; background: #00263e; color: #fff; font-size: 11px; font-weight: 500; letter-spacing: .02em; vertical-align: 2px; }
.feature-tag.is-updated { background: transparent; color: #456574; box-shadow: inset 0 0 0 1px #00263e33; }
/* the timeline sits at the card's foot, so it lines up across a row however long the copy runs */
.feature-stage .feature-when { margin-top: auto; padding-top: 14px; font-size: 13px; font-weight: 500; color: #456574; }
@media not all and (min-width: 64rem) {
  .feature-stage { grid-template-columns: 1fr; gap: 18px; }
  .feature-stage ul { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media not all and (min-width: 40rem) { .feature-stage ul { grid-template-columns: 1fr; gap: 32px; } .keynote-features { padding-bottom: 80px; } }

/* Slabs, one at a time: only the slab under the pointer takes its colour and shows its name. The label is the
   keynote's block label (src/scene/Labels.tsx): white pill, grey border, 12.5 px medium, the object's icon on a
   tile in its layer's Harmony category colour. The button's box is mostly transparent picture, so it ignores the
   pointer and a diamond over the slab itself (30–73 % down, 7–93 % across the render) takes the hover. */
.asset-slab { pointer-events: none; }
.slab-hit { position: absolute; inset: 0; z-index: 1; pointer-events: auto; cursor: pointer; clip-path: polygon(7% 50%, 50% 29%, 93% 50%, 50% 74%); }
.slab-apps .slab-hit { transform: rotate(14deg); transform-origin: 50% 52%; }
.slab-edge .slab-hit { transform: rotate(-14deg); transform-origin: 50% 52%; }
.slab-label {
  position: absolute; left: 50%; top: 24%;
  display: flex; align-items: center; gap: 6px; padding: 3px 10px 3px 3px;
  white-space: nowrap; border: 1px solid #c1c1c1; border-radius: 4px; background: #fff; color: #181818;
  font-size: 12.5px; font-weight: 500; line-height: 1;
  opacity: 0; transform: translate(-50%, calc(-100% + 6px)) scale(.94); transform-origin: 50% 100%;
  transition: opacity .2s ease, transform .25s cubic-bezier(.2,.7,.2,1); pointer-events: none;
}
.asset-slab:is(:hover, :focus-visible, .is-connected, .is-lit) .slab-label { opacity: 1; transform: translate(-50%, -100%); }
/* Harmony's smallest icon size (16 px, sm) rather than the keynote label's 11 px, on a tile with 4 px around it */
.slab-label-tile { display: grid; place-items: center; width: 24px; height: 24px; border-radius: 3px; }
.slab-label-tile svg { width: 16px; height: 16px; }
.slab-apps .slab-label-tile { background: #c2e2ff; color: #003b61; }
.slab-edge .slab-label-tile { background: #fed2cf; color: #6b0a17; }
.slab-connectors .slab-label-tile { background: #f7d7bb; color: #532e00; }
.slab-tables .slab-label-tile { background: #c8e6dc; color: #174035; }

/* the keynote's Celery highlight (system-of-what, human-potential): a square mark behind the words that matter,
   sweeping in from the left as they scroll into view (future.js adds .is-lit) */
mark.hl { color: #00263e; padding: 0 .14em; margin: 0 -.04em; border-radius: 0; -webkit-box-decoration-break: clone; box-decoration-break: clone;
  background: linear-gradient(#F2EEA1, #F2EEA1) no-repeat 0 50% / 0% 100%; transition: background-size .6s cubic-bezier(.22,1,.36,1); }
mark.hl.is-lit { background-size: 100% 100%; }
@media (prefers-reduced-motion: reduce) { mark.hl { transition: none; } }

/* Icons follow Harmony beta.10 iconography (design-system repo, docs/iconography.md): Lucide marks on their own
   24-unit grid, untouched, at a size from the scale, all at the default weight (--t-icon-stroke-default: 1.75px,
   which Harmony's <Icon> sets as the SVG's stroke-width, so it scales with the icon). One weight per region. */
:is(.feature-icon, .slab-label-tile) svg { stroke-width: 1.75px; }

/* Events: the keynote's community slide (design-system/community.html), in this page's own style rather than the
   slide's: hairline cards with 8 px corners like the release stages and feature thumbnails, the small uppercase
   label for the event code, and the section headings' Inter at 450 for the city. Each map keeps its city colour
   (community-maps/manifest.json: Boston blue, Tokyo purple, Lyon green), echoed in the code's dot. */
.keynote-events { min-height: 0; padding-top: 48px; padding-bottom: 72px; }
.events-intro { margin: 10px 0 28px; font-size: 17px; color: #456574; }
.event-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.event-card { min-width: 0; overflow: hidden; border: 1px solid #00263e16; border-radius: 8px; background: #fff; }
/* The maps carry the slide's own frame (a 1.4-unit #C1C1C1 outline, 8-unit corners, inset 0.7 on a 640 × 500
   canvas). In a card that frame doubles the border and leaves white wedges in the corners, so the page crops the
   outer 9 units off every side and lets the card's border and corners frame the map. The SVGs stay as they are
   for the slide. */
.event-map { overflow: hidden; aspect-ratio: 622 / 482; border-bottom: 1px solid #00263e10; }
.event-map img { display: block; width: calc(100% * 640 / 622); max-width: none; height: auto; margin: calc(-100% * 9 / 622) 0 0 calc(-100% * 9 / 622); }
.event-body { padding: 20px 22px 24px; }
.event-body p { margin: 0; }
.event-code { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: #456574; }
.event-code::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--city); }
.event-us { --city: #0e71c9; } .event-jp { --city: #6b3bc4; } .event-eu { --city: #174035; }
.event-card h3 { margin: 12px 0 14px; font-size: clamp(28px, 2.6vw, 36px); font-weight: 450; line-height: 1.05; letter-spacing: -.04em; }
.event-date { font-size: 16px; font-weight: 550; letter-spacing: -.01em; color: #00263e; }
.event-place { margin-top: 2px !important; font-size: 14px; color: #456574; }
/* the cards fade in one after another, left to right, as the section comes into view (future.js sets .will-reveal) */
.event-grid.will-reveal .event-card { opacity: 0; transform: translateY(16px); }
.event-grid.is-revealed .event-card { opacity: 1; transform: none; transition: opacity .6s ease, transform .6s cubic-bezier(.22,1,.36,1), translate .4s cubic-bezier(.22,1,.36,1), box-shadow .4s ease; transition-delay: var(--delay), var(--delay), 0s, 0s; }
/* Hover (or tap): the map zooms in on the city, about its pin, a ring ripples out from the pin, and the card lifts.
   The pin's place, as a share of the cropped map box: the SVG's pin centre less the 9-unit crop, over 622 × 482;
   as a share of the image (the zoom's origin): over 640 × 500. */
.event-us { --pin-x: 92.35%; --pin-y: 31.48%; --pin-ox: 91.16%; --pin-oy: 32.15%; }
.event-jp { --pin-x: 63.9%; --pin-y: 49.6%; --pin-ox: 63.51%; --pin-oy: 49.62%; }
.event-eu { --pin-x: 62.41%; --pin-y: 56.57%; --pin-ox: 62.07%; --pin-oy: 56.33%; }
.event-map { position: relative; }
.event-map img { transform-origin: var(--pin-ox) var(--pin-oy); transition: transform 1.1s cubic-bezier(.22,1,.36,1); }
.event-map::after { content: ''; position: absolute; left: var(--pin-x); top: var(--pin-y); width: 5.8%; aspect-ratio: 1; border: 2px solid var(--city); border-radius: 50%; opacity: 0; transform: translate(-50%, -50%); pointer-events: none; }
.event-card { transition: translate .4s cubic-bezier(.22,1,.36,1), box-shadow .4s ease; }
/* .is-zoomed: the map's part of it (the zoom and the ripple, not the card's lift), played by itself on touch screens
   while the card is in view, as the launch cards play only their tiles (future.js) */
.event-card:hover { translate: 0 -4px; box-shadow: 0 18px 36px -18px #00263e40; }
.event-card:is(:hover, .is-zoomed) .event-map img { transform: scale(1.7); }
.event-card:is(:hover, .is-zoomed) .event-map::after { animation: pin-ripple 1.6s cubic-bezier(.2,.6,.3,1) .35s infinite; }
@keyframes pin-ripple { from { opacity: .7; transform: translate(-50%, -50%) scale(1.7); } to { opacity: 0; transform: translate(-50%, -50%) scale(4.5); } }
@media not all and (min-width: 64rem) {
  .event-grid { grid-template-columns: 1fr; gap: 20px; max-width: 520px; }
  .keynote-events { padding-bottom: 40px; } /* the footer's own 80 px top (room for the page line to turn in) does the rest */
}

/* Footer: Endless courage. The outro's wireframe wave on a light grey ground (the design system's page grey), with
   Natan's sticker slapped on top. */
/* the grey fades in from the page's white over the footer's first 140 px, so there's no hard edge where it starts */
.site-footer { position: relative; overflow: hidden; isolation: isolate; background: linear-gradient(#fff, #eef2f5 140px); color: #00263e; padding: 140px 0 0; margin-top: 0; }
.footer-wave { position: absolute; z-index: -1; left: 0; right: 0; bottom: 0; width: 100%; height: 62%; pointer-events: none;
  /* fades in from the top, and out again behind the footer bar at the bottom */
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 45%, #000 55%, transparent 92%);
  mask-image: linear-gradient(to bottom, transparent, #000 45%, #000 55%, transparent 92%); }
/* one centred block: the quote, the lettering, the line under it; equal room above and below */
.footer-inner { width: min(1120px, calc(100% - 64px)); margin: 0 auto; display: grid; grid-template-columns: minmax(0, 1fr); gap: 48px; }

/* the sticker as the outro shows it: just the hand-drawn lettering, no card, outline or shadow, a little crooked; it
   slaps down when the footer comes in (future.js adds .is-stuck) and tips on hover */
.footer-sticker-wrap { position: relative; display: grid; justify-items: center; }
/* the doodles a press throws out (future.js) */
.sticker-doodle { position: absolute; z-index: 1; display: block; color: #008cb9; pointer-events: none; }
.sticker-doodle svg { display: block; width: 100%; height: 100%; }
.footer-copy { margin-top: -4px; text-align: center; }
.footer-sticker { --tilt: -4deg; display: block; width: min(100%, 560px); padding: 0; border: 0; background: none; cursor: pointer; color: inherit;
  transform: rotate(var(--tilt)); transition: transform .35s cubic-bezier(.2,.8,.2,1); }
.footer-sticker img { display: block; width: 100%; height: auto; }
.footer-sticker:hover, .footer-sticker:focus-visible { transform: rotate(calc(var(--tilt) + 2deg)) scale(1.03); }
.footer-sticker:focus-visible { outline: 2px solid #00263e; outline-offset: 10px; border-radius: 4px; }
.site-footer.will-stick .footer-sticker { opacity: 0; transform: rotate(-16deg) scale(1.45); }
.site-footer.will-stick.is-stuck .footer-sticker { opacity: 1; transform: rotate(var(--tilt)); animation: sticker-slap .55s cubic-bezier(.2,.9,.25,1.15) both; }
@keyframes sticker-slap { 0% { opacity: 0; transform: rotate(-16deg) scale(1.45); } 60% { opacity: 1; transform: rotate(-2deg) scale(.96); } 100% { opacity: 1; transform: rotate(var(--tilt)) scale(1); } }

.footer-head { grid-column: 1 / -1; text-align: center; }
.footer-quote { margin: 0; font-size: clamp(26px, 3.7vw, 44px); line-height: 1.12; font-weight: 450; letter-spacing: -.035em; color: #00263e; }
.footer-cite { margin: 16px 0 0; font-size: 14px; color: #456574; }
.footer-cite strong { font-weight: 600; color: #00263e; }
.footer-line { margin: 0; font-size: 17px; line-height: 1.5; color: #2b4a5a; }

.footer-bar { width: min(1120px, calc(100% - 64px)); margin: 140px auto 0; padding: 22px 0 28px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px 32px; }
.footer-brands { display: flex; align-items: center; gap: 16px; }
.footer-brands img { display: block; width: auto; }
.footer-divider { width: 1px; height: 18px; background: #00263e40; }
.footer-nav { display: flex; flex-wrap: wrap; gap: 6px 20px; }
.footer-nav a { color: #2b4a5a; text-decoration: none; font-size: 13px; }
.footer-nav a:hover { color: #00263e; text-decoration: underline; text-underline-offset: 3px; }
.footer-legal { margin: 0; font-size: 12px; color: #456574; }
@media not all and (min-width: 64rem) {
  .site-footer { padding-top: 80px; }
  .footer-inner { grid-template-columns: 1fr; width: calc(100% - 44px); gap: 44px; }
  .footer-quote { white-space: normal; }
  .footer-sticker { width: min(90%, 420px); }
  .footer-bar { width: calc(100% - 44px); margin-top: 96px; flex-direction: column; align-items: flex-start; }
}
@media (prefers-reduced-motion: reduce) { .footer-sticker { transition: none; } .site-footer.will-stick.is-stuck .footer-sticker { animation: none; } }

.footer-nav a:focus-visible { outline: 2px solid #00263e; outline-offset: 3px; }

/* the keynote placeholder under the release (Andrew, 2026-10-06): the vision film's frame on a quiet grid, no player yet */
.keynote-video-next { padding-top: 8px; }
.keynote-embed { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.keynote-video-next .video-placeholder { aspect-ratio: 16 / 9; } /* the embedded player is 16:9 on phones too */
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.video-placeholder.is-placeholder { background: #00263E repeating-linear-gradient(90deg, transparent 0 59px, #ffffff0d 59px 60px), #00263E repeating-linear-gradient(0deg, transparent 0 59px, #ffffff0d 59px 60px); background-color: #00263E; }
.video-placeholder.is-placeholder .video-overlay { background: linear-gradient(0deg, #000000a0, #00000000 55%); }
.video-placeholder.is-placeholder .video-play { cursor: default; opacity: .7; }
.video-placeholder.is-placeholder .video-play:hover { transform: none; }
