/* Privaro. The homepage is a short product story on matte graphite: the
   name, what it is and what it costs; the app itself; how it keeps things
   private; a last word. The other pages are plain text.

   The system, in brief:
   - Type: Apple's own font, one family. Character comes from scale and
     weight, not from a second face: a second family would mean a font
     download from somewhere, on a site that promises no trackers. Four
     roles: the mark (the name), display (a section's one statement), title,
     and text. Bold where something is being said, regular where it informs.
   - Colour: graphite, three greys of ink, one hairline, and the logo's blue
     for links. The screenshots supply the colour.
   - Space: a 4px grid, in a few named steps, and one rhythm between
     sections.
   - Shape: round controls (999px), soft surfaces (24px), and nothing else.
   - Motion: four durations and two curves. Headlines rise out of their own
     line; the phones arrive once; everything else is simply there. */
:root {
  --bg: #ffffff;
  --ink: #111111;
  --muted: #6e6e73;
  --faint: #6e6e73;
  --dim: #8e8e93;
  --rule: #e6e6e6;
  --blue: #1d63e0;
  --side: 24px;
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* At display sizes Apple's system font switches to its Display cut by itself. */
  --display: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --size-mark: clamp(88px, 17vw, 264px);
  --size-display: clamp(40px, 6.4vw, 96px);
  --size-title: clamp(26px, 2.6vw, 38px);
  --size-lead: 17px;
  --size-text: 15px;
  --size-small: 13px;
  --track-mark: -.058em;
  --track-display: -.044em;
  --track-title: -.022em;
  --track-text: -.006em;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;
  --section: clamp(112px, 18vh, 200px);

  --radius-round: 999px;
  --radius-surface: 24px;

  --dur-press: 90ms;
  --dur-state: 240ms;
  --dur-reveal: 700ms;
  --dur-scene: 1200ms;
  /* Arrivals: quick to start, long to settle. State changes: even. */
  --ease: cubic-bezier(.16, 1, .3, 1);
  --ease-state: cubic-bezier(.4, 0, .2, 1);
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0b0b0b;
    --ink: #ededed;
    --muted: #8e8e93;
    --faint: #8e8e93;
    --dim: #6e6e73;
    --rule: #262626;
    --blue: #6ea2ff;
  }
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
html.graphite-site { background: #161819; color-scheme: dark; }
body { background: var(--bg); color: var(--ink); font-family: var(--font); font-size: 16px; line-height: 1.5;
  -webkit-font-smoothing: antialiased; min-height: 100vh; min-height: 100svh; display: flex; flex-direction: column; }
/* Keep the footer at the bottom of short pages. */
body > main { flex: 1; }
a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
img { max-width: 100%; display: block; }
:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
h1, h2 { font-weight: 600; }
/* Korean wraps between words, not inside them. */
:lang(ko) { word-break: keep-all; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

.wrap { width: min(1000px, 100% - 2 * var(--side)); margin-left: auto; margin-right: auto; }
.appstore { display: inline-block; border-radius: 10px; }
.appstore img { height: 44px; width: auto; }
.appstore:hover { opacity: .86; }

/* Pressed controls give a little under the finger, then spring back. */
:is(.appstore, .head-get, .vignette-replay, .film-button, .lang summary, .shot-viewer button) {
  transition: scale var(--dur-reveal) var(--ease), color var(--dur-state) var(--ease-state),
    background-color var(--dur-state) var(--ease-state), border-color var(--dur-state) var(--ease-state),
    opacity var(--dur-state) var(--ease-state); }
:is(.appstore, .head-get, .vignette-replay, .film-button, .lang summary, .shot-viewer button):active {
  scale: .97; transition-duration: var(--dur-press); }

/* Header, on every page: one small pill floating at the top, like the
   island at the top of an iPhone. The way home, the other pages, and the
   download. It's the one translucent thing on the site, because it's the
   one thing content scrolls under; it firms up once that happens
   (presentation.js adds .scrolled). */
.site-head { position: sticky; top: 0; z-index: 30; padding: var(--space-3) var(--side) 0; pointer-events: none; }
.head-row { display: flex; align-items: center; gap: 2px; width: fit-content; max-width: 100%; margin-inline: auto;
  padding: var(--space-1); border: 1px solid var(--rule); border-radius: var(--radius-round); pointer-events: auto;
  background: var(--bg); background: color-mix(in srgb, var(--bg) 70%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(18px); backdrop-filter: saturate(1.4) blur(18px);
  box-shadow: 0 10px 30px -18px rgb(0 0 0 / .6);
  transition: background-color var(--dur-reveal) var(--ease-state), box-shadow var(--dur-reveal) var(--ease-state); }
.site-head.scrolled .head-row { background: color-mix(in srgb, var(--bg) 88%, transparent);
  box-shadow: 0 14px 36px -14px rgb(0 0 0 / .75); }
.brand { display: inline-flex; align-items: center; gap: var(--space-2); padding: 2px var(--space-3) 2px 2px;
  border-radius: var(--radius-round); font-size: 14px; font-weight: 600; color: var(--ink); letter-spacing: -.01em; }
.brand:hover { text-decoration: none; }
.brand img { width: 28px; height: 28px; border-radius: 8px; }
.head-links { display: flex; align-items: center; padding-inline-start: 6px; border-inline-start: 1px solid var(--rule); font-size: var(--size-small); }
.head-links a { padding: 6px var(--space-3); border-radius: var(--radius-round); color: var(--muted); white-space: nowrap;
  transition: color var(--dur-state) var(--ease-state), background-color var(--dur-state) var(--ease-state); }
.head-links a:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 8%, transparent); text-decoration: none; }
.head-get { display: inline-flex; align-items: center; min-height: 30px; margin-inline-start: var(--space-1); padding: 5px 14px;
  border-radius: var(--radius-round); background: var(--ink); color: var(--bg); font-size: var(--size-small); font-weight: 600; white-space: nowrap; }
.head-get:hover { text-decoration: none; opacity: .88; }
/* Beside the pill, the language menu as a round button of the same glass,
   opening downwards. On phones, just the globe. */
.head-bar { display: flex; justify-content: center; align-items: stretch; gap: var(--space-2); max-width: 100%; }
.head-bar .head-row { margin-inline: 0; min-width: 0; }
.site-head .lang { display: flex; pointer-events: auto; }
.site-head .lang summary { min-height: 0; padding: 0 14px 0 12px; border: 1px solid var(--rule); color: var(--muted);
  font-size: var(--size-small); background: var(--bg); background: color-mix(in srgb, var(--bg) 70%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(18px); backdrop-filter: saturate(1.4) blur(18px);
  box-shadow: 0 10px 30px -18px rgb(0 0 0 / .6); }
.site-head.scrolled .lang summary { background: color-mix(in srgb, var(--bg) 88%, transparent); }
.site-head .lang summary:hover, .site-head .lang[open] summary { color: var(--ink); }
.site-head .lang summary .chevron { transform: rotate(180deg); }
.site-head .lang[open] summary .chevron { transform: none; }
.site-head .lang-menu { top: calc(100% + 10px); bottom: auto; transform-origin: top right; }
[dir="rtl"] .site-head .lang-menu { transform-origin: top left; }
.site-head .lang[open] .lang-menu { animation-name: menu-down; }
@keyframes menu-down { from { opacity: 0; transform: translateY(-8px) scale(.96); } }
@media (max-width: 760px) {
  .head-links { display: none; }
  .head-get { min-height: 32px; }
  .site-head .lang summary { padding: 0; aspect-ratio: 1; justify-content: center; }
  .site-head .lang summary :is(span, .chevron) { display: none; }
  .site-head .lang summary svg { width: 15px; height: 15px; }
  /* The same sheet along the bottom as the footer's menu. */
  .site-head .lang-menu { inset: auto 12px 12px; transform-origin: bottom; }
  .site-head .lang[open] .lang-menu { animation-name: menu-in; }
}

/* ---------------------------------------------------------------- Home */

.home-scene .wrap { width: min(1400px, 100% - 2 * var(--side)); }
/* One light, high and to the left, falling across the graphite. Static. */
.home-scene.lock-scene { background:
  radial-gradient(1100px 700px at 10% -6%, rgb(255 255 255 / .055), transparent 64%),
  linear-gradient(155deg, #232526 -35%, #18191a 38%, #111213 100%); }

.display { font-family: var(--display); font-size: var(--size-display); font-weight: 700; line-height: 1;
  letter-spacing: var(--track-display); text-wrap: balance; }
.display .dim { color: var(--dim); }
/* A headline line rises out of its own mask. The padding keeps accents and
   descenders inside it. */
.mask { display: block; overflow: hidden; overflow: clip; padding-block: .1em .14em; margin-block: -.1em -.14em; }
.mask > .rise { display: block; }

/* Hero. The name on one side; what it is on the other, its last line on the
   name's baseline. Under both, behind a hairline, the badge and two plain
   sentences on what it costs and needs. */
.hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 420px); align-items: end;
  column-gap: clamp(var(--space-6), 6vw, 112px); padding-top: clamp(var(--space-7), 8vh, 104px); }
.hero-icon { width: 72px; height: 72px; border-radius: 16px;
  box-shadow: 0 0 0 1px rgb(255 255 255 / .08), 0 20px 40px -14px rgb(0 0 0 / .6); }
.wordmark { margin-top: var(--space-5); margin-inline-start: -.045em; font-family: var(--display); font-size: var(--size-mark);
  font-weight: 700; line-height: .86; letter-spacing: var(--track-mark); color: var(--ink); }
.wordmark .rise { display: inline-block; padding-inline-end: .06em; }
/* "Privaro" briefly reads "Private" (the script at the end of index.html).
   The letters underneath stay "ro", so screen readers and copying always
   get the name; the "te" is only drawn over them. */
.wordmark .rise { direction: ltr; }
.wordmark .tail { position: relative; }
/* Normal line height, so its baseline sits where the letters' does (the
   name's own line height is too tight for an overlay to inherit). */
.wordmark .tail::after { content: "te"; position: absolute; top: 0; left: 0; line-height: normal; visibility: hidden; color: var(--ink); }
.wordmark .tail.flip { color: transparent; }
.wordmark .tail.flip::after { visibility: visible; }
.hero-copy { padding-bottom: .2em; }
.tagline { font-family: var(--display); font-size: var(--size-title); font-weight: 600; line-height: 1.1;
  letter-spacing: var(--track-title); text-wrap: balance; }
.lead { margin-top: var(--space-4); font-size: var(--size-lead); line-height: 1.55; color: var(--muted); }

.buy { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--space-6); }
.hero .buy { margin-top: var(--space-8); padding-top: var(--space-6); border-top: 1px solid var(--rule); }
.buy .appstore img { height: 48px; }
.buy-note { font-size: var(--size-text); line-height: 1.5; letter-spacing: var(--track-text); color: var(--muted); }
.buy-note > span { display: block; }
.buy-note > span:first-child { color: var(--ink); }

/* The gallery: the four screens side by side, upright and aligned, each
   labelled with what it's for. A phone leans a little toward the pointer
   (presentation.js) and the others step back. */
.gallery { margin-top: var(--space-9); }
.shots { display: flex; justify-content: center; gap: clamp(20px, 2.6vw, 44px); }
.shots figure { flex: 0 1 312px; min-width: 0; max-width: calc(72vh * .4832); margin: 0; perspective: 1600px; }
/* Each screenshot is a JPEG of the phone in its frame, cut to the phone's
   outline (body and side buttons) by a mask drawn from the same
   measurements. A transparent AVIF came out blank in Chrome. */
.shots img { width: 100%; height: auto;
  -webkit-mask-image: url(/shots/framed-18-pro-max/phone-mask.svg); mask-image: url(/shots/framed-18-pro-max/phone-mask.svg);
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; }
.shots figcaption { margin-top: var(--space-5); padding-inline: var(--space-1); font-size: var(--size-text); line-height: 1.45;
  letter-spacing: var(--track-text); }
.shots figcaption strong { display: block; font-weight: 600; color: var(--ink); }
.shots figcaption > span { display: block; margin-top: 2px; color: var(--muted); }

.shot-open { position: relative; display: block; width: 100%; padding: 0; border: 0; background: none; color: inherit;
  cursor: zoom-in; border-radius: 12%; -webkit-tap-highlight-color: transparent;
  transform: rotateY(var(--ry, 0deg)) rotateX(var(--rx, 0deg));
  transition: transform var(--dur-scene) var(--ease), opacity var(--dur-reveal) var(--ease-state),
    filter var(--dur-reveal) var(--ease-state), scale var(--dur-reveal) var(--ease); }
.shot-open.squared { transition: none; }
.shot-open.tilting { transition: transform 200ms ease-out, opacity var(--dur-reveal) var(--ease-state),
  filter var(--dur-reveal) var(--ease-state), scale var(--dur-reveal) var(--ease); }
.shot-open:focus-visible { outline-offset: 8px; }
/* The shadow it casts, and the light on its glass, from the same high left. */
.shot-open::before { content: ""; position: absolute; z-index: -1; inset: auto 6% -3.5%; height: 7%;
  background: radial-gradient(closest-side, rgb(0 0 0 / .7), transparent); pointer-events: none; }
.shot-open::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  -webkit-mask: url(/shots/framed-18-pro-max/phone-mask.svg) center / 100% 100% no-repeat;
  mask: url(/shots/framed-18-pro-max/phone-mask.svg) center / 100% 100% no-repeat;
  background: radial-gradient(70% 45% at var(--mx, 20%) var(--my, -10%), rgb(255 255 255 / .14), transparent 70%),
    linear-gradient(118deg, rgb(255 255 255 / .06), transparent 32%);
  opacity: .5; transition: opacity var(--dur-reveal) var(--ease-state); }
.shot-open:is(:hover, :focus-visible)::after { opacity: 1; }
@media (hover: hover) and (min-width: 1181px) {
  .shots:has(.shot-open:hover) .shot-open:not(:hover) { opacity: .55; scale: .98; }
}
.reveal-pending { opacity: .65; transform: translateY(10px); }

/* Film: the app in motion, in one card like the security illustration's,
   sized so all of it fits on screen at once. Wide on larger screens, upright
   on phones (two sources, one <video>). Sound and Play sit over its bottom
   corner, on their own: frosted, so they read on dark and bright frames. */
.film { padding-top: var(--section); }
.film-card { position: relative; width: min(100%, calc((100vh - 200px) * 16 / 9)); width: min(100%, calc((100svh - 200px) * 16 / 9));
  margin: 0 auto; border: 1px solid var(--rule); border-radius: var(--radius-surface); overflow: hidden;
  background: rgb(255 255 255 / .025); }
.film-video { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; background: #09090b; }
.film-card[data-ready] .film-video { cursor: pointer; }
.film-controls { position: absolute; inset-inline-end: var(--space-4); bottom: var(--space-4); display: flex; gap: var(--space-2); }
.film-controls .film-button { min-height: 40px; padding: 8px 14px 8px 12px; border-radius: 999px; color: #f5f5f7;
  font-size: var(--size-small); font-weight: 500; background: rgb(18 18 20 / .5); box-shadow: inset 0 0 0 1px rgb(255 255 255 / .14);
  -webkit-backdrop-filter: blur(14px) saturate(1.4); backdrop-filter: blur(14px) saturate(1.4); }
.film-controls .film-button:hover { background: rgb(28 28 31 / .62); }
/* One icon per state: play, pause or play again; sound on or off. */
.film-play :is(.film-icon-pause, .film-icon-again),
.film-card[data-state="pause"] .film-play :is(.film-icon-play, .film-icon-again),
.film-card[data-state="again"] .film-play :is(.film-icon-play, .film-icon-pause),
.film-sound[aria-pressed="false"] .film-waves, .film-sound[aria-pressed="true"] .film-muted { display: none; }
.film-card[data-state="pause"] .film-play .film-icon-pause,
.film-card[data-state="again"] .film-play .film-icon-again { display: inline; }
@media (max-width: 760px) {
  .film-card { width: min(100%, calc((100vh - 200px) * 9 / 16)); width: min(100%, calc((100svh - 200px) * 9 / 16)); }
  .film-video { aspect-ratio: 9 / 16; }
  .film-controls { inset-inline-end: var(--space-3); bottom: var(--space-3); }
  .film-controls .film-button { min-height: 44px; }
}

/* Security: one statement across the page; under it one card, the
   illustration's phone rising out of its bottom edge and, beside the phone,
   the facts: each a title, then how. */
.safety { padding-top: var(--section); }
.safety .display { max-width: 12.5em; }
.safety-body { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); margin-top: var(--space-8);
  border: 1px solid var(--rule); border-radius: var(--radius-surface); overflow: hidden; background: rgb(255 255 255 / .025); }
.safety-art { position: relative; min-height: 440px; }
.ledger { align-self: center; max-width: 36em; padding-block: var(--space-7); padding-inline: var(--space-2) var(--space-7); }
.ledger > div { padding-block: var(--space-4); border-top: 1px solid var(--rule); }
.ledger > div:first-child { padding-top: 0; border-top: 0; }
.ledger > div:last-child { padding-bottom: 0; }
.ledger dt { font-size: var(--size-lead); font-weight: 600; line-height: 1.35; letter-spacing: -.012em; }
.ledger dd { margin-top: var(--space-1); font-size: var(--size-text); line-height: 1.5; letter-spacing: var(--track-text); color: var(--muted); }
.more { display: inline-block; margin-top: var(--space-6); font-size: var(--size-text); color: var(--ink);
  text-decoration: underline; text-decoration-color: var(--dim); text-decoration-thickness: 1px; text-underline-offset: 4px;
  transition: text-decoration-color var(--dur-state) var(--ease-state); }
.more:hover { text-decoration-color: var(--ink); }
/* Here the illustration fills its half of the card, with a larger phone and
   no card or caption of its own: the headline above already says what the
   caption says. The replay button sits in the corner. */
.safety .privacy-vignette { position: absolute; inset: 0; max-width: none; margin: 0; border: 0; border-radius: 0; background: none; }
.safety .privacy-art { --pw: 52cqw; position: absolute; inset: 0; aspect-ratio: auto; }
.safety .vg-phone { top: 64px; }
.safety .privacy-vignette figcaption { position: absolute; top: var(--space-2); inset-inline-start: var(--space-3);
  min-height: 0; padding: 0; border: 0; }
.safety .privacy-vignette figcaption > span { display: none; }
.safety .privacy-vignette figcaption:not(:has(.vignette-replay:not([hidden]))) { display: none; }

/* Closing: the last word on the left; on the right the Lock Screen, rising
   out of the hairline the page ends on, as the phone in the illustration
   rises out of its card. */
.closing { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; column-gap: var(--space-7);
  padding-top: var(--section); border-bottom: 1px solid var(--rule); }
.closing-copy { padding-bottom: var(--space-9); }
.closing .display { max-width: 9em; }
.closing .buy { margin-top: var(--space-7); }
.closing-shot { width: clamp(220px, 23vw, 330px); aspect-ratio: 760 / 960; overflow: hidden; }
.closing-shot img { width: 100%; height: auto;
  -webkit-mask: url(/shots/framed-18-pro-max/phone-mask.svg) center / 100% 100% no-repeat;
  mask: url(/shots/framed-18-pro-max/phone-mask.svg) center / 100% 100% no-repeat; }

/* Arrivals. Only with the "motion" class from <head> (so never with Reduce
   Motion or without JavaScript), each .rise waits, paused on its first
   frame, until the script at the end of the page sees it on screen. Three
   kinds, and only these: a headline rising out of its line, the phones
   arriving, and the hero's words fading in after the name. */
@keyframes fade { from { opacity: 0; } }
@keyframes mask-rise { from { transform: translateY(108%); } }
@keyframes phone-in { from { opacity: 0; transform: perspective(1400px) translateY(96px) rotateX(16deg) scale(.94); } }
@keyframes phone-up { from { transform: translateY(24%); } }
@media (prefers-reduced-motion: no-preference) {
  .motion .rise { animation: var(--anim, fade) var(--dur-scene) var(--ease) var(--d, 0s) both paused; }
  .motion .rise.in-view { animation-play-state: running; }
  .motion .shots .rise { --d: calc(.25s + var(--i) * .1s); animation-duration: 1400ms; }
  /* Arriving through a page crossfade, the top of the page is simply there. */
  .soft-arrival :is(.hero, .gallery) .rise { animation: none; }
}

/* ---------------------------------------------------------------- Viewer */

/* Native dialog supplies modal focus containment and makes the page inert.
   The image flies using transforms; the backdrop and controls only dissolve. */
.shot-viewer { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none;
  margin: 0; padding: 0; border: 0; background: transparent; color: #f2f2f3;
  color-scheme: dark; overflow: hidden; font-family: var(--font); }
.shot-viewer::backdrop { background: transparent; }
/* The page stays behind it, out of focus, rather than switched off. */
.viewer-surface { position: absolute; inset: 0; background: rgb(17 18 19 / .97); }
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .viewer-surface { background: rgb(15 16 17 / .84); -webkit-backdrop-filter: blur(30px) saturate(1.2); backdrop-filter: blur(30px) saturate(1.2); }
}
.viewer-toolbar { position: absolute; inset: max(20px, env(safe-area-inset-top)) var(--space-5) auto;
  display: flex; align-items: center; justify-content: space-between; gap: 20px; z-index: 2; }
.viewer-toolbar h2 { font-size: 17px; font-weight: 600; line-height: 1.4; letter-spacing: -.01em; }
.shot-viewer button { display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 44px; height: 44px; padding: 10px; border: 1px solid rgb(255 255 255 / .16);
  border-radius: 50%; background: rgb(255 255 255 / .05); color: #f2f2f3; cursor: pointer; }
.shot-viewer button:hover { background: rgb(255 255 255 / .12); border-color: rgb(255 255 255 / .3); }
.shot-viewer button svg { width: 22px; height: 22px; }
.viewer-stage { position: absolute; inset: 80px var(--space-5) 88px; display: flex; align-items: center; justify-content: center; }
.viewer-image { display: block; flex: none; max-width: none; transform-origin: top left; object-fit: contain;
  -webkit-mask: url(/shots/framed-18-pro-max/phone-mask.svg) center / 100% 100% no-repeat;
  mask: url(/shots/framed-18-pro-max/phone-mask.svg) center / 100% 100% no-repeat;
  user-select: none; -webkit-user-select: none; touch-action: pan-y; }
.viewer-navigation { position: absolute; inset: auto var(--space-5) max(20px, env(safe-area-inset-bottom));
  display: flex; justify-content: center; align-items: center; gap: var(--space-5); }
.viewer-count { min-width: 48px; text-align: center; font-size: var(--size-small); color: #a5a6a8; font-variant-numeric: tabular-nums; direction: ltr; }
[dir="rtl"] :is(.viewer-next, .viewer-previous) svg { transform: scaleX(-1); }

/* ---------------------------------------------------------------- Vignette */

/* A phone rising out of the bottom of a card, a photo on its screen. The
   phone's width (--pw) is a share of the card's (cqw), and everything on the
   phone is a share of the phone's, so it scales as one picture at whatever
   size a page gives it. */
.privacy-vignette { max-width: 640px; margin: 40px 0 0; border: 1px solid var(--rule);
  border-radius: var(--radius-surface); overflow: hidden; background: rgb(255 255 255 / .025); }
.privacy-art { --pw: 32cqw; position: relative; aspect-ratio: 2 / 1; overflow: hidden; container-type: inline-size; direction: ltr; }
.vg-phone { position: absolute; left: 50%; top: 6cqw; width: var(--pw); aspect-ratio: 1 / 2.05; translate: -50% 0;
  container-type: inline-size; padding: calc(var(--pw) * .0266); border-radius: calc(var(--pw) * .175);
  background: linear-gradient(150deg, #5c6165, #27292b 28%, #1b1d1f 72%, #3b3f42);
  box-shadow: inset 0 0 0 calc(var(--pw) * .00375) rgb(255 255 255 / .16), inset 0 0 0 calc(var(--pw) * .0156) #0b0c0d,
    0 calc(var(--pw) * .125) calc(var(--pw) * .25) calc(var(--pw) * -.0625) rgb(0 0 0 / .75); }
.vg-screen { position: relative; height: 100%; overflow: hidden; border-radius: 15.8cqw; background: #0d1012; }
.vg-island { position: absolute; top: 4.95cqw; left: 50%; width: 27.7cqw; height: 8.25cqw; translate: -50% 0;
  border-radius: 30cqw; background: #000; }
/* The finished state: the photo written over, the ciphertext in its place. */
.vg-photo { position: absolute; inset: 0; display: block; width: 100%; height: 100%; max-width: none;
  object-fit: cover; object-position: 50% 0; clip-path: inset(100% 0 0 0); }
.vg-cipher { position: absolute; inset: 0; margin: 0; padding: 24.75cqw 7.9cqw 0; overflow: hidden; word-break: break-all;
  font: 500 4.95cqw/1.62 ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace; letter-spacing: .08em;
  color: rgb(205 216 228 / .4); user-select: none; -webkit-user-select: none; }
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .vg-cipher { color: transparent; background: linear-gradient(180deg, rgb(228 235 242 / .6), rgb(150 166 182 / .2) 75%);
    -webkit-background-clip: text; background-clip: text; }
}
/* The line that writes it: a hairline of light with a faint wake above. */
.vg-scan { position: absolute; top: 0; left: -2%; right: -2%; height: 1.06cqw; margin-top: -.53cqw; opacity: 0; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgb(255 255 255 / .85) 18%, #fff 50%, rgb(255 255 255 / .85) 82%, transparent);
  box-shadow: 0 0 5.3cqw 1cqw rgb(150 185 255 / .5); }
.vg-scan::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 29.7cqw;
  background: linear-gradient(to top, rgb(150 185 255 / .14), transparent); }
.privacy-vignette figcaption { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
  gap: 4px 16px; min-height: 76px; padding: 8px 20px 12px; border-top: 1px solid var(--rule);
  color: var(--muted); font-size: var(--size-small); }
.vignette-replay, .film-button { display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; padding: 8px 4px; border: 0; border-radius: 6px;
  background: none; color: var(--ink); font: inherit; cursor: pointer; }
:is(.vignette-replay, .film-button)[hidden] { display: none; }
.vignette-replay:disabled { opacity: .45; cursor: default; }
:is(.vignette-replay, .film-button) svg { width: 16px; height: 16px; }
@media (max-width: 760px) {
  .privacy-vignette figcaption { min-height: 96px; }
}
@media (prefers-reduced-motion: no-preference) {
  /* Waiting to play (privacy-vignette.js): the photo, untouched. */
  .privacy-vignette[data-state="ready"] .vg-photo { clip-path: inset(0 0 0 0); }
  .privacy-vignette[data-state="ready"] .vg-cipher { clip-path: inset(0 0 100% 0); }
}
@media (prefers-reduced-motion: reduce) {
  .reveal-pending { opacity: 1; transform: none; }
  .shot-open, .shot-open.tilting { transition: opacity .2s, filter .2s; }
  :is(.appstore, .head-get, .vignette-replay, .film-button, .lang summary, .shot-viewer button):active { scale: none; }
}

/* A matte graphite surface. A broad, static tonal shift gives the canvas
   depth while the app screenshots supply the colour. Keep this dark in both
   device themes, as the original homepage was. */
.lock-scene {
  --bg: #161819;
  --ink: #f5f5f7;
  --muted: #a1a1a6;
  --faint: #8e8f94;
  --dim: #7d7e83;
  --rule: rgb(255 255 255 / .11);
  --blue: #6ea2ff;
  color-scheme: dark;
  isolation: isolate;
  background: linear-gradient(155deg, #242627 -35%, #191b1c 35%, #111213 100%);
}

/* Pro, Privacy, Terms and 404 */
.page { padding: 56px 0 88px; }
.page h1 { font-family: var(--display); font-size: clamp(36px, 4.8vw, 60px); font-weight: 700; line-height: 1.04;
  letter-spacing: -.035em; max-width: 16em; overflow-wrap: break-word; text-wrap: balance; }
.page .updated { font-size: var(--size-small); color: var(--muted); margin-top: 12px; }
.page .intro { font-size: 19px; line-height: 1.5; color: var(--muted); max-width: 34em; margin-top: 18px; }
.note { max-width: 40em; margin-top: 16px; font-size: 15px; color: var(--muted); }
.note strong { color: var(--ink); font-weight: 600; }

.features { list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: 28px 56px; margin-top: 48px; }
.features h2 { font-size: 16px; }
.features p { font-size: 15px; color: var(--muted); margin-top: 2px; }
.page .appstore { margin-top: 48px; }

.faq { max-width: 40em; margin-top: 40px; }
.faq h2 { font-size: 17px; margin-top: 32px; }
.faq h2:first-child { margin-top: 0; }
.faq p { color: var(--muted); margin-top: 6px; }

.legal { max-width: 40em; margin-top: 48px; line-height: 1.6; counter-reset: legal-section; }
.legal h2 { font-size: 17px; margin: 36px 0 8px; counter-increment: legal-section; }
.legal h2:first-child { margin-top: 0; }
.legal h2::before { content: counter(legal-section) ". "; color: var(--muted); font-weight: 400; }
.legal p { margin-bottom: 12px; }
.legal ul { margin: 0 0 16px; padding-inline-start: 20px; }
.legal li { margin-bottom: 6px; }
.legal a { text-decoration: underline; text-underline-offset: 2px; }
.legal .authoritative { margin-top: 40px; padding-top: 16px; border-top: 1px solid var(--rule); font-size: var(--size-small); color: var(--muted); }

/* Security: a long read, so it opens with a list of its sections, and has tables. */
.toc { max-width: 40em; margin-top: 32px; padding: 16px 0; border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule); font-size: 15px; }
.toc ol { list-style: none; columns: 2; column-gap: 32px; }
.toc li { margin-bottom: 4px; break-inside: avoid; }
.doc { max-width: 40em; margin-top: 48px; line-height: 1.6; }
.doc h2 { font-size: 21px; line-height: 1.3; margin: 56px 0 12px; }
.doc h2:first-child { margin-top: 0; }
.doc h3 { font-size: 17px; font-weight: 600; margin: 28px 0 8px; }
/* Clear of the header, which stays at the top. */
.doc :is(h2, h3) { scroll-margin-top: 88px; }
.doc p { margin-bottom: 12px; }
.doc :is(ul, ol) { margin: 0 0 16px; padding-inline-start: 20px; }
.doc li { margin-bottom: 6px; }
.doc a { text-decoration: underline; text-underline-offset: 2px; }
.doc code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .9em; }
.doc table { width: 100%; border-collapse: collapse; margin: 4px 0 20px; font-size: 14px; line-height: 1.45; }
.doc :is(th, td) { text-align: start; vertical-align: top; padding: 10px 16px 10px 0; border-bottom: 1px solid var(--rule); }
.doc :is(th, td):last-child { padding-inline-end: 0; }
.doc th { font-size: var(--size-small); font-weight: 600; color: var(--muted); }
.doc td:first-child { font-weight: 600; }

/* Footer: the links and the language menu in one slim pill, centred, and a
   single quiet line beneath it. */
.site-foot { display: flex; flex-direction: column; align-items: center; gap: 14px;
  padding: var(--space-5) 0 28px; font-size: var(--size-small); color: var(--muted); }
.foot-links { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 2px; max-width: 100%;
  padding: var(--space-1); border: 1px solid var(--rule); border-radius: var(--radius-round);
  background: color-mix(in srgb, var(--ink) 3%, transparent); }
.foot-links a { padding: 6px 11px; border-radius: var(--radius-round); color: var(--muted); white-space: nowrap;
  transition: color var(--dur-state) var(--ease-state), background-color var(--dur-state) var(--ease-state); }
.foot-links a:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 8%, transparent); text-decoration: none; }
.foot-links > a:last-of-type { margin-inline-end: 6px; }
.foot-note { max-width: 46em; font-size: 12px; line-height: 1.5; color: var(--faint); text-align: center; text-wrap: balance; }

/* Language menu, in the footer, so it opens upwards. The button is a small
   pill whose chevron turns over while it's open; the menu is a frosted panel
   that rises into place, seventeen languages in two columns, the current one
   ticked. It opens slowly: the panel grows out of the button's corner over
   half a second, easing to a stop, and the languages fade in just behind it. */
.lang { position: relative; }
.lang summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
  min-height: 30px; padding: 4px 11px 4px 10px; border-radius: var(--radius-round);
  background: color-mix(in srgb, var(--ink) 7%, transparent); }
.lang summary::-webkit-details-marker { display: none; }
.lang summary:hover, .lang[open] summary { color: var(--ink); background: color-mix(in srgb, var(--ink) 12%, transparent); }
.lang summary svg { width: 13px; height: 13px; flex: none; }
.lang summary .chevron { width: 10px; height: 10px; transition: transform .45s cubic-bezier(.22, 1, .36, 1); }
.lang[open] summary .chevron { transform: rotate(180deg); }
.lang-menu { position: absolute; inset-inline-end: 0; bottom: calc(100% + 14px); z-index: 20; width: 360px; padding: 8px;
  background: var(--bg); background: color-mix(in srgb, var(--bg) 92%, transparent);
  -webkit-backdrop-filter: blur(24px) saturate(1.6); backdrop-filter: blur(24px) saturate(1.6);
  border: 1px solid var(--rule); border-radius: 16px; box-shadow: 0 24px 60px rgb(0 0 0 / .18), 0 2px 8px rgb(0 0 0 / .06);
  font-size: 14px; transform-origin: bottom right; }
[dir="rtl"] .lang-menu { transform-origin: bottom left; }
/* Chrome only hides a closed <details>' content (content-visibility) and skips
   styling it, so the animations ran on the first open alone. Taking it out of
   the page while closed resets them, so they play on every open. */
.lang:not([open])::details-content { display: none; }
.lang[open] .lang-menu { animation: menu-in .5s cubic-bezier(.22, 1, .36, 1); }
@keyframes menu-in { from { opacity: 0; transform: translateY(10px) scale(.96); } }
.lang[open] :is(.lang-head, .lang-list) { animation: menu-content-in .45s .08s cubic-bezier(.22, 1, .36, 1) both; }
@keyframes menu-content-in { from { opacity: 0; transform: translateY(4px); } }
.lang-head { padding: 4px 10px 8px; font-size: 12px; font-weight: 600; color: var(--muted); }
.lang-list { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; }
.lang-list a { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 10px;
  border-radius: 10px; color: var(--ink); transition: background-color .12s; }
.lang-list a:hover { background: var(--rule); background: color-mix(in srgb, var(--ink) 8%, transparent); text-decoration: none; }
.lang-list a.active { font-weight: 600; background: var(--rule); background: color-mix(in srgb, var(--blue) 14%, transparent); }
.lang-list a svg { width: 14px; height: 14px; flex: none; color: var(--blue); }
/* Phones: a sheet along the bottom of the screen, so it can't run off the
   side whichever line the button has wrapped onto, over the page dimmed
   behind it. A tap on the dimmed page closes it (see the footer's script). */
@media (max-width: 760px) {
  .lang-menu { position: fixed; inset: auto 12px 12px; width: auto; max-height: 75vh; overflow-y: auto; }
  .lang-menu, [dir="rtl"] .lang-menu { transform-origin: bottom; }
  .lang[open]::before { content: ""; position: fixed; inset: 0; z-index: 19; background: rgb(0 0 0 / .32);
    animation: dim-in .5s ease-out; }
}
@keyframes dim-in { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .lang[open] :is(.lang-menu, .lang-head, .lang-list), .lang[open]::before { animation: none; }
  .lang summary .chevron { transition: none; }
}

/* Scripts other than Latin and Cyrillic. Letter-spacing would pull Arabic and
   Urdu's joined letters apart and crowds Devanagari and CJK, and Arabic, Urdu
   and Hindi need taller lines so marks above and below don't collide. */
:is(:lang(ar), :lang(ur), :lang(hi)) :is(.tagline, .display, .page h1, .buy-note, .ledger dt, .ledger dd, .shots figcaption) { letter-spacing: 0; }
:is(:lang(zh), :lang(ja), :lang(ko)) :is(.tagline, .display, .page h1) { letter-spacing: -.01em; }
/* Chinese and Japanese may break between any two characters; display lines
   break between phrases, where the strings mark it with <wbr>, and inside
   one only when a phrase is wider than the screen. */
:is(:lang(zh), :lang(ja)) :is(.tagline, .display) { word-break: keep-all; overflow-wrap: anywhere; }
:is(:lang(ar), :lang(hi)) :is(.tagline, .display) { line-height: 1.3; }
:is(:lang(ar), :lang(hi)) .mask { padding-block: .2em .25em; margin-block: -.2em -.25em; }
:lang(ur) body { line-height: 1.8; }
:lang(ur) .page h1 { line-height: 1.6; }
:lang(ur) :is(.tagline, .display) { line-height: 1.45; }
:lang(ur) .mask { padding-block: .35em .45em; margin-block: -.35em -.45em; }

/* Tablets and narrower windows: the hero stacks, and the phones become a row
   that scrolls sideways from edge to edge, the next one peeking in. */
@media (max-width: 1180px) {
  .hero { grid-template-columns: minmax(0, 1fr); }
  .wordmark { font-size: clamp(84px, 21vw, 220px); }
  .hero-copy { margin-top: var(--space-6); max-width: 36em; }
  .hero .buy { margin-top: var(--space-7); }
  .gallery { margin-top: var(--space-8); }
  /* The room at the bottom is for the row's scrollbar: Safari takes its height
     out of the row rather than adding it, which cut off the captions. */
  .shots.wrap { width: auto; margin-inline: 0; justify-content: flex-start; gap: var(--space-4);
    padding: var(--space-2) var(--side) var(--space-5); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--side);
    scrollbar-width: thin; scrollbar-color: rgb(255 255 255 / .18) transparent; }
  .shots figure { flex: none; width: min(56vw, 300px); max-width: none; scroll-snap-align: center; }
  .shots figure:first-child { scroll-snap-align: start; }
  .safety-body { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); }
  .ledger { padding-block: var(--space-6); padding-inline: var(--space-2) var(--space-6); }
}
@media (max-width: 760px) {
  :root { --side: 20px; --size-lead: 16px; }
  .hero { padding-top: var(--space-6); }
  .hero-icon { width: 60px; height: 60px; border-radius: 14px; }
  .wordmark { margin-top: var(--space-4); font-size: min(29vw, 140px); }
  .tagline { font-size: clamp(26px, 7.4vw, 34px); }
  .hero .buy { flex-direction: column; align-items: flex-start; gap: var(--space-4); }
  .shots figure { width: min(64vw, 280px); }
  .display { font-size: clamp(36px, 10.4vw, 56px); }
  .safety-body { grid-template-columns: minmax(0, 1fr); }
  .safety-art { min-height: 0; aspect-ratio: 4 / 3; }
  .safety .privacy-art { --pw: 46cqw; }
  .safety .vg-phone { top: var(--space-6); }
  .ledger { padding: var(--space-5); border-top: 1px solid var(--rule); }
  .closing { grid-template-columns: minmax(0, 1fr); }
  .closing-copy { padding-bottom: var(--space-7); }
  .closing .buy { flex-direction: column; align-items: flex-start; gap: var(--space-4); }
  .closing-shot { width: min(62vw, 260px); justify-self: center; }
  .page { padding: 40px 0 64px; }
  .page .intro { font-size: 17px; }
  .features { grid-template-columns: minmax(0, 1fr); gap: 24px; margin-top: 36px; }
  .legal { margin-top: 36px; }
  .toc ol { columns: 1; }
  .doc { margin-top: 36px; }
  /* Three columns of sentences don't fit a phone: each row becomes a block,
     its cells labelled from the column heading. */
  .doc thead { display: none; }
  .doc :is(table, tbody, tr, td) { display: block; }
  .doc tbody { border-top: 1px solid var(--rule); }
  .doc tr { padding: 12px 0; border-bottom: 1px solid var(--rule); }
  .doc td { padding: 0; border: 0; }
  .doc td + td { margin-top: 4px; }
  .doc td[data-label]::before { content: attr(data-label) ": "; color: var(--muted); }
  /* Too many links for one pill on a phone: a tight cluster instead. */
  .foot-links { padding: 0; border: 0; background: none; row-gap: 4px; }
  .foot-links a { padding: 6px 9px; }
  .foot-links > a:last-of-type { margin-inline-end: 4px; }
}
