/* ==========================================================================
   Nomyss — direction "Almanac"

   PALETTE DISCIPLINE
   One accent. Claret is the wordmark, the eyebrows, the CTA and the drive
   times — six roles, one colour, so the CTA never has to compete with
   decoration. Pine appears in exactly one role (the no-app tick) so it reads
   as "confirmed" rather than as a second brand colour.

   The dark ground needs three tints of the red where light needs one: claret
   is only 2.3:1 on #171412, which fails the 3:1 a button surface needs to be
   findable at all. That is a known cost of supporting both grounds, not an
   invitation to add a fourth.

   All contrast figures in the comments were computed, not eyeballed.
   ========================================================================== */

/* ---------- Self-hosted type. No third-party requests: this page gets
     opened on phones straight out of a text message, and a render-blocking
     font request is the most expensive thing that could be on it. ---------- */

@font-face {
  font-family: 'Literata';
  src: url(fonts/literata-600.woff2) format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Figtree';
  src: url(fonts/figtree-400.woff2) format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Figtree';
  src: url(fonts/figtree-600.woff2) format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url(fonts/jetbrains-mono-400.woff2) format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}

/* ========================== Tokens — light ============================== */

:root {
  --bg:        #FAF7F1;   /* paper */
  --bg-raise:  #FFFFFF;
  --rule:      #E3DDD1;   /* decorative hairline, deliberately under 3:1 */
  --field:     #DCD5C7;   /* separate, darker: this one defines a control edge */

  --ink:       #161413;   /* 17.5:1 on paper */
  --soft:      #5A554E;   /*  7.9:1 */
  /* Was #7A736A, recorded as 4.9:1. Measured, it is 4.38:1 on this ground —
     a real AA failure that shipped, affecting the trust row, the footnote and
     the timeline tick labels. Darkened until it clears the floor. */
  --faint:     #767068;   /*  4.63:1 on paper, 4.90:1 on white */

  /* Micro-labels inside the walkthrough's mock panels sit on --bg-raise. In
     dark mode that surface is lighter than the page, so --faint measures
     4.43:1 there — under the floor. Light needs no separate value. */
  --faint-panel: #767068; /*  4.90:1 on white */

  --accent:      #8C2F39; /*  7.7:1 */
  --accent-soft: rgba(140, 47, 57, 0.09);
  --accent-line: rgba(140, 47, 57, 0.26);
  --cta:         #8C2F39;
  --on-cta:      #FDF6F2; /*  7.7:1 on the claret button */

  --confirm:   #2F6B4F;   /*  5.5:1 — the no-app tick, and nothing else */
  --danger:    #A33A2F;   /*  6.2:1 — the collision, and nothing else */
  --danger-soft: rgba(163, 58, 47, 0.16);

  --block:     #EAE3D5;   /* a meeting on the timeline */
  --block-ink: #161413;   /* 14.5:1 on --block */

  /* The itinerary card: the one dark object on a paper page. */
  --plan-bg:    #1B1A18;
  --plan-ink:   #F6F2EA;
  --plan-dim:   #9E9689;
  --plan-rule:  rgba(246, 242, 234, 0.14);
  --plan-drive: #E9909A;  /*  7.8:1 on the card */
  --plan-shadow: 0 18px 40px -16px rgba(27, 26, 24, 0.55),
                 0 0 0 1px rgba(27, 26, 24, 0.08);

  --display: 'Literata', Georgia, 'Times New Roman', serif;
  --body:    'Figtree', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --mono:    'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --radius:    13px;
  --radius-sm: 9px;
  --measure:   58ch;
}

/* =========================== Tokens — dark ==============================
   The figure/ground flips: a paper itinerary card sitting on ink.
   ======================================================================== */

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #171412;   /* warm near-black, deliberately not navy */
    --bg-raise:  #221E1A;   /* a real raised surface, not a 5% tint — a tinted
                               field reads fainter than the select beside it */
    --rule:      rgba(247, 243, 236, 0.14);
    --field:     rgba(247, 243, 236, 0.26);

    --ink:       #F7F3EC;   /* 16.6:1 on ink */
    --soft:      #B7AEA3;   /*  8.4:1 */
    --faint:     #8B8378;   /*  4.9:1 on the page, 4.43:1 on --bg-raise */
    --faint-panel: #938B80; /*  4.9:1 on --bg-raise */

    --accent:      #E9909A; /*  7.8:1 — marks and eyebrows on ink */
    --accent-soft: rgba(233, 144, 154, 0.12);
    --accent-line: rgba(233, 144, 154, 0.30);
    --cta:         #C6414C; /*  3.7:1 surface v. page — passes the 3:1 floor */
    --on-cta:      #FDF6F2; /*  4.7:1 label on that button */

    --confirm:   #7FCFA4;   /*  9.9:1 */
    --danger:    #F09A8C;   /*  8.5:1 */
    --danger-soft: rgba(240, 154, 140, 0.20);

    --block:     #2C2723;
    --block-ink: #F7F3EC;   /* 13.4:1 on --block */

    --plan-bg:    #FAF7F1;
    --plan-ink:   #161413;
    /* Same correction as --faint: #7A736A on this paper card is 4.38:1, not
       the 4.9:1 it was assumed to be. It was never in the contrast tables. */
    --plan-dim:   #767068;  /*  4.63:1 on --plan-bg */
    --plan-rule:  rgba(22, 20, 19, 0.13);
    --plan-drive: #8C2F39;  /*  7.7:1 — claret comes back inside the card */
    --plan-shadow: 0 22px 46px -18px rgba(0, 0, 0, 0.72),
                   0 0 0 1px rgba(0, 0, 0, 0.30);
  }
}

/* ============================== Base ==================================== */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }

.wrap {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 22px;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* A real focus indicator. Removing the outline and tinting a border instead
   is not a focus indicator. */
:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

a { color: var(--accent); text-underline-offset: 3px; }

/* ============================= Header =================================== */

.site-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 0 6px;
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--display);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.wordmark-glyph { display: flex; flex-direction: column; gap: 2.5px; width: 18px; flex: none; }
.wordmark-glyph i { display: block; height: 3.5px; border-radius: 2px; background: var(--accent); }
.wordmark-glyph i:nth-child(2) { width: 58%; }
.wordmark-glyph i:nth-child(3) { width: 80%; }

.tag {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-line);
  padding: 6px 11px;
  border-radius: 100px;
  white-space: nowrap;
}

/* ============================== Hero ==================================== */

.hero {
  display: grid;
  gap: 18px;
  padding: 20px 0 clamp(56px, 9vw, 96px);
}

h1 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(30px, 6.4vw, 54px);
  line-height: 1.1;
  letter-spacing: -0.023em;
  margin-bottom: 12px;
  text-wrap: balance;
}

.lede {
  color: var(--soft);
  font-size: clamp(15.5px, 1.5vw, 18px);
  line-height: 1.52;
  max-width: 46ch;
  margin-bottom: 18px;
  text-wrap: pretty;
}

/* ------------------------------ Form ------------------------------------ */

.signup { display: flex; flex-direction: column; gap: 12px; max-width: 440px; }

.field label {
  display: block;
  font-family: var(--mono);
  font-size: 11px;          /* not smaller — this audience skews older */
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 6px;
}

.signup input,
.signup select {
  width: 100%;
  padding: 13px 14px;
  font-size: 16px;          /* 16px floor — anything less zooms iOS Safari */
  font-family: var(--body);
  color: var(--ink);
  background: var(--bg-raise);
  border: 1px solid var(--field);
  border-radius: var(--radius-sm);
  transition: border-color 0.16s ease;
}
.signup input::placeholder { color: var(--faint); }
.signup input:hover, .signup select:hover { border-color: var(--accent-line); }

.signup select {
  cursor: pointer;
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--soft) 50%),
    linear-gradient(135deg, var(--soft) 50%, transparent 50%);
  background-position: calc(100% - 19px) calc(50% + 1px), calc(100% - 14px) calc(50% + 1px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 40px;
}
.signup select option { background: var(--bg-raise); color: var(--ink); }

.signup button {
  padding: 15px 22px;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--cta);
  color: var(--on-cta);
  font-family: var(--body);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: filter 0.16s ease, transform 0.1s ease;
}
.signup button:hover { filter: brightness(1.12); }
.signup button:active { transform: translateY(1px); }

/* ---- Hero actions -------------------------------------------------------
   The hero's job is now to send you to the one form at the foot of the page,
   not to hold a second copy of it. */

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
}

.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 15px 24px;
  border-radius: var(--radius-sm);
  background: var(--cta);
  color: var(--on-cta);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  transition: filter 0.16s ease, transform 0.1s ease;
}
.btn-primary:hover { filter: brightness(1.12); }
.btn-primary:active { transform: translateY(1px); }
.btn-primary svg { width: 15px; height: 15px; }

.btn-quiet {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 4px 2px;
  font-size: 15px;
  font-weight: 600;
  color: var(--accent);
  text-decoration: underline;
}

.trust {
  display: flex;
  flex-wrap: wrap;
  gap: 7px 18px;
  margin-top: 9px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--faint);
}
.trust span { display: flex; align-items: center; gap: 6px; }
.trust svg { width: 12px; height: 12px; color: var(--confirm); flex: none; }

/* Left in the flow (and in the accessibility tree) but zero-height when empty,
   so it costs nothing above the fold. An error pushes the trust row and the
   card down, never the button — the control the user just aimed at stays put. */
.form-error {
  font-size: 13.5px;
  line-height: 1.35;
  color: var(--danger);
}

.notice {
  display: none;
  max-width: 440px;
  margin-top: 14px;
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  font-size: 14.5px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--ink);
}
.notice--warn { background: var(--danger-soft); border-color: var(--danger); }

/* -------------------------- Itinerary card ------------------------------ */

.plan {
  background: var(--plan-bg);
  color: var(--plan-ink);
  border-radius: var(--radius);
  box-shadow: var(--plan-shadow);
  overflow: hidden;
  max-width: 440px;
}

.plan-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 18px 9px;
  border-bottom: 1px solid var(--plan-rule);
}
.plan-head .k {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--plan-dim);
}
.plan-head .v { font-family: var(--display); font-weight: 600; font-size: 13.5px; }

.plan-stops { padding: 7px 18px 12px; list-style: none; }

.stop { display: flex; gap: 12px; padding: 4px 0; }
/* Start and end on one line. Two lines is more readable in isolation but costs
   16px a stop, which is the difference between both drive markers landing
   above the fold on a 375x812 phone and only one of them doing so. */
.stop-time {
  flex: none;
  min-width: 76px;
  font-family: var(--mono);
  font-size: 10.5px;
  line-height: 1.45;
  padding-top: 2px;
  white-space: nowrap;
}
.stop-dot {
  flex: none;
  width: 9px; height: 9px;
  margin-top: 7px;
  border-radius: 50%;
  border: 2px solid var(--plan-ink);
}
.stop > span:last-child { flex: 1; min-width: 0; }
.stop-who { display: block; font-size: 13.5px; font-weight: 600; letter-spacing: -0.005em; line-height: 1.26; }
.stop-where { display: block; font-size: 11.5px; color: var(--plan-dim); line-height: 1.3; }

/* The drive is the product, so it gets the accent and a real connector
   rather than being a footnote. */
.drive {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 2px 0 2px 88px;   /* aligns under the stop dot, not the time */
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--plan-drive);
}
.drive::before {
  content: "";
  width: 10px; height: 16px;
  border-left: 2px dotted var(--plan-drive);
  margin-left: 3px;
}

/* ============================ Sections ================================== */

section { padding: clamp(52px, 8vw, 92px) 0; border-top: 1px solid var(--rule); }

.eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 13px;
}

h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(25px, 3.6vw, 38px);
  line-height: 1.16;
  letter-spacing: -0.017em;
  margin-bottom: 14px;
  text-wrap: balance;
}
/* Literata italic isn't loaded, and synthetic italic is a sloppy thing to put
   at 38px. The emphasis is carried by colour instead. */
h2 em { font-style: normal; color: var(--accent); }

.body-copy { color: var(--soft); font-size: 16.5px; max-width: var(--measure); text-wrap: pretty; }
.body-copy + .body-copy { margin-top: 14px; }

/* ===================== Block 3 — the collision ==========================
   Both strips share one axis (--day, in minutes) and are positioned from
   --start / --len, so they are directly comparable and the collision columns
   sit on real overlaps. Red and green are never the only channel carrying
   meaning: the strip labels, the bracket labels and the stacked-versus-spaced
   geometry each say the same thing independently.
   ======================================================================== */

.compare { --day: 420; margin-top: 34px; }          /* 9:00a – 4:00p */

.strip + .strip { margin-top: 30px; }

.strip-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 10px;
}
.strip-label b { font-weight: 400; color: var(--ink); }

.lanes { position: relative; display: flex; flex-direction: column; gap: 5px; }
.lane { position: relative; height: 30px; }

.blk {
  position: absolute;
  top: 0; bottom: 0;
  left:  calc(var(--start) / var(--day) * 100%);
  width: calc(var(--len)   / var(--day) * 100%);
  display: flex;
  align-items: center;
  padding: 0 8px;
  border-radius: 6px;
  background: var(--block);
  color: var(--block-ink);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Drawn on the real overlap, not somewhere that looks about right. */
.clash {
  position: absolute;
  top: -3px; bottom: -3px;
  left:  calc(var(--start) / var(--day) * 100%);
  width: calc(var(--len)   / var(--day) * 100%);
  background: var(--danger-soft);
  border-left: 2px solid var(--danger);
  border-right: 2px solid var(--danger);
  border-radius: 3px;
  pointer-events: none;
}

/* The device the whole block rests on: one bracket shape, two meanings. */
.brackets { position: relative; height: 34px; margin-top: 8px; }
.bracket {
  position: absolute;
  top: 0;
  left:  calc(var(--start) / var(--day) * 100%);
  width: calc(var(--len)   / var(--day) * 100%);
  height: 7px;
  border: 2px solid currentColor;
  border-top: none;
  border-radius: 0 0 3px 3px;
  color: var(--faint);
}
.bracket b {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 400;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.bracket--bad  { color: var(--danger); }
.bracket--good { color: var(--accent); }

.ticks {
  position: relative;
  height: 16px;
  margin-top: 4px;
  border-top: 1px solid var(--rule);
}
.ticks span {
  position: absolute;
  top: 5px;
  left: calc(var(--at) / var(--day) * 100%);
  font-family: var(--mono);
  font-size: 10px;
  color: var(--faint);
  transform: translateX(-50%);
}
.ticks span:first-child { transform: none; }
.ticks span:last-child  { transform: translateX(-100%); }

figcaption {
  margin-top: 24px;
  font-size: 14px;
  color: var(--faint);
  max-width: 54ch;
}

/* ====================== Block 5 — the walkthrough =======================

   Six illustrative screens. Everything in here is a drawing of the product,
   not the product: the only element a visitor can operate is the meetup-type
   switcher in step 04, and all it does is swap between three hard-coded
   panels. Nothing here posts, stores or sends anything.

   The panels deliberately reuse the page's own tokens rather than inventing a
   second "app" palette. A mockup that looks like a different product than the
   page it sits on reads as a stock illustration.
   ======================================================================== */

.walk-steps {
  list-style: none;
  margin-top: clamp(34px, 5vw, 54px);
  display: flex;
  flex-direction: column;
  gap: clamp(44px, 6.5vw, 78px);
}

.walk-step { display: grid; gap: 20px; }

@media (min-width: 820px) {
  .walk-step {
    grid-template-columns: 0.86fr 1.14fr;
    gap: clamp(32px, 4vw, 56px);
    align-items: center;
  }
  /* Alternating sides so six steps in a row don't read as a list of cards.
     Order is a purely visual swap — the DOM order stays 01 to 06, which is
     the order a screen reader and the tab sequence follow. */
  .walk-step:nth-child(even) .walk-copy   { order: 2; }
  .walk-step:nth-child(even) .walk-screen { order: 1; }
}

.walk-num {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 9px;
}
.walk-copy h3 {
  font-family: var(--display);
  font-size: clamp(20px, 2.4vw, 25px);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.014em;
  margin-bottom: 10px;
  text-wrap: balance;
}
.walk-copy p { color: var(--soft); font-size: 15.5px; max-width: 44ch; text-wrap: pretty; }
.walk-copy em { font-style: normal; color: var(--accent); }

.walk-hint {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--faint) !important;
}

.walk-close {
  margin-top: clamp(44px, 6vw, 72px);
  padding-top: clamp(26px, 3vw, 34px);
  border-top: 1px solid var(--rule);
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(18px, 2.2vw, 23px);
  line-height: 1.34;
  letter-spacing: -0.012em;
  max-width: 46ch;
  text-wrap: pretty;
}

/* ---------------------------- The mock panel ---------------------------- */

.ui {
  background: var(--bg-raise);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 14px 32px -20px rgba(27, 26, 24, 0.4);
  overflow: hidden;
  max-width: 460px;
}

.ui-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--rule);
  background: var(--bg);
}
.ui-title { font-family: var(--display); font-weight: 600; font-size: 14.5px; letter-spacing: -0.008em; }
.ui-chip {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-line);
  padding: 4px 9px;
  border-radius: 100px;
  white-space: nowrap;
}

.ui-body { padding: 15px 16px 17px; }
.ui-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint-panel);
  margin-bottom: 11px;
}
.ui-foot {
  margin-top: 13px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.03em;
  color: var(--faint-panel);
}

/* ------------------------------- People --------------------------------- */

.people { list-style: none; display: flex; flex-direction: column; gap: 7px; }
.person {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--bg);
}
.avatar {
  flex: none;
  width: 27px; height: 27px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--block);
  color: var(--block-ink);
  font-size: 11.5px;
  font-weight: 600;
}
.avatar--add {
  background: transparent;
  border: 1px dashed var(--field);
  color: var(--faint);
  font-weight: 400;
}
.person-name { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 600; letter-spacing: -0.005em; }
.person--add { border-style: dashed; }
.person--add .person-name { font-weight: 400; color: var(--faint); }

.via {
  flex: none;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
  border: 1px solid var(--rule);
  padding: 3px 7px;
  border-radius: 100px;
}
.via--saved { color: var(--confirm); border-color: currentColor; }
.via--linked { color: var(--accent); border-color: var(--accent-line); background: var(--accent-soft); }

/* --------------------------- Messages (step 02) -------------------------- */

.ui--stack .msg { padding: 14px 16px; }
.ui--stack .msg + .msg { border-top: 1px solid var(--rule); }
.msg-head {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint-panel);
  margin-bottom: 9px;
}
.msg .bubble { max-width: 100%; }

.mail { border: 1px solid var(--rule); border-radius: 10px; padding: 12px 13px; background: var(--bg); }
.mail-subject { font-size: 13.5px; font-weight: 600; letter-spacing: -0.005em; margin-bottom: 5px; }
.mail-body { font-size: 12.5px; color: var(--soft); line-height: 1.45; }

/* ----------------------------- Fork (step 03) ---------------------------- */

.fork { display: grid; gap: 16px; padding: 16px; }
@media (min-width: 520px) {
  .fork { grid-template-columns: 1fr auto 1fr; align-items: center; gap: 14px; }
}
.fork-cap {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint-panel);
  margin-bottom: 9px;
}
.fork-or {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--faint-panel);
  text-align: center;
}
.fork-note { margin-top: 9px; font-family: var(--mono); font-size: 9.5px; color: var(--faint-panel); }
/* Shrink-wrapped. .bubble relies on flex align-self to size itself, and there
   is no flex container here — left full width it reads as a button, which is
   the one thing a text message should not look like. */
.fork-side .bubble { display: inline-block; max-width: 100%; }

.link-card { border: 1px solid var(--rule); border-radius: 10px; padding: 12px; background: var(--bg); }
.link-url {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--accent);
  margin-bottom: 9px;
  overflow-wrap: anywhere;
}
.link-line { font-size: 13px; font-weight: 600; margin-bottom: 10px; }
/* Spans, not buttons — this is a picture of a screen, and nothing in it
   should be focusable or clickable. */
.link-btn {
  display: block;
  text-align: center;
  background: var(--cta);
  color: var(--on-cta);
  border-radius: 8px;
  padding: 9px;
  font-size: 12.5px;
  font-weight: 600;
}
.link-alt {
  display: block;
  text-align: center;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 9.5px;
  color: var(--faint);
}

/* ------------------- Meetup type switcher (step 04) ---------------------- */

.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 15px; }
.chip {
  min-height: 44px;
  padding: 10px 15px;
  border-radius: 100px;
  border: 1px solid var(--field);
  background: var(--bg);
  color: var(--ink);
  font-family: var(--body);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: background-color 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}
.chip:hover { border-color: var(--accent-line); }
.chip.is-on {
  background: var(--cta);
  color: var(--on-cta);
  border-color: transparent;
}

/* Held open so swapping panels doesn't jolt the page under the reader's
   finger. Measured against the tallest of the three. */
.detail { min-height: 124px; }
.detail-panel[hidden] { display: none; }
.detail-cap {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint-panel);
  margin-bottom: 9px;
}
.detail-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 12px;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--bg);
}
.detail-row--ask { border-style: dashed; border-color: var(--accent-line); }
.detail-icon { flex: none; width: 16px; text-align: center; color: var(--accent); font-size: 13px; line-height: 1.35; }
.detail-main { display: block; font-size: 13.5px; font-weight: 600; letter-spacing: -0.005em; }
.detail-sub  { display: block; font-size: 12px; color: var(--soft); line-height: 1.4; }
.detail-note { margin-top: 9px; font-family: var(--mono); font-size: 9.5px; color: var(--faint-panel); }

/* The step 06 payoff reuses the hero's card wholesale. */
.plan--build { max-width: 460px; }

/* ------------------------------- Bubbles -------------------------------- */

.bubble {
  max-width: 86%;
  padding: 11px 14px;
  border-radius: 17px;
  font-size: 14px;
  line-height: 1.45;
}
.bubble.in {
  align-self: flex-start;
  background: var(--block);
  color: var(--block-ink);
  border-bottom-left-radius: 5px;
}
.bubble.out {
  align-self: flex-end;
  background: var(--cta);
  color: var(--on-cta);
  border-bottom-right-radius: 5px;
}
/* ============================== Footer ================================== */

.site-foot {
  padding: clamp(52px, 8vw, 92px) 0 44px;
  border-top: 1px solid var(--rule);
}
.site-foot .signup { margin-top: 22px; }
.site-foot .trust  { margin-top: 13px; }

.footnote {
  margin-top: 40px;
  padding-top: 22px;
  border-top: 1px solid var(--rule);
  font-size: 13px;
  color: var(--faint);
  max-width: 56ch;
}

/* ============================ Entrance ================================== */

.rise {
  opacity: 0;
  transform: translateY(12px);
  animation: rise 0.55s cubic-bezier(0.22, 0.8, 0.3, 1) forwards;
}
.rise-2 { animation-delay: 0.07s; }
.rise-3 { animation-delay: 0.14s; }
@keyframes rise { to { opacity: 1; transform: none; } }

/* ========================== Scroll motion ===============================

   Two locks, and each one alone is enough to make this whole section vanish.

   1. .js-motion, which the inline script in <head> puts on <html> only when
      JS is actually running. No class, no hidden state — if the script is
      blocked or fails, the page renders as though this section didn't exist.
      script.js also strips the class back off if its observer turns out not
      to be reporting, which is how a broken reveal ends up visible rather
      than stuck.

   2. This media query. Wrapping the hidden states in no-preference means a
      visitor who turns reduced motion ON mid-session doesn't need any of
      these declarations overridden — the rules simply stop matching, and
      width, padding and opacity revert through the normal cascade. Overrides
      would have had to restate values like the bars' 8px padding, which
      quietly beats the 400px breakpoint's 6px on specificity.

   Both matter because a reveal-on-scroll effect that defaults to hidden
   turns any failure into a blank page, and this page gets opened on
   strangers' phones straight out of a text message.

   Sections are the unit that gets observed; children stagger inside them.
   ======================================================================== */

:root { --ease-rise: cubic-bezier(0.22, 0.8, 0.3, 1); }

@media (prefers-reduced-motion: no-preference) {

/* The itinerary is the hero's argument, so its rows arrive in the order you
   would drive them. Starts after the card's own rise (0.07s) has finished.
   Pure CSS — this one needs no observer, so it is not gated on .js-motion. */
/* Scoped to the hero on purpose. The step 06 card is the same markup, but it
   is driven by Motion on scroll instead — and a CSS animation would win that
   fight, because animations outrank the inline styles Motion sets. */
.hero .plan-stops > li {
  opacity: 0;
  animation: rise 0.5s var(--ease-rise) forwards;
}
.hero .plan-stops > li:nth-child(1) { animation-delay: 0.34s; }
.hero .plan-stops > li:nth-child(2) { animation-delay: 0.42s; }
.hero .plan-stops > li:nth-child(3) { animation-delay: 0.50s; }
.hero .plan-stops > li:nth-child(4) { animation-delay: 0.58s; }
.hero .plan-stops > li:nth-child(5) { animation-delay: 0.66s; }

.js-motion main > section > *,
.js-motion .site-foot > * {
  opacity: 0;
  transform: translateY(14px);
}

.js-motion main > section.is-in > *,
.js-motion .site-foot.is-in > * {
  opacity: 1;
  transform: none;
  transition: opacity   0.6s var(--ease-rise) var(--stagger, 0s),
              transform 0.6s var(--ease-rise) var(--stagger, 0s);
}

.js-motion main > section.is-in > *:nth-child(2),
.js-motion .site-foot.is-in > *:nth-child(2) { --stagger: 0.06s; }
.js-motion main > section.is-in > *:nth-child(3),
.js-motion .site-foot.is-in > *:nth-child(3) { --stagger: 0.12s; }
.js-motion main > section.is-in > *:nth-child(4),
.js-motion .site-foot.is-in > *:nth-child(4) { --stagger: 0.18s; }
.js-motion main > section.is-in > *:nth-child(n+5),
.js-motion .site-foot.is-in > *:nth-child(n+5) { --stagger: 0.24s; }

/* ---- The comparison draws itself ----------------------------------------
   The bars grow from their real start position to their real width, which
   performs the claim the figcaption makes in words: every width is
   proportional to real minutes. Padding collapses with the width because
   border-box would otherwise leave a 16px stub sitting at 9:00a.

   The clash marks and brackets are held back until the bars have landed, so
   the collision reads as a consequence of the schedule rather than as
   decoration that was always there. ------------------------------------- */

/* Written as "collapsed until revealed" rather than as a pair of hidden and
   shown rules, because the shown rule would have to restate width and padding
   — and restating padding here beats the 400px breakpoint on specificity,
   settling narrow phones at 8px instead of the 6px they are supposed to get.
   Saying nothing about the revealed state lets the cascade answer instead. */
.js-motion .compare .blk {
  transition: width   0.7s var(--ease-rise) var(--bar-delay, 0.32s),
              padding 0.7s var(--ease-rise) var(--bar-delay, 0.32s);
}
.js-motion section:not(.is-in) .compare .blk {
  width: 0;
  padding-left: 0;
  padding-right: 0;
  transition: none;   /* collapse on arrival, animate only outward */
}

/* Row 1 is one block per lane; row 2 is three blocks in a single lane. */
.js-motion .compare .lane:nth-child(2) .blk { --bar-delay: 0.42s; }
.js-motion .compare .lane:nth-child(3) .blk { --bar-delay: 0.52s; }
.js-motion .compare .lane .blk:nth-child(2) { --bar-delay: 0.42s; }
.js-motion .compare .lane .blk:nth-child(3) { --bar-delay: 0.52s; }

.js-motion .compare .clash,
.js-motion .compare .bracket { opacity: 0; }
.js-motion section.is-in .compare .clash,
.js-motion section.is-in .compare .bracket {
  opacity: 1;
  transition: opacity 0.45s ease 0.98s;
}

/* ---- Steps ---- */
.js-motion .steps .step { opacity: 0; transform: translateY(12px); }
.js-motion section.is-in .steps .step {
  opacity: 1;
  transform: none;
  transition: opacity   0.55s var(--ease-rise) var(--stagger, 0.10s),
              transform 0.55s var(--ease-rise) var(--stagger, 0.10s);
}
.js-motion section.is-in .steps .step:nth-child(2) { --stagger: 0.19s; }
.js-motion section.is-in .steps .step:nth-child(3) { --stagger: 0.28s; }

/* ---- The thread ---------------------------------------------------------
   Slower and more separated than the other staggers on purpose: these are
   meant to land as three messages arriving, not as one block fading in. */
.js-motion .bubbles .bubble { opacity: 0; transform: translateY(10px); }
.js-motion section.is-in .bubbles .bubble {
  opacity: 1;
  transform: none;
  transition: opacity   0.5s var(--ease-rise) var(--stagger, 0.28s),
              transform 0.5s var(--ease-rise) var(--stagger, 0.28s);
}
.js-motion section.is-in .bubbles .bubble:nth-child(2) { --stagger: 0.60s; }
.js-motion section.is-in .bubbles .bubble:nth-child(3) { --stagger: 0.92s; }

}   /* end prefers-reduced-motion: no-preference */

/* =========================== Responsive ================================= */

@media (min-width: 860px) {
  .hero {
    grid-template-columns: 1.02fr 0.98fr;
    gap: 58px;
    align-items: center;
    padding-top: 34px;
  }
  .plan { max-width: none; }
}

@media (max-width: 859px) {
  /* The card does NOT lead on mobile. A visitor meeting an itinerary before
     they know what the product is has been shown an answer to a question
     nobody asked them yet. */
  .hero-copy { order: 1; }
  .hero-figure { order: 2; }
}

@media (max-width: 720px) {
  .steps { grid-template-columns: 1fr; gap: 13px; }
  .split { grid-template-columns: 1fr; }
  .thread { max-width: none; }
}

@media (max-width: 400px) {
  .wrap { padding: 0 17px; }
  .blk { font-size: 10.5px; padding: 0 6px; }
  .bracket b { font-size: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0.001ms !important;
  }
  .rise { opacity: 1; transform: none; }

  /* Nothing here needs to undo the scroll-motion section. Its hidden states
     live inside @media (prefers-reduced-motion: no-preference), so they stop
     matching the moment this query starts matching. See "Scroll motion". */
}
