/*
Theme Name: AppSwifts
Theme URI: https://appswifts.com
Author: AppSwifts
Description: Plugin-free block theme. No Elementor, no page builder, no plugin dependencies. Native WordPress blocks, one design-token stylesheet, self-hosted variable fonts.
Version: 1.0.0
Requires at least: 6.5
Tested up to: 6.7
Requires PHP: 8.1
License: GPL-2.0-or-later
Text Domain: appswifts
*/

/* ==========================================================================
   1. DESIGN TOKENS  — the single source of truth.
   Every value below is derived from the AppSwifts logo colour #86c13b.
   Change it here and the whole site follows.
   ========================================================================== */
:root{
  /* brand */
  --brand:        #86c13b;   /* exact logo lime */
  --brand-600:    #6ea32c;   /* hover / pressed */
  --brand-ink:    #3f6b12;   /* accessible lime for TEXT on light (4.8:1) */
  --brand-soft:   #eaf7d8;   /* tinted surface */
  --brand-glow:   rgba(134,193,59,.28);

  /* neutrals — green-tinted so they sit with the lime, not against it */
  --ink:          #0e140a;
  --ink-2:        #1b2314;
  --body:         #4a5240;
  --muted:        #5f6859;   /* 5.82:1 on white, 5.08:1 on cream, WCAG AA both */
  --line:         #e6eae1;
  /* one step darker than --line, for inset rings that must read as a real edge */
  --line-strong:  #d3dacb;
  --surface:      #ffffff;
  --bg:           #fafbf8;
  /* Warm stones. Google Labs alternates #ffffff with #F3EFEA and rules borders
     in #E8DFD5. Warm surfaces read as considered; the green-tinted neutrals alone
     read as default. Borders, not shadows, carry the depth. */
  --cream:        #f3efea;
  --cream-2:      #e8dfd5;
  --line-warm:    #e8dfd5;

  /* type
     Google Sans, self-hosted (assets/fonts/googlesans-var.woff2, variable 400-700,
     Latin subset). Both display AND body use it: Google serves Google Sans Text
     only as a dev-only face (requesting it silently returns Open Sans), so the
     same family covers both roles. Inter is kept as the metric fallback and its
     @font-face rule is retained, so body text renders even if the file 404s.
     Weights used across the sheet are 400/500/520/600, inside the 400-700 range. */
  --font-body:    "Google Sans", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: "Google Sans", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono:    ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Fluid type scale: confident, but compact enough that the content rather
     than the whitespace owns the page. The display step is reserved for the
     homepage only; section and interior page headings sit beneath it. */
  --t-xs:   clamp(.78rem, .76rem + .10vw, .84rem);
  --t-sm:   clamp(.88rem, .85rem + .15vw, .95rem);
  --t-base: clamp(1rem,   .96rem + .20vw, 1.09rem);
  --t-lg:   clamp(1.15rem,.08vw + 1rem,  1.3rem);
  --t-xl:   clamp(1.4rem, 1.18rem + .85vw,  1.85rem);
  --t-2xl:  clamp(2rem,1.5rem + 1.7vw,  2.85rem);
  /* Interior H1. Google Labs sets display type at 80-120px with the section
     headings below it a fraction of the size, so the jump between hero and body
     is what reads as "big". Homepage hero is 104px; interior pages sit one step
     under at 96px so the homepage still owns the biggest line on the site. */
  --t-3xl:  clamp(2.65rem, 1.7rem + 3.8vw,  4.75rem);
  --t-4xl:  clamp(2.85rem, 1.8rem + 3.7vw,  4.7rem);

  /* space */
  --s-1:.25rem; --s-2:.5rem;  --s-3:.75rem; --s-4:1rem;
  --s-5:1.5rem; --s-6:2rem;   --s-7:3rem;   --s-8:4rem;
  --section: clamp(3rem, 2rem + 3.6vw, 5.5rem);
  /* Wider than a normal 1180px text column on purpose: the display type is large
     enough to fill 1280px, and a narrow wrap would push the headings back to
     mid-size. Google Labs runs 1232px here. Pulled to 1200 so it fills a 1280
     desktop while body copy still stays inside a readable measure. */
  --wide: 1200px;

  /* shape + motion — radii capped at 12px for content (VoltAgent rule:
     nothing between a 6px workhorse and a 999px pill on interactive elements).
     Containers are the exception: Google Labs rounds cards to 24-26px, which
     reads as soft rather than blocky. --radius-card is for boxes, not buttons. */
  --radius:12px; --radius-sm:8px; --radius-lg:20px; --radius-card:24px; --radius-pill:999px;
  --shadow:    0 1px 2px rgba(14,20,10,.04), 0 6px 20px -10px rgba(14,20,10,.10);
  --shadow-lg: 0 2px 4px rgba(14,20,10,.05), 0 20px 48px -20px rgba(14,20,10,.18);
  --ease: cubic-bezier(.22,.61,.36,1);
  /* hairline colours for the border-led depth system */
  --line-dark:   rgba(255,255,255,.10);
  --line-mid:    rgba(255,255,255,.16);
  --maxw: 1180px;
}

/* ==========================================================================
   2. FONTS — three variable files (145 KB) replace 54 @font-face rules.
   font-display:swap + preload in functions.php = no invisible-text flash.
   ========================================================================== */
@font-face{
  font-family:Inter; font-style:normal; font-weight:100 900; font-display:swap;
  src:url(assets/fonts/inter-var.woff2) format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:Inter; font-style:italic; font-weight:100 900; font-display:swap;
  src:url(assets/fonts/inter-var-italic.woff2) format("woff2");
}
@font-face{
  font-family:"Google Sans"; font-style:normal; font-weight:400 700; font-display:swap;
  src:url(assets/fonts/googlesans-var.woff2) format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

/* ==========================================================================
   3. RESET + BASE
   ========================================================================== */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
body{
  margin:0; background:var(--bg); color:var(--body);
  font-family:var(--font-body); font-size:var(--t-base); line-height:1.65;
  font-synthesis-weight:none; -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
/* Headings: weight 600 not 700 — VoltAgent/Supabase both build hierarchy from
   SIZE, not weight. Compressed line-height (1.06) is the typographic signature. */
/* Weight is for hierarchy, not emphasis. Google Labs sets display type at
   weight 400-500 and never goes bold — the size carries the importance. Applied
   to h1/h2, which are display scale here. h3/h4 stay at 600: they sit inside
   cards at 33px next to 17px body copy, where the smaller size needs the weight
   to stay a heading. Small headings keep weight, big ones drop it. */
h1,h2,h3,h4,h5,h6{
  margin:0 0 var(--s-4); color:var(--ink);
  font-family:var(--font-display); font-weight:600;
  line-height:1.08; letter-spacing:-.01em; text-wrap:balance;
}
h1,h2{font-weight:500}
/* Letter-spacing is the single biggest giveaway of hand-set type. Google Labs
   runs -1px at 80px (i.e. -1.25%) and -0.26px at 26px (-1%), holding the ratio
   near -1% at every size instead of tightening as type grows. Ours was -3.8% on
   h1, which is why the headings read cramped rather than confident. Rule: about
   -1%, drifting only slightly tighter on the largest sizes. */
h1{font-size:var(--t-4xl); letter-spacing:-.015em; line-height:1.03}
h2{font-size:var(--t-2xl); letter-spacing:-.012em}
h3{font-size:var(--t-xl); letter-spacing:-.01em; line-height:1.18}
h4{font-size:var(--t-lg); letter-spacing:-.006em; line-height:1.3}
p{margin:0 0 var(--s-4); text-wrap:pretty}
a{color:var(--brand-ink); text-decoration-thickness:1px; text-underline-offset:3px}
a:hover{color:var(--brand-600)}
img,svg,video{max-width:100%; height:auto; display:block}
ul,ol{padding-left:1.2em}
hr{border:0;border-top:1px solid var(--line);margin:var(--s-7) 0}
::selection{background:var(--brand-glow); color:var(--ink)}
:focus-visible{outline:3px solid var(--brand); outline-offset:2px; border-radius:4px}
.skip-link{position:absolute;left:-9999px}
.skip-link:focus{left:var(--s-4);top:var(--s-4);z-index:999;background:var(--ink);color:#fff;padding:var(--s-3) var(--s-4);border-radius:var(--radius-sm)}

/* ==========================================================================
   4. LAYOUT
   ========================================================================== */
.wrap{width:100%; max-width:var(--maxw); margin-inline:auto; padding-inline:clamp(1rem,4vw,2rem)}
/* Display sections breathe wider than the text column, so 84px headings have room
   instead of wrapping at half a desktop. */
.wrap--wide{max-width:var(--wide)}
.section{padding-block:var(--section)}
.section--tight{padding-block:clamp(2.5rem,2rem + 3vw,4.5rem)}
.section--bg{background:var(--surface)}
/* Alternating warm band. Paired with .section--bg this gives the page the
   white / cream / white rhythm Google Labs uses, and lets a section be set apart
   without a box, a shadow or a gradient. */
.section--cream{background:var(--cream)}
.section--soft{background:var(--brand-soft)}
/* Dark bands: depth comes from a hairline border top/bottom, not a shadow.
   On near-black a shadow is invisible — the border IS the elevation. */
.section--dark{
  background:var(--ink); color:#c9d1c0;
  border-top:1px solid var(--line-dark); border-bottom:1px solid var(--line-dark);
}
.section--dark h1,.section--dark h2,.section--dark h3{color:#fff}
.section--dark a{color:var(--brand)}
.section--dark .lead{color:#a9b49f}
.stack>*+*{margin-top:var(--s-4)}
.grid{display:grid; gap:var(--s-5)}
.grid--2{grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr))}
.grid--3{grid-template-columns:repeat(auto-fit,minmax(min(100%,270px),1fr))}
.grid--4{grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr))}
.center{text-align:center; margin-inline:auto; max-width:62ch}
.lead{font-size:var(--t-lg); color:var(--body); max-width:60ch}

/* Section header + description, centred.
   This replaced five hand-written inline `style="max-width:46rem;…"` heads and
   two component-specific variants (.int__head, .map__head) that all did the
   same job with slightly different numbers. One class means one place to change.
   The measure is tightened because centred text needs a shorter line than
   left-aligned text to stay readable. */
.section__head{
  max-width:46rem;
  margin-inline:auto;
  margin-bottom:clamp(1.75rem,1.25rem + 1.5vw,2.5rem);
  text-align:center;
}
.section__head .lead{margin-inline:auto; max-width:54ch}
.section__head .btn-row{justify-content:center}
.muted{color:var(--muted)}
.small{font-size:var(--t-sm)}
.measure{max-width:68ch}

/* ==========================================================================
   5. HEADER + NAV — plain CSS, no JS required
   ========================================================================== */
/* Dark header over a light page, the way Google Labs does it: the header and
   footer frame the page in near-black, the content stays bright. It also fixes
   the logo — on white the lockup's white wordmark was invisible (1.00:1) and the
   green failed at 2.16:1; on this ink they measure 18.70:1 and 8.64:1. */
.site-header{
  position:sticky; top:0; z-index:100;
  background:color-mix(in srgb, var(--ink) 92%, transparent);
  backdrop-filter:saturate(180%) blur(14px);
  border-bottom:1px solid var(--line-dark);
  color:#fff;
}
.site-header__inner{display:flex; align-items:center; gap:var(--s-5); padding-block:var(--s-3)}
.site-brand{display:flex; align-items:center; gap:var(--s-2); font-family:var(--font-display);
  font-weight:600; font-size:1.12rem; color:#fff; text-decoration:none; letter-spacing:-.02em}
.site-brand:hover{color:#fff}

/* Logo sizing.
   The lockup is a 500x250 canvas whose ink occupies 495x150 — so the file is
   NOT square and height alone drives the render. At height:38px the ink only
   measured 22.8px tall, which read as small next to 15.2px nav links.
   Set by height, let width follow, cap width so a stray wide upload can't push
   the nav off-screen. 56px puts the ink at ~33.6px, in proportion with the nav. */
.custom-logo-link{display:flex; align-items:center; flex:none}
.custom-logo-link img,
.site-brand img,
img.custom-logo{
  height:clamp(44px, 4.4vw, 56px);
  width:auto;
  max-height:none;
  max-width:min(300px, 42vw);
  object-fit:contain;
}
@media (max-width:600px){
  .custom-logo-link img,
  img.custom-logo{height:40px; max-height:none; max-width:min(200px, 52vw)}
}
.site-nav{margin-left:auto}
.site-nav ul{display:flex; gap:var(--s-5); list-style:none; margin:0; padding:0; flex-wrap:wrap}
.site-nav a{color:rgba(255,255,255,.78); text-decoration:none; font-size:var(--t-sm); font-weight:520; transition:color .18s var(--ease)}
.site-nav a:hover{color:#fff}
.site-nav a[aria-current=page]{color:#fff; font-weight:600}
.site-header__cta{margin-left:var(--s-4)}
/* The in-panel CTA only exists on mobile; the standalone header CTA only on
   desktop. Keeping both in the markup means neither layout needs JS.
   These need .site-nav in the selector to outrank .btn on source order —
   the button styles are defined further down this file. */
.site-nav .site-nav__cta{display:none}
/* In the dark mobile panel this CTA inherits .btn--primary's lime fill, and
   .site-nav a's rgba(255,255,255,.78) colour lands on top of it: 4.13:1 at
   best and far worse over the panel's own dark bg. Pin the pair explicitly. */
.site-nav .btn--primary{background:var(--brand); color:var(--ink)}
.site-nav .btn--primary:hover{background:var(--brand-600); color:var(--ink)}
.nav-toggle{display:none}

@media (max-width:820px){
  .site-header__inner{gap:var(--s-3); position:relative}
  /* the desktop CTA is replaced by the one inside the panel.
     Needs the media query to win on specificity: .site-header .btn beats a
     bare class selector on source order. */
  .site-header .site-header__cta{display:none}

  .nav-toggle{
    display:grid; place-items:center; margin-left:auto;
    width:44px; height:44px; border-radius:var(--radius-sm);
    border:1px solid var(--line-dark); background:rgba(255,255,255,.06); color:#fff;
    cursor:pointer; flex:none;
    transition:border-color .18s var(--ease), background .18s var(--ease);
  }
  .nav-toggle:hover{border-color:color-mix(in srgb,var(--brand) 60%,transparent); background:rgba(255,255,255,.12)}
  .nav-toggle-close{display:none}
  /* swap the burger for a cross while the panel is open */
  .nav-toggle-input:checked ~ .nav-toggle .nav-toggle-open{display:none}
  .nav-toggle-input:checked ~ .nav-toggle .nav-toggle-close{display:grid; place-items:center}

  /* Focus stays reachable for keyboard users even though the input is
     visually hidden, so mirror the ring onto the label. */
  .nav-toggle-input:focus-visible ~ .nav-toggle{
    outline:3px solid var(--brand); outline-offset:2px;
  }

  /* Panel: absolutely positioned so opening it overlaps the page instead of
     pushing all the content down. A single grid row collapses to 0fr; the
     inner wrapper is the one scrollable/clippable grid child.
     visibility flips with a delay so collapsed links leave the tab order. */
  .site-nav{
    position:absolute; left:0; right:0; top:100%; margin:0;
    background:var(--ink); border-bottom:1px solid var(--line-dark);
    box-shadow:0 18px 32px -22px rgba(14,20,10,.55);
    display:grid; grid-template-rows:0fr;
    visibility:hidden; z-index:99;
    padding-inline:clamp(1rem,4vw,2rem);
    transition:grid-template-rows .26s var(--ease), visibility 0s linear .26s;
  }
  .site-nav__panel{overflow:hidden; min-height:0}
  .site-nav > .site-nav__panel > ul{
    display:grid; grid-template-columns:1fr; gap:0;
    padding:var(--s-2) 0 0;
  }
  .site-nav a{
    display:block; padding:.85rem 0; font-size:var(--t-base);
    border-bottom:1px solid var(--line-dark);
  }
  .site-nav > .site-nav__panel > ul > li:last-child > a{border-bottom:0}
  .site-nav .site-nav__cta{
    display:inline-flex; margin:var(--s-4) 0 var(--s-5);
  }

  .nav-toggle-input:checked ~ .site-nav{
    grid-template-rows:1fr; visibility:visible;
    transition:grid-template-rows .26s var(--ease), visibility 0s;
  }
}

/* Motion-sensitive users get an instant open, not a slide. */
@media (prefers-reduced-motion:reduce){
  .site-nav{transition:none}
}

/* ==========================================================================
   6. BUTTONS
   ========================================================================== */
/* Buttons: pill radius on CTAs (Supabase), weight 520 not 620 — restraint is
   what makes it read as expensive. Depth on hover comes from a brand glow.
   Sized up to match Google Labs' 18px/500 pill at 16px 32px: at our 17.4px body
   that is 1.03em type in .92em 1.84em padding, so CTAs read as the page's
   second-largest element after the headings. */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:.5em;
  padding:.92em 1.84em; border:1px solid transparent; border-radius:var(--radius-pill);
  font-family:var(--font-body); font-size:clamp(.95rem,.93rem + .10vw,1.03rem); font-weight:520; line-height:1.2;
  letter-spacing:-.005em;
  text-decoration:none; cursor:pointer;
  transition:transform .18s var(--ease), background .18s var(--ease), color .18s var(--ease), box-shadow .18s var(--ease), border-color .18s var(--ease);
}
.btn:active{transform:translateY(1px)}
.btn--primary{background:var(--brand); color:#0e140a; box-shadow:0 1px 2px rgba(14,20,10,.10)}
.btn--primary:hover{background:var(--brand-600); color:#0e140a; box-shadow:0 6px 24px -6px var(--brand-glow)}
.btn--dark{background:var(--ink); color:#fff}
.btn--dark:hover{background:var(--ink-2); color:#fff}
.btn--ghost{border-color:var(--line); background:transparent; color:var(--ink)}
.btn--ghost:hover{border-color:var(--brand); background:var(--brand-soft); color:var(--ink)}
.btn--on-dark{border-color:var(--line-mid); color:#fff; background:rgba(255,255,255,.03)}
.btn--on-dark:hover{background:rgba(255,255,255,.09); color:#fff; border-color:var(--brand)}
.btn--lg{font-size:var(--t-base); padding:.9em 1.7em}
.btn-row{display:flex; flex-wrap:wrap; gap:var(--s-3)}

/* ==========================================================================
   7. HERO
   ========================================================================== */
/* Hero: flat ink, one hairline, nothing decorative.
   It used to carry two radial brand-glow blobs and a 64px fake grid overlay.
   That pairing is the single most recognisable "AI built this" hero: coloured
   light blooming out of a dark box, plus a grid with no structural meaning.
   Real dark sections get depth from the content sitting on them, so the
   terminal card is now the only thing with texture. */
.hero{
  position:relative; overflow:hidden;
  background:var(--ink);
  color:#c9d1c0; padding-block:clamp(4.5rem,3rem + 8vw,9.5rem);
  border-bottom:1px solid var(--line-dark);
}
.hero > *{position:relative; z-index:1}
.hero h1{color:#fff; max-width:20ch}
.hero .lead{color:#b7c0ad; margin-bottom:var(--s-5)}
/* The headline is the design. Big, tight, and short-measure. */
.hero__title{
  font-size:var(--t-4xl);
  line-height:1.04;
  letter-spacing:-.015em;
  max-width:20ch;
  margin-bottom:var(--s-5);
  text-wrap:balance;
}
.hero__grid{display:grid; gap:clamp(2rem,5vw,4.5rem); grid-template-columns:1fr; align-items:center}
@media (min-width:980px){ .hero__grid{grid-template-columns:1.15fr .85fr} }

/* The hero is centred: headline, lede, buttons and the trust row all sit on the
   page's centre axis, and the product card drops below them. It was a two-column
   text-left split. Centring needed the card out of the second column — a centred
   paragraph beside a card just reads as a mistake. */
.hero__display{text-align:center}
.hero__title--display{margin-inline:auto; text-wrap:balance}
.hero__intro{text-align:center}
.hero__intro .lead{margin-inline:auto; max-width:54ch}
.hero__intro .btn-row{justify-content:center; margin-top:var(--s-5)}
.hero__intro .trust{justify-content:center; text-align:center}
@media (min-width:980px){ .hero__grid--under{grid-template-columns:1fr; gap:clamp(2.5rem,3vw,3.5rem)} }
/* The card is narrow when stacked, so it does not stretch to 1376px. */
.hero__grid--under .terminal{max-width:640px; margin-inline:auto; width:100%}

/* Full-width display headline above the two-column body. Google Labs sets its
   display type at 120px across 1232px; the equivalent here is the headline
   owning the whole container and the supporting copy sitting under it. */
.hero__display{margin-bottom:clamp(2.5rem,2rem + 3vw,4.5rem)}
.hero__title--display{
  font-size:clamp(2.75rem, 1.2rem + 7.2vw, 6.5rem);
  line-height:1.0;
  letter-spacing:-.015em;
  max-width:24ch;
}

/* Homepage banner: a quiet, immersive field behind one clear message. It uses
   CSS light and grain rather than a borrowed stock or sci-fi image, so the
   visual remains unmistakably AppSwifts and does not compete with the copy. */
.hero--banner{
  min-height:min(700px,calc(100svh - 1px));
  display:grid;place-items:center;
  isolation:isolate;
  padding-block:clamp(6.75rem,9vw,8.5rem) clamp(5rem,6vw,6.75rem);
  background:#06120d;
  border-block:1px solid rgba(183,223,154,.12);
}
.hero--banner::after{
  display:none;
}
.hero__atmosphere{display:none}
.hero-banner__content{position:relative;text-align:center;display:flex;flex-direction:column;align-items:center}
.hero-banner__badge{display:inline-flex;align-items:center;gap:.7rem;margin:0 0 var(--s-5);padding:.38rem .72rem .38rem .42rem;border:1px solid rgba(255,255,255,.17);border-radius:var(--radius-pill);background:#0c2118;color:#e9f0e2;font-size:var(--t-sm);line-height:1.2}
.hero-banner__badge span{background:#e8f7d5;color:#13230c;padding:.22rem .5rem;border-radius:var(--radius-pill);font-size:var(--t-xs);font-weight:700}
.hero--banner h1{max-width:16ch;margin:0;color:#fff;font-size:clamp(3rem,1.85rem + 5vw,6rem);letter-spacing:-.045em;line-height:.96;text-wrap:balance}
.hero--banner h1 em{font-family:var(--font-display);font-weight:400;letter-spacing:-.055em;color:#d7f1b3}
.hero-banner__lead{max-width:46ch;margin:var(--s-4) auto 0;color:#c7d3bc;font-size:clamp(1rem,.92rem + .2vw,1.12rem);line-height:1.58}
.hero-banner__actions{justify-content:center;margin-top:var(--s-5)}
.hero-banner__actions .btn{min-width:11.75rem;justify-content:center}
.hero-banner__actions .btn span{font-size:1.1em;line-height:1;margin-left:.15rem}
.hero-banner__note{margin:var(--s-5) 0 0;color:#aebba2;font-size:var(--t-sm)}
/* A real workspace gives the hero useful product context. The treatment keeps
   the screenshot legible and avoids loading a decorative 3D runtime. */
.hero-product{display:grid;justify-items:center;gap:clamp(2.5rem,5vw,5rem);min-height:inherit}
.hero-product__content{position:relative;z-index:2;display:grid;justify-items:center;text-align:center;max-width:50rem}
.hero-product__signals{position:absolute;inset:0;z-index:0;pointer-events:none}
.hero-product__signal-shell{position:absolute;width:clamp(4.2rem,7vw,7rem);height:clamp(4.2rem,7vw,7rem);display:grid;place-items:center;border:1px solid rgba(183,223,154,.27);border-radius:1rem;background:#0a1d15;box-shadow:0 .55rem 1.4rem rgba(0,0,0,.2);animation:hero-workflow-float 5.5s ease-in-out infinite}
.hero-product__signal-shell lottie-player{position:absolute;inset:0;width:100%;height:100%;opacity:.35}.hero-product__signal-shell svg{position:relative;z-index:1;width:38%;height:38%;fill:none;stroke:#ecf8e3;stroke-width:1.65;stroke-linecap:round;stroke-linejoin:round}
.hero-product__signal--2{animation-delay:-1.1s}.hero-product__signal--3{animation-delay:-2.2s}.hero-product__signal--4{animation-delay:-3.3s}.hero-product__signal--5{animation-delay:-4.4s}
.hero-product__signal--1{left:7%;top:16%}.hero-product__signal--2{right:7%;top:15%}.hero-product__signal--3{left:14%;top:32rem;width:clamp(5rem,8vw,8rem);height:clamp(5rem,8vw,8rem)}.hero-product__signal--4{right:13%;top:32rem;width:clamp(5rem,8vw,8rem);height:clamp(5rem,8vw,8rem)}.hero-product__signal--5{right:28%;top:20rem;width:clamp(3.5rem,5vw,5rem);height:clamp(3.5rem,5vw,5rem)}
@keyframes hero-workflow-float{50%{transform:translateY(-.65rem)}}
.hero-product__preview{width:min(100%,67rem);overflow:hidden;border:1px solid rgba(183,223,154,.22);border-radius:1rem 1rem .35rem .35rem;background:#06130e;box-shadow:0 .8rem 2.4rem rgba(0,0,0,.22)}
.hero-product__chrome{height:2.5rem;display:flex;align-items:center;gap:.36rem;padding:0 .9rem;border-bottom:1px solid rgba(183,223,154,.13);background:rgba(10,29,21,.92)}
.hero-product__chrome i{width:.48rem;height:.48rem;border-radius:50%;background:rgba(218,244,195,.28)}
.hero-product__chrome span{margin-left:.4rem;color:#98ae91;font-size:.72rem;letter-spacing:.03em}
.hero-product__preview img{display:block;width:100%;height:auto;object-fit:cover}
.hero-product__content .hero-banner__actions{justify-content:center}
.hero-product__content .hero-banner__lead{margin-inline:auto}
@media (min-width:900px){.hero--banner{padding-block:clamp(5.5rem,7vw,7.5rem) 0}.hero-product{gap:clamp(2.8rem,4vw,4.5rem)}.hero--banner h1{max-width:13ch}.hero-product__preview{margin-bottom:-1px}}
@media (max-width:700px){.hero-product__signal-shell{width:4.5rem;height:4.5rem;opacity:.58}.hero-product__signal--1{display:grid;left:.35rem;top:8.5rem}.hero-product__signal--2{display:grid;right:.35rem;top:8.5rem}.hero-product__signal--3{left:.2rem;top:24rem;bottom:auto}.hero-product__signal--4{right:.2rem;top:24rem;bottom:auto}.hero-product__signal--5{display:none}}
@media (prefers-reduced-motion:reduce){.hero-product__signals{display:none}}
@media (max-width:560px){
  .hero--banner{min-height:600px;padding-block:6rem 4.5rem}
  .hero--banner h1{font-size:clamp(2.8rem,12.5vw,4rem)}
  .hero-banner__actions{width:100%;flex-direction:column}
  .hero-banner__actions .btn{width:100%}
}
/* The note is shared by the cream integrations band and this dark band. Its
   light-band palette (#6d7668 on cream) drops to 3.95:1 here — a WCAG fail —
   so the dark band recolours it rather than the note carrying two palettes. */
.section--dark .int__note{color:#a9b49f; border-top-color:var(--line-mid)}
/* On the ink band, .btn--primary (lime fill) and .btn--on-dark (ink outline)
   both invert: the lime fill becomes the secondary, the outline becomes the
   primary. Without this the "See pricing" outline is lime-on-lime at 1.00:1. */
.section--dark .btn--primary{background:var(--brand); color:var(--ink)}
.section--dark .btn--on-dark{border-color:rgba(255,255,255,.22); background:transparent}
.section--dark .btn--on-dark:hover{border-color:var(--brand); background:rgba(134,193,59,.10)}
.trust{display:flex; flex-wrap:wrap; gap:var(--s-5) var(--s-6); margin-top:var(--s-7);
  padding-top:var(--s-5); border-top:1px solid rgba(255,255,255,.14); list-style:none; padding-left:0}
.trust li{font-size:var(--t-sm); color:#98a48e}
.trust strong{display:block; font-family:var(--font-display); font-size:var(--t-xl); color:#fff; line-height:1.15}

/* steps on the dark band: palette overrides live with the .steps rules above */

/* terminal-style product card in the hero — VoltAgent: the product IS the hero */
.terminal{
  background:rgba(255,255,255,.028); border:1px solid var(--line-mid);
  border-radius:var(--radius-lg); padding:var(--s-4); box-shadow:var(--shadow-lg);
  backdrop-filter:blur(10px); font-size:var(--t-sm);
}
.terminal__bar{display:flex; align-items:center; gap:.4rem; margin-bottom:var(--s-4)}
.terminal__bar i{width:9px;height:9px;border-radius:50%;background:rgba(255,255,255,.16)}
.terminal__bar i:first-child{background:rgba(134,193,59,.55)}
.terminal__name{margin-left:auto; font-family:var(--font-mono); font-size:.68rem;
  letter-spacing:.1em; text-transform:uppercase; color:#7d8875}
.terminal__row{display:flex; gap:var(--s-3); align-items:baseline;
  padding:.6rem .7rem; border-radius:var(--radius-sm);
  font-family:var(--font-mono); font-size:.78rem; color:#8f9a85}
.terminal__row:nth-child(odd){background:rgba(255,255,255,.028)}
.terminal__row b{color:var(--brand); font-weight:500; margin-left:auto;
  font-family:var(--font-body); text-align:right}

/* ==========================================================================
   7b. WEBSITE MOTION
   --------------------------------------------------------------------------
   Purposeful movement only: sections enter as they become relevant, the
   product card has a calm live signal, and the connection diagram visibly
   carries work from input to result. This is progressive enhancement. The
   HTML remains complete before JS runs and motion-sensitive visitors receive
   the finished state immediately.
   ========================================================================== */
.motion-reveal{
  opacity:0;
  transform:translate3d(0,18px,0);
  transition:
    opacity .58s var(--ease),
    transform .68s var(--ease);
  transition-delay:calc(var(--motion-order, 0) * 55ms);
  will-change:opacity,transform;
}
.motion-reveal.is-visible{opacity:1;transform:translate3d(0,0,0)}

/* The hero uses a short, staged entrance rather than a looping spectacle. */
.hero .motion-reveal{transition-delay:0}
.hero .hero__intro{transition-delay:100ms}
.hero .terminal{transition-delay:180ms}

/* The terminal reads as live through the status lamp, not flashing content. */
.terminal__bar i:first-child{animation:appswifts-live 2.6s ease-in-out infinite}
@keyframes appswifts-live{
  0%,100%{box-shadow:0 0 0 0 rgba(134,193,59,0)}
  46%{box-shadow:0 0 0 6px rgba(134,193,59,.10)}
  62%{box-shadow:0 0 0 0 rgba(134,193,59,0)}
}

/* Connection lines quietly carry a pulse toward the AppSwifts AI hub. */
.wire__stem{overflow:hidden}
.wire__stem::after{
  content:""; position:absolute; width:6px; height:6px; border-radius:50%;
  background:var(--brand); opacity:0; animation:appswifts-flow 3.8s var(--ease) infinite;
}
@keyframes appswifts-flow{
  0%,18%{opacity:0;transform:translateY(-110%)}
  24%{opacity:1}
  56%{opacity:1}
  72%,100%{opacity:0;transform:translateY(110%)}
}
@media (min-width:820px){
  .wire__stem::after{animation-name:appswifts-flow-wide}
  @keyframes appswifts-flow-wide{
    0%,18%{opacity:0;transform:translateX(-110%)}
    24%{opacity:1}
    56%{opacity:1}
    72%,100%{opacity:0;transform:translateX(110%)}
  }
}

/* Tactile feedback makes cards and action links feel deliberate without lift. */
@media (hover:hover){
  .int,.card,.wire__node{transition-duration:.22s}
  .int:hover,.card:hover{transform:translateY(-2px)}
  .btn:hover{transform:translateY(-1px)}
}

@media (prefers-reduced-motion:reduce){
  .motion-reveal{opacity:1;transform:none;transition:none}
  .terminal__bar i:first-child,.wire__stem::after{animation:none}
}

/* ==========================================================================
   8. CARDS
   ========================================================================== */
/* ==========================================================================
   CARD SYSTEM
   --------------------------------------------------------------------------
   The tell of an AI-built page is twelve identical icon-title-paragraph boxes
   in a tidy 3x3 grid, every one of them lifting 2px with a soft shadow on
   hover. The fix is not more decoration, it is giving each variant a job:

     .card             base, plain surface
     .card--feature    the recommended option, marked with a brand top-rule
     .card--dark       on the ink bands
     .card--link       the whole card is a link
     .card--stat       number-forward, no icon

   Hover moves the BORDER and the title colour, never the box. Uniform
   lift-and-shadow on every card is the most copied AI habit there is.
   ========================================================================== */
.card{
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--radius-card); padding:clamp(1.25rem,1rem + 1vw,1.65rem);
  display:flex; flex-direction:column; position:relative;
  transition:border-color .18s var(--ease), transform .22s var(--ease);
}
.card h3{margin-bottom:var(--s-2); transition:color .18s var(--ease)}
.card p{color:var(--body); font-size:var(--t-sm); line-height:1.62}
.card p:last-child{margin-bottom:0}
.card:hover{border-color:color-mix(in srgb,var(--brand) 46%,var(--line))}

/* Icon: a bare glyph on a hairline ring. No fill, no coloured tile — a grid of
   filled green squares is what a template generator reaches for first. */
.card__icon{
  width:40px;height:40px;border-radius:var(--radius-sm);display:grid;place-items:center;
  color:var(--brand-ink);
  box-shadow:inset 0 0 0 1px var(--line-strong);
  margin-bottom:var(--s-4); flex:none;
}
.card__icon svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}

/* Feature: marked by a top rule that is part of the card edge, not a gradient
   wash over the surface. */
.card--feature{
  border-color:color-mix(in srgb,var(--brand) 42%,var(--line));
  box-shadow:inset 0 3px 0 0 var(--brand);
}
.card--dark{background:var(--ink-2); border-color:var(--line-dark); color:#c9d1c0}
.card--dark:hover{border-color:var(--brand)}
.card--dark h3{color:#fff}
.card--dark p{color:#a9b49f}
.card--dark .card__icon{color:var(--brand); box-shadow:inset 0 0 0 1px var(--line-mid)}

/* Whole-card link: the title is the target, the card is the hit area, and the
   arrow is the only thing that moves. */
.card--link{padding:0; overflow:hidden}
.card--link > a.card__hit{
  display:flex; flex-direction:column; flex:1; padding:var(--s-6);
  text-decoration:none; color:inherit;
}
.card--link:hover .card__arrow{transform:translateX(3px)}
.card__arrow{
  margin-top:auto; padding-top:var(--s-4);
  font-size:var(--t-sm); font-weight:500; color:var(--brand-ink);
  display:inline-flex; align-items:center; gap:.4em;
  transition:transform .18s var(--ease);
}
.card--link:hover h3{color:var(--brand-ink)}

/* Stat: the number is the heading, so the eye lands on the figure first. */
.card--stat .card__n{
  font-family:var(--font-display); font-weight:500; letter-spacing:-.02em;
  font-size:var(--t-2xl); line-height:1; color:var(--ink); margin-bottom:var(--s-2);
}
.card--stat h3{font-size:var(--t-base); margin-bottom:var(--s-2)}
/* Price: display face at weight 500 to match the headings, tabular figures so
   the three plans line up instead of jittering. */
.card__price{
  margin:var(--s-4) 0 var(--s-1);
  font-family:var(--font-display); font-size:var(--t-2xl); font-weight:500;
  color:var(--ink); letter-spacing:-.02em; line-height:1;
  font-variant-numeric:tabular-nums;
}
.card__price-unit{font-size:var(--t-sm); font-weight:400; color:var(--muted); letter-spacing:0}
/* An image flush to the card edge needs the card's padding taken back off. */
.card__media{margin:calc(var(--s-6) * -1) calc(var(--s-6) * -1) var(--s-4);
  overflow:hidden; border-bottom:1px solid var(--line); background:var(--bg)}
.card__media img{width:100%; aspect-ratio:16/9; object-fit:cover; display:block;
  transition:transform .35s var(--ease)}
.card--link:hover .card__media img{transform:scale(1.03)}

/* Service block: one lead card beside a hairline-ruled list. Two shapes instead
   of the same card twelve times, so each service has an obvious entry point. */
.service{display:grid; gap:var(--s-6); grid-template-columns:1fr; align-items:start}
/* Each service's header is centred and its detail list runs underneath, on the
   same centre axis as every other section header. It was a two-column split, and
   a centred header cannot sit beside a column without looking misaligned. */
.service__lead{text-align:center; max-width:46rem; margin-inline:auto}
.service__lead h2{margin-bottom:var(--s-3); text-wrap:balance}
.service__lead .lead{margin-bottom:var(--s-4); margin-inline:auto; max-width:54ch}
.service__link{font-weight:500; color:var(--brand-ink); text-decoration:none;
  border-bottom:1px solid color-mix(in srgb,var(--brand) 40%,transparent); padding-bottom:2px}
.service__link:hover{border-bottom-color:var(--brand)}
.service__items{list-style:none; margin:0; padding:0; border-top:1px solid var(--line);
  max-width:56rem; margin-inline:auto; width:100%}
.service__items li{padding-block:var(--s-5); border-bottom:1px solid var(--line)}
.service__items h3{font-size:var(--t-xl); margin-bottom:var(--s-2)}

/* Two content columns under a centred header. Distinct from .hero__grid, which
   is sized for a display headline — a content section should not inherit hero
   type. Under a centred head the two columns stay balanced at 1fr each. */
.split-cards{display:grid; gap:clamp(1.75rem,3vw,2.75rem); grid-template-columns:1fr}
@media (min-width:900px){ .split-cards{grid-template-columns:minmax(0,1fr) minmax(0,1fr)} }

/* ==========================================================================
   MAP — "One team in Kigali"
   A WordPress translation of the React/dotted-map component: the dot field is
   a pre-built SVG mask, arcs draw with stroke-dashoffset, and the travelling
   dots ride the paths with CSS offset-path. No JS, no bundle, no layout thrash.

   Colour comes from `color` on .map, so on the ink band it is one line:
   `.section--dark .map{color:var(--brand)}` — nothing else needs to change.
   ========================================================================== */
.map{
  position:relative;
  /* Locked to the dot SVG's own 800x330. The mask below stretches to the
     container while the <svg> fits its viewBox with "meet" — those two only
     agree when the container ratio IS the viewBox ratio. Any other ratio and
     the arcs slide off the land. Do not change this without changing
     scripts/build_world_dots.py to match. */
  aspect-ratio:800/330;
  color:var(--brand-ink);
  margin-bottom:var(--s-6);
}
/* The dot field. Two nested elements because each carries one mask: the outer
   fades top and bottom so the field never reads as a boxed rectangle, the inner
   supplies the dots. One mask per element avoids mask-composite, whose syntax
   still differs between Blink and WebKit.
   mask-image resolves relative to this stylesheet, i.e. theme root. */
.map__dots,.map__dots-in{position:absolute; inset:0; display:block}
.map__dots{
  pointer-events:none;
  -webkit-mask-image:linear-gradient(to bottom,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(to bottom,transparent,#000 8%,#000 92%,transparent);
}
.map__dots-in{
  background:currentColor; opacity:.22;
  -webkit-mask-image:url("assets/world-dots.svg");
  mask-image:url("assets/world-dots.svg");
  -webkit-mask-size:100% 100%; mask-size:100% 100%;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
}
.map__svg{position:absolute; inset:0; width:100%; height:100%; overflow:visible}

/* Arcs draw once, then hold. pathLength="1" on the path normalises the length,
   so dasharray/offset are 0..1 and need no getTotalLength(). Delay is set per
   arc inline by PHP — a :nth-of-type chain would break the moment an arc is
   added or the markup order changes. */
.map__arc{
  fill:none; stroke-width:1.1; stroke-linecap:round;
  stroke-dasharray:1; stroke-dashoffset:1;
  animation:aswp-draw 1.6s var(--ease) forwards;
}
@keyframes aswp-draw{to{stroke-dashoffset:0}}

.map__hub{fill:var(--brand)}
.map__hub-ring{fill:none; stroke:var(--brand); stroke-width:1.2}
.map__dest{fill:currentColor}

/* The travelling dot. Motion along the path is SMIL <animateMotion>, which is
   the one reliable way to move an SVG element along a path without JS
   (offset-path on SVG children is still patchy). It cannot be disabled per se,
   so reduced-motion hides the dot instead — an unrendered element animates
   nothing. */
.map__pulse{fill:var(--brand)}

/* The map is decorative; this list carries the same information as text. */
.map__legend{
  list-style:none; padding:0; margin:0;
  display:flex; flex-wrap:wrap; gap:var(--s-3) var(--s-6);
}
.map__legend li{
  display:flex; align-items:center; gap:var(--s-3);
  font-size:var(--t-sm); color:var(--body);
}
.map__dot{
  width:9px; height:9px; border-radius:50%;
  background:var(--brand-ink); flex:none;
}
.map__dot--hub{background:var(--brand)}

@media (max-width:640px){
  /* The ratio stays locked here too: changing it would stretch the mask while
     the arcs letterbox, sliding the markers off the land. The map simply gets
     shorter on a phone, and the legend stacks under it. */
  .map__legend{flex-direction:column; gap:var(--s-3)}
}
@media (prefers-reduced-motion:reduce){
  .map__arc{animation:none; stroke-dashoffset:0}
  .map__pulse{display:none}
}

/* ==========================================================================
   INTEGRATIONS
   --------------------------------------------------------------------------
   Every logo is painted through a CSS mask, not an <img>. Two reasons:
   simple-icons SVGs carry no fill attribute, so an <img> renders them black
   (invisible on the dark band); and thirty brand palettes side by side is a
   logo-soup tell. Masked, they all take --ink here and --white on dark.

   The ink only reaches full strength on hover. Nine low-contrast marks read as
   texture; the one you are pointing at reads as a logo. That is the whole
   interaction — no lift, no shadow.
   ========================================================================== */
.int__grid{
  list-style:none; margin:0 0 var(--s-5); padding:0;
  display:grid; gap:var(--s-3);
  grid-template-columns:1fr;
}
@media (min-width:560px){ .int__grid{grid-template-columns:repeat(2,1fr)} }
@media (min-width:920px){ .int__grid{grid-template-columns:repeat(3,1fr)} }

.int{
  display:flex; gap:var(--s-3); align-items:flex-start;
  padding:var(--s-4);
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--radius-card);
  transition:border-color .18s var(--ease), background .18s var(--ease), transform .22s var(--ease);
}
.int:hover{border-color:var(--line-strong)}
.int:hover .int__mark{opacity:1;transform:scale(1.06)}

/* Full-colour brand artwork stays inside a fixed optical box so marks with
   different aspect ratios remain aligned without losing their real colours. */
.int__mark{
  flex:none; width:26px; height:26px; margin-top:2px;
  object-fit:contain; opacity:.92;
  transition:opacity .18s var(--ease), transform .18s var(--ease);
}
.int__body h3{font-size:var(--t-base); font-weight:600; margin-bottom:.15rem}
.int__body p{font-size:var(--t-sm); color:var(--muted); margin:0}

.int__note{
  font-size:var(--t-sm); color:var(--muted);
  max-width:70ch; margin:0;
  padding-top:var(--s-4); border-top:1px solid var(--line-warm);
}
.int__all{display:inline-flex;align-items:center;gap:.55rem;margin-top:var(--s-4);color:var(--ink);font-size:var(--t-sm);font-weight:650;text-decoration:none;border-bottom:1px solid currentColor;padding-bottom:.18rem}
.int__all:hover{color:var(--brand-ink)}
.int__all svg{width:1rem;height:1rem;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;transition:transform .18s var(--ease)}
.int__all:hover svg{transform:translateX(3px)}

/* ==========================================================================
   CAPABILITY CAROUSEL
   --------------------------------------------------------------------------
   A deliberate horizontal gallery for the work people can hand to their AI.
   It borrows the generous, tactile rhythm of an experiment gallery without
   imitating another product: these are task capabilities, not mock screens.
   The cards remain real HTML, keyboard scrollable and usable without JS.
   ========================================================================== */
.capability-section{position:relative;overflow:hidden;background:#f3efe9}
.capability-section__shape{position:absolute;z-index:0;top:clamp(2rem,2vw,4rem);right:clamp(-17rem,-7vw,-6rem);width:clamp(28rem,48vw,55rem);height:clamp(20rem,37vw,40rem);background:#c7dfb8;border-radius:44% 56% 49% 51% / 41% 42% 58% 59%;transform:rotate(-11deg)}
.capability-section__wrap{position:relative;z-index:1;max-width:var(--wide);padding-inline:clamp(1rem,6vw,8rem)}
.capability-section__head{max-width:78rem;margin-inline:0;text-align:left;margin-bottom:clamp(.75rem,.5rem + 1vw,1.5rem)}
.capability-section__head h2{max-width:17ch;font-size:clamp(3rem,6.35vw,7rem);line-height:.94;letter-spacing:-.075em}
.capability-section__head h2 em{font-style:normal;color:#5a6c4e}
.capability-section__head .lead{margin-inline:0;max-width:52ch}
.capability-carousel{position:relative;margin-inline:calc(50% - 50vw);width:100vw}
.capability-carousel__viewport{overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;cursor:grab;outline:0}
.capability-carousel__viewport::-webkit-scrollbar{display:none}
.capability-carousel__viewport:focus-visible{outline:3px solid var(--brand);outline-offset:5px;border-radius:var(--radius-card)}
.capability-carousel__track{display:flex;gap:clamp(1rem,2.3vw,2rem);width:max-content;padding:4.25rem max(1rem,calc((100vw - var(--wide))/2 - 6rem)) 9.5rem 0}
.capability-card{--curve-y:0px;--curve-r:0deg;--float-delay:0s;width:clamp(20rem,28vw,29rem);display:flex;flex-direction:column;scroll-snap-align:start;overflow:hidden;padding:.8rem .8rem 0;background:#fff;border:0;border-radius:2rem;box-shadow:none;transform:translateY(var(--curve-y)) rotate(var(--curve-r));animation:capability-breathe 8s ease-in-out var(--float-delay) infinite;will-change:transform}
.capability-card:nth-child(6n + 1){--curve-y:7.5rem;--curve-r:-11deg;--float-delay:-2.4s}
.capability-card:nth-child(6n + 2){--curve-y:2.5rem;--curve-r:-6deg;--float-delay:-5.2s}
.capability-card:nth-child(6n + 3){--curve-y:-1.65rem;--curve-r:-1.5deg;--float-delay:-1.2s}
.capability-card:nth-child(6n + 4){--curve-y:-1.15rem;--curve-r:2.5deg;--float-delay:-4.4s}
.capability-card:nth-child(6n + 5){--curve-y:3rem;--curve-r:7deg;--float-delay:-6.1s}
.capability-card:nth-child(6n + 6){--curve-y:8.5rem;--curve-r:12deg;--float-delay:-3.3s}
@keyframes capability-breathe{0%,100%{transform:translateY(var(--curve-y)) rotate(var(--curve-r))}50%{transform:translateY(calc(var(--curve-y) - .16rem)) rotate(var(--curve-r))}}
.capability-card__visual{position:relative;aspect-ratio:1/.88;overflow:hidden;background:#f4efe7;border-radius:1.3rem}
.capability-card__image{display:block;width:100%;height:100%;object-fit:cover}
.capability-card__content{display:flex;flex:1;flex-direction:column;padding:clamp(1.1rem,.85rem + .8vw,1.5rem) clamp(.55rem,.35rem + .5vw,.85rem) 1.35rem}
.capability-card__label{margin:0 0 .55rem;color:var(--brand-ink);font-size:var(--t-xs);font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.capability-card h3{margin-bottom:.65rem;font-size:var(--t-xl);line-height:1.1}
.capability-card__content>p:not(.capability-card__label){margin:0;color:var(--muted);font-size:var(--t-sm);line-height:1.6}
.capability-card__link{display:inline-flex;gap:.55rem;align-items:center;width:max-content;margin-top:auto;padding-top:1.4rem;color:var(--ink);font-size:var(--t-sm);font-weight:650;text-decoration:none}
.capability-card__link:hover{color:var(--brand-ink)}
.capability-card__link span{transition:transform .18s var(--ease)}
.capability-card__link:hover span{transform:translateX(3px)}
.capability-carousel__controls{display:flex;justify-content:flex-end;gap:.65rem;margin-top:var(--s-4)}
.capability-carousel__button{display:grid;place-items:center;width:2.9rem;height:2.9rem;border:1px solid var(--line-strong);border-radius:50%;background:transparent;color:var(--ink);font:inherit;font-size:1.25rem;line-height:1;cursor:pointer;transition:background .18s var(--ease),border-color .18s var(--ease),color .18s var(--ease)}
.capability-carousel__button:hover{background:var(--ink);border-color:var(--ink);color:#fff}
.capability-carousel__button:focus-visible{outline:3px solid var(--brand);outline-offset:2px}
@media (max-width:680px){.capability-section__shape{top:5rem;right:-15rem;width:30rem;height:24rem}.capability-section__wrap{padding-inline:1rem}.capability-section__head h2{max-width:13ch;font-size:clamp(2.65rem,13vw,4rem)}.capability-carousel__track{padding-block:2.2rem 5.5rem;padding-right:1.5rem}.capability-card{width:min(84vw,23rem);padding:.6rem .6rem 0;border-radius:1.55rem}.capability-card__visual{border-radius:1.05rem}.capability-card:nth-child(6n + 1){--curve-y:3rem;--curve-r:-7deg}.capability-card:nth-child(6n + 2){--curve-y:1rem;--curve-r:-3deg}.capability-card:nth-child(6n + 3){--curve-y:-.8rem;--curve-r:-1deg}.capability-card:nth-child(6n + 4){--curve-y:-.45rem;--curve-r:1.5deg}.capability-card:nth-child(6n + 5){--curve-y:1.25rem;--curve-r:4deg}.capability-card:nth-child(6n + 6){--curve-y:3.6rem;--curve-r:7deg}.capability-carousel__controls{display:none}}
@media (prefers-reduced-motion:reduce){.capability-carousel__viewport{scroll-behavior:auto}.capability-card,.capability-card__link span{animation:none;transition:none}.capability-card{transform:none}}

/* ==========================================================================
   CONNECTION MAP
   --------------------------------------------------------------------------
   Shows how Swifts AI sits between where customers reach you and where the
   work lands. Pure CSS: the connectors are pseudo-element rules, so there is
   no SVG, no canvas and nothing to load or keep in sync.

   The three nodes of a connector are staggered in size, not identical. Three
   equal boxes with three equal arrows is the diagram equivalent of the
   twelve-identical-cards tell.
   ========================================================================== */
.wire{
  display:flex; flex-direction:column; align-items:stretch;
  gap:0; margin-bottom:var(--s-8);
}

/* --- one row of endpoint chips ------------------------------------------- */
.wire__row{display:flex; flex-direction:column; gap:var(--s-3)}
.wire__label{
  font-size:var(--t-xs); font-weight:500; color:#8b967f;
}
.wire__nodes{
  list-style:none; margin:0; padding:0;
  display:flex; flex-wrap:wrap; gap:var(--s-2);
}
.wire__node{
  padding:.5em .95em; border-radius:var(--radius-pill);
  border:1px solid var(--line-mid); background:rgba(255,255,255,.04);
  color:#d6ddcd; font-size:var(--t-sm);
  transition:border-color .18s var(--ease), color .18s var(--ease);
}
.wire__node:hover{border-color:var(--brand); color:#fff}

/* --- the connector: three rules that read as a joining line, not an arrow -- */
.wire__stem{
  align-self:center; display:flex; flex-direction:column; align-items:center;
  gap:.28rem; padding-block:var(--s-3); position:relative;
}
.wire__stem i{
  display:block; width:1px; background:var(--line-mid);
  height:clamp(12px,1.6vw,20px);
}
/* the middle rule is the brand one, so the eye follows the flow */
.wire__stem i:nth-child(2){background:var(--brand); width:2px; border-radius:2px}

/* --- the hub: the only filled node, so it reads as the centre ------------- */
.wire__hub{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:var(--s-4) var(--s-6);
  padding:clamp(1.1rem,1rem + 1vw,1.6rem) clamp(1.2rem,1rem + 1.6vw,2rem);
  border-radius:var(--radius-card);
  background:var(--brand); color:var(--ink);
  border:1px solid var(--brand);
}
.wire__hub b{
  display:block; font-family:var(--font-display); font-weight:500;
  font-size:var(--t-2xl); letter-spacing:-.02em; line-height:1.1;
}
.wire__hub span{font-size:var(--t-sm); color:#33401f; display:block; margin-top:.25rem}
.wire__hub-roles{
  list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:var(--s-2);
}
.wire__hub-roles li{
  font-size:var(--t-xs); font-weight:600; letter-spacing:0;
  padding:.34em .7em; border-radius:var(--radius-pill);
  background:rgba(14,20,10,.14); color:#20290f;
}

@media (min-width:820px){
  /* On wide screens the endpoints flank the hub instead of stacking above and
     below it, which is what a connection actually looks like. */
  .wire{
    display:grid; align-items:center;
    grid-template-columns:minmax(0,.9fr) 72px minmax(0,1.35fr) 72px minmax(0,.9fr);
  }
  .wire__row{grid-row:1}
  .wire__row:first-child{grid-column:1; text-align:right}
  .wire__row:first-child .wire__nodes{justify-content:flex-end}
  .wire__stem{grid-row:1; align-self:center; padding-block:0;
    flex-direction:row; gap:.28rem}
  .wire__stem i{height:1px; width:clamp(12px,1.6vw,20px)}
  .wire__stem i:nth-child(2){width:clamp(18px,2.4vw,30px); height:2px}
  .wire__hub{grid-row:1; grid-column:3; flex-direction:column; align-items:flex-start;
    gap:var(--s-3)}
  .wire__row:last-child{grid-column:5}
  .wire__stem:first-of-type{grid-column:2}
  .wire__stem:last-of-type{grid-column:4}
.wire__hub-roles{width:100%}
}

/* Live integration map. Every named service uses its official mark; the moving
   pulses originate at the AppSwifts AI hub and travel along a route to each
   connected surface. The route is deliberately decorative rather than a claim
   of a permanently active third-party connection. */
.flow-map{max-width:1120px;margin:0 auto}
.flow-map__canvas{position:relative;min-height:35rem;isolation:isolate}
.flow-map__routes{position:absolute;inset:0;width:100%;height:100%;overflow:visible;z-index:-1}
.flow-map__route-lines use{fill:none;stroke:rgba(214,237,188,.31);stroke-width:1.5;vector-effect:non-scaling-stroke}
.flow-map__route-pulses circle{fill:var(--brand);filter:drop-shadow(0 0 6px var(--brand))}
.flow-map__nodes{position:absolute;inset:0;list-style:none;margin:0;padding:0}
.flow-node{position:absolute;top:calc(3.25rem + (var(--flow-row) * 6.8rem));display:flex;align-items:center;gap:.7rem;min-width:10rem;color:#e4ebde}
.flow-node--input{right:calc(50% + 13.75rem);justify-content:flex-end;text-align:right}
.flow-node--output{left:calc(50% + 13.75rem)}
.flow-node__label{font-size:var(--t-sm);font-weight:650;white-space:nowrap}
.flow-node__mark{width:1.7rem;height:1.7rem;flex:0 0 1.7rem;object-fit:contain;filter:drop-shadow(0 0 7px color-mix(in srgb,var(--flow-brand) 24%,transparent))}
.flow-node--input .flow-node__label{order:-1}
.flow-hub{position:absolute;top:50%;left:50%;width:13.5rem;min-height:11.5rem;transform:translate(-50%,-50%);display:grid;align-content:center;justify-items:center;text-align:center;gap:.85rem;padding:1.2rem;isolation:isolate}
.flow-hub::before{content:"";position:absolute;inset:0;border:1px solid rgba(191,234,138,.42);border-radius:var(--radius-card);background:linear-gradient(145deg,rgba(134,193,59,.18),rgba(134,193,59,.045));box-shadow:0 18px 46px -30px rgba(134,193,59,.9);z-index:-1}
.flow-hub::after{content:"";position:absolute;inset:.45rem;border:1px solid rgba(221,243,192,.13);border-radius:calc(var(--radius-card) - .35rem);z-index:-1}
.flow-hub__icon{display:block;width:4.9rem;height:4.9rem;object-fit:contain;border-radius:50%;box-shadow:0 0 0 9px rgba(134,193,59,.1),0 16px 34px -16px rgba(134,193,59,.75)}
.flow-hub__orbit{position:absolute;top:.9rem;left:50%;width:6.35rem;height:6.35rem;border:1px solid rgba(193,237,138,.32);border-radius:50%;transform:translateX(-50%);animation:flow-orbit 4.2s linear infinite}
.flow-hub strong{display:block;color:#fff;font-family:var(--font-display);font-size:var(--t-xl);font-weight:500;letter-spacing:-.02em}
@keyframes flow-orbit{to{transform:translateX(-50%) rotate(360deg)}}
@media (max-width:850px){.flow-map__canvas{min-height:32rem}.flow-node--input{right:calc(50% + 11.25rem)}.flow-node--output{left:calc(50% + 11.25rem)}.flow-hub{width:11rem}.flow-node{min-width:auto}.flow-node__label{font-size:var(--t-xs)}}
@media (max-width:620px){.flow-map__canvas{min-height:auto;display:grid;gap:var(--s-5)}.flow-map__routes{display:none}.flow-map__nodes{position:static;display:grid;gap:.65rem}.flow-map__nodes--input{order:2}.flow-map__nodes--output{order:3}.flow-node{position:static;justify-content:flex-start;text-align:left}.flow-node--input .flow-node__label{order:0}.flow-hub{position:relative;inset:auto;transform:none;width:min(100%,15rem);min-height:10.5rem;margin-inline:auto;order:1}.flow-hub__orbit{animation:none}}
@media (prefers-reduced-motion:reduce){.flow-map__route-pulses{display:none}.flow-hub__orbit{animation:none}}
.service__items p{color:var(--body); font-size:var(--t-sm); line-height:1.62; margin:0; max-width:62ch}
.badge{
  display:inline-block; padding:.28em .75em; border-radius:var(--radius-pill);
  font-family:var(--font-mono);
  font-size:var(--t-xs); font-weight:500; letter-spacing:.04em;
  background:var(--brand); color:#0e140a;
}
.badge--soft{background:var(--brand-soft); color:var(--brand-ink); box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--brand) 26%,transparent)}

/* ==========================================================================
   9. PROCESS / STEPS
   ========================================================================== */
.steps{counter-reset:step; list-style:none; padding:0; margin:0; display:grid; gap:0;
  border-top:1px solid var(--line);
  /* Both rails now sit under a centred header, so the rail is held to a readable
     measure on the same centre axis. At full container width the 56ch copy ended
     up stranded against the left edge with dead space to its right. */
  max-width:48rem; margin-inline:auto}
/* Vertical rail. The number is a grid cell, not an absolutely positioned badge:
   the old layout dropped the counter box on top of the heading it belongs to
   (4px overlap at 1440px) because the item column was wider than the item. */
.steps li{
  counter-increment:step; position:relative;
  display:grid; grid-template-columns:44px 1fr; gap:var(--s-4);
  align-items:start; padding-block:var(--s-5);
  border-bottom:1px solid var(--line);
}
.steps li::before{
  content:counter(step,decimal-leading-zero);
  font-family:var(--font-display); font-size:var(--t-lg); font-weight:500;
  letter-spacing:-.02em; line-height:1.1;
  color:var(--brand-ink); font-variant-numeric:tabular-nums;
  padding-top:.1em;
}
.steps h3{font-size:var(--t-lg); margin-bottom:var(--s-2)}
.steps p{font-size:var(--t-sm); line-height:1.62; margin:0; max-width:56ch}
/* On the ink band the rail rules and figures need the dark palette. */
.steps--dark{border-top-color:var(--line-dark)}
.steps--dark li{border-bottom-color:var(--line-dark)}
.steps--dark li::before{color:var(--brand)}
.steps--dark h3{color:#fff}
.steps--dark p{color:#a9b49f}

/* The onboarding sequence uses the same shared structure as the supplied
   component: one progression line, one number per card, then cards with an
   icon, concise explanation and practical outcomes. It is not a timeline rail
   because the four stages are equally important. */
.onboarding{max-width:72rem;margin:clamp(2.5rem,2rem + 2vw,4rem) auto 0}
.onboarding__markers{position:relative;display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-5);list-style:none;margin:0 0 var(--s-5);padding:0}
.onboarding__markers::before{content:"";position:absolute;top:50%;left:12.5%;right:12.5%;height:1px;background:var(--line-mid);transform:translateY(-50%)}
.onboarding__markers li{position:relative;z-index:1;display:grid;place-items:center;justify-self:center;width:2.5rem;height:2.5rem;border:1px solid var(--line-mid);border-radius:50%;background:var(--ink);color:var(--brand);font-family:var(--font-display);font-weight:600;font-variant-numeric:tabular-nums}
.onboarding__cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s-4)}
.onboarding-card{min-height:100%;padding:clamp(1.25rem,1rem + 1vw,1.65rem);border:1px solid var(--line-mid);border-radius:var(--radius-card);background:rgba(255,255,255,.025);transition:border-color .2s var(--ease),background .2s var(--ease),transform .2s var(--ease)}
.onboarding-card:hover{border-color:rgba(191,234,138,.6);background:rgba(191,234,138,.055);transform:translateY(-3px)}
.onboarding-card__icon{display:grid;place-items:center;width:2.75rem;height:2.75rem;margin-bottom:var(--s-4);border-radius:.75rem;background:rgba(191,234,138,.11);color:var(--brand)}
.onboarding-card__icon svg{width:1.35rem;height:1.35rem;fill:none;stroke:currentColor;stroke-width:1.65;stroke-linecap:round;stroke-linejoin:round}
.onboarding-card h3{margin:0 0 var(--s-2);font-size:var(--t-lg);color:#fff;line-height:1.15}
.onboarding-card p{margin:0 0 var(--s-5);font-size:var(--t-sm);line-height:1.55;color:#a9b49f}
.onboarding-card ul{display:grid;gap:.7rem;list-style:none;margin:0;padding:0}
.onboarding-card li{display:flex;gap:.6rem;align-items:flex-start;color:#c9d1c0;font-size:var(--t-xs);line-height:1.45}
.onboarding-card li::before{content:"";width:.43rem;height:.43rem;flex:none;margin-top:.33rem;border-radius:50%;background:var(--brand)}
@media (max-width:860px){.onboarding__markers{display:none}.onboarding__cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.onboarding__cards{grid-template-columns:1fr}.onboarding-card{padding:1.35rem}.onboarding-card:hover{transform:none}}
@media (prefers-reduced-motion:reduce){.onboarding-card{transition:none}.onboarding-card:hover{transform:none}}

/* ==========================================================================
   10. LOGO / PROOF STRIP
   ========================================================================== */
.proof{display:flex; flex-wrap:wrap; align-items:center; gap:var(--s-5) var(--s-6); list-style:none; padding:0; margin:0; justify-content:center}
.proof li{font-family:var(--font-display); font-weight:600; font-size:var(--t-sm); color:var(--muted);
  letter-spacing:-.01em; opacity:.85}

/* ==========================================================================
   11. CTA BAND
   ========================================================================== */
/* CTA band: flat brand fill, not a gradient. Supabase rule — the accent is an
   identity marker, and gradients on it muddy the one strong colour we have. */
.cta{
  background:var(--brand); color:#0e140a; border-radius:var(--radius-lg);
  padding:clamp(2.25rem,1.5rem + 3.5vw,4rem); text-align:center;
  box-shadow:0 24px 60px -30px rgba(134,193,59,.55);
}
.cta h2{color:#0e140a; margin-bottom:var(--s-3); letter-spacing:-.032em}
.cta p{color:#1e2a10; max-width:52ch; margin-inline:auto; font-size:var(--t-lg)}
.cta .btn-row{justify-content:center; margin-top:var(--s-6)}
/* On the lime CTA band, .btn--primary is lime-on-lime: 1.00:1, an invisible
   button. .btn--dark renders as ink-on-lime (8.64:1) in the same position, so
   the band recolours both buttons rather than each one carrying two palettes. */
.cta .btn--primary{background:var(--ink); color:#fff}
.cta .btn--primary:hover{background:var(--ink-2); color:#fff}
.cta .btn--on-dark{border-color:rgba(14,20,10,.28); color:var(--ink); background:transparent}
.cta .btn--on-dark:hover{border-color:var(--ink); background:rgba(14,20,10,.06); color:var(--ink)}

/* ==========================================================================
   12. FOOTER
   ========================================================================== */
.site-footer{
  background:var(--ink); color:#98a48e;
  padding-block:var(--s-8) var(--s-5); font-size:var(--t-sm);
  border-top:1px solid var(--line-dark);
}
.site-footer h4{
  color:#fff; font-family:var(--font-body);
  font-size:var(--t-sm); font-weight:600; letter-spacing:0;
  margin-bottom:var(--s-4);
}
.site-footer a{color:#b7c0ad; text-decoration:none}
.site-footer a:hover{color:var(--brand); text-decoration:underline}
.site-footer ul{list-style:none; padding:0; margin:0; display:grid; gap:var(--s-2)}
.footer-grid{display:grid; gap:var(--s-6); grid-template-columns:repeat(auto-fit,minmax(min(100%,190px),1fr))}
.footer-grid .footer-brand{grid-column:1/-1}
@media (min-width:780px){ .footer-grid .footer-brand{grid-column:span 2} }
.footer-brand p{color:#98a48e; max-width:38ch}
.footer-bottom{
  margin-top:var(--s-7); padding-top:var(--s-5); border-top:1px solid rgba(255,255,255,.12);
  display:flex; flex-wrap:wrap; gap:var(--s-3) var(--s-5); align-items:center; justify-content:space-between;
  font-size:var(--t-xs); color:#7d8875;
}
.footer-bottom nav ul{display:flex; gap:var(--s-5); flex-wrap:wrap}

/* ===========================================================================
   PRICING
   ========================================================================== */
.page-hero--pricing .pricing-kicker{margin:0 0 var(--s-3);color:var(--brand);font-size:var(--t-sm);font-weight:700;letter-spacing:.02em}
.pricing-section{background:var(--bg)}
.pricing-tabs{display:flex;justify-content:center;gap:.35rem;width:max-content;max-width:100%;margin:0 auto clamp(2.5rem,4vw,4rem);padding:.35rem;border:1px solid var(--line);border-radius:var(--radius-pill);background:var(--surface);overflow-x:auto}
.pricing-tabs__tab{appearance:none;border:0;border-radius:var(--radius-pill);padding:.68rem 1rem;background:transparent;color:var(--muted);font:inherit;font-size:var(--t-sm);font-weight:650;cursor:pointer;white-space:nowrap;transition:background .18s var(--ease),color .18s var(--ease),box-shadow .18s var(--ease)}
.pricing-tabs__tab:hover{color:var(--ink)}
.pricing-tabs__tab.is-active{background:var(--ink);color:#fff;box-shadow:var(--shadow)}
.pricing-tabs__tab:focus-visible{outline:3px solid var(--brand);outline-offset:2px}
.pricing-panel__head{text-align:center;max-width:48rem;margin:0 auto var(--s-7)}
.pricing-panel__head h2{margin-bottom:var(--s-3)}
.pricing-panel__head .lead{margin-inline:auto}
.pricing-group+.pricing-group{margin-top:var(--s-8)}
.pricing-group__title{font-family:var(--font-body);font-size:var(--t-sm);font-weight:700;letter-spacing:.02em;text-transform:uppercase;color:var(--muted);padding-bottom:var(--s-3);border-bottom:1px solid var(--line);margin-bottom:var(--s-4)}
.pricing-grid{display:grid;grid-template-columns:1fr;gap:var(--s-4)}
.pricing-card{display:flex;flex-direction:column;padding:var(--s-6);border:1px solid var(--line);border-radius:var(--radius-card);background:var(--surface)}
.pricing-card--featured{border-color:color-mix(in srgb,var(--brand) 72%,var(--line));box-shadow:inset 0 3px 0 var(--brand)}
.pricing-card__badge{align-self:flex-start;margin:0 0 var(--s-3);padding:.3rem .6rem;background:var(--brand-soft);border-radius:var(--radius-pill);color:var(--brand-ink);font-size:var(--t-xs);font-weight:700}
.pricing-card h4{font-size:var(--t-xl);margin:0 0 var(--s-2);letter-spacing:-.02em}
.pricing-card__desc{margin:0;color:var(--muted);font-size:var(--t-sm);line-height:1.6}
.pricing-card__price{margin:var(--s-5) 0 0;color:var(--ink);font-family:var(--font-display);font-size:clamp(2rem,1.5rem + 1.5vw,2.65rem);font-weight:500;letter-spacing:-.035em;line-height:1}
.pricing-card__price span{font-family:var(--font-body);font-size:var(--t-sm);font-weight:500;letter-spacing:0;color:var(--muted)}
.pricing-card__unit{margin:var(--s-2) 0 var(--s-5);color:var(--muted);font-size:var(--t-sm)}
.pricing-card ul{display:grid;gap:var(--s-3);list-style:none;padding:0;margin:0 0 var(--s-6);font-size:var(--t-sm);color:var(--body);line-height:1.45}
.pricing-card li{display:flex;gap:.65rem;align-items:flex-start}
.pricing-card li>span{display:grid;place-items:center;flex:none;width:1.1rem;height:1.1rem;color:var(--brand-ink);margin-top:.05rem}
.pricing-card li svg{width:100%;height:100%;stroke:currentColor}
.pricing-card .btn{margin-top:auto;justify-content:center}
.pricing-assurance{display:grid;gap:var(--s-5);grid-template-columns:1fr;margin-top:var(--s-8);padding-top:var(--s-6);border-top:1px solid var(--line)}
.pricing-assurance div{display:grid;gap:.35rem}
.pricing-assurance strong{font-size:var(--t-sm);color:var(--ink)}
.pricing-assurance span,.pricing-assurance a{font-size:var(--t-sm);color:var(--muted);line-height:1.55}
.pricing-assurance a{color:var(--brand-ink);font-weight:650;text-decoration:none}
.pricing-assurance a:hover{text-decoration:underline}
@media (min-width:720px){.pricing-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.pricing-assurance{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-6)}}
@media (min-width:1080px){.pricing-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}

/* ==========================================================================
   13. CONTENT: posts, pages, blocks
   ========================================================================== */
.entry-content{max-width:68ch}
.entry-content>*+*{margin-top:var(--s-4)}
.entry-content h2{margin-top:var(--s-7)}
.entry-content h3{margin-top:var(--s-6)}
.entry-content img,.entry-content figure{border-radius:var(--radius); margin-block:var(--s-5)}
.entry-content blockquote{
  margin:var(--s-5) 0; padding:var(--s-4) var(--s-5);
  border-left:3px solid var(--brand); background:var(--brand-soft);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0; color:var(--ink);
}
.entry-content code{background:var(--brand-soft); color:var(--brand-ink);
  padding:.15em .4em; border-radius:5px; font-family:var(--font-mono); font-size:.9em}
.entry-content pre{background:var(--ink); color:#e6eae1; padding:var(--s-4);
  border-radius:var(--radius); overflow-x:auto; font-size:var(--t-sm)}
.entry-content pre code{background:none;color:inherit;padding:0}
.entry-content table{width:100%; border-collapse:collapse; font-size:var(--t-sm)}
.entry-content th,.entry-content td{padding:.6em .8em; border-bottom:1px solid var(--line); text-align:left}
.entry-content th{color:var(--ink); font-weight:600; background:var(--brand-soft)}

.post-card{display:flex;flex-direction:column;background:var(--surface);
  border:1px solid var(--line); border-radius:var(--radius); overflow:hidden; box-shadow:var(--shadow)}
.post-card img{aspect-ratio:16/9;object-fit:cover;width:100%}
.post-card__body{padding:var(--s-4); display:flex; flex-direction:column; gap:var(--s-2); flex:1}
.post-card h3{font-size:var(--t-lg); margin:0}
.post-card h3 a{color:var(--ink); text-decoration:none}
.post-card h3 a:hover{color:var(--brand-ink)}
.post-card time{font-size:var(--t-xs); color:var(--muted)}
/* Interior pages open on the same near-black band as the homepage hero, so the
   site keeps one frame: dark above, dark below, bright content between.
   Wider where a display heading lives, so 96px type gets the room to be 96px. */
.page-hero{background:var(--ink); color:#b7c0ad; padding-block:clamp(3rem,2.2rem + 3.2vw,5.25rem); text-align:center}
/* interior pages get the 3xl step, so the homepage headline stays the biggest
   thing on the site */
.page-hero h1{color:#fff; margin-bottom:var(--s-4); font-size:var(--t-3xl);
  letter-spacing:-.015em; line-height:1.04; margin-inline:auto; max-width:22ch}
.page-hero p{color:#a9b49f; max-width:56ch; font-size:var(--t-lg); margin-inline:auto}
.page-hero .btn-row{justify-content:center}
/* Post date. Was an inline uppercase + 0.08em tracking label in the hero, which
   read as a generated "eyebrow" chip. Sentence case, body face. */
.post-date{display:block; font-size:var(--t-sm); letter-spacing:0; color:var(--brand); margin-bottom:var(--s-3)}
.page-hero .wrap{max-width:var(--maxw-wide)}
.pagination{display:flex;gap:var(--s-3);justify-content:center;margin-top:var(--s-7)}
.alignwide{max-width:1320px;margin-inline:auto}
.wp-block-image figcaption{font-size:var(--t-xs);color:var(--muted);text-align:center;margin-top:var(--s-2)}
.screen-reader-text{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ==========================================================================
   Portfolio — work archive, taxonomy filters, single project
   Added when the 22 projects were imported from the original site.
   ========================================================================== */

/* --- filter bar: plain links, so filters work with JS off and stay crawlable -- */
.filter-bar{display:flex;flex-direction:column;gap:var(--s-4);margin-bottom:var(--s-7);
  padding-bottom:var(--s-5);border-bottom:1px solid var(--line)}
.filter-bar__row{display:flex;gap:var(--s-4);align-items:baseline;flex-wrap:wrap}
.filter-bar__label{font-family:var(--font-body);font-size:var(--t-sm);font-weight:500;
  letter-spacing:0;color:var(--muted);flex:none;min-width:66px}
.pill-list{display:flex;flex-wrap:wrap;gap:var(--s-2);list-style:none;margin:0;padding:0}
.pill{display:inline-flex;align-items:center;gap:.5em;
  padding:.34em .85em;border-radius:var(--radius-pill);border:1px solid var(--line);
  background:var(--surface);color:var(--ink);font-size:var(--t-sm);font-weight:500;
  text-decoration:none;transition:border-color .18s var(--ease),background .18s var(--ease)}
.pill:hover{border-color:var(--brand);background:var(--brand-soft);color:var(--brand-ink)}
.pill__n{font-family:var(--font-mono);font-size:.72em;color:var(--muted);
  background:var(--bg);border-radius:var(--radius-pill);padding:.1em .5em}
.pill:hover .pill__n{background:var(--surface);color:var(--brand-ink)}

/* --- work card: image flush to the card edge, so it needs its own padding ---- */
.work-card{padding:0;overflow:hidden}
.work-card__media{overflow:hidden;background:var(--bg);border-bottom:1px solid var(--line)}
.work-card__media img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;
  transition:transform .35s var(--ease)}
.work-card:hover .work-card__media img{transform:scale(1.03)}
.work-card__body{padding:var(--s-5);display:flex;flex-direction:column;flex:1}
.work-card__tags{display:flex;flex-wrap:wrap;gap:var(--s-1);margin:0 0 var(--s-3)}

/* Partner proof uses the actual customer marks only. The presentation removes
   every card/container so the marks read as one quiet, static proof line. */
.partner-proof .section__head{margin-bottom:var(--s-5)}
.partner-proof__line{margin:0;color:#737b89;font-size:clamp(1rem,.92rem + .35vw,1.25rem);line-height:1.45}
.partner-logo-slider{width:100%}
.partner-logos{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); align-items:center;
  gap:clamp(.5rem,1.4vw,1.5rem);
}
.partner-logos__item{min-width:0;display:grid}
.partner-logo{
  width:100%; min-height:64px; padding:var(--s-2);
  display:grid; place-items:center;
  text-decoration:none; border-radius:var(--radius-sm);
  transition:opacity .18s var(--ease);
}
.partner-logo:hover{opacity:1}
.partner-logo:focus-visible{outline:3px solid var(--brand);outline-offset:3px}
.partner-logo__image{
  display:block; width:auto; height:auto;
  max-width:min(100%,184px); max-height:48px;
  object-fit:contain;
  filter:grayscale(1) brightness(.3) contrast(1.25);
  mix-blend-mode:multiply; opacity:.78;
  transition:opacity .18s var(--ease), transform .18s var(--ease);
}
.partner-logo:hover .partner-logo__image{opacity:1;filter:grayscale(1) brightness(.12) contrast(1.35);transform:scale(1.04)}
@media (max-width:900px){.partner-logos{grid-template-columns:repeat(4,minmax(0,1fr));gap:1rem}.partner-logo__image{max-height:42px}}
@media (max-width:540px){.partner-logos{grid-template-columns:repeat(2,minmax(0,1fr));gap:.7rem}.partner-logo{min-height:56px;padding:.35rem}.partner-logo__image{max-height:38px}}

/* FAQ: native details elements make the answers fast, keyboard-friendly and
   available without a JavaScript bundle. The plus becomes a minus when open. */
.section--faq{background:var(--surface);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.faq-layout{display:grid;gap:var(--s-7);align-items:start}
.faq-intro h2{max-width:11ch;margin-bottom:var(--s-3)}
.faq-intro .lead{max-width:34ch;margin-bottom:var(--s-5)}
.text-link{display:inline-flex;gap:.45em;align-items:center;color:var(--ink);font-weight:650;text-decoration:none;border-bottom:1px solid currentColor;padding-bottom:.14em}
.text-link:hover{color:var(--brand-ink)}
.faq-list{border-top:1px solid var(--line)}
.faq-item{border-bottom:1px solid var(--line)}
.faq-item summary{cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:var(--s-5);padding:var(--s-4) 0;color:var(--ink);font-family:var(--font-display);font-size:clamp(1.05rem,.99rem + .3vw,1.25rem);font-weight:600;line-height:1.25;list-style:none}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary:focus-visible{outline:3px solid var(--brand);outline-offset:4px;border-radius:var(--radius-sm)}
.faq-item__icon{flex:0 0 1.35rem;width:1.35rem;height:1.35rem;position:relative;border:1px solid var(--ink);border-radius:50%}
.faq-item__icon::before,.faq-item__icon::after{content:"";position:absolute;left:50%;top:50%;width:.55rem;height:1px;background:currentColor;transform:translate(-50%,-50%)}
.faq-item__icon::after{transform:translate(-50%,-50%) rotate(90deg);transition:transform .2s var(--ease)}
.faq-item[open] .faq-item__icon::after{transform:translate(-50%,-50%) rotate(0)}
.faq-item__answer{display:grid;grid-template-rows:0fr;transition:grid-template-rows .24s var(--ease)}
.faq-item[open] .faq-item__answer{grid-template-rows:1fr}
.faq-item__answer p{overflow:hidden;margin:0;max-width:62ch;padding:0 2.4rem var(--s-5) 0;color:var(--muted);line-height:1.65}
@media (min-width:860px){.faq-layout{grid-template-columns:minmax(0,.72fr) minmax(0,1.28fr);gap:clamp(3rem,7vw,8rem)}}
@media (prefers-reduced-motion:reduce){.faq-item__answer,.faq-item__icon::after{transition:none}}

/* --- single project gallery: lead image full width, rest on a grid ----------- */
.gallery{display:grid;gap:var(--s-4);grid-template-columns:repeat(2,1fr)}
.gallery__item{margin:0}
.gallery__item--lead{grid-column:1/-1}
.gallery__item img{width:100%;height:100%;object-fit:cover;border-radius:var(--radius);
  border:1px solid var(--line);display:block}
@media(min-width:760px){.gallery{grid-template-columns:repeat(3,1fr)}}

/* --- project facts --- */
.detail-list{margin:0;display:flex;flex-direction:column;gap:var(--s-3)}
.detail-list__row{display:grid;grid-template-columns:1fr;gap:var(--s-1);
  padding-bottom:var(--s-3);border-bottom:1px solid var(--line)}
.detail-list__row:last-child{border-bottom:0;padding-bottom:0}
.detail-list dt{font-family:var(--font-body);font-size:var(--t-xs);font-weight:500;
  letter-spacing:.01em;color:var(--muted)}
.detail-list dd{margin:0;color:var(--ink);font-weight:500}
@media(min-width:640px){
  .detail-list__row{grid-template-columns:180px 1fr;align-items:baseline}
}

/* Blog cards: the migrated posts have no images (the original kept them in
   Elementor postmeta, which REST cannot see), so the card must not reserve
   media space it will never fill. */
.post-card__cat{
  font-family:var(--font-body); font-size:var(--t-xs); font-weight:500;
  letter-spacing:0;
  color:var(--brand-ink); text-decoration:none; width:fit-content;
}
.post-card__cat:hover{ color:var(--brand-600) }
.related{margin-top:var(--s-8); padding-top:var(--s-6); border-top:1px solid var(--line)}
.related h2{font-size:var(--t-xl); margin-bottom:var(--s-5)}
