/* sohoai.app. Quiet the way The Row's site is quiet, precise the way Teenage Engineering's is: one
   small typeface, near-black on white, hierarchy from color and space rather than size; the app's
   pieces large on the chat's gray, like an object on a plain ground; tiny technical labels. Served
   by Vercel, the API by the Soho Worker. */

:root {
  --fs: 15px;
  --ink: #1c1b1b;
  --dim: rgba(28, 27, 27, 0.52);
  --hairline: rgba(28, 27, 27, 0.12);
  --edge: clamp(20px, 4vw, 48px);   /* the page's side margin */
  --gap: 72px;                      /* doc pages: under the bar */
  --section: clamp(96px, 12vw, 168px); /* home: between sections */
  --wide: 1180px;                   /* home: the hero and the catalogue */
  --section-gap: 4em;
}
@media (min-width: 1000px) { :root { --fs: 16px; } }

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html {
  background: #fff;
  color-scheme: light;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100dvh;
  color: var(--ink);
  background: #fff;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", "Segoe UI", sans-serif;
  font-size: var(--fs);
  line-height: 1.5;
  letter-spacing: -0.003em;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

p { text-wrap: pretty; margin: 0; }
h1, h2, h3 { font-size: 1em; font-weight: 400; margin: 0; text-wrap: balance; }
ul { margin: 0; padding: 0; list-style: none; }
a { color: inherit; }
img { -webkit-user-drag: none; user-select: none; }
::selection { background: var(--ink); color: #fff; }

/* ---------------------------------------------------------------- the bar
   One quiet line: what it is on the left, the wordmark in the middle, the waitlist on the right. */
.bar {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1em;
  padding: 22px var(--edge); font-size: 13px; line-height: 1;
}
.bar .side { color: var(--dim); }
.bar .side.right { justify-self: end; }
.wordmark { font-size: 17px; letter-spacing: -0.03em; text-decoration: none; color: var(--ink); }
/* The way in, always in reach: the app's primary button (a black pill), small. */
.cta {
  display: inline-block; font-size: 13px; line-height: 1; white-space: nowrap; text-decoration: none;
  color: #fff; background: var(--ink); border-radius: 999px; padding: 9px 14px;
  transition: opacity 0.15s ease;
}
.cta:hover { opacity: 0.85; }



/* ---------------------------------------------------------------- home */
.home { padding-bottom: env(safe-area-inset-bottom); }

.hero-wrap { max-width: var(--wide); margin: clamp(24px, 4vw, 56px) auto 0; padding: 0 var(--edge); }
.hero { display: block; width: 100%; height: auto; }

.lede {
  max-width: 27em; margin: var(--section) auto 0; padding: 0 var(--edge);
  font-size: clamp(19px, 1.6vw, 22px); line-height: 1.4; letter-spacing: -0.012em;
  text-align: center; text-wrap: balance;
}

/* Waitlist: under the statement, centered; the app's buttons (a black pill), smaller. */
.join { max-width: 26em; margin: 40px auto 0; padding: 0 var(--edge); text-align: center; }
.join-label { color: var(--dim); margin-bottom: 16px; }
.join-row { display: flex; gap: 8px; }
.join input[type=email] {
  flex: 1; min-width: 0;
  font: inherit; color: var(--ink);
  padding: 11px 18px;
  border: 1px solid var(--hairline); border-radius: 999px;
  background: #fff; outline: none;
  transition: border-color 0.15s ease;
}
.join input[type=email]:focus { border-color: var(--ink); }
.join button {
  font: inherit; color: #fff; background: var(--ink);
  border: 0; border-radius: 999px; padding: 11px 20px; cursor: pointer;
  transition: opacity 0.15s ease;
}
.join button:hover { opacity: 0.85; }
.join-note { margin-top: 10px; min-height: 1.5em; color: var(--dim); }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

/* Four things it does: a thin pictogram, a line, a quieter line. Grids here always fill their rows. */
.benefits {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 40px;
  max-width: var(--wide); margin: var(--section) auto 0; padding: 0 var(--edge);
}
.glyph { width: 22px; height: 22px; color: var(--ink); }
.benefit .glyph { display: block; margin-bottom: 18px; }
.benefit h2 { margin-bottom: 4px; }
.benefit p { color: var(--dim); }

/* What it does: the pieces first, large, on the chat's gray; a small caption under each. */
.catalogue { max-width: var(--wide); margin: var(--section) auto 0; padding: 0 var(--edge); }
.pieces { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(56px, 7vw, 96px) clamp(24px, 3vw, 40px); }
.piece { margin: 0; }
.piece .shot { display: block; width: 100%; height: auto; max-width: none; }
.piece figcaption { margin-top: 20px; max-width: 30em; }
.piece h3 { margin-bottom: 4px; }
.piece p { color: var(--dim); }

/* New: what shipped lately, a small black pill (Eli, 10/11: "black bg not blue"). */
.new {
  display: inline-block; vertical-align: 0.1em; margin-left: 8px;
  font-size: 11px; line-height: 1; white-space: nowrap;
  color: #fff; background: var(--ink); border-radius: 999px; padding: 0.35em 0.7em;
}

/* Coming soon: one plain sentence (no eyebrow labels, Eli 10/11), then a short list. A feature
   moves up into the catalogue when it ships. */
.soon-list { max-width: var(--wide); margin: var(--section) auto 0; padding: 0 var(--edge); text-align: center; }
.soon-list ul {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 40px clamp(24px, 3vw, 40px);
  margin-top: 48px; text-align: left;
}
.soon-list li { padding-top: 16px; border-top: 1px solid var(--hairline); }
.soon-list h3 { margin-bottom: 4px; }
.soon-note { color: var(--dim); }
.soon-list li p { color: var(--dim); }

/* The footer: a hairline, then small links and the company. */
.foot {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 24px;
  /* The hairline spans the content column, not the margins around it. */
  width: calc(100% - 2 * var(--edge)); max-width: calc(var(--wide) - 2 * var(--edge));
  margin: var(--section) auto 0; padding: 22px 0 40px;
  border-top: 1px solid var(--hairline); font-size: 13px; color: var(--dim);
}
.foot a { text-decoration: none; }
.foot a:hover { color: var(--ink); }
.foot span { margin-left: auto; }

@media (max-width: 760px) {
  .bar .side:not(.right) { visibility: hidden; }
  .pieces { grid-template-columns: 1fr; }
  .benefits { grid-template-columns: 1fr; gap: 28px; }
  .benefit { display: grid; grid-template-columns: 22px 1fr; column-gap: 16px; }
  .benefit .glyph { grid-row: span 2; margin: 1px 0 0; }
  .soon-list ul { grid-template-columns: 1fr; gap: 28px; }
  .foot { justify-content: center; }
  .foot span { flex-basis: 100%; margin-left: 0; text-align: center; }
}
@media (min-width: 761px) and (max-width: 1000px) {
  .soon-list ul, .benefits { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------------------------------------------------------------- the pieces, played
   scenes.js: a square of the chat's gray, its parts arriving in turn. Sizes are in the app's points:
   the square is 560 of them, so 1pt = 100cqw / 560. */
.scene {
  position: relative; width: 100%; aspect-ratio: 1; overflow: hidden;
  border-radius: 4.2857%; background: #f3f3f3 no-repeat 0 0 / 100% 100%; container-type: inline-size;
}
.scene .part { position: absolute; background-repeat: no-repeat; }
.scene .ground { background: #fff; }
.scene.armed .part { opacity: 0; }
.scene .typing {
  position: absolute; right: 4%; display: flex; align-items: center; gap: calc(12cqw / 5.6);
  font-size: calc(13cqw / 5.6); line-height: 1; white-space: nowrap; letter-spacing: 0;
}
.scene .dots {
  flex: none; display: flex; align-items: center; gap: calc(5cqw / 5.6);
  height: calc(36cqw / 5.6); padding: 0 calc(14cqw / 5.6); border-radius: calc(18cqw / 5.6); background: #fff;
}
.scene .dots i { width: calc(7cqw / 5.6); height: calc(7cqw / 5.6); border-radius: 50%; background: #000; opacity: 0.25; animation: dot 0.6s ease-in-out infinite alternate; }
.scene .dots i:nth-child(2) { animation-delay: 0.18s; }
.scene .dots i:nth-child(3) { animation-delay: 0.36s; }
@keyframes dot { to { opacity: 0.9; } }
/* The status line, with the app's shimmer: a darker band moving left to right every 1.8 s. */
.scene .status { position: relative; flex: 1; min-width: 0; height: 1.3em; }
.scene .line {
  position: absolute; left: 0; top: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; line-height: 1.3;
  color: rgba(60, 60, 67, 0.6);
  background: linear-gradient(90deg, rgba(60, 60, 67, 0.45) 0%, rgba(60, 60, 67, 0.45) 35%, #000 50%, rgba(60, 60, 67, 0.45) 65%, rgba(60, 60, 67, 0.45) 100%) 100% 0 / 300% 100%;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  animation: shimmer 1.8s linear infinite;
}
@keyframes shimmer { to { background-position: 0 0; } }

/* ---------------------------------------------------------------- other pages
   Privacy, Terms, the invite page and 404: one readable column under the same bar. */
.page {
  max-width: 36em;
  margin: 0 auto;
  padding: 0 var(--edge) calc(var(--section-gap) + env(safe-area-inset-bottom));
}
.page .bar { padding-left: 0; padding-right: 0; margin-bottom: var(--gap); }
.page .bar .side:not(.right) { display: none; }
.page .bar { grid-template-columns: auto 1fr; }
.page footer { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: var(--section-gap); padding-top: 22px; border-top: 1px solid var(--hairline); font-size: 13px; color: var(--dim); }
.page footer a { text-decoration: none; }
.page footer a:hover { color: var(--ink); }

/* Buttons, as in the app: primary a black pill, secondary clear with a hairline. */
.btn {
  display: inline-block; font: inherit; line-height: 1.2; text-decoration: none; text-align: center; cursor: pointer;
  border-radius: 999px; padding: 0.6em 1.2em; border: 1px solid transparent;
}
.btn.primary { color: #fff; background: var(--ink); }
.btn.secondary { color: var(--ink); background: rgba(255, 255, 255, 0.6); border-color: var(--hairline); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
.btn.secondary:hover { border-color: rgba(28, 27, 27, 0.3); }

/* The invite page (/i/<code>). */
.dim { color: var(--dim); }
.about { margin-bottom: 1.5em; }
.invite-title { margin-bottom: 1em; }
.invite .join { margin: 2em 0 var(--section-gap); padding: 0; text-align: left; max-width: none; }
.steps { list-style: none; counter-reset: step; padding: 0; margin: 2.5em 0 var(--section-gap); display: grid; gap: 2.5em; }
.steps li { counter-increment: step; position: relative; padding-left: 2.5em; display: flex; flex-direction: column; align-items: flex-start; gap: 0.6em; }
.steps li::before { content: counter(step); color: var(--dim); position: absolute; left: 0; top: 0; }
.code-row { display: flex; align-items: center; gap: 0.8em; margin: 0.4em 0 0.2em; }
.code { font-family: ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: 0.08em; font-size: 1.1em; user-select: all; }

/* Legal pages */
.doc h1 { margin-bottom: 0.3em; }
.doc .updated { color: var(--dim); margin-bottom: 2.5em; }
.doc h2 { margin: 2em 0 0.6em; }
.doc p, .doc li { color: rgba(28, 27, 27, 0.8); }
.doc p + p { margin-top: 0.8em; }
.doc ul { padding-left: 1.1em; margin: 0.6em 0 0; list-style: disc; }
.doc li + li { margin-top: 0.4em; }
.doc ul + p { margin-top: 0.8em; }

@media (max-width: 600px) {
  :root { --gap: 48px; }
}

@media (prefers-reduced-motion: no-preference) {
  .hero { animation: rise 0.8s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
  @keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
}
