/* Marketing landing page (public/landing.html) — plain, self-hosted, no
   build step, served at "/" (see worker/index.ts's own routing comment).
   Loaded alongside ../legal.css (terms.html/privacy.html/support.html's own
   stylesheet), which already defines the shared --paper/--ink/--ink-muted/
   --ink-faint tokens matching the app's light-mode palette (src/index.css) —
   this file only adds the accent color, font, and this page's own layout on
   top, rather than re-typing those same four hex values a third time. */

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("./fonts/space-grotesk-latin.woff2") format("woff2");
}

:root {
  --orange: #e2601f;
}

/* Light-mode only, deliberately — unlike legal.css's plain text, this page's
   gallery leads with a recorded demo video that's baked in light mode and
   wouldn't itself adapt, so a dark shell around it would just look broken. */

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  /* Overrides legal.css's own body padding — this page lays out spacing
     itself via .wrap/section rules below instead. */
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Space Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif;
  line-height: 1.5;
}

a {
  color: inherit;
}

.wrap {
  max-width: 56rem;
  margin: 0 auto;
  padding: 0 1.25rem;
}

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

header.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 0;
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 900;
  font-size: 1.15rem;
  letter-spacing: 0.02em;
  text-decoration: none;
}

.wordmark img {
  border-radius: 0.25rem;
}

.btn {
  display: inline-block;
  font-weight: 800;
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.65rem 1.25rem;
  border: 2.5px solid var(--ink);
  cursor: pointer;
}

.btn-primary {
  background: var(--orange);
  border-color: var(--orange);
  color: #fff;
}

.btn-ghost {
  background: transparent;
  color: var(--ink);
}

/* ---- Hero ---- */

.hero {
  padding: 1.5rem 0 2rem;
  text-align: center;
}

.hero .eyebrow {
  font-size: 0.85rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--orange);
  /* margin-bottom only — see .hero .note's own comment on why the shorthand
     broke centering here too. */
  margin-bottom: 0.5rem;
}

.hero h1 {
  font-size: clamp(1.75rem, 5vw, 2.75rem);
  font-weight: 900;
  letter-spacing: 0.01em;
  line-height: 1.05;
  margin: 0 0 0.75rem;
  text-transform: uppercase;
}

.hero h1 span {
  color: var(--orange);
}

.hero p {
  max-width: 34rem;
  margin: 0 auto 1rem;
  color: var(--ink-muted);
  font-size: 1rem;
}

.platforms {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
}

.platforms .chip {
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink-muted);
  border: 1.5px solid var(--ink-faint);
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
}

/* ---- Gallery ---- */

.gallery {
  position: relative;
  /* Capped and centered — the frame's own aspect-ratio (see below) is now
     taller than wide, so without a cap here it'd stretch to .wrap's full
     56rem width on desktop and end up unreasonably tall (56rem wide would
     mean a frame over 60rem/~960px tall). This keeps it a sensible hero-
     gallery size on any viewport instead of just solving mobile. */
  max-width: 34rem;
  margin: 0 auto 2.5rem;
  background: var(--paper);
}

.gallery .frame {
  position: relative;
  /* Matches the video/screenshots' own cropped dimensions exactly (see
     record-landing-demo.mjs's OUTPUT_WIDTH/OUTPUT_HEIGHT and
     record-landing-screenshots.mjs's CONTENT_CLIP) — cropped tight to the
     app's own real content instead of the wider 16:10 capture frame, which
     used to leave a lot of blank margin on a narrow (phone-width) gallery. */
  aspect-ratio: 740 / 800;
  overflow: hidden;
  cursor: grab;
  /* Leaves vertical page scrolling to the browser on touch — only
     horizontal drags are ours to handle (see landing.html's pointer
     handlers). */
  touch-action: pan-y;
}

.gallery .frame.dragging {
  cursor: grabbing;
}

.gallery .frame:focus-visible {
  outline: 2.5px solid var(--orange);
  outline-offset: -2.5px;
}

/* Tap-to-pause feedback: a faint icon flashed over the video, mirroring the
   play/pause state the click just switched to, then faded out again —
   never a persistent overlay, so it doesn't compete with the video itself
   while paused. */
.gallery .tap-feedback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.gallery .tap-feedback.visible {
  opacity: 1;
  transition: opacity 0.05s ease;
}

.gallery .tap-feedback svg {
  width: 4.5rem;
  height: 4.5rem;
  padding: 1.25rem;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.45);
  color: var(--paper);
  /* Re-inserted fresh (via innerHTML) on every tap, so a new element — and
     this animation — is created each time, letting it replay on repeated
     taps instead of only firing once. */
  animation: tap-feedback-pop 0.25s ease;
}

@keyframes tap-feedback-pop {
  from {
    transform: scale(0.6);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}

/* A plain `.nav` (same size/border/hover as prev/next — see the class list
   in landing.html) living in the same .controls row, not an overlay on the
   video itself — see landing.html's own comment on why an overlaid version
   (tried twice, pinned to different corners of .frame) kept either landing
   on the recorded video's own Settings icon or spilling past the page's
   edge on some viewport width. Hidden on every slide but the video (index
   0) — landing.html's own show() toggles this class alongside the slide
   switch; nothing to mute/unmute over a plain screenshot. */
.gallery .mute-toggle.hidden {
  /* NOT display:none — see .controls' own comment on why this column needs
     to keep reserving its width even while hidden. */
  visibility: hidden;
}

.gallery .track {
  display: flex;
  height: 100%;
  /* Overridden inline (transform + its own transition) by the drag/show()
     logic in landing.html — this is only the resting starting point. */
  transform: translateX(0);
}

.gallery .track > * {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: top center;
  /* Drag-select highlighting a slide mid-swipe reads as a UI glitch, not a
     real text/image/video selection. */
  user-select: none;
  -webkit-user-drag: none;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* Two equal outer columns (not e.g. auto/1fr) so .nav-group in the middle
   one is centered exactly the way a plain centered flex row of just
   prev/dots/next would be — the mute-toggle column on the right is mirrored
   by an equal-width empty column on the left purely to keep that centering,
   not because anything belongs there. */
.gallery .controls {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0.75rem 0;
}

.gallery .nav-group {
  grid-column: 2;
  display: flex;
  align-items: center;
  gap: 1.25rem;
}

.gallery .mute-toggle {
  grid-column: 3;
  justify-self: end;
}

.gallery .nav {
  width: 2.25rem;
  height: 2.25rem;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font-size: 1.1rem;
  font-weight: 900;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.gallery .nav:hover {
  background: var(--ink);
  color: var(--paper);
}

.gallery .dots {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.gallery .dots button {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  border: 1.5px solid var(--ink);
  background: transparent;
  padding: 0;
  cursor: pointer;
}

.gallery .dots button.active {
  background: var(--orange);
  border-color: var(--orange);
}

/* ---- Features ---- */

.features {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
  margin-bottom: 2.5rem;
}

.feature-card {
  border: 2.5px solid var(--ink);
  padding: 1.25rem;
  transition: transform 0.15s ease;
}

.feature-card:hover {
  transform: translateY(-2px);
}

.feature-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.4rem;
}

.feature-icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--orange);
}

.features h2 {
  font-size: 0.95rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin: 0;
}

.features p {
  margin: 0;
  color: var(--ink-muted);
  font-size: 0.92rem;
}

@media (max-width: 640px) {
  .features {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  /* The fixed 3-column grid (see footer .links above) doesn't wrap — at
     narrow widths, stack the links instead of letting them overflow. Each
     is centered on its own line, so "Support" stays centered here too. */
  footer .links {
    grid-template-columns: 1fr;
    gap: 0.5rem;
  }

  footer .links a {
    justify-self: center;
  }
}

/* ---- FAQ ---- */

.faq {
  border-top: 1.5px dashed var(--ink-faint);
  padding: 1.5rem 0 0.5rem;
}

.faq-title {
  /* Deliberately much larger than .features h2/.eyebrow's small-label
     size (0.95rem) — at that size "FAQ" read as another subtitle/eyebrow
     rather than this section's own heading. */
  font-size: 1.5rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  margin: 0 0 1.25rem;
  text-align: center;
}

.faq-item {
  max-width: 38rem;
  margin: 0 auto;
  padding: 0.85rem 0;
  border-top: 1px solid var(--ink-faint);
}

.faq-item:first-of-type {
  border-top: none;
}

.faq-item summary {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-right: 1.5rem;
  font-size: 0.95rem;
  font-weight: 800;
  cursor: pointer;
  list-style: none;
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

/* A drawn "+" (two bars) rather than a "+"/"−" text swap — a content
   change can't transition, but the vertical bar scaling away to leave just
   the horizontal one (i.e. a "−") can, for a quick, tasteful open/close
   morph instead of an instant flip. */
.faq-item summary::before,
.faq-item summary::after {
  content: "";
  position: absolute;
  /* right/top mark the CENTER point (not a corner) for both bars — the
     translate(50%, -50%) below re-centers whatever box is positioned here
     on that exact point regardless of its own width/height, which is what
     actually guarantees the two differently-sized bars land dead center on
     each other. Anchoring by an edge instead (as an earlier version of this
     did) requires separately hand-tuning each bar's offset to compensate
     for its own size, which is exactly what drifted them off-center. */
  right: 0.75rem;
  top: 50%;
  background: var(--orange);
  transition: transform 0.1s ease;
}

.faq-item summary::before {
  width: 0.7rem;
  height: 2px;
  transform: translate(50%, -50%);
}

.faq-item summary::after {
  width: 2px;
  height: 0.7rem;
  transform: translate(50%, -50%);
}

/* .is-open, not [open], is the source of truth for ALL open-visual-state
   CSS below — the JS keeps the native `open` attribute true for the whole
   close animation (so the content stays visible while it collapses) and
   only flips it off once that finishes, so anything gated on [open] instead
   would visibly lag behind the content, surfacing as a second animation
   after the first already finished. .is-open is toggled by JS right when a
   click starts. Any future open/closed styling on .faq-item should key off
   .is-open too; [open] is reserved for accessibility semantics only. */
.faq-item.is-open summary::after {
  transform: translate(50%, -50%) scaleY(0);
}

.faq-item p {
  --faq-gap: 0.6rem;
  overflow: hidden;
  height: 0;
  margin-top: 0;
  color: var(--ink-muted);
  font-size: 0.9rem;
  /* Height is driven from JS (landing.html) — native <details> has no
     open/close transition of its own to hook into (content just
     mounts/unmounts with display), so this animates between explicit pixel
     values it sets rather than relying on `auto`. margin-top has no such
     measurement step, so it's a plain two-value CSS transition off
     .is-open instead. */
  transition: height 0.1s ease, margin-top 0.1s ease;
}

.faq-item.is-open p {
  margin-top: var(--faq-gap);
}

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

footer {
  border-top: 1.5px dashed var(--ink-faint);
  padding: 1.25rem 0 2rem;
  text-align: center;
}

/* Grid with two equal outer columns, not flex — "Terms of Service" and
   "Privacy Policy" are different widths, so a flex row centered as a whole
   group still leaves "Support" off-center in the middle. The equal 1fr
   columns keep the true midpoint fixed regardless of the side links'
   widths, and "Support" is centered within its own middle column. */
footer .links {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1.25rem;
  font-size: 0.85rem;
  margin-bottom: 0.5rem;
}

footer .links a:first-child {
  justify-self: end;
}

footer .links a:nth-child(2) {
  justify-self: center;
}

footer .links a:last-child {
  justify-self: start;
}

footer .links a {
  text-decoration: none;
}

footer .links a:hover {
  text-decoration: underline;
}

footer .copyright {
  color: var(--ink-faint);
  font-size: 0.8rem;
}
