/* ==========================================================================
   Solvyn — Component Library
   Every rule here is traced to a real Figma instance in 343:12327 (Intro),
   343:12273 (Intro - Opener) or 421:173 (Home). Nothing invented except
   where explicitly marked "UNSPECIFIED IN FIGMA" — those need a decision,
   not a guess.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Button — "Learn More Button" (Figma's own layer name)
   ONE component family reused verbatim for: "Let's work together",
   "View our project" (hero) and "Start a project" (footer). Only the icon
   and label text change — never the shell.
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4, 4px); /* Figma: gap 4px on this component, not the 16px space-4 token */
  gap: 4px;
  padding: 12px 16px 12px 12px; /* pl-12 pr-16 py-12 */
  border-radius: var(--radius-pill);
  border: 2px solid var(--white);
  background: rgba(255, 255, 255, 0.25);
  box-shadow: var(--shadow-button);
  font-family: var(--font-display);
  font-weight: var(--weight-regular);
  font-size: var(--text-14);
  line-height: 1;
  color: var(--black);
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
}

.btn__icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

/* Per-letter hover lift — behavior only (not the reference's red/glossy
   styling): each character is its own inline-block span (wrapped by JS)
   so hovering one letter lifts just that letter. -4px, not the
   reference's -7px, since our label is 14px vs. their 24px bold. */
.btn__label {
  display: inline-flex; /* single flex item — keeps .btn's icon<->label gap:4px
                            from also inserting itself between every letter */
  flex-shrink: 0;
}
.btn__letter {
  display: inline-block;
  transition: transform 0.3s ease-out;
}
.btn__letter:hover {
  transform: translateY(-4px);
}

/* UNSPECIFIED IN FIGMA — no hover/active/disabled variant exists on this
   component in the file. These are a conservative placeholder consistent
   with the glassmorphic look (raise fill opacity + tiny lift on hover,
   settle on press). Flag before shipping — confirm or replace. */
.btn:hover {
  background: rgba(255, 255, 255, 0.4);
  transform: translateY(-1px);
}
.btn:active {
  background: rgba(255, 255, 255, 0.5);
  transform: translateY(0);
}
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

/* Text-link variant — "View our visuals" (no pill, label + arrow only) */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: var(--font-display);
  font-weight: var(--weight-regular);
  font-size: var(--text-12);
  color: var(--slate-400);
  text-align: center;
  cursor: pointer;
  text-decoration: none;
}
.link-arrow:hover { color: var(--slate-700); }
.link-arrow__icon {
  width: 16px;
  height: 16px;
}

/* --------------------------------------------------------------------------
   Sidebar nav item — Home / Our projects / UI visuals / Pricing
   Two confirmed states: active (Home) vs inactive (the rest).
   -------------------------------------------------------------------------- */
.nav-item {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 133px;
  font-family: var(--font-display);
  font-size: var(--text-14);
  line-height: 21px;
  text-decoration: none;
  transition: color 0.15s ease;
}
.nav-item__icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}
/* For icons where no separate bold/filled asset exists (Our projects, UI
   visuals): render as a CSS mask so background-color (not the SVG's own
   baked-in stroke color) drives it — lets hover actually recolor the icon,
   not just the label text, without inventing a bold asset that isn't in Figma. */
.nav-item__icon--mask {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  background-color: var(--slate-400);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  transition: background-color 0.15s ease;
}
.nav-item:hover .nav-item__icon--mask,
.nav-item:focus-visible .nav-item__icon--mask {
  background-color: var(--slate-700);
}
.nav-item--active .nav-item__icon--mask {
  background-color: var(--slate-900);
}
/* Icon crossfade: outline by default, swaps to the bold/filled glyph on
   hover/focus/active — matches how Figma renders whichever nav item is the
   *current* page as bold (confirmed on the Pricing page instance). */
.nav-item__icon-stack {
  position: relative;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}
.nav-item__icon-stack img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transition: opacity 0.15s ease;
}
.nav-item__icon-stack .icon-bold { opacity: 0; }
.nav-item:hover .nav-item__icon-stack .icon-outline,
.nav-item:focus-visible .nav-item__icon-stack .icon-outline { opacity: 0; }
.nav-item:hover .nav-item__icon-stack .icon-bold,
.nav-item:focus-visible .nav-item__icon-stack .icon-bold { opacity: 1; }
.nav-item--active .nav-item__icon-stack .icon-outline { opacity: 0; }
.nav-item--active .nav-item__icon-stack .icon-bold { opacity: 1; }
.nav-item--active {
  color: var(--slate-900); /* NOTE: Opener uses slate-700, full Home hero uses slate-900 for the same active state — defaulted to slate-900 (the more common instance) */
  font-weight: var(--weight-medium);
}
.nav-item--inactive {
  color: var(--slate-400);
  font-weight: var(--weight-regular);
}
.nav-item--inactive:hover,
.nav-item--inactive:focus-visible {
  color: var(--slate-700);
}
.nav-item--inactive:active {
  color: var(--slate-900);
}

/* --------------------------------------------------------------------------
   Section label — small colored square + uppercase caption + rule line
   Color of the square changes per section (confirmed instances below).
   -------------------------------------------------------------------------- */
.section-label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
}
.section-label__dot {
  width: 12px;
  height: 12px;
  border-radius: 1px;
  flex-shrink: 0;
}
.section-label__dot--orange { background: var(--orange-500); } /* WHY WE EXIST, TESTIMONIALS */
.section-label__dot--blue   { background: var(--blue-500); }   /* HOW WE WORK, ANSWERS TO SOME QUESTIONS */
.section-label__dot--purple { background: var(--purple-400); } /* WHAT WE BELIEVE, STATISTICS */
.section-label__text {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-14);
  line-height: 1.65;
  color: var(--slate-400);
  white-space: nowrap;
  text-transform: uppercase;
}
.section-label__rule {
  flex: 1 0 0;
  height: 1px;
  background: var(--slate-200);
}

/* --------------------------------------------------------------------------
   Process / feature card — "How We Work" 5-up grid
   Same shell, 3 tint variants tied to the same 3 accent colors as above.
   -------------------------------------------------------------------------- */
.feature-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: 24px 20px;
  border-radius: var(--radius-card);
  border: 1.5px solid var(--white);
  backdrop-filter: blur(3.9px);
  transition: transform 0.2s ease;
}
/* hover: hover + pointer: fine, not a max-width query — touch devices
   (phone AND tablet, any orientation/width) have no real hover state, so
   a finger-tap was leaving the card "stuck" scaled up until the next tap
   elsewhere. Scoping by input capability instead of viewport width is
   also correct for a touch-screen laptop, unlike a max-width cutoff. */
@media (hover: hover) and (pointer: fine) {
  .feature-card:hover { transform: scale(1.04); }
}
.feature-card--blue   { background: var(--tint-blue); }
.feature-card--orange { background: var(--tint-orange); }
.feature-card--purple { background: var(--tint-purple); }
/* Scroll-triggered entrance (js/process-cards.js) — one card at a time,
   not all five together. Higher specificity than the base rule's
   transform transition so it can use its own longer duration for the
   fade+rise without slowing down the hover scale above once the card has
   settled; js only ever REMOVES this class (never adds a resting-state
   class), so once it's gone the card falls back to plain default
   styling and .feature-card:hover works exactly as before. */
.feature-card.reveal-hidden {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s cubic-bezier(0.19,1,0.22,1), transform 0.6s cubic-bezier(0.19,1,0.22,1);
}
@media (prefers-reduced-motion: reduce) {
  .feature-card.reveal-hidden { opacity: 1; transform: none; transition: none; }
}

.feature-card__dot {
  width: 12px;
  height: 12px;
  border-radius: 1px;
  border: 1px solid currentColor;
  margin-bottom: var(--space-2);
}
.feature-card--blue .feature-card__dot   { color: var(--blue-500); }
.feature-card--orange .feature-card__dot { color: var(--orange-500); }
.feature-card--purple .feature-card__dot { color: var(--purple-500); }

.feature-card__title {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-18);
  line-height: 1.3;
  color: var(--slate-900);
}
.feature-card__body {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-14);
  line-height: 1.4;
  color: var(--slate-500);
}

/* Service list row (Mobile App Design, Website Design, ...) — title + body,
   no card shell, just the type pairing */
.service-row__title {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-18);
  line-height: 1.3;
  color: var(--slate-900);
}
.service-row__body {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-14);
  line-height: 1.4;
  color: var(--slate-500);
}
.service-row__index {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-14);
  letter-spacing: -0.28px;
  color: var(--slate-400);
}
.service-row__index--active { color: var(--black); }

/* --------------------------------------------------------------------------
   Testimonial card — white outer shell + tinted inner quote panel
   -------------------------------------------------------------------------- */
.testimonial {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  width: 353px;
  padding: 16px 10px 10px;
  background: var(--white);
  border-radius: var(--radius-testimonial);
}
.testimonial__stars {
  height: 18.8px;
  width: 94px;
  margin: 0 14px;
}
.testimonial__panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  padding: 24px 20px;
  border-radius: var(--radius-card);
  background: var(--tint-orange);
  backdrop-filter: blur(3.9px);
}
.testimonial__quote {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-16);
  line-height: 1.55;
  color: var(--orange-900);
}
.testimonial__author {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
}
.testimonial__avatar {
  width: 45px;
  height: 45px;
  border-radius: var(--radius-avatar);
  object-fit: cover;
}
.testimonial__name {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-16);
  line-height: 1.3;
  color: var(--orange-950);
}
/* per-card colour variants (default = orange) */
.testimonial--blue .testimonial__panel { background: var(--tint-blue); }
.testimonial--blue .testimonial__quote { color: var(--blue-950); }
.testimonial--blue .testimonial__name { color: var(--blue-950); }
.testimonial--blue .testimonial__role { color: var(--blue-700); }
.testimonial--blue .testimonial__stars { filter: hue-rotate(200deg); }
.testimonial--purple .testimonial__panel { background: var(--tint-purple); }
.testimonial--purple .testimonial__quote { color: var(--purple-800); }
.testimonial--purple .testimonial__name { color: var(--purple-800); }
.testimonial--purple .testimonial__role { color: var(--purple-500); }
.testimonial--purple .testimonial__stars { filter: hue-rotate(247deg) saturate(0.8); }
.testimonial__role {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-14);
  line-height: 1.3;
  color: var(--orange-700);
}
/* Carousel dots — active = filled pill, inactive = outline circle */
.testimonial-dots { display: flex; align-items: center; gap: 4px; }
.testimonial-dots__dot {
  width: 6px;
  height: 6px;
  border-radius: 50px;
  border: 1px solid var(--orange-500);
}
.testimonial-dots__dot--active {
  width: 31px;
  background: var(--orange-500);
  border: none;
}

/* --------------------------------------------------------------------------
   FAQ accordion row — all 7 rows now carry real answer text.
   Fixed 2026-08-18: `gap:116px; align-items:center` was on `.faq-row`
   itself (the outer column that also holds the answer paragraph below),
   not on `.faq-row__top` (the question+icon line) — so the icon had no
   flex context at all and stacked under the question as a plain block.
   That gap/align-items belongs on `.faq-row__top`; `.faq-row` itself
   needs `flex-direction: column` so the answer sits below, full-width.
   Visibility is now pure CSS (`.faq-row--closed .faq-row__answer` is
   hidden) since every row has its answer `<p>` in the HTML at all times
   — the accordion JS used to remove/never-restore that element on
   toggle, which meant clicking a row could never actually show its
   answer except row 1's original untouched state.
   -------------------------------------------------------------------------- */
.faq-row {
  display: flex;
  flex-direction: column;
  width: 100%;
}
.faq-row__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 116px;
  width: 100%;
  cursor: pointer;
}
.faq-row__question {
  font-family: var(--font-display);
  font-size: var(--text-16);
  line-height: 1.3;
  color: var(--slate-900);
}
.faq-row--open .faq-row__question { font-weight: var(--weight-semibold); }
.faq-row--closed .faq-row__question { font-weight: var(--weight-regular); }
.faq-row__answer {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-14);
  line-height: 1.4;
  color: var(--slate-500);
  margin-top: var(--space-2);
}
.faq-row--closed .faq-row__answer { display: none; }
.faq-row__icon { width: 16px; height: 16px; flex-shrink: 0; object-fit: contain; }

/* --------------------------------------------------------------------------
   Stats panel — dark gradient-photo card, right-aligned number/label pairs
   -------------------------------------------------------------------------- */
.stat-pair {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  width: 136px;
  text-align: right;
}
.stat-pair__number {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-24);
  line-height: 1.15;
  color: var(--white);
}
.stat-pair__label {
  font-family: var(--font-display);
  font-weight: var(--weight-regular);
  font-size: var(--text-14);
  line-height: 1.15;
  color: rgba(248, 250, 252, 0.7);
}

/* --------------------------------------------------------------------------
   Ticker — "BRANDING • MARKETING DESIGN • SHOPIFY DEV ..."
   Continuous auto-scroll, back to a plain CSS animation (the scroll-
   velocity-only version was tried live and rejected — it sat static
   except while actively scrolling, which read as broken/lifeless).
   Figma node 421:402 has TWO real stacked rows (421:403 top:0, 421:415
   top:82px), both simultaneously visible, moving in opposite directions
   (the standard "woven" two-row ticker look). Each row's word list is
   duplicated internally for a seamless loop (translateX 0 -> -50%).
   -------------------------------------------------------------------------- */
.marquee {
  overflow: hidden;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.marquee__row {
  overflow: hidden;
  width: 100%;
}
.marquee__track {
  display: flex;
  gap: 32px;
  align-items: center;
  width: max-content;
  animation: marquee-scroll 30s linear infinite;
}
.marquee__row:nth-child(2) .marquee__track { animation-name: marquee-scroll-reverse; }
.marquee__word {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-64);
  line-height: 0.9;
  letter-spacing: -1.28px;
  text-transform: uppercase;
  color: var(--black);
  white-space: nowrap;
}
.marquee__dot { width: 26px; height: 26px; flex-shrink: 0; }
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@keyframes marquee-scroll-reverse {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
}

/* --------------------------------------------------------------------------
   Video demo control pill (hero) — frosted glass bar w/ play button
   -------------------------------------------------------------------------- */
.video-controls {
  display: flex;
  align-items: center;
  padding: 8px;
  gap: 13px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.35);
  border: 1px solid var(--white);
  backdrop-filter: blur(8px);
  box-shadow: var(--shadow-video-pill);
}
.video-controls__chip {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  border-radius: var(--radius-pill);
  background: #f1f1f1;
}
.video-controls__chip svg,
.video-controls__chip img { width: 18px; height: 18px; }
.video-controls__time {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-14);
  line-height: 1.4;
  color: var(--slate-700);
}
.video-controls__play {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  border-radius: 86.538px;
  background: linear-gradient(to bottom, #9465ee, var(--purple-500) 86.538%);
  box-shadow: inset 0px 0px 0px 0.865px rgba(255, 255, 255, 0.38);
}

/* --------------------------------------------------------------------------
   Social icon chip (top-right nav — X / Instagram)
   -------------------------------------------------------------------------- */
.social-chip-link { position: relative; display: block; text-decoration: none; }
.social-chip {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-chip);
  border: 1px solid var(--white);
  box-shadow: var(--shadow-chip);
  background: rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(2px);
  transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
.social-chip-link:hover .social-chip,
.social-chip-link:focus-visible .social-chip {
  transform: scale(1.12);
  background: rgba(255, 255, 255, 0.55);
  border-color: var(--purple-400);
}

/* Tooltip overlay — same interaction as the user's reference (bouncy
   cubic-bezier pop, pointer triangle), simplified to a plain white
   label per their spec: l/r 14, t/b 10 padding, autolayout, no
   per-platform brand color swap. */
.social-tooltip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 10px);
  transform: translateX(-50%) translateY(6px) scale(0.85);
  display: inline-flex;
  padding: 10px 14px;
  border-radius: var(--radius-chip);
  background: var(--white);
  box-shadow: var(--shadow-chip);
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-12);
  line-height: 1;
  color: var(--slate-900);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55), transform 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.social-tooltip::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -4px;
  width: 8px;
  height: 8px;
  background: var(--white);
  transform: translateX(-50%) rotate(45deg);
}
.social-chip-link:hover .social-tooltip,
.social-chip-link:focus-visible .social-tooltip {
  opacity: 1;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0) scale(1);
}

/* --------------------------------------------------------------------------
   Surfaces — the rounded content column + dark intro screen
   -------------------------------------------------------------------------- */
.page-canvas {
  background: var(--bg-canvas);
}
.content-panel {
  background: var(--bg-panel);
  border-radius: var(--radius-panel-lg);
}
.intro-screen {
  background: var(--bg-intro);
  color: var(--white);
}

/* Giant wordmark (Intro hero + footer CTA share the base treatment; sizes,
   colors, AND tracking/leading differ per instance — verified against
   Figma node 421:511 for the footer, 2026-08-18. The shared -0.07em
   tracking / line-height:1 below are the Intro node's own values (kept as
   the base since Intro was built first); the footer node in Figma has
   NEITHER — default (0) letter-spacing and line-height:0.87 — so the
   earlier version of this file, which let the footer wordmark inherit
   Intro's tracking/leading unchanged, was rendering it measurably
   tighter and taller than the design. */
.wordmark {
  font-family: var(--font-display);
  font-weight: var(--weight-extrabold);
  line-height: 1;
  letter-spacing: -0.07em; /* -14px at 200px = -7%, Intro's own value — do not assume this applies to other instances */
  white-space: nowrap;
}
.wordmark--intro { font-size: var(--text-200); color: var(--white); }
.wordmark--footer {
  font-weight: var(--weight-black);
  font-size: var(--text-190);
  color: var(--purple-800);
  line-height: 0.87; /* Figma: leading-[0.87], not the Intro's leading-none */
  letter-spacing: normal; /* Figma: no tracking value on this node at all */
  font-optical-sizing: auto; /* engages the loaded variable Inter's opsz axis so large sizes approximate Figma's "Inter Display" cut — see css/fonts.css */
}

/* visually hidden but available to screen readers / crawlers (page <h1>s) */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* .btn is used on <a> as well as <button> */
a.btn { text-decoration: none; }

/* Mobile top bar: frosted so the logo + menu stay readable over any content */
.mobile-nav {
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  backdrop-filter: blur(16px) saturate(1.4);
  background: rgba(240, 240, 240, 0.72);
  box-sizing: border-box;
  min-height: 64px;
  padding-bottom: 12px !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.6);
}
