/* ---------- tokens ---------- */
:root {
  --bg: #ffffff;
  --text-primary: #111111;
  --text-secondary: #6b6b6b;
  --panel-border: #e5e5e5;
  --accent: #111111;
  /* the hover-selection ring and its name badge */
  --select: #0d99ff;
  --select-ease: cubic-bezier(0.32, 0.72, 0, 1);

  --font-body: "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* shared by the FAQ panel, its fade, and the caret — motion.js reads these
     so every part of an accordion toggle moves on one curve */
  --faq-duration: 340ms;
  --faq-ease: cubic-bezier(0.32, 0.72, 0, 1);

  --container: 1160px;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-weight: 900;
  -webkit-font-smoothing: antialiased;
}

/* The full-width horizontal hairlines are 100vw, which exceeds the document
   width whenever a vertical scrollbar is present — clip so that never turns
   into a horizontal scrollbar. */
main {
  overflow: clip;
}

/* ---------- hero ---------- */
.hero {
  position: relative;
  max-width: var(--container);
  margin: 0 auto;
  min-height: 70vh;
  padding: 4px 32px 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  text-align: center;
}

.site-header {
  position: relative;
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
  /* the bar is empty, so its former text height is held open explicitly */
  min-height: 44px;
  padding: 14px 40px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.site-header::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 100vw;
  height: 1px;
  margin-left: -50vw;
  background: var(--panel-border);
}

.site-footer {
  position: relative;
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
  padding: 14px 40px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.site-footer::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 100vw;
  height: 1px;
  margin-left: -50vw;
  background: var(--panel-border);
}

.brand-label {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.85rem;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  text-decoration: none;
  transition: opacity 0.3s ease;
}

/* Holds a measure-limited block — the tagline, the closing headline — out to
   the full column, so the band reads as wide as its neighbours while the type
   inside keeps its own line length. */
.text-band {
  position: relative;
  width: 100%;
  max-width: 640px;
}

.headline {
  position: relative;
  /* auto margins because it is centred inside .text-band now, not by the
     hero's own flex centring */
  margin: 0 auto;
  max-width: 32ch;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(1.4rem, 2.4vw, 2rem);
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  padding-top: 32px;
  padding-bottom: 32px;
}

/* The closing headline draws no bottom rule: it sits directly above the
   footer, whose ::before already rules that boundary. */

/* ---------- buttons ---------- */
/* A full-width band like the rest of the page rather than a shrink-wrapped
   row, so it rules the same column and its selection frame matches its
   neighbours. The leading gap is padding, not margin, so it belongs to the
   band and the button sits centred within it. */
.cta-row {
  position: relative;
  width: 100%;
  max-width: 640px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding-top: 32px;
  padding-bottom: 32px;
}

.cta-row::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 100vw;
  height: 1px;
  margin-left: -50vw;
  background: var(--panel-border);
}

.btn {
  display: inline-flex;
  align-items: center;
  /* centred rather than start-packed, so the label stays put once the button
     is stretched wider than its text — full width on a phone, card width in
     the pricing grid */
  justify-content: center;
  gap: 14px;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.95rem;
  text-decoration: none;
  padding: 8px 20px;
  border-radius: 4px;
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
    opacity 0.4s ease, box-shadow 0.4s ease;
}

.btn:hover {
  transform: translateY(-2px);
  opacity: 0.92;
}

.btn:active {
  transform: translateY(0);
  transition-duration: 0.1s;
}

.btn-white {
  background: transparent;
  color: var(--text-primary);
  border: 1px solid var(--panel-border);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.12);
}

.btn-dark {
  background: #2a2a2a;
  color: #ffffff;
}

.btn-key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 600;
}

.btn-dark .btn-key {
  background: rgba(255, 255, 255, 0.16);
  color: #ffffff;
}

.btn-white .btn-key {
  background: var(--panel-border);
  color: var(--text-secondary);
}

/* One continuous pair of column rules for the whole page. Each band used to
   carry its own 100vh-tall pair, which meant neighbouring bands stacked their
   lines on top of each other — doubling up wherever a band faded or slid in. */
.hero-grid {
  position: absolute;
  z-index: 51;
  top: 0;
  bottom: 0;
  left: 32px;
  right: 32px;
  max-width: 640px;
  margin-inline: auto;
  pointer-events: none;
}

.hero-grid::before,
.hero-grid::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--panel-border);
}

.hero-grid::before {
  left: 0;
}

.hero-grid::after {
  right: 0;
}

/* ---------- pricing ---------- */
/* Neither section carries a heading any more, so both sit flush against the
   hairline above them with no leading gap. */
.pricing,
.faq {
  position: relative;
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
  padding: 0;
  text-align: left;
}

.pricing::after,
.faq::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 100vw;
  height: 1px;
  margin-left: -50vw;
  background: var(--panel-border);
}

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
}

.pricing-card {
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border: 1px solid var(--panel-border);
  border-top: none;
  border-bottom: none;
  padding: 20px 18px;
}

.pricing-card-featured {
  border-color: var(--panel-border);
}

.pricing-name {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--text-primary);
}

.pricing-price {
  margin: 8px 0 16px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1.6rem;
  letter-spacing: -0.02em;
  color: var(--text-primary);
}

.pricing-price span {
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.pricing-features {
  flex: 1;
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.pricing-features li {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.82rem;
  line-height: 1.35;
  color: var(--text-secondary);
  padding: 8px 0;
}

.pricing-features li + li {
  border-top: 1px dashed #cbcbcb;
}

.pricing-card .btn {
  font-size: 0.85rem;
  padding: 8px 12px;
}

/* ---------- faq ---------- */
.faq-list {
  display: flex;
  flex-direction: column;
}

.faq-item {
  border-bottom: 1px dashed #cbcbcb;
}

.faq-q {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 40px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--text-primary);
}

.faq-q::-webkit-details-marker {
  display: none;
}

/* The nudge that optically centres the caret rides inside the transform, so
   it interpolates with the rotation instead of jumping at the halfway point. */
.faq-q::after {
  content: "";
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-right: 1.5px solid #b0b0b0;
  border-bottom: 1.5px solid #b0b0b0;
  transform: translateY(-3px) rotate(45deg);
  transition: transform var(--faq-duration) var(--faq-ease);
}

.js-faq .faq-item.is-open .faq-q::after,
html:not(.js-faq) .faq-item[open] .faq-q::after {
  transform: translateY(3px) rotate(-135deg);
}

/* motion.js animates the panel's height directly; it only needs the clip. */
.js-faq .faq-a {
  overflow: hidden;
}

.faq-a-inner {
  padding: 0 40px 20px;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

/* The fade runs on the same clock as the height so the two read as one
   movement — no lag, no delay to catch up on a fast second click. */
.js-faq .faq-a-inner {
  opacity: 0;
  transition: opacity var(--faq-duration) var(--faq-ease);
}

.js-faq .faq-item.is-open .faq-a-inner {
  opacity: 1;
}

/* animated "soffo" wordmark that opens the hero */
.wordmark-band {
  position: relative;
  width: 100%;
  max-width: 640px;
  padding-top: 20px;
  padding-bottom: 30px;
}

.wordmark-band::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 100vw;
  height: 1px;
  margin-left: -50vw;
  background: var(--panel-border);
}

.tile-field-host {
  position: relative;
  width: 100%;
}

.hero-tagline {
  position: relative;
  max-width: 44ch;
  margin: 0 auto;
  padding-top: 32px;
  padding-bottom: 32px;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.95rem;
  line-height: 1.45;
  letter-spacing: -0.01em;
  color: var(--text-secondary);
  text-align: center;
}

.hero-tagline::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 100vw;
  height: 1px;
  margin-left: -50vw;
  background: var(--panel-border);
}

.tile-field-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ---------- frame selection on hover ---------- */
/* A single ring, moved onto whichever band the pointer is over. It sits above
   the column rules (51) and never takes the pointer, so hovering it can't
   fight with the element underneath. */
.frame-select {
  position: absolute;
  z-index: 60;
  pointer-events: none;
  opacity: 0;
  box-shadow: 0 0 0 1px var(--select);
  transition: left 140ms var(--select-ease), top 140ms var(--select-ease),
    width 140ms var(--select-ease), height 140ms var(--select-ease),
    opacity 110ms linear;
}

.frame-select.is-active {
  opacity: 1;
}

/* Used for the single frame in which the ring is repositioned before it fades
   in, so it never travels from its last frame's box. */
.frame-select.is-snapping {
  transition: none;
}

.frame-handle {
  position: absolute;
  width: 7px;
  height: 7px;
  background: var(--bg);
  border: 1px solid var(--select);
}

.frame-handle-nw {
  top: -4px;
  left: -4px;
}

.frame-handle-ne {
  top: -4px;
  right: -4px;
}

.frame-handle-sw {
  bottom: -4px;
  left: -4px;
}

.frame-handle-se {
  bottom: -4px;
  right: -4px;
}

/* The badge Figma prints under a selection — the frame's name here rather than
   its measurements. */
.frame-label {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 6px;
  padding: 2px 6px;
  border-radius: 2px;
  background: var(--select);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.68rem;
  line-height: 1.35;
  letter-spacing: 0;
  color: #ffffff;
  white-space: nowrap;
}

/* Nothing below the last band to hang the badge over, so it flips to the top
   edge instead of running off the end of the page. */
.frame-select.is-flipped .frame-label {
  top: auto;
  bottom: 100%;
  margin-top: 0;
  margin-bottom: 6px;
}

@media (max-width: 560px) {
  /* Same shape as the desktop hero — the bands themselves carry the vertical
     rhythm, so the hero only sets the side gutter the column rules align to. */
  .hero {
    padding: 4px 20px 0;
  }

  .hero-grid {
    left: 20px;
    right: 20px;
  }

  /* Both bars are near-empty, so on a phone they only need to be tall enough
     to read as a bar above and below the content. */
  .site-header {
    min-height: 0;
    padding: 9px 20px;
  }

  .site-footer {
    padding: 9px 20px;
  }

  /* The band keeps the full column width like every other one — it is the
     band's own padding, not a narrower band, that insets the button. */
  .cta-row {
    padding: 24px 20px;
  }

  .cta-row .btn {
    width: 100%;
    max-width: 320px;
    padding: 12px 20px;
  }

  /* The 40px gutters read as generous next to a 32px desktop page margin and
     as cramped next to a 20px one — match the page gutter instead. */
  .faq-q {
    gap: 12px;
    padding: 16px 20px;
  }

  .faq-a-inner {
    padding: 0 20px 16px;
  }

  .hero-tagline,
  .headline {
    padding-top: 24px;
    padding-bottom: 24px;
  }

  .pricing-grid {
    grid-template-columns: 1fr;
  }

}

/* a little breathing room above anchor targets */
#pricing,
#faq {
  scroll-margin-top: 32px;
}

/* ---------- motion ---------- */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }

  .js-motion .hero-tagline,
  .js-motion .headline,
  .js-motion .cta-row,
  .js-motion .pricing,
  .js-motion .faq {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1),
      transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
    will-change: opacity, transform;
  }

  .js-motion .is-visible {
    opacity: 1;
    transform: none;
  }
}
