/* ============================================================
   TALESTEP — site.css
   Tokens → reset → type → layout → components → responsive
   No scroll-driven motion here: that lives in site.js (Lenis / GSAP).
   ============================================================ */

/* Lenis owns scroll easing; native smooth-scroll fighting it over the same
   frame is what causes stutter, so this keeps native scrolling instant
   underneath Lenis's own animation regardless of what triggers it. */
.lenis.lenis-smooth { scroll-behavior: auto !important; }

/* ---------- Font ---------- */
@font-face {
  font-family: "Inter Variable";
  src: url("/assets/fonts/InterVariable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */
:root {
  /* Brand palette */
  --ink:         #14231F;
  --sage:        #4D5C57;
  --teal:        #0E8D85;
  --teal-deep:   #0B6F69;
  --teal-bright: #2FB3A8;
  --cream:       #F7F5F1;
  --paper:       #FFFFFF;

  /* Derived surfaces / lines */
  --sage-pale:   #C7D0CC;
  --line:        #E4E1DA;
  --line-on-ink: rgba(247, 245, 241, 0.18);

  /* Type */
  --font-sans: "Inter Variable", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --fs-display-xl: clamp(2.75rem, 2.1rem + 3.2vw, 5.5rem);
  --fs-display-l:  clamp(2rem, 1.65rem + 1.8vw, 3.25rem);
  --fs-display-m:  clamp(1.375rem, 1.2rem + 0.9vw, 1.75rem);
  --fs-body-l: 1.1875rem;   /* 19px */
  --fs-body:   1.0625rem;   /* 17px */
  --fs-eyebrow: 0.75rem;    /* 12px */
  --measure: 62ch;

  --lh-body: 1.55;
  --lh-tight: 1.15;

  /* Space */
  --space-section: clamp(4rem, 3rem + 5vw, 9rem);
  --space-gutter: clamp(1.25rem, 1rem + 2vw, 3rem);
  --content-max: 1180px;
  --content-narrow: 760px;

  --radius-s: 8px;
  --radius-m: 16px;
  --radius-l: 28px;

  --shadow-soft: 0 24px 60px -20px rgba(20, 35, 31, 0.28);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p, figure, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img { display: block; max-width: 100%; height: auto; }
picture { display: block; }
[hidden] { display: none !important; }
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: 0; }

/* Visible keyboard focus everywhere */
:focus { outline: none; }
:focus-visible {
  outline: 3px solid var(--teal-deep);
  outline-offset: 3px;
  border-radius: 4px;
}
.ink :focus-visible, .site-footer :focus-visible {
  outline-color: var(--teal-bright);
}

.skip-link {
  position: absolute;
  left: 12px;
  top: -60px;
  background: var(--ink);
  color: var(--paper);
  padding: 12px 20px;
  border-radius: var(--radius-s);
  z-index: 200;
  transition: top 0.2s ease;
}
.skip-link:focus { top: 12px; }

/* ---------- Type roles ---------- */
h1 {
  font-size: var(--fs-display-xl);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: -0.035em;
  max-width: 18ch;
}
h2 {
  font-size: var(--fs-display-l);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: -0.025em;
  max-width: 20ch;
}
h3 {
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--teal-deep);
  margin-bottom: 0.75rem;
}
.ink .eyebrow { color: var(--teal-bright); }
.lede {
  font-size: var(--fs-body-l);
  color: var(--sage);
  max-width: var(--measure);
  margin-top: 1.5rem;
}
p { max-width: var(--measure); }
.callout {
  font-size: var(--fs-display-m);
  font-weight: 700;
  letter-spacing: -0.015em;
  max-width: 22ch;
  margin-top: 2rem;
}
.callout.center { max-width: 40ch; margin-left: auto; margin-right: auto; text-align: center; }
.fineprint {
  font-size: 0.875rem;
  color: var(--sage);
  margin-top: 1.5rem;
}

/* ---------- Buttons ---------- */
.btn-primary, .btn-primary-lg {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 28px;
  border-radius: 999px;
  font-weight: 700;
  text-decoration: none;
  transition: filter 0.2s ease, opacity 0.2s ease;
}
/* teal-deep + paper: 6.01:1. Plain --teal fails AA (4.06:1) at this text size. */
.btn-primary { background: var(--teal-deep); color: var(--paper); }
.btn-primary:hover, .btn-primary:focus-visible { filter: brightness(0.9); }
.btn-primary-lg {
  min-height: 56px;
  padding: 0 36px;
  font-size: var(--fs-body-l);
  background: var(--teal-bright);
  color: var(--ink);
}
.btn-primary-lg:hover, .btn-primary-lg:focus-visible { opacity: 0.85; }

/* ---------- Header ---------- */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px var(--space-gutter);
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
}
.brand-mark { width: 22px; height: 22px; fill: var(--ink); flex: none; }
.brand-mark .brand-mark-accent { fill: var(--teal); }
.brand-mark-reverse { fill: var(--paper); }
.brand-mark-reverse .brand-mark-accent { fill: var(--teal-bright); }
.brand-word {
  font-weight: 700;
  font-size: 1.125rem;
  letter-spacing: -0.02em;
}
.header-contact {
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  font-weight: 600;
  padding: 0 8px;
}
.header-contact:hover { color: var(--teal-deep); }

/* ---------- Spine ---------- */
.spine {
  position: fixed;
  left: clamp(12px, 2vw, 28px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 90;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.spine-bar {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.spine-bar::after {
  content: "";
  display: block;
  width: 26px;
  height: 4px;
  border-radius: 2px;
  background: var(--sage-pale);
  transition: background-color 0.2s ease, width 0.2s ease;
}
.spine-bar:hover::after,
.spine-bar:focus-visible::after {
  background: var(--sage);
}
.spine-bar[aria-current="true"]::after {
  background: var(--teal);
  width: 38px;
}

/* ---------- Layout shell ---------- */
main { display: block; }
.section {
  padding: var(--space-section) var(--space-gutter);
  max-width: var(--content-max);
  margin: 0 auto;
}
.section.ink {
  max-width: none;
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  padding: var(--space-section) var(--space-gutter);
  text-align: center;
}
.section.ink .lede,
.section.ink p:not(.eyebrow) { color: var(--sage-pale); }
.section.ink h2 { color: var(--paper); max-width: none; }
.section.ink p:not(.eyebrow) { max-width: 50ch; margin: 1.25rem auto 0; }
.section.ink .btn-primary-lg { margin-top: 2.5rem; }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  padding: calc(var(--space-section) + 64px) var(--space-gutter) var(--space-section);
  max-width: var(--content-max);
  margin: 0 auto;
  text-align: left;
  overflow: clip;
}
.hero-route-decoration {
  position: absolute;
  top: clamp(40px, 8vw, 120px);
  right: var(--space-gutter);
  width: clamp(220px, 28vw, 420px);
  height: auto;
  opacity: 0.5;
  z-index: 0;
  pointer-events: none;
}
.hero h1, .hero .lede, .hero .btn-primary, .hero .reassurance, .hero-visual {
  position: relative;
  z-index: 1;
}
.hero .btn-primary { margin-top: 2.25rem; }
.reassurance {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin-top: 2rem;
  color: var(--sage);
  font-size: 0.9375rem;
}
.reassurance li { display: flex; align-items: center; }
.reassurance li + li { margin-left: 1rem; padding-left: 1rem; border-left: 1px solid var(--line); }
.hero-visual {
  margin: clamp(3rem, 4vw, 5rem) auto 0;
  max-width: 420px;
  display: flex;
  justify-content: center;
}
.hero-visual img {
  width: 100%;
  height: auto;
}

/* Phone frame: applied to every visitor app screenshot so it reads as a
   device, not a floating rectangle. Console screenshots (landscape,
   browser based) keep their own plainer treatment further down. Attribute
   selectors here (rather than a parent class) keep the styling attached to
   each screenshot whether it is sitting inline in a panel (mobile, and the
   no-motion fallback) or has been moved into the sticky visual by site.js
   (desktop pinned sequence) — see the JS for why it relocates. The hero
   photo already has its own phone bezel baked in, so it is styled
   separately above rather than through this shared selector. */
#section-03 [data-pin-frame] img,
.steps picture img {
  box-sizing: border-box;
  border: 8px solid var(--ink);
  border-radius: 36px;
  background: var(--ink);
  box-shadow: var(--shadow-soft);
}

/* ---------- 02 How it works ---------- */
.steps {
  margin-top: 2.5rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.5rem, 3vw, 3rem);
}
.steps h3 { margin-bottom: 0.75rem; }
.steps p { color: var(--sage); }
.steps picture { margin-top: 1.5rem; max-width: 220px; }

/* ---------- 03 / 04 pinned sequences ---------- */
.pin-layout {
  margin-top: 2.5rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}
/* Each screenshot starts inline inside its panel (see .pin-copy article
   picture below). The sticky visual column only has content once site.js
   relocates the screenshots into it for the desktop pinned sequence, so an
   empty one collapses away entirely rather than leaving a dead column —
   this is what keeps mobile, reduced-motion and no-JS all correct without
   duplicating CSS per case. */
.pin-visual {
  position: sticky;
  top: 110px;
  display: grid;
  justify-items: center;
}
.pin-visual:empty { display: none; }
.pin-visual [data-pin-frame] {
  grid-area: 1 / 1;
  opacity: 0;
  transition: opacity 0.6s ease;
  pointer-events: none;
}
.pin-visual [data-pin-frame].is-active {
  opacity: 1;
  pointer-events: auto;
}
.pin-layout:has(.pin-visual:empty) { grid-template-columns: 1fr; }
[data-pin-frame] img {
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-soft);
}
#section-03 [data-pin-frame] img { max-width: 300px; }
#section-04 .pin-layout { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
#section-04 .pin-layout:has(.pin-visual:empty) { grid-template-columns: 1fr; }
#section-04 [data-pin-frame] img { max-width: 100%; border-radius: var(--radius-s); }
.pin-copy { display: flex; flex-direction: column; gap: clamp(3rem, 8vh, 6rem); }
.pin-copy p { color: var(--sage); margin-top: 0.5rem; }
.pin-copy article picture { display: block; margin-bottom: 1.25rem; max-width: 300px; }
#section-04 .pin-copy article picture { max-width: 100%; }

/* ---------- 05 Evidence ---------- */
#section-05 picture { margin-top: 2rem; }
#section-05 picture img { border-radius: var(--radius-m); box-shadow: var(--shadow-soft); }
.stats {
  margin-top: 2.5rem;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.5rem;
}
.stats dt {
  font-weight: 700;
  font-size: var(--fs-display-m);
  letter-spacing: -0.01em;
}
.stats dd { color: var(--sage); margin-top: 0.5rem; }

/* ---------- 06 Why it holds up ---------- */
.grid-2x2 {
  margin-top: 2.5rem;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(1.5rem, 3vw, 3rem) clamp(2rem, 4vw, 4rem);
}
.grid-2x2 h3 { margin-bottom: 0.75rem; }
.grid-2x2 p { color: var(--sage); }

/* ---------- 07 Who it is for ---------- */
.who-list {
  margin-top: 2.5rem;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1.5rem;
}
.who-list h3 { font-size: 1rem; margin-bottom: 0.5rem; }
.who-list p { color: var(--sage); font-size: 0.9375rem; }

/* ---------- 08 What it costs ----------
   Reuses .grid-2x2 (defined under section 06 above) for the two item
   layout — same simple two column / one column pattern, no need for a
   dedicated class. */

/* ---------- FAQ ---------- */
.accordion { margin-top: 2rem; max-width: var(--content-narrow); }
.accordion details {
  border-top: 1px solid var(--line);
  padding: 1.25rem 0;
}
.accordion details:last-child { border-bottom: 1px solid var(--line); }
.accordion summary {
  cursor: pointer;
  font-weight: 700;
  font-size: 1.0625rem;
  min-height: 48px;
  display: flex;
  align-items: center;
  list-style: none;
}
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary::before {
  content: "+";
  color: var(--teal-deep);
  font-weight: 700;
  margin-right: 1rem;
  width: 1em;
}
.accordion details[open] summary::before { content: "\2212"; }
.accordion details p { color: var(--sage); margin-top: 0.75rem; padding-left: 2rem; }

/* ---------- Footer ---------- */
.site-footer {
  background: var(--ink);
  color: var(--paper);
  padding: var(--space-section) var(--space-gutter) 2.5rem;
}
.footer-brand { margin-bottom: 2.5rem; }
.footer-brand .brand-mark { width: 28px; height: 28px; }
.footer-brand .brand-word { font-size: 1.25rem; }
.footer-cols {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  max-width: var(--content-max);
  margin: 0 auto;
}
.footer-heading {
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sage-pale);
  margin-bottom: 1rem;
}
.footer-col a { text-decoration: none; }
.footer-col a:hover { color: var(--teal-bright); }
.footer-links li + li { margin-top: 0.6rem; }
.company-details p { color: var(--sage-pale); font-size: 0.9375rem; }
.company-details p + p { margin-top: 0.35rem; }
.footer-bottom {
  max-width: var(--content-max);
  margin: 3rem auto 0;
  color: var(--sage-pale);
  font-size: 0.8125rem;
}

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

@media (max-width: 899px) {
  .spine { display: none; }
}

@media (max-width: 960px) {
  .steps { grid-template-columns: 1fr; }
  .who-list { grid-template-columns: repeat(2, 1fr); }
  .grid-2x2 { grid-template-columns: 1fr; }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .pin-layout { grid-template-columns: 1fr; }
  .pin-visual { position: static; margin-bottom: 1rem; }
  .footer-cols { grid-template-columns: 1fr; gap: 2.5rem; }
}

@media (max-width: 640px) {
  .who-list { grid-template-columns: 1fr; }
  .stats { grid-template-columns: 1fr; }
  .reassurance { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
  .reassurance li + li { margin-left: 0; padding-left: 0; border-left: 0; }
}

@media (max-width: 400px) {
  .section, .hero { padding-left: 1.25rem; padding-right: 1.25rem; }
}

/* ============================================================
   Motion: page load sequence, scroll reveals, pinned panels
   Gated behind html.js so content stays visible with no script.
   ============================================================ */

/* Load sequence */
.js .brand,
.js .hero h1,
.js .hero .lede,
.js .hero .btn-primary {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}
.js.loaded .brand { opacity: 1; transform: none; }
.js.loaded .hero h1 { opacity: 1; transform: none; transition-delay: 0.12s; }
.js.loaded .hero .lede { opacity: 1; transform: none; transition-delay: 0.26s; }
.js.loaded .hero .btn-primary { opacity: 1; transform: none; transition-delay: 0.38s; }

.js .spine { opacity: 0; transition: opacity 0.5s ease; transition-delay: 0.5s; }
.js.loaded .spine { opacity: 1; }

/* Scroll reveals */
.js .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s ease, transform 0.6s ease;
  transition-delay: var(--reveal-delay, 0ms);
}
.js .is-visible.reveal,
.js .is-visible .reveal {
  opacity: 1;
  transform: none;
}

/* Panels inside a pinned sequence (sections 03/04) get their own reveal
   class rather than the shared .reveal above. Reason: .is-visible .reveal
   matches at any depth, so as soon as the section itself (also .is-visible)
   comes 15% into view, it would satisfy that rule for every .reveal
   descendant at once — popping all four panels in together instead of one
   by one as the visitor actually reaches each. .panel-reveal only responds
   to .is-visible on the same element, which site.js adds per panel as its
   own IntersectionObserver fires. */
.js .panel-reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.js .panel-reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* Pinned sequence panels: dim until active. Scoped to .pin-active, which
   site.js only adds when it has actually lifted the screenshots into the
   sticky visual — otherwise (mobile, reduced motion, no JS) every panel
   keeps its own inline screenshot and stays at full opacity, using the
   .panel-reveal treatment above instead. */
.js .pin-active .pin-copy article {
  opacity: 0.35;
  transition: opacity 0.4s ease;
}
.js .pin-active .pin-copy article.is-active { opacity: 1; }

/* Once the screenshots move out, .pin-copy is text only and collapses to a
   few hundred pixels — nowhere near enough scroll distance for GSAP to hold
   the pin across. Each panel needs real dwell time, so give it one on
   desktop specifically (mobile stays a compact, naturally stacked story). */
.js .pin-active .pin-copy article {
  min-height: 70vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* ============================================================
   Motion safety net (full reveal/pin logic lives in site.js)
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
