/* ============================================================
   site.css — design tokens + base layer.
   These tokens are canonical for the site; tailwind.config.js
   mirrors a subset of them. Desktop-first max-width queries here;
   Tailwind utilities (mobile-first) handle per-component layout.
   ============================================================ */

:root {
  /* Tech Tactics palette. Legacy variable names are kept and remapped so
     existing rules pick up the new scheme without churn. */
  --blue: #0b2a3c;          /* headings on light (darkest navy) */
  --mid-blue: #35a7db;      /* bright accent blue */
  --light-blue: #1179a9;    /* primary: buttons, links, accents */
  --primary-hover: #0c5c82;
  --accent-hover: #5cbce7;
  --navy-1: #0b2a3c;        /* testimonials, stat band, footer base */
  --navy-2: #0e3a52;
  --navy-3: #11506e;
  --light-blue-30: #a9d6ee; /* chart bar tint */
  --chart-tint: #d7ebf6;
  --light-blue-5: #f1f8fc;  /* interaction tint: btn hovers, stripe gradient */
  --gray-tint: #f2f2f2;     /* portal neutral: support.techtactics.us contentBox */
  --tile: #eaf4fa;          /* icon tile background */
  --yellow: #35a7db;        /* legacy accent slot -> bright blue */
  --text: #16323f;          /* body text on light */
  --gray: #4a6675;          /* secondary text on light */
  --gray-80: #7fa2b4;       /* muted / captions on light */
  --gray-50: #e3eef4;       /* borders on light */
  --gray-20: #e3eef4;
  --border-light: #e3eef4;
  --on-dark-body: #c3dcea;
  --on-dark-muted: #8fbbd2;
  --on-dark-accent: #8fd4f5;
  --on-dark-bright: #d6edf9;
  --footer-fine: #6e93a8;
  --success: #2fb56b;
  --success-30: #a9edc4;
  --success-5: #e8f5ec;
  --btn-dark-text: #06222f; /* dark text on bright-blue buttons */
  --white: #fff;

  --font-ui: "Inter", sans-serif;
  --font-prose: "Lato", sans-serif;

  --radius-button: 0.3em;
  --radius-card: 12px;
  --radius-input: 4px;
  --shadow-nav: 0 2px 8px #0b2a3c26;

  --speed-fast: 0.2s;
  --speed-base: 0.3s;
  --speed-slow: 0.4s;

  --max-content: 1400px;
  --nav-offset: 100px; /* fixed navbar clearance; overridden per breakpoint */
}

/* ---------- minimal reset (Tailwind preflight is disabled) ---------- */

*, *::before, *::after { box-sizing: border-box; }
/* iOS Safari font boosting inflated nav text (17px phone link rendered ~26px,
   overflowing the header row); normalize like Tailwind preflight would. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
ul { list-style: none; margin: 0; padding: 0; }
img, svg { max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

/* ---------- base typography ---------- */

body {
  background: var(--white);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: 1vw; /* fluid base on desktop, as per reference */
  font-weight: 400;
  line-height: 150%;
  letter-spacing: 0;
  margin: 0;
}

h1, h2, h3, h4, h5 {
  color: var(--blue);
  font-family: var(--font-ui);
  font-weight: 700;
  line-height: 140%;
  margin: 0;
}
h1 { font-size: 44px; padding-bottom: 30px; }
h2 { font-size: 36px; padding-bottom: 0.7em; }
h3 { font-size: 28px; padding-bottom: 0.5em; }
h4 { font-size: 22px; padding-bottom: 0.5em; }

p {
  font-family: var(--font-prose);
  font-size: 23px;
  line-height: 150%;
  margin: 0;
}
.prose-link,
main a:not(.btn):not(.card-link):not([href^="tel:"]) {
  color: var(--light-blue);
  font-family: var(--font-prose);
  text-decoration: none;
}
/* phone numbers keep the UI font; color still matches prose links */
main a[href^="tel:"]:not(.btn) { color: var(--light-blue); text-decoration: none; }

.eyebrow {
  color: var(--light-blue);
  font-family: var(--font-ui);
  font-size: 15px;
  letter-spacing: 1px;
  text-transform: uppercase;
  padding-bottom: 0.5em;
  display: block;
}

/* Anchor jumps (e.g. footer deep-links to #case-title) land with the target
   heading below the fixed navbar instead of hidden underneath it. */
[id] { scroll-margin-top: calc(var(--nav-offset) + 1em); }

/* ---------- section shell: em vertical / vw horizontal ---------- */

.section { padding: 5em 4vw; }
.section-inner { max-width: var(--max-content); margin-inline: auto; }
.section--tint { background: var(--gray-tint); }
.section--hero {
  margin-top: var(--nav-offset);
  min-height: 550px;
  padding-bottom: 1em;
}
/* .section--dots-right / .section--dots-left kept in markup; scatter-dot
   backgrounds removed at client request (dots showed behind text). */
.section--interior-hero {
  margin-top: var(--nav-offset);
  min-height: 550px;
}
.section--interior-hero.no-illustration { min-height: auto; padding-bottom: 3em; }

/* small line-art icons used by 3-col feature rows */
.icon-illus { display: block; width: 90px; height: 90px; margin-inline: auto; }

/* ---------- components ---------- */

.btn {
  display: inline-block;
  background: var(--light-blue);
  color: var(--white);
  border: 0;
  border-radius: var(--radius-button);
  padding: 1em 1.4vw;
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: all var(--speed-base);
}
.btn:hover {
  background: var(--primary-hover);
  transform: translateX(8px);
}
.btn:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
}

.card {
  background: var(--white);
  border: 2px solid var(--border-light);
  border-radius: var(--radius-card);
  padding: 3em 3vw;
}
/* spotlight variant: brand-tinted callout for a card that must not read
   as one of the plain white cards (AI page strategy block) */
.card--spotlight {
  background: var(--light-blue-5);
  border-color: var(--light-blue);
  border-left-width: 8px;
}

.cta-panel {
  border-radius: var(--radius-card);
  padding: 5em 5vw;
  background: linear-gradient(150deg, #1179a9, #0c5c82); /* mission band */
}
.cta-panel h2 { color: var(--white); }
.cta-panel p { color: var(--on-dark-bright); }
/* buttons on dark panels: white like the footer */
.cta-panel .btn { background: var(--white); color: var(--light-blue); }
.cta-panel .btn:hover { background: var(--light-blue-5); }
/* solid darkest-navy variant (testimonials, stat bands) */
.cta-panel--navy {
  background: var(--navy-1);
}
.cta-panel--navy p { color: var(--on-dark-body); }
.cta-panel .cta-content {
  max-width: 60vw;
  margin-inline: auto;
  text-align: center;
}

.nav-link {
  color: var(--gray);
  font-family: var(--font-ui);
  font-size: 15px;
  text-decoration: none;
  padding: 1em 0.9vw;
  white-space: nowrap;
  transition: color var(--speed-fast);
}
.nav-link:hover, .nav-link[aria-current="page"] { color: var(--light-blue); }

/* mobile-only second nav line: the phone number gets its own full-width row
   under logo + hamburger (order pushes it past the burger; the header row
   is flex-wrap). Sharing a line with the 160px logo collided on iPhones. */
.nav-phone-mobile {
  order: 10;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45em;
  margin-top: 0.55em;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 17px;
  color: var(--light-blue);
  text-decoration: none;
  white-space: nowrap;
}

/* compact CTA button in the navbar */
.nav-cta {
  padding: 0.7em 1.2em;
  margin-left: 0.6vw;
  font-size: 15px;
  white-space: nowrap;
}
.nav-cta:hover { transform: none; }
@media (max-width: 991px) {
  .nav-cta { display: inline-block; margin: 1em 0 0.5em; font-size: 20px; }
}

.footer-link {
  color: var(--gray);
  font-family: var(--font-ui);
  font-size: 17px;
  text-decoration: none;
  display: inline-block;
  padding-block: 0.7em;
  transition: all var(--speed-slow);
}
.footer-link:hover { color: var(--light-blue); transform: translateX(4px); }

.form-field {
  background: var(--white); /* explicit: fields sit on the gray tint band */
  border: 2px solid var(--gray-50);
  border-radius: var(--radius-input);
  min-height: 60px;
  margin-bottom: 1.5em; /* 30px gap; was 3em, which doubled the form's height */
  padding: 1em;
  width: 100%;
  font-family: var(--font-prose);
  font-size: 20px;
  color: var(--gray);
}
.form-field:focus { border-color: var(--light-blue); outline: none; }

/* Reserve the Turnstile widget's height (300x65) so the async iframe can't
   shove the Submit button down as it loads — the placeholder it replaced
   held this space for the same reason. */
.cf-turnstile { min-height: 65px; }

/* ---------- blue footer (same gradient as the mission band) ---------- */

.footer-blue {
  background: linear-gradient(150deg, var(--light-blue), var(--primary-hover));
}
/* tighter desktop footer: less vertical padding, denser link stacks */
@media (min-width: 992px) {
  .footer-blue { padding-top: 3em; padding-bottom: 2.5em; }
  .footer-blue .footer-link { padding-top: 0.35em; padding-bottom: 0.35em; }
  .footer-blue .footer-areas li { padding-top: 0.35em; padding-bottom: 0.35em; }
}
.footer-blue h4 { color: var(--white); }
.footer-blue .footer-areas li { color: var(--on-dark-bright); }
.footer-blue .footer-legal { border-top: 1px solid rgba(255, 255, 255, 0.15); }
.footer-blue p { color: var(--on-dark-bright); }
.footer-blue .footer-link { color: var(--on-dark-bright); }
.footer-blue .footer-link:hover { color: var(--white); }
.footer-blue p.text-\[14px\] { color: var(--on-dark-muted); }
/* buttons on the blue footer: white so they stand out on the gradient */
.footer-blue .btn { background: var(--white); color: var(--light-blue); }
.footer-blue .btn:hover { background: var(--light-blue-5); }

/* links on navy cards (e.g. contact support card) */
.bg-brand-navy .prose-link { color: var(--on-dark-accent); }
/* buttons on navy cards: white like the footer */
.bg-brand-navy .btn { background: var(--white); color: var(--light-blue); }
.bg-brand-navy .btn:hover { background: var(--light-blue-5); }

.form-label {
  display: block;
  color: var(--blue);
  font-family: var(--font-ui);
  font-size: 18px;
  font-weight: 700;
  padding-bottom: 0.5em;
}
textarea.form-field { min-height: 160px; resize: vertical; }

/* Form live regions (#form-status / #form-error on contact + feedback).
   They stay in the DOM permanently — empty when idle — because a region
   toggled `hidden` leaves the accessibility tree and screen readers then
   announce updates unreliably. So the spacing has to be conditional:
   :not(:empty) keeps zero gap while idle, and clears the submit button
   below only once a message is actually showing. A plain margin here would
   leave a permanent hole under every form. */
#form-status:not(:empty),
#form-error:not(:empty) { display: block; margin-bottom: 1.1em; }

/* blog post article rhythm: base reset zeroes p margins, so restore
   breathing room between consecutive paragraphs inside a post */
.post p + p { margin-top: 1.2em; }

/* placeholder illustration frames (stand-ins for Lottie/SVG art) */
.ph-illustration {
  border: 3px dashed var(--gray-50);
  border-radius: var(--radius-card);
  background:
    linear-gradient(135deg, var(--light-blue-5) 25%, transparent 25%,
      transparent 50%, var(--light-blue-5) 50%, var(--light-blue-5) 75%, transparent 75%);
  background-size: 28px 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--gray-80);
  font-size: 15px;
  font-family: var(--font-ui);
  text-align: center;
}

/* ---------- scroll reveal (approximation of Webflow IX2 defaults) ----------
   Hidden states are gated on html.js (set by main.js) so the no-JS /
   broken-JS experience is a fully visible page, never a blank one. */

.js .reveal {
  opacity: 0;
  transform: translateY(24px);
}
.reveal {
  transition: opacity 0.6s ease, transform 0.6s ease;
  transition-delay: var(--reveal-delay, 0s);
}
.js .reveal.is-visible { opacity: 1; transform: none; }

.js .connector path { stroke-dashoffset: var(--path-len, 600); }
.connector path {
  stroke-dasharray: var(--path-len, 600);
  transition: stroke-dashoffset 1.2s ease;
}
.js .connector.is-visible path { stroke-dashoffset: 0; }

/* ---------- illustrations (original line-art, Lottie replacement) ----------
   Drawn paths carry pathLength="1" + class="draw", so a single dash rule
   animates them all. Draw-in triggers with the same .is-visible reveal the
   Webflow original uses; ambient loops (.anim-*) run continuously. */

.illus { display: block; width: 100%; height: auto; }

/* Lottie containers — aspect ratios match each animation's composition
   size so space is reserved before the JSON loads (no layout shift) */
.lottie { display: block; width: 100%; }
.lottie svg { display: block; }
/* Opaque backing: the animations are transparent line art, and section
   dot-scatter backgrounds must not show through inside the artwork. */
.lottie-hero, .lottie-graphic { background: var(--white); }

/* ---------- hero screen text overlay ----------
   The hero JSONs have no text layers; date/day/meeting text is an HTML
   overlay so it stays current. Coordinates are percentages of each
   composition (desktop 1200x540, mobile 800x540), measured from the
   device rects in the animation data; they switch at the same 768px
   breakpoint as the Lottie variant. Font sizes use container-query
   units so text scales with the artwork. */

/* The animation stays in normal flow and carries the aspect ratio itself.
   (Previously the child was position:absolute inside a container-type:
   inline-size box; iOS WebKit failed to paint the SVG under that
   combination — size containment + abs-positioned percentage heights.) */
.lottie-hero { position: relative; }
.lottie-hero > .lottie { width: 100%; aspect-ratio: 800 / 540; }
@media (min-width: 768px) { .lottie-hero > .lottie { aspect-ratio: 1200 / 540; } }

.hero-screen-text { position: absolute; inset: 0; pointer-events: none; }
/* mobile: no screen-text overlay — it misaligns against the mobile artwork
   and the type is unreadably small; empty device screens read fine */
@media (max-width: 767px) { .hero-screen-text { display: none; } }
.hero-text {
  position: absolute;
  color: var(--blue);
  font-family: var(--font-ui);
  font-weight: 600;
  line-height: 1.35;
  /* ~2.2% of the artwork width; vw-based since the hero no longer uses
     container queries (their size containment broke iOS SVG painting) */
  font-size: 1.95vw;
}
.hero-text--monitor { left: 32.5%; top: 41%; }
/* left-aligned so "Mon." sits flush with the date below it, rather than
   inheriting the hero section's centring. left values measured against the
   rendered tablet-screen path (mobile screen x 10.25%..21.70%, desktop
   23.50%..31.14%) to centre the date block with even side margins. */
.hero-text--tablet  { left: 11.3%; top: 42.5%; text-align: left; }
.hero-text--mug     { left: 77.8%; top: 46.5%; }

@media (min-width: 768px) {
  .hero-text { font-size: min(1.38vw, 16.5px); } /* ~1.5% of min(92vw, 1100px) */
  .hero-text--monitor { left: 38.6%; top: 42%; }
  .hero-text--tablet  { left: 24.1%; top: 42.3%; }
  .hero-text--mug     { left: 68.8%; top: 46.5%; }
}

/* fade the screen text in after the scene has largely drawn */
.js .reveal .hero-text { opacity: 0; }
.js .reveal.is-visible .hero-text { opacity: 1; transition: opacity 0.6s ease 1.6s; }

/* typing ellipsis after "Starting Meeting": dots appear one by one,
   clear together, repeat. Opacity-only so the line never reflows. */
.meeting-dots span { animation: 1.8s steps(1, end) infinite; }
.meeting-dots span:nth-child(1) { animation-name: meetingDot1; }
.meeting-dots span:nth-child(2) { animation-name: meetingDot2; }
.meeting-dots span:nth-child(3) { animation-name: meetingDot3; }
.meeting-dots span:nth-child(4) { animation-name: meetingDot4; }
@keyframes meetingDot1 { 0%, 14% { opacity: 0; } 15%, 92% { opacity: 1; } 93%, 100% { opacity: 0; } }
@keyframes meetingDot2 { 0%, 34% { opacity: 0; } 35%, 92% { opacity: 1; } 93%, 100% { opacity: 0; } }
@keyframes meetingDot3 { 0%, 54% { opacity: 0; } 55%, 92% { opacity: 1; } 93%, 100% { opacity: 0; } }
@keyframes meetingDot4 { 0%, 74% { opacity: 0; } 75%, 92% { opacity: 1; } 93%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .meeting-dots span { animation: none; opacity: 1; }
}
.lottie-hero { max-width: 1100px; margin-inline: auto; }
.lottie-graphic { aspect-ratio: 610 / 451; }
.lottie-connector { aspect-ratio: 798 / 181; width: min(60%, 798px); margin-inline: auto; }
.lottie-connector--bottom { aspect-ratio: 791 / 254; width: min(60%, 791px); }
.lottie-icon { width: 140px; aspect-ratio: 1; margin-inline: auto; }
.lottie-connector--half { aspect-ratio: 796 / 180; }
.lottie-advantage { aspect-ratio: 450 / 180; max-width: 300px; }
.lottie-pricing { aspect-ratio: 610 / 400; }

.js .reveal .draw { stroke-dasharray: 1; stroke-dashoffset: 1; }
.js .reveal.is-visible .draw {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1s ease 0.1s;
}
.js .reveal.is-visible .draw-2 { transition-delay: 0.45s; }
.js .reveal.is-visible .draw-3 { transition-delay: 0.8s; }

.anim-float, .anim-steam, .anim-flicker, .anim-spin,
.anim-led, .anim-wave, .anim-pulse {
  transform-box: fill-box;
  transform-origin: center;
}
.anim-float   { animation: illusFloat 4s ease-in-out infinite; }
.anim-steam   { animation: illusSteam 2.6s ease-out infinite; }
.anim-flicker { animation: illusFlicker 1.8s ease-in-out infinite; }
.anim-spin    { animation: illusSpin 6s linear infinite; }
.anim-led     { animation: illusLed 2.2s steps(1, end) infinite; }
.anim-wave    { animation: illusWave 2.8s ease-in-out infinite; transform-origin: left center; }
.anim-pulse   { animation: illusPulse 3s ease-in-out infinite; }

@keyframes illusFloat   { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes illusSteam   { 0% { transform: translateY(0); opacity: 0; } 25% { opacity: 0.9; } 100% { transform: translateY(-14px); opacity: 0; } }
@keyframes illusFlicker { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.12) translateY(-1px); } }
@keyframes illusSpin    { to { transform: rotate(360deg); } }
@keyframes illusLed     { 0%, 100% { opacity: 1; } 35% { opacity: 0.25; } 65% { opacity: 0.7; } }
@keyframes illusWave    { 0%, 100% { transform: skewY(0deg); } 50% { transform: skewY(-4deg); } }
@keyframes illusPulse   { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .reveal, .connector path { transition: none; opacity: 1; transform: none; stroke-dashoffset: 0; }
  .btn:hover, .footer-link:hover { transform: none; }
  .js .reveal .draw { stroke-dasharray: none; stroke-dashoffset: 0; transition: none; }
  .anim-float, .anim-steam, .anim-flicker, .anim-spin,
  .anim-led, .anim-wave, .anim-pulse { animation: none; }
  .anim-steam { opacity: 0.6; }
}

/* ---------- breakpoints (desktop-first, mirrors reference) ---------- */

/* 1024–1279: seven nav items + phone + CTA overflow the row and push the whole
   nav below the logo (measured: nav needs ~750px, only ~745px available at
   1024). Tightening type + padding here keeps it on one line; the ≥1280 rule
   below restores the roomy sizing. */
@media (min-width: 1024px) and (max-width: 1279px) {
  .nav-link { font-size: 14px; padding: 1em 0.6vw; }
}

@media (min-width: 1280px) {
  :root { --nav-offset: 110px; }
  h1 { font-size: 48px; }
  h2 { font-size: 40px; }
  .nav-link { font-size: 17px; }
  .cta-panel .cta-content { max-width: 50vw; }
}

@media (max-width: 991px) {
  :root { --nav-offset: 112px; } /* two-line mobile header: 102px measured + gap */
  body { font-size: 14px; }
  h1 { font-size: 44px; }
  h2 { font-size: 34px; padding-bottom: 0.8em; }
  h3 { font-size: 24px; }
  .section { padding: 4em 4vw; }
  .section--hero { padding-top: 3em; }
  .btn { padding-inline: 2vw; }
  .cta-panel { padding-block: 4em; }
  .cta-panel .cta-content { max-width: none; }
}

@media (max-width: 767px) {
  h1 { font-size: 40px; }
  h2 { font-size: 30px; }
  h3 { font-size: 22px; }
  .section { padding: 4em 5vw; }
  .btn { padding-inline: 3vw; }
}

@media (max-width: 479px) {
  h1 { font-size: 34px; }
  h2 { font-size: 28px; }
  p { font-size: 22px; }
  .section { padding: 2.5em 7vw; }
  .section--hero { min-height: 480px; padding-top: 2.5em; }
  .btn { padding-inline: 5vw; }
  .cta-panel { padding: 3em 7vw; }
}

/* Full-bleed CTA content. The default .cta-content is deliberately narrow
   (60vw, 50vw at >=1280) so short CTA lines stay readable. The homepage
   mission panel carries a full paragraph and reads better using the whole
   card, so it opts in with this modifier.

   Declared last on purpose: it has the same specificity as the
   `.cta-panel .cta-content` rule inside the >=1280px media query above, so
   source order is what makes it win at every width. Moving it earlier in
   this file would silently re-narrow the panel on large screens. */
.cta-panel .cta-content--full { max-width: none; }
