/* ==========================================================================
   FAQ  —  21st.dev "text-reveal-faqs", resolved to CSS

   The client's Tailwind turned into real values, so the proportions are the
   reference's rather than an approximation:

     py-16 / md:py-24      64px / 96px
     max-w-5xl / px-6      1024px / 24px
     grid gap-8 / md:gap-12   32px / 48px
     md:grid-cols-5        heading spans 2, accordion spans 3
     text-4xl font-semibold   36px / 600
     mt-4 text-lg          16px / 18px, text-balance
     mt-6                  24px
     border-b              1px hairline per row
     py-4                  16px on the trigger
     text-base font-medium 16px / 500
     h-4 w-4               16px chevron, rotate 180deg when open
     text-sm               14px answer
     pb-4 pt-0             16px below the answer, nothing above
     0.2s ease-out         the height change
     stagger 0.015 / 0.3s  the per-character reveal, blur(10px) -> blur(0)

   Changed: the palette and the display face. --primary becomes her ink and
   the headings take the brand serif. The reference's hover:underline on the
   trigger is dropped, as its own demo does with hover:no-underline.
   ========================================================================== */

.yp-faq {
  /* Shell, so it alternates against the Sand of Book a Call directly above.
     On White it read as a page that had stopped rather than a next section. */
  background: rgb(var(--yp-shell-rgb));
  padding: 64px 0;
}

@media (min-width: 768px) { .yp-faq { padding: 96px 0; } }

.yp-faq-wrap {
  max-width: 1024px;
  margin: 0 auto;
  padding: 0 24px;
}

/* ---- the 5-column grid --------------------------------------------------- */

.yp-faq-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 32px;
}

@media (min-width: 768px) {
  .yp-faq-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 48px;
  }
  .yp-faq-lead { grid-column: span 2; }
  .yp-faq-list { grid-column: span 3; }
}

/* ---- heading column ------------------------------------------------------ */

/* Divi pads every heading and typography.css forces a weight onto them, so
   both have to be taken back. Its inline rule also zeroes letter-spacing on
   h1-h6 and p with !important, which is what the tracking below is beating. */
.yp-faq-title {
  margin: 0;
  padding: 0 !important;
  font-family: var(--yp-serif);
  /* The reference is text-4xl font-semibold, which is 36px/600. That reads as
     a solid block in the sans a shadcn project ships. Newsreader is a serif
     with lighter stems and a smaller x-height, so the same numbers came out
     thin and small beside this site's other section heads. Matching the
     reference's WEIGHT on the page rather than its numeric values: up to the
     display scale the rest of the site uses, at the top of Newsreader's
     range. */
  font-size: clamp(2.25rem, 1.6rem + 1.9vw, 3rem);
  line-height: 1.05;
  font-weight: 800 !important;
  letter-spacing: -0.035em !important;
  color: var(--yp-ink);
}

.yp-faq-deck {
  margin: 18px 0 0;
  padding: 0 !important;
  font-size: 19px;
  line-height: 1.55;
  letter-spacing: 0 !important;
  color: rgb(var(--yp-ink-rgb) / 0.66);
  /* balance, not pretty: the deck is two lines in a narrow column, and pretty
     only fixes orphans. Without it the break fell after "ask", splitting
     "ask me". */
  text-wrap: balance;
}

.yp-faq-aside {
  margin: 24px 0 0;
  padding: 0 !important;
  font-size: 15px;
  line-height: 1.6;
  letter-spacing: 0 !important;
  color: rgb(var(--yp-ink-rgb) / 0.62);
}

/* The reference shows this line in the heading column on desktop and repeats
   it under the accordion on mobile, so it is never stranded at the top of a
   long list of questions. Two elements, one visible at a time. */
.yp-faq-aside-wide { display: none; }
.yp-faq-aside-narrow { display: block; }

@media (min-width: 768px) {
  .yp-faq-aside-wide { display: block; }
  .yp-faq-aside-narrow { display: none; }
}

.yp-faq-link {
  color: var(--yp-ink);
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid rgb(var(--yp-ink-rgb) / 0.3);
  transition: border-color 200ms ease;
}

.yp-faq-link:hover { border-color: var(--yp-ink); }

/* ---- rows ---------------------------------------------------------------- */

.yp-faq-item { border-bottom: 1px solid rgb(var(--yp-ink-rgb) / 0.13); }

.yp-faq-q {
  margin: 0;
  padding: 0 !important;
  font-weight: inherit !important;
  letter-spacing: 0 !important;
}

.yp-faq-trigger {
  appearance: none;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 21px 0;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
  font-family: var(--yp-serif);
  font-size: 17.5px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--yp-ink);
  transition: color 200ms ease;
}

.yp-faq-trigger:hover { color: rgb(var(--yp-ink-rgb) / 0.7); }

.yp-faq-trigger:focus-visible {
  outline: 2px solid var(--yp-ink);
  outline-offset: 2px;
}

.yp-faq-chev {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  transition: transform 200ms ease-out;
}

.yp-faq-trigger[aria-expanded="true"] .yp-faq-chev { transform: rotate(180deg); }

/* ---- answers ------------------------------------------------------------- */

/* Radix animates from 0 to --radix-accordion-content-height, which it has to
   measure in JS. A grid track does the same job with no measurement at all:
   0fr to 1fr, and the browser resolves 1fr from the content itself. That means
   no height to recompute when the viewport changes or a webfont lands, and no
   stale value if the answer text is ever edited. */
.yp-faq-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 200ms ease-out;
}

.yp-faq-a.is-open { grid-template-rows: 1fr; }

/* Both are required for the track to actually collapse: a grid item's
   automatic minimum size is its content, so without min-height:0 the row
   never reaches 0fr, and without overflow:hidden the text spills out of the
   collapsed row instead of being clipped. */
/* No padding on the grid ITEM. Padding is part of its box, so at 0fr the
   track could not collapse below the 16px bottom padding and exactly one line
   of every closed answer showed through, overlapping the row's own border.
   The spacing moves inside, where the clip can reach it. */
.yp-faq-a-inner {
  overflow: hidden;
  min-height: 0;
}

.yp-faq-text-wrap { padding: 0 0 22px; }

/* Animatable grid tracks are recent (Chrome 117, Firefox 127, Safari 17.2).
   Where they are not supported the rows still open and close, just without
   the 200ms, which is a better failure than a panel that never opens. */
@supports not (grid-template-rows: 0fr) {
  .yp-faq-a { display: block; height: 0; overflow: hidden; transition: none; }
  .yp-faq-a.is-open { height: auto; }
}

.yp-faq-text {
  margin: 0;
  padding: 0 !important;
  max-width: 62ch;
  font-size: 15.5px;
  line-height: 1.68;
  letter-spacing: 0 !important;
  color: rgb(var(--yp-ink-rgb) / 0.82);
  overflow-wrap: break-word;
}

/* ---- the per-character reveal -------------------------------------------
   The reference's BlurredStagger: every character starts at opacity 0 and
   blur(10px) and resolves over 300ms, each one 15ms behind the last. The
   delay is written onto the span by the script, because CSS cannot count.

   inline-block is what makes the blur render per character; the script keeps
   words intact so nothing breaks mid-word when the line wraps. */
.yp-faq-ch {
  display: inline-block;
  white-space: pre;
  opacity: 0;
  filter: blur(10px);
  transition: opacity 300ms ease, filter 300ms ease;
}

.yp-faq-a.is-open .yp-faq-ch { opacity: 1; filter: blur(0); }

/* No JS, or the script bailed: every answer is simply open and legible. */
.yp-faq-a:not(.is-ready) { grid-template-rows: 1fr; }
.yp-faq-a:not(.is-ready) .yp-faq-ch { opacity: 1; filter: none; }

/* ---- narrow -------------------------------------------------------------- */

@media (max-width: 420px) {
  .yp-faq-title { font-size: 30px; }
  .yp-faq-deck { font-size: 16.5px; }
  .yp-faq-trigger { font-size: 15.5px; gap: 12px; }
}

/* ---- reduced motion ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .yp-faq-a { transition: none; }
  .yp-faq-chev { transition: none; }
  /* The stagger is the effect, and 300 characters resolving one after another
     is exactly what someone asking for reduced motion does not want. The text
     simply appears. */
  .yp-faq-ch {
    transition: none;
    opacity: 1;
    filter: none;
  }
}

/* The site marks every section with a small eyebrow above the display line.
   The FAQ had none, which is a large part of why it read as something pasted
   in rather than as one of this page's sections. */
.yp-faq-eyebrow {
  margin: 0 0 14px;
  padding: 0 !important;
  letter-spacing: 0.18em !important;
}

/* The chevron was a 16px hairline against a 17.5px serif question; at that
   weight it looked like a stray mark. */
.yp-faq-chev { width: 18px; height: 18px; opacity: 0.55; }
.yp-faq-trigger:hover .yp-faq-chev,
.yp-faq-trigger[aria-expanded="true"] .yp-faq-chev { opacity: 1; }
