/* Kurdify landing extras: layered ON TOP of site.css, never replacing it.
   Adds the minimal sun-bloom intro, the aurora hero light, the real-listings
   ticker, three Kurdistan photo bands with parallax, gentle scroll snapping
   and the mega-landing sections (audience trio, prices strip, Kurdify Credit,
   pledge, growth band, ranking teaser, education/freelance duo, signup CTA,
   giveaway). Everything uses site.css variables so the light and dark themes
   both work untouched. */

/*
  Copyright (c) Kavalsia Inc. All Rights Reserved.
  Lead Architect & Engineer: Siavash Sadighi
*/

/* scroll-snap removed: the photo bands were trapping scroll on mobile */
html{ scroll-snap-type:none }
.kband{ scroll-snap-align:none }

/* ---------- sun-bloom intro (#pre gets .pre-sun; base #pre rules in site.css)
   The gold Kurdify sun scales/blooms in over ~1s, then extras.js calls
   window.__kxPreFinish. CSS-ONLY FAILSAFE: the overlay fades itself out at
   1.5s (animation below, overriding site.css's 40s one) so the page can
   never stay hidden even if every script fails. site.css also gives
   .pre-sun icon sizing for other pages, so the container overrides it. */
#pre.pre-sun{
  width:auto; height:auto; margin:0; color:inherit;
  display:grid; place-items:center;
  /* CSS-only failsafe, pushed past the 1.85s JS finish so the orb has time to play */
  animation:kxPreAway .7s ease 2.3s forwards;
}
/* The orb blooms in from a soft blur + scale, holds, then on .done dissolves out
   through blur again - a slow "focus" both directions. */
.pre-sun .pl-orb{ animation:plBloomIn 1s cubic-bezier(.16,1,.3,1) both }
#pre.pre-sun.done{ opacity:0; visibility:hidden; transition:opacity .6s ease, visibility .6s ease }
#pre.pre-sun.done .pl-orb{ animation:plBloomOut .6s ease forwards }
@keyframes kxPreAway{ to{ opacity:0; visibility:hidden } }
@keyframes plBloomIn{ from{ opacity:0; transform:scale(.72); filter:blur(22px) } to{ opacity:1; transform:scale(1); filter:blur(0) } }
@keyframes plBloomOut{ to{ opacity:0; transform:scale(1.12); filter:blur(18px) } }
/* Sun orb, ported from the app (:4660) so the marketing intro matches it:
   pulsing glow, two ripples, two counter-spinning rings, and a spinning,
   pulsing gold sun. Loops until __kxPreFinish (or a failsafe) clears #pre. */
.pl-orb{position:relative;width:150px;height:150px;display:grid;place-items:center}
/* rotating gold arc sweeping the orb - a premium progress indicator */
.pl-orb::before{content:"";position:absolute;inset:-3%;border-radius:50%;z-index:1;opacity:.85; /* borderless-keep: spinner ring, draws the loading arc */
  background:conic-gradient(from 0deg, transparent 0 60%, color-mix(in oklab,var(--gold) 75%,transparent) 80%, transparent 90%);
  -webkit-mask:radial-gradient(circle, transparent 58%, #000 60%);
          mask:radial-gradient(circle, transparent 58%, #000 60%);
  animation:plspin 2.4s cubic-bezier(.6,.1,.4,.9) infinite}
.pl-glow{position:absolute;inset:-18%;border-radius:50%;background:radial-gradient(circle,color-mix(in oklab,var(--gold) 42%,transparent),transparent 62%);animation:plGlow 1.7s ease-in-out infinite;z-index:0} /* borderless-keep: spinner ring, draws the loading arc */
.pl-ripple{position:absolute;inset:8%;border-radius:50%;border:1.5px solid color-mix(in oklab,#e23b34 60%,transparent);opacity:0;z-index:1;animation:plRipple 2.1s ease-out infinite} /* borderless-keep: spinner ring, draws the loading arc */
.pl-ripple2{animation-delay:1.05s;border-color:color-mix(in oklab,var(--green) 55%,transparent)} /* borderless-keep: spinner ring, draws the loading arc */
.pl-ring{position:absolute;inset:6%;border-radius:50%;border:2.5px solid transparent;border-top-color:var(--gold);border-inline-end-color:color-mix(in oklab,#e23b34 55%,transparent);z-index:2;animation:plspin 1.05s linear infinite} /* borderless-keep: spinner ring, draws the loading arc */
.pl-ring2{inset:20%;border-top-color:var(--green);border-inline-end-color:color-mix(in oklab,var(--green) 30%,transparent);animation-duration:1.7s;animation-direction:reverse;opacity:.7} /* borderless-keep: spinner ring, draws the loading arc */
.pl-sun{position:relative;z-index:3;width:52px;height:52px;color:var(--gold);animation:plspin 3.4s linear infinite,plPulse 1.7s ease-in-out infinite;filter:drop-shadow(0 0 16px color-mix(in oklab,var(--gold) 60%,transparent))}
@keyframes plspin{to{transform:rotate(360deg)}}
@keyframes plGlow{0%,100%{opacity:.45;transform:scale(.9)}50%{opacity:.95;transform:scale(1.08)}}
@keyframes plRipple{0%{opacity:.7;transform:scale(.6)}100%{opacity:0;transform:scale(1.25)}}
@keyframes plPulse{0%,100%{filter:drop-shadow(0 0 12px color-mix(in oklab,var(--gold) 45%,transparent))}50%{filter:drop-shadow(0 0 22px color-mix(in oklab,var(--gold) 80%,transparent))}}
/* ---------- .pre-sun override: the Kurdistan flag as a loading orb ----------
   Rebuilt 2026-07-28. The flag reads outward from the centre: the 21-ray gold
   sun, then a pale band, then green below and red above, all of it turning at
   different speeds so the three colours cross each other instead of sitting
   still. Everything animates transform/opacity/filter only, every colour comes
   from the theme variables so light mode works untouched, and the whole thing
   still clears itself through the same failsafes. */
.pre-sun .pl-orb{ width:170px; height:170px }

/* faint full circle behind everything, so the arcs read as parts of one dial */
.pre-sun .pl-orb::after{content:"";position:absolute;inset:2%;border-radius:50%; /* borderless-keep: spinner ring, draws the loading arc */
  border:1px solid color-mix(in oklab,var(--gold) 14%,transparent);z-index:1} /* borderless-keep: spinner ring, draws the loading arc */

/* outer dial: one continuous red -> pale -> green sweep, masked to a hairline ring */
.pre-sun .pl-orb::before{ inset:-2%; opacity:.9;
  background:conic-gradient(from 0deg,
    transparent 0 6%,
    color-mix(in oklab,var(--red) 85%,transparent) 20%,
    color-mix(in oklab,var(--text) 70%,transparent) 34%,
    color-mix(in oklab,var(--green) 85%,transparent) 48%,
    transparent 64% 100%);
  -webkit-mask:radial-gradient(circle, transparent 88%, #000 90%);
          mask:radial-gradient(circle, transparent 88%, #000 90%);
  animation:plspin 2.8s cubic-bezier(.45,.05,.35,1) infinite }

/* red arc on top, green arc counter-turning under it, pale band between them */
.pre-sun .pl-ring{ inset:9%; border-width:2.5px; /* borderless-keep: spinner ring, draws the loading arc */
  border-top-color:var(--red); /* borderless-keep: spinner ring, draws the loading arc */
  border-inline-end-color:color-mix(in oklab,var(--red) 35%,transparent); /* borderless-keep: spinner ring, draws the loading arc */
  border-bottom-color:transparent; border-inline-start-color:transparent; /* borderless-keep: spinner ring, draws the loading arc */
  animation:plspin 2.2s cubic-bezier(.5,0,.3,1) infinite }
.pre-sun .pl-ring2{ display:block; inset:19%; border-width:2.5px; opacity:1; /* borderless-keep: spinner ring, draws the loading arc */
  border-top-color:var(--green); /* borderless-keep: spinner ring, draws the loading arc */
  border-inline-end-color:color-mix(in oklab,var(--green) 35%,transparent); /* borderless-keep: spinner ring, draws the loading arc */
  border-bottom-color:transparent; border-inline-start-color:transparent; /* borderless-keep: spinner ring, draws the loading arc */
  animation:plspin 3s cubic-bezier(.5,0,.3,1) infinite reverse }
.pre-sun .pl-ring3{ inset:14%; border-width:1px; /* borderless-keep: spinner ring, draws the loading arc */
  border-color:color-mix(in oklab,var(--text) 26%,transparent); /* borderless-keep: spinner ring, draws the loading arc */
  border-bottom-color:transparent; /* borderless-keep: spinner ring, draws the loading arc */
  animation:plspin 5.5s linear infinite }

/* pale light sweeping the gap between the arcs: the flag's white band, moving */
.pre-sun .pl-sweep{position:absolute;inset:11%;border-radius:50%;z-index:2;opacity:.5; /* borderless-keep: spinner ring, draws the loading arc */
  background:conic-gradient(from 0deg, transparent 0 72%, color-mix(in oklab,var(--text) 55%,transparent) 88%, transparent 96%);
  -webkit-mask:radial-gradient(circle, transparent 62%, #000 66%, #000 82%, transparent 86%);
          mask:radial-gradient(circle, transparent 62%, #000 66%, #000 82%, transparent 86%);
  animation:plspin 4.4s linear infinite}

/* red and green ripples breathing outward from the sun, offset half a beat */
.pre-sun .pl-ripple,.pre-sun .pl-ripple2{ display:block; inset:24%;
  border-color:color-mix(in oklab,var(--red) 55%,transparent); /* borderless-keep: spinner ring, draws the loading arc */
  animation:plRipple 3.2s cubic-bezier(.22,1,.36,1) infinite }
.pre-sun .pl-ripple2{ animation-delay:1.6s; border-color:color-mix(in oklab,var(--green) 55%,transparent) } /* borderless-keep: spinner ring, draws the loading arc */

/* the sun itself: 21 rays, turning slowly, breathing in gold */
.pre-sun .pl-sun{ width:66px; height:66px;
  animation:plspin 9s linear infinite, plPulse 3.2s ease-in-out infinite }
.pre-sun .pl-glow{ inset:-14%;
  background:radial-gradient(circle,
    color-mix(in oklab,var(--gold) 40%,transparent),
    color-mix(in oklab,var(--gold) 8%,transparent) 45%,
    transparent 68%);
  animation:plGlow 3.2s ease-in-out infinite }

@media (prefers-reduced-motion:reduce){
  .pl-glow,.pl-ripple,.pl-ring2{ animation:none }
  .pl-sun{ animation:plspin 2s linear infinite }
  #pre.pre-sun{ animation-delay:.4s }
  /* keep the flag colours, drop the spinning: a still dial with one slow sun */
  .pre-sun .pl-orb::before,.pre-sun .pl-sweep,.pre-sun .pl-ring,
  .pre-sun .pl-ring2,.pre-sun .pl-ring3,
  .pre-sun .pl-ripple,.pre-sun .pl-ripple2{ animation:none }
  .pre-sun .pl-ripple,.pre-sun .pl-ripple2{ opacity:.35 }
  .pre-sun .pl-sun{ animation:plspin 12s linear infinite }
  .pre-sun .pl-orb{ animation:none }}

/* ---------- hero: quiet living light instead of the photo blur ----------
   Two soft auras in brand gold and green drift very slowly behind the copy.
   Transform-only animation, oversized layer so edges never show. */
/* Toned down: the aurora blobs read as a muddy glow behind the headline. Kept as
   a whisper of brand warmth in the corners only, away from the text. */
.hero::before{
  inset:-22%;
  background:
    radial-gradient(34% 26% at 84% 16%, rgba(224,182,74,.07), transparent 72%),
    radial-gradient(30% 24% at 12% 84%, rgba(47,191,135,.05), transparent 72%);
  opacity:1;
  animation:kxAurora 40s ease-in-out infinite alternate;
}
@keyframes kxAurora{
  from{ transform:translate3d(-2.5%,-2%,0) scale(1) }
  to{ transform:translate3d(2.5%,3%,0) scale(1.09) }
}
html[data-theme="light"] .hero::before{ opacity:.55 }
@media (prefers-reduced-motion:reduce){ .hero::before{ animation:none }}

/* ---------- ticker intro: headline + one-line subtext above the ticker (item 1, 2026-08-31) ---------- */
/* Owner request 2026-09-04: more air above the heading, and the heading group closer to the
   ticker under it. Those are two different values and they used to be one accident: the intro
   had no top margin at all (its space came from whatever section happened to end above it)
   while .ticker carried a 2.4-3.6rem gap below it. So the group sat far from its own strip and
   close to the section it does not belong to, which is why it read as floating.
   Both now come off one token, --tki-rhythm, so the pair cannot drift apart in a later pass:
   the space ABOVE is the full measure and the space BELOW is a third of it. The heading now
   clearly belongs to the strip it introduces.
   margin-block-start rather than the margin shorthand, which would have zeroed the `auto`
   inline margins and taken the block off centre. */
.ticker-intro{ --tki-rhythm:clamp(3.4rem,6.6vw,5.4rem);
  position:relative; z-index:2; text-align:center; max-width:640px;
  margin-inline:auto;
  /* PADDING, not margin, and this is not a preference. .ticker-intro is the first element
     child of .wrap.center, whose padding-top is 0, so a margin-block-start here COLLAPSES
     THROUGH the parent and paints nothing. Measured before the fix: computed margin-top
     81.216px, actual painted gap above the heading 36.6px, i.e. the whole value was lost
     while the stylesheet looked correct. Padding cannot collapse, and the element has no
     background or rim, so it reads identically. */
  padding-block-start:var(--tki-rhythm); padding-inline:1rem }
.ticker-intro h2{ font-size:clamp(1.3rem,2.6vw,1.7rem); font-weight:800; letter-spacing:-.01em;
  line-height:1.3; margin:0 0 .5rem }
.ticker-intro p{ color:var(--muted); font-size:.98rem; line-height:1.5; margin:0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
@media(max-width:560px){ .ticker-intro p{ white-space:normal; font-size:.92rem } }

/* ---------- mission banner: one full-width, low-height AI-generated photo under the
   mission intro (task #788, replaces the two-figure .lifestyle-row from item 2/#784).
   Decorative only (aria-hidden, empty alt), no caption -- the trio cards below already
   carry the audience copy, so a scrim+caption here would just repeat that text.
   No max-width and no extra padding-inline (the #784 lesson): the banner fills the same
   content width as its neighbors, edges flush with .wrap's own padding, margin-block-end
   matching .trio-grid's lack of top spacing so the two do not collide.
   Licensing: site/assets/img/stock/credits.json (mission-bazaar-dusk, generated).

   Task #791: aspect-ratio 4/1 -> 8/1 (owner: "half its current rendered height"; doubling
   the width:height ratio halves the rendered height at the same width, same arithmetic
   already used for .trio-photo's 16/9 -> 32/9 halving below).

   Slow horizontal drift, CSS-only: the img is rendered oversized (132% of the box) and
   recentred with a static -16% inline-start margin, then nudged the rest of the way by a
   transform animation alone (never top/left/margin, so the browser can run it off the
   compositor). Total travel is +-6% of the img's own width (~7.9% of the box width),
   comfortably inside the 16%-per-side overflow the oversize leaves, so the drift never
   uncovers the box's edge. 38s ease-in-out infinite alternate reads as ambient rather than
   as an obvious loop point -- alternate reverses smoothly at each end instead of jump-
   cutting back to the start, so there is no seam to notice. Gated on
   prefers-reduced-motion:no-preference (same idiom as .tk-track above): a reduced-motion
   visitor gets the photo static at its centred position, no override needed. Decorative and
   non-interactive already (aria-hidden on the wrapper, no handlers); pointer-events:none on
   the img is belt-and-suspenders so the animation is never a click target.
   max-width:none is load-bearing: site.css's global reset (img{max-width:100%}) otherwise
   clamps this img's declared width:132% straight back down to 100%, which collapses the
   oversize and leaves the -16% margin pulling the frame off-centre with the panel2 ground
   showing on one side instead of drifting a full photo (caught by measuring the img's own
   getBoundingClientRect against the box in a real browser, not just reading the rule).

   Task #796 (owner brief): the mission kicker/h2/p move onto the banner as an overlay,
   so the plain heading above it is gone (this is the section's only heading now, no
   duplicate).

   First implementation used CSS Grid (img/.mission-scrim/.s-head all at grid-area:1/1) and
   was wrong twice over, both caught by rendering rather than by reading the rule:
   (1) a grid item's default min-size is auto (its own min-content), which wins over an
   explicit 1fr track, so the row grew to fit .s-head's full content height instead of the
   aspect-ratio height it was supposed to share -- .s-head measured 350px tall inside a
   144px .mission-banner, entirely clipped and invisible, on the very first render.
   (2) forcing every item to min-height:0 fixed that, but froze the box at exactly the
   aspect-ratio height with no way to grow, so the fix only worked at the widths it happened
   to be tested at: single-column phone copy needed more room than 8/1 gives across the WHOLE
   481-760px stacked range, not only under an arbitrarily chosen 480px, and separately the
   two-column desktop layout's own headline wrapped to two lines at 800px wide and lost its
   second line off the bottom of the box with nothing visible to say so. Chasing each width
   with its own breakpoint is exactly the failure mode this rewrite exists to stop: any other
   language (en/ar/kmr line lengths all differ) or any other width could reopen it.

   Final shape: img and .mission-scrim are position:absolute, inset to the box, so they never
   contribute to the box's own sizing at all; .s-head is the box's only normal-flow child.
   The tempting theory here -- that a block box with aspect-ratio and height:auto should grow
   past the ratio once in-flow content needs more room, the ratio acting as a floor rather
   than a ceiling -- reads as plausible CSS Sizing spec behavior and is NOT what Chromium
   does once .s-head is the only in-flow child: measured directly (getBoundingClientRect on
   both .mission-banner and .s-head, at a dense sweep from 340px to 2000px), the box stayed
   pinned to exactly width/8 at every single width, including the two this rewrite was meant
   to fix -- .s-head still measured 158px of real content in a 79px box at 700px, and 127px
   in a 90px box at 800px, both silently clipped by the overflow:hidden below, THE SAME
   symptom the grid version had. Restructuring which element is in-flow did not change the
   outcome; the assumption that aspect-ratio yields to content on a plain block box was
   simply wrong, so it is not the plan any more.
   What actually works, still measured rather than guessed: .s-head's real needed height was
   read off across ~30 widths (the sweep above), which is lumpy rather than smooth -- text
   reflow moves in whole-line jumps, so needed height can drop 30-40px between two widths
   just because one more word fit on a line -- and the WORST (tallest) requirement in each of
   four ranges became a min-height floor for that range, laid on top of the aspect-ratio the
   box already had: min-height always wins over a smaller aspect-ratio-derived height (that
   part of the box-sizing spec IS reliable), so the box uses whichever is taller, at every
   width, with no per-language or per-width guesswork left for copy this dictionary already
   ships in four languages. Above 1200px the measured need (max 147px) sits under the ratio's
   own height (135px at 1200px and rising with width), so no floor is needed there and the
   banner keeps its full-width 8/1 read; below it, floors step down as the ratio's own height
   climbs, so the override only adds the minimum each range actually needs:
     <=480px:  200px floor (measured need up to 191px)
     <=760px:  178px floor (measured need up to 164px)
     <=1199px: 160px floor (measured need up to 147px)
   Confirmed empirically after the floors were added: 700px (previously clipped the
   paragraph) and 800px (previously clipped the h2's second line) both show every line now,
   and the sweep was re-run in full (not spot-checked) to confirm no other width in the
   340-2000px range clips either. The floors are the current-copy answer, not a permanent
   guarantee: a longer future translation could still need re-measuring against them.

   DOM order is img / scrim / text, and each also carries an explicit z-index (0/1/2): DOM
   order alone was NOT enough on the grid version -- the img's own compositing layer (filter +
   will-change:transform) painted above the scrim and text regardless of source order, so the
   scrim measured correctly in computed style (right color, right rect) while every pixel
   sampled from an actual screenshot came back at the raw image's brightness, unscrimmed.
   Explicit z-index pins the order regardless of which children end up layer-promoted; kept
   here since the img is still filtered and the failure mode was real, not grid-specific.
   The img keeps its own filter:blur() *in addition to* the existing oversize: the
   brief calls for a real blur on the image, not backdrop-filter on the text (backdrop-filter
   would blur whatever is UNDER the text element, which is the scrim + image together and
   re-samples every frame of the drift animation under the filter -- a plain filter:blur()
   on the img is cheaper and the blurred pixels are baked into what the scrim then darkens).
   The existing 16%-per-side oversize already covers the blur's own edge softening: a blurred
   image needs its edges to sit further outside the visible box than the blur radius, or the
   corners read as thin unblurred fringes where a sharp source edge peeks through the soft
   one; 16% of the box width is ~10x the 8px blur radius chosen below, checked in the
   rendered screenshots at all three widths with no fringe at any drift extreme.
   .mission-scrim is flat rgba(6,13,16,.75). Measured, not guessed: a headless harness froze
   the drift animation at nine points from -6% to +6%, screenshotted the banner with the text
   hidden (visibility:hidden, so the sampled pixels are pure image+scrim, never a text glyph
   mistaken for background), and took the brightest pixel inside each of the kicker/h2/p
   boxes at every position. .64 (the first value tried) cleared h2 and the paragraph but the
   kicker and the h2's own gold .hl phrase (see the HL map in extras.js -- a shared headline
   highlight this page does not own or want to remove) both sit on gold text, and gold-on-
   this-photo's-sunset is a near-hue clash that eats contrast .64 could not make up: kicker
   measured 3.56:1 against the WCAG 4.5:1 a kicker-sized run of text needs, and the .hl gold
   3.69:1 (the h2's own -- non-gold -- text cleared 5.83:1 at .64 already). .75 was the first
   value in a step search (.64/.68/.72/.75/.78/.80/.82/.85/.88) whose worst measured ratio,
   across the same nine drift positions and both gold runs, cleared every one of the four
   text roles at its own real WCAG floor (4.5:1 for the kicker and paragraph as normal-size
   text, 3:1 for h2 and .hl as large bold text) with real margin, not by a hair: kicker
   4.68:1, .hl 4.98:1, h2 non-hl already well clear, paragraph 7.19:1. --text/--muted/--gold
   are re-declared locally on .mission-banner .s-head to fixed light values regardless of the
   site's light/dark toggle (html[data-theme="light"] flips --text to a near-black #12262c,
   which would fail contrast against this always-dark scrim): kept the dark theme's own
   --text (#eaf4f2) and --gold (#e0b64a unchanged, already light enough once the scrim carries
   the weight above), but --muted is bumped from the dark theme's own #8fb0ad to the brighter
   #cddedb before measuring at all: the dark theme's #8fb0ad is a greyish teal picked to sit
   quietly on a flat panel background, and the paragraph here is normal-size text (4.5:1
   required, not 3:1) on a photo rather than a flat fill, so it went in as the safer starting
   guess rather than as something that was measured and found wanting. It measured at 7.19:1
   worst case once the scrim above was tuned, comfortable margin above the 4.5:1 floor. */
.mission-banner{ position:relative; width:100%; margin:1.75rem 0 clamp(1.75rem,4vw,2.75rem);
  border-radius:16px; overflow:hidden; aspect-ratio:8/1; background:var(--panel2);
  display:flex; align-items:center }
/* width:100% is load-bearing, not a no-op default: a block box's width:auto normally just
   fills its container, but adding min-height (below) alongside aspect-ratio on a width:auto
   box made Chromium derive WIDTH from the forced min-height via the ratio instead (measured:
   min-height:200px produced a 1600px-wide box, exactly 200*8, shifted off-screen) rather than
   keeping the container's actual width and letting min-height only affect height as intended.
   An explicit width makes the inline axis definite on its own, so aspect-ratio has nothing
   left to solve for on that axis and min-height only ever affects height. */
.mission-banner img{ display:block; position:absolute; z-index:0;
  inset-block-start:0; inset-inline-start:-16%; width:132%; max-width:none; height:100%;
  object-fit:cover; pointer-events:none; will-change:transform;
  /* !important: every <img> on this site is auto-tagged data-ld by img-reveal.js and gets
     .js-img img[data-ld].ld-on{filter:blur(0)} once loaded, at specificity (0,3,1) versus
     this rule's (0,1,1) -- without !important the reveal system's own "now show it sharp"
     rule silently wins on load and this banner's permanent blur vanishes the moment the
     image finishes loading (caught by reading getComputedStyle().filter as blur(0px) despite
     this rule, then walking img.matches() against every stylesheet rule to find the winner).
     That reveal system's fade is still wanted here (opacity/transform untouched), just not
     its end-state sharpening: this rule needs to win at every point in that transition, not
     only initially, so blur(8px) is the image's fixed state throughout, never a transition. */
  filter:blur(8px) !important }
.mission-scrim{ position:absolute; z-index:1; inset:0;
  background:rgba(6,13,16,.75); pointer-events:none }
@media(prefers-reduced-motion:no-preference){
  .mission-banner img{ animation:kxmissiondrift 38s ease-in-out infinite alternate }
}
@keyframes kxmissiondrift{ from{ transform:translateX(-6%) } to{ transform:translateX(6%) } }
.mission-banner .s-head{ position:relative; z-index:2; flex:1 1 auto; min-width:0;
  /* margin:0 is load-bearing under align-items:center, not tidiness: site.css:415 puts
     margin-bottom:2rem on every .s-head and #who's own override (site.css:2707) resets
     max-width and margin-inline but not that. A flex item is centred by its MARGIN box, so
     the inherited 30px bottom margin silently pushed the whole title block 15px above the
     banner's true centre -- measured as a 15px asymmetry in the gaps above and below the
     text, which is exactly the "not centred" this task exists to fix. */
  margin:0;
  padding:clamp(.8rem,1.8vw,1.2rem) clamp(1.1rem,4vw,2.75rem);
  --text:#eaf4f2; --muted:#cddedb; --gold:#e0b64a }
.mission-banner .s-head .kicker{ font-size:.84rem }
.mission-banner .s-head h2{ font-size:clamp(1.15rem,2.9vw,1.95rem) }
.mission-banner .s-head p{ font-size:clamp(.86rem,1.5vw,1.05rem); line-height:1.55 }
/* min-height floors: see the measurement note above .mission-banner. Ordered widest-first so
   the cascade lets the narrowest matching range win (a <=480px viewport matches all three
   max-width queries; the last one in source order, 206px, is the one that applies). The
   min-width:1200px range is new in #801/#802 and is the direct cost of the bigger type: the
   re-run sweep (84 widths from 340 to 2000, x ckb/en/ar/kmr, 336 measurements) found the
   only clipping band at 1200-1260px in ckb, where the 8/1 box is 135-142px and the taller
   headline needs 143.5px, so the ratio alone no longer covers the whole desktop range. Above
   ~1330px the ratio's own height passes the floor again and the banner keeps its full 8/1
   read. Every floor is set ~7-9px above the worst measured need in its range rather than at
   it: #796's 178px floor sat 0.5px above the 178.5px this copy now needs, which is inside
   sub-pixel rounding and is not a margin. Re-measure these if the copy or a translation
   changes; they are the current-copy answer, not a guarantee. */
@media(min-width:1200px){ .mission-banner{ min-height:152px } }
@media(max-width:1199px){ .mission-banner{ min-height:164px } }
@media(max-width:760px){ .mission-banner{ min-height:186px } }
@media(max-width:480px){ .mission-banner{ min-height:206px } }
@media(max-width:640px){
  .mission-banner{ margin:1.4rem 0 1.75rem; border-radius:12px }
}
@media(max-width:480px){
  .mission-banner .s-head h2{ font-size:clamp(1.12rem,4.9vw,1.45rem) }
}

/* ---------- ticker of real listings ---------- */
.ticker{
  /* A third of .ticker-intro's --tki-rhythm, deliberately: the heading and its strip are one
     group, and the gap inside a group must be visibly smaller than the gap that separates it
     from the section above. Was clamp(2.4rem,5vw,3.6rem), which was larger than the space
     above the heading and therefore split the group in half. */
  margin-block-start:clamp(1.13rem,2.2vw,1.8rem);
  /* Full-bleed (owner request 2026-07-30): escape the padded .wrap and run edge to
     edge. body carries overflow-x:hidden, so the 50vw arithmetic cannot add a
     horizontal scrollbar. */
  width:100vw;
  margin-inline:calc(50% - 50vw);
  background:var(--panel);
  padding-block:12px;
  overflow:hidden;
  -webkit-mask-image:linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
  mask-image:linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
}
.tk-track{ display:flex; align-items:center; width:max-content }
@media (prefers-reduced-motion:no-preference){
  .tk-track{ animation:kxtk 60s linear infinite }
  [dir="rtl"] .tk-track{ animation-name:kxtkR }}
@keyframes kxtk{ to{ transform:translateX(-50%) } }
@keyframes kxtkR{ to{ transform:translateX(50%) } }
.tk{ display:inline-flex; align-items:baseline; gap:8px; flex:none; margin-inline-end:clamp(26px,4vw,44px) }
.tk::before{
  content:""; align-self:center; flex:none;
  width:5px; height:5px; border-radius:50%;
  background:var(--gold); opacity:.75;
}
.tk b{ font-weight:700; font-size:.9rem; color:var(--text) }
.tk i{ font-style:normal; font-size:.78rem; color:var(--muted) }

/* ---------- Kurdistan photo bands ---------- */
.kband{
  position:relative;
  height:70vh; min-height:400px;
  overflow:clip;
}
.kband img{
  position:absolute; left:0; top:-13%;
  width:100%; height:126%;
  object-fit:cover;
  will-change:transform;
}
.kband-scrim{
  position:absolute; inset:0;
  background:
    radial-gradient(120% 90% at 50% 42%, transparent 52%, rgba(8,14,17,.5)),
    linear-gradient(to bottom,
      var(--bg) 0%, rgba(8,14,17,.06) 30%,
      rgba(8,14,17,.34) 68%, var(--bg) 100%);
}
.kband-cap{
  position:absolute; inset-inline:0; bottom:13%;
  padding-inline:clamp(20px,5vw,48px);
  text-align:center;
}
.kband-line::before{
  content:""; display:block;
  width:46px; height:2px; border-radius:2px;
  margin:0 auto 16px;
  background:var(--gold);
  box-shadow:0 0 14px rgba(224,182,74,.8);
}
.kband-line{
  margin:0;
  text-align:center;
  font-weight:800;
  font-size:clamp(1.9rem, 6vw, 3.6rem);
  line-height:1.15;
  color:#f6fbf9;
  text-shadow:0 4px 44px rgba(0,0,0,.72), 0 1px 10px rgba(0,0,0,.55);
  text-wrap:balance;
  opacity:0; transform:translateY(40px);
  transition:opacity 1s cubic-bezier(.16,1,.3,1), transform 1s cubic-bezier(.16,1,.3,1);
}
.kband.kb-in .kband-line{ opacity:1; transform:none }
.kband-sub{
  max-width:40rem; margin:.9rem auto 0;
  color:rgba(246,251,249,.86);
  font-size:clamp(.95rem, 2.4vw, 1.2rem);
  line-height:1.55; font-weight:500;
  text-shadow:0 2px 22px rgba(0,0,0,.66);
  text-wrap:pretty;
  opacity:0; transform:translateY(22px);
  transition:opacity 1s cubic-bezier(.16,1,.3,1) .14s, transform 1s cubic-bezier(.16,1,.3,1) .14s;
}
.kband.kb-in .kband-sub{ opacity:1; transform:none }
.kband-credit{
  position:absolute; bottom:12px; inset-inline-end:14px;
  font-size:.66rem; letter-spacing:.02em;
  color:rgba(234,244,242,.75);
  background:rgba(11,20,24,.52);
  padding:4px 11px; border-radius:100px;
}
@media (prefers-reduced-motion:reduce){
  .kband-line{ opacity:1; transform:none; transition:none }
  .kband-sub{ opacity:1; transform:none; transition:none }
  .kband img{ transform:none !important }}

/* ---------- feature cards: icon beside the title, no floating gap ----------
   The old layout parked the icon at the top corner with dead space beneath
   it on short cards; this keeps every card compact and visually equal. */
.grid .fcard{ display:grid; grid-template-columns:auto 1fr; gap:2px 14px; align-content:start; height:auto }
.grid .fcard .f-ic{ grid-row:span 2; margin-bottom:0; align-self:start }
.grid .fcard h3{ margin:0; align-self:center }
.grid .fcard p{ grid-column:2; margin:0 }
/* Mocks (countdown, ladder, mini-cards, bars) sit on their own full-width row below the
   icon+text, pushed to the card bottom, so they never land in the narrow icon column and
   squeeze the copy. */
.grid .fcard .f-mock{ grid-column:1 / -1; margin-top:auto; padding-top:1.1rem }

/* free callout used in the merged platform and rewards sections */
.kx-free{
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  margin:1.1rem auto 1.1rem; max-width:min(92%,60ch); width:fit-content;
  padding:.55rem 1.05rem; border-radius:100px;
  /* Round 2026-08-20 item 9: no outline. The tinted ground already separates the pill from
     the page, and the ring was the only hard edge left in a section of soft panels. Lifted
     the fill one step so removing the ring does not also remove the pill. */
  background:color-mix(in srgb,var(--green) 13%,transparent);
  border:0;
  color:var(--green); font-weight:700; font-size:.9rem; line-height:1.45;
  text-wrap:balance; text-align:center;
}
.kx-free svg{ width:16px; height:16px; flex:none }

/* Platform-features hero on a phone, owner request 2026-08-06 ("completely fixed for mobile,
   better styling and alignment").
   What was wrong at 375px: the heading sat at 2.1rem and broke into three ragged lines, and the
   free-pill centred two lines of text against a check icon pinned to the middle of the block, so
   the tick floated beside the gap between lines instead of reading with the first word.
   Scoped to #platform and to the pill, so the hero at the top of the page keeps its own scale.
   Uses the id for specificity: this file loads after site.css, but relying on order alone is how
   the level ladder silently kept its desktop size earlier today. */
@media(max-width:560px){
  #platform .hero-h1{font-size:1.75rem;line-height:1.22;margin:.8rem 0 .7rem}
  #platform .hero-lead{font-size:.92rem;line-height:1.62;max-width:34ch;margin-inline:auto}
  #platform .hero-cta{margin-top:1.15rem}
  #platform .hero-cta .btn{width:100%;justify-content:center}
  /* Icon to the top line, not the vertical centre, and a touch less air so the pill reads as one
     object rather than a paragraph in a box. */
  .kx-free{align-items:flex-start;gap:7px;padding:.5rem .85rem;font-size:.82rem;line-height:1.5;
    margin-top:.9rem;max-width:min(96%,38ch);text-align:start}
  .kx-free svg{width:14px;height:14px;margin-top:.2rem}}

/* Round 2026-08-22, changes 1 & 5: a tighter pill at true phone widths (390px). Covers both
   uses of .kx-free (the #platform hero pill and the #rewards points pill) since neither is
   scoped by id. align-items:flex-start and a 10px gap stop the check icon drifting to the
   vertical centre once the two-line copy wraps. width:fit-content + margin-inline:auto keep
   the pill hugging its balanced lines and centered in the section: a block-level flex here
   otherwise fills the 38ch cap edge to edge with start-aligned text, which reads as a broken
   left slab between a centered heading and a centered paragraph. */
@media(max-width:480px){
  .kx-free{display:flex;width:fit-content;max-width:96%;margin-inline:auto;
    align-items:flex-start;gap:10px;font-size:clamp(13px,3.6vw,15px);
    padding:10px 16px;line-height:1.35;text-wrap:balance}
  /* Owner request 2026-08-22: ONE line on phones. The full sentence cannot fit 390px at a
     legible size, so the pill keeps only the claim ("All of this is 100% free") and hides
     the enumeration; the checklists directly under both pills restate every item it names.
     The colon lives in the static .kx-sep span, not the dictionary, so hiding the tail
     never strands trailing punctuation in any language. */
  .kx-free{align-items:center;gap:8px;font-size:13px;padding:8px 14px}
  .kx-free svg{margin-top:0}
  .kx-free .kx-sep,.kx-free [data-kx="free.l2"]{display:none}
}

/* ============================================================
   MEGA LANDING SECTIONS (2026-07-11)
   ============================================================ */

.visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* shared coming-soon badge (PLAN 3.4) */
.soon-badge{display:inline-block;padding:.15em .55em;border-radius:999px;
background:color-mix(in srgb,var(--gold) 16%,transparent);color:var(--goldtext,#e0b64a);font-size:.72em;font-weight:700;
letter-spacing:.03em;vertical-align:middle;white-space:nowrap}

/* ---------- audience trio router ---------- */
/* Three paths (people, businesses, investors), each carrying a real feature list rather
   than one sentence. The creators card was removed on 2026-08-08 (owner request); creators
   still reach for-users.html#creators from four other links on this page. Three across only
   where a column can still hold a readable line; one column below that, because two columns
   over three cards leaves a half-width orphan on the second row. */
.trio-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:16px }
/* 980, not the old 720: with four cards the middle range fell back to a 2x2, so a third
   column only had to survive down to 720. Three columns hold their own width all the way
   down now, and below ~980 a card is too narrow to carry its six-line feature list. */
@media (max-width:980px){ .trio-grid{ grid-template-columns:1fr }}
/* What each audience actually gets. Ticks are the same green the comparison table uses. */
.trio-list{ list-style:none; margin:.35rem 0 .2rem; padding:0; display:flex; flex-direction:column; gap:.5rem }
.trio-list li{ display:flex; align-items:flex-start; gap:.55rem; font-size:.86rem; line-height:1.5;
  color:var(--muted); text-wrap:pretty }
.trio-list svg{ width:14px; height:14px; flex:none; margin-top:.28rem;
  color:color-mix(in srgb,var(--accent) 75%,var(--green)) }
/* Queue #492 looked at this rule and left it alone. "Coming soon" measured 3.94:1 light
   against a declared #7a5804 (--gold2) that computes to 5.71:1 on the same background, so it
   was tried as var(--goldtext) (6.78:1 declared, same family as the three gold-as-text fixes
   in site.css/index.html) and re-measured: the sampled ink was byte-identical, #90732d, either
   way. The colour is provably not what the sampler is reading, which makes this the same shape
   as the 'Slemani' case this task's own findings list carved out (declared clears, an 8.1px
   text anti-aliasing artifact does not) -- reverted rather than kept as a no-op diff. */
.trio-soon{ font-style:normal; font-size:.6rem; font-weight:800; letter-spacing:.05em;
  text-transform:uppercase; color:var(--gold2); white-space:nowrap;
  background:color-mix(in srgb,var(--gold) 13%,transparent); border-radius:100px;
  padding:.1rem .45rem; margin-inline-start:.4rem; align-self:center }
/* The link sits on the floor of the card, so four cards of different lengths still line up. */
.trio-card .trio-go,.trio-card .trio-links{ margin-top:auto; padding-top:.9rem }
.trio-card{
  --accent:var(--gold);
  position:relative; display:flex; flex-direction:column; gap:.6rem;
  /* More room above the mark (owner request 2026-08-03): the icon used to start 1.7rem from
     the top edge, directly under the accent bar, which made the card feel like it began
     mid-thought. */
  padding:2.5rem 1.6rem 1.5rem; border-radius:20px;
  background:
    radial-gradient(120% 80% at 50% -10%, color-mix(in srgb,var(--accent) 9%,transparent), transparent 60%),
    var(--panel);
  /* The resting border was removed on 2026-08-12 (owner request): the card now sits on its
     background tint alone. Transparent rather than none so the box does not shift 1px and the
     hover accent outline below still has a border to colour. */
  border:0;
  /* A hairline of light along the top edge instead of the 3px coloured bar that used to sit
     there. It still separates the card from the page and still carries the accent, but as
     lighting rather than as a stripe, which is the difference between a card and a tab. */
  box-shadow:none;
  color:var(--text); text-decoration:none; overflow:hidden;
  transition:transform .28s cubic-bezier(.22,1,.36,1), border-color .28s ease, box-shadow .28s ease;
}
/* per-card accent, driven by the card's own data-accent rather than its index, so the
   order can change without the colours shuffling */
.trio-card[data-accent=green]{ --accent:var(--green) }
/* soft glow that rises on hover */
.trio-card::before{
  content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background:radial-gradient(70% 55% at 50% 120%, color-mix(in srgb,var(--accent) 22%,transparent), transparent 70%);
  opacity:0; transition:opacity .3s ease;
}
/* #827, 2026-09-06: the second `.trio-card:hover` block that used to sit here
   (`translateY(-4px)` + `0 18px 44px -20px rgba(0,0,0,.75)`, the #822 repair) is DELETED, not
   commented out. It never painted. Asked the engine rather than read the file:
   CSS.getMatchedStylesForNode on a card with :hover FORCED through CDP, all 3 cards, dist/ on
   :4700 at 1400px, reduced-motion emulated as no-preference (headless Chromium answers
   `reduce` by default, which silently hands back `transform:none` from the block at :659 and
   reads exactly like a dead rule).
     box-shadow  won by index.html `<style id="card-light">`, a LATER sheet than this one:
                 `0 18px 40px -22px rgba(0,0,0,.7), 0 0 30px -14px gold 45%`. Measured 3 of 3.
                 So the surviving block at :1292 does not paint its shadow either; only the
                 gold-halo list does.
     transform   won by NEITHER. `html.js-motion .rv-stagger.rv-in > *{transform:none}`
                 (site.css:1650) is (0,3,1) against `.trio-card:hover` at (0,2,0), so once the
                 reveal finishes the lift is pinned off. Filed separately; do not "fix" it by
                 adding !important here.
   The `0 0 0 1px` accent stop from the old block is NOT restored - a 1px spread ring is a
   border, named by the law (only 3px and up is a halo). */
.trio-card:hover::before{ opacity:1 }
/* The 3px accent bar across the top was removed on 2026-08-03 at the owner's request. It made
   four cards in a row read as four browser tabs, and it fought the icon underneath it for the
   first look. The accent survives in the card's own tint, the icon, the hover glow and the
   inset highlight, so nothing about which card is which was lost with it. */
/* Owner request 2026-07-31: the columns read centred and the mark carries the card. The tile
   doubles and the glyph inside it roughly triples, so the icon is the first thing the eye
   lands on instead of a small chip above the heading. */
.trio-ic{ width:104px; height:104px; display:grid; place-items:center; border-radius:26px;
  background:color-mix(in srgb,var(--accent) 15%,transparent); color:var(--accent);
  box-shadow:none;
  transition:transform .28s cubic-bezier(.22,1,.36,1) }
.trio-card:hover .trio-ic{ transform:scale(1.08) rotate(-3deg) }
.trio-ic svg{ width:76px; height:76px; stroke-width:1.5 }
.trio-card h3{ margin:.15rem 0 0; font-size:1.18rem; letter-spacing:-.01em }
.trio-card p{ margin:0; color:var(--muted); font-size:.93rem; line-height:1.6; flex:0 0 auto }
/* Centred columns. The feature list keeps its start-aligned ticks (a centred checklist has no
   common edge to scan down), but the list block itself is centred inside the card, so the card
   still reads as one axis. */
.trio-card{ align-items:center; text-align:center }
.trio-card .trio-list{ text-align:start; align-self:center }
.trio-card .trio-links{ justify-content:center }
.trio-go{ display:inline-flex; align-items:center; gap:7px; font-weight:700; font-size:.9rem; color:var(--accent); min-height:44px }
.trio-go svg{ width:16px; height:16px; transition:transform .2s ease }
[dir="ltr"] .trio-go svg{ transform:scaleX(-1) }
.trio-card:hover .trio-arrow{ transform:translateX(-4px) }
[dir="ltr"] .trio-card:hover .trio-arrow{ transform:scaleX(-1) translateX(4px) }
.trio-go + .trio-go{ margin-top:-14px }
/* Two links in the same card (investors/sponsors) were reading as one crammed row: block
   default flow with only a text-node space between them. Give them a real flex gap and undo
   the single-link negative margin hack, which doesn't apply here. */
.trio-links{ display:flex; flex-wrap:wrap; gap:10px 26px; margin-top:.9rem }
.trio-links .trio-go + .trio-go{ margin-top:0 }
@media (prefers-reduced-motion:reduce){ .trio-card,.trio-ic,.trio-arrow{ transition:none } .trio-card:hover{ transform:none }}

/* ---------- trio card photo banners (task #786): a photo banner on each of the three
   audience cards, the same photographic language as .mission-banner above this grid --
   borderless, object-fit:cover, no caption. The card already carries a heading right under
   the photo, so a caption scrim here would just repeat that text. .trio-card already sets
   overflow:hidden at its own 20px border-radius (see :404), so this needs no radius of its
   own -- the card's own clip rounds it for free, and stays correct if that radius ever moves.
   The negative margin bleeds the photo to the card's actual edges: -2.4rem/-1.45rem/1.35rem
   is .trio-card's own padding, set once at :1044 (the rule that wins the cascade at every
   width, including the <=560px grid layout below, which does not touch padding), so one
   value is correct everywhere instead of one per breakpoint. Logical properties throughout,
   so this reads correctly in both the default RTL and ?lang=en LTR without a direction fork.
   Licensing: site/assets/img/stock/credits.json (trio-people, trio-business, trio-investors-v3).
   aspect-ratio:32/9 (task #788): half the rendered height of the original 16/9 banner --
   32/9 is exactly double 16/9's width:height ratio, so at the same rendered width the box
   is half as tall. Halving a 16/9 box under object-fit:cover would have sliced the old
   940x627 photos badly, so the three source files were re-cut to this aspect instead
   (trio-people/trio-business re-cropped from their originals with a deliberately chosen
   band, not a blind center crop; trio-investors-v2 generated at this aspect directly),
   and this rule only needs the new ratio, no further per-image adjustment.
   Task #791: all three source files re-cut again. The #788 bands put the people photo's
   afro flush against the crop's top edge (no headroom, read as clipped) and the business
   photo's baker close enough to the same edge to read the same way on a wide viewport, and
   trio-investors-v2 (generated at 21:9 with the skyline confined to a thin strip at the
   very bottom, then cropped to 32:9) came out as mostly empty sky with the skyline reduced
   to a sliver. trio-people/trio-business are re-cropped from the same two 940x627 originals
   at new bands that centre each subject with real headroom (see credits.json for the exact
   y-offsets); trio-investors-v2 is regenerated at 16:9 with a prompt asking for buildings
   filling most of the frame instead of a thin band, then cropped to 32:9 from a region that
   keeps the skyline's mass in the shot rather than a bottom sliver. Every source file's own
   aspect is close enough to 32:9 already (see credits.json byte/px notes) that object-fit's
   own crop is negligible, so no per-image object-position was needed on top of the recrop.
   Task #794: aspect-ratio taken from 32/9 (3.56:1) to 2.8/1 -- the owner's screenshot showed
   the 32/9 crop reading as too shallow a strip, and the #791 people/business bands, viewed at
   the actual rendered card width rather than at 940px, put both shoppers' heads close to the
   frame's top edge with the pair pushed into the right half and a dead gap of clothing rack on
   the left. All three sources are re-cut again, this time to 2.8:1 directly (no leftover
   object-fit crop to reason about, same as #791's approach): trio-people is re-cropped from
   the 940x627 original to a narrower 760x271 window (x180-940, y105-376) that recentres the
   pair's faces in the frame instead of using the full 940 width, which is what was pushing
   them right; trio-business is re-cropped from the same original to the full 940x336
   (y10-346), taller than #791's 264 so more of the oven's fire and the loaf-by-loaf reach
   is in frame, without needing to move off full width since the oven opening already spans
   nearly the whole photo. trio-investors-v3 replaces the cranes-at-dusk silhouette entirely
   (see credits.json for the three generated concepts and why the tower-construction one won)
   with a Replicate flux-schnell generation cropped 940x336 from a 1344x768 16:9 source.
   Task #801: 2.8/1 -> 2.2/1, and all three sources re-cut a fourth time. The owner's
   screenshot at ~2000px showed the 2.8/1 band still reading as a crop rather than a photo:
   the baker's head sat against the top edge with the counter and loaves he is working sliced
   off at the bottom, and BOTH shoppers' faces were cut through the chin by the bottom edge
   (the #794 band's 271px window simply did not reach far enough down for the chins at the
   rendered card width, which is the same class of mistake #794 made in the other direction).
   The ratio was picked by rendering candidate crops at the real card width (501px at a 2000px
   viewport, 373px at 1280px) and looking, not from arithmetic: 2.0/1 left the business photo
   with dead counter at the bottom and forced the investor crop down to 672px of usable source
   width, 2.2/1 was the shallowest ratio at which every subject cleared every edge.
   The two Pexels photos were re-fetched at 1880x1253 (2x the 940x627 the earlier rounds cut
   from, which is no longer on disk) so the new bands are cut from real pixels rather than
   upscaled: trio-people is (150,260)-(1880,1046) of that 1880x1253, a 1730x786 window that
   leaves ~110px of shelf above the taller woman's crown and puts both chins near the frame's
   own middle with the shoulders and the hand on the rail still in shot, resized to 1100x500;
   trio-business is (170,20)-(1880,797), a 1710x777 window that drops 170px of the plain brick
   the owner flagged from the left (which also recentres the baker, since his reaching arm
   already pushed the subject's mass right of the photo's centre), keeps every one of the 125px
   of brick the source has above his head, and reaches down past the full row of loaves and the
   dough on the counter instead of slicing them, resized to 1100x500.
   trio-investors-v3 is the one image with no larger source left (the 1344x768 generation was
   not kept and the Replicate token no longer authenticates, so it cannot be re-fetched or
   regenerated), so it is re-cut horizontally from the shipped 940x336 file to (80,0)-(819,336),
   739x336, at its native resolution with NO upscale: that window keeps the whole tower and
   crane group with the crane jibs clear of the top edge and the golden sunburst low in frame,
   and drops only the far-right sliver of building the 940 crop was already cutting. It ships
   smaller than the other two on purpose; inventing pixels to match their width would be worse
   than a slightly softer decorative photo at 2x DPR. */
.trio-photo{ display:block; position:relative; overflow:hidden; aspect-ratio:2.2/1;
  background:var(--panel2);
  margin-block:-2.4rem 1.1rem; margin-inline:-1.45rem }
.trio-photo img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover }

/* ---------- live prices strip ---------- */
.px-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:14px }
@media (max-width:960px){ .px-grid{ grid-template-columns:repeat(2,1fr) }}
@media (max-width:560px){ .px-grid{ grid-template-columns:1fr }}
.px-card{
  display:flex; flex-direction:column; gap:.4rem;
  padding:1.15rem 1.2rem; border-radius:16px;
  background:var(--panel);
  min-width:0;
}
.px-top{ display:flex; align-items:center; gap:10px }
.px-ic{ width:36px; height:36px; flex:none; display:grid; place-items:center; border-radius:10px;
  background:rgba(224,182,74,.13); color:var(--gold) }
.px-ic svg{ width:19px; height:19px }
.px-name{ font-weight:800; font-size:.98rem }
.px-tag{ margin-inline-start:auto; flex:none }
.px-live{ display:inline-flex; align-items:center; gap:6px; font-size:.72rem; font-weight:700; color:var(--green) }
.px-live::before{ content:""; width:7px; height:7px; border-radius:50%; background:var(--green);
  box-shadow:0 0 8px rgba(47,191,135,.9); animation:pxPulse 1.8s ease-in-out infinite }
@keyframes pxPulse{ 50%{ opacity:.35 } }
.px-val{ font-size:1.5rem; font-weight:800; line-height:1.2; letter-spacing:-.01em; min-height:1.9rem }
.px-val .px-skel{
  display:inline-block; width:96px; height:1.15em; border-radius:7px; vertical-align:middle;
  background:linear-gradient(90deg, var(--line) 25%, var(--line2) 50%, var(--line) 75%);
  background-size:200% 100%; animation:pxSkel 1.2s linear infinite;
}
@keyframes pxSkel{ to{ background-position:-200% 0 } }
.px-err{ font-size:.9rem; font-weight:600; color:var(--muted) }
.px-sub{ margin:0; font-size:.82rem; color:var(--muted) }
.px-sample .px-val{ opacity:.75 }
@media (prefers-reduced-motion:reduce){ .px-live::before,.px-val .px-skel{ animation:none }}

/* ---------- Kurdify Credit ---------- */
/* Section gets its own soft glow band (matches .gp-band's treatment elsewhere) so the
   heading sits on something instead of the flat page background, and its own top
   breathing room independent of the divider above it. */
#credit{
  position:relative; border-radius:24px; padding-top:.6rem; padding-bottom:.6rem;
  background:
    radial-gradient(65% 100% at 50% 0%, color-mix(in oklab,var(--gold) 7%,transparent), transparent 65%);
}
#credit .s-head{ padding-top:.4rem }
/* Kurdify Credit steps: a value-flow rail. The numbered nodes are stations on an
   animated gold->green line that carries value earn -> convert -> spend. */
/* The column count follows the number of steps instead of being hardcoded. This rule was
   written for investors.html, which has three, but it also lands on for-users.html, which has
   four, and site.css:2064 already said repeat(4,1fr) for exactly that page. extras.css loads
   second, so the 3-column rule won and the fourth step dropped to a second row on its own. */
.cr-steps{ position:relative; display:grid; grid-template-columns:repeat(3,1fr); gap:22px; counter-reset:crs }
.cr-steps:has(> .cr-step:nth-child(4)){ grid-template-columns:repeat(4,1fr); gap:16px }
/* Four narrow cards do not survive a tablet, so they pair off before they stack. Three-step
   boards keep their original single-column fallback. */
@media (max-width:1040px){ .cr-steps:has(> .cr-step:nth-child(4)){ grid-template-columns:repeat(2,1fr) }}
@media (max-width:860px){ .cr-steps{ grid-template-columns:1fr; gap:16px }}
@media (max-width:600px){ .cr-steps:has(> .cr-step:nth-child(4)){ grid-template-columns:1fr; gap:14px }}
.cr-step{
  position:relative; overflow:hidden; padding:1.75rem 1.5rem 1.6rem; border-radius:18px;
  background:linear-gradient(180deg, color-mix(in oklab,var(--panel) 55%,var(--panel2)), var(--panel));
  box-shadow:none;
  transition:transform .25s cubic-bezier(.22,1,.36,1), border-color .25s, box-shadow .25s;
}
/* top accent bar: gold -> gold/green blend -> green across the 3-step earn/convert/spend
   flow, so the narrative reads at a glance before anyone reads the copy */
.cr-step::after{ content:""; position:absolute; inset-inline:0; top:0; height:3px;
  background:linear-gradient(90deg,var(--gold),var(--gold)) }
.cr-step:nth-child(2)::after{ background:linear-gradient(90deg,var(--gold),var(--green)) }
.cr-step:nth-child(3)::after{ background:linear-gradient(90deg,var(--green),var(--green)) }
/* soft corner glow, same device other premium cards on the site use */
.cr-step .cr-glow{ position:absolute; inset-inline-end:-60px; top:-60px; width:150px; height:150px;
  border-radius:50%; background:radial-gradient(circle,color-mix(in oklab,var(--gold) 20%,transparent),transparent 70%);
  opacity:0; transition:opacity .3s; pointer-events:none; z-index:0 }
.cr-step:hover .cr-glow{ opacity:.9 }
.cr-step:hover{transform:translateY(-4px);box-shadow:0 20px 40px -26px color-mix(in oklab,var(--gold) 65%,transparent);}
@media(prefers-reduced-motion:reduce){ .cr-step:hover{ transform:none }}
/* numbered node — a station with a soft halo ring */
/* Two badges were rendering on every for-users step: this CSS counter, and the .n div that
   site.css styles. investors.html has no .n and depends on the counter, so neither rule can
   just be deleted. The card that ships its own numbered badge suppresses the counter, and the
   .n below inherits this badge's look, so both pages show one badge and for-users keeps the
   Arabic-Indic numeral its markup carries (counter() cannot localize). */
.cr-step:has(> .n)::before{ display:none }
.cr-step::before{
  counter-increment:crs; content:counter(crs);
  position:relative; z-index:2;
  display:grid; place-items:center; width:40px; height:40px; margin-bottom:.85rem;
  border-radius:50%; font-weight:800; font-size:1.05rem; color:var(--goldink,#231a05);
  background:linear-gradient(145deg,var(--gold2),var(--gold));
  border:0;
  box-shadow:0 0 0 5px color-mix(in oklab,var(--gold) 12%,transparent),
             0 6px 15px -6px color-mix(in oklab,var(--gold) 72%,transparent),
             0 1px 0 color-mix(in oklab,#fff 42%,transparent) inset;
}
/* The surviving badge wears the counter's treatment, so suppressing the duplicate above costs
   the page nothing visually. site.css:2068 drew this as a 38px rounded square in flat 13% gold;
   the two sat stacked and read as a rendering fault rather than a style. */
.cr-step > .n{
  position:relative; z-index:2;
  display:grid; place-items:center; width:40px; height:40px; margin:0 0 .85rem;
  border-radius:50%; font-weight:800; font-size:1.05rem; color:var(--goldink,#231a05);
  background:linear-gradient(145deg,var(--gold2),var(--gold));
  border:0;
  box-shadow:0 0 0 5px color-mix(in oklab,var(--gold) 12%,transparent),
             0 6px 15px -6px color-mix(in oklab,var(--gold) 72%,transparent),
             0 1px 0 color-mix(in oklab,#fff 42%,transparent) inset;
}
/* per-step glyph (earn / convert / spend) in the top corner */
.cr-glyph{ position:absolute; top:1.5rem; inset-inline-end:1.35rem; z-index:2;
  width:30px; height:30px; display:grid; place-items:center; border-radius:9px;
  color:color-mix(in oklab,var(--gold2) 78%,var(--text));
  background:color-mix(in oklab,var(--gold) 8%,transparent)}
.cr-glyph svg{ width:16px; height:16px }
/* the value-flow rail: line + chevron + a spark that travels toward the next step */
/* The connectors are children of .cr-steps, NOT of .cr-step. Each card is overflow:hidden (it
   has to be: it clips the corner glow and the rounded top accent bar), so a connector living
   inside a card and positioned past its right edge was clipped to a 1px stub in the gap. Anchored
   to the grid instead, each one spans a real column gap. Absolutely positioned children of a grid
   container are not grid items, so they do not disturb the 3-column layout.
   Geometry: 3 equal columns with two 22px gaps, so a column is (100% - 44px)/3. Gap centres are
   one and two columns in, plus the gaps already crossed. inset-inline-start keeps RTL correct. */
.cr-flow{ display:none }
@media (min-width:861px){
  .cr-flow{ display:block; position:absolute; z-index:3; pointer-events:none;
    top:calc(1.75rem + 20px);
    width:24px; height:12px; transform:translateY(-50%) }
  .cr-flow:nth-of-type(1){ inset-inline-start:calc((100% - 44px)/3 + 11px - 12px) }
  .cr-flow:nth-of-type(2){ inset-inline-start:calc((100% - 44px)/3*2 + 33px - 12px) }
  .cr-flow::before{ content:""; position:absolute; top:50%; inset-inline-start:0; width:100%; height:2px; border-radius:2px; transform:translateY(-50%);
    background:
      radial-gradient(circle at 0 50%, color-mix(in oklab,#fff 92%,var(--gold2)) 0, transparent 2.2px),
      linear-gradient(90deg, color-mix(in oklab,var(--gold) 75%,transparent), color-mix(in oklab,var(--green) 55%,transparent));
    background-size:9px 100%, 100% 100%; background-repeat:no-repeat; background-position:-9px 0, 0 0;
    box-shadow:0 0 7px color-mix(in oklab,var(--gold) 40%,transparent) }
  .cr-flow::after{ content:""; position:absolute; top:50%; inset-inline-end:-1px; width:6px; height:6px; transform:translateY(-50%) rotate(45deg);
    border-top:0; border-inline-end:0 }}
@media (min-width:861px) and (prefers-reduced-motion:no-preference){
  .cr-flow::before{ animation:crFlow 1.7s linear infinite }
  [dir="rtl"] .cr-flow::before{ animation-name:crFlowRtl }}
@keyframes crFlow{ to{ background-position:26px 0, 0 0 } }
@keyframes crFlowRtl{ to{ background-position:-26px 0, 0 0 } }
.cr-step h3{ margin:0 0 .35rem; font-size:1.05rem }
.cr-step p{ margin:0; color:var(--muted); font-size:.9rem }
/* spend row: an eyebrow + reward pills with leading icons, sitting in its own panel
   so it reads as one grouped "spend menu" rather than loose chips on bare background */
.cr-spend{
  display:flex; flex-wrap:wrap; gap:9px; justify-content:center; align-items:center;
  margin-top:1.6rem; padding:1.1rem 1.2rem;
  border-radius:16px;
  background:color-mix(in oklab,var(--panel) 55%,transparent);
}
.cr-spend-on{ width:100%; text-align:center; margin-bottom:.3rem;
  font-size:.68rem; font-weight:800; letter-spacing:.09em; text-transform:uppercase; color:var(--muted) }
.cr-spend .pill{ padding:.42rem .85rem; font-size:.76rem; transition:transform .18s cubic-bezier(.22,1,.36,1), border-color .18s }
.cr-spend .pill svg{ width:14px; height:14px }
.cr-spend .pill.gold{ box-shadow:0 8px 18px -10px color-mix(in oklab,var(--gold) 70%,transparent) }
.cr-spend .pill.muted{ background:color-mix(in oklab,var(--text) 5%,var(--panel))}
.cr-spend .pill.muted svg{ color:var(--gold2) }
.cr-spend .pill:hover{transform:translateY(-2px);}
@media(prefers-reduced-motion:reduce){ .cr-spend .pill:hover{ transform:none }}
.cr-facts{ display:grid; grid-template-columns:repeat(2,1fr); gap:14px; margin-top:1.4rem }
@media (max-width:720px){ .cr-facts{ grid-template-columns:1fr }}
/* premium feature tiles inside the credit section */
.cr-facts .fcard{ background:linear-gradient(180deg, color-mix(in oklab,var(--panel) 62%,var(--panel2)), var(--panel)) }
.cr-facts .f-ic{
  width:52px; height:52px; border-radius:15px;
  background:linear-gradient(145deg, color-mix(in oklab,var(--gold) 20%,transparent), color-mix(in oklab,var(--green) 10%,transparent));
  border:0;
  box-shadow:0 8px 20px -12px color-mix(in oklab,var(--gold) 62%,transparent);
}
.cr-facts .f-ic svg{ width:25px; height:25px }
.cr-facts h3{ display:flex; align-items:center; gap:.5rem; flex-wrap:wrap }
.cr-facts .soon-badge{
  display:inline-flex; align-items:center; gap:.42em; padding:.28em .66em; font-size:.68em;
  color:var(--gold);
  background:linear-gradient(180deg, color-mix(in oklab,var(--gold) 20%,transparent), color-mix(in oklab,var(--gold) 11%,transparent));
  border:0;
}
.cr-facts .soon-badge::before{
  content:""; width:.5em; height:.5em; border-radius:50%; background:var(--gold);
  box-shadow:0 0 6px color-mix(in oklab,var(--gold) 90%,transparent);
}

/* ---------- growth + partnership band ---------- */
.gp-band{
  border-radius:20px; padding:clamp(1.6rem,4vw,2.6rem);
  background:
    radial-gradient(80% 120% at 85% 0%, rgba(224,182,74,.14), transparent 60%),
    radial-gradient(70% 120% at 10% 100%, rgba(47,191,135,.12), transparent 60%),
    var(--panel);
}
.gp-band h2{ margin:.2rem 0 .6rem }
.gp-band p{ max-width:64ch }

/* ---------- ranking teaser ---------- */
.rk-list{ display:grid; gap:10px; max-width:560px; margin:0 auto }
.rk-row{
  display:flex; align-items:center; gap:12px;
  padding:.8rem 1rem; border-radius:14px;
  background:var(--panel);
}
.rk-medal{ width:34px; height:34px; flex:none; display:grid; place-items:center; border-radius:50%;
  font-weight:800; font-size:.95rem; background:rgba(224,182,74,.15); color:var(--gold) }
.rk-row:nth-child(2) .rk-medal{ background:rgba(170,180,190,.16); color:var(--muted) }
.rk-row:nth-child(3) .rk-medal{ background:rgba(190,120,60,.16); color:#c98a4b }
.rk-bar{ flex:1; height:10px; border-radius:6px; background:var(--line); overflow:hidden; min-width:0 }
.rk-bar i{ display:block; height:100%; border-radius:6px;
  background:linear-gradient(90deg, var(--gold), var(--green)) }

/* ---------- signup CTA + toast ---------- */
.kx-toast{
  position:fixed; z-index:400;
  inset-inline:16px; bottom:calc(18px + env(safe-area-inset-bottom));
  margin-inline:auto; max-width:420px;
  display:flex; align-items:center; gap:11px;
  padding:.95rem 1.15rem; border-radius:14px;
  background:var(--panel); border:0;
  color:var(--text); font-weight:600; font-size:.92rem;
  box-shadow:0 16px 48px rgba(0,0,0,.4);
  opacity:0; transform:translateY(14px); visibility:hidden;
  transition:opacity .3s ease, transform .3s ease, visibility .3s ease;
}
.kx-toast.show{ opacity:1; transform:none; visibility:visible }
.kx-toast svg{ width:20px; height:20px; flex:none; color:var(--gold) }
.btn.loading{ pointer-events:none; opacity:.7 }

/* ---------- giveaway band ---------- */
.gv-band{
  border-radius:20px; padding:clamp(1.6rem,4vw,2.6rem);
  text-align:center;
  background:
    radial-gradient(90% 130% at 50% 0%, rgba(224,182,74,.16), transparent 58%),
    var(--panel);
  overflow:hidden;
}
.gv-prizes{ display:grid; grid-template-columns:repeat(3,1fr); gap:14px; margin-top:1.5rem }
@media (max-width:860px){ .gv-prizes{ grid-template-columns:1fr }}
.gv-prize{
  padding:1.2rem 1rem; border-radius:16px;
  background:var(--card, var(--bg));
  transition:transform .25s ease, border-color .25s ease;
}
.gv-prize:hover{transform:translateY(-4px);}
.gv-prize .f-ic{ width:54px; height:54px; margin:0 auto .8rem; border-radius:15px; display:flex; align-items:center; justify-content:center; background:linear-gradient(135deg,rgba(224,182,74,.16),rgba(47,191,135,.08)); color:var(--gold) }
.gv-prize .f-ic svg{ width:26px; height:26px }
.gv-prize h3{ margin:0 0 .3rem; font-size:1.02rem }
.gv-prize p{ margin:0; font-size:.86rem; color:var(--muted) }
.gv-meter{
  display:flex; align-items:center; gap:10px; justify-content:center;
  margin-top:1.4rem; flex-wrap:wrap;
}
.gv-meter .pill{ font-size:.8rem }
[dir="rtl"] .gv-meter > svg{ transform:scaleX(-1) }

/* Rewards "points" mockup card: a loyalty engine, not a stat tile.
   Signature = the medal is the hub of a conic tier-ring that arcs gold->green
   toward the next tier (--pc-goal %). Everything else stays quiet and refined. */
@property --pc-fill{syntax:"<percentage>";inherits:true;initial-value:0%}

.pts-card{--pc-goal:62%;position:relative;display:flex;flex-direction:column;align-items:center;text-align:center;gap:.2rem;padding:1.5rem 1.35rem 1.5rem;overflow:hidden;
  background:
    radial-gradient(120% 90% at 50% -12%, color-mix(in oklab,var(--gold) 14%,transparent), transparent 60%),
    linear-gradient(180deg, color-mix(in oklab,var(--panel) 42%,var(--panel2)), var(--panel2));
  box-shadow:0 20px 44px -26px color-mix(in oklab,var(--gold) 60%,transparent)}
.pts-card::before{content:"";position:absolute;inset-inline:0;top:0;height:1px;z-index:2;
  background:linear-gradient(90deg,transparent,color-mix(in oklab,var(--gold) 60%,transparent),transparent)}
/* fine grain + a one-time diagonal sheen sweep for material depth */
.pts-card::after{content:"";position:absolute;inset:0;pointer-events:none;z-index:1;border-radius:inherit;
  background:linear-gradient(115deg,transparent 38%,color-mix(in oklab,#fff 12%,transparent) 48%,transparent 58%);
  background-size:250% 100%;background-position:120% 0}
@media (prefers-reduced-motion:no-preference){
  .pts-card::after{animation:pcSheen 5.5s ease-in-out .6s 2}}
@keyframes pcSheen{0%{background-position:120% 0}55%,100%{background-position:-60% 0}}
.pts-card > *{position:relative;z-index:2}

/* current-tier chip */
.pts-card .pc-tier{display:inline-flex;align-items:center;gap:.42rem;font-size:.66rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:color-mix(in oklab,var(--gold2) 84%,var(--text));margin-bottom:.7rem;padding:.32rem .68rem;border-radius:99px;
  background:color-mix(in oklab,var(--gold) 10%,transparent)}
.pts-card .pc-tier-dot{width:6px;height:6px;border-radius:99px;background:var(--gold2);box-shadow:0 0 8px var(--gold)}

/* conic tier-ring — the signature. The ring is a masked donut behind the medal;
   a slow highlight sweeps around it. Fill animates from 0 to --pc-goal on load. */
.pts-card .pc-ring{position:relative;width:86px;height:86px;display:grid;place-items:center;margin-bottom:.6rem;--pc-fill:var(--pc-goal)}
.pts-card .pc-ring::before{content:"";position:absolute;inset:0;border-radius:50%;
  background:conic-gradient(from -90deg,var(--gold),var(--gold2) 30%,var(--green) var(--pc-fill),color-mix(in oklab,var(--text) 9%,transparent) 0);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 5px),#000 calc(100% - 4px));
          mask:radial-gradient(farthest-side,transparent calc(100% - 5px),#000 calc(100% - 4px))}
.pts-card .pc-ring::after{content:"";position:absolute;inset:0;border-radius:50%;opacity:.5;
  background:conic-gradient(from 0deg,transparent 0 80%,color-mix(in oklab,#fff 60%,transparent) 90%,transparent 97%);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 5px),#000 calc(100% - 4px));
          mask:radial-gradient(farthest-side,transparent calc(100% - 5px),#000 calc(100% - 4px))}
.pts-card .pc-ic{position:relative;z-index:2;width:52px;height:52px;display:grid;place-items:center;border-radius:16px;color:var(--goldink,#231a05);
  background:linear-gradient(145deg,var(--gold2),var(--gold));
  border:0;
  box-shadow:0 7px 18px -7px color-mix(in oklab,var(--gold) 75%,transparent)}
.pts-card .pc-ic svg{width:25px;height:25px}
.pts-card .pc-num{font-size:2.95rem;font-weight:800;line-height:1;font-variant-numeric:tabular-nums;letter-spacing:-.015em;
  color:var(--gold)}
.pts-card .mini-sub{font-weight:700}

/* milestone bar with a glowing thumb + inline goal caption */
.pts-card .pc-bar{position:relative;width:100%;max-width:236px;height:9px;border-radius:99px;margin:.78rem 0 .55rem;
  background:color-mix(in oklab,var(--text) 9%,transparent);
  box-shadow:0 1px 2px color-mix(in oklab,#000 28%,transparent) inset}
.pts-card .pc-bar i{position:absolute;inset:0;inline-size:var(--pc-fill);height:100%;border-radius:99px;
  background:linear-gradient(90deg,var(--gold),var(--gold2) 46%,var(--green));
  box-shadow:0 0 12px color-mix(in oklab,var(--gold) 55%,transparent)}
[dir="rtl"] .pts-card .pc-bar i{background:linear-gradient(270deg,var(--gold),var(--gold2) 46%,var(--green))}
.pts-card .pc-bar b{position:absolute;top:50%;inset-inline-start:var(--pc-goal);width:13px;height:13px;border-radius:99px;transform:translate(-50%,-50%);
  background:radial-gradient(circle at 38% 34%,#fff,var(--gold2) 55%,var(--gold));
  border:0;
  box-shadow:0 0 0 3px color-mix(in oklab,var(--gold) 22%,transparent),0 2px 6px color-mix(in oklab,#000 45%,transparent)}
[dir="rtl"] .pts-card .pc-bar b{transform:translate(50%,-50%)}
.pts-card .pc-goal{font-size:.72rem;font-weight:600;color:var(--muted);margin-bottom:.9rem}
.pts-card .pc-goal b{color:color-mix(in oklab,var(--gold2) 80%,var(--text));font-weight:800}
/* Queue 351: chip row never wraps (house rule). Same rail pattern as .listing-card .mini-row. */
.pts-card .mini-row{justify-content:safe center;flex-wrap:nowrap;margin-bottom:0;gap:7px;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.pts-card .mini-row::-webkit-scrollbar{display:none}
.pts-card .mini-row>*{flex:none}
.pts-card .pill{transition:transform .18s ease}
.pts-card .pill:hover{transform:translateY(-1px)}

/* The card sits mid-page, so its entrance is gated on .rv-in (site.js adds this to the parent
   .showrow when it scrolls into view) instead of firing on load, where it would finish unseen
   above the fold. Before reveal the ring and bar hold empty and the contents wait, so the fill and
   count-up play right as the card arrives. The spinning highlight is the one always-on flourish. */
@media (prefers-reduced-motion:no-preference){
  .showrow:not(.rv-in) .pts-card{--pc-fill:0%}
  .showrow:not(.rv-in) .pts-card .pc-bar b{inset-inline-start:0}
  .showrow:not(.rv-in) .pts-card .pc-ic,
  .showrow:not(.rv-in) .pts-card .pc-num,
  .showrow:not(.rv-in) .pts-card .mini-row{opacity:0}
  .rv-in .pts-card .pc-ring::before{animation:pcFill 1.5s cubic-bezier(.22,1,.36,1) both}
  .pts-card .pc-ring::after{animation:pcSpin 7s linear infinite}
  .rv-in .pts-card .pc-bar i{animation:pcFill 1.5s cubic-bezier(.22,1,.36,1) both}
  .rv-in .pts-card .pc-bar b{animation:pcThumb 1.5s cubic-bezier(.22,1,.36,1) both}
  .rv-in .pts-card .pc-ic,.rv-in .pts-card .pc-num,.rv-in .pts-card .mini-row{animation:pcRise .7s cubic-bezier(.22,1,.36,1) both}
  .rv-in .pts-card .pc-num{animation-delay:.28s}
  .rv-in .pts-card .mini-row{animation-delay:.42s}}
@keyframes pcFill{from{--pc-fill:0%}to{--pc-fill:var(--pc-goal)}}
@keyframes pcThumb{from{inset-inline-start:0}to{inset-inline-start:var(--pc-goal)}}
@keyframes pcSpin{to{transform:rotate(1turn)}}
@keyframes pcRise{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:translateY(0)}}

/* ==========================================================================
   Ported from the app (index.html): the sponsored video banner and the
   WhatsApp AI agent section. Same visuals, adapted to this site's shell:
   section padding comes from section.block, and every physical left/right in
   the source is written as a logical property here, because ckb/ar are RTL by
   default and these blocks have to mirror.
   ========================================================================== */

/* ---------- sponsored video banner ----------
   Copy sits on top of footage, so it stays light in both themes on purpose. */
.vp-section{ padding-block-start:0 }
.vp-wide{
  position:relative; display:block; width:100%; padding:0; border:0; cursor:pointer;
  border-radius:22px; overflow:hidden; font-family:inherit; isolation:isolate;
  background:#0b1418; box-shadow:0 24px 60px -34px rgba(0,0,0,.9);
  transition:transform .35s cubic-bezier(.22,1,.36,1), box-shadow .35s;
}
.vp-wide:hover{ transform:translateY(-2px); box-shadow:0 30px 70px -32px rgba(0,0,0,1) }
.vp-wide:focus-visible{ outline:2px solid var(--gold); outline-offset:3px }
.vpw-media{ position:absolute; inset:0; z-index:0 }
.vpw-media .vp-vid{
  display:block; width:100%; height:100%; object-fit:cover; background:#0b1418;
  transform:scale(1.04); transition:transform 1.2s cubic-bezier(.22,1,.36,1);
}
.vp-wide:hover .vpw-media .vp-vid{ transform:scale(1.08) }
/* dark enough for AA text at the centre, lighter at the edges so the footage still reads */
.vpw-scrim{
  position:absolute; inset:0;
  background:
    radial-gradient(120% 100% at 50% 50%, rgba(6,12,15,.30), rgba(6,12,15,.78) 78%),
    linear-gradient(to top, rgba(6,12,15,.86), rgba(6,12,15,.18) 55%, rgba(6,12,15,.62));
}
.vp-wide .vp-tag{
  position:absolute; z-index:2; inset-block-start:16px; inset-inline-start:16px;
  font-size:.68rem; font-weight:800; letter-spacing:.14em; text-transform:uppercase;
  padding:.28rem .62rem; border-radius:999px; color:#17130a;
  /* No white in the mix: lightening the fill AND using the light ink on it is both halves of
     the pair moving the same way, which is how cream on #967421 landed at 4.11:1. */
  /* Queue 547. This badge sits on video footage whose own ground (.vp-wide, line ~781) is a
     literal #0b1418 in BOTH themes, same reasoning as .vpw-offer just below: the card is a
     picture, not a themed surface. var(--gold) does not know that -- it dims from #e0b64a to
     #8a6508 in light theme same as everywhere else on the page, and #17130a on #8a6508 is
     3.48:1. Literal gold instead, same value the dark theme already used, so the badge keeps
     its bright-gold character in both themes rather than answering a light-theme token its
     own background never followed. */
  background:#e0b64a;
}
.vpw-copy{
  position:relative; z-index:1; display:flex; flex-direction:column;
  align-items:center; justify-content:center; text-align:center; gap:14px;
  min-height:340px; padding:64px 26px;
}
.vpw-offer{
  display:inline-flex; align-items:center;
  font-size:.68rem; font-weight:800; letter-spacing:.16em; text-transform:uppercase; line-height:1;
  padding:.46rem .85rem; border-radius:999px;
  /* The pill sits on a 55% #0b1418 scrim over a photo, so its ground is dark in BOTH themes.
     var(--gold) resolves to the light theme's DARK gold there and measured 3.11:1. Literal
     bright gold, because the surface is literal too. */
  color:#e0b64a; border:0;
  background:color-mix(in srgb, #0b1418 55%, transparent);
  backdrop-filter:blur(3px); margin-block-end:2px;
}
.vpw-h{
  font-size:clamp(1.7rem,3.6vw,2.9rem); font-weight:800; line-height:1.12;
  letter-spacing:-.022em; color:#fff; text-wrap:balance; max-width:20ch;
  text-shadow:0 2px 30px rgba(0,0,0,.55);
}
/* Sorani and Arabic need looser leading and no negative tracking */
:root[lang="ckb"] .vpw-h, :root[lang="ar"] .vpw-h{ letter-spacing:0; line-height:1.35 }
.vpw-p{
  font-size:clamp(.92rem,1.2vw,1.05rem); line-height:1.65; color:rgba(255,255,255,.84);
  letter-spacing:.002em; max-width:48ch; text-wrap:pretty; margin:0;
}
:root[lang="ckb"] .vpw-p, :root[lang="ar"] .vpw-p{ line-height:1.85 }
/* the CTA reads as a real button here, not a text link */
.vp-wide .vp-cta{
  margin-block-start:8px; display:inline-flex; align-items:center; gap:9px;
  background:linear-gradient(135deg, var(--gold), var(--gold2)); color:var(--goldink,#231a05);
  border-radius:999px; padding:.78rem 1.5rem; font-size:.9rem; font-weight:800;
  box-shadow:0 14px 34px -16px var(--gold);
  transition:filter .18s, transform .18s;
}
.vp-wide:hover .vp-cta{ filter:brightness(1.06); transform:translateY(-1px) }
.vp-wide .vp-cta svg{ width:15px; height:15px }
/* the arrow points along the reading direction */
:root[dir="rtl"] .vp-wide .vp-cta svg{ transform:scaleX(-1) }
@media(max-width:720px){
  .vpw-copy{ min-height:270px; padding:44px 20px; gap:12px }
  .vpw-h{ font-size:1.5rem }
  .vpw-p{ font-size:.9rem }}
@media (prefers-reduced-motion:reduce){
  .vp-wide, .vp-wide .vp-cta, .vpw-media .vp-vid{ transition:none }
  .vp-wide:hover{ transform:none }
  .vp-wide:hover .vpw-media .vp-vid{ transform:scale(1.04) }}

/* ---------- Kurdify AI for your business (WhatsApp agent) ----------
   Columns rebalanced against the app's version only where section.block already
   supplies the vertical rhythm; the mockup itself is unchanged. */
.wai-inner{ display:grid; grid-template-columns:1fr 1.12fr; gap:clamp(.8rem,2vw,1.7rem); align-items:center; max-width:1180px }
@media(max-width:860px){ .wai-inner{ grid-template-columns:1fr; gap:2.6rem }}
.wai-text .kicker{ color:var(--gold); font-weight:800; font-size:.78rem; text-transform:uppercase; letter-spacing:.1em; margin-block-end:.6rem }
.wai-text h2{ font-size:clamp(1.55rem,3.6vw,2.25rem); letter-spacing:-.02em; line-height:1.18; margin:.5rem 0 .8rem; max-width:19ch }
:root[lang="ckb"] .wai-text h2, :root[lang="ar"] .wai-text h2{ letter-spacing:0; line-height:1.4 }
.wai-text p{ color:var(--muted); font-size:1.02rem; line-height:1.6; max-width:34ch; margin:0 0 1.3rem }
.wai-feats{ list-style:none; padding:0; margin:0 0 1.6rem; display:grid; gap:.7rem }
.wai-feats li{ display:flex; align-items:center; gap:.6rem; font-weight:600; white-space:nowrap }
@media(max-width:520px){ .wai-feats li{ white-space:normal; font-size:.94rem } }
.wai-feats li svg{ width:20px; height:20px; flex:0 0 20px; color:#25d366; background:rgba(37,211,102,.13); border-radius:50%; padding:3px }
/* Item 3 (2026-08-31): the CTA reads as a small pill next to a full-width phone mock;
   full-width matches the weight of the section it closes. */
.wai-cta{ display:flex; align-items:center; justify-content:center; gap:.5rem; width:100%; background:#25d366; color:#04231a; font-weight:800; padding:.9rem 1.35rem; border-radius:999px; text-decoration:none; transition:transform .15s, box-shadow .15s; box-shadow:0 8px 24px -8px rgba(37,211,102,.6) }
.wai-cta:hover{ transform:translateY(-2px); box-shadow:0 14px 30px -8px rgba(37,211,102,.7) }
.wai-cta svg{ width:18px; height:18px }
:root[dir="rtl"] .wai-cta svg{ transform:scaleX(-1) }
/* Column, not a row, so the sample caption can sit under the phone without splitting it. */
.wai-stage{ display:flex; flex-direction:column; align-items:center; position:relative }
/* Centred with inset-inline + auto margins rather than a left/transform pair, so the glow
   lands in the same place in both directions. */
.wai-stage::before{
  content:""; position:absolute; inset-block-start:50%; inset-inline:0; margin-inline:auto;
  width:min(420px,80%); aspect-ratio:1; transform:translateY(-50%);
  background:radial-gradient(circle at 50% 45%, rgba(37,211,102,.28), rgba(231,184,78,.10) 45%, transparent 68%);
  filter:blur(26px); z-index:0; animation:waiAura 7s ease-in-out infinite;
}
@keyframes waiAura{
  0%,100%{ opacity:.75; transform:translateY(-50%) scale(1) }
  50%{ opacity:1; transform:translateY(-50%) scale(1.06) }
}
.wai-phone{ position:relative; z-index:1; width:288px; max-width:88vw; border-radius:44px; background:linear-gradient(165deg,#16261f,#0a0f0d 70%); padding:9px; box-shadow:0 44px 90px -34px rgba(0,0,0,.75)}
.wai-note{ position:relative; z-index:1; margin:1.1rem 0 0; text-align:center }
.wai-wa{ border-radius:36px; overflow:hidden; background:#0b141a; display:flex; flex-direction:column; height:452px; position:relative }
.wai-wa::after{ content:""; position:absolute; inset:0; z-index:4; pointer-events:none; background:linear-gradient(180deg,transparent,rgba(37,211,102,.16),transparent); height:38%; transform:translateY(-140%); animation:waiScan 5.5s ease-in-out 1.2s infinite }
@keyframes waiScan{ 0%{ transform:translateY(-140%) } 18%,100%{ transform:translateY(320%) } }
.wai-statusbar{ display:flex; align-items:center; justify-content:space-between; padding:.5rem .95rem .12rem; background:#1f2c34; color:#dfeaf0; font-size:.7rem; font-weight:800 }
.wai-statusbar .sb-ic{ display:flex; gap:5px; align-items:center; opacity:.9 }
.wai-statusbar .sb-ic svg{ height:11px; width:auto; fill:currentColor }
.wai-wahead{ display:flex; align-items:center; gap:.55rem; background:#1f2c34; padding:.5rem .8rem .62rem; color:#e9edef; position:relative }
.wai-hmeta{ flex:1; min-width:0 }
.wai-av{ width:36px; height:36px; border-radius:50%; background:linear-gradient(135deg,#25d366,#128c7e); display:flex; align-items:center; justify-content:center; font-weight:800; color:#04231a; flex:0 0 36px; position:relative }
.wai-av::after{ content:""; position:absolute; inset:-2px; border-radius:50%; border:0; animation:waiRing 2.6s ease-out infinite }
@keyframes waiRing{ 0%{ transform:scale(1); opacity:.7 } 100%{ transform:scale(1.35); opacity:0 } }
.wai-hname{ font-weight:700; font-size:.92rem; line-height:1.15; display:flex; align-items:center; gap:.4rem; min-width:0 }
.wai-hname .nm{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.wai-aibadge{ flex:0 0 auto; display:inline-flex; align-items:center; gap:3px; font-size:.6rem; font-weight:800; letter-spacing:.02em; color:#04231a; background:linear-gradient(135deg,#5ff0a3,#e7b84e); padding:2px 6px; border-radius:999px }
.wai-aibadge svg{ width:9px; height:9px }
.wai-hstat{ font-size:.72rem; color:#8fe3b0; display:flex; align-items:center; gap:.3rem }
.wai-hstat i{ width:7px; height:7px; border-radius:50%; background:#25d366; display:inline-block; box-shadow:0 0 0 0 rgba(37,211,102,.6); animation:waiPulse 2s infinite }
@keyframes waiPulse{ 0%{ box-shadow:0 0 0 0 rgba(37,211,102,.5) } 70%{ box-shadow:0 0 0 6px rgba(37,211,102,0) } 100%{ box-shadow:0 0 0 0 rgba(37,211,102,0) } }
.wai-wabody{ flex:1; overflow:hidden; padding:.85rem .7rem; display:flex; flex-direction:column; gap:.45rem; background:#0b141a; background-image:radial-gradient(rgba(255,255,255,.025) 1px, transparent 1px); background-size:18px 18px } /* impeccable-disable-line codex-grid-background -- deliberate facsimile of WhatsApp's own chat wallpaper inside the WhatsApp mock: this whole block is WhatsApp's literal palette (#0b141a ground, #202c33 incoming, #005c4b outgoing, #25d366 brand). The texture is representational, not decoration. It has ONE hairline stop, under the rule's own >=2 threshold; it fires on 4.0.4's looser px-pair branch (background-size:18px 18px) alone. Assessed queue 560, 2026-08-25. */
.wai-msg{ max-width:82%; padding:.5rem .7rem; border-radius:13px; font-size:.85rem; line-height:1.45; opacity:0; transform:translateY(8px) scale(.98); transition:opacity .35s, transform .35s }
.wai-msg.show{ opacity:1; transform:none }
/* Tails use the logical start/end corners so the incoming bubble keeps its notch against
   whichever edge it is actually aligned to once the page flips to RTL. */
.wai-in{ align-self:flex-start; background:#202c33; color:#e9edef; border-start-start-radius:3px }
.wai-out{ align-self:flex-end; background:#005c4b; color:#e9edef; border-start-end-radius:3px }
.wai-card{ align-self:flex-start; max-width:88%; background:linear-gradient(160deg,#10241d,#0d1b16); border:0; border-radius:14px; border-start-start-radius:3px; padding:.6rem .7rem; opacity:0; transform:translateY(8px) scale(.98); transition:opacity .4s, transform .4s; box-shadow:0 10px 26px -14px rgba(0,0,0,.6) }
.wai-card.show{ opacity:1; transform:none }
.wai-card-top{ display:flex; align-items:center; gap:.4rem; font-weight:800; font-size:.8rem; color:#5ff0a3; margin-block-end:.45rem }
.wai-card-top svg{ width:15px; height:15px }
.wai-card-rows{ display:grid; gap:.28rem }
.wai-crow{ display:flex; align-items:center; gap:.45rem; font-size:.76rem; color:#cfe6da }
.wai-crow svg{ width:13px; height:13px; color:#8fa3ad; flex:0 0 13px }
.wai-crow b{ color:#fff; font-weight:700 }
.wai-typing{ align-self:flex-start; background:#202c33; border-radius:12px; border-start-start-radius:3px; padding:.6rem .75rem; display:none; align-items:center; gap:.4rem }
.wai-typing.show{ display:flex }
.wai-typing em{ font-style:normal; font-size:.68rem; color:#8fa3ad }
.wai-typing .dots{ display:flex; gap:4px }
.wai-typing .dots span{ width:6px; height:6px; border-radius:50%; background:#8fe3b0; animation:waiDot 1.2s infinite }
.wai-typing .dots span:nth-child(2){ animation-delay:.2s }
.wai-typing .dots span:nth-child(3){ animation-delay:.4s }
@keyframes waiDot{ 0%,60%,100%{ transform:translateY(0); opacity:.4 } 30%{ transform:translateY(-4px); opacity:1 } }
.wai-wabar{ display:flex; align-items:center; gap:.5rem; padding:.5rem .65rem; background:#1f2c34 }
.wai-wabar .wai-inp{ flex:1; background:#2a3942; border-radius:999px; padding:.5rem .8rem; color:#b6c6cf; font-size:.78rem }
.wai-wabar .wai-send{ width:32px; height:32px; border-radius:50%; background:#25d366; display:flex; align-items:center; justify-content:center; color:#04231a; flex:0 0 32px }
:root[dir="rtl"] .wai-wabar .wai-send svg{ transform:scaleX(-1) }
.wai-cap{ position:absolute; z-index:3; background:rgba(12,32,26,.72); border:0; border-radius:12px; padding:.42rem .65rem; font-size:.72rem; font-weight:700; color:#eaf4f2; display:flex; align-items:center; gap:.4rem; backdrop-filter:blur(9px); box-shadow:0 14px 34px -14px rgba(0,0,0,.6); animation:waiFloat 4.5s ease-in-out infinite }
.wai-cap svg{ width:14px; height:14px; color:#5ff0a3 }
.wai-cap.c1{ inset-block-start:21%; inset-inline-start:-30% }
.wai-cap.c2{ inset-block-end:22%; inset-inline-end:-24%; animation-delay:1.3s }
@media(max-width:1024px){ .wai-cap.c1{ inset-inline-start:-16% } .wai-cap.c2{ inset-inline-end:-12% }}
@keyframes waiFloat{ 0%,100%{ transform:translateY(0) } 50%{ transform:translateY(-8px) } }
/* Hidden below 520px: the chips overhang the phone, and at that width the overhang is what
   would push the page into horizontal scroll. */
@media(max-width:520px){ .wai-cap{ display:none }}
@media(prefers-reduced-motion:reduce){
  .wai-msg, .wai-card{ opacity:1; transform:none }
  .wai-cap, .wai-hstat i, .wai-av::after, .wai-wa::after, .wai-stage::before{ animation:none }}

/* ---------- points card: sample marker ----------
   The card shows a balance, a tier and wallet chips. None of it belongs to the visitor, so it
   is labelled the same way the other product mocks on this site are. */
.pts-card .pc-sample{
  position:absolute; z-index:2; inset-block-start:12px; inset-inline-start:12px;
  font-size:.6rem; letter-spacing:.06em; text-transform:uppercase;
}

/* Bridge junction: the little badge becomes a bare mini flag dial (owner request 2026-07-30):
   no background circle, just the red and green arcs turning around the sun. */
.ccb-node{background:transparent;border:none;box-shadow:none;width:60px;height:60px;animation:none}
.ccb-sun{width:auto;height:auto;margin:0;animation:none;color:var(--gold)}
.ccb-sun.pre-sun .pl-orb{width:54px;height:54px}
.ccb-sun.pre-sun .pl-orb::before,.ccb-sun.pre-sun .pl-orb::after{display:none}
.ccb-sun .pl-sun{width:24px;height:24px;animation-duration:22s,8s}
.ccb-sun .pl-ring{animation-duration:6.5s}
.ccb-sun .pl-ring2{animation-duration:9s}
@media(prefers-reduced-motion:reduce){.ccb-sun *{animation:none!important}}

/* Trio cards: hover lift, tighter body, ringed icon (owner: enhance the style). */
.trio-card{transition:transform .18s,box-shadow .18s,border-color .18s;padding:1.5rem 1.4rem 1.25rem;gap:.55rem}
.trio-card:hover{transform:translateY(-3px);box-shadow:0 18px 40px -22px rgba(0,0,0,.7)}
.trio-card .trio-ic{box-shadow:0 0 0 6px color-mix(in srgb,var(--accent) 7%,transparent)}
.trio-card p{line-height:1.6}

/* Suite phone mock: a touch shorter overall (owner request 2026-07-30). */
.suite-phone{zoom:.9}

/* ==== "Who Kurdify is for" cards, restyled 2026-08-03 (owner: make it look professional) ====
   The card was centre-aligned with a start-aligned checklist floated inside it, so each card
   carried two different text edges and no two cards agreed on where either of them fell. It
   reads on one axis now: mark, heading, sentence, list and link all begin on the same line.
   The icon drops from a 104px display tile to a 56px chip, a mark rather than an illustration,
   and the link sits under a hairline so a card with three bullets reads as finished instead of
   half empty next to one with six. */
/* Top padding raised 2026-08-03 (owner request). This is the rule that actually wins, not the
   base one further up, so the extra room has to be set here or nothing moves. */
.trio-card{align-items:stretch;text-align:start;padding:2.4rem 1.45rem 1.35rem;gap:.7rem}
.trio-ic{width:56px;height:56px;border-radius:16px}
.trio-ic svg{width:28px;height:28px;stroke-width:1.7}
.trio-card:hover .trio-ic{transform:translateY(-2px)}
.trio-card h3{font-size:1.12rem;margin:.4rem 0 0}
/* Caps on the three card headings (owner request 2026-08-16). Written here, not on the
   base rule at :384, for the reason the comment above already gives: this block wins.
   SCOPED TO LTR, the same guard site.css:53 puts on the top strip. Arabic script has no
   case, so text-transform is a harmless no-op on ckb and ar, but letter-spacing is not:
   it prises apart letters that are supposed to join. The two travel together, and only
   where there is a case to change. Tracking is opened from the base rule's -.01em, which
   was set for lowercase; caps at negative tracking read as one long word. */
:root[dir=ltr] .trio-card h3{text-transform:uppercase;letter-spacing:.045em}
.trio-card p{font-size:.9rem;max-width:36ch}
.trio-card .trio-list{align-self:stretch;text-align:start;margin:.5rem 0 0;gap:.55rem}
/* One text column with the tick hung in the margin: a wrapped line now aligns under the first
   word rather than under the tick, and the "coming soon" chip can sit inline at the end of the
   sentence instead of parking itself mid-line beside it. */
.trio-list li{display:block;position:relative;padding-inline-start:1.45rem}
.trio-list li svg{position:absolute;inset-inline-start:0;top:.34em;margin-top:0}
.trio-soon{display:inline-block;vertical-align:baseline;margin-inline-start:.35rem}
.trio-card .trio-go,.trio-card .trio-links{margin-top:auto;padding-top:.85rem}
.trio-card .trio-links{justify-content:flex-start;gap:6px 22px;margin-top:auto}
/* The two-link card puts the rule on the row, not on each link inside it, or the card ends
   with two stacked hairlines. */
.trio-card .trio-links .trio-go{border-top:0;padding-top:0;margin-top:0}
/* The single link is a 44px touch target that carries its own top padding inside that height,
   while the two-link row stacks the padding on top of a 44px row, so the card with two links
   drew its rule 14px higher than the other three. One height for both footers. */
.trio-card > .trio-go,.trio-card > .trio-links{min-height:58px;box-sizing:border-box}

/* Trio list, quieted 2026-08-12 (owner request: "better layout, make the check mark lines a bit
   smaller, more premium"). Six bullets at .86rem/1.5 with a 14px tick were running at nearly the
   weight of the card's own sentence above them, so the card had two paragraphs of equal voice and
   no hierarchy: heading, promise, then six more lines shouting the same size.

   Four changes, all in the same direction. The copy steps down one notch and the leading tightens
   with it, so the block reads as a specification list under the promise rather than as a second
   pitch. The tick goes from 14px to 11px and loses its green cast: it was mixing the card accent
   with the green token, which on the gold cards put a third colour in a two-colour card. It is a
   mark confirming a line, not a decoration, so it sits at the accent's own hue and low contrast.
   Row spacing goes up slightly WHILE the text goes down, which is what separates "smaller" from
   "cramped": each entry is quieter but the gaps between entries are more legible, so a wrapped
   two-line bullet still reads as one item. And the hanging indent narrows to match the smaller
   tick, so the text column starts closer to the card edge and the whole block sits on one axis
   with the heading above it. */
.trio-list li{font-size:.815rem;line-height:1.46}
.trio-card .trio-list{gap:.6rem;margin-top:.6rem}
.trio-list li{padding-inline-start:1.25rem}
.trio-list svg{width:11px;height:11px;stroke-width:3;
  color:color-mix(in srgb,var(--accent) 72%,transparent)}
.trio-list li svg{top:.42em}
/* The chip was
   heavier than the sentence it qualified: uppercase, 800, on a tinted pill, at the end of a line
   that is now .815rem. Same information, stated once, at the weight of an aside. */
.trio-soon{font-size:.56rem;font-weight:700;letter-spacing:.04em;padding:.08rem .38rem;
  background:color-mix(in srgb,var(--gold) 10%,transparent);
  color:color-mix(in srgb,var(--gold2) 82%,transparent)}
/* The card's own sentence keeps its size, and gains the measure it needs to stay two lines now
   that the list under it is lighter. Without this the promise and the list converge again. */
.trio-card p{font-size:.9rem;line-height:1.58;max-width:34ch}

/* ===== GIVEAWAY CARD =========================================================================
   Ported from the app's #giveawayPromo (owner request 2026-08-03), so the marketing page and
   the app show the same moment: the prize photograph full-bleed behind the card, the three
   ranked tiers, the two how-to-enter columns and the draw date.

   Two differences from the app, both forced by this being a static build. The app fills the
   prize names and the draw date from /api/giveaway at runtime; here they bind to the give.p1
   to give.p3 and give.drawval keys that extras.js already carries. And the app's CTA calls
   openAccount(); here it is a link to #signup. Everything else is the app's own CSS. ===== */






/* Prize car photo: a small slim banner on mobile, a smaller side-column photo on desktop. */


/* vintage grade: warm faded tone (sepia + gentle desaturation) */

/* film grain (~10%) for an editorial, less-CGI feel */

/* single strong dark scrim (above) keeps the overlaid text readable over the photo */
/* desktop: keep it a short, contained full-width banner (shows the whole car; no side-column crop) */

/* ---- Cinematic scroll-pinned giveaway moment (home) ---- */
.gcine-wrap{padding:0;margin:2.6rem 0}
.gcine-track{position:relative;height:220vh}
.gcine-stage{position:sticky;top:0;height:100vh;overflow:hidden;background:#06080a}
.gcine-bg{position:absolute;inset:-5%;width:110%;height:110%;object-fit:cover;object-position:center 58%;will-change:transform;filter:sepia(.28) saturate(.9) contrast(.98) brightness(.86);transform:scale(1.16)}
.gcine-scrim{position:absolute;inset:0;z-index:1;background:linear-gradient(to top,rgba(5,7,9,.94),rgba(5,7,9,.42) 46%,rgba(5,7,9,.7))}
.gcine-grain{position:absolute;inset:0;z-index:2;opacity:.1;mix-blend-mode:overlay;pointer-events:none;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='150' height='150'><filter id='gc'><feTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23gc)'/></svg>");background-size:150px 150px}
.gcine-content{position:absolute;inset:0;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:clamp(96px,13vh,150px) 20px 9vh;gap:1.05rem}
.gcine-kick{display:inline-flex;align-items:center;gap:8px;font-weight:800;font-size:.74rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold);border:0;border-radius:999px;padding:7px 15px;background:rgba(12,14,16,.4);backdrop-filter:blur(4px)}
.gcine-kick svg{width:14px;height:14px}
.gcine-title{margin:.2rem 0 0;font-size:clamp(2.3rem,7.4vw,5.2rem);font-weight:800;letter-spacing:-.03em;line-height:1.02;text-wrap:balance;max-width:15ch;color:#fff}
.gcine-sub{margin:0;color:rgba(255,255,255,.84);font-size:clamp(1rem,2.3vw,1.35rem);max-width:44ch;text-wrap:pretty}
.gcine-prizes{display:flex;gap:11px;flex-wrap:wrap;justify-content:center;margin-top:.5rem;max-width:min(92vw,880px)}
.gcine-chip{display:inline-flex;align-items:center;gap:9px;background:rgba(10,12,14,.5);backdrop-filter:blur(7px);border:0;border-radius:999px;padding:9px 16px;color:#fff;font-weight:700;font-size:.92rem}
.gcine-chip .gc-tier{flex:none;color:var(--goldink,#231a05);background:linear-gradient(135deg,var(--gold),var(--gold2));font-weight:900;font-size:.68rem;border-radius:7px;padding:3px 7px}

.gcine-cta{margin-top:.7rem;border:none;cursor:pointer;font:inherit;font-weight:800;font-size:1rem;color:var(--goldink,#231a05);background:linear-gradient(135deg,var(--gold),var(--gold2));border-radius:13px;padding:14px 26px;box-shadow:0 14px 34px rgba(0,0,0,.45);transition:transform .15s,filter .15s}
.gcine-cta:hover{transform:translateY(-2px);filter:brightness(1.05)}
.gcine-hint{position:absolute;inset-inline:0;bottom:26px;z-index:3;display:flex;flex-direction:column;align-items:center;gap:6px;color:rgba(255,255,255,.7);font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase}
.gcine-hint svg{width:20px;height:20px;animation:gcineBob 1.8s ease-in-out infinite}
@keyframes gcineBob{0%,100%{transform:translateY(0)}50%{transform:translateY(6px)}}
/* JS-driven reveal: hide content only when the scroll engine is active (so no-JS shows everything) */
.gcine-js .gcine-content>*{opacity:0;transform:translateY(26px);will-change:opacity,transform}
@media(prefers-reduced-motion:reduce){
  .gcine-track{height:auto}
  .gcine-stage{position:static;height:auto;min-height:78vh}
  .gcine-bg{transform:none!important}
  .gcine-js .gcine-content>*{opacity:1!important;transform:none!important}
  .gcine-hint{display:none}}













/* 2nd and 3rd sit on a DARK tier plate in both themes, so their label is committed light and
   does not follow the page. Inheriting the page ink put #73540a on #2c3134 at 1.88:1. */

/* silver medal */
/* bronze medal */














/* Wide screens: photo pinned to the physical LEFT, content on the right (works RTL + LTR) */


/* mobile: center the enter button and let it span full width */

/* The giveaway card ALWAYS sits on the dark car photo + scrim (in both themes), so its
   overlaid text must stay light regardless of the site theme, or it vanishes in light mode. */















/* ==== Border removal and finish pass, 2026-08-12 ==========================================
   Four separate owner requests from four screenshots, all pointing the same way: "remove the
   border around", on the giveaway prize rows, the jobs list, the Kavalsia section and its
   columns. Handled in one block because they are one decision, not four.

   The method is the same everywhere and it is not simply deleting the border. A 1px outline is
   doing two jobs at once: it separates the card from the page, and it draws its shape. Delete
   it outright and the cards dissolve into the background, which is the failure mode that makes
   "remove the borders" get asked for a second time. So the separation moves to the fill and a
   top-edge sheen, which is how a raised surface reads without an outline, and the border is set
   TRANSPARENT rather than removed so nothing shifts by a pixel and the hover states still have
   a border to colour.

   THE GIVEAWAY HALF OF THIS ROUND NOW LIVES IN site/assets/site.css (queue #489, 2026-08-21),
   with its reasoning, together with the whole .gvp-* component. It was defined in both files
   and rendered two different ways depending on which stylesheets the page loads, so the three
   giveaway pages that never load extras.css had never received this request at all. Nothing
   about the decision changed; only where it is written. Do not add a .gvp- rule to this file. */

/* Deal card badges, owner: "fix that bad TEST in the top corner and smaller". Two pills were
   sitting side by side in the corner of the photo at different sizes, on different grounds, one
   solid green and one outlined, and the outlined one overhung the card's rounded corner. They
   are now one size, one shape and one baseline, tucked inside the radius. */
/* The jobs list, the Kavalsia cards and chips, and the deal badge all live in the inline
   <style> of site/index.html, which the browser applies AFTER this file. Their border removal
   had to move there or it lost on source order at equal specificity; measured at the time with
   the giveaway prize rows going transparent from here and the other three still painting their
   outlines. The giveaway half has since moved to site.css, see the note above. */

/* =============================================================================
   PREMIUM LIFT ROUND, queue #460. Captures 1, 2, 17, 19, 21, 22, 23, 25, 26 of
   docs/screenshot-map-2026-08-19.md. Appended here rather than edited in place
   because extras.css is the LAST sheet index.html loads, so these win over
   site.css without a specificity fight, and the whole round reverts as one block.

   ONE MECHANISM CARRIES MOST OF IT. Eleven of the round's twenty-six notes say
   "remove the borders". Removing a rim and putting nothing back is what made the
   earlier passes read flat, and capture 23 asks for the opposite ("more 3D").
   So a rim is replaced by real elevation: a top light edge (inset 0 1px 0) plus
   a soft drop shadow. That is depth without a border, and it is the same pattern
   the #471 round already used on #rewards, so the page stays one system.

   NOT TOUCHED, deliberately: the hero's viewfinder corners (.cam-corners). They
   read as a gimmick next to the rest, but site/index.html records them as an
   owner request of 2026-07-30. Removing an owner decision is not a lift call.
   ========================================================================== */

/* ---- capture 1: hero -----------------------------------------------------
   NOTHING IS CHANGED HERE, and that is the finding.

   The four stat tiles were the obvious lift target: four tiles, each with its
   own gold gradient bar across the top, four things competing for one job. The
   change was written (one continuous instrument strip, hairline inset dividers,
   tabular numerals) and it was WRONG, in a way only the render showed.

   site.css already carries a deliberate, documented redesign of this exact
   strip: `.cam-hero .cam-stats .hstat` renders the tiles RECESSED, with an
   inset shadow, the gold top rule explicitly removed as "a raised edge catching
   light from the front", and a press-in hover instead of a lift. It even
   carries its own specificity note (site.css:2297) warning that an unanchored
   rule here "silently loses and the tiles stay raised while the file claims
   otherwise". That is precisely what happened: at (0,1,0) the new `gap:1px`
   lost to `.cam-stats .stat-strip` at (0,2,0), while `background:var(--line)`
   had nothing to lose to and applied. The result was the old recessed tiles
   sitting on a pale slab showing through 8px gutters. Half-applied, and worse
   than either intent.

   So the strip keeps its recessed design. "More premium" is not a reason to
   overwrite a reasoned design with a different one, and a rule that can only
   win by out-specifying a documented warning is a rule that should not be
   written. The deck below is the one hero change, and it fights nothing.

   The viewfinder corners stay too: index.html records them as an owner request
   of 2026-07-30. */
/* The deck runs one step lighter than the headline it sits under, and gets its
   own size on a phone: a clamp tuned for desktop leaves a five-line paragraph
   at 390. Both rules match site.css's own specificity and simply land later. */
.hero-lead{font-weight:300;max-width:56ch}
@media(max-width:560px){.hero-lead{font-size:.98rem;line-height:1.62}}

/* ---- capture 2: #who, the three mission cards ----------------------------
   "separate the check marks and the description". They are currently one stack
   with a gap, so the description reads as the first bullet. An inset hairline
   above the list separates them without putting a border back on the card: it is
   a rule INSIDE a surface, which is structure, not a rim. */
.trio-card .trio-list{margin-top:1rem;padding-top:1rem;position:relative}
.trio-card .trio-list::before{content:"";position:absolute;top:0;inset-inline:0;height:1px;
  background:linear-gradient(90deg,color-mix(in srgb,var(--accent,var(--gold)) 34%,transparent),transparent 72%)}
/* The tick was a 14px hairline glyph, the lightest mark on the card. It gets a
   tinted disc so it reads as deliberate, and it sits on the accent the card
   already declares via data-accent, so nothing new is introduced. */
.trio-card .trio-list li{gap:.62rem;align-items:flex-start}
.trio-card .trio-list li > svg{width:16px;height:16px;flex:none;margin-top:.12rem;padding:2px;
  border-radius:50%;background:color-mix(in srgb,var(--accent,var(--gold)) 15%,transparent);
  color:var(--accent,var(--gold));stroke-width:3}
/* Mobile: the 104px icon tile on its own row pushes the title most of a thumb
   below the card edge. Beside the heading, not stacked above it. */
@media(max-width:560px){
  .trio-card{display:grid;grid-template-columns:auto 1fr;column-gap:.9rem;align-items:center}
  /* Photo banner (task #786) takes its own full-width row above the icon+heading row, which
     the icon and heading move to explicitly (grid-row:2) so the photo's forced row:1 cannot
     overlap them -- .trio-ic already carried an explicit grid-row before this, so leaving it
     unset would have let both land in row 1 together. */
  .trio-card .trio-photo{grid-column:1/-1;grid-row:1;margin-block-end:.9rem}
  .trio-card .trio-ic{width:52px;height:52px;border-radius:15px;grid-row:2}
  .trio-card .trio-ic svg{width:24px;height:24px}
  .trio-card h3{grid-column:2;grid-row:2;margin:0}
  .trio-card > p,.trio-card .trio-list,.trio-card .trio-go,.trio-card .trio-links{grid-column:1/-1}}

/* ---- capture 17: the seven influencer levels ----------------------------
   REVERTED 2026-08-20, owner request: "reverse the design of this section back
   to how it was before". Queue #460 had replaced the seven check badges with a
   rising gold ladder and hidden the repeated "Followers+" label; that whole
   block is deleted here, so the section falls back to site.css's own tiles, the
   gradient check disc, the label under each level, and .lvl::before / .lvl::after.

   Two things come back with it, both recorded so the next round does not
   rediscover them as bugs: .lvl::after is a REMOTE Unsplash photograph behind
   every tile, so the section makes seven cross-origin image requests again, and
   .lvl::before is a conic-gradient rim that animates a registered custom
   property forever on seven elements. They were removed as a side effect of the
   ladder, never as an owner decision, so they return with the design.

   Do not re-add the ladder without a new owner instruction.

   Powered by Nexus V22 · Kavalsia Inc. · Siavash Sadighi */

/* ---- captures 19 and 21: #services and #pledge ---------------------------
   The round's global pass: rim off, elevation on. The icon tiles also carried a
   gold bloom on a dark ground, which is the single fastest way for a dark UI to
   read as generated. The tinted ground stays, the light does not. */
#services .grid > *,#pledge .grid > *{border:0;
  box-shadow:0 16px 34px -24px rgba(0,0,0,.8)}
#services .f-ic,#pledge .f-ic,#services .grid svg[class*=ic],#pledge .grid svg[class*=ic]{box-shadow:none}
#services [class*=-ic],#pledge [class*=-ic]{border:0;box-shadow:none;filter:none}
/* #pledge put three cards inside an outer panel. The panel is a card holding
   cards, it adds no information, and it is what makes the row read boxed-in. */
#pledge .gp-band{background:none;box-shadow:none;padding-inline:0}
/* Ragged bottoms: the three cards carry one, two and one line of body text, so
   the row ended on three different edges. */
/* Equal heights come from the grid stretching its items, which is already the
   default. An earlier version of this rule ALSO set display:flex;flex-direction:
   column on the cards, and that silently rewrote the card's own layout: the icon
   moved from beside the headline to stacked above it. Caught in the render, not
   in the source. Stretch is the whole fix. */
#services .grid,#pledge .grid{align-items:stretch}

/* ---- capture 22: #pricing, the free panel --------------------------------
   "fix the text to make them better structured ... and make it premium".
   Three faults, all structural: the eyebrow rendered in plain sentence case
   while every other eyebrow on the page is uppercase gold; the three list rows
   floated centred inside a much wider panel with no measure; and a band of dead
   space sat between the last row and a call to action that was styled as bare
   text rather than as a control. */
.free-band .kicker{color:var(--gold);font-weight:800;font-size:.78rem;text-transform:uppercase;
  letter-spacing:.1em;margin-bottom:.6rem}
.free-band{box-shadow:0 20px 44px -28px rgba(0,0,0,.8)}
/* The rows become one block with its own measure, left aligned inside a centred
   box, with an inset rule separating them from the description above, the same
   separation capture 2 asked for on the mission cards. */
.free-list{max-width:34rem;margin-inline:auto;text-align:start;gap:.75rem;
  margin-top:1.5rem;padding-top:1.4rem;position:relative}
.free-list::before{content:"";position:absolute;top:0;inset-inline:0;height:1px;
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--green) 30%,transparent),transparent)}
.free-cta{margin-top:1.5rem}

/* ---- capture 23: #rewards ------------------------------------------------
   The #471 round already took the rims off these cards and set one vertical
   rhythm. What its note still asks for is depth ("more 3D") and old screens.
   Depth here is the same top light edge and drop shadow as everything else,
   plus a hover that lifts, so the card has somewhere to go. */
#rewards .grid .fcard{box-shadow:0 16px 34px -24px rgba(0,0,0,.8);
  transition:transform .22s ease,box-shadow .22s ease}
#rewards .grid .fcard:hover{transform:translateY(-3px);
  box-shadow:0 22px 44px -22px rgba(0,0,0,.85)}
@media(prefers-reduced-motion:reduce){
  #rewards .grid .fcard{transition:none}
  #rewards .grid .fcard:hover{transform:none}}
/* "optimized for old screens": 320px. The icon column plus the padding leaves
   the title about 150px, which breaks "Points for inviting friends" onto three
   lines and pushes the pill row past the gutter. */
@media(max-width:359px){
  #rewards .grid .fcard{padding:1.05rem 1rem}
  #rewards .grid .fcard .f-ic{width:34px;height:34px;border-radius:11px}
  #rewards .grid .fcard .f-ic svg{width:17px;height:17px}
  #rewards .grid .fcard h3{font-size:.95rem}}

/* ---- capture 25: the FAQ -------------------------------------------------
   Seven separate floating pills with a gap between them. An accordion is ONE
   list, and drawing it as seven detached boxes is what makes it read cheap. It
   becomes one continuous panel with inset dividers, which is the same call the
   #471 round already recorded for the compare table ("continuous-panel radii and
   the inset dividers are structure, not scale").

   The toggle glyph is NOT changed. It looks like a plus that becomes an "x",
   and it was worth checking whether those were two different marks; they are
   not. site.css already rotates the one "+" by 45 degrees on [open], which is
   the ordinary accordion convention, so there was nothing here to fix. Recorded
   because the render invites the same wrong conclusion next time. */
.faq{gap:0;border-radius:18px;overflow:hidden;background:var(--panel);
  box-shadow:0 20px 44px -28px rgba(0,0,0,.8)}
.faq details{border-radius:0;background:none}
.faq details + details{border-top:0}
.faq summary{padding:1.25rem 1.45rem}
.faq summary:hover{background:color-mix(in srgb,#fff 3%,transparent)}
/* The open row is one surface with its answer, not a lid on a separate box. */
.faq details[open] summary{background:none;color:var(--gold2)}
.faq details[open]{background:color-mix(in srgb,var(--gold) 4%,transparent)}
.faq .fq-body{padding:0 1.45rem 1.35rem}

/* ---- capture 26: the footer social row -----------------------------------
   This is the one capture that carries a drawn annotation box, and the box is
   around these four icons. They were 40px flat squares at 0.85 opacity with no
   rim and no resting state, which is why they read as placeholders.

   40px is also under the 44px touch floor, so this is a correctness fix as much
   as a look one. */
.foot-social{gap:12px;margin-top:1.25rem}
.foot-social a{width:44px;height:44px;border-radius:13px;opacity:1;
  background:linear-gradient(180deg,color-mix(in srgb,#fff 4%,var(--panel)),var(--panel));
  color:color-mix(in srgb,var(--text) 78%,transparent);
  box-shadow:0 8px 18px -12px rgba(0,0,0,.9);
  transition:color .18s ease,transform .18s ease,box-shadow .18s ease}
.foot-social a:hover{color:var(--gold2);transform:translateY(-2px);
  box-shadow:0 14px 26px -12px rgba(0,0,0,.95)}
.foot-social a:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.foot-social svg{width:20px;height:20px;flex:none}
@media(prefers-reduced-motion:reduce){
  .foot-social a,.foot-social a:hover{transition:none;transform:none}}

/* ---- capture 22, second pass: the call to action --------------------------
   The render showed what the source did not: "See the paid plans" is
   `.btn.ghost`, and site.css defines that as background:transparent with no
   rim, no hover change and no focus style. It is a control with zero affordance
   in every state. That reads as a consequence of capture 7's "no outline
   buttons" taken one step too far, and it is a real defect rather than a taste
   call: nothing on screen says this is clickable.

   Scoped to this panel, NOT to .btn.ghost globally. The ghost variant is used
   across all 15 marketing pages and capture 7 is a different task in this round
   with its own owner. A quiet filled control, never an outline. */
.free-cta .btn.ghost{background:color-mix(in srgb,#fff 7%,transparent);color:var(--text);
  box-shadow:none;transition:background .18s ease,color .18s ease}
.free-cta .btn.ghost:hover{background:color-mix(in srgb,var(--gold) 16%,transparent);color:var(--gold2)}
.free-cta .btn.ghost:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
@media(prefers-reduced-motion:reduce){.free-cta .btn.ghost{transition:none}}
/* The band under the control. The panel padded itself equally on all four sides,
   so the CTA sat with more space beneath it than the list had above it. */
.free-band{padding-bottom:clamp(1.3rem,3vw,1.9rem)}

/* ---- capture 26, second pass: the LEGAL column ---------------------------
   Measured, not guessed: .foot-grid is five columns holding SIX children, so
   Legal wraps to row 2 column 1. Row 1 is 358px tall because the longest link
   column sets it, which leaves Legal sitting alone under the brand with about
   1090px of empty footer to its right. Empty space that large is not restraint,
   it is a wrap nobody noticed.

   Six columns puts every child on one row. The brand keeps its wider track. */
@media(min-width:1041px){
  .foot-grid{grid-template-columns:1.55fr repeat(5,1fr);align-items:start}}
/* Between 721 and 1040 the sheet already drops the brand onto its own row and
   uses four columns, which leaves the same orphan with five link columns. */
@media(max-width:1040px) and (min-width:721px){
  .foot-grid{grid-template-columns:repeat(5,1fr)}}

/* ---- capture 23, second pass: the equalised row on one column ------------
   Measured at eight widths rather than eyeballed. The #471 round set
   `#rewards .grid.g3{grid-auto-rows:1fr}` so that two cards sharing a ROW end
   on the same edge, which is right. But grid-auto-rows sizes EVERY row to the
   tallest, and site.css collapses .grid.g3 to one column at 560px, where there
   is no row to match. Result at 320: every card forced to 153px while its
   content ended between 90 and 132, so up to 41px of dead space under six cards
   in a row, on the narrowest screen, which is the one capture 23 asked about.
   Above 560 it stays 1fr: there the trailing space is the card's own padding. */
@media(max-width:560px){#rewards .grid.g3{grid-auto-rows:auto}}

/* ===== Giveaway on phones =================================================================
   Owner request 2026-08-21: "make this section better: a bit smaller, more premium, on one
   line, with smaller fonts". The card had no small-screen type scale at all -- it went from
   the 720px padding step straight to the base rules, so a 375px phone read the same .9rem
   and 1rem sizes a 700px tablet did, inside 22px of padding. Everything below is scale and
   rhythm only: no colour, no token and no desktop rule is touched, and the composition is
   unchanged.

   "On one line" is read as the repeated element it is worst on: each prize row. One of three
   otherwise identical rows growing a second line is the thing that reads cheap. The title is
   brought down far enough to hold one line in Latin as well.

   SECOND COPY, AND THE ONE THAT WINS. This component is defined twice: site/assets/site.css
   carries the same block, and index.html and for-users.html load extras.css AFTER site.css,
   so on those two pages every duplicated property here beats it. The three other pages that
   render a giveaway (for-business, preview, scoring) do not load extras.css and are served by
   the site.css copy. The two blocks are therefore deliberately identical; dropping either one
   gives the same component two different mobile scales depending on the page. Cost of finding
   this out: one whole build-and-measure cycle, because the site.css block measured as having
   no effect at all. Filed as its own queue task. Keep them in step, or delete one copy of the
   component and repoint the three pages.

   The CTA is deliberately NOT shrunk. It is the only tap target in here and already sits near
   the 44px floor, so it gets an explicit min-height instead of a smaller padding. */


/* ---- #who trio list, second pass (owner: "fix this check mark and text, make them
   smaller") -----------------------------------------------------------------------
   The 2026-08-12 pass took the copy down to .815rem but the tick went the other way in the
   capture-2 block below it: 16px with a 2px pad and a tinted disc. On desktop the page runs
   at html{font-size:90%}, so .815rem is 11.7px of text sitting next to a 16px disc, i.e. the
   confirmation mark is taller than the cap height of the sentence it confirms. That is what
   reads as "too big": not the disc on its own, the ratio.

   Both come down and the ratio comes with them. The disc goes 16px -> 13px with a 1.5px pad,
   so the glyph inside it stays the same proportion of the circle and does not turn into a
   dot. The copy steps one notch to .78rem/1.5 - the leading is opened as the size drops, the
   same trade the earlier pass made, so a wrapped two-line bullet still reads as one item.

   The hanging indent is retuned rather than left alone: it was 1.25rem against a 16px disc,
   which left about 2px of gutter, and shrinking only the disc would have widened that gap
   into the text column. 1.3rem against a 13px disc puts ~6px between mark and word on
   desktop and ~8px on a phone, where the root is not scaled. The chip follows the sentence
   down so it stays an aside rather than becoming the loudest thing on the line. */
.trio-list li{font-size:.78rem;line-height:1.5;padding-inline-start:1.3rem}
.trio-card .trio-list li > svg{width:13px;height:13px;padding:1.5px;margin-top:0}
.trio-list li svg{top:.36em}
.trio-soon{font-size:.54rem;padding:.06rem .34rem}

/* ===== BORDERLESS PASS, extras (owner rule, 2026-08-23) ==============================
   The companion to the block at the end of site.css. It lives here rather than there because
   extras.css loads AFTER site.css on the four pages that use it (index, for-users, services,
   whatsapp), so a rule in site.css naming these components loses every equal-specificity
   contest to the originals above.

   Same rule as the other block: a rim is removed only where it was fencing a container, a chip
   or a badge, and its job moves into the fill. Rings that ARE the thing stay:
   .pl-ripple (a ripple), .pre-sun .pl-orb::after (a halo), .cr-flow::after (an arrow head made
   of two borders), .pts-card .pc-bar b (a slider knob on a track). */

/* Chat demo. The rim goes and the GROUND STAYS EXACTLY AS IT WAS, which is the correction to
   the first version of this block: it replaced the hardcoded dark grounds with themed ones
   (color-mix over --panel2), and in light theme that turned a dark green bubble pale while its
   text stayed the light green and white it was drawn for. Measured with tools/contrast-proof.mjs
   before and after: it put "Table booked" at 1.18:1, "8:00 PM" and "4 people" at 1.21:1, and
   both captions at 1.11:1. Six readings, all mine, none of them there before the pass.
   These are a picture of a WhatsApp thread. Their ground is literal and fixed in BOTH themes on
   purpose, exactly like .vpw-offer below, and a borderless pass has no business theming it. */
.wai-card{border:0}
.wai-cap{border:0}

/* Badges and chips: the weight moves off the rim and into the fill. */
.cr-facts .f-ic{border:0;background:color-mix(in oklab,var(--gold) 20%,transparent)}
.cr-facts .soon-badge{border:0;background:color-mix(in oklab,var(--gold) 24%,transparent)}
.gcine-kick{border:0;background:color-mix(in srgb,var(--gold) 20%,transparent)}
.gcine-chip{border:0;background:color-mix(in srgb,var(--gold) 16%,transparent)}
/* Same correction, and this rule had said so in its own comment before I overwrote it: the pill
   sits on a 55% #0b1418 scrim over a photograph, so its ground is dark in BOTH themes and its
   gold is a literal bright gold rather than the token, which resolves to the light theme's dark
   gold. Theming the ground put bright gold on pale gold at 1.38:1. The rim comes off and the
   scrim goes UP instead, which is what the rim was helping to do: hold the pill off the photo. */
.vpw-offer{border:0;background:color-mix(in srgb,#0b1418 68%,transparent)}
.pts-card .pc-ic{border:0;background:color-mix(in oklab,var(--gold2) 26%,transparent)}
/* The numbered step marker was a gold ring around a numeral, twice: once on the ::before and
   once on the numeral itself. One filled disc reads as a step; two concentric rings read as a
   target. */
.cr-step::before{border:0}
.cr-step > .n{border:0;background:color-mix(in oklab,var(--gold2) 26%,var(--panel2))}

/* The toast was a gold-outlined box floating over the page. Elevation alone lifts it off what
   is underneath, without drawing the box.

   FIXED 2026-09-03 (queue #807). This read `box-shadow:none 0 22px 46px -20px rgba(0,0,0,.9)`.
   A `none` in front of a shadow list is not valid box-shadow syntax, so the parser dropped the
   whole declaration: measured on the live page, this rule's box-shadow read back as absent
   through the CSSOM while the toast still painted a shadow.

   WHAT THAT ACTUALLY COST is smaller than it looks, and worth stating because the queue entry
   guessed it wrong. The toast did NOT ship shadowless: `.kx-toast` is declared twice in this
   file, and with the later declaration dropped the earlier one at the top still applied, so the
   computed value was `0 16px 48px rgba(0,0,0,.4)` - the PRE-borderless-pass shadow. The defect
   is that this pass never landed, not that the toast had no elevation. Measured on
   dist/index.html, which is a page that really links this stylesheet.

   The old comment promised "a gold-lit top edge" as well. That is `inset 0 1px 0 <colour>`, a
   lit edge is still an edge, and the borderless law bans it by name; it was never in the code
   either. The comment is corrected rather than the code, so nobody adds it back to match. */
.kx-toast{border:0;box-shadow:0 22px 46px -20px rgba(0,0,0,.9)}

/* An FAQ divider is a typographic rule between list items, not a container edge, so it stays.
   It was mixed off --line, which is a surface token; re-tinted off text it holds the same
   weight in both themes without being tied to the panel colour. */
.faq details + details{border-top:0}

/* ---- #who trio list, third pass (#803) ------------------------------------------------
   Owner, 2026-09-01, on a capture of the business card: "type a bit smaller, give the list
   more width, every bullet on one line". The worst offender was the WhatsApp bullet, which
   wrapped with the Latin "AI" alone on the second line: a bidi orphan, because a Latin run at
   the end of an RTL sentence is the piece the line breaker is most willing to push down.

   Three levers, in the order they were spent, so the copy only pays for what the layout
   could not:

   1. WIDTH first. The card carried 1.45rem of inline padding and the list hung its tick in a
      1.3rem margin, so a 375px phone gave the sentence 256px of the 375 it started with. The
      padding drops to 1.15rem and the hanging indent to 1rem, which is +14px of text column on
      a phone and +13px on desktop. The photo's negative margin has to move WITH the padding or
      it stops bleeding to the card edge, so -1.45rem becomes -1.15rem in the same change; the
      2.2/1 aspect set in #801 is untouched.
   2. SIZE second, and only one step: .78rem -> .74rem. That is 11.1px on desktop, where the
      root runs at 94%, and 11.8px on a phone. It stays clear of the 10.5px micro-label floor
      on purpose. This is Arabic script, which reads lighter and smaller than Latin at the same
      px, so a second step down would have bought a line at the cost of the list being read at
      all. The tick follows it down 13px -> 12px so the ratio the second pass tuned holds.
   3. COPY last, in extras.js, and only for the keys still over their column after 1 and 2.

   The breakpoint move is part of the width lever. Three columns were held down to 981px, where
   a card measures 293px and the sentence gets 230px: narrower than the same card on a 375px
   phone. That band is iPad landscape, so it is not theoretical. One column from 1140px down
   gives the list the full card, which is what the 980 rule was already doing 40px lower. */
@media (max-width:1140px){ .trio-grid{ grid-template-columns:1fr } }
.trio-card{ padding-inline:1.15rem }
.trio-photo{ margin-inline:-1.15rem }
.trio-list li{ font-size:.74rem; line-height:1.52; padding-inline-start:1rem }
.trio-card .trio-list li > svg{ width:12px; height:12px; padding:1.5px }
.trio-list li svg{ top:.4em }
.trio-soon{ font-size:.52rem; padding:.05rem .32rem; margin-inline-start:.3rem }

/* ---------- audience trio: the mark sits BESIDE the heading, and loses its tile ----------
   Owner request 2026-09-04. Three changes, and the first is the one that carries it.

   1. .trio-head puts the icon and the h3 on ONE ROW. Done by wrapping them in the markup
      rather than by switching .trio-card to a grid, and that is not a style preference:
      .trio-card is a flex COLUMN whose `.trio-go{margin-top:auto}` is what lines the links
      up on a common floor across three cards of different lengths. Grid has no equivalent
      of that auto margin here, so the CSS-only version would have quietly cost the row of
      links its alignment to save a span.
   2. The tinted 56px tile and its 6px accent halo are gone, so the glyph carries the accent
      by itself. That is also why it is drawn slightly larger than the 28px it was: a mark
      that used to read against a fill has to hold the eye without one.
   3. The hover lift moves from the icon to the whole head row, so the mark and its label
      travel together instead of the icon sliding out from under its own heading.

   These rules sit at the end of the file on purpose. .trio-ic is styled in three earlier
   places (the 104px original, the 6px halo, and the 56px tile), and a fix placed above any
   of them would be undone lower in this same file. */
.trio-head{ display:flex; align-items:center; gap:.62rem; margin:.4rem 0 0;
  transition:transform .28s cubic-bezier(.22,1,.36,1) }
.trio-card .trio-ic{
  width:auto; height:auto; border-radius:0;
  background:none; box-shadow:none; color:var(--accent);
  display:grid; place-items:center;
  /* An inline SVG in a flex row is a flex item and WILL be squeezed by a long heading
     beside it. Without this the mark loses width before the text wraps. */
  flex:none }
.trio-card .trio-ic svg{ width:30px; height:30px; stroke-width:1.7 }
/* The heading's own top margin now belongs to the row, or it pushes the text off the
   icon's centre line. */
.trio-card .trio-head h3{ margin:0 }
.trio-card:hover .trio-ic{ transform:none }
.trio-card:hover .trio-head{ transform:translateY(-2px) }
@media (prefers-reduced-motion:reduce){
  .trio-head{ transition:none }
  .trio-card:hover .trio-head{ transform:none }
}
