/* Hallmark · genre: modern-minimal · macrostructure: Workbench
 * theme: studied-DNA (source: https://www.usehallmark.com/examples/tally/)
 * observed: paper oklch(0.984 0.005 258) · ink oklch(0.18 0.03 258) · Geist 600
 * observed: buttons ink-filled, radius 999px · accents used as marks only
 * nav: N12 banner + retract · footer: Ft5 statement
 * studied: yes · rhythm: read from live computed styles, not markup alone
 * section rhythm: hero → marquee → analytics → calendar → composer → shop grid
 *   → community → proof → capabilities → steps → pricing → questions → CTA
 * Following the reference's own habits, read off the live page: section heads
 *   are CENTRED, feature cells are all the SAME SIZE, and sections are parted
 *   by whitespace — no rules, no tinted bands. The mixed-span bento and the
 *   tabbed screen-switcher that were here read as several competing shapes in
 *   one glance; one screen per section, one idea per cell, is calmer and says
 *   more. The testimonial slot stays empty rather than carry an invented quote.
 * App surfaces live in app.css under `.flk`, transcribed from the app's source.
 * The Create post section is a real screenshot in a bare <figure> — no drawn
 *   browser chrome, per the anti-pattern list.
 * pre-emit critique: P5 H5 E5 S5 R5 V4
 *
 * Diversification is suspended for this build: the brief is "match the
 * reference closely", so following its DNA is the job, not rotating away.
 */

@import url("tokens.css");

/* ============================================================ base */

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

html,
body {
  /* clip, never hidden — hidden breaks position: sticky */
  overflow-x: clip;
}

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

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  /* Copied verbatim from the reference's computed styles. Two very light,
     very large radial pools painted on body — not blurred divs. Mine were
     oklch(0.88 0.075) and read as dark blobs; these are 0.94 lightness at
     0.04 chroma, which is why the reference's page still reads as white. */
  background-color: var(--color-paper);
  background-image:
    radial-gradient(1200px 600px at 12% -10%, var(--orb-lilac), transparent 60%),
    radial-gradient(900px 500px at 88% 8%, var(--orb-lime), transparent 55%);
  background-repeat: no-repeat;
  background-attachment: fixed;
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  /* roman only — italic display is the most reliable AI tell */
  font-style: normal;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
  overflow-wrap: anywhere;
  min-width: 0;
}

p {
  margin: 0;
}

a {
  color: inherit;
}

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

:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

.wrap {
  width: min(100% - 2.5rem, 1180px);
  margin-inline: auto;
}

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

/* ============================================================ N5 floating pill nav */

:root {
  --banner-h: 0px;
  --bar-h: 76px;
}

/* The reference floats one white pill, centred, with a soft shadow — no
   announcement banner, no full-width bar. The bar version I shipped first was
   the single biggest reason the page didn't read like it. */
.nav {
  position: fixed;
  inset: var(--space-md) 0 auto;
  z-index: 500;
  display: flex;
  justify-content: center;
  padding-inline: var(--space-md);
  transition: transform var(--dur-base) var(--ease-out);
}

.nav.is-compact {
  transform: translateY(calc(-100% - var(--space-md)));
}

.nav__bar {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  max-width: 100%;
  padding: 0.5rem 0.5rem 0.5rem 1.25rem;
  border-radius: var(--radius-pill);
  background: oklch(1 0 0 / 0.82);
  backdrop-filter: blur(20px) saturate(170%);
  -webkit-backdrop-filter: blur(20px) saturate(170%);
  border: var(--rule-hair) solid oklch(1 0 0 / 0.9);
  box-shadow: 0 8px 30px -12px oklch(0.18 0.03 258 / 0.22);
}

.nav__brand {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-base);
  letter-spacing: -0.02em;
  text-decoration: none;
  white-space: nowrap;
}

.nav__mark {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: var(--color-ink);
  display: grid;
  place-items: center;
  color: var(--color-paper);
  font-size: 11px;
}

.nav__links {
  display: flex;
  gap: var(--space-lg);
  font-size: var(--text-sm);
}

.nav__links a {
  padding: 0.4rem 0.7rem;
  border-radius: var(--radius-pill);
  text-decoration: none;
  color: var(--color-ink-2);
  white-space: nowrap;
  transition:
    color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}

.nav__links a:hover {
  color: var(--color-ink);
  background: oklch(0.18 0.03 258 / 0.05);
}

.btn--sm {
  padding: 0.6rem 1.1rem;
}

@media (max-width: 860px) {
  .nav__links {
    display: none;
  }
}

/* ============================================================ buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  /* single line always — a wrapped button is a mobile tell */
  white-space: nowrap;
  padding: 0.8rem 1.4rem;
  border: 0;
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
}

.btn--accent {
  background: var(--color-ink);
  color: var(--color-paper);
  box-shadow: var(--shadow-card);
}

.btn--accent:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lift);
}

.btn--accent:active {
  transform: translateY(0);
}

.btn--ghost {
  background: var(--color-card);
  color: var(--color-ink);
  border: var(--rule-hair) solid var(--color-line-strong);
}

.btn--ghost:hover {
  border-color: var(--color-ink);
}

.btn[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* ============================================================ hero */

.hero {
  padding-top: calc(var(--bar-h) + var(--space-2xl));
  padding-bottom: var(--space-3xl);
  position: relative;
  overflow: hidden;
}

/* No hero wash. The reference sits on flat paper and lets the type carry it;
   the gradient pools were mine, and they were the other half of the purple. */

.hero__inner {
  position: relative;
  display: grid;
  gap: var(--space-2xl);
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  align-items: center;
}

@media (max-width: 900px) {
  .hero__inner {
    grid-template-columns: minmax(0, 1fr);
  }
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: 0.3rem 0.8rem;
  border-radius: var(--radius-pill);
  border: var(--rule-hair) solid var(--color-line-strong);
  background: oklch(1 0 0 / 0.7);
  backdrop-filter: blur(10px);
  color: var(--color-ink-2);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.pill__live {
  position: relative;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-accent);
}

/* A ring that expands and fades — the "this is live" tell. */
.pill__live::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--color-accent);
  animation: ping 2s var(--ease-out) infinite;
}

@keyframes ping {
  0% {
    transform: scale(1);
    opacity: 0.6;
  }
  70%,
  100% {
    transform: scale(2.6);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pill__live::after {
    animation: none;
  }
}

/* mono micro-line under the CTAs, dot-separated */
.hero__note {
  margin-top: var(--space-lg);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: 0.04em;
  color: var(--color-ink-3);
}

.hero h1 {
  font-size: var(--text-display);
  margin-top: var(--space-md);
}

/* Hallmark bans italic headers as an AI tell. The reference deliberately breaks
   that with one italic serif word in accent colour, and it's the single most
   characterful thing on its page — so it's here by explicit request, kept to
   one word per heading and never the whole line. */
/* The italic accent word, as asked. */
.say {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  color: var(--color-indigo);
  letter-spacing: -0.01em;
  padding-right: 0.06em;
}

.hero__lede {
  margin-top: var(--space-lg);
  max-width: 46ch;
  font-size: var(--text-xl);
  color: var(--color-ink-2);
}

.hero__cta {
  margin-top: var(--space-xl);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.hero__note {
  margin-top: var(--space-md);
  font-size: var(--text-xs);
  color: var(--color-ink-3);
}

/* The hand-built composer widget lived here; it has been replaced by a real
   screenshot of the Create post drawer. Its rules are deleted rather than
   parked, because `.app`, `.frame` and `.tag` are exactly the kind of generic
   names that clamp something else later — which is what the dead
   `.post { height: 26px }` below was doing to the calendar. */

/* The old week-scene widget lived here. It was dead markup-wise but very
   much alive in the cascade: its `.post { height: 26px }` was clamping the
   app calendar's post chips, which is what made them overlap. Deleted, not
   parked — an unused rule on a name as common as `.post` is a trap. */

/* ============================================================ channel marquee */

.channels {
  border-block: var(--rule-hair) solid var(--color-line);
  overflow: hidden;
  padding-block: var(--space-sm);
  /* fade both edges so words are never sliced mid-letter at the viewport */
  mask-image: linear-gradient(90deg, transparent, oklch(0 0 0) 8%, oklch(0 0 0) 92%, transparent);
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent,
    oklch(0 0 0) 8%,
    oklch(0 0 0) 92%,
    transparent
  );
}

.channels__track {
  display: flex;
  /* No gap. With gap, translateX(-50%) does not land on the start of the
     duplicated half — that mismatch is the "jump" and the big space after X.
     Spacing lives on the items so the two halves are exactly equal. */
  white-space: nowrap;
  width: max-content;
  animation: slide 46s linear infinite;
}

.channels__track span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding-inline: var(--space-xl);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-ink-3);
}

/* Each network wears its own pastel, the same tile the app puts it in. */
.mq-logo {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: 7px;
}

.mq-logo svg {
  width: 12px;
  height: 12px;
  fill: currentColor;
}

.mq-logo[data-ch="ig"]  { background: var(--color-ig);  color: var(--color-ig-fg); }
.mq-logo[data-ch="fb"]  { background: var(--color-fb);  color: var(--color-fb-fg); }
.mq-logo[data-ch="tt"]  { background: var(--color-tt);  color: var(--color-tt-fg); }
.mq-logo[data-ch="x"]   { background: var(--color-x);   color: var(--color-x-fg); }
.mq-logo[data-ch="li"]  { background: var(--color-li);  color: var(--color-li-fg); }
.mq-logo[data-ch="pin"] { background: var(--color-pin); color: var(--color-pin-fg); }

.dot {
  width: 7px;
  height: 7px;
  border-radius: var(--radius-pill);
  display: inline-block;
}

@keyframes slide {
  to {
    transform: translateX(-50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .channels__track {
    animation: none;
  }
}

/* ============================================================ sections */

/* One rhythm for the whole page. This was 7rem top AND bottom, so every
   join between two sections opened a 224px hole — generous stops being
   generous once the reader can't tell the sections are related. 4.5rem a
   side gives a 9rem seam, which is what the reference actually runs. */
.section {
  padding-block: var(--space-3xl);
}

.section--tint {
  background: var(--color-paper-2);
  border-block: var(--rule-hair) solid var(--color-line);
}

/* The 64px ruled grid, at the reference's exact 6% ink. The colour pools now
   live on body, so this layer carries the grid alone. */
.orbs {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--grid-line) var(--rule-hair), transparent var(--rule-hair)),
    linear-gradient(var(--grid-line) var(--rule-hair), transparent var(--rule-hair));
  background-size: 64px 64px;
  mask-image: linear-gradient(180deg, oklch(0 0 0) 0%, transparent 88%);
  -webkit-mask-image: linear-gradient(180deg, oklch(0 0 0) 0%, transparent 88%);
}

.orb {
  display: none;
}

.section--mint,
.section--sky,
.section--blush,
.section--butter,
.section--lilac,
.section--tint {
  background: transparent;
  border-block: 0;
}

/* Frosted glass: surfaces are translucent so the orb behind them tints the
   card, rather than each card being an opaque white rectangle. */
.cell,
.plan,
.qa {
  background: oklch(1 0 0 / 0.62);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border-color: oklch(1 0 0 / 0.7);
  box-shadow: var(--shadow-card);
}

/* The reference centres every section head — headline above copy, nothing in
   a left margin. Left-aligned heads over a centred grid was the thing making
   the middle of the page feel unplanned. */
.section__head {
  max-width: 62ch;
  margin-inline: auto;
  margin-bottom: var(--space-2xl);
  text-align: center;
}

.section__head h2 {
  font-size: var(--text-4xl);
  margin-top: var(--space-sm);
}

.section__head p {
  margin-top: var(--space-md);
  font-size: var(--text-xl);
  color: var(--color-ink-2);
}

.eyebrow {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-3);
}

/* tiny bar chart, hand-built */
.bars {
  margin-top: var(--space-md);
  display: flex;
  align-items: flex-end;
  gap: 7px;
  height: 74px;
}

.bars i {
  flex: 1;
  border-radius: 5px 5px 0 0;
  background: var(--color-accent);
  opacity: 0.35;
  transition: opacity var(--dur-base) var(--ease-out);
}

.step:hover .bars i {
  opacity: 1;
}

/* ============================================================ workbench

   Text left, the live composer right — the reference's two-column workbench
   rhythm, carrying a surface the visitor can actually click rather than a
   picture of one. */

@media (max-width: 900px) {
  }

.tour__list {
  margin: var(--space-md) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-xs);
  font-size: var(--text-sm);
  color: var(--color-ink-2);
}

.tour__list li::before {
  content: "→";
  color: var(--color-accent);
  margin-right: var(--space-xs);
}

/* ============================================================ proof

   Three plain facts about the product, not three invented performance
   statistics. The numeral is the mark; the sentence underneath is the claim. */

.proof {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-xl);
}

.proof__item b {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-display-s);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--color-accent-deep);
}

.proof__item h3 {
  margin-top: var(--space-xs);
  font-size: var(--text-xl);
  letter-spacing: -0.01em;
}

.proof__item p {
  margin-top: var(--space-xs);
  font-size: var(--text-sm);
  color: var(--color-ink-2);
}

@media (max-width: 820px) {
  .proof {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-lg);
  }
}

/* ============================================================ steps

   Three columns, genuinely ordinal, so the numbering earns its place. */

.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-lg);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.step {
  display: flex;
  flex-direction: column;
  padding: var(--space-lg);
  border: var(--rule-hair) solid var(--color-line);
  border-radius: var(--radius-lg);
  background: var(--color-card);
  box-shadow: var(--shadow-card);
}

.step__n {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: 0.1em;
  color: var(--color-accent-deep);
}

.step h3 {
  margin-block: var(--space-2xs) var(--space-xs);
  font-size: var(--text-2xl);
  letter-spacing: -0.02em;
}

.step p {
  font-size: var(--text-sm);
  color: var(--color-ink-2);
}

.step__art {
  margin-top: auto;
  padding-top: var(--space-lg);
}

.step__art--week {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 5px;
}

.step__art--week span {
  height: 34px;
  border-radius: var(--radius-sm);
  background: var(--color-paper-2);
}

.step__art--week span.is-on {
  background: var(--app-primary-soft);
  border: var(--rule-hair) solid var(--app-primary);
}

.step__art--queue {
  display: grid;
  gap: 6px;
}

.step__art--queue span {
  height: 10px;
  border-radius: var(--radius-pill);
  background: var(--color-paper-2);
}

.step__art--queue span:nth-child(1) {
  width: 100%;
  background: var(--app-primary-soft);
}

.step__art--queue span:nth-child(2) {
  width: 72%;
}

.step__art--queue span:nth-child(3) {
  width: 46%;
}

@media (max-width: 900px) {
  .steps {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ============================================================ pricing */

.plans {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-lg);
  align-items: start;
}

@media (max-width: 900px) {
  .plans {
    grid-template-columns: minmax(0, 1fr);
  }
}

.plan {
  background: var(--color-card);
  border: var(--rule-hair) solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: var(--space-xl);
  box-shadow: var(--shadow-card);
  transition:
    transform var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
}

.plan:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
}

.plan--featured {
  border: 2px solid var(--color-accent);
  position: relative;
}

.plan__badge {
  position: absolute;
  top: -12px;
  left: var(--space-xl);
  background: var(--color-accent-deep);
  color: var(--color-paper);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.25rem 0.7rem;
  border-radius: var(--radius-pill);
}

.plan__name {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
}

.plan__price {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 700;
  letter-spacing: -0.03em;
  margin-top: var(--space-xs);
}

.plan__price small {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-ink-3);
  letter-spacing: 0;
}

.plan__for {
  margin-top: var(--space-xs);
  font-size: var(--text-sm);
  color: var(--color-ink-3);
  min-height: 3rem;
}

.plan__list {
  margin: var(--space-lg) 0 var(--space-lg);
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-sm);
  font-size: var(--text-sm);
}

.plan__list li {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: var(--space-xs);
  color: var(--color-ink-2);
}

.plan__list li::before {
  content: "✓";
  color: var(--color-accent);
  font-weight: 700;
}

.plan__from {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-ink-3);
  margin-bottom: var(--space-sm);
}

.plan .btn {
  width: 100%;
}

/* ============================================================ faq */

.faq {
  display: grid;
  gap: var(--space-xs);
  max-width: 820px;
}

.qa {
  background: var(--color-card);
  border: var(--rule-hair) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: var(--space-md) var(--space-lg);
  transition: border-color var(--dur-base) var(--ease-out);
}

.qa[open] {
  border-color: var(--color-accent);
}

.qa summary {
  cursor: pointer;
  font-weight: 600;
  font-size: var(--text-base);
  list-style: none;
  display: flex;
  gap: var(--space-md);
  align-items: flex-start;
  justify-content: space-between;
}

.qa summary::-webkit-details-marker {
  display: none;
}

.qa summary::after {
  content: "+";
  color: var(--color-accent);
  font-size: 1.35rem;
  line-height: 1;
  flex: none;
  transition: transform var(--dur-base) var(--ease-out);
}

.qa[open] summary::after {
  transform: rotate(45deg);
}

.qa p {
  margin-top: var(--space-sm);
  color: var(--color-ink-2);
  font-size: var(--text-sm);
  max-width: 68ch;
}

/* ============================================================ waitlist */

.signup {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-lg);
  max-width: 480px;
}

.signup input {
  flex: 1 1 220px;
  min-width: 0;
  padding: 0.8rem 1rem;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--color-ink);
  background: var(--color-card);
  border: var(--rule-hair) solid var(--color-line-strong);
  border-radius: var(--radius-pill);
  transition: border-color var(--dur-fast) var(--ease-out);
}

.signup input:hover {
  border-color: var(--color-accent);
}

.signup input[aria-invalid="true"] {
  border-color: oklch(0.58 0.19 22);
}

.signup__msg {
  margin-top: var(--space-sm);
  font-size: var(--text-sm);
  min-height: 1.4em;
}

.signup__msg[data-state="error"] {
  color: oklch(0.5 0.19 22);
}

.signup__msg[data-state="success"] {
  color: oklch(0.45 0.12 155);
}

/* ============================================================ cta strip */

.strip {
  background: var(--color-ink);
  color: var(--color-paper);
  border-radius: var(--radius-xl);
  padding: var(--space-3xl) var(--space-xl);
  text-align: center;
}

.strip h2 {
  font-size: var(--text-4xl);
  max-width: 20ch;
  margin-inline: auto;
}

.strip p {
  margin-top: var(--space-md);
  color: oklch(1 0 0 / 0.86);
  max-width: 48ch;
  margin-inline: auto;
}

.strip .signup {
  margin-inline: auto;
  justify-content: center;
}

.strip .signup input {
  border-color: transparent;
}

.strip .btn--ghost {
  background: var(--color-paper);
  border-color: transparent;
}

/* ============================================================ Ft5 footer */

.foot {
  padding-block: var(--space-3xl) var(--space-xl);
  border-top: var(--rule-hair) solid var(--color-line);
  background: var(--color-paper-2);
}

.foot__statement {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.1;
  max-width: 24ch;
}

.foot__meta {
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: var(--rule-hair) solid var(--color-line);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md) var(--space-lg);
  align-items: center;
  font-size: var(--text-xs);
  color: var(--color-ink-3);
}

.foot__meta nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-lg);
  margin-right: auto;
}

.foot__meta a {
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out);
}

.foot__meta a:hover {
  color: var(--color-accent-ink);
}

/* ============================================================ scroll reveal */

[data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
}

[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1;
    transform: none;
    transition: opacity 140ms var(--ease-out);
  }
}

/* ============================================================ legal pages */

.doc {
  padding-top: calc(var(--bar-h) + var(--space-2xl));
  padding-bottom: var(--space-4xl);
}

.doc__body {
  max-width: 68ch;
}

.doc__body h2 {
  font-size: var(--text-3xl);
  margin-top: var(--space-2xl);
}

.doc__body h3 {
  font-size: var(--text-xl);
  margin-top: var(--space-xl);
}

.doc__body p,
.doc__body li {
  margin-top: var(--space-md);
  color: var(--color-ink-2);
}

.doc__body ul {
  padding-left: 1.1rem;
}

.doc__updated {
  font-size: var(--text-sm);
  color: var(--color-ink-3);
  margin-top: var(--space-sm);
}

/* ============================================================ hero

   Copy left, the product's artefact right — the reference's own hero shape.
   The analytics screen is a section of its own further down; a graph crammed
   into a hero is a graph nobody reads. */

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
  gap: var(--space-3xl);
  align-items: center;
}

.hero__lede {
  max-width: 46ch;
}

@media (max-width: 980px) {
  .hero__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-2xl);
  }
}

/* The scheduled-post ticket lived here. The hero now carries the drag demo
   instead — showing the act rather than the artefact — so these rules are
   deleted rather than parked. */

/* ============================================================ app section

   The console is a section in its own right, with room to breathe and a
   heading that says plainly what it is. */

/* The analytics screen now sits mid-page rather than under the marquee, so
   it takes the same seam as every other section. */

/* The supplied icon is a square PNG; the radius rounds it off in place. */
img.nav__mark {
  border-radius: 7px;
  object-fit: cover;
}


/* ============================================================ capability grid

   Six equal cells, one idea each. Whitespace separates sections — no rules,
   no tinted bands — the way the reference does it. */

.grid3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-md);
}

.cell {
  position: relative;
  z-index: 1;
  padding: var(--space-lg);
  border: var(--rule-hair) solid var(--color-line);
  border-radius: var(--radius-lg);
  background: var(--color-card);
  box-shadow: var(--shadow-card);
  transition:
    transform var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}

.cell:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
  border-color: var(--color-accent);
}

.cell__label {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent-deep);
}

.cell h3 {
  margin-block: var(--space-xs) var(--space-sm);
  font-size: var(--text-2xl);
  letter-spacing: -0.02em;
}

.cell p {
  font-size: var(--text-sm);
  color: var(--color-ink-2);
}

@media (max-width: 900px) {
  .grid3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 620px) {
  .grid3 {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ============================================================ split rows

   Copy one side, an app surface the other, alternating down the page — the
   reference's workbench rhythm, one screen per row. */

.split {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
  gap: var(--space-2xl);
  align-items: center;
}

.split--flip .split__text {
  order: 2;
}

.split__text h2 {
  font-size: var(--text-4xl);
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.split__text > p {
  margin-top: var(--space-md);
  color: var(--color-ink-2);
  max-width: 46ch;
}

@media (max-width: 900px) {
  .split {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-xl);
  }
  .split--flip .split__text {
    order: 0;
  }
}


/* `.bench` was the composer row's own layout. That row is now a plain
   `.split`, so its rules are removed rather than left to shadow something
   with a similar name later. */

/* ============================================================ screenshot

   A real capture in a plain figure with a hairline border. No drawn browser
   bar, no traffic lights: the reader's own window is the chrome, and a fake
   one is the tell. */

.shot {
  /* Capped and centred. Run full-bleed it dominates the page and the drawer's
     own type ends up larger than the site's — which reads as a different
     document pasted in rather than a window into the product. */
  max-width: 920px;
  margin-inline: auto;
  border: var(--rule-hair) solid var(--color-line-strong);
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: var(--color-card);
  box-shadow: 0 24px 60px -30px oklch(0.18 0.03 258 / 0.4);
}

.shot img {
  display: block;
  width: 100%;
  height: auto;
}

/* the notes under it — plain text in two columns, no icons, no cards */
.notes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-lg) var(--space-2xl);
  margin: var(--space-2xl) auto 0;
  padding: 0;
  max-width: 1000px;
  list-style: none;
  font-size: var(--text-sm);
  color: var(--color-ink-2);
}

.notes b {
  color: var(--color-ink);
}

@media (max-width: 760px) {
  .notes {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-md);
  }
}

/* ============================================================ intelligence

   Flockly Intelligence explained as a pipeline, hand-built. The heatmap is a
   real 7×24 grid rendered from data attributes, not a decorative squiggle —
   the point of the section is that the recommendation is auditable, so the
   graphic has to be too. */

.intel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--space-2xl);
  align-items: center;
}

.intel__text h2 {
  font-size: var(--text-4xl);
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.intel__text > p {
  margin-top: var(--space-md);
  color: var(--color-ink-2);
  max-width: 46ch;
}

/* the numbered pipeline */
.steps-list {
  margin: var(--space-lg) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-md);
  counter-reset: pipe;
}

/* Hanging indent, not a two-column grid: the <b> and the text after it are
   separate children, so a grid gave each its own cell and broke the sentence
   into one word per line. */
.steps-list li {
  position: relative;
  padding-left: 32px;
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--color-ink-2);
}

.steps-list li::before {
  counter-increment: pipe;
  content: counter(pipe, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 2px;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 500;
  color: var(--color-accent-deep);
}

.steps-list b {
  color: var(--color-ink);
}

/* ---- the heatmap card ---- */

.heat {
  padding: var(--space-lg);
  border-radius: var(--radius-xl);
  border: var(--rule-hair) solid var(--color-line);
  background: var(--color-card);
  box-shadow: var(--shadow-lift);
}

.heat__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
}

.heat__head p {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-3);
}

.heat__grid {
  display: grid;
  grid-template-columns: 26px repeat(12, minmax(0, 1fr));
  gap: 3px;
  align-items: center;
}

.heat__day {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--color-ink-3);
}

.heat__cell {
  aspect-ratio: 1;
  border-radius: 3px;
  background: var(--app-primary);
  /* strength drives opacity, so the grid reads as evidence not decoration */
  opacity: calc(var(--v) * 0.9 + 0.06);
}

.heat__cell[data-pick] {
  outline: 2px solid var(--color-accent-deep);
  outline-offset: 1px;
  opacity: 1;
}

.heat__hours {
  display: grid;
  grid-template-columns: 26px repeat(12, minmax(0, 1fr));
  gap: 3px;
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--color-ink-3);
}

.heat__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-top: var(--space-md);
  padding-top: var(--space-md);
  border-top: var(--rule-hair) solid var(--color-line);
  font-size: var(--text-2xs);
  color: var(--color-ink-3);
}

.heat__legend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.heat__legend i {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--app-primary);
}

.heat__legend i[data-weak] { opacity: 0.25; }
.heat__legend i[data-pick] { outline: 2px solid var(--color-accent-deep); outline-offset: 1px; }

@media (max-width: 900px) {
  .intel {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-xl);
  }
}


/* ============================================================ contact

   Form left, the ways-to-reach-us column right. The form composes an email
   rather than posting to an endpoint — see site/js/site.js for why. */

.contact {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: var(--space-2xl);
  margin-top: var(--space-2xl);
  align-items: start;
}

.contact__form {
  display: grid;
  gap: var(--space-md);
  padding: var(--space-xl);
  border: var(--rule-hair) solid var(--color-line);
  border-radius: var(--radius-xl);
  background: var(--color-card);
  box-shadow: var(--shadow-card);
}

.field {
  display: grid;
  gap: 6px;
}

.field label {
  font-size: var(--text-sm);
  font-weight: 600;
}

.field label span {
  font-weight: 400;
  color: var(--color-ink-3);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.7rem 0.85rem;
  border: var(--rule-hair) solid var(--color-line-strong);
  border-radius: var(--radius-md);
  background: var(--color-paper);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--color-ink);
  transition: border-color var(--dur-fast) var(--ease-out);
}

.field textarea {
  resize: vertical;
  min-height: 120px;
  line-height: 1.55;
}

.field input:hover,
.field select:hover,
.field textarea:hover {
  border-color: var(--color-ink-3);
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 1px;
  border-color: var(--color-focus);
}

.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: oklch(0.6 0.2 25);
}

.contact__form .btn {
  justify-self: start;
}

.contact__note {
  font-size: var(--text-xs);
  color: var(--color-ink-3);
}

.contact__aside h2 {
  font-size: var(--text-xl);
  margin-top: var(--space-lg);
}

.contact__aside h2:first-child {
  margin-top: 0;
}

.contact__aside p {
  margin-top: var(--space-xs);
  font-size: var(--text-sm);
  color: var(--color-ink-2);
}

@media (max-width: 860px) {
  .contact {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-xl);
  }
}

/* ============================================================ billing cycle

   The same monthly/yearly switch the app puts above its plan cards, with the
   app's own 20% figure. Prices are swapped by JS from data attributes, so the
   two numbers can't drift apart in the markup. */

.cycle {
  display: inline-flex;
  gap: 3px;
  margin-top: var(--space-lg);
  padding: 3px;
  border-radius: var(--radius-pill);
  border: var(--rule-hair) solid var(--color-line);
  background: var(--color-paper-2);
}

.cycle button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: 0.5rem 1rem;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-ink-3);
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out);
}

.cycle button:hover {
  color: var(--color-ink);
}

.cycle button[aria-pressed="true"] {
  background: var(--color-card);
  color: var(--color-ink);
  font-weight: 600;
  box-shadow: var(--shadow-card);
}

.cycle__save {
  padding: 0.1rem 0.45rem;
  border-radius: var(--radius-pill);
  background: var(--color-accent-soft);
  color: var(--color-accent-deep);
  font-size: var(--text-2xs);
  font-weight: 600;
}

.plan__billed {
  margin-top: 2px;
  font-size: var(--text-xs);
  color: var(--color-ink-3);
}

/* the figure itself animates, not the whole card */
.plan__price b {
  display: inline-block;
  font-weight: inherit;
  transition: transform var(--dur-fast) var(--ease-out);
}

.plan__price.is-swapping b {
  transform: translateY(-3px);
  opacity: 0.35;
}



/* ============================================================ floaties

   The six networks drifting behind the capability grid, the way Buffer floats
   its platform marks. Decorative and aria-hidden: the section still reads
   identically with them switched off.

   Each mark carries its own position, size, duration and delay as custom
   properties, so one keyframe animates all six without them marching in step.
   Transform and opacity only. */

.section--floaties {
  position: relative;
  overflow: hidden;
}

.floaties {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* behind the cards: a mark drifting under a frosted cell shows through
     softened, which is the effect, rather than covering the copy */
  z-index: 0;
}

/* the section's own content sits above them */
.section--floaties .wrap {
  position: relative;
  z-index: 1;
}

.floatie {
  position: absolute;
  left: var(--x);
  top: var(--y);
  display: grid;
  place-items: center;
  width: var(--s);
  height: var(--s);
  margin: calc(var(--s) / -2) 0 0 calc(var(--s) / -2);
  border-radius: 30%;
  background: var(--color-card);
  border: var(--rule-hair) solid var(--color-line);
  box-shadow: 0 12px 28px -14px oklch(0.18 0.03 258 / 0.35);
  pointer-events: auto;
  opacity: 0.85;
  animation: drift var(--dur) var(--ease-in-out) var(--delay) infinite;
  transition:
    transform var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
}

.floatie svg {
  width: 45%;
  height: 45%;
  transition: color var(--dur-fast) var(--ease-out);
}

.floatie[data-ch="ig"]  { color: var(--color-ig-fg); }
.floatie[data-ch="tt"]  { color: var(--color-tt-fg); }
.floatie[data-ch="fb"]  { color: var(--color-fb-fg); }
.floatie[data-ch="li"]  { color: var(--color-li-fg); }
.floatie[data-ch="pin"] { color: var(--color-pin-fg); }
.floatie[data-ch="x"]   { color: var(--color-x-fg); }

/* hovering one pauses its drift and fills it with the network's pastel */
.floatie:hover {
  opacity: 1;
  animation-play-state: paused;
  transform: scale(1.12);
  box-shadow: 0 18px 36px -14px oklch(0.18 0.03 258 / 0.45);
}

.floatie[data-ch="ig"]:hover  { background: var(--color-ig); }
.floatie[data-ch="tt"]:hover  { background: var(--color-tt); }
.floatie[data-ch="fb"]:hover  { background: var(--color-fb); }
.floatie[data-ch="li"]:hover  { background: var(--color-li); }
.floatie[data-ch="pin"]:hover { background: var(--color-pin); }
.floatie[data-ch="x"]:hover   { background: var(--color-x); }

@keyframes drift {
  0%,
  100% {
    transform: translate3d(0, 0, 0) rotate(0deg);
  }
  25% {
    transform: translate3d(18px, -26px, 0) rotate(4deg);
  }
  50% {
    transform: translate3d(34px, -8px, 0) rotate(-3deg);
  }
  75% {
    transform: translate3d(12px, 18px, 0) rotate(2deg);
  }
}

/* Kept on at normal desktop widths, where they drift across and behind the
   cards. Dropped on small screens: there's no room for them to travel without
   sitting under every word on the page. */
@media (max-width: 780px) {
  .floaties {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .floatie {
    animation: none;
  }
  .floatie:hover {
    transform: none;
  }
}
