/* Geni, for the people who would embed it.
   Dark because the brand is; Apple's grammar because the page is a walk past
   capabilities and that is the form that walk takes. Tokens first, and every
   colour in the file comes from one. */

:root{
  /* Sampled across the logo file itself, not read off a swatch row.
     The mark is not one value: it runs from a warm greige at #B0A69E up to
     highlights at #F1EBE3, and its warmth is constant — red sits 16 to 18
     above blue everywhere on it. That is the platinum cast, and it is why a
     flat #EBEBE8 read as a different brand. Type is made of the same metal. */
  --void:#090A0C;
  --metal-hi:#F1EBE3;                  /* the chalk where it catches light */
  --metal-mid:#B8AFA6;                 /* its body */
  --metal-lo:#A0978F;                  /* where it thins out */
  --ink:#F1EBE3;
  --ink-head:#C8C1B7;                  /* fallback for the clipped gradient */
  --ink-dim:rgba(226,220,210,.60);
  --ink-mute:rgba(226,220,210,.50);
  --ink-faint:rgba(226,220,210,.40);
  --hair:rgba(226,220,210,.09);
  --glass:rgba(226,220,210,.035);
  --shell:1160px;
  /* One easing for everything, so nothing on the page snaps. */
  --ease:cubic-bezier(.22,.61,.36,1);
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

@font-face{font-family:Satoshi;src:url(fonts/satoshi-300.woff2) format('woff2');font-weight:300;font-display:swap}
@font-face{font-family:Satoshi;src:url(fonts/satoshi-400.woff2) format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:Satoshi;src:url(fonts/satoshi-500.woff2) format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:Satoshi;src:url(fonts/satoshi-700.woff2) format('woff2');font-weight:700;font-display:swap}

/* One ground for the whole page.
   Sections used to alternate between two flat colours, which drew a hard line
   across the page at every boundary — the seam the eye lands on instead of the
   words. This is a single gradient the height of the document, moving a couple
   of semitones and back. Every section still sits on its own tone; none of
   them has an edge. */
body{
  margin:0;color:var(--ink-dim);
  background:linear-gradient(180deg,
    #090A0C 0%, #0C0E12 14%, #0A0B0E 26%, #10121A 40%,
    #0B0C10 54%, #0E1016 68%, #090A0D 82%, #0C0E13 100%);
  background-attachment:scroll;
  font:400 18px/1.62 Satoshi,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;min-height:100%;
}

/* Film grain over the whole page. The Cactus Jack half of the brief: it is what
   stops a flat near-black from reading as an empty div. */
body::after{
  content:"";position:fixed;inset:-50%;z-index:9999;pointer-events:none;opacity:.038;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grain 7s steps(6) infinite;
}
@keyframes grain{
  0%,100%{transform:translate(0,0)} 16%{transform:translate(-3%,2%)}
  33%{transform:translate(2%,-3%)} 50%{transform:translate(-2%,-2%)}
  66%{transform:translate(3%,1%)}  83%{transform:translate(-1%,3%)}
}
@media (prefers-reduced-motion:reduce){body::after{animation:none}}

.shell{width:min(100% - 48px,var(--shell));margin-inline:auto}

/* ── type ─────────────────────────────────────────────────────────────── */
h1,h2,h3{margin:0;font-weight:700;letter-spacing:-.035em;line-height:1.03;text-wrap:balance;
  color:var(--ink-head)}

/* Platinum rather than paint. The board's type is not one flat value: it
   catches light down its height and carries the same grain as everything else
   on it. A gradient and a noise tile clipped to the glyphs give both, and the
   plain colour above stays as the fallback wherever clipping is unsupported. */
@supports (-webkit-background-clip:text) or (background-clip:text){
  h1,h2{
    /* The background is painted across the element's box and then clipped to
       the glyphs, so anything hanging below that box — the tail of a g, y or p
       at a 1.03 line height — is clipped away with it. The padding gives the
       tails somewhere to be painted; the negative margin gives the space back
       to the layout. */
    padding-bottom:.16em;margin-bottom:-.16em;
    background-image:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='t'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.1' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23t)' opacity='.16'/%3E%3C/svg%3E"),
      linear-gradient(168deg,var(--metal-hi) 0%,#D5CEC4 26%,var(--metal-mid) 58%,#CFC8BE 84%,#EDE7DF 100%);
    -webkit-background-clip:text;background-clip:text;
    color:transparent;-webkit-text-fill-color:transparent;
  }
}
h1{font-size:clamp(2.6rem,5.2vw,4.5rem)}
h2{font-size:clamp(2.1rem,4.8vw,3.7rem)}
h3{font-size:1.28rem;letter-spacing:-.02em;line-height:1.25}
p{margin:0}
.lede{font-size:clamp(1.05rem,1.5vw,1.32rem);line-height:1.55;color:var(--ink-dim);max-width:47ch}
.label{
  font-size:.7rem;font-weight:500;letter-spacing:.3em;text-transform:uppercase;
  color:var(--ink-faint);margin:0 0 1.6rem
}
.note{font-size:.9rem;line-height:1.55;color:var(--ink-mute);max-width:52ch}
.num{font-variant-numeric:tabular-nums}

/* ── sections ─────────────────────────────────────────────────────────── */
section{padding:clamp(60px,6.4vw,92px) 0;position:relative}
/* `.band` no longer paints. Kept as a hook, and as the record of what
   the alternating slabs used to be. */
.stack{display:grid;gap:1.5rem;max-width:56ch}
.wide{display:grid;gap:clamp(2.2rem,4vw,3.6rem);grid-template-columns:1fr;align-items:center}
@media (min-width:900px){.wide{grid-template-columns:1fr 1fr}}

/* ── glass ────────────────────────────────────────────────────────────── */
.glass{
  background:var(--glass);border:1px solid var(--hair);border-radius:22px;
  backdrop-filter:blur(26px) saturate(1.25);-webkit-backdrop-filter:blur(26px) saturate(1.25);
  position:relative;overflow:hidden
}
/* The lit top edge that makes a panel read as glass rather than as a grey box. */
.glass::before{
  content:"";position:absolute;inset:0 0 auto;height:1px;
  background:linear-gradient(90deg,transparent,rgba(235,235,232,.34),transparent)
}

/* ── buttons ──────────────────────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;gap:.6rem;border-radius:999px;
  padding:.82rem 1.5rem;font-size:.96rem;font-weight:500;text-decoration:none;
  transition:transform .4s var(--ease),background .4s var(--ease),border-color .4s var(--ease)
}
.btn-primary{background:var(--ink);color:var(--void)}
.btn-primary:hover{transform:translateY(-2px)}
.btn-ghost{color:var(--ink);border:1px solid rgba(235,235,232,.24)}
.btn-ghost:hover{border-color:rgba(235,235,232,.5);transform:translateY(-2px)}
.btn .arw{transition:transform .4s var(--ease)}
.btn:hover .arw{transform:translateX(4px)}
.cta-row{display:flex;flex-wrap:wrap;gap:.85rem;margin-top:.6rem}

/* ── nav ──────────────────────────────────────────────────────────────── */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:100;
  display:flex;align-items:center;justify-content:space-between;
  padding:1rem 0;transition:background .5s var(--ease),backdrop-filter .5s var(--ease)
}
.nav.stuck{background:rgba(8,11,13,.72);backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px)}
.nav .shell{display:flex;align-items:center;justify-content:space-between;gap:2rem}
.nav-mark{display:flex;align-items:center;gap:.6rem;text-decoration:none;color:var(--ink)}
.nav-mark svg,.nav-mark object{width:20px;height:20px;display:block}
.wordmark{font-size:.9rem;font-weight:500;letter-spacing:.42em}
.nav-links{display:none;gap:2rem}
@media (min-width:860px){.nav-links{display:flex}}
.nav-links a{color:var(--ink-dim);text-decoration:none;font-size:.88rem;transition:color .3s var(--ease)}
.nav-links a:hover{color:var(--ink)}

/* ── hero ─────────────────────────────────────────────────────────────── */
.hero{min-height:100svh;display:grid;align-items:center;padding-top:96px}
.hero .shell{display:grid;gap:clamp(2.5rem,6vw,5rem);grid-template-columns:1fr;align-items:center}
.hero .stack{max-width:none}
@media (min-width:980px){.hero .shell{grid-template-columns:1.25fr .75fr}}
.hero-mark{justify-self:center;width:min(78vw,340px)}
/* The portal's glow. Sits behind the mark, breathes, and is the only light
   source on the first screen. */
.hero-mark-wrap{position:relative;display:grid;place-items:center}
.hero-mark-wrap::before{
  content:"";position:absolute;width:120%;aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle,rgba(235,235,232,.20),rgba(235,235,232,.05) 45%,transparent 68%);
  filter:blur(44px);animation:breathe 7s var(--ease) infinite
}
@keyframes breathe{0%,100%{opacity:.5;transform:scale(.94)}50%{opacity:1;transform:scale(1.06)}}
@media (prefers-reduced-motion:reduce){.hero-mark-wrap::before{animation:none}}

/* ── the slip demonstration ───────────────────────────────────────────── */
.slip{padding:1.6rem;display:grid;gap:1.1rem}
.slip-said{
  align-self:end;justify-self:end;max-width:82%;padding:.7rem 1rem;border-radius:16px 16px 4px 16px;
  background:rgba(235,235,232,.09);font-size:.94rem
}
.leg{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;padding:.72rem 0;border-top:1px solid var(--hair)}
.leg-what{display:grid;gap:.12rem}
.leg-mk{font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-faint)}
.leg-price{font-weight:500;font-variant-numeric:tabular-nums}
.slip-total{display:flex;justify-content:space-between;align-items:baseline;padding-top:.9rem;border-top:1px solid rgba(235,235,232,.2)}
.slip-total b{font-size:1.7rem;font-weight:700;letter-spacing:-.02em;font-variant-numeric:tabular-nums}

/* ── figures ──────────────────────────────────────────────────────────── */
.figs{display:grid;gap:1px;background:var(--hair);border:1px solid var(--hair);border-radius:20px;overflow:hidden;margin-top:.6rem}
@media (min-width:680px){.figs{grid-template-columns:repeat(3,1fr)}}
.fig{background:rgba(9,10,12,.55);padding:1.7rem 1.4rem;display:grid;gap:.3rem}

.fig b{font-size:clamp(2rem,3.6vw,2.9rem);font-weight:700;letter-spacing:-.04em;line-height:1;font-variant-numeric:tabular-nums}
/* The same measurement as the one beside it, shown as the count it came from.
   Two identical percentages read as a mistake, and rounding one of them to
   make them differ would be the same number wearing two precisions. This is
   84 out of 86 either way, and the denominator earns its place: it tells a
   technical reader how big the benchmark was without a footnote. */
.fig .of{
  /* The tight tracking on these numerals closes any gap a bare slash needs,
     so "84/86" set itself as 8486. A word cannot collapse. */
  font-size:.44em;font-weight:400;opacity:.5;letter-spacing:.04em;
  margin:0 .3em;vertical-align:.14em
}
.fig span{font-size:.86rem;color:var(--ink-mute);line-height:1.45}

/* ── chips ────────────────────────────────────────────────────────────── */
.chips{display:flex;flex-wrap:wrap;gap:.5rem}
.chip{
  padding:.42rem .95rem;border:1px solid var(--hair);border-radius:999px;
  font-size:.83rem;color:var(--ink-dim);letter-spacing:.05em;
  transition:border-color .4s var(--ease),color .4s var(--ease)
}
.chip:hover{border-color:rgba(235,235,232,.34);color:var(--ink)}

/* ── code ─────────────────────────────────────────────────────────────── */
.code{
  padding:1.3rem 1.4rem;font:400 .82rem/1.75 ui-monospace,SFMono-Regular,Menlo,monospace;
  color:var(--ink-dim);overflow-x:auto;white-space:pre;-webkit-overflow-scrolling:touch
}
.code i{color:var(--ink);font-style:normal}

/* ── quote ────────────────────────────────────────────────────────────── */
.said{padding:1.5rem 1.7rem;display:grid;gap:.8rem}
.said-q{font-size:.92rem;color:var(--ink-faint)}
.said-a{font-size:clamp(1.1rem,2vw,1.45rem);line-height:1.4;letter-spacing:-.015em}

/* ── footer ───────────────────────────────────────────────────────────── */
footer{padding:4rem 0 3rem;border-top:1px solid var(--hair);color:var(--ink-faint);font-size:.85rem}
footer .shell{display:flex;flex-wrap:wrap;gap:1.2rem;justify-content:space-between;align-items:center}
footer a{color:var(--ink-dim);text-decoration:none}
footer a:hover{color:var(--ink)}

/* ── the seam between sections ────────────────────────────────────────────
   With the alternating slabs gone there was nothing at all between one screen
   and the next, and the vertical space read as an accident rather than as a
   rest. A hairline that fades out at both ends and carries the mark's own
   ellipse at its middle: enough to say a section ended, far too quiet to be a
   rule across the page. */
.seam{height:1px;margin:0 auto;width:min(100% - 48px,var(--shell));
  background:linear-gradient(90deg,transparent,var(--hair) 22%,var(--hair) 78%,transparent)}


/* Sections that are one column of writing had a whole empty half beside them.
   The mark goes there, very quiet, large, cropped by the section — a watermark
   rather than a second logo. */
.solo{position:relative;overflow:hidden}
/* Scenery, along the bottom of a section rather than beside its writing.
   The first attempt put a sketch in the empty half next to the copy, which
   put it in the reader's text column at picture size — the user's words, and
   they were right. These sit on the floor of the section instead, wide and
   shallow, a horizon under the content. Nothing shares a line with a
   sentence, and the space they fill is the space that was doing nothing.

   Not one place, either: a sea with birds over it, a sun on rolling hills,
   saguaro, mesas, dunes with a lone tree, cracked ground, peaks. One per
   section, none repeated. The mark comes back for the last one, where a
   closing signature is the point. */
/* Room under the writing for the scenery to stand in. Without it a short
   section pushes its horizon up into the last paragraph, which is the same
   complaint as before in a different place. */
.scene{position:relative;overflow:hidden;padding-bottom:clamp(180px,17vw,270px)}
.scene .wm{
  position:absolute;left:0;right:0;bottom:0;
  opacity:.15;pointer-events:none;user-select:none;z-index:0
}
.scene .wm svg{width:100%;height:auto;display:block}
.scene .wm path,.scene .wm circle{
  fill:none;stroke:var(--ink);stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;
  filter:url(#j-pencil);vector-effect:non-scaling-stroke
}
/* The signature at the end keeps its old corner: it is a mark, not a place. */
.scene .wm-mark{
  left:auto;right:2%;bottom:auto;top:50%;translate:0 -50%;
  width:min(30vw,330px);opacity:.06
}
.scene .wm-mark object{width:100%;height:auto;display:block}

/* Content sits over the scenery, never under it. */
.scene .shell{position:relative;z-index:1}

@media (max-width:900px){
  .scene .wm{opacity:.1}
  .scene .wm-mark{width:56vw;right:-8%;opacity:.05}
}

/* ── arrival ──────────────────────────────────────────────────────────────
   A card arrives whole: it is one object and cutting it into pieces would be
   a shuffle, not an entrance. */
.rise{opacity:0;transform:translateY(26px);transition:opacity .9s var(--ease),transform .9s var(--ease)}
.rise.in{opacity:1;transform:none}

/* A block of writing does not. Moving label, heading and paragraphs as one
   slab reads as a finished thing being placed rather than as words arriving,
   so the children come in one after another. Six steps of 85ms is under half a
   second end to end — enough to feel like a sequence, not enough to wait on.

   The parent stops moving when it stages its children, or everything travels
   twice and the whole block drifts. */
.stack.rise{transform:none;opacity:1;transition:none}
.stack.rise > *{
  opacity:0;transform:translateY(20px);
  transition:opacity .82s var(--ease),transform .82s var(--ease)
}
.stack.rise.in > *{opacity:1;transform:none}
.stack.rise.in > :nth-child(1){transition-delay:0ms}
.stack.rise.in > :nth-child(2){transition-delay:85ms}
.stack.rise.in > :nth-child(3){transition-delay:170ms}
.stack.rise.in > :nth-child(4){transition-delay:255ms}
.stack.rise.in > :nth-child(5){transition-delay:340ms}
.stack.rise.in > :nth-child(6){transition-delay:425ms}

/* The hero is on screen at load, so its arrival competes with the mark's.
   Held back until the ring has opened. */
.hero .stack.rise.in > :nth-child(1){transition-delay:220ms}
.hero .stack.rise.in > :nth-child(2){transition-delay:320ms}
.hero .stack.rise.in > :nth-child(3){transition-delay:440ms}
.hero .stack.rise.in > :nth-child(4){transition-delay:560ms}

@media (prefers-reduced-motion:reduce){
  .rise,.stack.rise > *{opacity:1;transform:none;transition:none}
}

:focus-visible{outline:2px solid var(--ink);outline-offset:3px;border-radius:4px}

/* ── phones ───────────────────────────────────────────────────────────────
   Half the people who get this link will open it on a phone, so this is not a
   fallback. Three things change and the rest holds.

   The mark goes first. Stacked, the grid put it under the buttons, which
   buries the strongest thing on the page under a scroll nobody owes us. It is
   also the fastest way to say what this is before a word is read. */
@media (max-width:760px){
  h1{font-size:clamp(2.05rem,8.4vw,3rem)}
  h2{font-size:clamp(1.75rem,7vw,2.4rem)}
  .lede{font-size:1.02rem}

  .hero{min-height:auto;padding-top:84px;padding-bottom:clamp(56px,12vw,96px)}
  .hero .shell{gap:2.2rem}
  .hero-mark-wrap{order:-1}
  .hero-mark{width:min(46vw,190px)}

  /* A full-size pill beside a wordmark eats the header on a narrow screen. */
  .nav .btn{padding:.6rem 1.05rem;font-size:.86rem}
  .nav{padding:.7rem 0}

  /* Stacked buttons want the full measure rather than hugging their label. */
  .cta-row{gap:.7rem}
  .cta-row .btn{justify-content:center;flex:1 1 100%}

  section{padding:clamp(64px,15vw,92px) 0}
  .code{font-size:.74rem;padding:1.1rem}
  .fig{padding:1.3rem 1.15rem}
  footer .shell{gap:.9rem;justify-content:flex-start}
}


/* ── the journey ──────────────────────────────────────────────────────────
   The stem of the mark leaves the ring and travels down the page as the
   reader does, laying a trail of sand behind it. Absolutely positioned over
   the document and underneath everything, so it can cross a heading without
   ever being in the way of one. */
.journey{
  position:absolute;top:0;left:0;width:100%;z-index:0;pointer-events:none;
  overflow:visible
}
.nav,.hero,section,footer,.seam{position:relative;z-index:1}
.nav{z-index:100}

/* The path is measured, never drawn. A line down the page announced the
   machinery and the reader does not need to see the rails — what should be
   visible is sand, and only just behind the funnel. Both paths stay in the
   document because `getPointAtLength` needs a real element to ask. */
#j-laid,#j-spark{stroke:none;fill:none}
/* Rebuilt every frame rather than moved, so the funnel bends along the path
   and the grit behind it is wherever the path was. */
#j-blade{opacity:0}
#j-funnel{fill:none;stroke:var(--metal-hi);stroke-linecap:round;
  filter:drop-shadow(0 0 6px rgba(226,214,186,.32))}
#j-grit circle{fill:#E4D9C4}

@media (prefers-reduced-motion:reduce){.journey{display:none}}


