/* ---- Fonts ----
   Poppins (self-hosted static weights: 400 Regular, 500 Medium, 600 SemiBold, 800 ExtraBold) per
   the Technoitic brand guide - one type family for wordmark, headings, and body copy. Self-hosted
   rather than linked from Google Fonts so visitors' browsers only ever talk to technoitic.com,
   not a third party. Latin subset only (site is English-only), same approach as the Fraunces file
   it replaces. */
@font-face {
  font-family: "Poppins";
  src: url("/assets/fonts/poppins-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("/assets/fonts/poppins-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("/assets/fonts/poppins-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("/assets/fonts/poppins-800.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

/* ---- Design tokens ----
   Technoitic brand palette (product/brand kit, 2026-08): Deep Navy #0B1220, Vivid Blue #0066FF,
   Slate Gray #64748B, Light Gray #E5E7EB, White. Container/outline/shadow shades below are
   derived from those five brand colors to cover the full light/dark token set. */
:root {
  --primary: #0066ff;
  --primary-strong: #0047b3;
  --on-primary: #ffffff;
  --primary-container: #dce9ff;
  --on-primary-container: #0047b3;
  --secondary-container: #e5e7eb;
  --on-secondary-container: #0b1220;
  --surface: #ffffff;
  --surface-dim: #f5f6f8;
  --surface-variant: #e5e7eb;
  --on-surface: #0b1220;
  --on-surface-variant: #64748b;
  --outline: #dce1e8;
  --page-bg: #fafbfc;
  --ink: #0b1220;
  --ink-soft: #64748b;
  --link: #0066ff;
  --code-bg: #f1f3f6;
  --shadow: 0 1px 2px rgba(11, 18, 32, 0.06), 0 8px 24px rgba(11, 18, 32, 0.08);
  --shadow-lift: 0 4px 10px rgba(11, 18, 32, 0.08), 0 16px 32px rgba(11, 18, 32, 0.1);
  --max-width: 1160px;
  --content-width: 700px;
  --font-sans: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Code", "Roboto Mono", Consolas, monospace;
  --font-display: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --primary: #4d94ff;
    --primary-strong: #2563eb;
    --on-primary: #0b1220;
    --primary-container: #12294d;
    --on-primary-container: #a9c6ff;
    --secondary-container: #1e293b;
    --on-secondary-container: #e2e8f0;
    --surface: #131c2e;
    --surface-dim: #0b1220;
    --surface-variant: #1e293b;
    --on-surface: #f5f6f8;
    --on-surface-variant: #94a3b8;
    --outline: #263042;
    --page-bg: #0b1220;
    --ink: #f5f6f8;
    --ink-soft: #94a3b8;
    --link: #4d94ff;
    --code-bg: #16202f;
    --shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35);
    --shadow-lift: 0 4px 12px rgba(0, 0, 0, 0.4), 0 20px 40px rgba(0, 0, 0, 0.4);
  }
}

/* The theme toggle (assets/js/theme.js) stamps data-theme on <html> to override the OS
   preference above in either direction - these two blocks must win regardless of
   prefers-color-scheme, so they're plain :root[...] selectors, not nested in a media query. */
:root[data-theme="dark"] {
  --primary: #4d94ff;
  --primary-strong: #2563eb;
  --on-primary: #0b1220;
  --primary-container: #12294d;
  --on-primary-container: #a9c6ff;
  --secondary-container: #1e293b;
  --on-secondary-container: #e2e8f0;
  --surface: #131c2e;
  --surface-dim: #0b1220;
  --surface-variant: #1e293b;
  --on-surface: #f5f6f8;
  --on-surface-variant: #94a3b8;
  --outline: #263042;
  --page-bg: #0b1220;
  --ink: #f5f6f8;
  --ink-soft: #94a3b8;
  --link: #4d94ff;
  --code-bg: #16202f;
  --shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35);
  --shadow-lift: 0 4px 12px rgba(0, 0, 0, 0.4), 0 20px 40px rgba(0, 0, 0, 0.4);
}

:root[data-theme="light"] {
  --primary: #0066ff;
  --primary-strong: #0047b3;
  --on-primary: #ffffff;
  --primary-container: #dce9ff;
  --on-primary-container: #0047b3;
  --secondary-container: #e5e7eb;
  --on-secondary-container: #0b1220;
  --surface: #ffffff;
  --surface-dim: #f5f6f8;
  --surface-variant: #e5e7eb;
  --on-surface: #0b1220;
  --on-surface-variant: #64748b;
  --outline: #dce1e8;
  --page-bg: #fafbfc;
  --ink: #0b1220;
  --ink-soft: #64748b;
  --link: #0066ff;
  --code-bg: #f1f3f6;
  --shadow: 0 1px 2px rgba(11, 18, 32, 0.06), 0 8px 24px rgba(11, 18, 32, 0.08);
  --shadow-lift: 0 4px 10px rgba(11, 18, 32, 0.08), 0 16px 32px rgba(11, 18, 32, 0.1);
}

/* ---- Reset ---- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  color-scheme: light dark;
}

body {
  margin: 0;
  background: var(--page-bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

a {
  color: var(--link);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 2px;
}

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 0 0 0.5em;
}

p {
  margin: 0 0 1em;
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--primary);
  display: inline-block;
  margin-bottom: 0.9em;
}

/* ---- Layout ---- */
.wrap {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 24px;
}

.prose {
  max-width: var(--content-width);
  margin: 0 auto;
}

.prose h2 {
  margin-top: 1.6em;
  font-size: 1.6rem;
}

.prose h3 {
  margin-top: 1.4em;
  font-size: 1.25rem;
  font-family: var(--font-sans);
  font-weight: 600;
}

.prose ul,
.prose ol {
  padding-left: 1.3em;
}

.prose code {
  font-family: var(--font-mono);
  background: var(--code-bg);
  padding: 0.15em 0.4em;
  border-radius: 5px;
  font-size: 0.9em;
}

.prose blockquote {
  margin: 1.5em 0;
  padding: 0.2em 1.2em;
  border-left: 3px solid var(--primary);
  color: var(--ink-soft);
}

/* ---- Post table of contents ----
   Auto-built from the post's own <h2> headings (see the buildToc filter in eleventy.config.js) -
   always matches the article, never a hand-maintained list that drifts out of sync. A collapsed-by-
   default <details>, not an always-open box: an always-open list of every heading was taking up
   most of the first mobile screen before a reader reached any actual content - collapsing it (one
   tap to expand, native <details>, no JS) fixes that on every screen size, not just mobile. */
.post-toc {
  max-width: var(--content-width);
  background: var(--surface);
  border: 1px solid var(--outline);
  border-radius: 16px;
  margin-bottom: 32px;
}

.post-toc summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--primary);
  list-style: none;
}

.post-toc summary::-webkit-details-marker {
  display: none;
}

.post-toc summary .chevron {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  transition: transform 0.2s ease;
}

.post-toc[open] summary .chevron {
  transform: rotate(180deg);
}

.post-toc ol {
  list-style: none;
  counter-reset: toc;
  margin: 0;
  padding: 0 20px 20px;
  display: grid;
  gap: 8px;
}

.post-toc li {
  counter-increment: toc;
}

.post-toc a {
  display: flex;
  align-items: baseline;
  gap: 8px;
  color: var(--ink);
  font-weight: 500;
  font-size: 0.95rem;
  text-decoration: none;
}

.post-toc a::before {
  content: counter(toc);
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.post-toc a:hover {
  color: var(--primary);
}

/* ---- Callout boxes ----
   .callout-tip for helpful asides, .callout-warning for privacy/security caveats (e.g. uploading a
   document to an online converter) - a colored left border + tinted background distinguishes them
   from surrounding prose at a glance, which plain blockquotes don't. Colors are mixed against
   --surface/--outline rather than hardcoded, so both variants stay correct in dark mode without a
   separate dark-mode color block. */
.callout {
  display: flex;
  gap: 12px;
  margin: 1.6em 0;
  padding: 16px 18px;
  border-radius: 12px;
  border: 1px solid;
  font-size: 0.95rem;
}

.callout .icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-top: 0.1em;
}

.callout p {
  margin: 0;
}

.callout p + p {
  margin-top: 0.6em;
}

.callout-tip {
  background: color-mix(in srgb, #10b981 10%, var(--surface));
  border-color: color-mix(in srgb, #10b981 35%, var(--outline));
  color: color-mix(in srgb, #10b981 35%, var(--ink));
}

.callout-tip .icon {
  color: #10b981;
}

.callout-tip p {
  color: var(--ink);
}

.callout-warning {
  background: color-mix(in srgb, #f59e0b 10%, var(--surface));
  border-color: color-mix(in srgb, #f59e0b 40%, var(--outline));
}

.callout-warning .icon {
  color: #f59e0b;
}

.callout-warning p {
  color: var(--ink);
}

/* ---- Comparison table ----
   Wrapped in a scroll container so a wide table (e.g. 4+ columns) degrades to horizontal scroll on
   narrow viewports instead of squeezing illegibly small or breaking the page's own width. */
.compare-table-wrap {
  margin: 1.8em 0;
  overflow-x: auto;
  border: 1px solid var(--outline);
  border-radius: 14px;
}

.compare-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
  min-width: 480px;
}

.compare-table th,
.compare-table td {
  padding: 14px 18px;
  text-align: left;
  border-bottom: 1px solid var(--outline);
  white-space: normal;
}

.compare-table thead th {
  background: var(--surface-variant);
  font-family: var(--font-sans);
  font-weight: 600;
  color: var(--ink);
}

.compare-table tbody th {
  font-weight: 600;
  color: var(--ink-soft);
  white-space: nowrap;
}

.compare-table tbody tr:last-child td,
.compare-table tbody tr:last-child th {
  border-bottom: none;
}

.compare-table td.is-good {
  color: #10b981;
  font-weight: 600;
}

.compare-table td.is-bad {
  color: #f59e0b;
  font-weight: 600;
}

/* ---- Step cards ----
   <ol class="steps"> in place of a plain numbered list - CSS counters draw a big circled number
   per step instead of relying on the browser's default list-marker glyph, matching the visual
   weight the rest of the site's ".card" components use for "here are N things." */
.prose ol.steps {
  list-style: none;
  counter-reset: step;
  padding: 0;
  margin: 1.6em 0;
  display: grid;
  gap: 14px;
}

.prose ol.steps li {
  counter-increment: step;
  position: relative;
  padding: 18px 20px 18px 62px;
  background: var(--surface);
  border: 1px solid var(--outline);
  border-radius: 14px;
}

.prose ol.steps li::before {
  content: counter(step);
  position: absolute;
  left: 18px;
  top: 18px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--primary);
  color: var(--on-primary);
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---- Screenshot wrapper ----
   Soft shadow + border + a styled caption, consistent with how screenshots are already framed
   elsewhere on the site (.showcase-frame) rather than a bare inline <img> dropped into prose. */
.post-figure {
  margin: 1.8em 0;
  text-align: center;
}

.post-figure img {
  max-width: 280px;
  width: 100%;
  height: auto;
  margin: 0 auto;
  border-radius: 20px;
  border: 1px solid var(--outline);
  box-shadow: 0 2px 6px rgba(11, 18, 32, 0.14), 0 20px 40px -16px rgba(11, 18, 32, 0.35);
}

.post-figure figcaption {
  margin-top: 12px;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

/* ---- In-article CTA banners (PDF Handy) ----
   Two reusable components for driving Play Store installs from blog content:
   .cta-banner - compact, dropped right after the intro paragraph.
   .cta-banner-full - prominent, full-width end-of-article card with the official Play badge. */
.cta-banner {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 1.8em 0;
  padding: 16px 20px;
  background: var(--primary-container);
  border-radius: 16px;
}

.cta-banner img.app-icon-tile {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  flex-shrink: 0;
}

.cta-banner-copy {
  flex: 1;
  min-width: 0;
}

.cta-banner-copy p {
  margin: 0;
  font-size: 0.9rem;
  color: var(--on-primary-container);
}

.cta-banner-copy strong {
  display: block;
  font-size: 0.98rem;
  color: var(--on-primary-container);
}

.cta-banner .btn {
  flex-shrink: 0;
  white-space: nowrap;
}

.cta-banner-full {
  margin: 2.4em 0;
  padding: 40px 32px;
  text-align: center;
  background: linear-gradient(160deg, color-mix(in srgb, var(--primary) 12%, var(--surface)), var(--surface));
  border: 1px solid var(--outline);
  border-radius: 24px;
}

.cta-banner-full .app-icon-tile {
  width: 64px;
  height: 64px;
  border-radius: 16px;
  margin: 0 auto 16px;
}

.cta-banner-full h3 {
  margin-bottom: 0.3em;
}

.cta-banner-full p {
  color: var(--ink-soft);
  max-width: 46ch;
  margin: 0 auto 20px;
}

.cta-banner-full .hero-trust {
  justify-content: center;
  margin-top: 0;
  margin-bottom: 22px;
}

@media (max-width: 560px) {
  .cta-banner {
    flex-wrap: wrap;
  }
  .cta-banner .btn {
    width: 100%;
    justify-content: center;
  }
}

/* ---- Header ---- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  border-bottom: 1px solid var(--outline);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 14px;
  padding-bottom: 14px;
  position: relative;
}

.brand {
  display: flex;
  align-items: center;
  text-decoration: none;
  flex-shrink: 0;
}

/* Logo lockup swaps per theme (light-mode file has navy wordmark text, dark-mode file has white
   wordmark text) - same show/hide pattern as the sun/moon theme-toggle icons below. */
.brand-logo {
  height: 28px;
  width: auto;
  display: block;
}

.brand-logo-dark {
  display: none;
}

:root[data-theme="dark"] .brand-logo-light {
  display: none;
}

:root[data-theme="dark"] .brand-logo-dark {
  display: block;
}

@media (prefers-color-scheme: dark) {
  .brand-logo-light {
    display: none;
  }
  .brand-logo-dark {
    display: block;
  }
  :root[data-theme="light"] .brand-logo-light {
    display: block;
  }
  :root[data-theme="light"] .brand-logo-dark {
    display: none;
  }
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 28px;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* :not(.btn) so this plain-nav-link color rule structurally never fights a .btn's own color in
   any state (hover, focus, aria-current) - a version of this that only excluded .btn from the
   base rule still lost to "a:hover"/"a[aria-current]" on those specific states, since a
   class+pseudo-class+element selector still out-specifies a two-class one. */
.site-nav a:not(.btn) {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 500;
}

.site-nav a:not(.btn):hover,
.site-nav a:not(.btn)[aria-current="page"] {
  color: var(--primary);
}

.site-nav .btn {
  padding: 8px 18px;
  font-size: 0.88rem;
}

/* ---- Mobile nav toggle (hamburger) ----
   Hidden on wide screens where the full nav row fits; below the breakpoint it becomes the only
   way to open .site-nav, which turns into a full-width dropdown panel (see the media query near
   the bottom of this file). Icon swap mirrors the sun/moon theme-toggle pattern - CSS driven by a
   class the JS toggles, not two separately-shown/hidden elements picked by media query. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--outline);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
}

.nav-toggle svg {
  width: 18px;
  height: 18px;
}

.nav-toggle .icon-close {
  display: none;
}

.nav-toggle.is-open .icon-menu {
  display: none;
}

.nav-toggle.is-open .icon-close {
  display: block;
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--outline);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  padding: 0;
}

.theme-toggle:hover {
  color: var(--primary);
  border-color: var(--primary);
}

.theme-toggle svg {
  width: 17px;
  height: 17px;
}

.theme-toggle .icon-sun {
  display: none;
}

:root[data-theme="dark"] .theme-toggle .icon-moon {
  display: none;
}

:root[data-theme="dark"] .theme-toggle .icon-sun {
  display: block;
}

@media (prefers-color-scheme: dark) {
  .theme-toggle .icon-moon {
    display: none;
  }
  .theme-toggle .icon-sun {
    display: block;
  }
  :root[data-theme="light"] .theme-toggle .icon-sun {
    display: none;
  }
  :root[data-theme="light"] .theme-toggle .icon-moon {
    display: block;
  }
}

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 13px 24px;
  border-radius: 100px;
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  border: none;
  cursor: pointer;
  overflow-wrap: anywhere;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.btn-primary {
  background: var(--primary);
  color: var(--on-primary);
  box-shadow: var(--shadow);
}

.btn-outline {
  background: transparent;
  color: var(--ink);
  border: 1.5px solid var(--outline);
}

@media (hover: hover) {
  .btn-primary:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-lift);
  }
  .btn-outline:hover {
    border-color: var(--primary);
    color: var(--primary);
  }
}

/* ---- Play Store badge ----
   Google's own official "GET IT ON Google Play" badge image, not a text button - Google's brand
   guidelines expect their provided badge artwork for this, and it's the standard virtually every
   app website uses rather than a plain link. */
.play-badge {
  display: inline-block;
  height: 54px;
  width: auto;
}

@media (hover: hover) {
  .play-badge {
    transition: transform 0.15s ease, opacity 0.15s ease;
  }
  .play-badge:hover {
    transform: translateY(-1px);
    opacity: 0.9;
  }
}

/* ---- Hero ---- */
.hero {
  position: relative;
  padding: 96px 0 80px;
  overflow: hidden;
}

.hero::before {
  content: "";
  position: absolute;
  inset: -20% -10% auto -10%;
  height: 640px;
  background: radial-gradient(60% 60% at 30% 20%, color-mix(in srgb, var(--primary) 22%, transparent), transparent 70%),
    radial-gradient(45% 45% at 85% 60%, color-mix(in srgb, var(--primary) 12%, transparent), transparent 70%);
  z-index: -1;
}

/* Faint dot-grid, faded out toward the edges via a radial mask so it reads as texture, not a
   hard-edged tile. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(color-mix(in srgb, var(--ink) 22%, transparent) 1px, transparent 1px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(60% 60% at 32% 30%, #000 0%, transparent 75%);
  mask-image: radial-gradient(60% 60% at 32% 30%, #000 0%, transparent 75%);
  opacity: 0.5;
  z-index: -1;
}

.hero .wrap {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 64px;
  align-items: center;
}

/* Single-column variant for pages with no hero visual (About) - same dot-grid/glow backdrop,
   centered content instead of the two-column product-hero layout. */
.hero .wrap.hero-center {
  display: block;
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
}

.hero .wrap.hero-center .hero-actions {
  justify-content: center;
}

.hero .wrap.hero-center .lede {
  margin-inline: auto;
}

@media (max-width: 860px) {
  .hero .wrap {
    grid-template-columns: 1fr;
  }
  .hero {
    padding: 56px 0 48px;
  }
}

.hero h1 {
  font-size: clamp(2.4rem, 4.6vw, 3.6rem);
  font-weight: 800;
  letter-spacing: -0.02em;
}

.hero .lede {
  font-size: 1.18rem;
  color: var(--ink-soft);
  max-width: 46ch;
}

.hero-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 30px;
  flex-wrap: wrap;
}

.hero h1 .accent {
  background: linear-gradient(100deg, var(--primary), color-mix(in srgb, var(--primary) 55%, #8ab4ff));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero-trust {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.86rem;
  color: var(--ink-soft);
}

.hero-trust li {
  display: flex;
  align-items: center;
  gap: 7px;
}

.hero-trust svg {
  width: 15px;
  height: 15px;
  color: var(--primary);
  flex-shrink: 0;
}

/* ---- Showcase frame ----
   Both products' screenshots are pre-styled marketing composites (device mockup, background, and
   banner text already baked into the image, from each app's Play Store assets) rather than raw
   screen captures, so this just rounds the corners and lifts the image with a shadow - no
   illustrated device chrome added on top of the one already in the image. */
.showcase-frame {
  width: 100%;
  height: auto;
  min-width: 0;
  max-width: 280px;
  margin: 0 auto;
  display: block;
  border-radius: 24px;
  box-shadow: 0 2px 6px rgba(11, 18, 32, 0.18), 0 30px 60px -20px rgba(11, 18, 32, 0.45);
}

/* ---- App icon tile ----
   Each app's real launcher icon, shown as its own consistent square tile - used instead of
   screenshots wherever a raw UI screenshot would be misleading or visually inconsistent between
   products (the homepage hero, and the "Our Apps" summary cards): a QRcode scan screen or a PDF
   Handy tool grid captured mid-flow doesn't represent "the app" the way its own icon does, and two
   real launcher icons are already the same shape/scale by construction, unlike two arbitrary UI
   screenshots. */
.app-icon-tile {
  display: block;
  width: 88px;
  height: 88px;
  border-radius: 22px;
  overflow: hidden;
  box-shadow: 0 2px 6px rgba(11, 18, 32, 0.14), 0 14px 28px -10px rgba(11, 18, 32, 0.35);
  flex-shrink: 0;
}

.app-icon-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---- Hero icon stage ----
   The homepage hero represents both products as equally-sized icon tiles joined by a "+", inside
   a soft panel that gives the visual real footprint (matching a phone-mockup's weight) - rather
   than picking one product's screenshot to feature (biased on a company-level page) or mixing two
   differently-styled screenshots side by side (the two products don't share a screenshot visual
   language - see product/DECISIONS.md). */
.hero-icon-stage {
  background: linear-gradient(160deg, color-mix(in srgb, var(--primary) 10%, var(--surface)), var(--surface));
  border: 1px solid var(--outline);
  border-radius: 32px;
  padding: 48px 32px;
  box-shadow: var(--shadow-lift);
}

.hero-icon-duo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 28px;
}

.hero-icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.hero-icon-duo .app-icon-tile {
  width: 132px;
  height: 132px;
  border-radius: 30px;
}

.hero-icon-label {
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

.hero-icon-duo-plus {
  font-size: 2rem;
  font-weight: 800;
  color: var(--ink-soft);
}

@media (max-width: 480px) {
  .hero-icon-stage {
    padding: 32px 20px;
  }
  .hero-icon-duo {
    gap: 16px;
  }
  .hero-icon-duo .app-icon-tile {
    width: 92px;
    height: 92px;
    border-radius: 22px;
  }
  .hero-icon-duo-plus {
    font-size: 1.5rem;
  }
}

/* The "Our Apps" cards (homepage + /products/) lead with the real app icon tile in place of the
   generic outline-svg .icon or a screenshot - see .app-icon-tile above for why. */
.card > .app-icon-tile {
  margin-bottom: 18px;
}

@media (hover: hover) {
  @media (prefers-reduced-motion: no-preference) {
    .showcase-frame {
      transition: transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.4s ease;
    }
    .showcase-frame:hover {
      transform: translateY(-4px);
      box-shadow: 0 4px 10px rgba(11, 18, 32, 0.2), 0 40px 70px -20px rgba(11, 18, 32, 0.55);
    }
    .hero-icon-duo .app-icon-tile {
      transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.3s ease;
    }
    .hero-icon-duo .app-icon-tile:hover {
      transform: translateY(-4px);
      box-shadow: 0 4px 10px rgba(11, 18, 32, 0.2), 0 20px 40px -12px rgba(11, 18, 32, 0.4);
    }
  }
}

/* ---- Sections / cards ---- */
.section {
  padding: 64px 0;
}

.section-head {
  max-width: 620px;
  margin: 0 0 40px;
}

.section-head h2 {
  font-size: clamp(1.6rem, 2.6vw, 2.1rem);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}

/* Blog list specifically stays at 2 columns (never auto-fits up to 4+ like .card-grid) - post
   excerpts are meant to be read, not just scanned as icons, and narrow columns wrap excerpt text
   into short, choppy lines. Wider cards give each one a real reading measure. */
.post-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
  max-width: 880px;
  margin-inline: auto;
}

@media (max-width: 640px) {
  .post-grid {
    grid-template-columns: 1fr;
  }
}

.card {
  background: var(--surface);
  border: 1px solid var(--outline);
  border-radius: 18px;
  padding: 26px;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

@media (hover: hover) {
  .card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow);
    border-color: color-mix(in srgb, var(--primary) 35%, var(--outline));
  }
}

.card .icon {
  width: 40px;
  height: 40px;
  border-radius: 11px;
  background: var(--primary-container);
  color: var(--on-primary-container);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
}

.card .icon svg {
  width: 20px;
  height: 20px;
}

.card h3 {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 1.02rem;
  margin-bottom: 0.35em;
}

.card p {
  color: var(--ink-soft);
  font-size: 0.95rem;
  margin-bottom: 0;
}

.section-cta {
  background: linear-gradient(135deg, var(--primary), var(--primary-strong));
  border-radius: 24px;
  padding: 56px 40px;
  text-align: center;
  color: #fff;
}

.section-cta h2 {
  color: #fff;
}

.section-cta p {
  color: color-mix(in srgb, #fff 82%, transparent);
  max-width: 480px;
  margin: 0 auto 26px;
}

.section-cta .btn-primary {
  background: #fff;
  color: var(--primary-strong);
}

.section-cta-email {
  margin: 16px 0 0;
}

.section-cta-email a {
  color: color-mix(in srgb, #fff 88%, transparent);
  font-size: 0.92rem;
}

/* ---- How it works (3-step) ---- */
.steps-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
}

@media (max-width: 760px) {
  .steps-grid {
    grid-template-columns: 1fr;
    gap: 28px;
  }
}

.step-badge {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--primary);
  color: var(--on-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: 0.95rem;
  margin-bottom: 16px;
}

.step h3 {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 1.08rem;
  margin-bottom: 0.4em;
}

.step p {
  color: var(--ink-soft);
  font-size: 0.96rem;
  margin-bottom: 0;
}

/* ---- Company teaser ---- */
.teaser {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 56px;
  align-items: center;
}

@media (max-width: 860px) {
  .teaser {
    grid-template-columns: 1fr;
    gap: 32px;
  }
}

.teaser p {
  color: var(--ink-soft);
  font-size: 1.02rem;
  max-width: 50ch;
}

.teaser-card {
  background: var(--surface);
  border: 1px solid var(--outline);
  border-radius: 20px;
  padding: 36px;
  box-shadow: var(--shadow);
}

.value-checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 18px;
}

.value-checklist li {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
}

.value-checklist .icon {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: var(--primary-container);
  color: var(--on-primary-container);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.value-checklist .icon svg {
  width: 17px;
  height: 17px;
}

/* ---- Coverflow screenshot carousel ----
   Shared by both products' "See it in action" section - drag/swipe or click a peeking neighbor to
   rotate through all 8 screenshots, coverflow style (center slide large and flat, neighbors
   smaller and faded toward the edges). Replaced an earlier click-a-thumbnail grid design
   (.screen-viewer/.screen-thumb, now removed) after direct feedback that it didn't feel
   interactive enough. No 3D tilt on the neighbor slides - an earlier version added a rotateY tilt,
   but that made a rotated slide's actual on-screen shape smaller than its clickable bounding box,
   producing a dead-click zone near each neighbor's outer edge; dropped in favor of reliable clicks
   over the extra visual flourish. */
.coverflow {
  --slide-w: 230px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  max-width: 720px;
  margin: 0 auto;
  outline: none;
}

.coverflow-glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.coverflow-glow::before {
  content: "";
  position: absolute;
  inset: 12%;
  background: radial-gradient(circle, var(--accent-glow, var(--primary)) 0%, transparent 70%);
  opacity: 0.45;
  filter: blur(40px);
}

.coverflow-arrow {
  position: relative;
  z-index: 40;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1.5px solid var(--outline);
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  box-shadow: var(--shadow);
}

.coverflow-arrow svg {
  width: 18px;
  height: 18px;
}

.coverflow-arrow:hover {
  border-color: color-mix(in srgb, var(--primary) 45%, var(--outline));
  color: var(--primary);
}

.coverflow-viewport {
  position: relative;
  flex: 1;
  min-width: 0;
  height: calc(var(--slide-w) * 1.78);
  cursor: grab;
  touch-action: pan-y;
}

.coverflow-viewport.is-dragging {
  cursor: grabbing;
}

.coverflow-track {
  position: relative;
  width: 100%;
  height: 100%;
}

.coverflow-slide {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--slide-w);
  cursor: pointer;
  user-select: none;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.45s ease;
}

.coverflow-slide .showcase-frame {
  width: 100%;
  max-width: none;
  margin: 0;
}

.coverflow-slide:hover .showcase-frame {
  transform: none;
}

.coverflow-slide.is-active {
  cursor: default;
}

.is-dragging .coverflow-slide {
  transition: none;
}

.coverflow.no-motion .coverflow-slide,
.coverflow.no-motion .coverflow-glow::before {
  transition: none !important;
}

.coverflow-caption {
  text-align: center;
  margin-top: 20px;
}

.coverflow-caption-title {
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--ink);
  margin: 0;
}

.coverflow-caption-sub {
  color: var(--ink-soft);
  margin: 4px 0 0;
  font-size: 0.95rem;
}

.coverflow-dots {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 20px;
}

.coverflow-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: none;
  background: var(--outline);
  cursor: pointer;
  padding: 0;
  --thumb-accent: var(--primary);
  transition: background 0.2s ease, transform 0.2s ease;
}

.coverflow-dot:hover {
  background: color-mix(in srgb, var(--thumb-accent) 55%, var(--outline));
}

.coverflow-dot.is-active {
  background: var(--thumb-accent);
  transform: scale(1.3);
}

@media (max-width: 720px) {
  .coverflow {
    --slide-w: 190px;
    gap: 4px;
  }
  .coverflow-arrow {
    width: 36px;
    height: 36px;
  }
}

@media (max-width: 480px) {
  .coverflow {
    --slide-w: 150px;
  }
}

/* ---- Blog post card ----
   Shared by the homepage's "From the blog" preview and the full /blog/ list - each card leads
   with its post's own real screenshot (the same `image` front-matter field every post now sets
   for its BlogPosting schema) instead of one generic document icon repeated on every card
   regardless of topic. Image flush to the card's top edge (.card's own padding is overridden to
   0 here, with .post-card-body carrying the padding instead), cropped to a landscape strip with
   object-position: top so a screenshot's own headline text - the most recognizable, on-brand part
   at thumbnail size - stays in frame rather than the phone mockup below it. */
.post-card {
  display: block;
  text-decoration: none;
  color: inherit;
  padding: 0;
  overflow: hidden;
}

.post-card-thumb {
  aspect-ratio: 16 / 10;
  background: var(--surface-variant);
}

.post-card-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
}

.post-card-body {
  padding: 20px 24px 24px;
}

.post-card h2,
.post-card h3 {
  margin: 0.3em 0;
  font-size: 1.15rem;
}

.post-card .post-excerpt {
  color: var(--ink-soft);
  margin: 0;
  font-size: 0.95rem;
}

@media (hover: hover) {
  .post-card-thumb img {
    transition: transform 0.3s ease;
  }
  .post-card:hover .post-card-thumb img {
    transform: scale(1.04);
  }
}

.post-meta {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--ink-soft);
  letter-spacing: 0.02em;
}

.post-header {
  max-width: var(--content-width);
  margin: 0 auto 10px;
}

.post-header h1 {
  font-size: clamp(1.9rem, 3.4vw, 2.5rem);
}

/* Small "back to list" link above a post's own title - a reader who came from /blog/ needs a way
   back that doesn't mean scrolling past the whole article to the footer. */
.post-back {
  max-width: var(--content-width);
  margin: 0 auto 20px;
}

.post-back a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 0.92rem;
  text-decoration: none;
}

.post-back a:hover {
  color: var(--primary);
}

/* ---- Footer ---- */
.site-footer {
  border-top: 1px solid var(--outline);
  margin-top: 72px;
  padding: 48px 0 32px;
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, 1fr);
  gap: 32px;
  padding-bottom: 32px;
}

@media (max-width: 720px) {
  .footer-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.footer-brand {
  display: flex;
  align-items: center;
  text-decoration: none;
  margin-bottom: 14px;
}

.footer-brand .brand-logo {
  height: 24px;
}

.footer-col h4 {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 12px;
}

.footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.footer-col a {
  color: var(--ink);
  text-decoration: none;
  font-size: 0.92rem;
}

.footer-col a:hover {
  color: var(--primary);
}

.footer-bottom {
  border-top: 1px solid var(--outline);
  padding-top: 24px;
  color: var(--ink-soft);
  font-size: 0.85rem;
}

/* ---- Utility ---- */
.text-center {
  text-align: center;
}

@media (max-width: 640px) {
  body {
    font-size: 16px;
  }
}

/* ---- Responsive header nav ----
   Below this width the nav row (Home/QRcode/Blog/About + theme toggle + Get-the-app button)
   doesn't fit next to the logo - rather than let flexbox squeeze the logo down to nothing, it
   collapses into a hamburger-triggered dropdown panel. */
@media (max-width: 760px) {
  .nav-toggle {
    display: inline-flex;
  }
  .site-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    background: var(--surface);
    border-bottom: 1px solid var(--outline);
    padding: 8px 24px 20px;
    box-shadow: var(--shadow);
  }
  .site-nav.is-open {
    display: flex;
  }
  .site-nav a:not(.btn) {
    padding: 11px 2px;
    font-size: 1rem;
    border-bottom: 1px solid var(--outline);
  }
  .site-nav li {
    width: 100%;
  }
  .site-nav .theme-toggle {
    margin: 10px 0;
  }
  .site-nav .btn {
    width: 100%;
    justify-content: center;
    padding: 13px 18px;
  }
}
