/*
 * revigoapp.eu — shared stylesheet.
 *
 * Palette and type are lifted from the app (src/theme/variables.scss and
 * the /join fallback page) so the site and the product look like one
 * thing. Mulish is self-hosted rather than pulled from Google Fonts: a
 * site whose main job is to host a privacy policy should not make the
 * reader's browser call a third party to render it.
 */

@font-face {
  font-family: "Mulish";
  src: url("/assets/mulish-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: "Mulish";
  src: url("/assets/mulish-400-latin-ext.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Mulish";
  src: url("/assets/mulish-600-latin.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: "Mulish";
  src: url("/assets/mulish-600-latin-ext.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Mulish";
  src: url("/assets/mulish-800-latin.woff2") format("woff2");
  font-weight: 800;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

:root {
  --bg: #f9f4ea;
  --surface: #fdf9ef;
  --ink: #00204c;
  --ink-soft: #6b5b48;
  --line: rgba(110, 80, 35, 0.18);
  --accent: #0069b3;
  --accent-ink: #ffffff;
  --wrap: 64rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #241c14;
    --surface: #2e241a;
    --ink: #f4ead8;
    --ink-soft: #bda98c;
    --line: rgba(240, 220, 180, 0.16);
    --accent: #6cb6e8;
    --accent-ink: #10202e;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.6 "Mulish", system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: -apple-system, "SF Pro Display", BlinkMacSystemFont, "Segoe UI Variable Display", "Segoe UI", system-ui, "Mulish", sans-serif;
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: 0 0 0.5em;
}

h1 { font-size: clamp(2rem, 5vw, 3rem); font-weight: 800; }
h2 { font-size: clamp(1.4rem, 3vw, 1.9rem); font-weight: 700; margin-top: 2em; }
h3 { font-size: 1.1rem; font-weight: 700; }

p { margin: 0 0 1em; }
a { color: var(--accent); }

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 20px;
}

/* Visible only when tabbed to — a legal page has to be reachable by
   keyboard, and the nav sits above the content. */
/* The standard visually-hidden pattern rather than a huge negative
   offset: WebKit painted a sliver of the off-screen link under the
   header, and a 1px clipped box cannot. */
.skip {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.skip:focus {
  width: auto;
  height: auto;
  overflow: visible;
  clip-path: none;
  left: 12px;
  top: 12px;
  z-index: 10;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 14px;
}

/* ---- header ---- */

.site-header {
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  position: sticky;
  top: 0;
  z-index: 5;
}

.header-inner {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding-block: 12px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 800;
  font-size: 1.05rem;
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
}
.brand img { border-radius: 8px; }

.site-nav, .lang-nav {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}

.site-nav a, .lang-nav a {
  padding: 6px 10px;
  border-radius: 8px;
  text-decoration: none;
  color: var(--ink-soft);
  font-size: 0.94rem;
}
.site-nav a:hover, .lang-nav a:hover { background: var(--bg); color: var(--ink); }
.site-nav a.is-current, .lang-nav a.is-current { color: var(--ink); font-weight: 700; }

.lang-nav {
  border-left: 1px solid var(--line);
  padding-left: 12px;
  font-size: 0.8rem;
}
.lang-nav a { padding: 6px 7px; font-size: 0.8rem; letter-spacing: 0.06em; }

/* ---- blocks ---- */

/* Bottom padding is small on purpose: a band follows immediately on
   every inner page, and the two paddings together left a hole under
   the lede wide enough to look like a missing section. */
.hero { padding: clamp(40px, 7vw, 76px) 0 clamp(8px, 1.5vw, 16px); }
.hero h1 { max-width: 18ch; }

.lede {
  font-size: clamp(1.05rem, 2vw, 1.25rem);
  color: var(--ink-soft);
  max-width: 62ch;
}

.actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 28px;
}

.btn {
  display: inline-block;
  padding: 12px 22px;
  border-radius: 12px;
  text-decoration: none;
  border: 1px solid transparent;
  /* A <button> inherits neither the page font nor a pointer cursor, so
     every real button rendered in the browser default — Arial at 13px —
     while the <a> elements wearing the same class were Mulish at 16px.
     The class is used for both, so it has to say so itself. */
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  transition: transform 180ms ease-out, filter 180ms ease-out;
}
.btn:disabled,
.btn[aria-disabled='true'] {
  cursor: not-allowed;
  opacity: 0.5;
}
.btn.primary { background: var(--accent); color: var(--accent-ink); }
.btn.ghost { border-color: var(--line); color: var(--ink); background: var(--surface); }
/* Sign out is not an action anyone comes here for. */
.btn.link {
  background: none;
  border-color: transparent;
  color: var(--ink-soft);
  padding-left: 0;
  padding-right: 0;
  text-decoration: underline;
}
.btn:hover { filter: brightness(1.06); transform: translateY(-1px); }

/* A visible focus ring on everything reachable by keyboard. The site
   never removes the default without putting a stronger one back. */
a:focus-visible,
.btn:focus-visible,
button:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}

/* ---- showcase: the home page's opening ----
   The panel is painted with the gradient the store screenshots are
   composed on, so the cropped device sitting on it has no visible seam.
   It keeps that gradient in dark mode too: the seam is with the
   artwork, not with the page, and re-tinting it would break the join
   while gaining nothing — white on this blue is 5.7:1 either way. */

.showcase {
  background: linear-gradient(180deg, #0069b3 0%, #004b8c 100%);
  color: #ffffff;
  overflow: hidden;
}
.showcase-inner {
  display: grid;
  gap: clamp(16px, 4vw, 40px);
  align-items: end;
  padding-top: clamp(40px, 8vw, 80px);
}
.showcase-copy { padding-bottom: clamp(32px, 6vw, 72px); }
.showcase h1 {
  color: #ffffff;
  max-width: 16ch;
  font-size: clamp(2rem, 6vw, 3.1rem);
  line-height: 1.1;
  margin-top: 0;
}
.showcase .lede {
  color: rgba(255, 255, 255, 0.88);
  max-width: 34ch;
}
/* The device bleeds off the bottom edge on purpose: a phone running out
   of the frame reads as a window into the app, not a picture of one. */
.showcase-shot {
  justify-self: center;
  margin-bottom: -8%;
  max-width: 17rem;
}
.showcase-shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 380 / 810;
  filter: drop-shadow(0 18px 40px rgba(0, 22, 48, 0.45));
}

@media (min-width: 48rem) {
  .showcase-inner {
    grid-template-columns: 1fr auto;
    gap: clamp(24px, 5vw, 64px);
    align-items: center;
  }
  /* Centred against the device rather than bottom-aligned: the copy is
     the shorter column, and hanging it off the baseline left a hollow
     above the headline. */
  .showcase-copy { padding-bottom: clamp(48px, 8vw, 96px); }
  .showcase-shot { justify-self: end; align-self: end; max-width: 20rem; }
}

/* ---- official store badges ----
   Apple's SVG and Google's PNG are used exactly as supplied. They are
   shown at different heights on purpose: Google bakes its clear space
   into the file (a 250px box around 192px of artwork) and Apple does
   not, so equal boxes would make Apple's badge look a third larger.
   These heights match the artwork; Apple's padding supplies the clear
   space its guidelines require. */

.actions--badges {
  gap: 12px;
  align-items: center;
}
.store-badge {
  display: inline-flex;
  border-radius: 10px;
  transition: transform 180ms ease-out, opacity 180ms ease-out;
}
.store-badge img { display: block; height: 40px; width: auto; }
.store-badge--apple { padding: 4px; }
.store-badge--google img { height: 52px; }
.store-badge:hover { transform: translateY(-2px); opacity: 0.92; }
.store-badge:focus-visible {
  outline: 3px solid #ffffff;
  outline-offset: 3px;
}

/* ---- screenshot gallery ---- */

.band--shots { background: var(--surface); }
/* Wider than the prose measure: five devices in a row need the room,
   and the section is pictures rather than text. */
.band--shots .wrap { max-width: 76rem; }
.shots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: clamp(16px, 3vw, 32px);
  margin: 28px 0 0;
  padding: 0;
}
.shot { margin: 0; }
.shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 260 / 554;
  /* drop-shadow, not box-shadow: the device is masked to transparency
     at its corners, and a box shadow would trace the rectangle the
     image no longer visually has. */
  filter: drop-shadow(0 12px 24px rgba(0, 22, 48, 0.22));
  transition: transform 200ms ease-out;
}
.shot:hover img { transform: translateY(-4px); }
.shot figcaption {
  margin-top: 10px;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink-soft);
  text-align: center;
}

.band { padding: clamp(32px, 6vw, 64px) 0; }
.band + .band { border-top: 1px solid var(--line); }
.band h2 { margin-top: 0; }

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

.cards li, .plan {
  transition: transform 200ms ease-out, box-shadow 200ms ease-out;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 22px;
}
.cards li:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 28px rgba(0, 22, 48, 0.10);
}
.cards li h3 { margin-top: 0; }
.cards li p { margin-bottom: 0; color: var(--ink-soft); }

/* ---- feature rows: the copy beside the screen it describes ---- */

.feature-row__inner {
  display: grid;
  gap: clamp(20px, 4vw, 48px);
  align-items: center;
}
.feature-row__shot { justify-self: center; max-width: 13rem; }
.feature-row__shot img {
  display: block;
  width: 100%;
  height: auto;
  /* Reserved in CSS as well as by the width/height attributes. The
     attributes alone left the box unreserved until the image loaded,
     and the copy beneath it jumped 374px — 0.19 CLS on this page,
     measured, twice. */
  aspect-ratio: 260 / 554;
  filter: drop-shadow(0 14px 28px rgba(0, 22, 48, 0.20));
}
.feature-row__copy h2 { margin-top: 0; }
/* The paragraph above each feature list. Set at the body measure rather
   than the full column width: a 150-word paragraph running the whole
   width of a wide feature row is a wall. */
.feature-row__lead {
  color: var(--ink-soft);
  max-width: 44rem;
  margin: 0 0 22px;
}
.feature-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 18px; }
.feature-list h3 { margin: 0 0 4px; font-size: 1.05rem; }
.feature-list p { margin: 0; color: var(--ink-soft); }
.feature-list li { border-left: 3px solid var(--line); padding-left: 16px; }

@media (min-width: 48rem) {
  .feature-row__inner { grid-template-columns: 15rem 1fr; }
  /* Alternating sides so three groups read as a rhythm rather than
     three identical slabs. Order, not direction, so the DOM stays in
     reading order for a screen reader. */
  .feature-row--flip .feature-row__shot { order: 2; }
  .feature-row--flip .feature-row__inner { grid-template-columns: 1fr 15rem; }
  .feature-list { grid-template-columns: repeat(2, 1fr); gap: 24px 32px; }
}

/* ---- the two ways to buy ---- */

.choices {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(16px, 3vw, 28px);
  align-items: start;
}
.choice {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: clamp(20px, 3vw, 30px);
}
/* One primary action on the page, and it lives here. The other card's
   form is deliberately the quieter of the two. */
.choice--featured { border-color: var(--accent); border-width: 2px; }
.choice h2 { margin: 0 0 4px; font-size: 1.3rem; }
.choice p { color: var(--ink-soft); }
.choice__price {
  font-size: 2rem;
  font-weight: 800;
  color: var(--ink);
  margin: 0 0 14px;
  line-height: 1.1;
}
.choice__price span {
  display: block;
  font-size: 0.92rem;
  font-weight: 400;
  color: var(--ink-soft);
}
.choice__cta { display: inline-block; margin-top: 4px; }
.choice__note {
  margin: 12px 0 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

@media (min-width: 48rem) {
  .choices { grid-template-columns: 1fr 1fr; }
}

/* ---- closing call to action ---- */

.callout {
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding: clamp(32px, 6vw, 56px) 0;
}
.callout-inner {
  display: grid;
  gap: 20px;
  align-items: center;
}
.callout h2 { margin: 0 0 6px; }
.callout .lede { margin: 0; }
.callout .actions { margin: 0; }

@media (min-width: 48rem) {
  .callout-inner { grid-template-columns: 1fr auto; gap: 40px; }
}

/* ---- questions and answers ---- */

.faq {
  display: grid;
  gap: clamp(14px, 2vw, 20px);
  margin-top: 20px;
}
.faq-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 20px 22px;
}
.faq-item h3 { margin: 0 0 6px; font-size: 1.02rem; }
.faq-item p { margin: 0; color: var(--ink-soft); }
/* Answers run to several paragraphs now. The first and last stay flush
   with the card's own padding; only the gaps between them are spaced,
   so a one-paragraph answer looks exactly as it did before. */
.faq-item p + p { margin-top: 0.8em; }

@media (min-width: 48rem) {
  .faq { grid-template-columns: repeat(2, 1fr); }
}

/* ---- pricing ---- */

.plan { display: flex; flex-direction: column; }
.plan.is-featured { border-color: var(--accent); }
.plan h3 { margin-top: 0; }
.price { font-size: 1.9rem; font-weight: 800; margin: 0; }
.price-sub { color: var(--ink-soft); font-size: 0.92rem; }
.plan ul { padding-left: 1.1em; margin: 0 0 20px; color: var(--ink-soft); }
.plan ul li { margin-bottom: 6px; }
.plan .btn { margin-top: auto; text-align: center; }

.note { color: var(--ink-soft); font-size: 0.92rem; margin-top: 24px; }

/* ---- comparison table ---- */

/* Three columns of Dutch do not fit a phone, so the table scrolls
   inside its own box. The page body must never scroll sideways. */
.table-scroll {
  overflow-x: auto;
  margin-top: 24px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface);
  /* Keeps the rounded corners while the content inside scrolls. */
  -webkit-overflow-scrolling: touch;
}
.compare {
  border-collapse: collapse;
  width: 100%;
  min-width: 34rem;
  font-size: 0.95rem;
}
.compare th,
.compare td {
  text-align: left;
  padding: 13px 18px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.compare tbody tr:last-child th,
.compare tbody tr:last-child td { border-bottom: 0; }
.compare thead th {
  font-size: 0.83rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: var(--bg);
}
/* The row-label column is a header too, so it is a th — but it should
   read as a label, not as a column heading. */
.compare tbody th {
  font-weight: 600;
  color: var(--ink);
  width: 34%;
}
.compare td { color: var(--ink-soft); }
/* The column the page is selling. */
.compare thead th:last-child,
.compare tbody td:last-child { background: color-mix(in srgb, var(--accent) 7%, transparent); }

/* On a phone the min-width above would push the Revigo Team column —
   the one this page exists to sell — off the right edge, behind a
   sideways scroll nobody performs. Below that width the table gives up
   its minimum and lets the cells wrap instead: tighter type, narrower
   padding, three columns that fit. */
@media (max-width: 34rem) {
  .compare {
    min-width: 0;
    font-size: 0.85rem;
  }
  .compare th,
  .compare td { padding: 10px 9px; }
  .compare tbody th { width: 38%; }
  .compare thead th { font-size: 0.72rem; letter-spacing: 0.02em; }
}

/* ---- a plain answer to a plain question ---- */

/* One question, one answer, no cards. Used where the whole job of a
   section is to be quotable: the definition under the home page's
   hero, which is the first thing an answer engine reads. */
/* The measure is applied to the text, not the container — same reason as
   .prose below. Narrowing the wrap itself would centre a 44rem column
   inside a 64rem page and pull this section's left edge away from every
   other section's. */
.answer h2 { margin-top: 0; }
.answer p { color: var(--ink-soft); max-width: 44rem; }
.answer p:last-child { margin-bottom: 0; }

/* ---- long-form legal ---- */

.prose { padding: clamp(32px, 6vw, 64px) 0 clamp(16px, 3vw, 32px); }
/* The measure is applied to the text, not the container. Narrowing the
   wrap centred it, so on a page that mixes prose with other sections —
   support has an FAQ and a call to action under it — the left edges did
   not line up. Constraining the paragraphs keeps long-form text
   readable while every section starts at the same place. */
.prose .wrap { max-width: var(--wrap); }
.prose p, .prose li, .prose .lede { max-width: 42rem; }
.prose h2 { font-size: 1.25rem; margin-top: 2.2em; }
.prose p, .prose li { color: var(--ink-soft); }
.prose ul { padding-left: 1.2em; }
.prose li { margin-bottom: 8px; }
.updated {
  font-size: 0.88rem;
  color: var(--ink-soft);
  border-bottom: 1px solid var(--line);
  padding-bottom: 20px;
}

/* ---- footer ---- */

.site-footer {
  border-top: 1px solid var(--line);
  background: var(--surface);
  margin-top: 48px;
  padding: 32px 0;
}
.footer-inner { display: grid; gap: 12px; }
.footer-tag { font-weight: 700; margin: 0; }
.footer-nav { display: flex; gap: 16px; flex-wrap: wrap; }
.footer-nav a { color: var(--ink-soft); font-size: 0.94rem; }
/* Two footer rows now, and they are not the same kind of thing: the
   guides are pages worth reading, the row below them is fine print.
   Without this they render as one undifferentiated block of grey. */
.footer-nav--guides a { color: var(--ink); font-weight: 600; }
.footer-legal { color: var(--ink-soft); font-size: 0.86rem; margin: 0; }

/* ---- the account panel on /subscribe ----
   The one interactive area on the site. Without JavaScript the mount
   point stays empty and the block's own paragraphs still explain the
   other way to pay, so nothing here is load-bearing. */

.account {
  margin-top: 16px;
  display: grid;
  gap: 12px;
}
.account:empty { margin-top: 0; }
.account-lede { color: var(--ink-soft); margin: 0; }
.account-form {
  display: grid;
  gap: 10px;
  max-width: 22rem;
}
.account-form label {
  font-size: 0.9rem;
  font-weight: 700;
}
.account-form input {
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  /* 16px is the threshold below which iOS Safari zooms the page on
     focus, which on a payment form reads as the site breaking. */
  font-size: 16px;
}
.account-form input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.account-form .btn { justify-self: start; }
.account-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.account-status { margin: 0; font-size: 0.94rem; }
.account-status--note { color: var(--ink-soft); }
.account-status--error { color: #b3261e; }

@media (prefers-color-scheme: dark) {
  .account-status--error { color: #ff9d94; }
}

/* ---- consent banner ----
   Docked to the bottom rather than covering the page: this site has
   nothing to hide behind a scrim, and a full-screen wall on a privacy
   policy is its own kind of joke. Both answers carry equal weight —
   a loud accept beside a muted decline is a dark pattern, and it is
   also not valid consent. */

.consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 100;
  background: var(--surface);
  border-top: 1px solid var(--line);
  box-shadow: 0 -8px 28px rgba(0, 22, 48, 0.14);
  padding: 18px 20px calc(18px + env(safe-area-inset-bottom));
}
.consent__inner {
  max-width: var(--wrap);
  margin: 0 auto;
  display: grid;
  gap: 16px;
  align-items: center;
}
.consent__title { margin: 0 0 6px; font-weight: 700; }
.consent__body { margin: 0 0 8px; color: var(--ink-soft); font-size: 0.94rem; max-width: 62ch; }
.consent__more { font-size: 0.9rem; }
.consent__actions { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.consent__actions .btn { flex: 1 1 auto; text-align: center; }
/* Declining is a quieter link beside the primary action: one click, on
   this layer, but plainly the secondary path. */
.consent__decline { flex: 0 0 auto; font-size: 0.9rem; }

@media (min-width: 48rem) {
  .consent__inner { grid-template-columns: 1fr auto; gap: 32px; }
  .consent__actions .btn { flex: 0 0 auto; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  /* Hover lifts are motion too — hold everything still. */
  .cards li:hover,
  .shot:hover img,
  .store-badge:hover,
  .btn:hover { transform: none; }
}
