/* ====================================
   VOICEBASKET — LANDING PAGE STYLES
   ==================================== */

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
  --green:      #16a34a;
  /* Brand green is #16a34a and stays #16a34a. But as TEXT it failed WCAG AA on
     47 of the 49 places it was used - 2.70-3.30:1 against a 4.5 requirement -
     because it is a mid-tone sitting on white and on its own pale tints.
     #166534 is the same hue (142.8 vs 142.1 degrees) taken darker, and clears
     4.5:1 on every measured background with margin (worst case 5.83:1 on the
     .10 tint over --bg). --green-d/#15803d was tried first and is NOT enough:
     it lands at 4.10:1 on that same background. Use this for text only;
     use --green for fills, borders and icons. Audit #11 follow-up, ADR-015. */
  --green-text: #166534;
  --green-l:    #22c55e;
  /* WHITE-ALPHA FLOOR - ADR-030, 2026-09-03.
     Text on this site's dark grounds is rgba(255,255,255,a). The grounds are not
     one colour: the footer is #0f2027 but the hero/how panels are green-tinted and
     lighter, up to #264539. A floor has to clear the LIGHTEST of them.
     Minimum passing alpha measured per ground: #264539 needs .56, #2a433c .56,
     #254136 .55, #163129 .49, #0f2027 .46.
     => any alpha used as a TEXT colour is >= .6, which lands 4.89-6.75:1 everywhere.
     .55 was not enough (4.44 on #264539). .75 would also work but collapses
     .6/.65/.7 into one value and flattens the scale for no gain.
     Borders and fills are NOT covered: .btn-outline's .4 border measures 3.68:1,
     which is what WCAG 1.4.11 asks of a UI boundary, and it stays as it is.
     The one text exemption is .arch-arrow - see the rule. */
  --green-d:    #15803d;
  --teal:       #0d9488;
  --wa:         #25D366;
  --bg:         #f9fafb;
  --bg2:        #f3f4f6;
  --surface:    #ffffff;
  --border:     #e5e7eb;
  --text1:      #111827;
  --text2:      #374151;
  --text3:      #6b7280;
  --text4:      #374151;
  /* audit #11: was #9ca3af, which failed WCAG AA on every one of its 43 uses
     (measured 1.3-2.54:1 against real composited pixels). Owner chose #374151. */
  --radius-sm:  8px;
  --radius-md:  14px;
  --radius-lg:  20px;
  --radius-xl:  28px;
  --shadow-sm:  0 1px 3px rgba(0,0,0,.08);
  --shadow-md:  0 4px 16px rgba(0,0,0,.1);
  --shadow-lg:  0 12px 40px rgba(0,0,0,.12);
  --transition: .22s ease;
}
html{scroll-behavior:smooth;scroll-padding-top:76px}
body{font-family:'Inter',system-ui,sans-serif;font-size:16px;line-height:1.65;color:var(--text2);background:var(--bg);-webkit-font-smoothing:antialiased;overflow-x:hidden}
h1,h2,h3,h4{font-family:'Plus Jakarta Sans',sans-serif;color:var(--text1);line-height:1.22}
h1{font-size:clamp(2.2rem,5vw,3.8rem);font-weight:800}
h2{font-size:clamp(1.75rem,3.5vw,2.6rem);font-weight:700}
h3{font-size:1.1rem;font-weight:600}
p{color:var(--text3)}
a{text-decoration:none;color:inherit;transition:color var(--transition)}
ul{list-style:none}
img,svg{display:block}

.container{max-width:1180px;margin:0 auto;padding:0 24px}
.section{padding:88px 0}

.gradient-text{
  background:linear-gradient(135deg,#16a34a,#0d9488 50%,#059669);
  -webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text
}

/* Buttons */
.btn{display:inline-flex;align-items:center;gap:8px;padding:11px 22px;border-radius:var(--radius-sm);font-size:.88rem;font-weight:600;font-family:'Inter',sans-serif;border:none;cursor:pointer;transition:all var(--transition);white-space:nowrap}
/* --green-d, not --green: white on #16a34a is 3.30:1 and this label is 14.1px.
   ADR-025 set the same precedent for .od-btn.confirm. The glow keeps the brand
   green so the button still reads as brand-coloured. Hover goes one step darker
   again - it used to land on --green-d, which would now be a no-op. */
.btn-primary{background:var(--green-d);color:#fff;box-shadow:0 2px 10px rgba(22,163,74,.3)}
.btn-primary:hover{background:var(--green-text);transform:translateY(-2px);box-shadow:0 6px 20px rgba(22,163,74,.4)}
.btn-outline{background:transparent;color:var(--green-text);border:1.5px solid var(--green)}
.btn-outline:hover{background:rgba(22,163,74,.06);transform:translateY(-2px)}
.btn-ghost{background:rgba(255,255,255,.12);color:#fff;border:1.5px solid rgba(255,255,255,.2);backdrop-filter:blur(6px)}
.btn-ghost:hover{background:rgba(255,255,255,.2);transform:translateY(-2px)}
.btn-lg{padding:14px 30px;font-size:1rem;border-radius:var(--radius-md)}
.btn-full{width:100%;justify-content:center}

/* Tags */
.sec-tag{display:inline-block;font-size:.75rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--green-text);background:rgba(22,163,74,.08);border:1px solid rgba(22,163,74,.2);padding:5px 13px;border-radius:100px;margin-bottom:14px}

.sec-header{text-align:center;max-width:680px;margin:0 auto 56px}
.sec-header h2{margin-bottom:12px}
.sec-header p{font-size:1rem}

/* AOS */
[data-aos]{opacity:0;transform:translateY(22px);transition:opacity .55s ease,transform .55s ease}
[data-aos].visible{opacity:1;transform:translateY(0)}
[data-aos][data-delay="100"]{transition-delay:.1s}
[data-aos][data-delay="200"]{transition-delay:.2s}
[data-aos][data-delay="300"]{transition-delay:.3s}
[data-aos][data-delay="400"]{transition-delay:.4s}
[data-aos][data-delay="500"]{transition-delay:.5s}
[data-aos][data-delay="600"]{transition-delay:.6s}
[data-aos][data-delay="700"]{transition-delay:.7s}

/* ===== NAVBAR ===== */
.navbar{position:fixed;top:0;left:0;right:0;z-index:1000;height:72px;display:flex;align-items:center;transition:all .3s ease;background:transparent}
.navbar.scrolled{background:rgba(255,255,255,.95);backdrop-filter:blur(16px);border-bottom:1px solid var(--border);box-shadow:var(--shadow-sm)}
.nav-wrap{display:flex;align-items:center;justify-content:space-between;width:100%}
.logo{display:flex;align-items:center;gap:10px}
.logo-icon svg{flex-shrink:0}
.logo-text{font-family:'Plus Jakarta Sans',sans-serif;font-size:1.2rem;font-weight:700;color:var(--text1);transition:color .3s ease}
/* White text/links when over dark hero */
.navbar:not(.scrolled) .logo-text{color:#fff}
.navbar:not(.scrolled) .nav-link{color:rgba(255,255,255,.7)}
.navbar:not(.scrolled) .nav-link:hover{color:#fff;background:rgba(255,255,255,.08)}
.navbar:not(.scrolled) .nav-link.nav-demo{color:var(--green-l)}
.navbar:not(.scrolled) .btn-outline{color:#fff;border-color:rgba(255,255,255,.4)}
.navbar:not(.scrolled) .hamburger span{background:#fff}
.logo-accent{color:var(--green)}
.nav-links{display:flex;align-items:center;gap:4px}
/* white-space:nowrap is the part that actually fixes the crowding. The seventh
   link (Testimonials) pushed the row past the space .nav-links is given, and
   because the links are flex items they shrank and wrapped their own text -
   measured up to FOUR lines per link at 1121px, and three even at 1920px. The
   72px bar never grew, so an overflow check passed while the bar looked a mess.

   Sizing is set by the tightest desktop case, 1121px (just above the 1120px
   collapse), where the row has 1058px to work with. At .88rem/14px the row needs
   1189px. .78rem with 8px padding needs 1046px, leaving 12px of slack; .80rem/8px
   lands on exactly 1058 with none, which is too tight for font-metric variance. */
.nav-link{padding:8px;border-radius:var(--radius-sm);font-size:.78rem;font-weight:500;color:var(--text3);white-space:nowrap;transition:all var(--transition)}
.nav-link:hover{color:var(--text1);background:rgba(0,0,0,.04)}
.nav-link.nav-demo{color:var(--green-text);font-weight:600}
.nav-cta{display:flex;align-items:center;gap:10px}
.hamburger{display:none;flex-direction:column;gap:5px;background:none;border:none;cursor:pointer;padding:6px}
.hamburger span{display:block;width:22px;height:2px;background:var(--text1);border-radius:2px;transition:all var(--transition)}
.hamburger.open span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.hamburger.open span:nth-child(2){opacity:0}
.hamburger.open span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

/* ===== HERO ===== */
.hero{position:relative;background:linear-gradient(160deg,#0f2027 0%,#1a3a2a 40%,#0a1628 100%);min-height:100vh;display:flex;align-items:center;padding:100px 0 80px;overflow:hidden}
.hero-gradient{position:absolute;inset:0;background:radial-gradient(ellipse at 20% 50%,rgba(22,163,74,.15) 0%,transparent 60%),radial-gradient(ellipse at 80% 30%,rgba(13,148,136,.1) 0%,transparent 50%);pointer-events:none}

/* Two-column layout: text left, phone right */
.hero-inner{
  position:relative;z-index:1;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:48px;
}
.hero-text{
  flex:1;
  min-width:0;
  max-width:600px;
}

.hero-tag-row{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin-bottom:24px}
.hero-tag{display:inline-flex;align-items:center;gap:6px;font-size:.82rem;font-weight:600;color:rgba(255,255,255,.7);background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.15);padding:6px 14px;border-radius:100px}
.lang-pills{display:flex;gap:8px;flex-wrap:wrap}
.pill{font-size:.75rem;font-weight:600;color:var(--green-l);background:rgba(22,163,74,.12);border:1px solid rgba(22,163,74,.25);padding:4px 10px;border-radius:100px}

.hero-title{color:#fff;margin-bottom:20px;letter-spacing:-.02em}
.hero-sub{font-size:1.05rem;color:rgba(255,255,255,.65);margin-bottom:32px;line-height:1.75}
.hero-btns{display:flex;gap:14px;flex-wrap:wrap;margin-bottom:40px}

/* Phone column — now a normal flex child, no absolute */
.hero-phone-wrap{
  position:relative;
  flex-shrink:0;
  padding:20px 60px 20px 20px; /* space for the right-side badge */
}
/* Was `@media(max-width:1100px){.hero-phone-wrap{display:none}}` - see ADR-010.
   The stacking rules live *below* .phone-mockup / .phone-badge-*, because they
   override those and CSS resolves equal specificity by source order. */

.phone-mockup{width:280px;background:#1a1f2e;border-radius:36px;border:6px solid #2a3040;box-shadow:0 40px 80px rgba(0,0,0,.5),0 0 0 1px #3a4158;overflow:hidden}
.phone-notch{height:24px;background:#111624;display:flex;align-items:center;justify-content:center}
.phone-notch::before{content:'';width:80px;height:14px;background:#1a1f2e;border-radius:8px}
.phone-screen{background:#ece5dd;min-height:380px}
.wa-header{background:#075e54;color:white;padding:10px 14px;display:flex;align-items:center;gap:10px}
.wa-avatar{width:36px;height:36px;background:#25D366;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:1.1rem}
.wa-name{font-size:.82rem;font-weight:600;line-height:1.2}
.wa-status{font-size:.68rem;color:rgba(255,255,255,.7)}
.wa-messages{padding:12px;display:flex;flex-direction:column;gap:8px}
.wa-msg{display:flex;flex-direction:column;gap:3px}
.wa-msg.customer{align-items:flex-end}
.wa-msg.bot{align-items:flex-start}
.wa-bubble{background:#fff;border-radius:8px;padding:8px 10px;max-width:90%;box-shadow:0 1px 2px rgba(0,0,0,.1)}
.wa-bubble.order-card{background:#fff;font-size:.72rem}
.wa-time{font-size:.65rem;color:#888;padding:0 4px}
.voice-note{display:flex;align-items:center;gap:6px}
.mic-icon{font-size:.9rem}
.waveform{display:flex;align-items:center;gap:2px;height:20px}
.waveform span{display:inline-block;width:3px;background:var(--wa);border-radius:2px;animation:wave .8s ease-in-out infinite}
.waveform span:nth-child(1){height:4px;animation-delay:0s}
.waveform span:nth-child(2){height:12px;animation-delay:.1s}
.waveform span:nth-child(3){height:8px;animation-delay:.2s}
.waveform span:nth-child(4){height:16px;animation-delay:.3s}
.waveform span:nth-child(5){height:10px;animation-delay:.4s}
.waveform span:nth-child(6){height:14px;animation-delay:.5s}
.waveform span:nth-child(7){height:6px;animation-delay:.6s}
.waveform span:nth-child(8){height:12px;animation-delay:.7s}
.waveform span:nth-child(9){height:8px;animation-delay:.8s}
@keyframes wave{0%,100%{transform:scaleY(1)}50%{transform:scaleY(1.5)}}
.duration{font-size:.68rem;color:#666}
.order-header{font-weight:700;color:var(--green-text);margin-bottom:6px;font-size:.78rem}
.order-item{display:flex;align-items:center;gap:6px;padding:2px 0;font-size:.72rem;color:var(--text2);border-bottom:1px solid #f0f0f0}
.order-total{font-size:.72rem;font-weight:600;color:var(--green-text);margin-top:6px;text-align:right}
.phone-badge{position:absolute;background:rgba(255,255,255,.97);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.3);border-radius:var(--radius-md);padding:10px 16px;display:flex;align-items:center;gap:10px;font-size:.8rem;box-shadow:var(--shadow-lg);color:var(--text1);white-space:nowrap}
.phone-badge span{font-size:1.4rem}
.phone-badge strong{font-weight:700;color:var(--green-text);font-size:1rem}
/* Positioned relative to .hero-phone-wrap (position:relative) */
.phone-badge-1{right:-10px;bottom:30px;animation:float 4s ease-in-out infinite}
.phone-badge-2{right:-10px;top:40px;animation:float 4s ease-in-out infinite 2s}
@keyframes float{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}

/* ADR-010: stack the phone mockup under the copy below 1120px instead of hiding
   it. Placed here, after .phone-mockup and .phone-badge-*, so these win on source
   order. Three things are needed, not one:
   1. .hero-inner min-width:0 - .hero is display:flex and .hero-inner is its flex
      item, so min-width:auto floored it at the 360px wrap's min-content. That is
      why the container measured 408px inside a 320px viewport.
   2. .hero-phone-wrap needs a *definite* width before the phone's percentage can
      resolve; shrink-to-fit + a percentage child is circular and falls back to auto.
   3. the badges sit at right:-10px, 10px outside the wrap, so pull them in when
      the wrap is narrower than its natural 360px. */
@media(max-width:1120px){
  .hero-inner{flex-direction:column;align-items:flex-start;min-width:0}
  .hero-text{max-width:100%}
  .hero-phone-wrap{width:100%;max-width:360px}
  .phone-mockup{width:min(280px,100%)}
}
@media(max-width:440px){
  .hero-phone-wrap{padding-right:44px}
  .phone-badge-1,.phone-badge-2{right:0}
  .phone-badge{padding:8px 12px;font-size:.74rem}
}

/* Stats */
.hero-stats{display:flex;align-items:center;gap:28px;flex-wrap:wrap;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-lg);padding:20px 28px;backdrop-filter:blur(10px)}
.hstat{display:flex;flex-direction:column;gap:4px}
.hstat .hstat-row{display:flex;align-items:baseline;gap:2px}
.hstat-num{font-family:'Plus Jakarta Sans',sans-serif;font-size:1.5rem;font-weight:700;color:#fff;line-height:1}
.hstat .hstat-row>span{font-size:1.1rem;font-weight:700;color:var(--green-l)}
.hstat-lbl{font-size:.72rem;color:rgba(255,255,255,.6)}
.hstat-div{width:1px;height:36px;background:rgba(255,255,255,.15)}

/* ===== PROBLEM ===== */
.problem{background:var(--surface)}
.problems-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.prob-card{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-lg);padding:28px;display:flex;flex-direction:column;gap:12px;transition:all .3s ease}
.prob-card:hover{transform:translateY(-4px);border-color:rgba(22,163,74,.3);box-shadow:var(--shadow-md)}
.prob-icon{font-size:2rem;line-height:1}
.prob-card h3{color:var(--text1);font-size:1rem}
.prob-card p{font-size:.88rem;line-height:1.65}

/* ===== HOW IT WORKS ===== */
.how{background:linear-gradient(160deg,#0f2027,#1a3a2a 50%,#0a1628)}
.how .sec-tag,.how .sec-header h2,.how .sec-header p{color:rgba(255,255,255,.9) !important}
.how .sec-header p{color:rgba(255,255,255,.6) !important}

/* Arch flow */
.arch-flow{display:flex;align-items:flex-start;gap:0;flex-wrap:wrap;justify-content:center;margin-bottom:56px}
/* padding was `20px 16px`. The six steps + five arrows needed 1157px but the
   .container caps usable width at 1180-48 = 1132px at ANY viewport, so the row
   could never fit and always wrapped 5+1 with a dangling arrow - even at 1920px.
   11px sides save 10px per step (60px total), bringing the row to ~1097px. */
.arch-step{display:flex;flex-direction:column;align-items:center;gap:10px;padding:20px 11px;min-width:110px;text-align:center}
.arch-icon{width:60px;height:60px;border-radius:16px;display:flex;align-items:center;justify-content:center;box-shadow:0 8px 24px rgba(0,0,0,.3)}
.arch-label{font-size:.85rem;font-weight:600;color:#fff}
.arch-sub{font-size:.72rem;color:rgba(255,255,255,.6);line-height:1.4}
.arch-langs{display:flex;gap:4px;flex-wrap:wrap;justify-content:center}
.arch-langs span{font-size:.65rem;background:rgba(22,163,74,.2);color:var(--green-l);border:1px solid rgba(22,163,74,.3);padding:2px 7px;border-radius:100px}
/* Exempt from the .6 floor (ADR-030): this is a connective glyph between pipeline
   steps, not a label. At 24px it needs 3:1 rather than 4.5, and .6 would turn a
   faint separator into a prominent element. Each step is labelled in text, so the
   arrow adds direction, not information.
   .4, not .35: the five arrows sit across a gradient and the LIGHTEST ground under
   one of them is #1a392a, where .35 gives 2.93 - still short. .4 gives 3.37-3.54
   across all five. Measure the lightest ground, not a sampled one. */
.arch-arrow{font-size:1.5rem;color:rgba(255,255,255,.4);padding:0 4px;margin-top:30px}
/* ADR-011. Usable width is min(1180,viewport) - 48, so even after the padding trim
   above the row (~1097px) only fits from ~1145px up. Below that, stack vertically
   and hide the arrows - the same treatment the <=768px block already used, just
   applied wherever the row genuinely does not fit. 1200px, not 1145px, to leave
   margin for font-metric variance. Above it: one clean row, no orphan, no arrow
   pointing at nothing. */
@media(max-width:1199px){
  .arch-flow{flex-direction:column;align-items:center}
  .arch-arrow{display:none}
}

/* Sample output */
.sample-output{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-xl);overflow:hidden}
.so-header{display:flex;align-items:center;gap:16px;padding:16px 24px;background:rgba(255,255,255,.04);border-bottom:1px solid rgba(255,255,255,.08)}
.so-badge{font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;background:rgba(22,163,74,.2);color:var(--green-l);border:1px solid rgba(22,163,74,.3);padding:3px 10px;border-radius:100px}
.so-title{font-size:.9rem;font-weight:600;color:#fff}
.so-lang{font-size:.8rem;color:rgba(255,255,255,.6);margin-left:auto}
.so-body{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:0}
.so-input,.so-output{padding:28px}
.so-label{font-size:.72rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.6);margin-bottom:10px}
.so-text{font-size:1rem;color:#fff;line-height:1.6;margin-bottom:8px}
.so-transl{font-size:.85rem;color:rgba(255,255,255,.6);font-style:italic}
.so-arrow{display:flex;flex-direction:column;align-items:center;gap:8px;font-size:.75rem;color:var(--green-l);font-weight:600;padding:0 16px;text-align:center}
.so-json{background:rgba(0,0,0,.4);border:1px solid rgba(255,255,255,.08);border-radius:var(--radius-md);padding:20px;font-family:'Courier New',monospace;font-size:.75rem;line-height:1.7;color:#a8d8b4;overflow-x:auto}

/* ===== FEATURES ===== */
.features{background:var(--surface)}
.features-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.feat-card{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-lg);padding:24px;display:flex;flex-direction:column;gap:12px;transition:all .3s ease}
.feat-card:hover{transform:translateY(-4px);border-color:rgba(22,163,74,.3);box-shadow:var(--shadow-md)}
.feat-card.big{grid-column:span 2}
.feat-icon{font-size:1.8rem;line-height:1}
.feat-card h3{color:var(--text1);font-size:1rem}
.feat-card p{font-size:.87rem;line-height:1.65}
.feat-langs{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}
.feat-langs span{font-size:.75rem;font-weight:600;color:var(--green-text);background:rgba(22,163,74,.08);border:1px solid rgba(22,163,74,.15);padding:3px 10px;border-radius:100px}
.feat-progress{display:flex;flex-direction:column;gap:10px;margin-top:8px}
.fp-row{display:grid;grid-template-columns:1fr 1fr auto;align-items:center;gap:10px;font-size:.78rem;color:var(--text3)}
.fp-bar{height:8px;background:var(--border);border-radius:100px;overflow:hidden}
.fp-bar div{height:100%;background:linear-gradient(90deg,var(--green),var(--teal));border-radius:100px;transition:width 1s ease}

/* The fill's target width is inline (style="width:85%"). To animate up to it,
   hold it at zero while the bar is waiting and release it when JS adds .fp-in;
   the existing `transition:width 1s ease` then does the work. !important is
   needed to beat the inline width, and :not(.fp-in) is what releases it -
   nothing has to be un-set.

   Width rather than transform:scaleX: scaling would squash the 100px border-
   radius into an ellipse for the duration of the animation.

   .fp-anim is added by JS, so with scripting off or broken the bars are simply
   painted at full width - the failure mode is 'no animation', never 'no bars'.
   Audit #16/#17 follow-up. */
.fp-bar.fp-anim:not(.fp-in) div{width:0!important}
.fp-row span:last-child{font-weight:600;color:var(--green-text);width:36px;text-align:right}

/* ===== PRICING ===== */
.pricing{background:var(--bg2)}
/* minmax(0,1fr), not 1fr: an fr track carries min-width:auto, so each column is
   floored at its own min-content width and the three cards stop sharing the row
   equally. Between 769px and 781px that produced tracks of 232/241/236px inside
   a 769px viewport - up to 13px of overflow, and unequal cards either side of it.
   Same root cause as #5 and the #9 view overflow. */
.pricing-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px;margin-bottom:24px;padding-top:16px;/* ensure "Most Popular" badge isn't clipped */}
.price-card{background:var(--surface);border:1.5px solid var(--border);border-radius:var(--radius-xl);padding:36px;display:flex;flex-direction:column;gap:20px;transition:all .3s ease;position:relative}
.price-card:hover{transform:translateY(-6px);box-shadow:var(--shadow-lg)}
.price-card.featured{border-color:var(--green);box-shadow:0 0 0 4px rgba(22,163,74,.1)}
.pc-popular{position:absolute;top:-12px;left:50%;transform:translateX(-50%);background:var(--green-d);color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;padding:4px 14px;border-radius:100px;white-space:nowrap}
.pc-badge{font-size:.78rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text3)}
.pc-price{display:flex;align-items:baseline;gap:4px}
.pc-curr{font-size:.9rem;font-weight:600;color:var(--text3)}
.pc-num{font-family:'Plus Jakarta Sans',sans-serif;font-size:2.8rem;font-weight:800;color:var(--text1);line-height:1}
.pc-per{font-size:.85rem;color:var(--text4)}
.pc-desc{font-size:.88rem;line-height:1.6;border-bottom:1px solid var(--border);padding-bottom:20px}
.pc-list{display:flex;flex-direction:column;gap:10px;flex:1}
.pc-list li{font-size:.87rem;color:var(--text2);display:flex;align-items:center;gap:8px}
.pc-list li.dim{color:var(--text4)}
.pricing-note{text-align:center;font-size:.9rem;color:var(--text3)}

/* ===== TESTIMONIALS ===== */
.testi{background:var(--surface)}
.testi-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.testi-card{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-xl);padding:32px;display:flex;flex-direction:column;gap:16px;transition:all .3s ease}
.testi-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-md)}
.t-stars{color:#f59e0b;letter-spacing:3px}
.testi-card p{font-size:.9rem;line-height:1.75;color:var(--text2);flex:1}
.t-auth{display:flex;align-items:center;gap:12px}
.t-av{width:40px;height:40px;background:linear-gradient(135deg,var(--green),var(--teal));color:#fff;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:.78rem;font-weight:700;flex-shrink:0}
.t-auth strong{font-size:.9rem;display:block;color:var(--text1)}
.t-auth small{font-size:.78rem;color:var(--text4)}

/* ===== CONTACT ===== */
.contact{background:var(--bg2)}
.contact-wrap{display:grid;grid-template-columns:1fr 1.4fr;gap:72px;align-items:start}
.contact-info{display:flex;flex-direction:column;gap:20px}
.contact-info h2{margin-bottom:0}
.contact-info>p{font-size:.98rem;line-height:1.75}
.contact-perks{display:flex;flex-direction:column;gap:12px}
.perk{display:flex;align-items:center;gap:10px;font-size:.9rem;font-weight:500;color:var(--text1)}
.contact-reach{display:flex;flex-direction:column;gap:14px;margin-top:4px}
.reach-item{display:flex;align-items:center;gap:14px}
.reach-icon{width:40px;height:40px;background:rgba(22,163,74,.1);border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;font-size:1.1rem}
.reach-lbl{font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;color:var(--text4)}
.reach-val{font-size:.92rem;font-weight:500;color:var(--text1)}
.contact-form{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-xl);padding:40px;display:flex;flex-direction:column;gap:20px;box-shadow:var(--shadow-md)}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.fg{display:flex;flex-direction:column;gap:7px}
.fg.full{grid-column:span 2}
/* .fg sets display:flex, and an author declaration beats the UA's
   [hidden]{display:none}, so the hidden attribute alone would not hide a .fg -
   the conditional 'Other language' field would simply always be on screen. */
.fg[hidden]{display:none}
label{font-size:.8rem;font-weight:500;color:var(--text2)}
input,select,textarea{background:var(--bg);border:1.5px solid var(--border);border-radius:var(--radius-sm);padding:11px 14px;color:var(--text1);font-family:'Inter',sans-serif;font-size:.9rem;transition:border-color var(--transition),box-shadow var(--transition);outline:none;width:100%;-webkit-appearance:none}
/* --text3, not --text4. #11 moved --text4 to #374151, which is also the body
   text colour, so a placeholder became indistinguishable from a filled-in value.
   --text3 #6b7280 reads as 4.63:1 on the field - well past the 3:1 that
   placeholders need, and visibly lighter than the --text1 a user actually types. */
input::placeholder,textarea::placeholder{color:var(--text3)}
input:focus,select:focus,textarea:focus{border-color:var(--green);box-shadow:0 0 0 3px rgba(22,163,74,.1)}
textarea{resize:vertical;min-height:100px}
.check-group{display:flex;flex-wrap:wrap;gap:16px;padding:8px 0}
.checkbox{display:flex;align-items:center;gap:6px;font-size:.88rem;color:var(--text2);cursor:pointer}
/* The `input,select,textarea` rule above sets -webkit-appearance:none for text
   fields and selects, and it caught checkboxes too - which strips the native box
   AND its tick, so a checked box rendered identically to an unchecked one. The
   accent-color here is the giveaway that the native widget was always intended:
   accent-color only colours a native control, so it had been inert all along.
   Restore appearance, and undo the text-field padding/border/background that had
   stretched a 16px square into a 30x24 rectangle. */
.checkbox input{appearance:auto;-webkit-appearance:auto;width:16px;height:16px;
  flex:none;padding:0;border:0;border-radius:0;background:none;
  accent-color:var(--green);cursor:pointer}
.form-ok{display:none;align-items:center;gap:10px;font-size:.9rem;color:var(--green-text);background:rgba(22,163,74,.06);border:1px solid rgba(22,163,74,.2);border-radius:var(--radius-sm);padding:12px 16px}
.form-ok.show{display:flex}
/* Failure counterpart to .form-ok, mirroring it line for line so the two read
   as a pair. #b91c1c is NOT a new colour: it is the negative-state red this
   product already uses in dashboard.css for the out-of-stock bar and badge
   (with the same rgba(185,28,28,...) tint behind it). Reusing an existing
   meaning rather than introducing a hue - owner-approved, see ADR-033. */
.form-err{display:none;align-items:center;gap:10px;font-size:.9rem;color:#b91c1c;background:rgba(185,28,28,.06);border:1px solid rgba(185,28,28,.2);border-radius:var(--radius-sm);padding:12px 16px}
.form-err.show{display:flex}
.form-err a{color:#b91c1c;text-decoration:underline}
/* Honeypot wrapper. display:none rather than the `hidden` attribute, because
   some bots skip [hidden] but fill anything else they find in the DOM. */
.hp-field{display:none}

/* ===== FOOTER ===== */
.footer{background:#0f2027;padding-top:64px}
.footer-inner{display:grid;grid-template-columns:1fr 1.5fr;gap:72px;padding-bottom:56px}
.footer-brand{display:flex;flex-direction:column;gap:14px}
.footer-brand .logo-text{color:#fff}
.footer-brand p{font-size:.88rem;color:rgba(255,255,255,.6);max-width:240px}
/* These inherited --text2 (#374151) from body onto the #0f2027 footer: 1.62:1,
   effectively invisible. They are flag emoji, but Windows has no flag glyphs, so
   they fall back to regional-indicator letters and the colour genuinely applies -
   measured 424px wide for six flags, which is letters, not glyphs.
   rgba(255,255,255,.75) gives 9.84:1 and matches the footer's white-alpha scale. */
.footer-flags{font-size:1.2rem;letter-spacing:4px;margin-top:4px;color:rgba(255,255,255,.75)}
.footer-cols{display:grid;grid-template-columns:repeat(3,1fr);gap:40px}
/* h3, not h4: the nearest heading above these in document order is an h2,
   so h4 skipped a level. Nothing else on the page uses h3 at this size. */
.fc h3{font-size:.82rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.6);margin-bottom:16px}
.fc ul{display:flex;flex-direction:column;gap:10px}
.fc li,.fc a{font-size:.85rem;color:rgba(255,255,255,.6);transition:color var(--transition)}
.fc a:hover{color:rgba(255,255,255,.8)}
.footer-bar{border-top:1px solid rgba(255,255,255,.08);padding:18px 0}
.footer-bar .container{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px}
.footer-bar span{font-size:.8rem;color:rgba(255,255,255,.6)}

/* ===== RESPONSIVE ===== */
/* The desktop nav needs 1122px to render correctly: below that "← Nexsec Global",
   "How It Works" and "Live Demo" each break onto a second line inside the 72px bar,
   and below 980px the row runs off-screen entirely (up to 198px past the viewport
   at 770px, taking "Get Early Access" with it). The mobile nav was switching in at
   768px, so the whole 769-1121px band - iPad Air portrait 820, iPad Pro 11" 834,
   iPad landscape 1024 - got a broken desktop nav. Collapse to the hamburger
   wherever the desktop nav does not fit. Nav rules only; every other 768px rule
   (hero stacking, grids, footer) is unchanged and still switches at 768px. */
@media(max-width:1120px){
  .nav-links{position:fixed;top:72px;left:0;right:0;background:rgba(15,32,39,.97);backdrop-filter:blur(16px);flex-direction:column;align-items:stretch;padding:16px 24px 28px;border-bottom:1px solid rgba(255,255,255,.1);gap:4px;transform:translateY(-120%);opacity:0;pointer-events:none;transition:all .3s ease;z-index:999}
  .nav-links.open{transform:translateY(0);opacity:1;pointer-events:all}
  /* The drawer keeps the original .88rem. The size drop above exists to stop the
     desktop row crowding; stacked vertically in a full-width drawer there is no
     crowding to solve, and smaller text there would be a downgrade for nothing. */
  .nav-links .nav-link{color:rgba(255,255,255,.75);padding:12px 16px;font-size:.88rem}
  .nav-links .nav-link:hover{color:#fff;background:rgba(255,255,255,.06)}
  .nav-cta .btn-outline{display:none}
  .hamburger{display:flex}
}
@media(max-width:1024px){
  .features-grid{grid-template-columns:repeat(2,1fr)}
  .feat-card.big{grid-column:span 2}
  .contact-wrap{grid-template-columns:1fr;gap:48px}
  .footer-inner{grid-template-columns:1fr;gap:40px}
  /* minmax(0,1fr), not 1fr: an fr track carries min-width:auto, which resolves to
     the min-content of its widest item. .so-json is a <pre> whose longest line is
     ~640px, so the track was forced to 696px inside a 290px container and
     .sample-output{overflow:hidden} silently sliced off the Arabic transcript, the
     English translation and the right-hand side of the JSON, with no scrollbar.
     Capping the track's minimum at 0 lets it follow the container; .so-json's own
     overflow-x:auto (already present) then scrolls the long lines as intended. */
  .so-body{grid-template-columns:minmax(0,1fr);gap:0}
  .so-arrow{flex-direction:row;padding:0 24px 24px}
  /* Hero: stack columns on medium screens */
  .hero-inner{gap:32px}
  .hero-text{max-width:100%}
}
@media(max-width:768px){
  .section{padding:64px 0}
  /* Nav mobile rules moved to the 1120px block above - the desktop nav does not
     fit below 1122px, so the collapse has to happen there, not here. */
  /* Hero stacked */
  .hero{padding:100px 0 60px;min-height:auto}
  .hero-inner{flex-direction:column;align-items:flex-start;gap:0}
  .hero-text{max-width:100%}
  .hero-btns{flex-direction:column;gap:10px}
  .hero-btns .btn{width:100%;justify-content:center}
  .hero-stats{flex-wrap:wrap;gap:16px;width:100%}
  .hstat-div{display:none}
  /* Other sections */
  .problems-grid,.pricing-grid,.testi-grid{grid-template-columns:1fr}
  /* .arch-flow / .arch-arrow moved to the 1199px block (ADR-011) - the row
     does not fit below ~1145px, so the stack has to start higher than 768px. */
  .form-row{grid-template-columns:1fr}
  .fg.full{grid-column:span 1}
  .contact-form{padding:24px 18px}
  .footer-cols{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:480px){
  h1{font-size:1.9rem}
  h2{font-size:1.55rem}
  .hero-stats{padding:16px 20px}
  .features-grid{grid-template-columns:1fr}
  .feat-card.big{grid-column:span 1}
  .footer-cols{grid-template-columns:1fr}
  .footer-bar .container{flex-direction:column;align-items:flex-start}
  .pricing-grid{grid-template-columns:1fr}
}
/* Below ~388px the nav row (logo + "Get Early Access" + hamburger) is wider than
   the viewport. .navbar is position:fixed, so body{overflow-x:hidden} does not
   clip it and it adds nothing to scrollWidth - it just runs off-screen silently,
   taking the hamburger with it and leaving no way to open the menu at all.
   Drop the CTA here, exactly as .btn-outline is already dropped at 768px above;
   the logo + hamburger alone need only ~190px. #contact stays reachable from the
   hero, pricing and footer. */
@media(max-width:400px){
  .nav-cta .btn-primary{display:none}
}

/* ===== KEYBOARD FOCUS (audit #12) =====
   .filter-sel set outline:none with no replacement and was the one control on
   either page with no focus indicator at all - verified as 0% pixel change on
   keyboard focus, against 11-14% for every other control. Everything else fell
   back to Chrome's UA ring, which is drawn from currentColor: white on
   .btn-primary, green on .btn-outline, and different again in other browsers.
   So the real defect was one dead control plus an inconsistent, UA-dependent
   indicator everywhere else. One brand ring fixes both.

   :focus-visible, not :focus - a mouse click on a button should not leave a ring
   behind, which is why the UA distinguishes them.
   Specificity (0,1,0) beats the `input,select,textarea` element selector that
   carries outline:none, and this block sits last in the file so it also wins on
   source order against .filter-sel's own (0,1,0) rule.
   outline-offset keeps the ring clear of the control, so it stays visible on the
   green .btn-primary fill by sitting on the surface behind it. */
:focus-visible{outline:3px solid var(--green);outline-offset:2px}

/* Ring contrast against the surfaces it lands on: 3.30:1 on white and 5.25:1 on
   the dark sidebar/hero, both clearing the 3:1 WCAG 1.4.11 asks of non-text UI. */

/* ===== REDUCED MOTION (audit #14) =====
   Nothing here honoured prefers-reduced-motion: the waveform bars, the two
   floating phone badges and the dashboard status dots all ran infinite loops,
   and the hero figures counted up on scroll.

   The wildcard is a safety net so anything added later is covered by default;
   it needs !important because a class selector outranks `*`. Durations are
   near-zero rather than `none` so animations still reach their end state and
   anything keyed off animationend still fires. Every keyframe here rests at its
   0%/100% frame, so stopping there is the natural, undisturbed appearance. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:1ms!important;
    animation-iteration-count:1!important;
    transition-duration:1ms!important;
    scroll-behavior:auto!important
  }
  html{scroll-behavior:auto}

  /* Scroll-reveal starts at opacity:0 and is only revealed by a transition. With
     transitions neutralised it must be placed directly, or the page would be
     blank for these users - a far worse outcome than the animation. */
  [data-aos],[data-aos].visible{opacity:1;transform:none;transition:none}

  /* The two the audit named, stopped outright rather than merely shortened. */
  .waveform span{animation:none}
  .phone-badge-1,.phone-badge-2{animation:none}
}

/* The skip link that used to live here was removed 2026-09-03 by owner
   decision - see ADR-032. Deliberate, not an oversight: it is how these two
   pages satisfied WCAG 2.4.1 (Bypass Blocks, Level A), and they no longer do.
   <main id="main"> is still in the markup, so restoring it is markup + this
   block. Do not re-add it as an "accessibility fix" without asking. */
