/*
 * delvia.health — one stylesheet for every page and every locale.
 *
 * Tokens are the app's canonical design-system values, so the site and the
 * product read as one thing. Externalized (rather than inlined per page) so
 * the Caddy vhost can serve the static handle under a strict CSP without
 * 'unsafe-inline'.
 */

/* IBM Plex Sans — self-hosted, not the Google Fonts CDN: a health app that
   advertises privacy shouldn't hand visitor IPs to a font CDN. unicode-range
   means a Russian reader never downloads the Arabic face. */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-sans-latin-400-normal.24828974.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-sans-latin-600-normal.90d9c226.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-sans-latin-ext-400-normal.c23e9877.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-sans-latin-ext-600-normal.2e84f56d.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-sans-cyrillic-400-normal.e24ab12d.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-sans-cyrillic-600-normal.76fa1c68.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-sans-arabic-arabic-400-normal.a9cefdca.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0898-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'IBM Plex Sans Arabic';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-sans-arabic-arabic-600-normal.9e5c019d.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0898-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}

/* Canonical design-system tokens — light, then dark. Components only ever
   reference these, never a raw hex.
 *
 * The site is LIGHT for everyone by default: there is deliberately no
 * prefers-color-scheme branch here. The app's own captures are light-theme, so
 * a dark page would be selling a product it does not show, and the previous
 * behaviour — silently following the operating system with no control anywhere
 * — read to a dark-OS reader as "this site has no light mode". Dark is now a
 * choice, made with the header button and stored by assets/ui.js. */
:root {
  color-scheme: light;
  /* The header is this tall; the landing page subtracts it from the screen
     to place the phone (.lp-hero-top). */
  --head-h: 3.6875rem;
  --canvas: #fafbfc;
  --surface: #ffffff;
  --surface-alt: #f1f5f9;
  --border: #e2e8f0;
  --t1: #0f172a;
  --t2: #475569;
  --t3: #94a3b8;
  --primary: #0f766e;
  --primary-pressed: #115e59;
  --primary-tint: #f0fdfa;
  --success: #16a34a;
  --warning: #d97706;
  --danger: #dc2626;
  --danger-tint: #fef2f2;
  --on-primary: #ffffff;
  --shadow-lift: 0 24px 48px -24px rgb(15 23 42 / 25%);
  --shadow-crop: 0 18px 34px rgb(15 23 42 / 16%);

  /* The landing page's one inverted ground — the section carrying the three
     problem statistics. One change of ground on a page is a decision; five is
     a template, which is what the alternating bands here used to be. */
  --ink: #0f172a;
  --on-ink: #f1f5f9;
  --on-ink-dim: rgb(241 245 249 / 72%);
  --ink-rule: rgb(241 245 249 / 14%);

  /* Chrome and the landing page run wide; long prose stays at .prose-page. */
  --page: 68rem;
  /* The landing page runs wider still: its panels carry a phone beside a
     column of prose, which --page cannot hold without squeezing one of them. */
  --page-lp: 76rem;
  --measure: 44rem;
  /* The landing page's prose column: shorter than .prose-page's, because it
     sits beside images rather than running the width of the page. */
  --measure-lp: 34rem;
  --radius: 12px;
  /* Each landing section is a panel on the page's ground rather than a band
     across it — the app's own screens are rounded cards, and the page that
     sells them should not read as a document. */
  --panel-radius: 28px;
  --shadow-panel: 0 1px 2px rgb(15 23 42 / 4%), 0 14px 36px -18px rgb(15 23 42 / 14%);
  --font: 'IBM Plex Sans', -apple-system, 'Segoe UI', Roboto, sans-serif;
}

/* font-family is re-declared, not just the token. var() substitutes at the
   element that DECLARES the property — and font-family is declared on body.
   A descendant that only redefines --font inherits body's already-resolved
   latin stack, which is why the Arabic endonym in the language switcher used
   to render in a system fallback face on every non-Arabic page. */
:root:lang(ar),
:lang(ar),
[dir='rtl'] {
  --font: 'IBM Plex Sans Arabic', 'IBM Plex Sans', -apple-system, 'Segoe UI', sans-serif;
  font-family: var(--font);
}

/* Attribute, not a media query: ui.js sets it from the reader's stored choice
   before the first paint. Nothing here fires on an operating-system setting. */
:root[data-theme='dark'] {
  color-scheme: dark;
  --canvas: #0b1220;
  --surface: #111a2c;
  --surface-alt: #1a2436;
  --border: #253248;
  --t1: #f1f5f9;
  --t2: #94a3b8;
  --t3: #64748b;
  --primary: #2dd4bf;
  --primary-pressed: #14b8a6;
  --primary-tint: #0f2e2b;
  --success: #4ade80;
  --warning: #fbbf24;
  --danger: #f87171;
  --danger-tint: #2d1416;
  --on-primary: #0b1220;
  --shadow-lift: 0 24px 48px -24px rgb(0 0 0 / 55%);
  --shadow-crop: 0 18px 34px rgb(0 0 0 / 45%);
  --shadow-panel: 0 1px 2px rgb(0 0 0 / 20%), 0 14px 36px -18px rgb(0 0 0 / 45%);
  /* Deeper than the canvas, so the inverted panel still reads as a change of
     ground on a page that is already dark. */
  --ink: #060b15;
  --on-ink: #f1f5f9;
  --on-ink-dim: rgb(241 245 249 / 70%);
  --ink-rule: rgb(241 245 249 / 12%);
}

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

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

body {
  background: var(--canvas);
  color: var(--t1);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.65;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}

a {
  color: var(--primary);
}

:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: 4px;
}

.skip {
  position: absolute;
  inset-inline-start: -9999px;
}
.skip:focus {
  inset-inline-start: 1rem;
  top: 1rem;
  z-index: 10;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.5rem 0.9rem;
}

/* ---------------------------------------------------------------- chrome */

.wrap {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

/* Long prose reads at a measure, not at the full page width. Declared after
   .wrap so the narrower max-width wins on `.wrap.prose-page`. */
.prose-page {
  max-width: var(--measure);
  padding-block: 2.5rem 4rem;
}

/* Sticky, because the language menu and the theme button are the only
   navigation the site has and both should stay reachable. Translucent over
   the canvas so a panel scrolling under it is visible but not legible. */
.site-head {
  position: sticky;
  top: 0;
  z-index: 20;
  min-height: var(--head-h);
  border-bottom: 1px solid var(--border);
  padding-block: 0.7rem;
  background: var(--canvas);
  background: color-mix(in srgb, var(--canvas) 80%, transparent);
  backdrop-filter: blur(14px);
}

.site-head .wrap {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--t1);
  margin-inline-end: auto;
}

.brand-lockup {
  display: block;
  width: auto;
  height: 32px;
  overflow: visible;
}

.brand-lockup__mark {
  color: var(--primary);
}

/* ------ the way into the web app
 *
 * The hero button's white pill at header size, without its disc, and in the
 * shape of the language control beside it. Same 34px height as the theme
 * button so the three controls sit on one line. */

.head-cta {
  flex: none;
  display: inline-flex;
  align-items: center;
  height: 34px;
  padding-inline: 0.85rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--t1);
  font-size: 0.85rem;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  transition:
    opacity 200ms ease,
    transform 200ms ease,
    visibility 0s linear 0s,
    border-color 150ms ease;
}

.head-cta:hover {
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
}

/* On the landing page the header's link steps aside while the hero's own
 * button is on screen, so no screen offers the app twice. ui.js puts
 * data-observe on <html> from <head>, before the first paint, and only where
 * IntersectionObserver exists; it adds .is-hero-away once the hero button has
 * gone under the header (or starts below the fold). Every other page, and a
 * browser without the script or :has(), keeps the link throughout.
 * visibility rather than display: the row keeps its shape when the link comes
 * back, and a hidden link also leaves the tab order. The visibility change
 * waits for the fade on the way out and is immediate on the way in. */
:root[data-observe]:has([data-hero-open]) .site-head:not(.is-hero-away) .head-cta {
  opacity: 0;
  transform: translateY(-4px);
  visibility: hidden;
  transition:
    opacity 200ms ease,
    transform 200ms ease,
    visibility 0s linear 200ms,
    border-color 150ms ease;
}

.head-cta:focus-visible {
  border-radius: 999px;
}

/* The short label exists for phones only; see the narrow-header rule below. */
.head-cta__short {
  display: none;
}

/* ------ theme button */

/* flex: none, like the app link: squeezed, a 34px circle became a 20px oval
   before anything else on the row gave way. */
.theme-toggle {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 999px;
  background: none;
  color: var(--t2);
  cursor: pointer;
}

.theme-toggle:hover {
  background: var(--surface-alt);
  color: var(--t1);
}

.theme-toggle svg {
  width: 18px;
  height: 18px;
}

/* One icon per theme: the moon is what the button will do, not what is on. */
.theme-toggle__sun {
  display: none;
}

[data-theme='dark'] .theme-toggle__sun {
  display: block;
}

[data-theme='dark'] .theme-toggle__moon {
  display: none;
}

/* ------ language menu
 *
 * Seven endonyms laid out inline took more width than the logo and wrapped
 * onto two rows on a phone, so the first thing a reader met was a language
 * list. One disclosure instead — native <details>, so it still opens with
 * JavaScript off; ui.js only closes it on Escape or an outside click. */

.langs {
  position: relative;
}

.langmenu > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--t2);
  font-size: 0.85rem;
  cursor: pointer;
  list-style: none;
  user-select: none;
  white-space: nowrap;
}

.langmenu > summary::-webkit-details-marker {
  display: none;
}

.langmenu > summary:hover,
.langmenu[open] > summary {
  color: var(--t1);
}

.langmenu__panel {
  position: absolute;
  inset-inline-end: 0;
  top: calc(100% + 0.5rem);
  z-index: 30;
  display: flex;
  flex-direction: column;
  min-width: 12rem;
  padding: 0.3rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-lift);
}

.langmenu__panel a {
  padding: 0.45rem 0.7rem;
  border-radius: 9px;
  color: var(--t2);
  text-decoration: none;
  font-size: 0.92rem;
}

.langmenu__panel a:hover {
  background: var(--surface-alt);
  color: var(--t1);
}

.langmenu__panel a[aria-current='page'] {
  color: var(--primary);
  font-weight: 600;
}

/* No page padding here — the landing page's bands run edge to edge and set
   their own; prose pages get theirs from .prose-page. */
main {
  flex: 1;
}

.site-foot {
  border-top: 1px solid var(--border);
  margin-block-start: clamp(2rem, 5vw, 4rem);
  padding-block: clamp(2rem, 4vw, 3rem) 2.5rem;
  color: var(--t3);
  font-size: 0.9rem;
}

.site-foot .wrap {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

/* align-items, not the default stretch: an <svg> with width:auto stretched to
   the column's full width centres its own artwork inside it, which read as a
   logo mysteriously centred over left-aligned text. */
.site-foot__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
}

.site-foot .brand-lockup {
  height: 26px;
  color: var(--t1);
}

/* The brand on one side and its accounts elsewhere on the other; the accounts
   drop under the brand when the row runs out of width. */
.site-foot__top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem 2rem;
}

/* Round links the size of a thumb, each holding one platform's mark in the
   footer's own colour. The negative margin is the ring around a mark: with
   it the marks themselves, not their empty circles, line up with the edge of
   the text above and below, on whichever side the row lands. */
.site-foot__social {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin: -0.5rem -0.625rem;
  padding: 0;
  list-style: none;
}

.site-foot__social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 999px;
  color: var(--t2);
}

.site-foot__social a:hover {
  background: var(--surface-alt);
  color: var(--t1);
}

.site-foot__social svg {
  width: 1.25rem;
  height: 1.25rem;
}

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

.site-foot a {
  color: var(--t2);
}

.site-foot__legal {
  padding-block-start: 1rem;
  border-block-start: 1px solid var(--border);
}

.site-foot__disclosure {
  margin-block-end: 0.4rem;
  max-width: 65ch;
  line-height: 1.45;
  font-size: 0.85rem;
}

.site-foot__marks {
  margin-block-start: 0.4rem;
  font-size: 0.8rem;
  color: var(--t3);
}

.disclaimer {
  color: var(--t3);
  max-width: 42ch;
}

/* "Cookie settings" opens something on this page and leads nowhere, so it is
   a button, set as one of the footer's links. */
.site-foot__settings {
  padding: 0;
  border: 0;
  background: none;
  color: var(--t2);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* ------ the cookie question
 *
 * A quiet card at the foot of the window, over the page and not in its way:
 * it holds nothing back, so the page stays readable and usable behind it.
 * The two answers are the same button side by side: declining is not the
 * harder one to find. */

.measure {
  position: fixed;
  inset-inline: 1rem;
  inset-block-end: 1rem;
  z-index: 40;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
  max-width: 46rem;
  margin-inline: auto;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
}

.measure__text {
  flex: 1 1 18rem;
  color: var(--t2);
  font-size: 0.9rem;
  line-height: 1.5;
}

.measure__actions {
  display: flex;
  gap: 0.5rem;
  margin-inline-start: auto;
}

.measure__btn {
  min-height: 40px;
  padding: 0.45rem 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--t1);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

.measure__btn:hover {
  background: var(--surface-alt);
}

/* ------------------------------------------------------------ long prose */

.prose h1 {
  font-size: 1.7rem;
  line-height: 1.25;
  margin-bottom: 0.4rem;
  text-wrap: balance;
}

.prose .meta {
  color: var(--t3);
  font-size: 0.9rem;
  margin-bottom: 2rem;
}

.prose h2 {
  font-size: 1.15rem;
  margin: 2.2rem 0 0.6rem;
}

.prose p,
.prose ul,
.prose ol {
  color: var(--t2);
  margin-bottom: 0.9rem;
}

.prose ul,
.prose ol {
  padding-inline-start: 1.3rem;
}

.prose li {
  margin-bottom: 0.35rem;
}

.prose strong {
  color: var(--t1);
}

/* Tables can be wider than the measure — scroll them, never the page. */
.table-scroll {
  overflow-x: auto;
  margin-bottom: 1rem;
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
  min-width: 34rem;
}

.prose th,
.prose td {
  text-align: start;
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
  color: var(--t2);
}

.prose th {
  color: var(--t1);
}

.card {
  background: var(--primary-tint);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  margin: 1rem 0;
}

.card p:last-child {
  margin-bottom: 0;
}

/* The page that says what Delvia Health is (templates/about.html): its first
   paragraph is the definition, a step larger than the answers under it and in
   the ink colour, and it ends on the home page's two ways in, set at the
   start of the line, where this page's text is. */
.prose .about-lead {
  margin-block: 1.1rem 2.4rem;
  font-size: 1.2rem;
  line-height: 1.55;
  color: var(--t1);
  text-wrap: pretty;
}

.about-start {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem 1rem;
  margin-block-start: 2.6rem;
}

.translation-note {
  color: var(--t3);
  font-size: 0.85rem;
  border-inline-start: 3px solid var(--border);
  padding-inline-start: 0.9rem;
  margin-bottom: 1.5rem;
}

/* ---------------------------------------------------------------- forms */

.form-row {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-bottom: 1rem;
}

label {
  font-size: 0.9rem;
  font-weight: 600;
}

input[type='email'],
input[type='password'] {
  font: inherit;
  font-size: 1rem;
  color: var(--t1);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.7rem 0.85rem;
  width: 100%;
}

.consent {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-weight: 400;
  color: var(--t2);
  line-height: 1.5;
}

.consent input {
  margin-top: 0.3rem;
  accent-color: var(--primary);
}

.btn {
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 0.7rem 1.2rem;
  background: var(--primary);
  color: var(--on-primary);
}

.btn:hover {
  background: var(--primary-pressed);
}

.btn[disabled] {
  opacity: 0.55;
  cursor: default;
}

/* Not a hard-coded white: --danger is a light red in dark mode, and white on
   it lands around 2.5:1. This is the account-deletion button — the one
   destructive control on the site — so it takes the token that is defined to
   contrast with a bright fill in both themes. */
.btn-danger {
  background: var(--danger);
  color: var(--on-primary);
}

.btn-danger:hover {
  filter: brightness(0.92);
}

.notice {
  border-radius: var(--radius);
  padding: 0.9rem 1rem;
  margin: 1rem 0;
  border: 1px solid var(--border);
}

.notice-error {
  background: var(--danger-tint);
  border-color: var(--danger);
  color: var(--danger);
}

.notice-success {
  background: var(--primary-tint);
  border-color: var(--success);
  color: var(--success);
}

[hidden] {
  display: none !important;
}

/* --------------------------------------------------------------- landing
 *
 * A column of soft panels on the page's own ground, in the shape of the app's
 * own screens. The version before this was one flat canvas with hairlines
 * between sections, which read as ten thousand pixels of grey document; the
 * panels give each section an edge and give the screenshots somewhere to sit.
 *
 * The imagery is nothing but real captures of the shipped app. An earlier
 * version drew a phone in CSS with an invented transcript and an SVG trend
 * chart with an invented polyline. Both are gone: assets/shots/ holds the real
 * thing in all seven languages, and a drawn imitation of your own product is
 * the one asset you never have to fake.
 *
 * Everything sits on logical properties (inline-start/end, border-block) so
 * the Arabic build mirrors without a second set of rules.
 */

.lp {
  width: 100%;
  max-width: var(--page-lp);
  margin-inline: auto;
  padding-inline: clamp(1rem, 3vw, 2rem);
  display: flex;
  flex-direction: column;
  gap: clamp(1rem, 1.5vw, 1.5rem);
}

.lp-panel {
  display: flex;
  flex-direction: column;
  gap: clamp(2rem, 4vw, 3rem);
  padding: clamp(1.75rem, 4vw, 3.5rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--panel-radius);
  box-shadow: var(--shadow-panel);
  /* No overflow: hidden here. A stage clips its own screenshot and never
     reaches the panel's edge anyway, and an overflow on an ancestor makes it
     the scroll container for any position: sticky inside — which would stop
     the FAQ heading sticking to the viewport. */
  /* The header is sticky: an anchored panel would otherwise land under it. */
  scroll-margin-block-start: 5rem;
}

/* ------ type */

/* A headline breaks between words. overflow-wrap is the backstop for a word
   wider than its line, which only then breaks, and without a hyphen. */
.lp h1 {
  font-size: clamp(2.6rem, 5.6vw, 4.25rem);
  line-height: 1.03;
  letter-spacing: -0.035em;
  font-weight: 600;
  text-wrap: balance;
  hyphens: manual;
  overflow-wrap: break-word;
}

.lp h2 {
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.14;
  letter-spacing: -0.022em;
  font-weight: 600;
  text-wrap: balance;
  hyphens: manual;
  overflow-wrap: break-word;
}

/* hyphens for the two languages whose headline words are that long: German's
   nouns are compounds ("Gesundheitsgeschichte" is 21 characters and at the
   hero size wider than a 390px phone, with no space in it to break at), and
   Russian's run nearly as long. The <html lang> picks the dictionary. Only
   for them: with `auto` on every language, balancing the lines cut English
   ("for-get"), French and Italian words that fitted whole (2026-10-09). */
.lp h1:lang(de),
.lp h2:lang(de),
.lp h1:lang(ru),
.lp h2:lang(ru) {
  hyphens: auto;
}

/* Arabic carries dots under its letters as well as over them, and at a Latin
   headline's leading the dots under one line sit against the dots over the
   next, where they read as belonging to either (the owner's word,
   2026-10-06). Its headings get more room between their lines and nothing
   else: the size and the weight stay the other languages'. */
.lp h1:lang(ar),
.lp h2:lang(ar) {
  line-height: 1.32;
}

.lp-lede {
  font-size: clamp(1.125rem, 1.5vw, 1.3rem);
  line-height: 1.55;
  color: var(--t2);
  text-wrap: pretty;
}

.lp-body {
  font-size: 1.0625rem;
  line-height: 1.7;
  color: var(--t2);
  text-wrap: pretty;
}

.lp-label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--t3);
}

/* Prose stops at a measure even when its column is wider. Applied to the
   children so the column itself still fills its grid track. */
.lp-copy {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.lp-copy > * {
  max-width: var(--measure-lp);
}

/* ------ two columns */

.lp-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
  gap: clamp(2rem, 4.5vw, 4rem);
  align-items: start;
}

.lp-split-center {
  align-items: center;
}

/* Image first, copy second — alternated down the page so it does not read as
   a stack of identical rows. `order` rather than source order, so the reading
   order stays copy-then-image for a screen reader and for a narrow screen.
   The tracks swap with it, or the image lands in the track sized for prose. */
.lp-split-flip {
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
}

.lp-split-flip > :first-child {
  order: 2;
}

.lp-split-flip > :last-child {
  order: 1;
}

/* Fifteen questions under a heading leaves half the panel empty; beside it,
   the heading holds the column the answers do not need — and it travels with
   them, because fifteen rows are taller than one heading and the column would
   otherwise empty out under it. */
.lp-split-faq {
  grid-template-columns: minmax(0, 0.55fr) minmax(0, 1fr);
}

.lp-split-faq > .lp-copy {
  position: sticky;
  top: 5.5rem;
  align-self: start;
}

/* ------ the real screenshots
 *
 * One treatment everywhere: the capture inset in a thin bezel of the page's
 * own surface. No drawn notch and no invented status bar — the Play assets
 * carry those because a bare capture reads as a card at thumbnail size, but at
 * this scale they would just be more fiction on a page that is removing it.
 *
 * The captures are light-theme (capture.mjs pins the preference), which is
 * what a lit phone looks like on any ground, so nothing is recoloured. */
.lp-shot {
  width: min(20rem, 100%);
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 30px;
  box-shadow: var(--shadow-lift);
}

.lp-shot img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 24px;
}

/* A phone is taller than any column of copy beside it. Rather than shrink it
   until the app is unreadable, it stands on a tinted stage and runs off the
   bottom of it: a deliberate crop with an edge, instead of a mask fading into
   nothing — and true to the app, where these screens keep going below the
   fold too. */
.lp-stage {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  height: clamp(21rem, 44vw, 28rem);
  padding: clamp(1.25rem, 3vw, 2rem) 0.75rem 0;
  background: var(--surface-alt);
  border-radius: 22px;
  overflow: hidden;
}

.lp-stage .lp-shot {
  width: min(19rem, 100%);
  box-shadow: none;
}

.lp-stage-sm {
  height: clamp(18rem, 36vw, 23rem);
}

/* A single element lifted out of a capture at reading size — the one thing a
   screenshot of a whole screen cannot do at web scale. It sits under the
   paragraph it illustrates, not over the phone: a crop laid on the device's
   face reads as a sticker, and lands somewhere different at every width. Its
   corners are transparent in the file itself, so the shadow follows the
   card's own shape rather than a box around it. */
.lp-crop {
  width: min(24rem, 100%);
  margin: 0.5rem 0 0;
}

.lp-crop img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(var(--shadow-crop));
}

/* ------ hero */

/* Centred, on open canvas rather than in a panel, so the page opens with air
   and the product gets one moment instead of half a column. Centred also
   mirrors for Arabic with nothing to flip. */
.lp-hero {
  /* The phone's frame is 20rem wide, or the screen less its gutters. */
  --hero-shot: min(20rem, calc(100vw - 2 * clamp(1rem, 3vw, 2rem)));
  /* How much of the phone the first screen shows: its frame (7px) and the
     capture down to just under the greeting, which ends 0.36 of the
     capture's width down; the green card under it starts at 0.43. */
  --hero-peek: calc(7px + (var(--hero-shot) - 14px) * 0.395);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* The phone is placed against the bottom of the first screen (user decision
   2026-10-02): in every language and at every window size it shows down to
   its greeting and no further, the green card just under the fold. So the
   block above it is as tall as the screen less the header and that much of
   the phone, and what it holds sits in the middle of it: the space above and
   below the copy is what gives, never the phone's place. A screen too short
   for the copy lets the block grow and the phone start lower; a very tall one
   stops the block growing and shows more of the phone instead of a void. */
.lp-hero-top {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(0.75rem, 2.6vh, 1.25rem);
  width: 100%;
  min-height: min(calc(100vh - var(--head-h) - var(--hero-peek)), 64rem);
  min-height: min(calc(100svh - var(--head-h) - var(--hero-peek)), 64rem);
  padding-block: clamp(0.75rem, 3vh, 3rem) clamp(1.25rem, 3vh, 3rem);
}

.lp-hero h1 {
  max-width: min(18ch, 100%);
}

/* The lede is one sentence set centred, so its lines are evened out: left to
   fill each line, it ended on two stranded words ("that history."). The
   number of lines stays what the measure makes it. */
.lp-hero .lp-lede {
  max-width: 46ch;
  text-wrap: balance;
}

/* A longer translation gets a wider measure, not more lines. Wherever the
   page has the room, the headline is two lines and the lede four in every
   language, so the phone's top edge lands where it does in English and
   shows in the first screen. At one measure for all, German and Russian
   took three headline lines and up to six lede lines, which pushed the
   phone under the fold.

   Each headline value is the narrowest that holds two lines in Chrome
   (de 22ch, ru 19ch) plus a few ch for another browser's metrics.

   The lede is the definition sentence since 2026-10-12 (about.definition)
   and was measured again that day at 1440 by 900. It takes four lines from
   the first width given here to the second, where it drops to three:
   en 38 to 46, it 38 to 50, ms 41 to 52, ru 42 to 55, de 43 to 53,
   fr 44 to 60. Each value sits inside its language's range, so no language
   sets a wide three-line block under a two-line headline. Arabic's is
   shorter and takes three lines at the common measure. A change to a
   language's hero copy means measuring again. */
.lp-hero h1:lang(de) {
  max-width: min(24ch, 100%);
}

.lp-hero h1:lang(ru) {
  max-width: min(21ch, 100%);
}

.lp-hero .lp-lede:lang(en) {
  max-width: 43ch;
}

.lp-hero .lp-lede:lang(de),
.lp-hero .lp-lede:lang(ru) {
  max-width: 48ch;
}

.lp-hero .lp-lede:lang(fr) {
  max-width: 51ch;
}

/* The wash and the phone share one grid cell, so the glow is centred on the
   device in both directions without a physical-property transform. */
.lp-hero-shot {
  display: grid;
  justify-items: center;
  width: 100%;
}

.lp-hero-shot > * {
  grid-area: 1 / 1;
}

.lp-hero-shot::before {
  content: '';
  grid-area: 1 / 1;
  align-self: stretch;
  width: min(52rem, 94vw);
  background: radial-gradient(
    closest-side,
    color-mix(in srgb, var(--primary) 12%, transparent),
    transparent
  );
}

/* An outlined chip, not a filled button: it states a fact (the web app is
   live), and the button that acts on it is .lp-cta below the lede. Two
   button-shaped things saying the same thing would be one too many. */
.lp-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--primary);
}

.lp-pill::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--primary);
  flex: none;
}

.lp-textlink {
  font-size: 0.95rem;
  color: var(--t2);
  text-decoration-color: var(--border);
  text-underline-offset: 4px;
}

.lp-textlink:hover {
  color: var(--primary);
}

/* The hero's actions come after the lede, a little further from it than the
   hero's own gap, because they answer it: the Google Play badge and, after
   it, the button, whose arrow then points off the row and not at the badge
   (user decision 2026-10-07), then one quiet line under both. Each row wraps
   only when a narrow screen leaves it no choice (the advert page's longer
   label on a phone: French at 390 px, Russian at 360), and then it wraps
   upwards,
   so the button stands over the badge: stacked, no arrow points at anything,
   and the way into the web app is still the first thing under the lede. */
.lp-hero-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  margin-block-start: 0.6rem;
}

.lp-hero-row {
  display: flex;
  flex-wrap: wrap-reverse;
  align-items: center;
  justify-content: center;
  gap: 0.9rem 1rem;
}

/* Google's own badge, as tall as the button beside it. The files are
   Google's artwork with only the transparent margin trimmed, and they come in
   two pixel sizes of almost one shape, so the height is set and the width
   follows each file: nothing is stretched. The height sits on the image
   itself: as a percentage of the link's, the row measured the file at its
   full pixel width and put the badge under the button with room to spare.
   The row's gap is the clear space Google asks for, a quarter of the badge's
   height. */
.lp-store {
  flex: none;
  display: block;
  border-radius: 8px;
  transition: transform 150ms ease;
}

.lp-store img {
  display: block;
  width: auto;
  height: 52px;
}

.lp-store:active {
  transform: translateY(1px);
}

.lp-store:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}

/* The hero's way into the web app (user decision 2026-09-30): a white pill
   with ink text, never a teal block, whose one teal thing is the disc its
   arrow sits in at the trailing end. The bloom circle and the teal glow it
   used to carry are gone: five parts in one pill read as a badge. Hover warms
   the edge and slides the arrow on, both themes from the tokens. */
.lp-open {
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
  min-height: 52px;
  padding-block: 6px;
  padding-inline: 1.4rem 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--t1);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 1px 2px rgb(15 23 42 / 5%);
  transition: border-color 150ms ease, transform 150ms ease;
}

.lp-open:hover {
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
}

.lp-open:active {
  transform: translateY(1px);
}

/* The global focus ring rounds itself to 4px; keep the pill's shape. */
.lp-open:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
  border-radius: 999px;
}

/* --on-primary, not white: dark mode's primary is a bright teal, and the
   token is the one defined to contrast with it in both themes. */
.lp-open__disc {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--primary);
  color: var(--on-primary);
}

.lp-open__arrow {
  width: 16px;
  height: 16px;
  transition: transform 150ms ease;
}

.lp-open:hover .lp-open__arrow {
  transform: translateX(3px);
}

/* The arrow points the way the line reads. */
[dir='rtl'] .lp-open__arrow {
  transform: scaleX(-1);
}

[dir='rtl'] .lp-open:hover .lp-open__arrow {
  transform: scaleX(-1) translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
  .lp-open,
  .lp-store,
  .lp-open__arrow {
    transition: none;
  }
}

/* ------ the page an advert leads to (templates/start.html)
 *
 * The home page's hero and panels, and five things of its own: ticked
 * lists, three numbered steps, a taller stage for a conversation, the
 * family band, and the closing panel with the button under what it gets.
 * All from the tokens, so both themes follow, and on logical properties, so
 * Arabic mirrors.
 */

/* The headline is two short sentences, longer than the home page's one, so
   it gets a wider measure and a size a step down: it has to leave the button
   in the first screen of a phone. */
.ad .lp-hero h1 {
  max-width: min(21ch, 100%);
  font-size: clamp(2.25rem, 4.6vw, 3.6rem);
  line-height: 1.08;
}

/* Arabic keeps the room between lines its headings have on every page
   (.lp h1:lang(ar)), which the rule above would otherwise take back. */
.ad .lp-hero h1:lang(ar) {
  line-height: 1.32;
}

.ad .lp-hero .lp-lede {
  max-width: 54ch;
  text-wrap: pretty;
}

/* An iPhone or an iPad cannot install from Google Play: there the badge is
   left off these pages, in the hero and in the closing panel, and the button
   stands alone (user decision 2026-10-08; ui.js sets the mark before the
   first paint). The home page keeps it for everyone. */
:root[data-apple] .ad .lp-store {
  display: none;
}

/* The languages whose headline runs longest get a wider measure, not more
   lines, as on the home page. */
.ad .lp-hero h1:lang(de),
.ad .lp-hero h1:lang(fr),
.ad .lp-hero h1:lang(it),
.ad .lp-hero h1:lang(ms),
.ad .lp-hero h1:lang(ru) {
  max-width: min(28ch, 100%);
}

/* A list whose items each carry the drawn tick the plan cards use. */
.ad-ticks {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin: 0.25rem 0 0;
  padding: 0;
  list-style: none;
  color: var(--t1);
  line-height: 1.5;
}

.ad-ticks li {
  position: relative;
  padding-inline-start: 2rem;
}

/* The tick sits in a disc of the brand's tint, as the benchmark's arrow does. */
.ad-ticks li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0.1em;
  width: 1.3rem;
  height: 1.3rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--primary) 14%, transparent);
}

.ad-ticks li::after {
  content: '';
  position: absolute;
  inset-inline-start: 0.5rem;
  inset-block-start: calc(0.1em + 0.3rem);
  width: 0.3rem;
  height: 0.58rem;
  border: solid var(--primary);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Under the hero's buttons: the same ticks in one centred row, quieter. */
.ad-ticks--row {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.5rem;
  margin: 0.35rem 0 0;
  font-size: 0.9rem;
  color: var(--t2);
}

.ad-ticks--row li {
  padding-inline-start: 1.7rem;
}

.ad-ticks--row li::before {
  inset-block-start: 0.05em;
  width: 1.2rem;
  height: 1.2rem;
}

.ad-ticks--row li::after {
  inset-inline-start: 0.46rem;
  inset-block-start: calc(0.05em + 0.27rem);
  width: 0.28rem;
  height: 0.54rem;
}

/* Three steps side by side, each a card on the stage's ground with its
   number in a disc of the brand colour. The number is a counter, so the
   markup is one loop in every language. */
.ad-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(0.9rem, 2vw, 1.5rem);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: ad-step;
}

.ad-steps li {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: clamp(1.25rem, 2.4vw, 1.75rem);
  background: var(--surface-alt);
  border-radius: 22px;
  counter-increment: ad-step;
}

.ad-steps li::before {
  content: counter(ad-step);
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  margin-block-end: 0.5rem;
  border-radius: 50%;
  background: var(--primary);
  color: var(--on-primary);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.ad-steps h3 {
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1.3;
  text-wrap: balance;
}

.ad-steps p {
  color: var(--t2);
  line-height: 1.6;
  text-wrap: pretty;
}

/* A conversation reads from its top: the stage is taller for it, so the
   question and the answer that draws on earlier results are both in view. */
.lp-stage.ad-stage-tall {
  height: clamp(31rem, 60vw, 34rem);
}

/* The family: a band in the brand's tint, its mark beside the words. */
.ad-family {
  flex-direction: row;
  align-items: center;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  background: var(--primary-tint);
  border-color: color-mix(in srgb, var(--primary) 16%, var(--border));
  box-shadow: none;
}

.ad-family__mark {
  flex: none;
  width: clamp(3.5rem, 7vw, 5rem);
  height: clamp(3.5rem, 7vw, 5rem);
  padding: clamp(0.8rem, 1.6vw, 1.15rem);
  border-radius: 28%;
  background: var(--surface);
  color: var(--primary);
}

.ad-family .lp-copy {
  gap: 0.6rem;
}

.ad-family .lp-copy > * {
  max-width: 44rem;
}

.ad-family__note {
  font-size: 0.9rem;
  color: var(--t2);
}

/* The closing panel ends the page as the hero opened it, on one axis: the
   heading, what the Free plan holds, then the hero's own row (the badge and
   the button) with its quiet line under it. It was two columns, the list at
   one edge and the buttons at the other with the panel's width empty between
   them (the owner's word 2026-10-08: it needed more elegance).

   The brand's colour rises from the panel's foot, as it does behind the
   hero's phone: the button is white, and on a white panel it stood behind
   Google's black badge, the lesser of the two ways in. */
.ad-end {
  align-items: center;
  gap: clamp(1.5rem, 3vw, 2.25rem);
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  text-align: center;
  background:
    radial-gradient(
      ellipse 62% 90% at 50% 100%,
      color-mix(in srgb, var(--primary) 11%, transparent),
      transparent
    ),
    var(--surface);
}

/* Three lines of what Free does, in one row, quieter than the heading they
   support. The block is as wide as its words and stands in the middle; each
   line still starts at its tick, and a line too long for its column breaks
   inside it. */
.ad-end .ad-ticks {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, max-content));
  justify-content: center;
  gap: 0.75rem clamp(1.5rem, 3vw, 2.5rem);
  margin: 0;
  color: var(--t2);
  text-align: start;
}

.ad-end__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  margin-block-start: 0.5rem;
}

.ad-end__note {
  font-size: 0.9rem;
  color: var(--t2);
}

/* Its way to the plans, where Free's limits stand in full: a link in the
   line's own colour, so the button above stays the panel's one call. */
.ad-end__note a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.ad-end__note a:hover {
  color: var(--t1);
}

@media (max-width: 56rem) {
  .ad-steps {
    grid-template-columns: 1fr;
  }

  /* One line to a row again, the block still in the middle. */
  .ad-end .ad-ticks {
    grid-template-columns: minmax(0, max-content);
  }
}

@media (max-width: 36rem) {
  .ad-family {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* On a phone the headline follows the screen's height, as the home page's
   does, from a smaller start: two sentences in four lines. */
@media (max-width: 30rem) {
  .ad .lp-hero h1 {
    font-size: clamp(1.75rem, 4.7svh, 2.25rem);
    line-height: 1.12;
  }

  .ad-ticks--row {
    gap: 0.4rem 1.1rem;
    font-size: 0.85rem;
  }
}

/* The app's primary button: 48px, radius 12, teal with its on-primary text.
   Both themes come from the tokens (dark mode is bright teal with dark text,
   exactly as in the app), so there is no second rule for dark. */
.lp-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  min-width: 12rem;
  padding: 0.75rem 1.6rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--primary);
  color: var(--on-primary);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  box-shadow: 0 10px 24px -14px color-mix(in srgb, var(--primary) 70%, transparent);
  transition: background-color 120ms ease, transform 120ms ease;
}

.lp-cta:hover {
  background: var(--primary-pressed);
}

.lp-cta:active {
  background: var(--primary-pressed);
  transform: translateY(1px);
}

/* The global focus ring rounds itself to 4px, which would square the
   button's corners the moment it takes focus. */
.lp-cta:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
  border-radius: var(--radius);
}

/* The same button without the fill, for a page where it is the way out rather
   than the thing to do (the checkout page's "Back to Delvia"). */
.lp-cta--quiet {
  background: var(--surface);
  border-color: var(--border);
  color: var(--t1);
  box-shadow: none;
}

.lp-cta--quiet:hover,
.lp-cta--quiet:active {
  background: var(--surface-alt);
}

/* The data link and the line about the iPhone app: one line with a dot
   between them wherever both fit, so the phone below keeps its place in the
   first screen. A longer language on a phone takes two lines, and there the
   dot would open the second: ui.js sets .is-stacked when that happens, which
   CSS alone cannot tell. Without the script the dot simply stays. */
.lp-hero-notes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.3rem 0;
  font-size: 0.9rem;
}

.lp-hero-notes .lp-textlink {
  font-size: inherit;
}

.lp-hero-notes.is-stacked {
  flex-direction: column;
}

/* Quiet, but --t2 rather than --t3: at this size --t3 on the canvas is well
   under a readable contrast, and this line is information, not decoration. */
.lp-soon {
  color: var(--t2);
}

.lp-soon::before {
  content: '';
  display: inline-block;
  width: 3px;
  height: 3px;
  margin-inline: 0.75rem;
  border-radius: 50%;
  background: var(--t3);
  vertical-align: middle;
}

.lp-hero-notes.is-stacked .lp-soon::before {
  display: none;
}

/* A short desktop window: the headline and the lede follow the window's
   height below about 680px, so the copy still fits above the phone. */
@media (min-width: 30.0625rem) {
  .lp-hero h1 {
    font-size: min(clamp(2.6rem, 5.6vw, 4.25rem), 10svh);
  }

  .lp-hero .lp-lede {
    font-size: min(clamp(1.125rem, 1.5vw, 1.3rem), 3.1svh);
  }
}

/* On a phone the button and the badge stay side by side by both giving up a
   little size, and the copy's size follows the screen's height, so that it
   fits above the phone on a short screen: the headline and the lede shrink
   with the height, within limits, and the longer languages start from a
   smaller size. The figures are the largest that keep the phone's place on a
   360 by 640 screen in Chrome; a change to a language's hero copy means
   measuring again (as with the measures above). A screen shorter than that
   lets the phone start lower. */
@media (max-width: 30rem) {
  .lp-hero-top {
    gap: clamp(0.5rem, 2vh, 1rem);
    padding-block: clamp(0.375rem, 2vh, 2rem) clamp(0.8rem, 2.5vh, 2rem);
  }

  .lp-hero h1 {
    font-size: clamp(2rem, 5.9svh, 2.6rem);
  }

  .lp-hero .lp-lede {
    font-size: clamp(0.9375rem, 2.6svh, 1.125rem);
    line-height: 1.5;
  }

  .lp-hero h1:lang(de),
  .lp-hero h1:lang(fr),
  .lp-hero h1:lang(ru) {
    font-size: clamp(1.75rem, 5svh, 2.6rem);
  }

  .lp-hero .lp-lede:lang(de),
  .lp-hero .lp-lede:lang(fr),
  .lp-hero .lp-lede:lang(it),
  .lp-hero .lp-lede:lang(ms),
  .lp-hero .lp-lede:lang(ru) {
    font-size: clamp(0.9375rem, 2.35svh, 1.125rem);
  }

  .lp-hero-actions {
    margin-block-start: 0;
  }

  .lp-hero-row {
    gap: 0.75rem 0.7rem;
  }

  .lp-open {
    gap: 0.6rem;
    min-height: 44px;
    padding-block: 5px;
    padding-inline: 1rem 5px;
    font-size: 0.95rem;
  }

  .lp-open__disc {
    width: 34px;
    height: 34px;
  }

  .lp-store img {
    height: 44px;
  }
}

@media (max-width: 23.5rem) {
  .lp-open {
    gap: 0.5rem;
    min-height: 40px;
    padding-block: 4px;
    padding-inline: 0.85rem 4px;
    font-size: 0.9rem;
  }

  .lp-open__disc {
    width: 32px;
    height: 32px;
  }

  .lp-store img {
    height: 40px;
  }
}

/* ------ the three numbers, on the page's one inverted ground */

.lp-ink {
  background: var(--ink);
  border-color: transparent;
  color: var(--on-ink);
}

.lp-ink h2 {
  color: var(--on-ink);
}

.lp-ink .lp-lede {
  color: var(--on-ink-dim);
}

/* Three explicit columns rather than auto-fit: with three items, an auto-fit
   grid at tablet width strands the third on a row of its own. */
.lp-figures {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
  margin: 0;
}

.lp-figures > div {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding-block-start: clamp(1rem, 2vw, 1.5rem);
  border-block-start: 1px solid var(--ink-rule);
}

.lp-figures dt {
  font-size: clamp(1.9rem, 3.2vw, 2.8rem);
  line-height: 1.05;
  font-weight: 600;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

.lp-figures dd {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--on-ink-dim);
  text-wrap: pretty;
}

/* ------ what it remembers about you */

.lp-cats-wrap {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* A list, not an icon grid: six icons in six boxes is the feature grid this
   page is deliberately not. Six divides evenly by three, two and one, so
   auto-fit never strands a row here. */
.lp-cats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  column-gap: clamp(1.5rem, 4vw, 3rem);
  margin: 0;
}

/* Name over detail, always — inline would put the short ones on one line and
   the long ones on two, and six rows at two different heights read as an
   accident. */
.lp-cats > div {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding-block: 1rem;
  border-block-start: 1px solid var(--border);
}

.lp-cats dt {
  font-weight: 600;
}

.lp-cats dd {
  margin: 0;
  color: var(--t2);
  font-size: 0.95rem;
}

/* ------ the benchmark comparison
 *
 * A bar chart on the ground and corner of a screenshot's stage, so the
 * section reads as one of the page's panels and not as a widget set into it:
 * no border and no shadow. Inside, it is set out the way a published chart
 * is: the measure's name with which way is better, a scale with hairline
 * gridlines, each bar's number over it and its name under it, and a foot
 * that says where the figures come from. Every bar starts from zero, so the heights
 * are honest and the numbers do the comparing. Delvia's is the only bar in
 * the brand colour. */

.lp-bench {
  /* One step of the scale: 20 points at the 2.5 pixels a point the bars in
     landing.html are drawn to. Four steps make the plot, 0 to 80%. */
  --bench-step: 50px;
  --bench-rule: color-mix(in srgb, var(--t3) 30%, transparent);
  display: flex;
  flex-direction: column;
  gap: clamp(1.25rem, 2.6vw, 1.75rem);
  margin: 0;
  padding: clamp(1.25rem, 3.5vw, 2.25rem);
  background: var(--surface-alt);
  border-radius: 22px;
}

.lp-bench-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
}

.lp-bench-title {
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--t1);
}

/* "Lower is better" as a legend: a drawn arrow in a disc of the brand
   colour's tint, then the words, small. The arrow is not in the string, so
   it is the same arrow in every language and sits before the words in
   Arabic too. */
.lp-bench-note {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--t2);
}

.lp-bench-arrow {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  padding: 0.2rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--primary) 14%, transparent);
  color: var(--primary);
}

/* The scale beside the columns. The half line of room above is for the top
   label, which stands centred on the plot's upper edge. */
.lp-bench-chart {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 0.6rem;
  padding-block-start: 0.35rem;
}

/* Five labels on four steps: each sits at the top of its row and is lifted by
   half its own height, which centres it on a gridline; the last row has no
   height, so "0%" lands on the baseline. */
.lp-bench-axis {
  display: grid;
  grid-template-rows: repeat(4, var(--bench-step)) 0;
  height: calc(4 * var(--bench-step));
  font-size: 0.7rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  text-align: end;
  color: var(--t2);
}

.lp-bench-axis > span {
  align-self: start;
  transform: translateY(-50%);
}

/* Two rows shared by all four columns (a subgrid, like the plan cards): the
   bars with their numbers, then the names. A name that takes two lines in
   one column therefore never lifts that column's bar off the baseline. */
.lp-bench-cols {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-template-rows: auto auto;
  margin: 0;
  padding: 0;
  list-style: none;
}

.lp-bench-col {
  display: grid;
  grid-row: span 2;
  grid-template-rows: subgrid;
}

/* The number sits on its bar and the bar on the baseline: one unbroken rule
   under all four, because the cells touch and each bar is inset in its own.
   The gridlines are each cell's own background for the same reason, a
   hairline at the top of every step; the height is the four steps and the
   baseline under them. The inset is a share of the cell, so on a phone the
   bars keep air between them and do not close into a wall. */
.lp-bench-plot {
  grid-row: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 0.3rem;
  height: calc(4 * var(--bench-step) + 1px);
  padding-inline: 16%;
  border-block-end: 1px solid color-mix(in srgb, var(--t3) 75%, transparent);
  background: repeating-linear-gradient(
    to top,
    transparent 0 calc(var(--bench-step) - 1px),
    var(--bench-rule) calc(var(--bench-step) - 1px) var(--bench-step)
  );
}

/* A number stands on the figure's own ground, so a gridline that would run
   through it stops either side of it. */
.lp-bench-val {
  padding: 0.15rem 0.3rem;
  border-radius: 4px;
  background: var(--surface-alt);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--t1);
}

.lp-bench-own .lp-bench-val {
  font-weight: 700;
  color: var(--primary);
}

/* Mixed with the ground and not with nothing: a bar that lets the gridlines
   show through it reads as glass. */
.lp-bench-bar {
  display: block;
  max-width: 3.25rem;
  fill: color-mix(in srgb, var(--t3) 55%, var(--surface-alt));
}

.lp-bench-own .lp-bench-bar {
  fill: var(--primary);
}

.lp-bench-name {
  grid-row: 2;
  padding: 0.65rem 0.15rem 0;
  font-size: 0.8rem;
  line-height: 1.3;
  text-align: center;
  text-wrap: balance;
  color: var(--t2);
}

/* The app's own icon beside its name, where a column is wide enough for
   both, and over it where it is not. */
.lp-bench-own .lp-bench-name {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-content: flex-start;
  justify-content: center;
  gap: 0.2rem 0.3rem;
  font-weight: 600;
  color: var(--t1);
}

.lp-bench-mark {
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
}

.lp-bench-foot {
  margin: 0;
  padding-block-start: 0.85rem;
  border-block-start: 1px solid var(--bench-rule);
  font-size: 0.75rem;
  line-height: 1.5;
  text-wrap: pretty;
  color: var(--t2);
}

/* ------ your data */

/* Two columns, because there are four of them: a three-across grid leaves the
   fourth stranded on a row of its own. */
.lp-points {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(2rem, 5vw, 3.5rem);
  margin: 0;
}

.lp-points > div {
  padding-block: 1.4rem;
  border-block-start: 1px solid var(--border);
}

.lp-points dt {
  font-weight: 600;
  margin-block-end: 0.3rem;
}

.lp-points dd {
  margin: 0;
  color: var(--t2);
  line-height: 1.65;
}

/* The one inset strip on the page, because it is the one thing that should
   read as a notice rather than as prose. */
.lp-note {
  display: flex;
  gap: 0.9rem;
  align-items: flex-start;
  background: var(--surface-alt);
  border-radius: 18px;
  padding: 1.25rem 1.4rem;
}

.lp-note svg {
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--t3);
  margin-block-start: 0.15rem;
}

.lp-note p {
  color: var(--t2);
  font-size: 0.95rem;
  line-height: 1.65;
}

/* ------ plans
 *
 * Four cards in one grid, each a subgrid of four rows (name, price, button,
 * list).
 * Without the subgrid a price line that wraps in one card (German's do) pushes
 * that card's list down, and four lists at four heights read as an accident. Cards sit on the page's own ground inside the panel; the marked
 * one (Family) takes the primary edge and the primary tint, and its badge sits
 * on that edge, absolutely placed so it takes no grid row of its own. No
 * overflow: hidden anywhere here, or the badge would be clipped at the card's
 * top. */
.lp-plans {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(0.9rem, 1.6vw, 1.25rem);
}

.lp-plan {
  position: relative;
  display: grid;
  grid-row: span 4;
  grid-template-rows: subgrid;
  row-gap: 0.9rem;
  align-content: start;
  padding: clamp(1.25rem, 2vw, 1.6rem);
  background: var(--canvas);
  border: 1px solid var(--border);
  border-radius: 20px;
}

.lp-plan--marked {
  background: var(--primary-tint);
  border-color: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary);
}

.lp-plan__badge {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: clamp(1.25rem, 2vw, 1.6rem);
  transform: translateY(-50%);
  padding: 0.2rem 0.7rem;
  border-radius: 999px;
  background: var(--primary);
  color: var(--on-primary);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.lp-plan h3 {
  font-size: 1.2rem;
  line-height: 1.25;
  font-weight: 600;
}

.lp-plan__price {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding-block: 0.9rem;
  border-block: 1px solid var(--border);
  color: var(--t2);
  font-size: 0.9rem;
  line-height: 1.45;
}

.lp-plan__price .lp-plan__amount {
  color: var(--t1);
  font-size: clamp(1.5rem, 2.2vw, 1.85rem);
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin-block-end: 0.2rem;
}

.lp-plan__per {
  font-size: 0.95rem;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--t2);
}

/* One price block per billing period; the switch above the cards shows
   one of them. Yearly is the one shown before anything is chosen. */
.lp-plan__yearly,
.lp-plan__monthly {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.lp-plan__monthly,
#lp-period-monthly:checked ~ .lp-plans .lp-plan__yearly {
  display: none;
}

#lp-period-monthly:checked ~ .lp-plans .lp-plan__monthly {
  display: flex;
}

/* Every figure on a right-to-left page keeps its own order. Unicode reads a
   number that follows Arabic words as an Arabic number, and the dollar sign
   in front of it then drifts to its other side ("بدلاً من 359.88$"); a
   figure that opens the line did not, which is why only some showed it. */
[dir='rtl'] [data-pricing] {
  direction: ltr;
  unicode-bidi: isolate;
}

/* What a plan that holds several people comes to for each of them: a
   quieter second line under the people it holds, one per billing period,
   shown by the switch as the prices are. */
.lp-plan__each {
  display: block;
  margin-block-start: 0.1rem;
  color: var(--t2);
  font-size: 0.85rem;
}

.lp-plan__each--monthly,
#lp-period-monthly:checked ~ .lp-plans .lp-plan__each--yearly {
  display: none;
}

#lp-period-monthly:checked ~ .lp-plans .lp-plan__each--monthly {
  display: block;
}

/* A card's way into the app: one button per card, as wide as the card, in
   the row under the price so the four line up. Outlined on the card's own
   ground; the marked card's is the filled primary button, so the page has
   one loud button among the four. */
.lp-plan__action {
  display: flex;
}

.lp-plan__cta {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0.55rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--t1);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.lp-plan__cta:hover,
.lp-plan__cta:active {
  background: var(--surface-alt);
  border-color: var(--primary);
}

/* The global focus ring rounds itself to 4px, which would square the
   button's corners the moment it takes focus. */
.lp-plan__cta:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
  border-radius: var(--radius);
}

.lp-plan--marked .lp-plan__cta {
  border-color: transparent;
  background: var(--primary);
  color: var(--on-primary);
}

.lp-plan--marked .lp-plan__cta:hover,
.lp-plan--marked .lp-plan__cta:active {
  border-color: transparent;
  background: var(--primary-pressed);
}

/* One link per billing period, each carrying its period into the app; the
   switch shows one of them, as it does the price blocks. */
.lp-plan__cta--monthly,
#lp-period-monthly:checked ~ .lp-plans .lp-plan__cta--yearly {
  display: none;
}

#lp-period-monthly:checked ~ .lp-plans .lp-plan__cta--monthly {
  display: flex;
}

@media (prefers-reduced-motion: reduce) {
  .lp-plan__cta {
    transition: none;
  }
}

/* The switch's own radio inputs: read out and reachable by keyboard, not
   shown (their labels are what is seen and clicked). */
.lp-period__input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The heading and the switch share a row, the switch on the far edge.
   Where they do not fit side by side the switch drops under the heading. */
.lp-plans-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
}

/* The heading takes what the switch leaves and wraps inside it, so a long
   heading (French, Russian) does not push the switch off the row. Under
   16rem of room for it, the switch drops below instead. */
.lp-plans-head .lp-copy {
  flex: 1 1 16rem;
  min-width: 0;
}

/* One segmented control: a quiet track as wide as its two choices, the
   chosen one a raised chip, the other plain text. */
.lp-period {
  display: inline-flex;
  max-width: 100%;
  gap: 2px;
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-alt);
}

.lp-period label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 40px;
  padding: 0.3rem 1.15rem;
  border-radius: 999px;
  color: var(--t2);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.3;
  cursor: pointer;
  transition: background-color 150ms ease, color 150ms ease, box-shadow 150ms ease;
}

.lp-period label:hover {
  color: var(--t1);
}

#lp-period-monthly:checked ~ .lp-plans-head label[for='lp-period-monthly'],
#lp-period-yearly:checked ~ .lp-plans-head label[for='lp-period-yearly'] {
  background: var(--surface);
  color: var(--t1);
  box-shadow: 0 0 0 1px var(--border), 0 2px 6px -2px rgb(15 23 42 / 18%);
}

#lp-period-monthly:focus-visible ~ .lp-plans-head label[for='lp-period-monthly'],
#lp-period-yearly:focus-visible ~ .lp-plans-head label[for='lp-period-yearly'] {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* The saving, in the primary colour on its own tint: it reads on the chip
   and on the track alike, so it still invites when Monthly is chosen. */
.lp-period__save {
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--primary-tint);
  background: color-mix(in srgb, var(--primary) 14%, transparent);
  color: var(--primary);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* On a phone the two choices sit closer, and a label too long for the row
   (Russian's) lets its saving drop under the word: the control never
   grows past the panel. */
@media (max-width: 480px) {
  .lp-period label {
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.15rem 0.4rem;
    padding-inline: 0.85rem;
    border-radius: 22px;
    text-align: center;
  }

  .lp-period {
    border-radius: 26px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .lp-period label {
    transition: none;
  }
}

.lp-plan__features {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.95rem;
  line-height: 1.5;
}

/* A drawn tick in the primary colour: a character would take each font's own
   glyph, and Plex Sans Arabic draws a different one. */
.lp-plan__features li {
  position: relative;
  padding-inline-start: 1.4rem;
}

.lp-plan__features li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0.2rem;
  inset-block-start: 0.35em;
  width: 0.35rem;
  height: 0.65rem;
  border: solid var(--primary);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Three short promises under the cards, each one already made at length
   elsewhere on the site. The same drawn tick as the feature lists. */
.lp-plans-trust {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--t2);
  font-size: 0.9rem;
  line-height: 1.5;
}

/* Centred in the panel where they sit side by side, their gaps unchanged.
   On a phone they stack, and stay on the starting edge so the ticks line
   up under each other. */
@media (min-width: 640px) {
  .lp-plans-trust {
    justify-content: center;
  }
}

.lp-plans-trust li {
  position: relative;
  padding-inline-start: 1.4rem;
}

.lp-plans-trust li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0.2rem;
  inset-block-start: 0.3em;
  width: 0.35rem;
  height: 0.65rem;
  border: solid var(--primary);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* ------ FAQ */

.lp-faq-list {
  display: flex;
  flex-direction: column;
}

.lp-faq-list details {
  border-block-start: 1px solid var(--border);
  padding-block: 1.05rem;
}

/* last-of-type, not last-child: the phone's "Show all questions" control
   follows the list. */
.lp-faq-list details:last-of-type {
  border-block-end: 1px solid var(--border);
}

.lp-faq-list summary {
  cursor: pointer;
  font-size: 1.0625rem;
  font-weight: 600;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
}

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

.lp-faq-list summary::after {
  content: '+';
  color: var(--t3);
  font-weight: 400;
  font-size: 1.2rem;
  line-height: 1;
}

.lp-faq-list details[open] summary::after {
  content: '\2212';
}

.lp-faq-list details p {
  margin-block-start: 0.75rem;
  color: var(--t2);
  line-height: 1.65;
  max-width: 62ch;
}

/* "Show all questions": a phone's control, and nothing on a wider window,
   which shows the whole list. Its tick box is read out and reachable by
   keyboard, not shown, as the plans' switch's radios are. */
.lp-faq-more {
  display: none;
  align-self: center;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  margin-block-start: 1.5rem;
  padding-inline: 1.25rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--t1);
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
}

.lp-faq-more__input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.lp-faq-more:has(.lp-faq-more__input:focus-visible) {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}

/* On a phone seventeen closed rows are two screens of scrolling before the
   footer. Until the control is ticked the list is the six questions a
   newcomer asks first, and the control; ticked, it is everything and the
   control is gone. Only ever display: none, never a display of our own: a
   question about the free trial is also hidden by its own attribute while
   no trial is offered, and a rule that showed it would undo that. A browser
   without :has() matches none of this and shows the whole list. */
@media (max-width: 40rem) {
  .lp-faq-list:has(.lp-faq-more__input:not(:checked)) details[data-more] {
    display: none;
  }

  .lp-faq-list:has(.lp-faq-more__input:not(:checked)) .lp-faq-more {
    display: flex;
  }
}

/* -------------------------------------------------------------- checkout
 *
 * What sits behind Paddle's overlay. One card, one status line at a time
 * (checkout.js reveals it), and a way back. No panel stack and no marketing:
 * someone who is paying should meet nothing but the payment. */

.checkout-page {
  display: flex;
  justify-content: center;
  padding-block: clamp(2.5rem, 9vw, 5.5rem) 1rem;
}

.checkout {
  width: min(28rem, 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: clamp(1.75rem, 5vw, 2.5rem);
  text-align: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--panel-radius);
  box-shadow: var(--shadow-panel);
}

.checkout__mark {
  width: 48px;
  height: 48px;
  padding: 13px;
  border-radius: 50%;
  background: var(--primary-tint);
  color: var(--primary);
}

.checkout h1 {
  font-size: 1.5rem;
  line-height: 1.25;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

/* Holds one line's height while no line shows, so the button below does not
   jump each time the state changes. */
.checkout__status {
  min-height: 1.65em;
  margin-block-end: 0.5rem;
  color: var(--t2);
}

.checkout__line {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-wrap: balance;
}

.checkout__line--done {
  color: var(--t1);
  font-weight: 600;
}

.checkout__spinner {
  flex: none;
  width: 16px;
  height: 16px;
  border: 2px solid var(--border);
  border-block-start-color: var(--primary);
  border-radius: 50%;
  animation: checkout-spin 0.8s linear infinite;
}

@keyframes checkout-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ------ narrow screens */

/* A phone. Brand, app link, theme and language have to share one row in every
   locale, and measured at 320-512px they do not: "Bahasa Melayu" alone is a
   157px pill, and Russian's "Открыть приложение" is 172px. So below 32rem
   (the widest locale's long label needs ~490px) the app link takes its short
   label, the language control shows its globe and chevron only, and the
   gutter drops to 16px. The language name stays in the control for screen
   readers — visually hidden, never removed — and the menu it opens is
   unchanged.

   The short label is a verb, never the noun "App": "Start free" on the
   pages that sell (the verb alone where a language's two words are too wide:
   German, French, Russian) and "Open" on the others. Worked out from the
   row, not yet measured in a browser: at 360px the logo (95px), the theme
   button (34px), the language control (59px) and three gaps leave the pill
   about 120px, 96px of it for text at this size; the widest of the seven,
   Malay's "Mula percuma", is about 90px. */
@media (max-width: 32rem) {
  .site-head .wrap {
    padding-inline: 1rem;
    gap: 0.4rem;
  }

  .head-cta {
    padding-inline: 0.7rem;
  }

  .head-cta__long {
    display: none;
  }

  .head-cta__short {
    display: inline;
  }

  .langmenu > summary > span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* The narrowest phones (320px): the row gives up a little everywhere so the
   same label still stands on one line. */
@media (max-width: 22.4rem) {
  .site-head .wrap {
    padding-inline: 0.75rem;
    gap: 0.3rem;
  }

  .head-cta {
    padding-inline: 0.55rem;
    font-size: 0.8rem;
  }
}

@media (max-width: 56rem) {
  .lp-split,
  .lp-split-flip,
  .lp-split-faq {
    grid-template-columns: 1fr;
    gap: 2.25rem;
  }

  /* Source order again: the copy introduces the screenshot it sits above. */
  .lp-split-flip > :first-child,
  .lp-split-flip > :last-child {
    order: 0;
  }

  /* One column: the heading sits above the questions and scrolls away with
     the page. Pinned here it stayed over them, with no ground of its own. */
  .lp-split-faq > .lp-copy {
    position: static;
  }

  .lp-figures,
  .lp-points {
    grid-template-columns: 1fr;
  }

  .lp-stage {
    height: clamp(19rem, 62vw, 24rem);
  }
}

/* Two by two before the page's other columns fold: four plan cards at tablet
   width are narrower than a German feature line. */
@media (max-width: 68rem) {
  .lp-plans {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 1.5rem;
  }
}

@media (max-width: 40rem) {
  .lp-plans {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
