/*
 * NoPrompt — noprompt.app
 *
 * Colours come from the app rather than being invented: the neutral surfaces
 * and #ef4444 (`primary-500`) are lifted from apps/mobile/tailwind.config.js.
 * Someone arriving from a shared link should recognise the thing they are about
 * to install.
 *
 * The visual language follows what current app landing pages actually do —
 * dark-first, bento tiles with heavy corner rounding, oversized type carrying
 * the value proposition, a dimensional device mock, and layered gradients for
 * depth. Deliberately restrained with it: the loud gradient-soup era is over,
 * and for a product whose pitch is "no filters" a page that looked
 * over-produced would argue against itself.
 *
 * No build step, no framework, no JavaScript. Motion is CSS scroll-driven
 * animation behind an @supports guard, so a browser without it simply shows
 * the content.
 */

:root {
  --bg: #141414;
  --bg-lift: #1c1c1c;
  --surface: #242424;
  --border: #333;
  --border-soft: #2a2a2a;
  --text: #fafafa;
  --muted: #a8a8a8;
  --dim: #6f6f6f;
  --accent: #ef4444;
  --accent-soft: rgba(239, 68, 68, 0.14);
  --measure: 34rem;
  --radius: 1.5rem;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /*
   * `clip`, not `hidden`. Setting overflow-x to hidden forces overflow-y to
   * compute to auto, which turns <body> into a scroll container — and a sticky
   * child then resolves against a box that never itself scrolls, so the glass
   * header quietly stopped sticking. `clip` trims the same overflow without
   * creating a scroll container. `hidden` stays first as the fallback for
   * anything that does not understand `clip`.
   */
  overflow-x: hidden;
  overflow-x: clip;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: #fff;
  padding: 0.75rem 1rem;
  z-index: 20;
}

.skip-link:focus {
  left: 0;
}

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.wrap {
  max-width: 68rem;
  margin: 0 auto;
  padding: 0 1.5rem;
}

/* --------------------------------------------------------------------------
   Header — glass, so the hero bloom reads through it on scroll.
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  border-bottom: 1px solid var(--border-soft);
  background: rgba(20, 20, 20, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 1rem;
  padding-bottom: 1rem;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text);
  text-decoration: none;
  letter-spacing: -0.02em;
}

.wordmark img {
  width: 28px;
  height: 28px;
  border-radius: 8px;
}

.site-header nav {
  display: flex;
  gap: 1.4rem;
  font-size: 0.92rem;
}

.site-header nav a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.18s ease;
}

.site-header nav a:hover {
  color: var(--text);
}

/* --------------------------------------------------------------------------
   Hero
   --------------------------------------------------------------------------
   Tight by design: the headline, the value proposition and the primary CTA all
   have to clear the fold, and the fold on a phone is short. The copy is written
   short enough for the small canvas rather than scaled down into it.
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  padding: 3.5rem 0 4rem;
}

/*
 * Ambient bloom. Two offset radial gradients rather than one flat wash — the
 * overlap is what reads as depth instead of as a coloured rectangle.
 * Pointer-events off so it can never intercept a tap.
 */
.hero::before {
  content: '';
  position: absolute;
  inset: -30% -20% auto -20%;
  height: 46rem;
  pointer-events: none;
  background:
    radial-gradient(48% 40% at 22% 30%, rgba(239, 68, 68, 0.16), transparent 70%),
    radial-gradient(40% 38% at 78% 18%, rgba(120, 120, 255, 0.07), transparent 70%);
  filter: blur(12px);
}

.hero-grid {
  position: relative;
  display: grid;
  gap: 3.5rem;
  align-items: center;
}

@media (min-width: 62rem) {
  .hero {
    padding: 5rem 0 6rem;
  }

  .hero-grid {
    grid-template-columns: 1fr minmax(18rem, 21rem);
    gap: 4.5rem;
  }
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 1.25rem;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--accent-soft);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}

.eyebrow::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

/* Oversized type carrying the value proposition, in place of a hero image. */
.hero h1 {
  margin: 0 0 1.35rem;
  font-size: clamp(2.4rem, 6.5vw, 4.25rem);
  line-height: 1.02;
  letter-spacing: -0.04em;
  font-weight: 800;
  max-width: 14ch;
}

/*
 * The pivot word. `color: transparent` is only survivable once the clip is
 * known to work — unguarded, anything that drops background-clip paints
 * transparent text over a transparent background and the word disappears from
 * the headline outright. Solid accent is the fallback; the gradient is the
 * enhancement. Same guard as the scroll reveals further down, for the same
 * reason: the failure mode is invisible content, not a missing flourish.
 */
.hero h1 em {
  font-style: normal;
  color: var(--accent);
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .hero h1 em {
    background: linear-gradient(100deg, var(--accent), #ff9a6b);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

.hero .sub {
  margin: 0;
  max-width: var(--measure);
  color: var(--muted);
  font-size: 1.08rem;
}

/* --------------------------------------------------------------------------
   Store buttons
   -------------------------------------------------------------------------- */

.stores {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2.25rem;
}

/*
 * The font-family and text-align declarations are belt-and-braces: they cost
 * nothing on an <a> and stop the rule breaking if these ever become <button>s
 * again, which would otherwise inherit the UA's form-control font.
 */
.store-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  /* 48px clears both floors — Apple's 44pt and Material's 48dp. Below that,
     mis-taps start happening at scale. */
  min-height: 48px;
  padding: 0.7rem 1.4rem;
  border-radius: 0.9rem;
  background: var(--text);
  border: 1px solid var(--text);
  color: #101010;
  text-decoration: none;
  font-family: inherit;
  font-weight: 650;
  font-size: 0.98rem;
  line-height: 1.15;
  text-align: left;
  cursor: pointer;
  transition:
    transform 0.18s ease,
    box-shadow 0.18s ease;
}

.store-btn + .store-btn {
  background: transparent;
  border-color: var(--border);
  color: var(--text);
}

.store-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 0.75rem 1.75rem rgba(0, 0, 0, 0.45);
}

.store-btn small {
  display: block;
  font-size: 0.68rem;
  font-weight: 500;
  opacity: 0.7;
  letter-spacing: 0.02em;
}

.store-icon {
  width: 22px;
  height: 22px;
  flex: none;
}

/* --------------------------------------------------------------------------
   Device mock
   --------------------------------------------------------------------------
   Dimensional rather than flat — a slight perspective rotation and a real
   shadow are what separate a mockup from a screenshot pasted onto a page. It
   shows the retake badge, which IS the product, in the first screen.
   -------------------------------------------------------------------------- */

.phone {
  justify-self: center;
  width: min(19.5rem, 100%);
  transform: perspective(1400px) rotateY(-13deg) rotateX(4deg) rotateZ(0.6deg);
}

@media (max-width: 61.99rem) {
  /* Straighten on narrow screens: the rotation eats horizontal room the
     layout does not have. */
  .phone {
    transform: none;
  }
}

.phone-frame {
  position: relative;
  border: 1px solid #383838;
  border-radius: 2.4rem;
  padding: 0.5rem;
  background: linear-gradient(155deg, #2c2c2c, #0e0e0e);
  box-shadow:
    0 2.5rem 5rem rgba(0, 0, 0, 0.65),
    inset 0 0 0 1px rgba(255, 255, 255, 0.03);
}

.phone-screen {
  background: var(--bg);
  border-radius: 2rem;
  overflow: hidden;
  padding-bottom: 0.85rem;
}

.p-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.95rem 0.9rem 0.75rem;
}

.p-avatar {
  width: 31px;
  height: 31px;
  border-radius: 50%;
  background: linear-gradient(140deg, #4a4a4a, #262626);
  flex: none;
}

.p-names {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}

.p-names b {
  font-size: 0.86rem;
}

.p-names i {
  font-style: normal;
  font-size: 0.72rem;
  color: var(--dim);
}

/*
 * Holds the shot. The background is a mid-tone sampled from the photograph
 * rather than a neutral grey, so the frame before it paints reads as part of
 * the image instead of as a hole in the layout.
 */
.p-photo {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  background: #9aa6ad;
}

/* object-fit so a real photo can be dropped in at any aspect ratio later and
   still fill the frame instead of letterboxing. */
.p-shot {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.p-take {
  position: absolute;
  left: 0.7rem;
  bottom: 0.7rem;
  padding: 0.32rem 0.7rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.66);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: #fff;
  font-size: 0.73rem;
  font-weight: 700;
}

.p-meta {
  padding: 0.75rem 0.9rem 0.45rem;
  font-size: 0.72rem;
  color: var(--dim);
}

.p-actions {
  display: flex;
  gap: 1rem;
  padding: 0 0.9rem;
  font-size: 0.8rem;
  color: var(--muted);
}

/* --------------------------------------------------------------------------
   Section headings
   -------------------------------------------------------------------------- */

.section-head {
  text-align: center;
  margin: 0 auto 2.5rem;
  max-width: 32rem;
}

.section-head h2 {
  font-size: clamp(1.7rem, 4.5vw, 2.5rem);
  letter-spacing: -0.03em;
  margin: 0 0 0.65rem;
  font-weight: 800;
}

.section-head p {
  margin: 0;
  color: var(--muted);
}

.features {
  padding: 4.5rem 0;
}

/* --------------------------------------------------------------------------
   Bento grid
   --------------------------------------------------------------------------
   Varied tile sizes rather than a uniform card row: the lead tile carries the
   feature the product is actually built around, and the rest fall in behind it.
   -------------------------------------------------------------------------- */

.bento {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
}

@media (min-width: 45rem) {
  .bento {
    grid-template-columns: repeat(4, 1fr);
  }

  .bento .lead {
    grid-column: span 2;
    grid-row: span 2;
  }

  .bento .tile:not(.lead) {
    grid-column: span 2;
  }

  /*
   * Close the hole. Between here and 62rem the lead occupies four cells and
   * the other five occupy two each — fourteen, which is not a multiple of the
   * four columns, so the final row came up half empty. Letting the last tile
   * take a full row makes it sixteen and the grid resolves flush. This band is
   * 720-991px, so iPad portrait lands squarely inside it.
   */
  .bento .tile:last-child {
    grid-column: span 4;
  }
}

@media (min-width: 62rem) {
  .bento .wide {
    grid-column: span 2;
  }

  .bento .tile:not(.lead):not(.wide) {
    grid-column: span 1;
  }

  /* Back to a half row — at this width the spans already resolve to exactly
     three full rows without help. */
  .bento .tile:last-child {
    grid-column: span 2;
  }
}

.tile {
  position: relative;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  background: linear-gradient(165deg, var(--bg-lift), rgba(28, 28, 28, 0.4));
  padding: 1.75rem;
  overflow: hidden;
  transition:
    transform 0.22s ease,
    border-color 0.22s ease;
}

/* Micro-interaction: a small lift, not a bounce. */
.tile:hover {
  transform: translateY(-3px);
  border-color: var(--border);
}

.tile h3 {
  margin: 0 0 0.55rem;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.015em;
}

.tile p {
  margin: 0;
  color: var(--muted);
  font-size: 0.94rem;
}

.tile.lead {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 2rem;
  background:
    radial-gradient(85% 60% at 15% 10%, rgba(239, 68, 68, 0.13), transparent 65%),
    linear-gradient(165deg, var(--bg-lift), rgba(28, 28, 28, 0.4));
}

.tile.lead h3 {
  font-size: 1.5rem;
  letter-spacing: -0.025em;
}

.tile.lead p {
  font-size: 1rem;
}

/* The badge, blown up — the same thing the app draws over every photo. */
.badge-demo {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.badge-demo span {
  padding: 0.45rem 0.85rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: rgba(0, 0, 0, 0.35);
  font-size: 0.82rem;
  font-weight: 650;
  color: var(--text);
}

.badge-demo span:first-child {
  background: var(--accent-soft);
  border-color: rgba(239, 68, 68, 0.4);
  color: var(--accent);
}

/* --------------------------------------------------------------------------
   Trust strip
   --------------------------------------------------------------------------
   Where a launched app would put ratings, downloads or testimonials, this
   states verifiable properties of the software instead. The app has no users
   yet, so it has no honest social proof, and inventing some is not an option.
   -------------------------------------------------------------------------- */

.trust {
  padding: 4rem 0;
  border-top: 1px solid var(--border-soft);
  border-bottom: 1px solid var(--border-soft);
  background: linear-gradient(180deg, rgba(28, 28, 28, 0.5), transparent);
}

.trust-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.trust-list li {
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  padding: 1.5rem;
  background: rgba(20, 20, 20, 0.5);
}

.trust-list strong {
  display: block;
  margin-bottom: 0.4rem;
  color: var(--text);
  font-size: 1rem;
}

.trust-list span {
  color: var(--muted);
  font-size: 0.92rem;
}

.trust-check {
  display: inline-block;
  margin-bottom: 0.9rem;
  width: 30px;
  height: 30px;
  line-height: 30px;
  text-align: center;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 800;
}

/* --------------------------------------------------------------------------
   Closing CTA
   -------------------------------------------------------------------------- */

.cta-end {
  position: relative;
  padding: 5rem 0;
  text-align: center;
  overflow: hidden;
}

.cta-end::before {
  content: '';
  position: absolute;
  inset: auto -20% -60% -20%;
  height: 30rem;
  pointer-events: none;
  background: radial-gradient(45% 50% at 50% 80%, rgba(239, 68, 68, 0.16), transparent 70%);
}

.cta-end .wrap {
  position: relative;
}

.cta-end h2 {
  font-size: clamp(1.9rem, 5.5vw, 3rem);
  letter-spacing: -0.035em;
  margin: 0 0 1.75rem;
  font-weight: 800;
}

.cta-end h2 em {
  font-style: normal;
  color: var(--accent);
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .cta-end h2 em {
    background: linear-gradient(100deg, var(--accent), #ff9a6b);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/*
 * Forced colours (Windows High Contrast) override our palette but not
 * background-clip, which would leave the clipped words transparent against a
 * forced background — i.e. invisible. Hand them back to the system colour.
 */
@media (forced-colors: active) {
  .hero h1 em,
  .cta-end h2 em {
    background: none;
    -webkit-text-fill-color: currentcolor;
    color: CanvasText;
  }
}

.cta-end .stores {
  justify-content: center;
  margin-top: 0;
}

/* --------------------------------------------------------------------------
   Legal pages
   -------------------------------------------------------------------------- */

.doc {
  max-width: 44rem;
  padding-top: 3.5rem;
  padding-bottom: 5rem;
}

.doc h1 {
  font-size: clamp(2rem, 6vw, 2.75rem);
  letter-spacing: -0.03em;
  margin: 0 0 0.5rem;
}

.doc .updated {
  color: var(--dim);
  font-size: 0.9rem;
  margin: 0 0 2.5rem;
}

.doc h2 {
  font-size: 1.25rem;
  margin: 2.75rem 0 0.75rem;
  letter-spacing: -0.02em;
}

.doc h3 {
  font-size: 1rem;
  margin: 1.75rem 0 0.5rem;
  color: var(--text);
}

.doc p,
.doc li {
  color: var(--muted);
}

.doc li {
  margin-bottom: 0.4rem;
}

.doc strong {
  color: var(--text);
}

.doc a {
  color: var(--accent);
}

/*
 * Draft banner. Loud on purpose: these pages describe real data handling
 * accurately, but the legally operative parts are not written, and a policy
 * that merely looks finished is worse than one that obviously is not.
 */
.draft {
  border: 1px solid var(--accent);
  border-left-width: 4px;
  border-radius: 0.75rem;
  background: rgba(239, 68, 68, 0.08);
  padding: 1.15rem 1.25rem;
  margin-bottom: 2.5rem;
}

.draft p {
  margin: 0;
  color: var(--text);
  font-size: 0.95rem;
}

.draft strong {
  color: var(--accent);
}

.todo {
  background: rgba(239, 68, 68, 0.16);
  color: var(--accent);
  padding: 0.05em 0.4em;
  border-radius: 0.25rem;
  font-size: 0.9em;
  font-weight: 600;
  white-space: nowrap;
}

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

.site-footer {
  border-top: 1px solid var(--border-soft);
  padding: 2.5rem 0 3.5rem;
  color: var(--dim);
  font-size: 0.9rem;
}

.site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.75rem;
  align-items: center;
  justify-content: space-between;
}

.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}

.site-footer a {
  color: var(--muted);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--text);
}

/* --------------------------------------------------------------------------
   Scroll-driven reveal
   --------------------------------------------------------------------------
   CSS only, and gated twice. @supports means a browser without scroll-driven
   animation never applies the starting state, so content is simply visible
   rather than stuck at opacity 0 — the usual way this pattern breaks. The
   reduced-motion query below opts out entirely.
   -------------------------------------------------------------------------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: reveal-in linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 26%;
    }
  }
}

@keyframes reveal-in {
  from {
    opacity: 0;
    transform: translateY(1.25rem);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* Pre-launch stand-in for the hidden store buttons (index.html). */
/* display:flex on the containers would otherwise override the hidden attribute. */
.stores[hidden],
.cta-row[hidden] {
  display: none;
}

.stores-soon {
  margin-top: 1.5rem;
  font-weight: 600;
  opacity: 0.85;
}
