/* =========================================================
   The AIO Guy — Design System
   Apple-inspired minimalism: black/off-white, single orange accent
   ========================================================= */

:root {
  /* --- Primitives --- */
  --black: #0A0A0A;
  --white: #FAFAFA;
  --accent: #FF5A1F;
  --accent-dim: #E04E19;

  /* --- Semantic text tokens ---
     Split by surface. A single gray ramp cannot serve both a #FAFAFA and a
     #0A0A0A background: the value that reads as "muted" on white collapses to
     ~2:1 on black. Every pair below clears WCAG AA (4.5:1) on its own surface. */
  --text-on-light:            var(--black);      /* 18.1:1 */
  --text-secondary-on-light:  #4B5563;           /*  7.0:1 */
  --text-muted-on-light:      #6B7280;           /*  5.0:1 */

  --text-on-dark:             var(--white);      /* 18.1:1 */
  --text-secondary-on-dark:   #9CA3AF;           /*  8.9:1 */
  --text-muted-on-dark:       #8A9099;           /*  6.0:1 */

  --border-on-dark: rgba(250, 250, 250, 0.12);
  --border-on-light: rgba(10, 10, 10, 0.1);

  /* --- Minimum accessible hit area (WCAG 2.5.5 / touch guidance) --- */
  --tap-min: 44px;

  --font: "Geist", -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* Terminal face for the intro loader. Ships with every target OS, so there
     is nothing extra to download before the first paint. */
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace;

  --max-width: 1160px;
  --gutter: 24px;

  --section-pad: 96px;
}

@media (min-width: 768px) {
  :root { --section-pad: 140px; }
}
@media (min-width: 1200px) {
  :root { --section-pad: 190px; }
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}

body {
  margin: 0;
  font-family: var(--font);
  background: var(--white);
  color: var(--black);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  line-height: 1.5;
}

h1, h2, h3, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
button { font-family: inherit; background: none; border: none; cursor: pointer; color: inherit; }

.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

@media (min-width: 768px) {
  .container { padding: 0 40px; }
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: var(--white);
  padding: 12px 20px;
  z-index: 1000;
  font-weight: 600;
}
.skip-link:focus {
  left: var(--gutter);
  top: var(--gutter);
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  padding: 14px 28px;
  font-size: 15px;
  font-weight: 600;
  border-radius: 5px;
  transition: opacity 0.2s ease, background-color 0.2s ease, color 0.2s ease;
  white-space: nowrap;
}
.btn-primary {
  background: var(--accent);
  color: var(--white);
}
.btn-primary:hover { opacity: 0.85; }
.btn-lg { padding: 17px 34px; font-size: 16px; }

.btn-nav { display: none; }
@media (min-width: 1024px) {
  .btn-nav { display: inline-block; padding: 10px 20px; font-size: 14px; }
}

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 15px;
  font-weight: 500;
  color: var(--black);
  border-bottom: 1px solid var(--border-on-light);
  padding-bottom: 2px;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.link-arrow:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- Reveal animation ---------- */
.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.reveal.in-view {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- Header ---------- */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  transition: background-color 0.3s ease, border-color 0.3s ease;
  border-bottom: 1px solid transparent;
}
.site-header.scrolled {
  background: rgba(10, 10, 10, 0.92);
  backdrop-filter: saturate(180%) blur(10px);
  border-bottom-color: var(--border-on-dark);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 76px;
  color: var(--white);
}

.logo {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.03em;
}

.main-nav { display: none; }
@media (min-width: 1024px) {
  .main-nav { display: block; }
  .main-nav ul { display: flex; gap: 28px; }
  .main-nav a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap-min);
    padding: 0 4px;
    font-size: 14.5px;
    color: rgba(250, 250, 250, 0.85);
    transition: color 0.2s ease;
  }
  .main-nav a:hover { color: var(--white); }
}

.nav-toggle {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
  gap: 5px;
  width: var(--tap-min);
  height: var(--tap-min);
  margin-right: -10px;
}
@media (min-width: 1024px) { .nav-toggle { display: none; } }
.nav-toggle span {
  display: block;
  width: 24px;
  height: 1.5px;
  background: var(--white);
  transition: transform 0.25s ease, opacity 0.25s ease;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.mobile-nav {
  position: fixed;
  inset: 76px 0 0 0;
  background: var(--black);
  transform: translateY(-8px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
  overflow-y: auto;
}
.mobile-nav.open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.mobile-nav ul {
  padding: 32px var(--gutter);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mobile-nav a {
  display: block;
  padding: 14px 0;
  font-size: 22px;
  color: var(--white);
  border-bottom: 1px solid var(--border-on-dark);
}
.mobile-nav .btn { margin-top: 20px; text-align: center; border-bottom: none; }
@media (min-width: 1024px) { .mobile-nav { display: none; } }

/* ---------- Hero ---------- */
.hero {
  background: var(--black);
  color: var(--white);
  padding: 150px 0 90px;
}
@media (min-width: 768px) {
  .hero { padding: 190px 0 120px; }
}

.hero-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 72px;
  text-align: center;
}

.hero-copy { display: flex; flex-direction: column; align-items: center; max-width: 780px; }

.hero-headline {
  font-size: 44px;
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.05;
  margin-bottom: 24px;
}
@media (min-width: 640px) { .hero-headline { font-size: 62px; } }
@media (min-width: 1200px) { .hero-headline { font-size: 78px; } }

.hero-headline .highlight {
  display: inline-block;
  background: var(--accent);
  color: var(--black);
  padding: 0.05em 0.25em;
  border-radius: 4px;
  margin-top: 0.1em;
}

.hero-sub {
  font-size: 17px;
  color: var(--text-secondary-on-dark);
  max-width: 480px;
  margin-bottom: 40px;
}
@media (min-width: 768px) { .hero-sub { font-size: 18px; } }

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 28px;
}
.hero-actions .link-arrow { color: var(--white); border-color: var(--border-on-dark); }
.hero-actions .link-arrow:hover { color: var(--accent); border-color: var(--accent); }

.hero-visual { width: 100%; display: flex; justify-content: center; }

/* =========================================================
   Intro overlay — terminal boot sequence
   Painted black by this stylesheet alone, so the very first frame is already
   the loader with no unstyled flash to cover. js/main.js fills the log.

   `introFailsafe` is the belt-and-braces escape hatch: if the script ever
   throws, the overlay still clears itself rather than trapping the visitor on
   a black screen. It doubles as the reduced-motion path — the global rule near
   the top of this file collapses animation durations to nothing, so the
   overlay is gone on the first frame before any typing can start. Its duration
   has to outlast the whole sequence (~9.5s), or a slow device would get the
   overlay yanked mid-scan.
   ========================================================= */
.intro {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  padding: 24px;
  background: var(--black);
  /* `margin:auto` on the child centres the box when it fits and lets the
     overlay scroll instead of clipping when it doesn't (short phones). */
  overflow-y: auto;
  transition: opacity 0.6s ease;
  animation: introFailsafe 14s forwards;
}
@media (min-width: 768px) { .intro { padding: 40px; } }

.intro.is-done {
  animation: none;
  opacity: 0;
  pointer-events: none;
}

@keyframes introFailsafe {
  0%, 95% { opacity: 1; }
  100% { opacity: 0; visibility: hidden; }
}

/* ---------- The terminal window ----------
   Phosphor green on near-black. The green is deliberately off-brand: it reads
   as a machine reporting, which is the point, and it hands the one orange
   accent in the box (the NOT FOUND verdict) all of the attention. */
.term {
  --term-fg: #4ADE80;
  --term-fg-dim: rgba(74, 222, 128, 0.6);
  --term-rule: rgba(74, 222, 128, 0.26);

  margin: auto;
  position: relative;
  width: 100%;
  max-width: 640px;
  overflow: hidden;
  background: #060A07;
  border: 1px solid var(--term-rule);
  border-radius: 5px;
  box-shadow: 0 0 70px rgba(74, 222, 128, 0.07), inset 0 0 60px rgba(74, 222, 128, 0.03);
  font-family: var(--font-mono);
  font-size: clamp(12.5px, 2.9vw, 15px);
  line-height: 1.75;
  color: var(--term-fg);
  /* Phosphor bloom. Subtle enough not to muddy the glyph edges. */
  text-shadow: 0 0 8px rgba(74, 222, 128, 0.3);
}

/* CRT scanlines. Static, so there is no motion to suppress. */
.term::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.028) 0 1px,
    transparent 1px 3px
  );
}

.term-head,
.term-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 16px;
  font-size: 0.86em;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--term-fg-dim);
}
.term-head { border-bottom: 1px solid var(--term-rule); }
.term-foot { border-top: 1px solid var(--term-rule); }

.term-body { padding: 16px; }

/* Each log line reserves its wrapped height up front (see `.term-line-ghost`),
   so the box is its finished size from the first frame and the border never
   grows as output arrives. */
.term-line { position: relative; margin: 0; }
.term-line-ghost { visibility: hidden; }
.term-line-live {
  position: absolute;
  inset: 0;
  visibility: hidden;
}
.term-line.is-started .term-line-live { visibility: visible; }

.term-prompt { color: var(--term-fg-dim); }

/* The verdict is the one thing in the box that isn't the machine's own voice,
   so it gets the brand accent. */
.term-line.is-alert .term-out { color: var(--accent); text-shadow: 0 0 10px rgba(255, 90, 31, 0.35); }
.term-line.is-note .term-out { color: var(--white); text-shadow: 0 0 8px rgba(250, 250, 250, 0.25); }

/* Block cursor. Sized in `ch` so it fills exactly one character cell of
   whichever monospace face the visitor actually has. */
.term-cursor {
  display: none;
  width: 1ch;
  height: 1.05em;
  vertical-align: -0.18em;
  background: var(--term-fg);
  box-shadow: 0 0 10px rgba(74, 222, 128, 0.55);
  animation: termBlink 1s step-end infinite;
}
.term-cursor.is-shown { display: inline-block; }

@keyframes termBlink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* Progress readout. `white-space: nowrap` keeps the meter on one line on
   narrow screens; the row wraps between meter and percentage instead. */
.term-meter { color: var(--term-fg); letter-spacing: 0.04em; white-space: nowrap; }
.term-meter-track { color: rgba(74, 222, 128, 0.17); text-shadow: none; }
.term-pct { color: var(--term-fg); font-variant-numeric: tabular-nums; }

.intro-skip {
  position: fixed;
  right: 20px;
  bottom: 20px;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding: 0 18px;
  border-radius: 5px;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-secondary-on-dark);
  /* On short phones the terminal box scrolls underneath it, so it carries
     its own backdrop rather than relying on the overlay behind it. */
  background: rgba(10, 10, 10, 0.78);
  border: 1px solid var(--border-on-dark);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.intro-skip:hover { color: var(--white); border-color: var(--white); }

@media (min-width: 768px) {
  .intro-skip { right: 32px; bottom: 32px; }
}

/* Locks the page behind the overlay while it plays. */
.intro-open, .intro-open body { overflow: hidden; }

/* =========================================================
   Hero device mockup — animated iPad
   Self-contained: every selector is `ipad-` prefixed and the canvas
   re-declares font/line-height/list-style so the site's global resets
   (`ul,ol{list-style:none;padding:0}`, `p{margin:0}`) can't leak in.
   ========================================================= */
.ipad-stage {
  position: relative;
  width: 100%;
  max-width: 1000px;
  aspect-ratio: 1920 / 1440;
  overflow: hidden;
  /* Rounded so the light photo backdrop reads as a framed shot rather
     than a hard rectangle cut into the black hero. */
  border-radius: 20px;
}

/* Designed at a fixed 1920x1440 and scaled to fit — keeps every
   px value in the device UI exactly as authored at any width. */
.ipad-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 1920px;
  height: 1440px;
  transform-origin: top left;
  transform: scale(var(--ipad-scale, 1));
  overflow: hidden;
  background: radial-gradient(ellipse 1400px 900px at 30% 20%, #cfd6da 0%, #aab3b8 45%, #8b959b 100%);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  color: #1c1c1e;
  text-align: left;
}

.ipad-vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 1600px 1100px at 70% 85%, rgba(255, 255, 255, 0.10) 0%, rgba(0, 0, 0, 0.25) 100%);
}

.ipad-body {
  position: absolute;
  left: 60px;
  top: 70px;
  width: 1800px;
  height: 1300px;
  border-radius: 90px;
  background: linear-gradient(155deg, #e9eaec 0%, #c7cacd 30%, #b3b6ba 55%, #dcdedf 100%);
  box-shadow: 0 60px 140px rgba(0, 0, 0, 0.45), inset 0 0 0 2px rgba(255, 255, 255, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
}

.ipad-camera {
  position: absolute;
  top: 34px;
  left: 50%;
  transform: translateX(-50%);
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #1a1c1e;
  box-shadow: 0 0 0 5px rgba(0, 0, 0, 0.06), inset 0 0 3px rgba(255, 255, 255, 0.3);
}

.ipad-bezel {
  width: 1740px;
  height: 1200px;
  border-radius: 64px;
  background: #050505;
  padding: 22px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.ipad-screen {
  width: 100%;
  height: 100%;
  border-radius: 44px;
  overflow: hidden;
  background: #ffffff;
  display: flex;
  position: relative;
}

/* Hides the scrollbars on the device's own scroll regions. */
.ipad-scroll { scrollbar-width: none; -ms-overflow-style: none; }
.ipad-scroll::-webkit-scrollbar { display: none; }

/* ---------- iPad: sidebar ---------- */
.ipad-sidebar {
  width: 340px;
  flex: none;
  background: #f7f6f4;
  border-right: 1px solid #e6e3dd;
  display: flex;
  flex-direction: column;
  padding: 22px 16px;
}

.ipad-brand { display: flex; align-items: center; gap: 10px; padding: 6px 8px 22px; }
.ipad-brand-mark {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: linear-gradient(135deg, #2b2d31, #111214);
  display: flex;
  align-items: center;
  justify-content: center;
}
.ipad-brand-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: linear-gradient(135deg, #ffd166, #ef6a5a);
}
.ipad-brand-name { font-size: 22px; font-weight: 700; letter-spacing: -0.2px; }

.ipad-nav-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border-radius: 12px;
  margin-bottom: 2px;
}
.ipad-nav-row.is-last { margin-bottom: 18px; }
.ipad-nav-label { font-size: 18px; font-weight: 500; color: #3a3a3c; }
.ipad-nav-label.is-strong { font-weight: 600; color: #1c1c1e; }

/* Thin-line icons, drawn in CSS to avoid extra assets. */
.ipad-ic { position: relative; flex: none; }
.ipad-ic-plus {
  width: 20px;
  height: 20px;
  border-radius: 6px;
  border: 2px solid #3a3a3c;
}
.ipad-ic-plus::before,
.ipad-ic-plus::after { content: ""; position: absolute; background: #3a3a3c; }
.ipad-ic-plus::before { left: 50%; top: 3px; bottom: 3px; width: 2px; transform: translateX(-50%); }
.ipad-ic-plus::after { top: 50%; left: 3px; right: 3px; height: 2px; transform: translateY(-50%); }
.ipad-ic-plus.is-lg { width: 26px; height: 26px; border-radius: 50%; border-color: #6b6b70; }
.ipad-ic-plus.is-lg::before { top: 5px; bottom: 5px; background: #6b6b70; }
.ipad-ic-plus.is-lg::after { left: 5px; right: 5px; background: #6b6b70; }

.ipad-ic-search { width: 16px; height: 16px; border-radius: 50%; border: 2px solid #6b6b70; }
.ipad-ic-search::after {
  content: "";
  position: absolute;
  width: 7px;
  height: 2px;
  background: #6b6b70;
  bottom: -4px;
  right: -5px;
  transform: rotate(45deg);
}
.ipad-ic-square { width: 16px; height: 16px; border: 2px solid #6b6b70; border-radius: 4px; }
.ipad-ic-circle { width: 16px; height: 16px; border: 2px solid #6b6b70; border-radius: 50%; }

.ipad-section-label {
  font-size: 13px;
  font-weight: 700;
  color: #9a9a9e;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  padding: 0 12px 10px;
}

.ipad-recent { display: flex; flex-direction: column; gap: 1px; overflow-y: auto; flex: 1; }
.ipad-recent-item {
  padding: 12px;
  border-radius: 10px;
  font-size: 17px;
  font-weight: 500;
  color: #3a3a3c;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ipad-recent-item.is-active { background: #efece6; font-weight: 600; color: #1c1c1e; }

.ipad-profile {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 10px 6px;
  margin-top: 8px;
  border-top: 1px solid #e6e3dd;
}
.ipad-profile-meta { display: flex; flex-direction: column; line-height: 1.2; }
.ipad-profile-name { font-size: 17px; font-weight: 700; }
.ipad-profile-plan { font-size: 14px; font-weight: 500; color: #9a9a9e; }

.ipad-avatar {
  flex: none;
  border-radius: 50%;
  background: linear-gradient(140deg, #f2b47e 0%, #d97b5a 100%);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  letter-spacing: 0.2px;
}
.ipad-avatar-sm { width: 38px; height: 38px; font-size: 17px; }
.ipad-avatar-md { width: 42px; height: 42px; font-size: 18px; box-shadow: 0 0 0 2px #fff, 0 0 0 3px #e6e3dd; }

/* ---------- iPad: main panel ---------- */
.ipad-main { flex: 1; display: flex; flex-direction: column; background: #ffffff; min-width: 0; }

.ipad-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px 40px 14px;
  flex: none;
}
.ipad-model { display: flex; align-items: center; gap: 6px; font-size: 23px; font-weight: 700; }
.ipad-caret-down {
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 7px solid #9a9a9e;
  margin-top: 3px;
}

.ipad-convo {
  flex: 1;
  overflow-y: auto;
  /* Positioning context for the auto-scroll offset maths in main.js. */
  position: relative;
  padding: 10px 60px 20px;
  display: flex;
  flex-direction: column;
  gap: 26px;
}

.ipad-ask-row {
  display: flex;
  justify-content: flex-end;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.ipad-ask-row.is-shown { opacity: 1; transform: translateY(0); }
.ipad-ask {
  max-width: 640px;
  background: #f0eee9;
  border-radius: 20px;
  padding: 18px 24px;
  font-size: 24px;
  line-height: 1.5;
  font-weight: 500;
}

.ipad-thinking { display: none; align-items: center; gap: 8px; padding: 6px 4px; }
.ipad-thinking.is-shown { display: flex; }
.ipad-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #9a9a9e;
  animation: ipadDotBounce 1.1s ease-in-out infinite;
}
.ipad-dot:nth-child(2) { animation-delay: 0.15s; }
.ipad-dot:nth-child(3) { animation-delay: 0.3s; }

@keyframes ipadDotBounce {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
  30% { transform: translateY(-6px); opacity: 1; }
}

.ipad-answer { max-width: 960px; font-size: 24px; line-height: 1.68; color: #2a2a2c; }
.ipad-answer p { margin: 0 0 18px; }
.ipad-answer p:last-child { margin-bottom: 0; }

.ipad-answer-list {
  list-style: decimal;
  margin: 0 0 18px;
  padding-left: 26px;
}
.ipad-answer-list > li { margin-bottom: 16px; }
.ipad-answer-list > li.is-last { margin-bottom: 0; }

.ipad-callout {
  list-style: none;
  margin-left: -26px;
  background: #fff7e6;
  border: 2px solid #f6c445;
  border-radius: 16px;
  padding: 16px 20px 16px 52px;
  position: relative;
}
.ipad-callout-num { position: absolute; left: 18px; top: 16px; font-weight: 700; color: #8a5b00; }
.ipad-callout-title { color: #8a5b00; }

/* Each answer chunk fades in on its own beat. */
.ipad-chunk {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.45s ease, transform 0.45s ease;
}
.ipad-chunk.is-shown { opacity: 1; transform: translateY(0); }

.ipad-composer { flex: none; padding: 16px 60px 30px; }
.ipad-input {
  display: flex;
  align-items: center;
  gap: 16px;
  background: #f4f3f0;
  border-radius: 32px;
  padding: 16px 22px;
  box-shadow: inset 0 0 0 1px #e6e3dd;
}
.ipad-input-text { flex: 1; font-size: 21px; font-weight: 500; color: #1c1c1e; }
.ipad-input-text.is-placeholder { color: #9a9a9e; }

.ipad-caret {
  display: none;
  border-left: 2px solid #3a3a3c;
  margin-left: 1px;
  animation: ipadCaretBlink 1s step-end infinite;
}
.ipad-caret.is-shown { display: inline-block; }
.ipad-caret::before { content: "\00a0"; }

@keyframes ipadCaretBlink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

.ipad-send {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: #1c1c1e;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.ipad-send::after {
  content: "";
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 9px solid #fff;
}

/* ---------- iPad: small screens ----------
   Below this width, scaling the 1920px canvas down would shrink the
   conversation past legibility (the callout is the whole point of the
   visual). So drop the fixed-canvas scaling and let the same markup
   reflow fluidly: sidebar off, device chrome slimmed, type resized. */
@media (max-width: 860px) {
  .ipad-stage {
    aspect-ratio: auto;
    border-radius: 16px;
  }
  .ipad-canvas {
    position: static;
    width: 100%;
    height: auto;
    transform: none;
    background: linear-gradient(160deg, #c6ced3 0%, #9aa3a9 100%);
    padding: 14px;
  }
  .ipad-vignette { display: none; }

  .ipad-body {
    position: static;
    width: 100%;
    height: auto;
    border-radius: 26px;
    padding: 12px;
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35), inset 0 0 0 1px rgba(255, 255, 255, 0.4);
  }
  .ipad-camera { display: none; }

  .ipad-bezel {
    width: 100%;
    height: auto;
    border-radius: 18px;
    padding: 8px;
  }
  .ipad-screen { border-radius: 12px; height: auto; }

  .ipad-sidebar { display: none; }

  .ipad-topbar { padding: 12px 14px 8px; }
  .ipad-model { font-size: 13px; }
  .ipad-avatar-md { width: 26px; height: 26px; font-size: 12px; }

  .ipad-convo {
    padding: 4px 14px 10px;
    gap: 14px;
    overflow: visible;
  }

  .ipad-ask { font-size: 13px; padding: 10px 13px; border-radius: 14px; max-width: 88%; }

  .ipad-answer { font-size: 13px; line-height: 1.55; }
  .ipad-answer p { margin: 0 0 10px; }
  .ipad-answer-list { margin: 0 0 10px; padding-left: 18px; }
  .ipad-answer-list > li { margin-bottom: 9px; }
  .ipad-callout {
    margin-left: -18px;
    border-radius: 10px;
    border-width: 1.5px;
    padding: 10px 12px 10px 32px;
  }
  .ipad-callout-num { left: 11px; top: 10px; }

  .ipad-dot { width: 7px; height: 7px; }

  .ipad-composer { padding: 6px 14px 14px; }
  .ipad-input { padding: 9px 12px; gap: 9px; border-radius: 20px; }
  .ipad-input-text { font-size: 12px; }
  .ipad-ic-plus.is-lg { width: 17px; height: 17px; }
  .ipad-ic-plus.is-lg::before { top: 3px; bottom: 3px; }
  .ipad-ic-plus.is-lg::after { left: 3px; right: 3px; }
  .ipad-send { width: 24px; height: 24px; }
  .ipad-send::after { border-left-width: 4px; border-right-width: 4px; border-bottom-width: 6px; }
}

/* ---------- Trust bar ---------- */
.trust-bar {
  background: var(--white);
  border-bottom: 1px solid var(--border-on-light);
  padding: 28px 0;
}
.trust-inner {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
  justify-content: space-between;
}
@media (min-width: 768px) {
  .trust-inner { flex-direction: row; align-items: center; gap: 24px; }
}
.trust-locations {
  font-size: 13px;
  color: var(--text-secondary-on-light);
  letter-spacing: 0.01em;
}
.trust-quote {
  font-size: 13px;
  color: var(--text-secondary-on-light);
  font-style: italic;
}
.trust-quote span { font-style: normal; color: var(--text-muted-on-light); }

/* ---------- Sections (generic) ---------- */
.section {
  padding: var(--section-pad) 0;
  background: var(--white);
  color: var(--black);
}
.section-dark {
  background: var(--black);
  color: var(--white);
}

.section-label {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 24px;
}
/* Editorial rule trailing the label — anchors each section to the grid
   without adding a box or shadow. */
.section-label::after {
  content: "";
  flex: 1;
  max-width: 88px;
  height: 1px;
  background: currentColor;
  opacity: 0.35;
}

.section-headline {
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.1;
  max-width: 720px;
}
@media (min-width: 768px) { .section-headline { font-size: 48px; } }
@media (min-width: 1200px) { .section-headline { font-size: 58px; } }

/* ---------- Shift section ---------- */
.shift-section { text-align: left; }
.shift-lines {
  margin-top: 64px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.shift-lines p {
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text-secondary-on-dark);
}
.shift-lines p:last-child { color: var(--white); }
@media (min-width: 768px) {
  .shift-lines p { font-size: 34px; }
}

/* ---------- Platforms ---------- */
.platforms {
  padding: 64px 0;
  background: var(--white);
  border-bottom: 1px solid var(--border-on-light);
}
.platforms-label {
  font-size: 13px;
  color: var(--text-muted-on-light);
  text-align: center;
  margin-bottom: 32px;
  letter-spacing: 0.02em;
}
.platforms-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 20px 40px;
}
.platforms-row li {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 16px;
  font-weight: 600;
  color: var(--text-secondary-on-light);
  letter-spacing: -0.01em;
  transition: color 0.25s ease, transform 0.25s ease;
}
/* Marks inherit `currentColor`, so they darken with the label on hover rather
   than needing a hover rule of their own. */
.platform-icon {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--text-muted-on-light);
  transition: color 0.25s ease;
}
.platform-icon svg { width: 100%; height: 100%; }
.platforms-row li:hover .platform-icon { color: var(--accent); }
/* Darkens rather than tinting: accent sits at roughly 3.2:1 on
   `--white`, under AA for text at this size. */
.platforms-row li:hover { color: var(--text-on-light); transform: translateY(-3px); }

/* ---------- Problem section ---------- */
.problem-grid {
  margin-top: 64px;
  display: grid;
  gap: 48px;
}
/* Asymmetric 7/5 split rather than a centered 50/50 — the prose column reads
   as body text, the stat column as a pulled callout. */
@media (min-width: 900px) {
  .problem-grid {
    grid-template-columns: 7fr 5fr;
    gap: 88px;
    align-items: start;
  }
}
.problem-copy p {
  font-size: 17px;
  color: var(--text-secondary-on-light);
  max-width: 480px;
}
.problem-stat {
  position: relative;
  isolation: isolate;
  border-top: 2px solid var(--accent);
  padding-top: 28px;
}
/* Hover surface. The stat sits flush in the grid with no box of its own, so
   the card face is a pseudo-element behind the content — it can bleed past the
   text without shifting layout. Held below the accent rule (top: 0) so that
   rule stays the sharp edge of the card. The element itself carries `.reveal`,
   whose entrance owns `transform`, so the hover motion is on a child. */
.problem-stat::before {
  content: "";
  position: absolute;
  inset: 0 -22px -20px;
  z-index: -1;
  border-radius: 0 0 16px 16px;
  background: rgba(10, 10, 10, 0.03);
  opacity: 0;
  transition: opacity 0.3s ease;
}
.problem-stat:hover::before { opacity: 1; }
.problem-stat:hover .stat-number { transform: translateY(-2px); }
.stat-number {
  font-size: 64px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: -0.04em;
  line-height: 1;
  margin-bottom: 16px;
  transition: transform 0.3s ease;
}
@media (min-width: 1200px) { .stat-number { font-size: 76px; } }
.stat-label { font-size: 15px; color: var(--text-secondary-on-light); max-width: 360px; }
.stat-footnote { font-size: 12px; color: var(--text-muted-on-light); margin-top: 12px; }

/* ---------- Services ---------- */
.services-grid {
  margin-top: 64px;
  display: grid;
  border-top: 1px solid var(--border-on-dark);
}
@media (min-width: 768px) {
  .services-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .services-grid { grid-template-columns: repeat(3, 1fr); }
}

.service {
  position: relative;
  padding: 40px 8px 40px 0;
  border-bottom: 1px solid var(--border-on-dark);
  display: flex;
  flex-direction: column;
  gap: 12px;
  transition: background-color 0.3s ease;
}
@media (min-width: 768px) {
  .service { padding: 44px 32px; border-right: 1px solid var(--border-on-dark); }
}

/* Accent rule that wipes in over the cell's own bottom border. Absolutely
   positioned, so the featured card's grid-template-areas can't auto-place it
   as a grid item. These cards are also `.reveal` elements, whose entrance owns
   `transform` on the element itself — so the hover motion lives on children. */
.service::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s ease;
}

.service:hover,
.service:focus-visible { background: rgba(250, 250, 250, 0.045); }
.service:hover::after,
.service:focus-visible::after { transform: scaleX(1); }
.service:hover .service-icon,
.service:focus-visible .service-icon { transform: translateY(-3px) scale(1.08); }
.service:hover h3,
.service:focus-visible h3 { color: var(--accent); }
.service:hover .service-arrow,
.service:focus-visible .service-arrow { transform: translateX(6px); }

.service-icon {
  width: 28px;
  height: 28px;
  color: var(--accent);
  transition: transform 0.3s ease;
}
.service-icon svg { width: 100%; height: 100%; }

.service h3 { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; transition: color 0.25s ease; }
.service p { font-size: 14.5px; color: var(--text-secondary-on-dark); max-width: 320px; }
.service-arrow {
  margin-top: 4px;
  font-size: 16px;
  color: var(--accent);
  align-self: flex-start;
  transition: transform 0.3s ease;
}

/* The lead service spans the row. Declared AFTER the generic `.service h3`
   rule: both have equal specificity (0,1,1), so source order decides — putting
   these first would let the 19px generic size silently win. */
.service-featured { grid-column: 1 / -1; }
.service-featured h3 { font-size: 28px; letter-spacing: -0.03em; }
@media (min-width: 768px) { .service-featured h3 { font-size: 34px; } }

/* On wide screens the copy sits beside the title rather than stacking, so the
   full-bleed row carries weight instead of trailing dead space. */
@media (min-width: 1024px) {
  .service-featured {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "icon  copy"
      "title copy"
      "arrow copy";
    align-content: start;
    column-gap: 48px;
    row-gap: 14px;
  }
  .service-featured .service-icon  { grid-area: icon; }
  .service-featured h3             { grid-area: title; }
  .service-featured p              { grid-area: copy; align-self: center; font-size: 16px; max-width: 420px; }
  .service-featured .service-arrow { grid-area: arrow; }
}

/* ---------- Process ---------- */
.process-list {
  margin-top: 64px;
  display: flex;
  flex-direction: column;
}
@media (min-width: 1024px) {
  .process-list { flex-direction: row; gap: 24px; }
}

.process-step {
  padding: 28px 0;
  border-top: 1px solid var(--border-on-light);
  transition: border-color 0.3s ease;
}
.process-step:last-child { border-bottom: 1px solid var(--border-on-light); }
@media (min-width: 1024px) {
  .process-step {
    flex: 1;
    padding: 0 24px 0 0;
    border-top: none;
    border-left: 1px solid var(--border-on-light);
    padding-left: 20px;
  }
  .process-step:last-child { border-bottom: none; }
}

/* The step's rule is its only chrome, so hover lights it up rather than
   drawing a box. Stacked, that rule is the top border; in the desktop row it
   becomes the left border — both are recoloured so the affordance follows the
   layout. `transform` on the step itself belongs to `.reveal`, hence the
   nudge sits on the number. */
.process-step:hover {
  border-top-color: var(--accent);
  border-bottom-color: var(--accent);
}
@media (min-width: 1024px) {
  .process-step:hover { border-left-color: var(--accent); }
}
.process-step:hover .process-number { transform: translateX(4px); }

.process-number {
  display: block;
  font-size: 14px;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 10px;
  letter-spacing: 0.02em;
  transition: transform 0.3s ease;
}
.process-step h3 { font-size: 18px; font-weight: 600; margin-bottom: 8px; letter-spacing: -0.01em; }
.process-step p { font-size: 14px; color: var(--text-secondary-on-light); }

/* ---------- Results ---------- */
.results-grid {
  margin-top: 64px;
  display: grid;
  gap: 40px;
}
@media (min-width: 768px) {
  .results-grid { grid-template-columns: repeat(3, 1fr); gap: 32px; }
}
/* Same pseudo-element card face as `.problem-stat`, tuned for the dark
   surface. Nothing is drawn until hover, so the row stays a clean grid of
   numbers at rest. */
.result-stat {
  position: relative;
  isolation: isolate;
}
.result-stat::before {
  content: "";
  position: absolute;
  inset: -20px -22px;
  z-index: -1;
  border-radius: 16px;
  background: rgba(250, 250, 250, 0.05);
  opacity: 0;
  transition: opacity 0.3s ease;
}
.result-stat:hover::before { opacity: 1; }
.result-stat:hover .result-number { transform: translateY(-3px); }

.result-number {
  font-size: 56px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: -0.04em;
  line-height: 1;
  margin-bottom: 14px;
  transition: transform 0.3s ease;
}
@media (min-width: 768px) { .result-number { font-size: 68px; } }
.result-label { font-size: 15px; color: var(--text-secondary-on-dark); max-width: 260px; }
.results-footnote { margin-top: 48px; font-size: 12.5px; color: var(--text-muted-on-dark); }

/* ---------- About ---------- */
.about-grid {
  display: grid;
  gap: 40px;
}
@media (min-width: 900px) {
  .about-grid { grid-template-columns: auto 1fr; gap: 56px; align-items: start; }
}
.about-avatar {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  border: 1px solid var(--border-on-light);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted-on-light);
  transition: border-color 0.3s ease, color 0.3s ease;
}
.about-avatar svg { width: 36px; height: 36px; transition: transform 0.35s ease; }
.about-avatar:hover { border-color: var(--accent); color: var(--accent); }
.about-avatar:hover svg { transform: scale(1.1); }
.about-copy p {
  margin-top: 24px;
  font-size: 17px;
  color: var(--text-secondary-on-light);
  max-width: 560px;
}

/* ---------- FAQ ---------- */
.faq-list {
  margin-top: 56px;
  border-top: 1px solid var(--border-on-light);
}
.faq-item { position: relative; border-bottom: 1px solid var(--border-on-light); }
/* Accent rule wiping in over the row's own bottom border — same gesture as the
   service cards. It stays drawn while the row is open, so the expanded panel
   reads as attached to its question. */
.faq-item::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1.5px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s ease;
}
.faq-item:hover::after,
.faq-item.open::after { transform: scaleX(1); }
/* Indents the question rather than tinting it — same AA reason as the
   platform row. Padding, not transform, so the icon stays pinned right. */
.faq-item:hover .faq-trigger { padding-left: 8px; }
.faq-item:hover .faq-icon::before,
.faq-item:hover .faq-icon::after { background: var(--accent); }

.faq-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 26px 0;
  font-size: 17px;
  font-weight: 500;
  text-align: left;
  letter-spacing: -0.01em;
  transition: padding-left 0.25s ease;
}
@media (min-width: 768px) { .faq-trigger { font-size: 19px; } }

.faq-icon {
  position: relative;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
}
.faq-icon::before, .faq-icon::after {
  content: "";
  position: absolute;
  background: var(--black);
  top: 50%;
  left: 50%;
  transition: transform 0.25s ease, background-color 0.25s ease;
}
.faq-icon::before { width: 18px; height: 1.5px; transform: translate(-50%, -50%); }
.faq-icon::after { width: 1.5px; height: 18px; transform: translate(-50%, -50%); }
.faq-trigger[aria-expanded="true"] .faq-icon::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }

.faq-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s ease;
}
.faq-panel > p {
  overflow: hidden;
  min-height: 0;
  font-size: 15px;
  color: var(--text-secondary-on-light);
  max-width: 640px;
  padding-bottom: 0;
}
.faq-item.open .faq-panel { grid-template-rows: 1fr; }
.faq-item.open .faq-panel > p { padding-bottom: 26px; }

/* ---------- Final CTA ---------- */
.final-cta {
  background: var(--black);
  color: var(--white);
  padding: var(--section-pad) 0;
  text-align: center;
}
.final-cta-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
}
.final-cta h2 {
  font-size: 36px;
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.08;
  max-width: 700px;
}
@media (min-width: 768px) { .final-cta h2 { font-size: 54px; } }

/* ---------- Footer ---------- */
.site-footer {
  background: var(--black);
  color: var(--text-secondary-on-dark);
  padding: 72px 0 28px;
  border-top: 1px solid var(--border-on-dark);
}
.footer-inner {
  display: grid;
  gap: 48px;
}
@media (min-width: 900px) {
  .footer-inner { grid-template-columns: 1.4fr 1fr 1fr; gap: 32px; }
}
.footer-brand .logo { color: var(--white); }
.footer-tagline { margin-top: 14px; font-size: 14px; max-width: 300px; }

.footer-nav ul { display: flex; flex-direction: column; }
/* Link text stays 14px, but the hit area is padded out to the 44px minimum.
   Negative margin keeps the visual rhythm identical to the unpadded version. */
.footer-nav a {
  display: block;
  font-size: 14px;
  padding: 11px 0;
  transition: color 0.2s ease;
}
.footer-nav a:hover { color: var(--white); }

.footer-contact { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
@media (min-width: 900px) { .footer-contact { align-items: flex-end; } }
.footer-contact > a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  font-size: 14px;
  transition: color 0.2s ease;
}
.footer-contact > a:hover { color: var(--white); }

.footer-social { display: flex; gap: 4px; margin-left: -10px; }
@media (min-width: 900px) { .footer-social { margin-left: 0; margin-right: -10px; } }
.footer-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min);
  height: var(--tap-min);
  color: var(--text-secondary-on-dark);
  transition: color 0.2s ease;
}
.footer-social a svg { width: 18px; height: 18px; }
.footer-social a:hover { color: var(--accent); }

.footer-bottom {
  margin-top: 56px;
  padding-top: 24px;
  border-top: 1px solid var(--border-on-dark);
}
.footer-bottom p { font-size: 12.5px; color: var(--text-muted-on-dark); }

/* ---------- Reduced motion ----------
   The global rule near the top collapses transition durations, which stops the
   card hovers animating but still lets them jump. These are decorative, so
   drop the movement entirely and keep the colour and surface cues. */
@media (prefers-reduced-motion: reduce) {
  .service:hover .service-icon,
  .service:focus-visible .service-icon,
  .service:hover .service-arrow,
  .service:focus-visible .service-arrow,
  .process-step:hover .process-number,
  .problem-stat:hover .stat-number,
  .result-stat:hover .result-number,
  .platforms-row li:hover,
  .about-avatar:hover svg { transform: none; }
  .faq-item:hover .faq-trigger { padding-left: 0; }
}

/* ---------- Typed headings ----------
   Headings type themselves out when they scroll into view. js/main.js wraps
   every character in its own span; only `opacity` is animated, so each glyph
   holds its place from the first frame and the line never reflows as it
   fills. That also means the full text is in the DOM for search engines and
   screen readers whether or not the animation ever runs.

   Words are wrapped too — `.type-word` keeps `white-space: nowrap` so a line
   can never break in the middle of one. */
.type-word { white-space: nowrap; }

/* A highlighted run inside a typed heading is a big block of colour that would
   otherwise sit empty until the caret reached it. `.type-heading` is set by the
   script, so with no JS the highlight just shows as authored. */
.type-heading .highlight { opacity: 0; transition: opacity 0.3s ease; }
.type-heading .highlight.is-lit { opacity: 1; }
.type-char { opacity: 0; }
.type-char.is-typed { opacity: 1; }

/* Absolutely positioned so moving it between characters costs no reflow;
   js/main.js parks it after the last revealed glyph. */
.type-caret {
  position: absolute;
  width: 3px;
  background: var(--accent);
  opacity: 0;
  pointer-events: none;
  animation: typeCaretBlink 0.9s step-end infinite;
}
.type-caret.is-shown { opacity: 1; }

@keyframes typeCaretBlink {
  0%, 54% { opacity: 1; }
  55%, 100% { opacity: 0; }
}

/* A heading mid-type is a partial sentence, so it is hidden from assistive
   tech until it is complete; `.type-source` carries the real text for them. */
.type-source {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
