/* ───────────────────────────────────────────────────────────────────────────
   Campus landing — prototype
   Colors pulled 1:1 from the Campus dark theme (ffdesigner_ds holoColorsDark).
   ─────────────────────────────────────────────────────────────────────────── */
:root {
  --bg: #181818;
  --bg-alt: #1c1f24;
  --fg: #f0f0f0;
  --fg-muted: #abb2bf;
  --fg-weak: #767d89;
  --stroke: #373a44;

  /* peer accent palette (dark) */
  --purple: #7272ea;
  --teal: #22808d;
  --orange: #d19a66;
  --green: #81b88b;
  --pink: #d18bba;
  --red: #e06c75;

  /* dot grid — matches CampusCanvasBackgroundPainter: 48px spacing, ~1.1px,
     muted foreground @ 22% alpha */
  --dot: rgba(171, 178, 191, 0.22);
  --dot-spacing: 48px;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: auto; /* the choreography owns the feel */
  /* clip (not hidden): hides the off-screen parked hero lines WITHOUT making
     <html> a scroll container — `hidden` would break `position: sticky`, which
     the cross-device hand-off section relies on. */
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: ui-sans-serif, -apple-system, "SF Pro Display", "Inter",
    system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

/* ── Full-page dotted canvas surface ───────────────────────────────────────
   Tiled radial-gradient (effectively free to paint). The layer is oversized by
   one dot-period top & bottom and drifts via a compositor-only `transform`
   driven by scroll, so the canvas appears to pan behind the content. Because
   the dot pattern is periodic, the drift is wrapped within one period — it
   never runs out and never relayouts. */
.canvas-dots {
  position: fixed;
  left: 0;
  right: 0;
  top: -48px;
  height: calc(100vh + 96px);
  z-index: 0;
  pointer-events: none;
  background-color: var(--bg);
  background-image: radial-gradient(var(--dot) 1.1px, transparent 1.2px);
  background-size: var(--dot-spacing) var(--dot-spacing);
  will-change: transform;
}

/* faint vignette so text reads against the dots — fixed, does not drift */
.canvas-veil {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    120% 80% at 50% 30%,
    transparent 40%,
    rgba(24, 24, 24, 0.55) 100%
  );
}

/* ── Chrome ───────────────────────────────────────────────────────────────
   Floating, centered glass pill. Draggable (see tiles.js): the drag offset is
   composed onto the centering translate as translate(calc(-50% + dx), dy). */
.topbar {
  position: fixed;
  top: 22px;
  left: 50%;
  /* centering + a hand-drag offset (--bx/--by, tiles.js) + an intro slide
     (--iy, app.js chrome intro), all composed so none of them clobber another.
     --io fades it in as the cursor drags it down into place on load. */
  transform: translate(calc(-50% + var(--bx, 0px)), calc(var(--by, 0px) + var(--iy, 0px)));
  opacity: var(--io, 1);
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 11px 13px 11px 24px;
  border-radius: 999px;
  /* ── Liquid Glass ────────────────────────────────────────────────────────
     The BASE backdrop here (low blur + saturate/brightness) is the universal
     fallback Safari & Firefox show. On Chromium, liquid-glass.js overrides this
     with the vendored package's real refraction + chromatic aberration. Kept
     deliberately soft — a faint top highlight only, no bright inset rims (those
     read as an unwanted inner "border"). */
  border: 1px solid rgba(255, 255, 255, 0.09);
  background: linear-gradient(
      135deg,
      rgba(255, 255, 255, 0.09),
      rgba(255, 255, 255, 0.02) 42%,
      rgba(255, 255, 255, 0) 72%
    ),
    rgba(255, 255, 255, 0.035);
  backdrop-filter: blur(8px) saturate(180%) brightness(1.08);
  -webkit-backdrop-filter: blur(8px) saturate(180%) brightness(1.08);
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.46),
    inset 0 1px 0 rgba(255, 255, 255, 0.14); /* one faint top highlight, no rim lines */
  overflow: hidden; /* clip the refraction cleanly to the pill */
  cursor: grab;
  user-select: none;
}
/* The real refraction (SVG displacement + chromatic aberration) is applied to
   .topbar's own backdrop-filter at runtime by the vendored rizroze/liquid-glass
   package (liquid-glass.js) — it overrides the base blur above on Chromium and
   leaves it as the fallback on Safari/Firefox. */
/* keep the wordmark + nav above the glass layer */
.topbar .wordmark,
.topbar .topnav-sep,
.topbar .topnav {
  position: relative;
  z-index: 1;
}
.topbar.grabbing {
  cursor: grabbing;
  border-color: color-mix(in srgb, var(--purple) 55%, rgba(255, 255, 255, 0.1));
}

/* Logo lockup: the real Campus logomark + wordmark. */
.wordmark {
  display: flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: var(--fg);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.5px;
}
.wordmark-logo {
  width: 23px;
  height: 23px;
  object-fit: contain;
  display: block;
  /* lift the logomark off the glass a touch */
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
}
.wordmark-text {
  line-height: 1;
}

.topnav-sep {
  width: 1px;
  height: 18px;
  background: var(--stroke);
}
.topnav {
  display: flex;
  align-items: center;
  gap: 2px;
}
/* thin "|" divider between nav categories */
.navsep {
  width: 1px;
  height: 13px;
  margin: 0 4px;
  background: var(--stroke);
  opacity: 0.7;
}
.topnav a {
  color: var(--fg-muted);
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  padding: 7px 11px;
  border-radius: 999px;
  transition: color 0.2s, background 0.2s;
}
.topnav a.dl {
  margin-left: 6px; /* breathing room before the CTA */
}
.topnav a:hover {
  color: var(--fg);
  background: rgba(255, 255, 255, 0.06);
}
.topnav a.dl {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #fff;
  background: var(--purple);
}
.topnav a.dl:hover {
  background: color-mix(in srgb, var(--purple) 86%, #fff);
}
.dl-apple {
  width: 13px;
  height: 13px;
  margin-top: -2px; /* optically center the glyph on the text */
  fill: currentColor;
}

/* ── Layout ─────────────────────────────────────────────────────────────── */
main {
  position: relative;
  z-index: 10;
}

section {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 32px;
}

.hero {
  position: relative;
  max-width: none; /* full viewport, so the hero tiles can frame from the edges */
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.hero-inner {
  position: relative;
  z-index: 6; /* keep the headline above the hero tiles if they ever overlap */
  max-width: 700px;
  margin: 0 auto;
  /* the headline + sub + CTA sit dead-centre in the hero section (the .hero flex
     centres this column; the tiles are absolutely placed, so this never moves
     them). A hair above true centre reads as optically centred. */
  transform: translateY(-2vh);
  text-align: center; /* ONLY the headline column is centered — never the tiles */
}

/* Hero tile cluster — real Campus tiles dragged in to frame the headline.
   A centered, capped-size box (not full-bleed) so on big screens the tiles
   stay grouped AROUND the title and large, instead of flying to far corners.
   Click-through except on the tiles themselves. */
.hero-stage {
  position: absolute;
  top: 84px; /* clear the floating topbar */
  bottom: 92px; /* leave the bottom strip for the marquee */
  left: 50%;
  transform: translateX(-50%);
  width: min(100% - 56px, 1840px); /* capped + centered so tiles stay grouped */
  z-index: 5;
  pointer-events: none;
  text-align: left; /* tiles are never centered, whatever the hero does */
}
.hero-stage .stage {
  pointer-events: auto;
}

/* Trusted-by marquee pinned to the bottom of the hero — social proof above
   the fold. A centered, contained band (not full-bleed) so it reads as
   centered; the bottom-corner terminals flank it. */
.hero-marquee {
  position: absolute;
  left: 50%;
  bottom: 52px;
  /* centering + an intro slide (--iy) so a cursor can drag the whole band up
     into place on load; --io fades it in. Parked off the bottom edge at start. */
  transform: translateX(-50%) translateY(var(--iy, 0px));
  opacity: var(--io, 1);
  /* kept narrow so the bottom-corner terminal flanks it (the marquee scrolls, so
     a tighter band still reads); a wider band would slide under the terminal. */
  width: min(100% - 56px, 680px);
  z-index: 6;
  text-align: center;
}
.hero-marquee .trusted-label {
  margin: 0 0 14px;
}

.eyebrow {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 20px;
}

.hero-title {
  font-size: clamp(36px, 4.6vw, 64px);
  line-height: 1.05;
  font-weight: 700;
  letter-spacing: -1.5px;
  margin: 0;
}
.hero-title .line {
  display: block;
}

/* Hand-drawn arrows pointing at the hero CTA. A SEPARATE element laid on the
   page background (a child of .hero), positioned in pixel space around the
   .circled button so the arrowheads never skew. A periwinkle pen-cursor sketches
   each arrow, synced to a pathLength="1" dash sweep (all driven in app.js).
   non-scaling-stroke keeps the marker an even weight at any size; an
   feTurbulence displacement warps it into an organic, hand-drawn wobble. */
.hero-anno {
  position: absolute;
  z-index: 4; /* on the bg, behind the headline (hero-inner is z6) */
  pointer-events: none;
  overflow: visible;
  opacity: 0; /* stay invisible until the pen starts inking (no dash-seam sliver) */
}
.hero-anno path {
  stroke: #9296f2; /* periwinkle ink — keep in sync with ANNO_COLOR in app.js */
  stroke-width: 4.5;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
  filter: url(#annoRough);
  stroke-dasharray: 1;
  stroke-dashoffset: 1; /* JS drives this 1→0 as the pen traces each arrow */
}
.anno-cursor {
  z-index: 16; /* the pen rides just above the ink */
}
@media (prefers-reduced-motion: reduce) {
  .hero-anno path {
    stroke-dashoffset: 0; /* show it already drawn, no pen */
  }
}

.hero-sub {
  margin: 32px auto 0;
  max-width: 560px;
  font-size: 18px;
  line-height: 1.6;
  color: var(--fg-muted);
  /* a cursor drags this in on load (app.js chrome intro); parked + hidden at
     start via these vars so the hero begins truly empty. */
  transform: translateY(var(--iy, 0px));
  opacity: var(--io, 1);
}

/* Hero primary CTA — the pen's arrows point at this (it carries the .circled
   anchor). The intro slide rides the WRAPPER (no transition) so it never fights
   the button's own hover transform-transition. */
.hero-cta {
  margin-top: 38px;
  transform: translateY(var(--iy, 0px));
  opacity: var(--io, 1);
}
.hero-cta .cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 15px 30px;
  font-size: 17px;
}
.cta-apple {
  width: 17px;
  height: 17px;
  margin-top: -2px; /* optically center the glyph on the text */
  fill: currentColor;
}

.scroll-hint {
  margin-top: 48px;
  font-size: 13px;
  letter-spacing: 2px;
  color: var(--fg-weak);
  text-transform: uppercase;
}

/* ── Trusted-by marquee ─────────────────────────────────────────────────────
   Two identical groups scroll left; each group carries a trailing gap so the
   track is exactly two periods wide and translateX(-50%) loops seamlessly. */
.trusted {
  text-align: center;
  padding: 18px 32px 34px;
}
.trusted-label {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 26px;
}
.marquee {
  position: relative;
  overflow: hidden;
  /* fade the two edges so wordmarks slide in/out instead of hard-clipping */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.marquee-track {
  display: flex;
  width: max-content;
  animation: marquee 30s linear infinite;
}
.marquee:hover .marquee-track {
  animation-play-state: paused;
}
.marquee-group {
  display: flex;
  align-items: center;
  gap: 64px;
  padding-right: 64px; /* one gap of trailing space — makes the loop seamless */
}
.logo {
  font: 600 27px/1 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: -0.4px;
  white-space: nowrap;
  color: var(--fg-weak);
  opacity: 0.72;
  transition: color 0.2s ease, opacity 0.2s ease;
}
.logo:hover {
  color: var(--fg);
  opacity: 1;
}
@keyframes marquee {
  to {
    transform: translateX(-50%);
  }
}

.band {
  min-height: 92vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 28px;
}
.band-title {
  font-size: clamp(34px, 5.5vw, 64px);
  line-height: 1.05;
  letter-spacing: -1.5px;
  font-weight: 700;
  margin: 0;
}
.band-title .line {
  display: inline-block;
}
.band-body {
  max-width: 620px;
  font-size: clamp(18px, 2.2vw, 24px);
  line-height: 1.55;
  color: var(--fg-muted);
  margin: 0;
}

.closer {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 32px;
  padding: 12vh 32px 13vh;
}
.closer-title {
  font-size: clamp(40px, 7vw, 88px);
  letter-spacing: -2px;
  font-weight: 700;
  margin: 0;
}
.cta {
  display: inline-block;
  padding: 14px 26px;
  border-radius: 10px;
  background: var(--purple);
  color: #fff;
  font-weight: 600;
  font-size: 16px;
  text-decoration: none;
  box-shadow: 0 8px 30px rgba(114, 114, 234, 0.35);
  transition: transform 0.15s ease, box-shadow 0.2s ease;
}
.cta:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 40px rgba(114, 114, 234, 0.5);
}

/* ── Product screenshot ─────────────────────────────────────────────────────
   A real Campus workspace as the product proof point immediately after hero. */
.product-shot {
  max-width: none;
  padding: 9vh 0 11vh;
  overflow: hidden;
}
.product-shot-head {
  width: min(100% - 48px, 760px);
  margin: 0 auto 38px;
  text-align: center;
}
.product-shot-eyebrow {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 14px;
}
.product-shot h2 {
  margin: 0 0 16px;
  font-size: clamp(34px, 4.4vw, 58px);
  line-height: 1.04;
  font-weight: 720;
}
.product-shot-sub {
  margin: 0 auto;
  max-width: 560px;
  color: var(--fg-muted);
  font-size: 17px;
  line-height: 1.6;
}
/* Clean: no coloured glow, no dark cloud. We crop the screenshot's own black
   margins (top 38 / sides 56 / bottom 74 px of 1802×1022) with clip-path so
   only the rounded app window remains, and sit it straight on the page's
   dotted canvas with a soft neutral shadow. drop-shadow (not box-shadow)
   tracks the clipped shape. */
.product-shot-frame {
  position: relative;
  width: min(100% - 24px, 1680px);
  margin: 0 auto;
}
.product-shot-frame img {
  display: block;
  width: 100%;
  height: auto;
  clip-path: inset(3.72% 3.11% 7.24% 3.11% round 12px);
  filter: drop-shadow(0 26px 50px rgba(0, 0, 0, 0.5));
}
@media (max-width: 760px) {
  .product-shot {
    padding: 7vh 0 6vh;
  }
  .product-shot-head {
    width: min(100% - 32px, 760px);
    margin-bottom: 26px;
  }
  .product-shot-frame {
    width: min(100% - 16px, 1680px);
  }
  .product-shot-frame img {
    filter: drop-shadow(0 16px 34px rgba(0, 0, 0, 0.5));
  }
}

/* ── What is Campus — split header + three illustrated pillars ──────────────
   Header splits headline (left) / lead (right). Each pillar is topped by a
   small on-brand illustration card built from the real tile vocabulary (mini
   tiles + cursors), sized in container-query units so it scales crisply. */
.core {
  padding-top: 13vh;
  padding-bottom: 5vh;
}
.core-head {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 24px 48px;
  align-items: end;
  margin: 0 0 56px;
}
.core-eyebrow {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 16px;
}
.core-head h2 {
  margin: 0;
  font-size: clamp(30px, 4vw, 50px);
  line-height: 1.06;
  letter-spacing: -1.4px;
  font-weight: 700;
}
.core-lead {
  margin: 0;
  color: var(--fg-muted);
  font-size: 17px;
  line-height: 1.6;
}

.core-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 30px;
}
.pillar {
  --accent: var(--purple);
}
.pillar[data-accent="teal"] { --accent: var(--teal); }
.pillar[data-accent="orange"] { --accent: var(--orange); }
.pillar h3 {
  margin: 22px 0 10px;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.3px;
  color: var(--fg);
}
.pillar p {
  margin: 0;
  font-size: 15px;
  line-height: 1.62;
  color: var(--fg-muted);
}

/* illustration card: a mini dotted canvas with mini tiles/cursors on it */
.pillar-art {
  container-type: inline-size;
  --ca: 0.3125cqw; /* 1 design px at a 320-wide reference card */
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: 14px;
  border: 1px solid var(--stroke);
  background-color: #131315;
  background-image: radial-gradient(rgba(171, 178, 191, 0.13) calc(1 * var(--ca)), transparent calc(1.25 * var(--ca)));
  background-size: calc(26 * var(--ca)) calc(26 * var(--ca));
}
.pillar-art::after {
  /* faint accent bloom keyed to the pillar */
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(60% 60% at 50% 62%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 72%);
}

/* mini tile chrome */
.mtile {
  --accent: var(--purple);
  position: absolute;
  z-index: 1;
  display: flex;
  flex-direction: column;
  border-radius: calc(8 * var(--ca));
  border: 1px solid var(--stroke);
  background: rgba(20, 20, 24, 0.92);
  box-shadow: 0 calc(8 * var(--ca)) calc(20 * var(--ca)) rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
.mtile[data-accent="teal"] { --accent: var(--teal); }
.mtile[data-accent="orange"] { --accent: var(--orange); }
.mbar {
  display: flex;
  align-items: center;
  gap: calc(5 * var(--ca));
  height: calc(18 * var(--ca));
  padding: 0 calc(7 * var(--ca));
  background: rgba(0, 0, 0, 0.36);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.mbar .sq {
  flex: none;
  width: calc(5.5 * var(--ca));
  height: calc(5.5 * var(--ca));
  border-radius: calc(1.5 * var(--ca));
  background: var(--accent);
}
.mbar span {
  font: 600 calc(8.5 * var(--ca)) / 1 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg-muted);
  white-space: nowrap;
}
.mbody {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: calc(5 * var(--ca));
  padding: calc(9 * var(--ca));
}
.mbody .ln {
  height: calc(5 * var(--ca));
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.15);
}
.mbody .ln.s { width: 58%; }
.mweb .mhero {
  height: calc(30 * var(--ca));
  border-radius: calc(6 * var(--ca));
  background: linear-gradient(135deg, rgba(114, 114, 234, 0.85), rgba(34, 128, 141, 0.7));
  margin-bottom: calc(2 * var(--ca));
}
.mterm { gap: calc(6 * var(--ca)); }
.mterm .cl {
  height: calc(5 * var(--ca));
  border-radius: 999px;
  width: 84%;
}
.mterm .cl.p { width: 72%; background: color-mix(in srgb, var(--purple) 55%, #fff); }
.mterm .cl.g { width: 50%; background: rgba(129, 184, 139, 0.65); }
.mterm .cl.d { width: 88%; background: rgba(255, 255, 255, 0.16); }
.mterm .cl.s { width: 36%; }

/* mini named cursors */
.mcursor {
  position: absolute;
  z-index: 3;
}
.mcursor svg {
  display: block;
  width: calc(14 * var(--ca));
  height: calc(14 * var(--ca));
  filter: drop-shadow(0 calc(1 * var(--ca)) calc(1.5 * var(--ca)) rgba(0, 0, 0, 0.45));
}
.mcursor b {
  position: absolute;
  left: calc(10 * var(--ca));
  top: calc(11 * var(--ca));
  padding: calc(1.5 * var(--ca)) calc(5 * var(--ca));
  border-radius: calc(4 * var(--ca));
  font: 600 calc(8 * var(--ca)) / 1.2 "SF Pro Display", system-ui, sans-serif;
  color: #fff;
  white-space: nowrap;
}
.cu-a svg { fill: var(--teal); }
.cu-a b { background: var(--teal); }
.cu-b svg { fill: var(--purple); }
.cu-b b { background: var(--purple); }
.cu-cc svg { fill: var(--purple); }
.cu-cc b { background: var(--purple); }

/* art 1 — a small tile cluster */
.art-work .mt-web  { left: calc(14 * var(--ca)); top: calc(24 * var(--ca)); width: calc(150 * var(--ca)); height: calc(100 * var(--ca)); }
.art-work .mt-note { left: calc(184 * var(--ca)); top: calc(15 * var(--ca)); width: calc(116 * var(--ca)); height: calc(86 * var(--ca)); }
.art-work .mt-term { left: calc(86 * var(--ca)); top: calc(82 * var(--ca)); width: calc(172 * var(--ca)); height: calc(102 * var(--ca)); z-index: 2; }

/* art 2 — one shared tile + two teammate cursors */
.art-team .mt-shared { left: calc(84 * var(--ca)); top: calc(44 * var(--ca)); width: calc(152 * var(--ca)); height: calc(110 * var(--ca)); }
.art-team .cu-a { left: calc(56 * var(--ca)); top: calc(120 * var(--ca)); }
.art-team .cu-b { left: calc(206 * var(--ca)); top: calc(54 * var(--ca)); }

/* art 3 — a claude-code terminal + an agent cursor */
.art-agents .mt-cc { left: calc(40 * var(--ca)); top: calc(30 * var(--ca)); width: calc(226 * var(--ca)); height: calc(130 * var(--ca)); }
.art-agents .cu-cc { left: calc(196 * var(--ca)); top: calc(120 * var(--ca)); }

@media (max-width: 860px) {
  .core-head {
    grid-template-columns: 1fr;
    align-items: start;
    gap: 18px;
  }
}
@media (max-width: 620px) {
  .core-grid {
    grid-template-columns: 1fr;
    gap: 34px;
  }
  .pillar-art {
    max-width: 420px;
  }
}

/* ── What-is-Campus bento ──────────────────────────────────────────────────
   Hero-bento layout: the canvas cell anchors top-left (2×2) and the other five
   wrap around it. Calm: each cell is a line-icon + title + one line, quieter
   than the animated showcase right below. Accents reuse the peer palette. */
.bento {
  max-width: 1180px;
  padding-top: 13vh;
  padding-bottom: 5vh;
}
.bento-head {
  text-align: center;
  margin: 0 auto 46px;
}
.bento-eyebrow {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 14px;
}
.bento-head h2 {
  font-size: clamp(30px, 4vw, 50px);
  line-height: 1.06;
  letter-spacing: -1.4px;
  font-weight: 700;
  margin: 0;
}

.bento-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(158px, auto);
  gap: 16px;
  grid-template-areas:
    "canvas canvas terms"
    "canvas canvas agents"
    "any    native native";
}
.cell-canvas { grid-area: canvas; }
.cell-terms  { grid-area: terms; }
.cell-agents { grid-area: agents; }
.cell-any    { grid-area: any; }
.cell-native { grid-area: native; }

.bento-cell {
  /* near-monochrome: icons stay neutral; purple is reserved for the one
     canvas anchor cell, so the grid reads restrained, not rainbow. */
  --accent: var(--fg-muted);
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 18px;
  padding: 24px 26px;
  border: 1px solid var(--stroke);
  border-radius: 16px;
  background: color-mix(in srgb, var(--bg-alt) 55%, transparent);
  overflow: hidden;
  transition: border-color 0.2s ease, transform 0.2s ease, background 0.2s ease;
}
.bento-cell:hover {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--fg) 26%, var(--stroke));
  background: color-mix(in srgb, var(--bg-alt) 80%, transparent);
}

.bento-ico {
  flex: none;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.bento-ico svg {
  width: 20px;
  height: 20px;
}
.bento-cell h3 {
  margin: 0 0 8px;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.3px;
  color: var(--fg);
}
.bento-cell p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--fg-muted);
}
.bento-cell code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.92em;
  color: var(--fg);
}

/* the anchor cell — the one brand-color moment: purple icon + a faint dotted
   purple wash so it reads as a slice of the real surface. Still calm. */
.cell-canvas {
  --accent: var(--purple);
  padding: 32px 34px;
  background: radial-gradient(var(--dot) 1.1px, transparent 1.1px) 0 0 /
      var(--dot-spacing) var(--dot-spacing),
    color-mix(in srgb, var(--purple) 9%, var(--bg-alt) 55%);
  border-color: color-mix(in srgb, var(--purple) 28%, var(--stroke));
}
.cell-canvas .bento-ico {
  width: 46px;
  height: 46px;
}
.cell-canvas .bento-ico svg {
  width: 24px;
  height: 24px;
}
.cell-canvas h3 {
  font-size: clamp(24px, 2.4vw, 33px);
  letter-spacing: -0.8px;
}
.cell-canvas p {
  font-size: 16px;
  max-width: 32ch;
}

@media (max-width: 1080px) {
  .bento-grid {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "canvas canvas"
      "terms  agents"
      "any    native";
  }
}
@media (max-width: 680px) {
  .bento-grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "canvas"
      "terms"
      "agents"
      "any"
      "native";
  }
}

/* ── Anything canvas pan ───────────────────────────────────────────────────
   A wide world translated inside a clipped viewport to read as a camera pan,
   not a carousel of cards. */
.anything {
  max-width: none;
  padding: 94px 0 104px;
  overflow: hidden;
}
.anything-head {
  width: min(100% - 48px, 920px);
  margin: 0 auto 36px;
  text-align: center;
}
.anything-eyebrow {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 14px;
}
.anything h2 {
  margin: 0 0 16px;
  font-size: 48px;
  line-height: 1.05;
  font-weight: 720;
}
.anything-sub {
  margin: 0 auto;
  max-width: 640px;
  color: var(--fg-muted);
  font-size: 18px;
  line-height: 1.55;
}
.anything-viewport {
  position: relative;
  height: 620px;
  margin-top: 34px;
  overflow: hidden;
  border-top: 1px solid var(--stroke);
  border-bottom: 1px solid var(--stroke);
  background:
    radial-gradient(circle at 1px 1px, rgba(255,255,255,0.12) 1.1px, transparent 1.2px) 0 0 / 44px 44px,
    linear-gradient(180deg, rgba(255,255,255,0.035), rgba(255,255,255,0.01));
}
.anything-viewport::before,
.anything-viewport::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 8;
  width: 16vw;
  pointer-events: none;
}
.anything-viewport::before {
  left: 0;
  background: linear-gradient(90deg, var(--bg) 0%, transparent 100%);
}
.anything-viewport::after {
  right: 0;
  background: linear-gradient(270deg, var(--bg) 0%, transparent 100%);
}
.anything-world {
  position: absolute;
  left: 0;
  top: 38px;
  width: 2600px;
  height: 540px;
  transform: translate3d(0, 0, 0);
  animation: anything-pan 42s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes anything-pan {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(min(0px, calc(100vw - 2600px)), 0, 0); }
}
.anything-tile {
  position: absolute;
}
.anything-tile .tile {
  height: 100%;
}
.anything-tile .tile-bar {
  cursor: default;
}
.anything-tile .tile-acts {
  margin-left: 8px;
}
.anything-tile .tile-acts .act.x::before {
  content: "";
  display: block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--fg-weak) 60%, transparent);
}
.t-term { left: 28px; top: 34px; width: 560px; height: auto; }
.t-browser { left: 640px; top: 296px; width: 520px; height: 284px; }
.t-repo { left: 604px; top: 18px; width: 360px; height: 230px; }
.t-design { left: 1012px; top: 74px; width: 460px; height: 310px; }
.t-tasks { left: 1452px; top: 262px; width: 520px; height: auto; }
/* real-app-render tiles: the PNG carries its own chrome, radius and shadow */
.anything-tile.is-shot img {
  display: block;
  width: 100%;
  height: auto;
}
.t-video { left: 1590px; top: 36px; width: 390px; height: 230px; }
.t-map { left: 2040px; top: 64px; width: 420px; height: 270px; }
.t-app { left: 2198px; top: 358px; width: 380px; height: 210px; }
.t-voice { left: 1226px; top: 420px; width: 310px; height: 160px; }

.term-lite {
  font: 13px/1.75 "SF Mono", Menlo, monospace;
  color: var(--fg);
}
.term-lite p {
  margin: 0;
}
.term-lite span {
  color: var(--purple);
}
.term-lite .ok {
  color: var(--green);
}
.term-lite .dim {
  color: var(--fg-weak);
}
.mini-site {
  height: calc(100% - 34px);
  padding: 18px;
  background: linear-gradient(135deg, #171922, #101116);
}
.mini-hero {
  height: 86px;
  border-radius: 16px;
  background:
    radial-gradient(circle at 74% 34%, rgba(34,128,141,0.9) 0 22px, transparent 23px),
    linear-gradient(135deg, rgba(114,114,234,0.9), rgba(209,139,186,0.75));
}
.mini-copy {
  display: grid;
  gap: 10px;
  width: 68%;
  margin-top: 18px;
}
.mini-copy i,
.mini-grid i,
.app-copy i {
  display: block;
  height: 10px;
  border-radius: 999px;
  background: rgba(255,255,255,0.12);
}
.mini-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin-top: 20px;
}
.mini-grid i {
  height: 44px;
  border-radius: 12px;
}
.repo-lite {
  padding: 18px;
  background: #15171c;
  font: 13px/1.4 "SF Mono", Menlo, monospace;
  color: var(--fg-muted);
}
.repo-lite .branch {
  color: var(--green);
  margin-bottom: 16px;
}
.repo-lite p {
  margin: 0 0 14px;
  color: var(--fg);
}
.repo-lite .diff {
  height: 12px;
  border-radius: 3px;
  margin: 9px 0;
  width: 92%;
}
.repo-lite .diff.add { background: rgba(129,184,139,0.32); }
.repo-lite .diff.del { background: rgba(224,108,117,0.28); width: 74%; }
.repo-lite .diff.short { width: 48%; }
.repo-lite .diff.mid { width: 64%; }
.design-lite svg,
.map-lite svg {
  width: 100%;
  height: 100%;
  display: block;
}
.board-lite {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  padding: 14px;
  background: #15151a;
}
.board-lite div {
  min-width: 0;
  border: 1px solid var(--stroke);
  border-radius: 12px;
  padding: 12px;
  background: rgba(255,255,255,0.045);
}
.board-lite b {
  display: block;
  margin-bottom: 10px;
  color: var(--fg);
  font-size: 12px;
}
.board-lite i {
  display: block;
  margin-top: 8px;
  padding: 8px;
  border-radius: 9px;
  background: rgba(255,255,255,0.06);
  color: var(--fg-muted);
  font-style: normal;
  font-size: 12px;
}
.board-lite i.done {
  color: color-mix(in srgb, var(--green) 78%, white);
}
.video-lite {
  position: relative;
  height: 100%;
  background:
    radial-gradient(circle at 68% 28%, rgba(224,108,117,0.6), transparent 28%),
    linear-gradient(135deg, #23222c, #101116);
}
.video-lite .play {
  position: absolute;
  left: 50%;
  top: 44%;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: rgba(255,255,255,0.14);
  border: 1px solid rgba(255,255,255,0.24);
}
.video-lite .play::before {
  content: "";
  position: absolute;
  left: 23px;
  top: 17px;
  border-left: 18px solid #fff;
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
}
.video-lite .timeline {
  position: absolute;
  left: 20px;
  right: 20px;
  bottom: 20px;
  height: 7px;
  border-radius: 999px;
  background: rgba(255,255,255,0.14);
}
.video-lite .timeline i {
  display: block;
  width: 42%;
  height: 100%;
  border-radius: inherit;
  background: var(--red);
}
.map-lite {
  background: #10141a;
}
.map-lite svg {
  fill: none;
  stroke: rgba(84,214,217,0.58);
  stroke-width: 3;
}
.map-lite circle {
  fill: var(--teal);
  stroke: #fff;
}
.app-lite {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 18px 22px;
  background: #14161b;
}
.app-lite .phone {
  width: 82px;
  height: 146px;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 20px;
  padding: 13px 10px;
  background: #07080c;
}
.app-lite .phone i,
.app-lite .phone b,
.app-lite .phone span {
  display: block;
  border-radius: 999px;
}
.app-lite .phone i {
  height: 8px;
  width: 28px;
  margin: 0 auto 16px;
  background: rgba(255,255,255,0.18);
}
.app-lite .phone b {
  height: 42px;
  background: linear-gradient(135deg, var(--green), var(--teal));
}
.app-lite .phone span {
  height: 8px;
  margin-top: 12px;
  background: rgba(255,255,255,0.14);
}
.app-copy {
  flex: 1;
  display: grid;
  gap: 13px;
}
.app-copy i:nth-child(1) { width: 82%; }
.app-copy i:nth-child(2) { width: 58%; }
.app-copy i:nth-child(3) { width: 72%; }
.voice-lite {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 20px;
  padding: 18px 20px;
  background: #15141b;
}
.avatars {
  display: flex;
}
.avatars i {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin-left: -9px;
  border-radius: 50%;
  border: 2px solid #15141b;
  background: var(--purple);
  color: #fff;
  font-style: normal;
  font-weight: 700;
}
.avatars i:first-child {
  margin-left: 0;
}
.avatars i:nth-child(2) { background: var(--teal); }
.avatars i:nth-child(3) { background: var(--pink); }
.wave {
  display: flex;
  align-items: center;
  gap: 6px;
}
.wave span {
  width: 7px;
  height: 38px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--purple) 74%, white);
  animation: wave-bounce 1.3s ease-in-out infinite alternate;
}
.wave span:nth-child(2) { animation-delay: 0.1s; height: 58px; }
.wave span:nth-child(3) { animation-delay: 0.2s; height: 46px; }
.wave span:nth-child(4) { animation-delay: 0.3s; height: 66px; }
.wave span:nth-child(5) { animation-delay: 0.4s; height: 34px; }
@keyframes wave-bounce {
  to { transform: scaleY(0.45); opacity: 0.62; }
}

@media (max-width: 860px) {
  .anything {
    padding: 72px 0 78px;
  }
  .anything h2 {
    font-size: 36px;
  }
  .anything-sub {
    font-size: 16px;
  }
  .anything-viewport {
    height: 600px;
  }
  .anything-world {
    top: 18px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .anything-world {
    animation: none;
    transform: translate3d(max(-760px, calc((100vw - 2600px) / 2)), 0, 0);
  }
  .wave span {
    animation: none;
  }
}

/* ── Build-on-top SDK ──────────────────────────────────────────────────────
   "A full SDK for every layer." A split: outcome bullets on the left, a tabbed
   code panel on the right whose snippet swaps per tab (sdk.js). Restrained
   palette — one keyword hue (purple) + one string hue (green) over greys — so
   the code reads as real, not a rainbow. */
.sdk {
  max-width: 1280px;
  padding-top: 9vh;
  padding-bottom: 11vh;
}
.sdk-head {
  max-width: 760px;
  margin: 0 auto 46px;
  text-align: center;
}
.sdk-sub em {
  font-style: normal;
  color: var(--fg);
}
.sdk-eyebrow {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 14px;
}
.sdk-head h2 {
  font-size: clamp(30px, 4vw, 50px);
  line-height: 1.06;
  letter-spacing: -1.4px;
  font-weight: 700;
  margin: 0 0 16px;
}
.sdk-sub {
  color: var(--fg-muted);
  font-size: 18px;
  line-height: 1.55;
  margin: 0 auto;
  max-width: 580px;
}

.sdk-body {
  display: grid;
  grid-template-columns: 0.82fr 1.18fr;
  gap: 44px;
  align-items: center;
}

/* left: outcome list — neutral icons, matches the calm bento above */
.sdk-points {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 26px;
}
.sdk-points li {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}
.sdk-pt-ico {
  flex: none;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  color: var(--fg-muted);
  background: color-mix(in srgb, var(--fg-muted) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--fg-muted) 22%, var(--stroke));
}
.sdk-pt-ico svg {
  width: 20px;
  height: 20px;
}
.sdk-points h3 {
  margin: 0 0 5px;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.3px;
  color: var(--fg);
}
.sdk-points p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--fg-muted);
  max-width: 34ch;
}

/* right: tabbed code panel — a glass card with a faux editor window bar */
.sdk-panel {
  position: relative;
  border: 1px solid var(--stroke);
  border-radius: 16px;
  background: color-mix(in srgb, var(--bg-alt) 72%, transparent);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45);
  overflow: hidden;
}
.sdk-winbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--stroke);
  background: color-mix(in srgb, var(--bg-alt) 55%, transparent);
}
.sdk-dots {
  display: inline-flex;
  gap: 7px;
}
.sdk-dots i {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--fg-weak) 55%, transparent);
}
.sdk-file {
  font: 500 12.5px/1 ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--fg-weak);
  letter-spacing: 0.2px;
}
.sdk-run {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--green) 36%, var(--stroke));
  background: color-mix(in srgb, var(--green) 12%, transparent);
  color: color-mix(in srgb, var(--green) 75%, var(--fg));
  font: 600 11px/1 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.sdk-run svg {
  width: 9px;
  height: 9px;
}

/* tabs — segmented labels reading as the panel's "open layers" */
.sdk-tabs {
  display: flex;
  gap: 4px;
  padding: 10px 12px 0;
  border-bottom: 1px solid var(--stroke);
}
.sdk-tab {
  position: relative;
  border: 0;
  background: transparent;
  color: var(--fg-weak);
  font: 600 13.5px/1 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: 0.2px;
  padding: 9px 14px 12px;
  cursor: pointer;
  border-radius: 8px 8px 0 0;
  transition: color 0.18s ease, background 0.18s ease;
}
.sdk-tab:hover {
  color: var(--fg-muted);
}
.sdk-tab.is-active {
  color: var(--fg);
  background: color-mix(in srgb, var(--purple) 10%, transparent);
}
.sdk-tab.is-active::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: var(--purple);
  box-shadow: 0 0 8px color-mix(in srgb, var(--purple) 55%, transparent);
}

/* the code itself — fixed height so the panel never jumps between snippets, with
   a subtle line-number gutter. Snippets are sized so all four fill it evenly. */
.sdk-code {
  --c-gutter: rgba(171, 178, 191, 0.26);
  margin: 0;
  padding: 22px 26px;
  overflow: auto;
  height: 430px;
  font: 14px/1.7 ui-monospace, "SF Mono", Menlo, monospace;
  counter-reset: ln;
}
.sdk-code code {
  display: block;
  white-space: pre;
  color: var(--fg-muted);
  animation: sdkfade 0.2s ease;
}
.sdk-code .cl {
  display: block;
}
.sdk-code .cl::before {
  counter-increment: ln;
  content: counter(ln);
  display: inline-block;
  width: 2ch;
  margin-right: 18px;
  text-align: right;
  color: var(--c-gutter);
  -webkit-user-select: none;
  user-select: none;
}

/* Syntax palette — One Dark, the theme the Campus colors are pulled from. */
.t-com {
  color: #7f848e;
  font-style: italic;
}
.t-str {
  color: #98c379;
}
.t-kw {
  color: #c678dd;
}
.t-type {
  color: #e5c07b;
}
.t-num {
  color: #d19a66;
}
.t-fn {
  color: #61afef;
}
.t-anno {
  color: #56b6c2;
}
@keyframes sdkfade {
  from {
    opacity: 0.25;
    transform: translateY(3px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ── SDK playground: code | live preview split ─────────────────────────────*/
.sdk-split {
  display: grid;
  grid-template-columns: 1.02fr 0.98fr;
}
/* No divider — the code opens straight onto the canvas (not a gated box). */

/* the preview side reads as FREE, open canvas: it shares the panel surface (no
   darker inset) and the dot grid fades out toward every edge so it feels like a
   slice of the infinite canvas rather than a bounded cell. */
.sdk-preview {
  position: relative;
  height: 430px;
  overflow: hidden;
}
.sdk-preview::before {
  content: "";
  position: absolute;
  inset: -40px;
  z-index: 0;
  background: radial-gradient(var(--dot) 1.1px, transparent 1.1px) 0 0 /
    var(--dot-spacing) var(--dot-spacing);
  -webkit-mask-image: radial-gradient(125% 120% at 60% 46%, #000 46%, transparent 100%);
  mask-image: radial-gradient(125% 120% at 60% 46%, #000 46%, transparent 100%);
  pointer-events: none;
}
.sdk-pv-label {
  position: absolute;
  top: 12px;
  left: 14px;
  z-index: 2;
  font: 600 10.5px/1 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--fg-weak);
  pointer-events: none;
}
/* each preview surface fills the pane (above the dots); only the active shows */
.pv {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: none;
  animation: sdkfade 0.28s ease;
}
.pv.is-active {
  display: block;
}

/* caption under the split — updates per tab from the snippet's blurb */
.sdk-caption {
  padding: 13px 24px;
  border-top: 1px solid var(--stroke);
  background: color-mix(in srgb, var(--bg-alt) 50%, transparent);
  font-size: 13.5px;
  color: var(--fg-muted);
  min-height: 44px;
}
.sdk-cap-text {
  transition: opacity 0.2s ease;
}

/* shared mini-tile chrome reused by the pomodoro + terminal mockups */
.ptile,
.pterm {
  position: absolute;
  border: 1px solid var(--stroke);
  border-radius: 12px;
  background: color-mix(in srgb, var(--bg-alt) 92%, transparent);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45);
  overflow: hidden;
}
.ptile-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--stroke);
  background: color-mix(in srgb, var(--bg-alt) 70%, transparent);
}
.ptile-name {
  font: 600 12px/1 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg);
}
.ptile-tag {
  font: 500 11px/1 ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--fg-weak);
}
.ptile-x {
  margin-left: auto;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--fg-weak) 50%, transparent);
}

/* Pomodoro tile */
.pv-tile .ptile {
  left: 50%;
  top: 50%;
  width: 280px;
  transform: translate(-50%, -50%);
}
.ptile-body {
  padding: 20px 20px 18px;
  text-align: center;
}
.ptimer-time {
  font: 700 52px/1 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: -1px;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}
.ptrack {
  height: 5px;
  margin: 16px 0 16px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--fg-weak) 26%, transparent);
  overflow: hidden;
}
.ptrack-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: var(--purple);
  box-shadow: 0 0 10px color-mix(in srgb, var(--purple) 60%, transparent);
  transition: width 0.9s linear;
}
.pbtns {
  display: flex;
  gap: 8px;
  justify-content: center;
}
.pbtn {
  flex: 1;
  border: 1px solid var(--stroke);
  border-radius: 8px;
  background: color-mix(in srgb, var(--bg) 50%, transparent);
  color: var(--fg-muted);
  font: 600 12px/1 "SF Pro Display", system-ui, sans-serif;
  padding: 9px 0;
  cursor: pointer;
  transition: color 0.16s ease, border-color 0.16s ease, background 0.16s ease;
}
.pbtn:hover {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--fg) 24%, var(--stroke));
}
.pbtn.is-on {
  color: #fff;
  border-color: color-mix(in srgb, var(--purple) 60%, var(--stroke));
  background: color-mix(in srgb, var(--purple) 22%, transparent);
}

/* deploy: the created terminal tile sits on the canvas (offset, not boxed-in),
   and the "created" confirmation floats on free canvas just off its corner. */
.pv-command .pterm {
  left: 34px;
  top: 84px;
  width: 56%;
  min-width: 300px;
  opacity: 0;
  transform: translateY(12px) scale(0.97);
  transition: opacity 0.34s ease, transform 0.34s cubic-bezier(0.2, 0.7, 0.3, 1.3);
}
.pv-command .pterm.in {
  opacity: 1;
  transform: none;
}
.pterm-out {
  margin: 0;
  padding: 14px 16px 16px;
  min-height: 128px;
  overflow: hidden;
  font: 12.5px/1.7 ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--fg-muted);
}
.pcreated-badge {
  position: absolute;
  left: calc(34px + 56% + 34px);
  top: 122px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 13px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--green) 48%, var(--stroke));
  background: color-mix(in srgb, var(--green) 16%, var(--bg-alt));
  color: color-mix(in srgb, var(--green) 82%, var(--fg));
  font: 600 12px/1 "SF Pro Display", system-ui, sans-serif;
  white-space: nowrap;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.42);
  opacity: 0;
  transform: scale(0.82) translateY(4px);
  transition: opacity 0.28s ease, transform 0.28s cubic-bezier(0.2, 0.7, 0.3, 1.4);
}
.pcreated-badge.in {
  opacity: 1;
  transform: none;
}
.pcreated-badge::before {
  /* a short connector back toward the tile it was spawned from */
  content: "";
  position: absolute;
  right: 100%;
  top: 50%;
  width: 22px;
  height: 1.5px;
  margin-right: 7px;
  background: linear-gradient(
    90deg,
    transparent,
    color-mix(in srgb, var(--green) 55%, transparent)
  );
}
.pcreated-badge i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 8px color-mix(in srgb, var(--green) 70%, transparent);
}
.pln {
  white-space: pre-wrap;
  animation: plnIn 0.18s ease;
}
.pln-cmd {
  color: var(--fg);
}
.pln-ok {
  color: var(--green);
}
.pln-dim {
  color: var(--fg-weak);
}
.pterm-out.is-running::after {
  content: "▋";
  color: var(--purple);
  animation: pblink 1s steps(1) infinite;
}
@keyframes plnIn {
  from {
    opacity: 0;
    transform: translateY(2px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes pblink {
  50% {
    opacity: 0;
  }
}

/* mindmap renderer */
.pmap {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.pmap.is-grab {
  cursor: grabbing;
}
.pmap-link line {
  stroke: color-mix(in srgb, var(--fg-weak) 55%, transparent);
  stroke-width: 1.4;
}
.pnode {
  cursor: grab;
}
.pnode text {
  pointer-events: none;
  font-family: "SF Pro Display", system-ui, sans-serif;
}
.pv-render .pv-hint,
.pv-protocol .proom-log {
  position: absolute;
  z-index: 4;
  pointer-events: none;
}
.pv-render .pv-hint {
  right: 14px;
  bottom: 12px;
  font: 500 11px/1 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg-weak);
}

/* live room */
.proom {
  position: absolute;
  inset: 0;
}
.ptileghost {
  position: absolute;
  left: 0;
  top: 0;
  width: 150px;
  height: 96px;
  border: 1px solid color-mix(in srgb, var(--purple) 45%, var(--stroke));
  border-radius: 10px;
  background: color-mix(in srgb, var(--purple) 12%, var(--bg-alt));
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);
  will-change: transform;
}
.ptileghost-bar {
  display: block;
  height: 22px;
  border-bottom: 1px solid color-mix(in srgb, var(--purple) 35%, var(--stroke));
  background: color-mix(in srgb, var(--purple) 18%, transparent);
}
.pcur {
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  align-items: flex-start;
  gap: 4px;
  will-change: transform;
  z-index: 3;
}
.pcur svg {
  width: 15px;
  height: 19px;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.4));
}
.pcur-tag {
  margin-top: 9px;
  padding: 2px 7px;
  border-radius: 6px;
  font: 600 10.5px/1.3 "SF Pro Display", system-ui, sans-serif;
  color: #fff;
}
.pcur-a .pcur-tag {
  background: var(--purple);
}
.pcur-b .pcur-tag {
  background: var(--teal);
}
.proom-log {
  left: 14px;
  bottom: 12px;
  font: 500 11px/1 ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--fg-weak);
}

/* ── Multiplayer, out of the box ───────────────────────────────────────────
   A live room: named peer cursors with personalities roam a free canvas,
   react to each other and to the visitor's real cursor, and use the real
   Campus cursor-chat / GIF / confetti features. mp.js drives the sim. */
.mp {
  max-width: 1240px;
  padding-top: 9vh;
  padding-bottom: 11vh;
}
.mp-head {
  max-width: 760px;
  margin: 0 auto 40px;
  text-align: center;
}
.mp-eyebrow {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 14px;
}
.mp-head h2 {
  font-size: clamp(30px, 4vw, 50px);
  line-height: 1.06;
  letter-spacing: -1.4px;
  font-weight: 700;
  margin: 0 0 16px;
}
.mp-sub {
  color: var(--fg-muted);
  font-size: 18px;
  line-height: 1.55;
  margin: 0 auto;
  max-width: 600px;
}
.mp-sub em {
  font-style: normal;
  color: var(--fg);
}

/* The cursors roam the PAGE canvas, not a boxed widget: a full-bleed band with
   no frame or fill, so the site's own dotted surface shows straight through and
   the room feels like an open slice of the infinite canvas. A soft top/bottom
   mask lets cursors + confetti fade in/out at the band edges instead of hard
   clipping. (body has overflow-x:hidden, so 100vw never adds a scrollbar.) */
.mp-field {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: 26px;
  height: min(66vh, 600px);
  overflow: hidden;
  touch-action: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 8%, #000 91%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 8%, #000 91%, transparent 100%);
}
.mp-field.is-live {
  cursor: none;
}

/* the follower (Sam) latches onto you when you visit the section, then trails
   your real cursor across the WHOLE page for the rest of the visit — so it
   leaves the field and pins to the viewport, above page content. */
.mp-cur.mp-follow {
  position: fixed;
  z-index: 60;
}
.mp-bub.mp-follow-bub {
  position: fixed;
  z-index: 61;
}

.mp-confetti {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
}

.mp-hint {
  position: absolute;
  left: 50%;
  bottom: 12%;
  transform: translateX(-50%);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  font: 500 12.5px/1 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg-weak);
  pointer-events: none;
  transition: opacity 0.5s ease;
}
.mp-hint kbd {
  font: 600 11px/1 ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--fg-muted);
  background: color-mix(in srgb, var(--fg) 8%, transparent);
  border: 1px solid var(--stroke);
  border-radius: 5px;
  padding: 3px 6px;
}

/* ── cursors (peers + you) ────────────────────────────────────────────────*/
.mp-cur,
.mp-you {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 6;
  pointer-events: none;
  will-change: transform;
}
.mp-you {
  z-index: 9;
}
.mp-cur svg,
.mp-you svg {
  display: block;
  width: 15px;
  height: 19px;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
}
.mp-pill {
  position: absolute;
  left: 12px;
  top: 13px;
  padding: 2px 7px;
  border-radius: 6px;
  font: 600 10.5px/1.3 "SF Pro Display", system-ui, sans-serif;
  color: #fff;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: opacity 0.2s ease;
}
.mp-you .mp-pill {
  background: #2a2d34;
  color: #f0f0f0;
  border: 1px solid #3a3e47;
}

/* ── cursor-chat bubble (mirrors Campus: FigJam speech-bubble shape, accent
   fill, white text, types in then lingers then fades) ────────────────────*/
.mp-bub {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 7;
  max-width: 230px;
  pointer-events: none;
  opacity: 0;
  will-change: transform, opacity;
}
.mp-you-bub {
  z-index: 10;
}
.mp-bub-inner {
  display: inline-block;
  padding: 6px 10px;
  border-radius: 2px 12px 12px 12px;
  background: color-mix(in srgb, var(--a, var(--purple)) 86%, #101216);
  color: #fff;
  font: 500 13px/1.28 "SF Pro Display", system-ui, sans-serif;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
  word-break: break-word;
}
.mp-bub.is-you .mp-bub-inner {
  background: #2a2d34;
  color: #f0f0f0;
  border: 1px solid #3a3e47;
}
.mp-bub.is-gif .mp-bub-inner {
  padding: 4px;
}
.mp-caret {
  display: none;
  width: 2px;
  height: 13px;
  margin-left: 1px;
  vertical-align: -2px;
  background: currentColor;
  opacity: 0.85;
}
.mp-bub.is-typing .mp-caret {
  display: inline-block;
  animation: mp-caret 1.05s steps(1) infinite;
}
@keyframes mp-caret {
  0%, 50% { opacity: 0.85; }
  50.01%, 100% { opacity: 0; }
}

/* ── GIF reaction cards (stand in for Giphy results; looping CSS scenes with a
   Giphy-style badge) ─────────────────────────────────────────────────────*/
.mp-gif {
  position: relative;
  width: 158px;
  height: 110px;
  border-radius: 8px;
  overflow: hidden;
  display: grid;
  place-items: center;
  isolation: isolate;
}
.mp-gif-emoji {
  font-size: 46px;
  line-height: 1;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.4));
}
.mp-gif-cap {
  position: absolute;
  left: 8px;
  bottom: 6px;
  z-index: 2;
  font: 700 11px/1 "SF Pro Display", system-ui, sans-serif;
  color: #fff;
  letter-spacing: 0.3px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
}
.mp-gif-badge {
  position: absolute;
  right: 6px;
  top: 6px;
  z-index: 2;
  font: 800 8.5px/1 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: 0.6px;
  color: #fff;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 4px;
  padding: 2px 4px;
}
.mp-gif-party { background: radial-gradient(120% 120% at 50% 30%, #d18bba 0%, #6a4c93 100%); }
.mp-gif-shipit { background: radial-gradient(120% 120% at 30% 80%, #22808d 0%, #1f2937 100%); }
.mp-gif-lgtm { background: radial-gradient(120% 120% at 50% 40%, #81b88b 0%, #2c4a36 100%); }
.mp-gif-mind { background: radial-gradient(120% 120% at 50% 30%, #7272ea 0%, #221f3a 100%); }
.mp-gif-dance { background: radial-gradient(120% 120% at 70% 70%, #d19a66 0%, #5a2f3a 100%); }
.mp-gif-party .mp-gif-emoji { animation: mp-wiggle 0.9s ease-in-out infinite; }
.mp-gif-shipit .mp-gif-emoji { animation: mp-zoom 1.5s ease-in-out infinite; }
.mp-gif-lgtm .mp-gif-emoji { animation: mp-pop 1.1s ease-in-out infinite; }
.mp-gif-mind .mp-gif-emoji { animation: mp-shake 0.4s ease-in-out infinite; }
.mp-gif-dance .mp-gif-emoji { animation: mp-sway 0.7s ease-in-out infinite; }
@keyframes mp-wiggle {
  0%, 100% { transform: rotate(-12deg) scale(1); }
  50% { transform: rotate(12deg) scale(1.12); }
}
@keyframes mp-zoom {
  0% { transform: translate(-26px, 22px) rotate(-8deg) scale(0.8); }
  60% { transform: translate(20px, -16px) rotate(-8deg) scale(1.1); }
  100% { transform: translate(26px, -22px) rotate(-8deg) scale(0.7); opacity: 0.4; }
}
@keyframes mp-pop {
  0%, 100% { transform: scale(0.82); }
  45% { transform: scale(1.18); }
}
@keyframes mp-shake {
  0%, 100% { transform: translate(-2px, 0) rotate(-5deg); }
  50% { transform: translate(2px, -1px) rotate(5deg); }
}
@keyframes mp-sway {
  0%, 100% { transform: translateX(-7px) rotate(-9deg); }
  50% { transform: translateX(7px) rotate(9deg); }
}

/* real Giphy result: an <img> loaded from media.giphy.com, with the required
   GIPHY attribution mark. Falls back to the emoji card above when offline. */
.mp-gif-wrap {
  position: relative;
  display: block;
  line-height: 0;
}
.mp-gif-img {
  display: block;
  height: 132px;
  width: auto;
  max-width: 240px;
  border-radius: 8px;
  background: #0e0f13;
}
.mp-gif-by {
  position: absolute;
  right: 5px;
  bottom: 5px;
  z-index: 2;
  font: 800 7.5px/1 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: 1px;
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
  border-radius: 3px;
  padding: 2px 4px;
}
.mp-gif-load {
  width: 150px;
  height: 100px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: color-mix(in srgb, var(--a, var(--purple)) 24%, #14161b);
}
.mp-gif-load i {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.25);
  border-top-color: #fff;
  animation: mp-spin 0.7s linear infinite;
}
@keyframes mp-spin {
  to { transform: rotate(360deg); }
}

/* ── legend: who's who ────────────────────────────────────────────────────*/
.mp-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 14px;
  margin: 30px 0 0;
  padding: 0;
  list-style: none;
}
.mp-legend li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--fg-muted);
}
.mp-legend li::before {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--a);
  box-shadow: 0 0 8px color-mix(in srgb, var(--a) 60%, transparent);
}
.mp-legend b {
  color: var(--fg);
  font-weight: 600;
}

@media (max-width: 760px) {
  .mp-field {
    height: 68vh;
  }
  .mp-hint {
    white-space: normal;
    width: 84%;
    text-align: center;
    justify-content: center;
    flex-wrap: wrap;
  }
}

@media (max-width: 900px) {
  .sdk-body {
    grid-template-columns: 1fr;
    gap: 30px;
  }
  .sdk-split {
    grid-template-columns: 1fr;
  }
  .sdk-split .sdk-code {
    border-right: 0;
    border-bottom: 1px solid var(--stroke);
    height: 360px;
  }
  .sdk-preview {
    height: 360px;
  }
}

/* ── Drag targets ──────────────────────────────────────────────────────────
   JS drives a CSS var --p (0..1) on each [data-drag] element, plus the
   translate/opacity. We only declare the resting + will-change here. */
[data-drag] {
  will-change: transform, opacity;
}

/* Every drag-in line is also grabbable by the user once it's settled — pick it
   up like a canvas object. The accent ring echoes the Campus selection box. */
.movable {
  cursor: grab;
}
.movable.grabbing {
  cursor: grabbing;
  outline: 1.5px solid color-mix(in srgb, var(--purple) 60%, transparent);
  outline-offset: 8px;
  border-radius: 4px;
}

[data-reveal] {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
[data-reveal].in {
  opacity: 1;
  transform: none;
}

/* ── Selection bounding box (shown while a cursor drags the text) ──────────
   Mirrors the Campus selection / group bounding box: accent stroke, faint
   accent fill, small white corner markers. Rendered in the cursor's accent. */
.dragbox {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 14;
  pointer-events: none;
  opacity: 0;
  box-sizing: border-box;
  border: 1.5px solid var(--accent);
  border-radius: 5px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  transform-origin: center;
  will-change: transform, opacity, left, top, width, height;
}
.dragbox .cm {
  position: absolute;
  width: 7px;
  height: 7px;
  background: #fff;
  border: 1px solid var(--accent);
  border-radius: 1px;
}
.dragbox .cm.tl {
  left: 0;
  top: 0;
  transform: translate(-50%, -50%);
}
.dragbox .cm.tr {
  right: 0;
  top: 0;
  transform: translate(50%, -50%);
}
.dragbox .cm.bl {
  left: 0;
  bottom: 0;
  transform: translate(-50%, 50%);
}
.dragbox .cm.br {
  right: 0;
  bottom: 0;
  transform: translate(50%, 50%);
}

/* ── Named cursor ─────────────────────────────────────────────────────────
   One reusable cursor per drag target, positioned absolutely over the page.
   Mirrors the Campus PeerCursor: accent SVG arrow + accent name pill. */
.cursor {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 15;
  pointer-events: none;
  opacity: 0;
  will-change: transform, opacity;
  transform: translate3d(-200px, -200px, 0);
}
.cursor svg {
  display: block;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
}
.cursor .pill {
  position: absolute;
  left: 12px;
  top: 14px;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

/* ── Campus workspace: real tiles on the canvas ────────────────────────────*/
.terminals {
  max-width: 1220px;
  padding-top: 4vh;
  padding-bottom: 16vh;
}
.terminals .band-title,
.terminals .band-body {
  max-width: 1080px;
}

/* the board: absolutely-arranged tiles on desktop, a stack on narrow screens */
.workspace {
  position: relative;
  width: 1200px;
  max-width: 100%;
  height: 1110px;
  margin: 46px auto 0;
}

/* DMG-style annotations: a label + a tapered curved arrow aimed at a tile */
.annot-label {
  position: absolute;
  z-index: 40;
  pointer-events: none;
  font: 600 14.5px/1.3 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg);
  letter-spacing: 0.2px;
  opacity: 0;
  transition: opacity 0.55s ease;
}
.annot-arrow {
  position: absolute;
  z-index: 40;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.55s ease;
  transform-origin: center;
}
.annot-label.is-on { opacity: 1; }
.annot-arrow.is-on { opacity: 0.9; }
/* stage = drag-in target (data-drag) + layout slot; tile = user-movable surface */
.stage {
  position: absolute;
  will-change: transform, opacity;
}

/* ── Campus tile chrome (glass body, title pill + action pills, accent) ─────*/
.tile {
  --accent: var(--purple);
  position: relative;
  border-radius: 16px;
  border: 1px solid var(--stroke);
  background: rgba(18, 18, 22, 0.66);
  backdrop-filter: blur(16px) saturate(1.05);
  -webkit-backdrop-filter: blur(16px) saturate(1.05);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  will-change: transform;
}
.tile[data-accent="teal"] { --accent: var(--teal); }
.tile[data-accent="orange"] { --accent: var(--orange); }
.tile[data-accent="green"] { --accent: var(--green); }
.tile[data-accent="pink"] { --accent: var(--pink); }
.tile[data-accent="red"] { --accent: var(--red); }
.tile.dragging {
  border-color: color-mix(in srgb, var(--accent) 60%, var(--stroke));
  box-shadow: 0 34px 92px rgba(0, 0, 0, 0.62);
}

.tile-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 8px 0 9px;
  background: rgba(0, 0, 0, 0.3);
  border-bottom: 1px solid var(--stroke);
  cursor: grab;
  user-select: none;
}
.tile.dragging .tile-bar { cursor: grabbing; }
.tile-name {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 3px 11px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.05);
  font: 600 12.5px/1 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg);
  letter-spacing: 0.2px;
}
.tile-name::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--accent);
}
.tile-tag {
  margin-left: auto;
  font: 11px/1 "SF Mono", Menlo, monospace;
  color: var(--fg-weak);
}
.tile-acts {
  margin-left: auto;
  display: flex;
  gap: 6px;
}
.tile-tag + .tile-acts { margin-left: 10px; }
.tile-acts .act {
  width: 24px;
  height: 24px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  color: var(--fg-weak);
  background: rgba(255, 255, 255, 0.04);
}
.tile-acts .act svg { width: 12px; height: 12px; }
.tile-acts .act:hover { color: var(--fg); }
.tile-acts .act.x:hover { color: var(--red); }

.tile-body { overflow: hidden; }

/* terminal body (solid, holds xterm) */
.tile.is-term .tile-body { padding: 12px 14px; background: #141417; }
.term-mount .xterm { transform-origin: top left; will-change: transform; }
.tile-body .xterm-viewport { overflow-y: hidden !important; scrollbar-width: none; }
.tile-body .xterm-viewport::-webkit-scrollbar {
  width: 0 !important;
  height: 0 !important;
  display: none;
}

/* scratchpad note */
.tile-body.note {
  padding: 16px 18px;
  font: 14px/1.55 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg-muted);
}
/* hero scratchpads are a uniform, larger card size (content top-aligned) */
.hero-stage .tile-body.note {
  height: 176px;
}
.note h3 { margin: 0 0 12px; font-size: 15px; color: var(--fg); font-weight: 700; }
.note .todo { list-style: none; margin: 0 0 14px; padding: 0; }
.note .todo li { position: relative; padding: 5px 0 5px 26px; color: var(--fg); }
.note .todo li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 5px;
  width: 15px;
  height: 15px;
  border-radius: 4px;
  border: 1.5px solid var(--fg-weak);
}
.note .todo li.done { color: var(--fg-muted); text-decoration: line-through; text-decoration-color: var(--fg-weak); }
.note .todo li.done::before { background: var(--accent); border-color: var(--accent); }
.note .todo li.done::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 8px;
  width: 4px;
  height: 8px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.note .muted { color: var(--fg-weak); font-size: 13px; margin: 0; }
.note .tag { color: var(--accent); font-weight: 600; }

/* image tile */
.tile.is-image .tile-body { padding: 0; background: #15151a; }
.tile.is-image img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* webview tile */
.tile.is-web .tile-body { padding: 0; background: var(--bg); }
.urlbar {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 34px;
  padding: 0 10px;
  background: #141414;
  border-bottom: 1px solid var(--stroke);
}
.urlbar .nav { display: flex; gap: 7px; color: var(--fg-weak); }
.urlbar .nav svg { width: 14px; height: 14px; }
.urlbar .addr {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 7px;
  background: var(--bg);
  border: 1px solid var(--stroke);
  border-radius: 8px;
  height: 22px;
  padding: 0 9px;
  font: 11.5px/1 "SF Mono", Menlo, monospace;
  color: var(--fg-muted);
}
.urlbar .addr svg { width: 11px; height: 11px; color: var(--fg-weak); }
.tile.is-web iframe { display: block; width: 100%; border: 0; background: #15151a; }

/* Hero tile cluster, responsive tiers. The full frame needs real room; below
   that we trim only the pieces that would collide with the centered headline /
   CTA, so MacBook-class screens still get the dragged-in tiles framing the hero.
   (The app.js intro guard skips whatever ends up display:none.) */

/* The lowest scratchpad reaches down into the trusted-by marquee unless the
   viewport is tall — drop it so the left fan stays clear. */
@media (max-height: 899px) {
  .hero-stage .s-lower {
    display: none;
  }
}
/* The bottom-right terminal needs room to clear the centered CTA + its arrows.
   Below ~1450px wide it would start riding over them, so drop just the terminal
   (the scratchpad fan + design keep framing down to 1240px). */
@media (max-width: 1450px) {
  .hero-stage .s-term {
    display: none;
  }
}
/* Too narrow to frame the headline without overlapping it — drop the cluster. */
@media (max-width: 1240px) {
  .hero-stage {
    display: none;
  }
}

/* narrow screens: drop the canvas, stack the tiles */
@media (max-width: 1100px) {
  .workspace {
    width: 100%;
    height: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 26px;
  }
  .stage {
    position: static !important;
    left: auto !important;
    top: auto !important;
    width: min(680px, 100%) !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-drag],
  .cursor {
    transform: none !important;
    opacity: 1 !important;
  }
  .cursor {
    display: none;
  }
  .marquee-track,
  .tstrip-track {
    animation: none;
  }
}

/* ───────────────────────────────────────────────────────────────────────────
   "Your whole stack" — opposite-scrolling marquees of brand logos. Rows + chips
   are built by tools.js from the vendored Simple Icons paths (tool-logos.js).
   Each row's track holds two identical groups and slides -50% for a seamless
   loop; adjacent rows reverse direction. Logos are monochrome at rest and take
   their brand colour on hover (--brand, set per chip in tools.js).
   ─────────────────────────────────────────────────────────────────────────── */
.tools {
  max-width: none; /* full-bleed: the rows run edge to edge */
  padding: 12vh 24px 12vh;
  text-align: center;
  overflow: hidden; /* clip the off-screen ends of the tracks */
}
.tools-head {
  max-width: 720px;
  margin: 0 auto 64px;
}
.tools-head h2 {
  font-size: clamp(30px, 4vw, 52px);
  letter-spacing: -1.5px;
  font-weight: 700;
  line-height: 1.05;
  margin: 0;
}

.tools-rows {
  display: flex;
  flex-direction: column;
  gap: 34px; /* generous air between rows */
  /* Centered band, narrower than any single logo group (~1160px+). Keeping the
     band below the group width guarantees the two-group loop ALWAYS fills it —
     no empty gap appears at the seam — and reads as a centered cluster rather
     than a full-bleed strip that looks left-anchored. */
  max-width: 1000px;
  margin: 0 auto;
}
.tstrip-row {
  position: relative;
  overflow: hidden;
  /* fade both edges so logos slide in/out instead of hard-clipping */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.tstrip-track {
  display: flex;
  width: max-content;
  animation: marquee var(--dur, 44s) linear infinite;
  will-change: transform;
}
/* adjacent rows scroll the other way — the whole point of the strip */
.tstrip-row:nth-child(even) .tstrip-track {
  animation-direction: reverse;
}
.tstrip-group {
  display: flex;
  align-items: center;
  gap: 56px;
  padding-right: 56px; /* one gap of trailing space → seamless loop */
}

/* No pill — just the logo + wordmark, like a logo wall that drifts. Muted at
   rest, the logo lights up in its real brand colour on hover. */
.tchip {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  flex: none;
  color: var(--fg-weak);
  white-space: nowrap;
  transition: color 0.22s ease;
}
.tchip svg {
  width: 25px;
  height: 25px;
  flex: none;
  color: inherit; /* silhouette inherits the muted wordmark colour at rest */
  opacity: 0.82;
  transition: color 0.22s ease, opacity 0.22s ease;
}
.tchip .tname {
  font: 600 19px/1 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: -0.3px;
  color: inherit;
}
.tchip:hover {
  color: var(--fg);
}
.tchip:hover svg {
  color: var(--brand, #fff); /* light up in the real brand colour */
  opacity: 1;
}

@media (max-width: 720px) {
  .tools {
    padding: 8vh 16px;
  }
  .tools-rows {
    gap: 26px;
  }
  .tstrip-group {
    gap: 40px;
    padding-right: 40px;
  }
  .tchip svg {
    width: 21px;
    height: 21px;
  }
  .tchip .tname {
    font-size: 16px;
  }
}

/* ───────────────────────────────────────────────────────────────────────────
   Versatility showcase — an auto-switching tab bar over a mini Campus canvas.
   Each tab is one "workarea" (Coder / Designer / Marketer). The active tab's
   fill grows to signal the next auto-switch. The stage is a fixed design-size
   canvas (scaled to fit) with overflow:hidden, so tiles dragged off by their
   cursors clip cleanly at the edge. All of it is driven by showcase.js — it is
   intentionally decoupled from the hero's data-drag engine.
   ─────────────────────────────────────────────────────────────────────────── */
.showcase {
  max-width: none; /* full-bleed: the mini-canvas uses the whole viewport width */
  padding: 10vh 24px 12vh;
  text-align: center;
}
.showcase-head {
  max-width: 720px;
  margin: 0 auto;
}
.showcase .sc-eyebrow {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 14px;
}
.showcase h2 {
  font-size: clamp(30px, 4vw, 52px);
  letter-spacing: -1.5px;
  font-weight: 700;
  line-height: 1.05;
  margin: 0 0 16px;
}
.showcase .sc-sub {
  color: var(--fg-muted);
  font-size: 18px;
  line-height: 1.55;
  margin: 0 auto;
  max-width: 560px;
}

/* tab bar — centered glass pill, one segment per workarea. Each carries an
   auto-advance fill (scaleX 0→1) that visually counts down to the next switch. */
/* editorial tabs: bare text labels on the canvas — no container box. The active
   label glows in its scene accent; a thin accent underline grows L→R as the
   countdown to the next auto-switch (over a faint static rail). */
.sc-tabs {
  display: inline-flex;
  gap: 12px;
  margin: 28px auto 40px;
  padding: 0;
}
.sc-tab {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px 16px;
  border: 0;
  background: transparent;
  color: var(--fg-weak);
  font: 600 16px/1 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: 0.2px;
  cursor: pointer;
  transition: color 0.2s;
}
.sc-tab:hover {
  color: var(--fg-muted);
}
.sc-tab.is-active {
  color: var(--accent, #7272ea);
}
.sc-tab .dot {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--accent, #7272ea);
  opacity: 0.4;
  transition: opacity 0.2s, box-shadow 0.2s;
}
.sc-tab.is-active .dot {
  opacity: 1;
  box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 70%, transparent);
}
/* faint full-width rail under the active tab (painted first) */
.sc-tab.is-active::before {
  content: "";
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 5px;
  height: 2.5px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}
/* the bright underline that grows L→R = countdown (driven by scaleX in JS) */
.sc-tab .sc-fill {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 5px;
  height: 2.5px;
  border-radius: 2px;
  background: var(--accent, #7272ea);
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 55%, transparent);
  transform-origin: left center;
  transform: scaleX(0);
  pointer-events: none;
}

/* the stage: a fixed-size mini-canvas, scaled to fit its container (showcase.js
   sets the scale + reserves height). Its own dotted surface reads as a canvas. */
.showcase-stage-wrap {
  position: relative;
  /* full-bleed: break out of the section padding and span the whole viewport so
     the clip happens at the PAGE edges, not a small centered box. Tiles dragged
     off by the cursors slide all the way off the sides of the page — the scene
     feels like a slice of the big canvas, not a framed widget. (body has
     overflow-x:hidden, so 100vw never adds a scrollbar.) */
  width: 100vw;
  margin-left: calc(50% - 50vw);
  overflow: hidden;
}
.showcase-stage {
  position: absolute;
  left: 50%; /* centered on the viewport; showcase.js sets translateX(-50%) scale(s) */
  top: 0;
  width: 1840px;
  height: 1010px;
  transform-origin: top center;
  text-align: left; /* never let the section's centering leak into tiles */
  /* No frame and no clip here — the parent wrap clips at the page edges. */
}

.sc-tile {
  position: absolute;
  will-change: transform, opacity;
}
.sc-tile.is-hidden {
  display: none;
}
/* tiles fill their sc-tile slot and stack chrome vertically: bar, body, then an
   optional composer at the bottom. */
.sc-tile .tile {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.sc-tile .tile-body {
  flex: 1 1 auto;
  min-height: 0;
}
.sc-tile .tile-bar,
.sc-tile .composer {
  flex: 0 0 auto;
}

/* a named cursor that lives INSIDE the stage (so it clips at the canvas edge,
   unlike the page-level .cursor which is position:fixed). */
.sc-cursor {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 60;
  pointer-events: none;
  opacity: 0;
  will-change: transform, opacity;
}
.sc-cursor svg {
  display: block;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
}
.sc-cursor .pill {
  position: absolute;
  left: 12px;
  top: 14px;
  padding: 2px 6px;
  border-radius: 4px;
  font: 600 11px/1 system-ui, sans-serif;
  color: #fff;
  white-space: nowrap;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

/* a prompt composer the roamer cursor types into (terminals + the draft doc) */
.composer {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 30px;
  margin: 0 10px 10px;
  padding: 0 10px;
  border-radius: 8px;
  border: 1px solid var(--stroke);
  background: rgba(255, 255, 255, 0.03);
  font: 12px/1 "SF Mono", Menlo, monospace;
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
}
.composer .cg {
  color: var(--accent);
  font-weight: 700;
}
.composer .ctext {
  white-space: pre;
}
.composer .ccaret {
  width: 7px;
  height: 14px;
  background: var(--accent);
  opacity: 0;
  border-radius: 1px;
}
.composer.is-focus {
  border-color: color-mix(in srgb, var(--accent) 60%, var(--stroke));
  background: color-mix(in srgb, var(--accent) 9%, rgba(255, 255, 255, 0.03));
}
.composer.is-focus .ccaret {
  opacity: 0.9;
  animation: blink 1s steps(1) infinite;
}
.composer.is-sent {
  color: var(--green);
  border-color: color-mix(in srgb, var(--green) 50%, var(--stroke));
}
.composer.is-sent .cg {
  color: var(--green);
}

/* terminal tile in the showcase: fixed-height body window, xterm scaled to the
   content width and clipped (no auto-resizing the body like terminals.js does) */
.sc-tile .tile.is-term .tile-body {
  padding: 12px 14px 6px;
  background: #141417;
}

/* WIP dashboard (the "webview" that keeps updating) */
.sc-tile .tile.is-web .tile-body {
  display: flex;
  flex-direction: column;
}
.dash {
  flex: 1 1 auto;
  min-height: 0;
  padding: 14px 16px;
  background: var(--bg);
  overflow: hidden;
}
.dash-row {
  display: flex;
  gap: 10px;
}
.dash-kpi {
  flex: 1;
  border: 1px solid var(--stroke);
  border-radius: 10px;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.02);
}
.dash-kpi .k {
  font: 10px/1 system-ui, sans-serif;
  color: var(--fg-weak);
  text-transform: uppercase;
  letter-spacing: 1px;
}
.dash-kpi .v {
  font: 700 22px/1.1 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg);
  margin-top: 7px;
}
.dash-kpi .v small {
  font-size: 12px;
  color: var(--green);
  margin-left: 5px;
  font-weight: 600;
}
.dash-chart {
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 96px;
  margin-top: 16px;
  padding-top: 10px;
  border-top: 1px solid var(--stroke);
}
.dash-chart i {
  flex: 1;
  min-height: 3px;
  background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 26%, transparent));
  border-radius: 3px 3px 0 0;
  transition: height 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
.dash-log {
  margin-top: 14px;
  font: 11.5px/1.75 "SF Mono", Menlo, monospace;
  color: var(--fg-weak);
}
.dash-log b {
  color: var(--green);
  font-weight: 600;
}
.dash-log .pend {
  color: var(--orange);
}

/* document / blog-draft tile */
.doc {
  padding: 16px 18px;
  height: 100%;
  text-align: left;
  overflow: hidden;
}
.doc .doc-title {
  font: 700 16px/1.3 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg);
  margin: 0 0 4px;
}
.doc .doc-by {
  font: 11px/1 system-ui, sans-serif;
  color: var(--fg-weak);
  margin: 0 0 16px;
}
/* real blog-post copy */
.doc p {
  font: 13.5px/1.62 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg-muted);
  margin: 0 0 11px;
}
/* the live draft the marketer is writing — brighter, with a trailing caret */
.doc-write p.wp {
  font: 14px/1.66 "SF Pro Display", system-ui, sans-serif;
  color: var(--fg);
  margin: 0 0 12px;
}
.doc-write p.wp:last-child::after {
  content: "▍";
  margin-left: 1px;
  color: var(--accent);
  animation: blink 1s steps(1) infinite;
}
.doc .ln {
  height: 8px;
  border-radius: 4px;
  background: rgba(171, 178, 191, 0.15);
  margin: 9px 0;
}
.doc .ln.s {
  width: 55%;
}
.doc .ln.m {
  width: 82%;
}
.doc .ln.h {
  height: 11px;
  width: 70%;
  background: rgba(171, 178, 191, 0.28);
  margin: 16px 0 12px;
}

/* inspiration / preview image mock (inline SVG fills the body) */
.sc-tile .tile.is-image .tile-body {
  padding: 0;
  background: #0f0f13;
}
.sc-tile .tile.is-image svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* responsive: showcase.js scales the stage; below the design width the heading
   copy still reads. Hide nothing — the stage just shrinks. */
@media (prefers-reduced-motion: reduce) {
  .sc-cursor {
    display: none;
  }
  .composer.is-focus .ccaret {
    animation: none;
  }
}

/* ════════════════ CROSS-DEVICE HAND-OFF — tiles fly onto iPad ═══════════════
   A pinned, scroll-scrubbed section: real Campus tiles live on the page and, as
   you scroll, rotate + converge onto a CSS iPad running Campus (status bar,
   floating toolbar, presence, home indicator). One preserve-3d space, so the
   tiles physically fly onto the device. Driven by device_flyin.js; the on-iPad
   tile layout is ported from the showcase "coder" scene and composed via
   `index.html?edit` (drag = move, wheel = scale, "Copy slots JSON"). */
.handoff {
  max-width: none;
  padding: 0;
  position: relative;
  min-height: 260vh;
}
.handoff-pin {
  position: sticky;
  top: 0;
  height: 100vh;
  display: grid;
  place-items: center;
  overflow: hidden;
  perspective: 1600px;
  perspective-origin: 50% 44%;
}
.handoff-glow {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 760px;
  height: 760px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--purple) 32%, transparent) 0%, transparent 62%);
  filter: blur(20px);
  opacity: var(--glow, 0.12);
  pointer-events: none;
  z-index: 0;
}
.ff-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  transform-style: preserve-3d;
}
.handoff-head { text-align: center; max-width: 600px; margin: 0 auto; }
.handoff-eyebrow {
  text-transform: uppercase;
  letter-spacing: 3px;
  font-size: 12px;
  color: var(--fg-weak);
  margin: 0 0 14px;
}
.handoff-head h2 {
  font: 700 clamp(30px, 3.6vw, 48px)/1.05 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: -1.4px;
  margin: 0 0 16px;
}
.handoff-sub {
  color: var(--fg-muted);
  font-size: 17px;
  line-height: 1.55;
  margin: 0 auto;
  max-width: 540px;
}

/* the shared 3D stage + the CSS iPad */
.ff-scene {
  position: relative;
  width: min(1120px, 94vw);
  height: 600px;
  margin: 0 auto;
  transform-style: preserve-3d;
}
.ff-ipad {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 820px;
  height: 584px;
  margin: -292px 0 0 -410px;
  transform-style: preserve-3d;
  will-change: transform;
}
.ff-ipad-shell {
  position: absolute;
  inset: 0;
  border-radius: 36px;
  background: linear-gradient(150deg, #2a2a31 0%, #101013 50%, #202027 100%);
  box-shadow: 0 0 0 2px #000, 0 1px 0 rgba(255, 255, 255, 0.05) inset, 0 60px 130px rgba(0, 0, 0, 0.62);
  opacity: var(--dev, 0);
}
.ff-ipad-shell::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  background: linear-gradient(150deg, #54545e, #0a0a0c 42%, #43434c 72%, #111114);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}
.ff-ipad-screen {
  position: absolute;
  inset: 16px;
  border-radius: 22px;
  overflow: hidden;
  background-color: var(--bg);
  background-image: radial-gradient(var(--dot) 1px, transparent 1px);
  background-size: 30px 30px;
  opacity: var(--dev, 0);
}
.ff-ipad-cam {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #15151a;
  box-shadow: 0 0 0 1px #2a2a30;
  opacity: var(--dev, 0);
}

/* iPadOS status bar */
.ff-status {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 28px;
  z-index: 6;
  opacity: var(--dev, 0);
}
.ff-time { font: 600 14px/1 "SF Pro Display", system-ui; color: #fff; letter-spacing: 0.2px; }
.ff-sys { display: flex; align-items: center; gap: 8px; color: #fff; }
.ff-wifi { width: 18px; height: 13px; }
.ff-batt {
  width: 24px;
  height: 12px;
  border: 1.4px solid rgba(255, 255, 255, 0.9);
  border-radius: 3px;
  position: relative;
}
.ff-batt::before { content: ""; position: absolute; inset: 1.6px; right: 5px; background: #fff; border-radius: 1px; }
.ff-batt::after { content: ""; position: absolute; right: -3px; top: 3.4px; width: 2px; height: 5px; border-radius: 0 1px 1px 0; background: rgba(255, 255, 255, 0.9); }

/* floating Campus toolbar (glass pill over the canvas) */
.ff-bar {
  position: absolute;
  top: 44px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(18, 18, 24, 0.72);
  border: 1px solid var(--stroke);
  backdrop-filter: blur(16px) saturate(1.1);
  -webkit-backdrop-filter: blur(16px) saturate(1.1);
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.42);
  white-space: nowrap;
  z-index: 6;
  opacity: var(--dev, 0);
}
.ff-logo {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: linear-gradient(150deg, var(--purple), #4f4fc4);
  display: grid;
  place-items: center;
}
.ff-logo svg { width: 15px; height: 15px; color: #fff; }
.ff-room { display: inline-flex; align-items: center; gap: 6px; font: 700 15px/1 "SF Pro Display", system-ui; color: var(--fg); }
.ff-room svg { width: 13px; height: 13px; color: var(--fg-weak); }
.ff-sep { width: 1px; height: 18px; background: var(--stroke); }
.ff-presence { display: flex; padding-left: 7px; }
.ff-presence i {
  width: 25px;
  height: 25px;
  margin-left: -7px;
  border-radius: 50%;
  background: var(--a);
  border: 2px solid #14141a;
  color: #fff;
  font: 700 11px/21px "SF Pro Display", system-ui;
  font-style: normal;
  text-align: center;
}
.ff-zoom { font: 600 13px/1 "SF Mono", Menlo, monospace; color: var(--fg-muted); }

/* iPadOS home indicator */
.ff-home {
  position: absolute;
  bottom: 9px;
  left: 50%;
  transform: translateX(-50%);
  width: 154px;
  height: 5px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.55);
  z-index: 6;
  opacity: var(--dev, 0);
}

/* each tile wrapper is centred in the iPad's 3D frame; device_flyin.js drives
   its transform from a spread "page" pose to a small "on-screen" slot. */
.ff-tile {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 340px;
  transform-origin: center center;
  will-change: transform;
}
.ff-tile .tile { width: 100%; display: flex; flex-direction: column; }
.ff-tile .tile-body { flex: 1; min-height: 0; }
.ff-tile .ff-term { height: 100%; }
.ff-tile .note { overflow: hidden; }

/* tiny static terminal body used inside the flying tiles (no real xterm) */
.ff-term {
  padding: 14px 16px;
  background: #141417;
  font: 20px/1.5 "SF Mono", Menlo, monospace;
  color: #c9d1d9;
  overflow: hidden;
}
.ff-term .ln { white-space: pre; }
.ff-term .pr { color: var(--purple); }
.ff-term .ok { color: var(--green); }
.ff-term .dim { color: var(--fg-weak); }
.ff-term .cur::after {
  content: "▊";
  color: var(--purple);
  animation: ff-blink 1.1s steps(1) infinite;
}
@keyframes ff-blink { 50% { opacity: 0; } }

/* narrow screens: the iPad is a fixed 820px; scale the whole stage to fit */
@media (max-width: 980px) {
  .handoff-pin { perspective: 1150px; }
  .ff-wrap { transform: scale(calc(100vw / 1200)); }
}
@media (prefers-reduced-motion: reduce) {
  .ff-term .cur::after { animation: none; }
}

/* ════════════════════════════ SITE FOOTER ═══════════════════════════════ */
.site-footer {
  position: relative;
  z-index: 10;
  border-top: 1px solid var(--stroke);
  background: rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.footer-top {
  max-width: 1080px;
  margin: 0 auto;
  padding: 72px 32px 48px;
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr;
  gap: 48px;
}
.footer-brand { max-width: 300px; }
.footer-logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
}
.footer-logo img { width: 26px; height: 26px; border-radius: 7px; }
.footer-logo span {
  font: 800 19px/1 "SF Pro Display", system-ui, sans-serif;
  letter-spacing: -0.5px;
  color: var(--fg);
}
.footer-tagline {
  margin: 16px 0 22px;
  color: var(--fg-muted);
  font-size: 13.5px;
  line-height: 1.6;
}
.footer-social { display: flex; gap: 10px; }
.footer-social a {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 9px;
  border: 1px solid var(--stroke);
  background: rgba(255, 255, 255, 0.03);
  color: var(--fg-weak);
  transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.footer-social a:hover {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--purple) 50%, var(--stroke));
  background: rgba(255, 255, 255, 0.06);
}
.footer-social svg { width: 16px; height: 16px; }

.footer-nav { display: contents; }
.footer-col h4 {
  margin: 0 0 16px;
  font: 700 11px/1 "SF Pro Display", system-ui, sans-serif;
  text-transform: uppercase;
  letter-spacing: 1.6px;
  color: var(--fg-weak);
}
.footer-col a {
  display: block;
  margin-bottom: 11px;
  color: var(--fg-muted);
  font-size: 14px;
  text-decoration: none;
  width: max-content;
  transition: color 0.18s ease;
}
.footer-col a:hover { color: var(--fg); }

.footer-bottom {
  max-width: 1080px;
  margin: 0 auto;
  padding: 22px 32px 36px;
  border-top: 1px solid var(--stroke);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
}
.footer-copy { color: var(--fg-weak); font-size: 13px; }
.footer-bottom-meta { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.footer-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--fg-muted);
  font-size: 13px;
}
.footer-status i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 8px color-mix(in srgb, var(--green) 80%, transparent);
}
.footer-mini { display: flex; gap: 16px; }
.footer-mini a {
  color: var(--fg-weak);
  font-size: 13px;
  text-decoration: none;
  transition: color 0.18s ease;
}
.footer-mini a:hover { color: var(--fg); }

@media (max-width: 860px) {
  .footer-top {
    grid-template-columns: 1fr 1fr;
    gap: 36px 24px;
    padding: 56px 24px 40px;
  }
  .footer-brand { grid-column: 1 / -1; max-width: none; }
  .footer-bottom { padding: 22px 24px 32px; }
}
@media (max-width: 520px) {
  .footer-bottom { flex-direction: column; align-items: flex-start; gap: 14px; }
}
