/**
 * Theme Name:     Verge
 * Author:         Appetiser
 * Template:       generatepress
 * Text Domain:    appetiser
 * Description:    Landing page theme for Verge. GeneratePress child theme built on the Appetiser Baseplate: landing pages assembled from self-contained section components under /components — no page builder, no build step. Text domain, function prefix (apt_), options key (apt_options) and submissions table ({prefix}apt_submissions) are inherited from the baseplate and intentionally unchanged.
 * Version:        0.1.0
 */

/* ── Design Tokens ──────────────────────────────────────────────
 * Colours are exact, read from the Figma SVG export of the Homepage frame
 * (2026-09-24), not sampled off a PNG — except the budget-card colours, which
 * come from the card images embedded in that same export.
 * Type sizes were solved from the outlined glyphs in the export against the
 * real Saira Condensed / Work Sans metrics (cap height + ink width), which is
 * also where the letter-spacing values come from.
 * ------------------------------------------------------------- */
:root {
  /* Colour */
  --color-bg:            #0B1013;
  --color-surface:       #10181F; /* budget cards */
  --color-track:         #22272C; /* progress-bar track */
  --color-text:          #FFFFFF; /* headings */
  --color-text-muted:    #C5C5C5; /* body copy */
  --color-icon:          #E7EFF1;
  --color-accent:        #9DFF52; /* every CTA */
  --color-accent-hover:  #B6FF7E;
  --color-accent-ink:    #0B1013; /* text on the accent */
  --color-logo-green:    #80E434;
  --color-placeholder:   #9B9B9B;
  --color-field:         #FFFFFF;
  --color-field-border:  #44494F;
  --color-step-num:      #5890A0;
  --color-teal-hi:       #0F6771;
  --color-teal-lo:       #012428;
  --color-teal-deep:     #010D0E; /* feature tiles' small blurred squares */
  --color-teal-glow:     #114D54;
  --color-panel:         #0D4F57; /* contact panel gradient, bottom-left */
  --color-error:         #FF6B6B;

  /* Budget categories (budget_marquee) — the Verge app's own eleven, from
     verge-api's TransactionCategorySeeder (colours sampled there from the
     design exports). Keys match the API's `key`, with _ as -. */
  --cat-groceries:     #76F892;
  --cat-bills:         #82F1F3;
  --cat-transport:     #FFDE84;
  --cat-shopping:      #FF84CA;
  --cat-savings:       #2DD4BF;
  --cat-eating-out:    #FFB273;
  --cat-investment:    #AD89FF;
  --cat-subscriptions: #7AA0FF;
  --cat-pet-supplies:  #F2FE85;
  --cat-hobbies:       #FF8C8C;
  --cat-other:         #CACACA;

  /* Typography */
  --font-title: 'Saira Condensed', 'Arial Narrow', sans-serif;
  --font-body:  'Work Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --text-h1:        3.75rem;  /* 60 — Saira Condensed 800 */
  --leading-h1:     1.2;      /* 72 */
  --tracking-h1:    -0.032em;
  --text-h2:        3rem;     /* 48 — Saira Condensed 700 */
  --leading-h2:     1.25;     /* 60 */
  --tracking-h2:    -0.02em;
  --text-h3:        2.25rem;  /* 36 — step titles, Saira Condensed 600 */
  --tracking-h3:    -0.0556em;
  --text-h4:        1.5rem;   /* 24 — feature titles, Saira Condensed 700 */
  --text-body-lg:   1.125rem; /* 18 — Work Sans 400 */
  --text-body:      1rem;     /* 16 */
  --text-sub:       0.875rem;

  /* Layout */
  --content-w:   1000px;  /* the comp's content band: x 220–1220 at 1440 */
  --page-max:    1440px;
  --gutter:      64px;

  /* Radius */
  --radius-sm:    0.5rem;
  --radius-md:    0.75rem;
  --radius-lg:    1rem;
  --radius-xl:    1.5rem;
  --radius-2xl:   2.5rem;
  --radius-pill:  999px;

  /* Motion */
  --ease-out:    cubic-bezier(0.22, 1, 0.36, 1);

  /* ── Baseplate aliases ──
   * legal_page and message_screen (the utility templates) still read these
   * baseplate names. Mapped onto the Verge palette rather than renamed there. */
  --color-text-pri:       var(--color-text);
  --color-text-sec:       var(--color-text-muted);
  --color-text-inv:       var(--color-accent-ink);
  --color-brand:          var(--color-accent);
  --color-brand-shade:    var(--color-accent-hover);
  --color-brand-shade-04: var(--color-surface);
  --space-xs:  0.25rem;
  --space-sm:  0.5rem;
  --space-md:  0.75rem;
  --space-lg:  1rem;
  --space-xl:  1.5rem;
  --space-2xl: 2rem;
  --space-3xl: 2.5rem;
  --space-5xl: 3.5rem;
  --radius-6xl: 4rem;
}

@media (max-width: 900px) {
  :root {
    --text-h1:  3.25rem;  /* 52 */
    --text-h2:  2.5rem;   /* 40 */
    --text-h3:  2rem;     /* 32 */
    --text-h4:  1.375rem; /* 22 */
    --gutter:   32px;
  }
}

@media (max-width: 480px) {
  :root {
    --text-h1:      2.5rem;  /* 40 */
    --leading-h1:   1.15;
    --text-h2:      2.125rem; /* 34 */
    --leading-h2:   1.18;
    --text-h3:      1.75rem; /* 28 */
    --text-body-lg: 1rem;
    --gutter:       16px;
  }
}

/* ── Page base ──────────────────────────────────────────────── */
body {
  font-family: var(--font-body);
  color: var(--color-text-muted);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Saira Condensed ships real 600/700/800 and Work Sans real 400/700 — never
     let the browser fake a weight while the webfont is still loading. */
  font-synthesis-weight: none;
}

body.full-width-content,
.full-width-content {
  background-color: var(--color-bg);
}

::selection {
  background: var(--color-accent);
  color: var(--color-accent-ink);
}

/* ── Accessibility utility ──────────────────────────────────── */
/* Visually-hidden but available to screen readers / form labels.
   Standard clip pattern; site-wide because it is a generic a11y helper. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ── Landing page layout reset ──────────────────────────────── */
/* GeneratePress sets display:flex on .site-content, which makes
   all direct children (our sections) render side-by-side at desktop.
   Force block layout on the landing page template only. */
.full-width-content .site-content,
.full-width-content #primary,
.full-width-content #main {
  display: block;
  width: 100%;
}

/* `clip`, not `hidden`: hidden turns .site-content into a scroll container,
   which clips vertically too — and the hero's top-right line shape
   deliberately rises behind the header. clip cuts the sideways overflow of
   full-bleed decoration without touching the vertical axis. */
.site-content {
  overflow-x: clip;
}

/* ── Global chrome height (site_header + site_footer) ───────────
   Full-screen section views (message_screen, legal_page) fill exactly
   the space between the global header and footer via
   min-height: calc(100dvh - var(--apt-chrome-h)). */
:root {
  --apt-chrome-h: 292px; /* desktop: 146 header + 146 footer */
}
@media (max-width: 900px) {
  :root { --apt-chrome-h: 330px; }
}
@media (max-width: 480px) {
  :root { --apt-chrome-h: 300px; }
}
body.apt-chrome-off {
  --apt-chrome-h: 0px; /* Coming Soon etc. — no header/footer to subtract */
}

/* ── Shared type ────────────────────────────────────────────── */
/* Section headings and their lead paragraph are identical in feature_grid,
   how_it_works and contact_form, so they live here rather than three times. */
.apt-h2 {
  margin: 0;
  font-family: var(--font-title);
  font-size: var(--text-h2);
  font-weight: 700;
  line-height: var(--leading-h2);
  letter-spacing: var(--tracking-h2);
  color: var(--color-text);
}

.apt-lead {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-body-lg);
  font-weight: 400;
  line-height: 1.444; /* 26 at 18px */
  color: var(--color-text-muted);
}

@media (max-width: 900px) {
  .apt-lead,
  .apt-h2,
  .feature-grid__body,
  .how-it-works__body {
    text-wrap: pretty;
  }
}

/* ── Buttons ────────────────────────────────────────────────── */
/* Every CTA in the comp is the same lime pill: header, waitlist, contact. */
.apt-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 50px;
  padding: 0 24px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--color-accent);
  color: var(--color-accent-ink);
  font-family: var(--font-body);
  font-size: var(--text-body);
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform 0.25s var(--ease-out),
    box-shadow 0.25s var(--ease-out),
    background-color 0.2s ease;
}

.apt-btn:hover,
.apt-btn:focus-visible {
  background: var(--color-accent-hover);
  color: var(--color-accent-ink);
  transform: translateY(-2px);
  box-shadow: 0 12px 32px -12px rgba(157, 255, 82, 0.55);
}

.apt-btn:active {
  transform: translateY(0);
  box-shadow: none;
}

.apt-btn:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 3px;
}

/* ── Scroll reveal ──────────────────────────────────────────────
 * Ported from sports-engaged, where each of these choices was paid for.
 * Driven by apt-animations.js, which adds .is-revealed on first entry.
 *
 * A keyframe ANIMATION, not a transition: component CSS loads after this file,
 * and any component `transition` declared for a hover effect would replace a
 * reveal transition wholesale — opacity would snap to 1 and every stagger
 * delay would silently do nothing. Animations are a separate property.
 *
 * Fill mode is `backwards`, deliberately not `both`: it holds the FROM state
 * through the delay, then releases the element so hover transforms still
 * work. With `both` the last keyframe would pin transform forever.
 *
 * Variants: data-reveal (rise), ="left", ="right" (slide in from that side),
 * ="zoom", ="fade". Stagger with style="--reveal-delay: 120ms".
 * ------------------------------------------------------------- */
[data-reveal] {
  opacity: 0;
}

[data-reveal].is-revealed {
  opacity: 1;
  animation: apt-reveal 800ms var(--ease-out) backwards;
  animation-delay: var(--reveal-delay, 0ms);
}

[data-reveal="left"].is-revealed  { animation-name: apt-reveal-left; }
[data-reveal="right"].is-revealed { animation-name: apt-reveal-right; }
[data-reveal="zoom"].is-revealed  { animation-name: apt-reveal-zoom; }
[data-reveal="fade"].is-revealed  { animation-name: apt-reveal-fade; }

@keyframes apt-reveal {
  from { opacity: 0; transform: translateY(34px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

@keyframes apt-reveal-left {
  from { opacity: 0; transform: translateX(-56px); }
  to   { opacity: 1; transform: none; }
}

@keyframes apt-reveal-right {
  from { opacity: 0; transform: translateX(56px); }
  to   { opacity: 1; transform: none; }
}

@keyframes apt-reveal-zoom {
  from { opacity: 0; transform: scale(0.85); }
  to   { opacity: 1; transform: none; }
}

@keyframes apt-reveal-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ── Line shapes (inc/line-shapes.php) ─────────────────────────
 * Inline SVG outlines. On reveal the line draws itself in (the whole path is
 * one dash — pathLength="1" — pulled into view), then a short bright-teal
 * spark loops round the outline for as long as the page is open.
 * ------------------------------------------------------------- */
.apt-lines {
  --line-spark: #4FD1DC;
  position: absolute;
  display: block;
  max-width: none;
  height: auto;
  overflow: visible;
  pointer-events: none;
}

.apt-lines path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.apt-lines__stroke {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}

/* The reveal system hides [data-reveal] until it fires; lines stay visible
   and hide their stroke instead, so they can draw in. */
[data-reveal="lines"] {
  opacity: 1;
}

[data-reveal="lines"]:not(.is-revealed) .apt-lines__stroke {
  stroke-dashoffset: 1;
}

[data-reveal="lines"].is-revealed {
  animation: none;
}

[data-reveal="lines"].is-revealed .apt-lines__stroke {
  animation: apt-lines-draw 2.4s var(--ease-out) backwards;
  animation-delay: var(--reveal-delay, 0ms);
}

/* The spark's paint is the shape's "lit" gradient (line-shapes.php), which
   fades it out wherever the line fades into the background. */
.apt-lines__lit stop {
  stop-color: var(--line-spark);
}

.apt-lines__spark {
  stroke-dasharray: 0.06 0.94;
  stroke-dashoffset: 1;
  opacity: 0.95;
}

.apt-lines__spark--glow {
  opacity: 0.7;
}

/* The spark starts moving hidden and fades in over its first stretch, so
   it rises out of the line instead of switching on at full strength. The
   paths are closed, so every later loop runs on without a seam. */
.apt-lines__pulse {
  opacity: 0;
}

[data-reveal="lines"].is-revealed .apt-lines__pulse {
  animation: apt-lines-spark-in 2s ease-in-out both;
  animation-delay: calc(var(--reveal-delay, 0ms) + 2.2s + var(--pulse-delay, 0s));
}

[data-reveal="lines"].is-revealed .apt-lines__spark {
  animation: apt-lines-pulse var(--pulse-dur, 8s) linear infinite;
  animation-delay: calc(var(--reveal-delay, 0ms) + 2.2s + var(--pulse-delay, 0s));
}

@keyframes apt-lines-draw {
  from { stroke-dashoffset: 1; }
  to   { stroke-dashoffset: 0; }
}

@keyframes apt-lines-pulse {
  from { stroke-dashoffset: 1; }
  to   { stroke-dashoffset: 0; }
}

@keyframes apt-lines-spark-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Numbers that count up (apt-animations.js) keep a steady width. */
[data-count-to] {
  font-variant-numeric: tabular-nums;
}

/* Gentle idle float: hero phones, step illustrations and their cards. */
@keyframes apt-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-10px); }
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1;
  }

  [data-reveal].is-revealed {
    animation: none;
  }

  .apt-btn {
    transition: none;
  }

  .apt-btn:hover,
  .apt-btn:focus-visible {
    transform: none;
  }

  [data-reveal="lines"] .apt-lines__stroke {
    stroke-dashoffset: 0;
    animation: none !important;
  }

  .apt-lines__pulse {
    display: none;
  }
}
