/* HoldSpace site: Sage & Stone. Dark palette taken from the app's own dark mode.
   See website/DESIGN.md. Tokens only; Work Sans 400/600 only. */

@font-face {
  font-family: 'Work Sans';
  src: url('/fonts/work-sans-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Work Sans';
  src: url('/fonts/work-sans-latin-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  --background: #F8F5F0;
  --surface: #FFFFFF;
  --surface-2: #F2EEE7;
  --text: #262320;
  --muted: #635C54;
  --lines: #E5DFD6;
  --accent: #3F5C45;
  --accent-soft: #E7EDE8;
  --on-accent: #FFFFFF;
  --hero-card: rgba(248, 245, 240, 0.93);
  --shadow: 0 18px 44px rgba(38, 35, 32, 0.10), 0 4px 12px rgba(38, 35, 32, 0.05);
  --measure: 40rem;
  --wide: 68rem;
  --section: clamp(4rem, 10vw, 7rem);
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #181614;
    --surface: #211E1B;
    --surface-2: #2A2622;
    --text: #EDE8E1;
    --muted: #A69C90;
    --lines: #322E29;
    --accent: #93BA97;
    --accent-soft: #232A24;
    --on-accent: #181614;
    --hero-card: rgba(24, 22, 20, 0.88);
    --shadow: 0 18px 44px rgba(0, 0, 0, 0.35);
  }
}

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

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

body {
  margin: 0;
  background: var(--background);
  color: var(--text);
  font-family: 'Work Sans', system-ui, sans-serif;
  font-weight: 400;
  font-size: 1.125rem; /* 18px: comfortable for older readers on phones */
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, strong, b { font-weight: 600; }

/* Long words wrap rather than push the page sideways at large text sizes. */
body { overflow-wrap: break-word; }
h1, h2 { hyphens: auto; }

a {
  color: var(--accent);
  text-underline-offset: 0.18em;
  text-decoration-color: color-mix(in srgb, currentColor 55%, transparent);
  overflow-wrap: anywhere;
}
@media (hover: hover) and (pointer: fine) {
  a:hover { text-decoration-color: currentColor; }
}

/* Focus: a two-tone ring (background, then accent) stays visible on any
   background, including the photo. The shape of the element never changes. */
a:focus-visible,
.button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--background);
}

img { max-width: 100%; height: auto; display: block; }

.skip-link {
  position: absolute;
  left: 1rem;
  top: -4rem;
  z-index: 10;
  padding: 0.6rem 1rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--lines);
  border-radius: 0.5rem;
  font-weight: 600;
}
.skip-link:focus-visible { top: 1rem; }

/* Header */
.site-header {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 1rem;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 44px;
  color: var(--text);
  text-decoration: none;
  border-radius: 999px;
}
.brand .mark { color: var(--accent); }
.wordmark { font-size: 1.35rem; letter-spacing: -0.03em; font-weight: 400; }
.wordmark b { font-weight: 600; }

/* On the home page the header floats over the top of the photo, where the
   pale sky fades into the page colour. */
.home .site-header {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 2;
}
.home .brand {
  background: var(--hero-card);
  padding: 0.3rem 0.85rem 0.3rem 0.55rem;
}

/* Hero: a calm photo band (no people, no objects), with the headline on the
   page colour below it. The top of the photo fades into the page colour. */
.hero {
  position: relative;
  height: min(58svh, 42vw);
  min-height: 15rem;
  overflow: hidden;
  background: var(--surface-2);
}
.hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 30% 100%;
}
.hero::after {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 30%;
  background: linear-gradient(to bottom, var(--background), transparent);
  pointer-events: none;
}
@media (max-aspect-ratio: 4/5) {
  .hero { height: 56svh; }
  .hero img { object-position: 40% 55%; }
}

/* Intro: what HoldSpace is, the headline and the first call to action. */
main > section { padding: 0 1rem; }
.intro {
  max-width: var(--wide);
  margin: 0 auto;
  padding-top: clamp(1.75rem, 5vw, 2.75rem);
  display: grid;
  gap: 0.9rem;
  justify-items: start;
}
.eyebrow {
  margin: 0;
  color: var(--accent);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
}
.intro h1 {
  margin: 0;
  max-width: 18ch;
  font-size: clamp(2.25rem, 6vw, 4rem);
  line-height: 1.06;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
.intro-line {
  margin: 0;
  max-width: 34rem;
  font-size: clamp(1.25rem, 3.4vw, 1.6rem);
  line-height: 1.35;
  letter-spacing: -0.01em;
  text-wrap: pretty;
}

/* Call to action: the button, with a plain note of what it does. */
.cta { display: grid; gap: 0.5rem; justify-items: start; margin-top: 0.4rem; }
.cta-note { margin: 0; color: var(--muted); font-size: 0.95rem; }
.button {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0.85rem 1.6rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
  text-decoration: none;
}
@media (hover: hover) and (pointer: fine) {
  .button:hover { filter: brightness(1.08); }
}
.button.secondary { background: var(--accent-soft); color: var(--accent); }
.text-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 600;
}

/* The letter: why HoldSpace exists, in Antal's words, signed. */
.letter {
  max-width: var(--wide);
  margin: var(--section) auto 0;
}
.letter > * { max-width: var(--measure); }
.letter .big {
  margin: 0;
  font-size: clamp(2rem, 6vw, 3.1rem);
  line-height: 1.1;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
.letter .lede { margin: 0.6rem 0 0; color: var(--muted); font-size: clamp(1.15rem, 2.8vw, 1.35rem); }
.letter blockquote {
  margin: clamp(2rem, 6vw, 3rem) 0 0;
  padding: 0 0 0 1.25rem;
  border-left: 2px solid var(--accent);
  font-size: clamp(1.2rem, 3vw, 1.4rem);
  line-height: 1.55;
}
.letter blockquote p { margin: 0; text-wrap: pretty; }
.letter .sig { margin-top: 1rem; font-size: 1rem; font-weight: 600; }

/* The three moments: real app screenshots, cropped only, on a quiet mat. */
.moments {
  max-width: var(--wide);
  margin: var(--section) auto 0;
  display: grid;
  gap: clamp(3rem, 7vw, 4.5rem);
}
.moment { margin: 0; display: grid; gap: 1rem; align-items: center; }
.moment h2 {
  margin: 0;
  font-size: clamp(1.4rem, 3.4vw, 1.9rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.shot {
  border-radius: 1rem;
  border: 1px solid var(--lines);
  box-shadow: var(--shadow);
  background: var(--surface);
  overflow: hidden;
}
.shot img, .shot picture { display: block; width: 100%; }
/* In dark mode the light screenshots sit on a soft mat, so the white app
   window doesn't glare against the dark page. The pixels are unchanged. */
@media (prefers-color-scheme: dark) {
  .shot { padding: 0.5rem; background: var(--surface-2); border-color: var(--lines); }
  .shot img { border-radius: 0.6rem; }
}
.stack { display: grid; gap: 0.6rem; }
@media (min-width: 52rem) {
  .moment { grid-template-columns: 1fr 1.8fr; gap: 3rem; }
  .moment:nth-child(even) { grid-template-columns: 1.8fr 1fr; }
  .moment:nth-child(even) figcaption { order: 2; }
}
@media (max-width: 51.99rem) { .wide-only { display: none; } }
@media (min-width: 52rem) { .narrow-only { display: none; } }

/* Testimonial slot (left out of the build while hidden). */
.testimonial { max-width: var(--measure); margin: var(--section) auto 0; }
[hidden] { display: none !important; }

/* Privacy promise and offer: the page ends on trust, then the action. */
.promise {
  max-width: var(--wide);
  margin: var(--section) auto 0;
  display: grid;
  gap: 2.5rem;
  align-items: start;
}
@media (min-width: 52rem) { .promise { grid-template-columns: 1.15fr 1fr; gap: 4rem; } }
.promise h2 {
  margin: 0;
  font-size: clamp(1.5rem, 3.8vw, 2rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.facts { list-style: none; margin: 1.5rem 0 0.75rem; padding: 0; display: grid; gap: 0.85rem; }
.facts li { padding-top: 0.85rem; border-top: 1px solid var(--lines); }
.facts li:first-child { border-top: 0; padding-top: 0; }
.offer-card {
  background: var(--surface);
  border: 1px solid var(--lines);
  border-radius: 1rem;
  padding: clamp(1.5rem, 4vw, 2rem);
  display: grid;
  gap: 1.25rem;
  justify-items: start;
}
.offer-card .price {
  margin: 0;
  font-weight: 400;
  font-size: clamp(1.2rem, 3vw, 1.4rem);
  line-height: 1.35;
  letter-spacing: normal;
}
.offer-card .free { font-weight: 600; display: block; font-size: 1.15em; }
.offer-card .contact { margin: 0; color: var(--muted); }
.offer-card .cta { margin-top: 0; }

/* Legal pages */
.legal {
  max-width: var(--measure);
  margin: 1.5rem auto 0;
  padding: 0 1rem;
  box-sizing: content-box;
}
.legal h1 {
  font-size: clamp(1.8rem, 5vw, 2.4rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 1rem 0 1.25rem;
  text-wrap: balance;
}
.legal h2 {
  font-size: 1.25rem;
  margin: 2.25rem 0 0.5rem;
  letter-spacing: -0.01em;
}
.legal ul, .legal ol { padding-left: 1.3rem; }
.legal li + li { margin-top: 0.4rem; }
.legal .draft {
  padding: 0.9rem 1.1rem;
  border-radius: 0.75rem;
  background: var(--surface-2);
  border: 1px solid var(--lines);
  border-left: 4px solid var(--accent);
}

/* Download page */
.download-page {
  max-width: 34rem;
  margin: 2rem auto 0;
  padding: 0 1rem;
  box-sizing: content-box;
}
.download-page h1 {
  font-size: clamp(1.8rem, 5vw, 2.4rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 1rem 0 1.5rem;
}
.download-empty { margin: 0; font-size: 1.2rem; line-height: 1.5; }
.download-contact { margin: 1.5rem 0 0; color: var(--muted); }
.downloads {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.9rem;
}
.download {
  display: grid;
  gap: 0.2rem;
  padding: 1.1rem 1.3rem;
  background: var(--surface);
  border: 1px solid var(--lines);
  border-radius: 1rem;
  color: var(--text);
  text-decoration: none;
  box-shadow: var(--shadow);
}
.download:hover { border-color: var(--accent); }
.download-name { font-weight: 600; color: var(--accent); font-size: 1.15rem; }
.download-note { color: var(--muted); }

/* Footer */
.site-footer {
  max-width: var(--wide);
  margin: var(--section) auto 0;
  padding: 1.5rem 1rem 2.5rem;
  border-top: 1px solid var(--lines);
  color: var(--muted);
  font-size: 0.95rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 2rem;
  justify-content: space-between;
  align-items: center;
}
.site-footer nav { display: flex; flex-wrap: wrap; gap: 0 1.5rem; }
.site-footer a { color: var(--muted); display: inline-flex; align-items: center; min-height: 44px; }
.site-footer a[aria-current='page'] { color: var(--text); text-decoration: none; font-weight: 600; }
.site-footer p { margin: 0; }

/* --- Motion -----------------------------------------------------------------
   Crafted, once, then still (see DESIGN.md, Motion). Nothing here runs under
   prefers-reduced-motion, and the three app moments need the tiny /motion.js
   to arm them: without it the page simply shows its final state. Only opacity
   and transform animate.

   The moment layers are drawn from each screenshot's own pixels and colours
   (fixed hex below, matching the light screenshot in both themes); they exist
   only while a moment plays, and the final state is the untouched screenshot. */
:root {
  --ease-arrive: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-move: cubic-bezier(0.45, 0, 0.25, 1);
  --ease-press: cubic-bezier(0.23, 1, 0.32, 1);
}

/* Links and buttons: soft, quick feedback. */
@media (prefers-reduced-motion: no-preference) {
  a { transition: text-decoration-color 200ms ease, color 200ms ease; }
  /* The press lands quickly; the release eases back a little slower. */
  .button { transition: filter 200ms ease, transform 200ms var(--ease-press); }
  .button:active { transform: scale(0.97); transition-duration: 200ms, 100ms; }
  .download { transition: border-color 200ms ease; }
}

/* Hero: the photo settles once as the page opens. */
.hero img { transform-origin: 40% 60%; }
@media (prefers-reduced-motion: no-preference) {
  .hero img { animation: hero-settle 1.2s var(--ease-arrive) both; }
}
@keyframes hero-settle {
  from { opacity: 0; transform: scale(1.03); }
  to { opacity: 1; transform: none; }
}

/* Moment frames: layers are placed in the image's own pixel coordinates. */
.frame { position: relative; container-type: inline-size; }
.frame-history { --iw: 1240; }
@media (max-width: 51.99rem) { .frame-history { --iw: 720; } }
.m {
  position: absolute;
  left: calc(var(--x) / var(--iw) * 100%);
  top: calc(var(--y) / var(--ih) * 100%);
  width: calc(var(--w) / var(--iw) * 100%);
  height: calc(var(--h) / var(--ih) * 100%);
  display: none;
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .is-ready .m { display: block; }
  .is-ready.is-done .m { display: none; }
}

/* Given, in two taps: two soft rings on "+ add", then the entry appears with
   the same brief highlight the app shows (about 1.5 s). Total 2.4 s. */
.given-cover { background: #E7EDE8; }
.given-add { background: url('/img/moment-event-add.png') 0 0 / 100% 100%; }
.given-tap {
  border: calc(3 / var(--iw) * 100cqw) solid #3F5C45;
  border-radius: 50%;
  opacity: 0;
}
/* Above the cover, so the highlight tints the whole cell evenly. */
.given-flash { background: rgba(63, 92, 69, 0.12); opacity: 0; z-index: 1; }
.is-playing .given-tap { animation: tap 520ms var(--ease-arrive) 250ms both; }
.is-playing .given-tap.tap-2 { animation-delay: 780ms; }
.is-playing .given-add { animation: fade-out 160ms var(--ease-arrive) 1050ms both; }
.is-playing .given-cover { animation: fade-out 420ms var(--ease-arrive) 1050ms both; }
.is-playing .given-flash { animation: given-flash 1350ms ease 1050ms both; }
@keyframes tap {
  0% { opacity: 0; transform: scale(0.8); }
  35% { opacity: 0.55; }
  100% { opacity: 0; transform: scale(1.25); }
}
@keyframes given-flash {
  0% { opacity: 0; }
  12% { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes fade-out { to { opacity: 0; } }

/* The note from the earlier event fades in where it sits. Total 1.6 s. */
.note-cover { background: #FFFFFF; }
.is-playing .note-cover { animation: fade-out 1300ms var(--ease-arrive) 300ms both; }

/* Stock counts down 12, 11, 10, 9 as the bar shortens, then the Low badge
   settles in. Bar widths are the real 9-of-60 fill scaled to each count.
   Total 2.0 s. */
.stock-bar { overflow: hidden; border-radius: calc(7 / var(--iw) * 100cqw); }
.stock-bar > span {
  display: block;
  width: 100%;
  height: 100%;
  background: #8A5A0F;
  border-radius: inherit;
  transform: translateX(-84.91%);
}
.stock-cover, .badge-cover { background: #FFFFFF; }
.stock-line {
  font: 400 calc(28.8 / var(--iw) * 100cqw) / 1 'Work Sans', system-ui, sans-serif;
  color: #635C54;
  background: #FFFFFF;
  white-space: nowrap;
}
.stock-line b { font-weight: 600; color: #262320; }
.stock-line .l { position: absolute; left: 0; top: calc(5.2 / 42 * 100%); opacity: 0; }
.stock-line .l12 { opacity: 1; }
.badge {
  background: url('/img/moment-inventory.png') 92.754% 20.183% / 921.43% 503.7%;
  opacity: 0;
  transform: scale(0.96);
}
.is-playing .stock-bar > span { animation: stock-bar 2000ms both; }
.is-playing .stock-line .l12 { animation: show-12 2000ms both; }
.is-playing .stock-line .l11 { animation: show-11 2000ms both; }
.is-playing .stock-line .l10 { animation: show-10 2000ms both; }
.is-playing .stock-cover,
.is-playing .stock-line { animation: count-done 2000ms both; }
.is-playing .badge { animation: badge-settle 2000ms both; }
@keyframes stock-bar {
  0%, 15% { transform: translateX(-80.03%); animation-timing-function: var(--ease-move); }
  35%, 37% { transform: translateX(-81.66%); animation-timing-function: var(--ease-move); }
  55%, 57% { transform: translateX(-83.28%); animation-timing-function: var(--ease-move); }
  75%, 100% { transform: translateX(-84.91%); }
}
@keyframes show-12 { 0%, 14.9% { opacity: 1; } 15%, 100% { opacity: 0; } }
@keyframes show-11 { 0%, 14.9% { opacity: 0; } 15%, 36.9% { opacity: 1; } 37%, 100% { opacity: 0; } }
@keyframes show-10 { 0%, 36.9% { opacity: 0; } 37%, 56.9% { opacity: 1; } 57%, 100% { opacity: 0; } }
@keyframes count-done { 0%, 56.9% { opacity: 1; } 57%, 100% { opacity: 0; } }
@keyframes badge-settle {
  0%, 74% { opacity: 0; transform: scale(0.96); animation-timing-function: var(--ease-arrive); }
  100% { opacity: 1; transform: none; }
}
