/* ==========================================================================
   Speeko landing page — light, Preline-Pro-styled stylesheet.

   Built on top of vendor/preline/main.min.css (a full Tailwind/Preline
   utility build copied from the Preline Pro template library — see
   vendor/preline/ for the source). This file supplies only what that build
   can't: the Speeko brand palette and a handful of hand-rolled component
   classes, both named to match the Nuxt dashboard's Tailwind tokens
   (frontend/tailwind.config.ts, frontend/assets/css/main.css) so the two
   surfaces share one design language.

   Deliberately light-only: no dark-mode stylesheet or `prefers-color-scheme`
   branch is wired up here. The previous version of this page switched to a
   dark palette automatically whenever the visitor's OS was in dark mode,
   which is what actually prompted this redesign — so this file never
   toggles the `.dark` class main.min.css looks for, and the page stays on
   the light tokens below regardless of OS/browser theme.

   No webfonts, no CDN calls: font stack is system-only, all colors are
   local CSS variables, every icon is inline SVG.
   ========================================================================== */

:root {
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  /* Surface / ink — RGB triplets so `rgb(var(--x) / <alpha>)` can express
     opacity variants below. Values match frontend/assets/css/main.css
     exactly (light block): surface = page/card white, surface-muted =
     slate-50 page chrome, surface-subtle = slate-100 hover/inset,
     surface-border = slate-200, ink = slate-900/600/400. */
  --surface: 255 255 255;
  --surface-muted: 248 250 252;
  --surface-subtle: 241 245 249;
  --surface-border: 226 232 240;
  --ink: 15 23 42;
  --ink-muted: 71 85 105;
  --ink-subtle: 148 163 184;

  /* Brand (speeko) — indigo half of the login-page gradient. Matches
     frontend/tailwind.config.ts `speeko` scale. */
  --speeko-50: 238 240 252;
  --speeko-100: 221 226 250;
  --speeko-200: 188 197 245;
  --speeko-300: 149 163 238;
  --speeko-400: 117 136 232;
  --speeko-500: 102 126 234;
  --speeko-600: 77 101 214;
  --speeko-700: 63 83 181;
  --speeko-800: 54 69 147;
  --speeko-900: 45 58 118;
  --speeko-950: 28 36 82;

  /* Accent — violet half of the gradient, matches `accent` scale. */
  --accent-400: 160 109 200;
  --accent-500: 138 91 184;
  --accent-600: 118 75 162;
  --accent-700: 94 59 128;
  --accent-800: 74 47 100;

  --gradient-brand: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

  --success-600: 22 163 74;   /* green-600 */
  --success-700: 21 128 61;   /* green-700 */
  --danger-600: 220 38 38;    /* red-600 */
  --danger-700: 185 28 28;    /* red-700 */

  /* Legacy variable names still referenced by inline SVG mockups further
     down this template set (hero visual, security diagram, dashboard
     preview charts) — aliased to the tokens above so those SVGs re-theme
     automatically without touching their markup. */
  --bg: rgb(var(--surface));
  --bg-alt: rgb(var(--surface-muted));
  --bg-raised: rgb(var(--surface));
  --text: rgb(var(--ink));
  --text-muted: rgb(var(--ink-muted));
  --border: rgb(var(--surface-border));
  --brand: rgb(var(--speeko-500));
  --brand-strong: rgb(var(--speeko-700));
  --brand-soft: rgb(var(--speeko-50));
  --accent: rgb(var(--accent-600));
  --success: rgb(var(--success-600));
  --danger: rgb(var(--danger-600));

  color-scheme: light;
}

/* ---------- Base ---------- */

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 76px; /* clears the sticky header when jumping to a #section */
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
}

body {
  font-family: var(--font-sans);
  background-color: rgb(var(--surface-muted));
  color: rgb(var(--ink));
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid rgb(var(--speeko-500));
  outline-offset: 2px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: rgb(var(--speeko-600));
  color: #fff;
  padding: 10px 16px;
  border-radius: 0 0 10px 0;
  z-index: 1000;
  font-weight: 600;
  font-size: 0.9rem;
}
.skip-link:focus { left: 0; }

/* ---------- Color utilities ----------
   Named to match the Nuxt dashboard's Tailwind color tokens 1:1
   (bg-surface, text-ink-muted, bg-speeko-600, ...) even though these are
   hand-written rather than Tailwind-generated — everything else (spacing,
   grid, radius, shadow, responsive prefixes) comes from the copied
   vendor/preline/main.min.css utility build. */

.bg-surface { background-color: rgb(var(--surface)); }
.bg-surface-muted { background-color: rgb(var(--surface-muted)); }
.bg-surface-subtle { background-color: rgb(var(--surface-subtle)); }
.border-surface-border { border-color: rgb(var(--surface-border)); }
.border-surface-border\/40 { border-color: rgb(var(--surface-border) / 0.4); }
.border-surface-border\/60 { border-color: rgb(var(--surface-border) / 0.6); }
.bg-surface\/90 { background-color: rgb(var(--surface) / 0.9); }
.bg-surface-muted\/60 { background-color: rgb(var(--surface-muted) / 0.6); }

.text-ink { color: rgb(var(--ink)); }
.text-ink-muted { color: rgb(var(--ink-muted)); }
.text-ink-subtle { color: rgb(var(--ink-subtle)); }

.bg-speeko-50 { background-color: rgb(var(--speeko-50)); }
.bg-speeko-100 { background-color: rgb(var(--speeko-100)); }
.bg-speeko-500 { background-color: rgb(var(--speeko-500)); }
.bg-speeko-600 { background-color: rgb(var(--speeko-600)); }
.bg-speeko-900 { background-color: rgb(var(--speeko-900)); }
.text-speeko-500 { color: rgb(var(--speeko-500)); }
.text-speeko-600 { color: rgb(var(--speeko-600)); }
.text-speeko-700 { color: rgb(var(--speeko-700)); }
.border-speeko-200 { border-color: rgb(var(--speeko-200)); }
.border-speeko-600 { border-color: rgb(var(--speeko-600)); }

.bg-accent-50 { background-color: rgb(var(--accent-400) / 0.12); }
.bg-accent-600 { background-color: rgb(var(--accent-600)); }
.text-accent-600 { color: rgb(var(--accent-600)); }
.text-accent-700 { color: rgb(var(--accent-700)); }

.bg-success-50 { background-color: rgb(var(--success-600) / 0.1); }
.text-success-700 { color: rgb(var(--success-700)); }
.bg-danger-50 { background-color: rgb(var(--danger-600) / 0.1); }
.text-danger-700 { color: rgb(var(--danger-700)); }

.bg-gradient-brand { background-image: var(--gradient-brand); }
.text-gradient-brand {
  background-image: var(--gradient-brand);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Soft decorative blobs behind the hero / CTA band. Marked aria-hidden in
   markup; purely visual, ignored by prefers-reduced-motion (they're static). */
.brand-blob {
  position: absolute;
  border-radius: 999px;
  background: var(--gradient-brand);
  opacity: 0.16;
  filter: blur(64px);
  pointer-events: none;
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.btn:hover { text-decoration: none; }

.btn-primary { background-color: rgb(var(--speeko-600)); color: #fff; }
.btn-primary:hover { background-color: rgb(var(--speeko-700)); }

.btn-secondary { background-color: rgb(var(--surface)); color: rgb(var(--ink)); border-color: rgb(var(--surface-border)); }
.btn-secondary:hover { background-color: rgb(var(--surface-subtle)); }

.btn-ghost { background-color: transparent; color: rgb(var(--ink-muted)); }
.btn-ghost:hover { background-color: rgb(var(--surface-subtle)); color: rgb(var(--ink)); }

.btn-white { background-color: #fff; color: rgb(var(--speeko-700)); }
.btn-white:hover { background-color: rgb(var(--speeko-50)); }

/* ---------- Header / nav ---------- */

.site-header {
  background-color: rgb(var(--surface) / 0.92);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.nav-link {
  color: rgb(var(--ink-muted));
  font-weight: 500;
  font-size: 0.875rem;
  border-radius: 0.5rem;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.nav-link:hover { color: rgb(var(--ink)); background-color: rgb(var(--surface-subtle)); }

.lang-switch {
  display: inline-flex;
  gap: 2px;
  background-color: rgb(var(--surface-subtle));
  border-radius: 999px;
  padding: 3px;
}
.lang-switch form { margin: 0; }
.lang-switch button {
  border: 0;
  background: transparent;
  color: rgb(var(--ink-muted));
  font-weight: 700;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  padding: 5px 11px;
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}
.lang-switch button.active {
  background-color: rgb(var(--surface));
  color: rgb(var(--speeko-700));
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
}
.lang-switch button:hover:not(.active) { color: rgb(var(--ink)); }

/* ---------- FAQ accordion ----------
   Preline's hs-accordion JS toggles `.active` on `.hs-accordion` and
   removes/adds `hidden` on the content panel + the two indicator icons;
   the color/background response to that state is ours. */

.hs-accordion.active { background-color: rgb(var(--surface-subtle)); }

.hs-accordion-toggle { text-align: start; }

/* ---------- Contact form ----------
   Django renders these as bare <input>/<select>/<textarea> (no classes) —
   ContactRequestForm intentionally doesn't set widget classes, see
   apps/landing/forms.py — so they're styled by tag, scoped to the card. */

.form-card input:not([type="checkbox"]):not([type="radio"]),
.form-card select,
.form-card textarea {
  width: 100%;
  padding: 0.7rem 0.9rem;
  border-radius: 0.75rem;
  border: 1px solid rgb(var(--surface-border));
  background-color: rgb(var(--surface));
  color: rgb(var(--ink));
  font-family: inherit;
  font-size: 0.925rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.form-card input::placeholder,
.form-card textarea::placeholder { color: rgb(var(--ink-subtle)); }
.form-card input:focus,
.form-card select:focus,
.form-card textarea:focus {
  outline: none;
  border-color: rgb(var(--speeko-500));
  box-shadow: 0 0 0 3px rgb(var(--speeko-500) / 0.15);
}
.form-card textarea { resize: vertical; min-height: 6.5rem; }

.form-error { color: rgb(var(--danger-600)); font-size: 0.82rem; margin-top: 0.35rem; }
.form-alert {
  background-color: rgb(var(--danger-600) / 0.08);
  border: 1px solid rgb(var(--danger-600) / 0.35);
  color: rgb(var(--danger-700));
  border-radius: 0.75rem;
  padding: 0.7rem 1rem;
  font-size: 0.9rem;
}

/* Honeypot: hidden from sighted and mouse users, but still present in the
   DOM (not display:none) so naive bots that fill every field still trip it. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---------- Footer ---------- */

.footer-link-sep {
  position: relative;
  padding-inline-end: 0.9rem;
}
.footer-link-sep:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 50%;
  inset-inline-end: 0;
  width: 3px;
  height: 3px;
  border-radius: 999px;
  background-color: rgb(var(--surface-border));
  transform: translateY(-50%);
}

/* ---------- Simple content pages (privacy policy, success) ---------- */

.doc-page h2 { color: rgb(var(--ink)); }
.doc-page p, .doc-page li { color: rgb(var(--ink-muted)); }

/* ---------- Misc ---------- */

.step-connector {
  display: none;
}
@media (min-width: 768px) {
  .step-connector {
    display: block;
    position: absolute;
    top: 1.5rem;
    left: calc(50% + 1.75rem);
    width: calc(100% - 3.5rem);
    height: 2px;
    background-image: repeating-linear-gradient(to right, rgb(var(--surface-border)) 0 6px, transparent 6px 12px);
  }
}

/* ---- classes the sections use that the pre-compiled Preline build lacks ----
 * main.min.css is a fixed build of the utilities Preline's own demo pages
 * used; everything below was referenced by these templates but never
 * compiled, so it silently did nothing until written out here.
 */
.text-surface-subtle { color: rgb(var(--surface-subtle)); }
.text-slate-400      { color: rgb(148 163 184); }
.text-speeko-100     { color: rgb(var(--speeko-100)); }
.hover\:text-ink:hover         { color: rgb(var(--ink)); }
.hover\:text-speeko-600:hover  { color: rgb(var(--speeko-600)); }
.start-2 { inset-inline-start: .5rem; }
@media (min-width: 768px) { .md\:py-24 { padding-top: 6rem; padding-bottom: 6rem; } }

/* Accordion: Preline's JS drives the open/close, but the collapsed height has
   to start at zero or every answer is visible on load. */
.hs-accordion-group { }
.hs-accordion-content {
  height: 0; overflow: hidden;
  transition: height .3s ease;
}
@media (prefers-reduced-motion: reduce) { .hs-accordion-content { transition: none; } }

/* Contact-success page and the privacy-policy timestamp. */
.success-page {
  min-height: 70vh; display: flex; align-items: center; justify-content: center;
  padding: 3rem 1rem;
}
.success-card {
  max-width: 32rem; width: 100%; text-align: center;
  background: rgb(var(--surface)); border: 1px solid rgb(var(--surface-border));
  border-radius: 1.5rem; padding: 2.5rem 2rem;
}
.success-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 3.5rem; height: 3.5rem; border-radius: 9999px; margin-bottom: 1.25rem;
  background: rgb(var(--speeko-50)); color: rgb(var(--speeko-600));
}
.doc-updated { color: rgb(var(--ink-subtle)); font-size: .875rem; }

/* ==========================================================================
   Scroll reveal
   --------------------------------------------------------------------------
   The hidden state is applied ONLY under `.reveal-ready`, a class landing.js
   adds after it has confirmed IntersectionObserver exists and the visitor has
   not asked for reduced motion. So with JS off, JS broken, or reduce-motion
   on, every `[data-reveal]` element simply stays visible — the page can never
   be blank because an animation did not fire.
   ========================================================================== */
.reveal-ready [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  /* Only these two properties animate, so the browser can keep it on the
     compositor and nothing reflows while a section scrolls in. */
  transition: opacity .55s cubic-bezier(.16, 1, .3, 1),
              transform .55s cubic-bezier(.16, 1, .3, 1);
  will-change: opacity, transform;
}
.reveal-ready [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}
.reveal-ready [data-reveal="left"]  { transform: translateX(-22px); }
.reveal-ready [data-reveal="right"] { transform: translateX(22px); }
.reveal-ready [data-reveal="scale"] { transform: scale(.96); }
.reveal-ready [data-reveal="fade"]  { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal-ready [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* Section nav link that matches the section currently in view. */
[data-nav-link].is-active { color: rgb(var(--speeko-600)); font-weight: 600; }

/* Mobile menu panel. */
[data-menu] { display: none; }
[data-menu].is-open { display: block; }
@media (min-width: 1024px) {
  [data-menu] { display: flex; }
  [data-menu-toggle] { display: none; }
}

/* Brand mark — the real logo, not a hand-drawn stand-in. */
.brand-mark {
  width: 2.25rem; height: 2.25rem; border-radius: .75rem;
  display: block; flex: none;
}
.brand-mark-lg { width: 3.5rem; height: 3.5rem; border-radius: 1rem; }
