/* ==========================================================================
   Home page — Customers & Email AI.

   The page has exactly two orchestrated moments: one email being read in the
   hero, and the chorus of subject lines sorting itself. Everything else holds
   still. In both cases the finished state is the default state, so a visitor
   with reduced motion or no JavaScript arrives at the end, not at nothing.
   ========================================================================== */

/* ---------- Hero ---------------------------------------------------------
   Email AI is the product, so the hero is the product: a working mailbox at
   full width, and the three things one message turns into underneath it.
   Every label here exists in the real app — Compose, Weekly summary, Inbox,
   AI Summary, Save to Voyage → Create New Voyage / Choose Existing Voyage.
   ------------------------------------------------------------------------ */

.hero {
  position: relative;
  padding-bottom: var(--s-10);
  background: var(--surface-warm);
}

/* The photograph belongs to the sentence, not to the whole hero: it runs from
   the top of the page to the moment the mailbox begins, and stops there. */
.hero__band {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding-block: var(--section-y) var(--s-9);
  background: var(--surface-ink);
}

/* The band's proportions decide how much of the photograph survives `cover`:
   at 2.4:1 it keeps 62% of the frame, at 1.9:1 it keeps 80%. So the band is
   given a floor height and the text centres inside it — the extra height is
   not padding, it is picture. */
@media (min-width: 900px) {
  .hero__band {
    display: flex;
    align-items: center;
    min-height: 780px;
  }
  .hero__band > .shell { width: 100%; }
}

/* Shown whole: `cover` at centre, no zoom, so the frame gives up as little of
   itself as the band's proportions allow. The band is deliberately tall for
   the same reason — a shallower strip would crop more of the picture away. */
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-size: cover;
  background-repeat: no-repeat;
  filter: saturate(0.78) contrast(1.03) brightness(0.94);
}

.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      180deg,
      rgba(11, 36, 57, 0.82) 0%,
      rgba(11, 36, 57, 0.72) 45%,
      rgba(11, 36, 57, 0.6) 100%
    ),
    linear-gradient(0deg, rgba(50, 33, 26, 0.2), rgba(50, 33, 26, 0.2));
}

.hero__band h1 { color: #fff; }
.hero__band .lead { color: rgba(255, 255, 255, 0.93); }
.hero__band .eyebrow { color: rgba(255, 255, 255, 0.78); }

.hero__band .btn--secondary {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.42);
  color: #fff;
}

.hero__band .btn--secondary:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: #fff;
}

/* The mailbox now sits on warm ground rather than inside the band, so it needs
   its own air above it. */
.hero .wsp { margin-top: calc(-1 * var(--s-8)); }

.hero__head { display: grid; gap: var(--s-6); }

@media (min-width: 1000px) {
  /* `end` pushed the left column down 48px, and the hole it opened above the
     headline was the "empty hero" — not a missing picture. Both columns now
     start on the same line. */
  .hero__head { grid-template-columns: 1.1fr 1fr; gap: var(--s-10); align-items: start; }
}

/* The only h1 on the site that has to hold an 1112px field on its own, so it
   gets its own step rather than borrowing the shared display size. */
.hero__head h1 {
  margin-top: var(--s-5);
  max-width: 14ch;
  font-size: clamp(2.75rem, 1.4rem + 4.6vw, 4.75rem);
}
.hero__aside { display: flex; flex-direction: column; align-items: flex-start; }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-6); }

/* ---------- The workspace ------------------------------------------------ */

.wsp { position: relative; }

.wsp__app {
  display: grid;
  min-width: 0;
  border-radius: var(--r-media);
  background: var(--surface-white);
  border: 1px solid var(--hairline);
  box-shadow: var(--shadow-float);
}

@media (min-width: 900px) {
  .wsp__app { grid-template-columns: 186px 268px 1fr; }
}

@media (min-width: 1200px) {
  .wsp__app { grid-template-columns: 200px 310px 1fr; }
}

/* Sidebar ---------------------------------------------------------------- */

.wsp__side {
  display: none;
  padding: var(--s-4);
  background: var(--surface-warm-hover);
  border-right: 1px solid var(--hairline);
  /* The app no longer clips, so the tinted sidebar rounds its own corners. */
  border-radius: var(--r-media) 0 0 var(--r-media);
}

@media (min-width: 900px) { .wsp__side { display: block; } }

.wsp__compose {
  display: block;
  width: 100%;
  padding: 9px;
  border-radius: 9px;
  background: var(--brand-700);
  color: #fff;
  text-align: center;
  font-size: var(--t-caption);
  font-weight: 500;
}

.wsp__weekly {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  margin-top: var(--s-2);
  padding: 8px 10px;
  border-radius: 9px;
  background: var(--warm-100);
  color: var(--warm-700);
  font-size: var(--t-caption);
  font-weight: 500;
}

.wsp__folders { margin-top: var(--s-5); display: flex; flex-direction: column; gap: 1px; }

.wsp__folder {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: var(--t-caption);
  color: var(--ink-600);
}

.wsp__folder b { margin-left: auto; font-weight: 500; color: var(--ink-400); }

/* The active folder keeps the left rail the real app uses. */
.wsp__folder--on {
  background: var(--warm-100);
  color: var(--warm-700);
  font-weight: 500;
  border-left: 3px solid var(--warm-500);
  border-radius: 0 8px 8px 0;
  padding-left: 7px;
}

.wsp__folder--on b { color: var(--warm-700); }

.wsp__catlabel {
  display: block;
  margin: var(--s-5) 0 var(--s-2) 10px;
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--ink-400);
}

.wsp__cat {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 10px;
  font-size: var(--t-caption);
  color: var(--ink-600);
}

.wsp__cat i { width: 9px; height: 9px; border-radius: 3px; background: var(--c); flex: none; }
.wsp__cat b { margin-left: auto; font-weight: 400; color: var(--ink-400); }

/* Message list ------------------------------------------------------------ */

.wsp__list { min-width: 0; border-right: 1px solid var(--hairline); }

.wsp__row {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 2px var(--s-3);
  padding: var(--s-4);
  border-bottom: 1px solid var(--hairline);
  cursor: default;
  transition: background-color 420ms var(--ease), box-shadow 420ms var(--ease);
}

.wsp__from {
  min-width: 0;
  font-size: var(--t-caption);
  font-weight: 600;
  color: var(--ink-900);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wsp__when { font-size: 11px; color: var(--ink-400); }
.wsp__subj {
  grid-column: 1 / -1;
  min-width: 0;
  font-size: var(--t-caption);
  color: var(--ink-600);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* On a phone the list is a taste, not the whole inbox: six rows plus the
   reading pane would push the hero past two screens. */
@media (max-width: 899px) {
  .wsp__list .wsp__row:nth-child(n + 4) { display: none; }
}

/* The label rides on the first line beside the timestamp, the way a Gmail
   label does — not on a line of its own under the subject. The coloured dot is
   gone: the tinted pill already carries the colour, and the row is tight. */
.wsp__pill {
  justify-self: end;
  align-self: center;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--tint);
  color: var(--ink);
  font-size: 10.5px;
  font-weight: 500;
  white-space: nowrap;
}

/* Selected row: the app marks it with the accent rail, so the picture does. */
.wsp__list .wsp__row:first-child { border-radius: 0; }
/* The list is shorter than the reading pane, so the last divider would hang
   in empty space. */
.wsp__list .wsp__row:last-child { border-bottom: none; }
.wsp__row--on { background: var(--warm-100); box-shadow: inset 3px 0 0 0 var(--warm-500); }
.anim .wsp:not(.is-picked) .wsp__row--on { background: transparent; box-shadow: inset 3px 0 0 0 transparent; }

/* Reading pane ------------------------------------------------------------ */

.wsp__read { min-width: 0; padding: var(--s-5); display: flex; flex-direction: column; gap: var(--s-4); }

.wsp__readhead {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: var(--s-3);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--hairline);
}

.wsp__avatar {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--r-pill);
  display: grid;
  place-items: center;
  background: var(--warm-100);
  color: var(--warm-700);
  font-size: 11px;
  font-weight: 600;
}

/* The address is one unbreakable token, so without this the header sets the
   app's min-content width and pushes the whole page sideways on a phone. */
.wsp__who {
  min-width: 0;
  font-size: var(--t-caption);
  color: var(--ink-400);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.wsp__who b {
  display: block;
  font-size: var(--t-ui);
  font-weight: 600;
  color: var(--ink-900);
  overflow: hidden;
  text-overflow: ellipsis;
}

.wsp__tools { flex: none; margin-left: auto; display: flex; gap: var(--s-2); color: var(--ink-400); }
.wsp__tools span {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: var(--surface-warm);
  color: var(--ink-400);
}

.wsp__subject { font-size: var(--t-h4); font-weight: 600; color: var(--ink-900); overflow-wrap: anywhere; }
.wsp__body { font-size: var(--t-ui); line-height: 1.7; color: var(--ink-600); }
.wsp__body p { margin: 0 0 var(--s-2); }
.wsp__body p:last-child { margin: 0; }

/* ---------- The step that was missing: classification ---------------------
   A message lands with nothing on it. The product's first act is to read it
   and decide which of the customer's own categories it belongs to. Everything
   after — the summary, the voyage, the tracked container — depends on that,
   so it gets its own beat rather than arriving pre-labelled.
   ------------------------------------------------------------------------ */

.wsp__classify {
  position: relative;
  min-height: 26px;
  margin-top: var(--s-2);
}

.wsp__cstate {
  position: absolute;
  left: 0;
  top: 0;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--t-caption);
  font-weight: 500;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(3px);
  transition: opacity 300ms var(--ease), transform 300ms var(--ease-land);
}

.wsp__cstate--none { color: var(--ink-400); }
.wsp__cstate--reading { color: var(--warm-700); }
.wsp__cstate--done { color: var(--ink-600); }

/* Only one of the three shows at a time; the finished one is the default. */
.wsp__cstate--done { opacity: 1; transform: none; }

.anim .wsp:not(.is-classified) .wsp__cstate--done { opacity: 0; transform: translateY(3px); }
.anim .wsp:not(.is-reading) .wsp__cstate--none { opacity: 1; transform: none; }
.anim .wsp.is-reading:not(.is-classified) .wsp__cstate--reading { opacity: 1; transform: none; }

/* Three dots that actually run while it is reading. */
.wsp__dots { display: inline-flex; gap: 3px; }

.wsp__dots i {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--warm-500);
  opacity: 0.35;
}

.anim .wsp.is-reading:not(.is-classified) .wsp__dots i { animation: cdot 900ms ease-in-out infinite; }
.wsp__dots i:nth-child(2) { animation-delay: 150ms; }
.wsp__dots i:nth-child(3) { animation-delay: 300ms; }

@keyframes cdot {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 1; }
}

/* The read itself: a line passing down the message. */
.wsp__sweep {
  position: absolute;
  left: var(--s-5);
  right: var(--s-5);
  top: 0;
  height: 2px;
  border-radius: 1px;
  background: linear-gradient(90deg, transparent, var(--warm-500), transparent);
  opacity: 0;
  pointer-events: none;
}

.wsp__body { position: relative; }

.anim .wsp.is-reading:not(.is-classified) .wsp__sweep {
  animation: csweep 1100ms ease-in-out infinite;
}

@keyframes csweep {
  0% { top: 6px; opacity: 0; }
  15% { opacity: 0.9; }
  85% { opacity: 0.9; }
  100% { top: calc(100% - 8px); opacity: 0; }
}

/* Before the reader decides, the row simply has no label — an empty slot says
   "not filed yet" more honestly than a word standing in for one. The detail
   pane carries the wording. */
.wsp__pill--set { opacity: 1; transform: none; }

.anim .wsp:not(.is-classified) .wsp__pill--set { visibility: hidden; }

/* The set label lands rather than fades — it was just applied. */
.anim .wsp.is-classified .wsp__row--on .wsp__pill--set,
.anim .wsp.is-classified .wsp__cstate--done .wsp__pill--set {
  animation: cpill 420ms var(--ease-land) both;
}

@keyframes cpill {
  0% { opacity: 0; transform: scale(0.86); }
  100% { opacity: 1; transform: none; }
}

/* The category it went into counts one higher. The sidebar lives inside .wsp,
   so both counters key off the same state class. */
.cat-before { display: none; }
.anim .wsp:not(.is-classified) .cat-before { display: inline; }
.anim .wsp:not(.is-classified) .cat-after { display: none; }

.wsp__cat--target { transition: color 320ms var(--ease); }
.anim .wsp.is-classified .wsp__cat--target { color: var(--ink-900); }

/* AI summary: the one block the product adds to the message. It unfolds
   rather than fading, because the point is that it was not there before. */
.wsp__ai {
  border: 1px solid var(--warm-500);
  border-radius: var(--r-input);
  background: var(--surface-warm-hover);
  padding: var(--s-4);
  transform-origin: top;
  overflow: hidden;
  transition: opacity 460ms var(--ease), transform 460ms var(--ease-land), max-height 560ms var(--ease-land), padding 460ms var(--ease);
  max-height: 340px;
  opacity: 1;
}

.anim .wsp:not(.is-summarised) .wsp__ai {
  max-height: 0;
  padding-block: 0;
  border-color: transparent;
  opacity: 0;
  transform: scaleY(0.94);
}

.wsp__ailabel {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--warm-700);
  font-weight: 500;
  margin-bottom: var(--s-3);
}

.wsp__ai ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }

/* The bullet is positioned, not a grid column: the <b> and the text after it
   are siblings, so a grid would put them in separate tracks and break the
   sentence into one word per line. */
.wsp__ai li {
  position: relative;
  padding-left: 16px;
  font-size: var(--t-caption);
  color: var(--ink-600);
  line-height: 1.55;
}

.wsp__ai li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 7px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--warm-500);
}
.wsp__ai li b { color: var(--ink-900); font-weight: 500; }

/* Save to Voyage, with the two choices the app actually offers. */
.wsp__act { position: relative; display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center; }

.wsp__save {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 14px;
  border-radius: 9px;
  background: var(--brand-700);
  color: #fff;
  font-size: var(--t-caption);
  font-weight: 500;
  transition: box-shadow 300ms var(--ease);
}

.wsp.is-saving .wsp__save { box-shadow: 0 0 0 4px rgba(2, 96, 137, 0.16); }

.wsp__menu {
  position: absolute;
  left: 0;
  top: calc(100% + 6px);
  z-index: 4;
  width: max-content;
  padding: 5px;
  border-radius: var(--r-input);
  background: var(--surface-white);
  border: 1px solid var(--hairline);
  box-shadow: var(--shadow-float);
  transform: translateY(0);
  opacity: 1;
  transition: opacity 260ms var(--ease), transform 260ms var(--ease-land);
}

.anim .wsp:not(.is-saving) .wsp__menu { opacity: 0; transform: translateY(-6px); }

.wsp__menu span { display: block; padding: 8px 10px; border-radius: 8px; font-size: var(--t-caption); color: var(--ink-600); }
.wsp__menu span:first-child { background: var(--surface-warm); color: var(--ink-900); font-weight: 500; }

.wsp__hint { font-size: 11px; color: var(--ink-400); }

/* ---------- What one message became -------------------------------------- */

.wsp__out { display: grid; gap: var(--s-5); margin-top: var(--s-10); }

@media (min-width: 800px) { .wsp__out { grid-template-columns: repeat(3, 1fr); } }

.out {
  position: relative;
  padding: var(--s-5);
  border-radius: var(--r-card);
  background: var(--surface-white);
  border: 1px solid var(--hairline);
  transform: translateY(0);
  opacity: 1;
  transition: transform 520ms var(--ease-land), opacity 520ms var(--ease);
}

.anim .wsp:not(.is-out) .out { transform: translateY(18px); opacity: 0; }

.wsp.is-out .out:nth-child(1) { transition-delay: 0ms; }
.wsp.is-out .out:nth-child(2) { transition-delay: 1000ms; }
.wsp.is-out .out:nth-child(3) { transition-delay: 2000ms; }

/* The stem is drawn just before its own card lands. */
.wsp.is-out .out:nth-child(2)::before { transition-delay: 900ms; }
.wsp.is-out .out:nth-child(3)::before { transition-delay: 1900ms; }

/* A short stem back up to the mailbox: the card came from up there. */
.out::before {
  content: "";
  position: absolute;
  left: var(--s-5);
  top: calc(-1 * var(--s-10));
  width: 1px;
  height: var(--s-10);
  background: var(--hairline-strong);
  transform-origin: top;
  transform: scaleY(1);
  transition: transform 420ms var(--ease-land);
}

.anim .wsp:not(.is-out) .out::before { transform: scaleY(0); }

@media (max-width: 799px) { .out::before { display: none; } }

.out__label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--ink-400);
  margin-bottom: var(--s-3);
}

.out__label i { width: 8px; height: 8px; border-radius: 2px; background: var(--c); }
.out__title { display: block; font-size: var(--t-ui); font-weight: 600; color: var(--ink-900); }
.out__sub { display: block; font-size: var(--t-caption); color: var(--ink-400); margin-top: 2px; }

.out__line {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-4);
  padding: 9px var(--s-3);
  border-radius: var(--r-input);
  background: var(--surface-warm);
  font-size: var(--t-caption);
  color: var(--ink-600);
}

.out__line .mono { font-family: var(--font-mono); font-size: 0.75rem; color: var(--ink-900); }
.out__line .right { margin-left: auto; color: var(--ink-400); }

/* ---------- Soft transition ----------------------------------------------
   The strongest objection in this market is not price, it is "we would have to
   change how we work". It gets answered immediately after the product is shown
   and before anything is asked for. */

.soft { display: grid; gap: var(--s-6); }

@media (min-width: 860px) {
  .soft { grid-template-columns: repeat(3, 1fr); gap: var(--s-8); }
}

.soft__item { padding-left: var(--s-5); border-left: 2px solid var(--warm-500); }
.soft__item b { display: block; font-size: var(--t-h4); font-weight: 600; color: var(--ink-900); }
.soft__item p { margin-top: 6px; font-size: var(--t-ui); color: var(--ink-600); }

/* ---------- Moment 2: the chorus ---------------------------------------- */

.chorus { position: relative; }

.chorus__field {
  position: relative;
  height: 340px;
  margin-block: var(--s-7) var(--s-8);
  /* The field is texture, not content: it must never push the page sideways. */
  overflow: hidden;
}

@media (max-width: 767px) {
  .chorus__field { height: 300px; }
  .chorus__field span { font-size: calc(var(--fs, 16px) * 0.62); }
}

.chorus__field span {
  position: absolute;
  font-size: var(--fs, 16px);
  white-space: nowrap;
  color: var(--ink-900);
  font-weight: 400;
  transform: rotate(var(--r, 0deg));
  transition: color 700ms var(--ease), opacity 700ms var(--ease);
}

/* Resolving the chorus points at where things go — it does not take the
   subject lines away. Blurring or fading the whole field meant a reader who
   scrolled in at normal speed lost the text before finishing it. */
.chorus.is-resolved .chorus__field span[data-lane] {
  color: var(--lane-color);
  opacity: 0.95 !important;
  font-weight: 500;
}

.chorus.is-resolved .chorus__field span[data-lane="mail"] { --lane-color: #96432c; }
.chorus.is-resolved .chorus__field span[data-lane="docs"] { --lane-color: #1d5bff; }
.chorus.is-resolved .chorus__field span[data-lane="wh"] { --lane-color: #8a5908; }

.lanes { display: flex; flex-direction: column; gap: var(--s-3); max-width: 620px; }

.lane {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 480ms var(--ease), transform 480ms var(--ease);
}

.chorus.is-resolved .lane { opacity: 1; transform: none; }
.chorus.is-resolved .lane:nth-child(1) { transition-delay: 0ms; }
.chorus.is-resolved .lane:nth-child(2) { transition-delay: 140ms; }
.chorus.is-resolved .lane:nth-child(3) { transition-delay: 280ms; }

.lane__bar {
  flex: 1;
  height: 2px;
  border-radius: 1px;
  background: var(--accent);
  opacity: 0.55;
}

.lane__name { font-size: var(--t-body); font-weight: 500; color: var(--ink-900); min-width: 190px; }

.chorus__caption { margin-top: var(--s-7); font-size: var(--t-lead); color: var(--ink-900); }

html:not(.anim) .lane { opacity: 1; transform: none; }

/* ---------- Flow motif --------------------------------------------------- */

.flow { display: grid; gap: var(--s-9); align-items: center; }

@media (min-width: 900px) {
  .flow { grid-template-columns: 5fr 7fr; gap: var(--s-9); }
}

.flow__media {
  border-radius: var(--r-media);
  background: var(--surface-white);
  border: 1px solid var(--hairline);
  padding: var(--s-6);
}

.flow__list {
  list-style: none;
  margin: var(--s-6) 0 0;
  padding-left: var(--s-5);
  border-left: 1px solid var(--hairline-strong);
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.flow__list li {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: var(--s-3);
  align-items: start;
  font-size: var(--t-body);
  color: var(--ink-600);
}

.flow__list svg { margin-top: 4px; color: var(--warm-500); }

/* ---------- APAC line ---------------------------------------------------- */

.ports {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3) var(--s-5);
  margin-top: var(--s-6);
  font-size: var(--t-ui);
  color: var(--ink-400);
}

.ports span { display: inline-flex; align-items: center; gap: 8px; }

.ports i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ink-900);
  display: inline-block;
}

