/* The static pages — landing, consent, and connected apps. Astro renders them
   from site/ and carries this stylesheet to the site root verbatim, no bundler
   involved, so they take the Dramless color roles from the generated
   `/colors.css` their HEAD links, and every colour below is one of those roles
   (web/spec/001-foundation.md). The roles carry both appearances themselves,
   so this file has no dark-mode block. */

/* The same three type roles the application uses. Noto Sans Armenian sits
   second in each text stack so per-glyph fallback typesets the ֏ dram sign in
   the family the design names for it, with no markup around the symbol. */
:root {
  /* The one shadow in the system: a hard 2px offset in the divider colour, no
     blur and no alpha. Dark drops it — the surface step is the depth there. */
  --lift: 0 2px 0 var(--dramless-divider);

  --font-sans: "Figtree", "Noto Sans Armenian", ui-sans-serif, system-ui, sans-serif;
  --font-display: "Gabarito", "Noto Sans Armenian", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  font: 16px/1.5 var(--font-sans);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: var(--dramless-canvas);
  color: var(--dramless-text-primary);
}

.card {
  width: min(32rem, 100%);
  padding: 2rem;
  border: 1px solid var(--dramless-divider);
  border-radius: 1rem;
  background: var(--dramless-surface);
}

/* The lockup: the mark, then the wordmark in lowercase display type — the app
   never shouts. The gap is the chevron's width, and the mark is drawn against
   the wordmark's cap height rather than sized independently. Both strokes are
   colour roles, so the mark brightens with the appearance like the rest of the
   page. */
.lockup { display: flex; align-items: center; gap: .625rem; margin: 0 0 1.25rem; }
.mark { height: 2.25rem; width: auto; }
.wordmark {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 2rem;
  line-height: 1;
  letter-spacing: -0.01em;
}
h1 {
  margin: 0 0 1rem;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(1.6rem, 5vw, 2.5rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
}
p, ul { color: var(--dramless-text-secondary); }

/* The eyebrow is a label, not an accent: apricot fails AA as small text on the
   light canvas, and it is reserved for the one filled action on the page —
   which is the primary button below. */
.eyebrow {
  margin: 0 0 .5rem;
  color: var(--dramless-text-secondary);
  font-family: var(--font-mono);
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.5rem; }

/* The email sign-in form on the authorization pages. A column rather than the
   wrapping row `.actions` draws, because the field takes the width and the
   buttons under it read as a sequence of steps. */
.auth-form { display: flex; flex-direction: column; gap: .75rem; margin-top: 1.5rem; max-width: 22rem; }
.auth-form input {
  appearance: none;
  border: 1px solid var(--dramless-divider);
  border-radius: .875rem;
  padding: .7rem 1rem;
  background: var(--dramless-surface);
  color: var(--dramless-text-primary);
  font: inherit;
}
.auth-form input::placeholder { color: var(--dramless-text-faint); }

button,
.button {
  appearance: none;
  display: inline-block;
  border: 1px solid var(--dramless-divider);
  border-radius: .875rem;
  padding: .7rem 1rem;
  font-family: var(--font-display);
  font-weight: 700;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
  text-decoration: none;
}

button.primary,
.button {
  border-color: var(--dramless-accent);
  background: var(--dramless-accent);
  color: var(--dramless-on-accent);
}
button.danger { border-color: var(--dramless-negative); color: var(--dramless-negative); }
button:disabled { cursor: wait; opacity: .55; }
.grant { border-top: 1px solid var(--dramless-divider); padding: 1rem 0; }
code { overflow-wrap: anywhere; }
.error { color: var(--dramless-negative); }

@media (prefers-color-scheme: dark) {
  :root {
    --lift: none;
  }
}

/* ---- The landing page ----------------------------------------------------
   The selling main page flows as a document rather than as one centered card,
   so it opts out of the centering grid the authorization pages keep. It is six
   full-width sections whose grounds alternate canvas and surface — the change
   of tone is the whole boundary, no hairline between them — each a big
   display heading and one line of copy beside real screenshots: the hero's
   phones and browser window, every other section's phone stack. Every colour
   stays a generated role. The apricot fill is the get button, in the header
   and under the hero's devices — one per screenful — while the closing
   section's actions are the stores' badges and the Nur web-version link. */

body[data-page="landing"],
body[data-page="privacy"] {
  display: block;
  padding: 0;
}

.wrap { width: min(64rem, 100% - 2.5rem); margin-inline: auto; }
.narrow { width: min(44rem, 100% - 2.5rem); margin-inline: auto; }
/* The base body's centering must not shrink the landing's content to its
   longest word, especially when translated copy is shown at larger text sizes. */
body[data-page="landing"] main { width: 100%; }

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  padding-block: 1.25rem;
}
.site-header .site-nav a { white-space: nowrap; }
.site-header .lockup { margin: 0; text-decoration: none; color: inherit; }
.site-nav { display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap; }
.site-nav a {
  color: var(--dramless-text-secondary);
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
}
.site-nav a:hover { color: var(--dramless-text-primary); }
.site-nav a.button:not(.ghost),
.site-nav a.button:not(.ghost):hover { color: var(--dramless-on-accent); }
.landing-header .lockup .mark { height: 1.75rem; }
/* Header and footer align by ink, not by box: the mark's ink centre, the
   locale name's and the footer links' x-height centres, and the caret all
   sit level with the wordmark's lowercase x-height centre. Box centring
   leaves the mark and the smaller text about a pixel or two high, so each
   is nudged down by what an ink-row scan of a 2x render measured. */
.landing-header .lockup .mark { translate: 0 .125rem; }
.landing-footer .lockup .mark { translate: 0 .125rem; }
.landing-footer .site-nav a { translate: 0 .0625rem; }
.landing-header .lockup .wordmark { font-size: 1.5rem; }
/* On a phone the header keeps the lockup and the one action; the text links
   are in the footer. */
@media (max-width: 40rem) {
  .landing-header .site-nav a:not(.button) { display: none; }
  .landing-header .site-header,
  .header-start { gap: .75rem; }
}

/* The language menu beside the lockup: a <details> whose summary reads like
   a nav link and whose content is a stripe of the locale routes, so it opens,
   closes and navigates with no script. The header is a full-width positioned
   block, so the stripe spans the viewport edge to edge just under it. The
   stripe is the landing's one inverted band — a navigation cut-out rather
   than a surface — in the contrast fill: the text-primary ground with links
   in the canvas role, which inverts correctly in both appearances. While it
   is open the hero is pushed down by its height, so it reads as cut into the
   page rather than laid over it. */
/* The landing body is display: block but still carries the base rule's
   `place-items: center`; engines that apply justify-items to block layout
   shrink and center a block child under it, so the width is explicit. The
   header stacks above the hero, whose lights bleed up under it. */
.landing-header { position: relative; z-index: 1; width: 100%; }
.header-start { display: flex; align-items: center; gap: 1.25rem; }
/* The summary's text box is set like the wordmark's (line-height 1, no
   padding or margin), so the lockup and the locale name share one centre. */
.lang-menu { display: flex; }
.lang-menu summary {
  display: flex;
  align-items: center;
  margin: 0;
  padding: 0;
  line-height: 1;
  gap: .4rem;
  translate: 0 .0625rem;
  list-style: none;
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--dramless-text-secondary);
  border-radius: .375rem;
}
.lang-menu summary::-webkit-details-marker { display: none; }
.lang-menu summary:hover { color: var(--dramless-text-primary); }
.lang-menu summary:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--dramless-info) 50%, transparent);
  outline-offset: 2px;
}
.lang-menu summary::after {
  content: "";
  width: .4rem;
  height: .4rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-.0875rem) rotate(45deg);
  transition: transform 220ms ease-out;
}
.lang-menu[open] summary::after { transform: translateY(.1625rem) rotate(-135deg); }
.lang-stripe {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 1;
  height: 4.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2rem;
  background: var(--dramless-text-primary);
}
.lang-stripe a {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.125rem;
  text-decoration: none;
  white-space: nowrap;
  color: color-mix(in srgb, var(--dramless-canvas) 72%, transparent);
}
.lang-stripe a:hover,
.lang-stripe a[aria-current="page"] { color: var(--dramless-canvas); }
.lang-stripe a:focus-visible {
  outline: 3px solid var(--dramless-canvas);
  outline-offset: 4px;
  border-radius: .25rem;
}
.lang-menu[open] .lang-stripe { animation: lang-stripe-in 220ms ease-out; }
@keyframes lang-stripe-in {
  from { opacity: 0; transform: translateY(-.5rem); }
  to { opacity: 1; transform: none; }
}
main > .stage:first-child { transition: padding-top 220ms ease-out; }
body:has(.lang-menu[open]) main > .stage:first-child {
  padding-top: calc(clamp(2.5rem, 6vw, 4.5rem) + 4.5rem);
}
@media (prefers-reduced-motion: reduce) {
  .lang-menu[open] .lang-stripe { animation: none; }
  main > .stage:first-child,
  .lang-menu summary::after { transition: none; }
}

/* The landing's buttons set their own type: the shared `.button` rule ends in
   `font: inherit`, which the display face would otherwise lose to. */
.button.large,
.button.small,
.button.ghost {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.2;
}
.button.large { padding: .8rem 1.5rem; font-size: 1.0625rem; }
.button.small { padding: .5rem 1rem; font-size: .9375rem; }
.button.small.ghost { padding: .5rem 1rem; font-size: .9375rem; }
.button.ghost {
  padding: .8rem 1.5rem;
  font-size: 1.0625rem;
  border-color: var(--dramless-divider);
  background: transparent;
  color: var(--dramless-text-primary);
}
.button.ghost:hover { background: color-mix(in srgb, var(--dramless-text-primary) 5%, transparent); }

.stage {
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  text-align: center;
}
.stage.surface { background: var(--dramless-surface); }
.stage h1,
.stage h2 {
  margin: 0 0 1.25rem;
  font-family: var(--font-display);
  font-weight: 900;
  line-height: 1.02;
  letter-spacing: -0.02em;
  overflow-wrap: break-word;
  text-wrap: balance;
}
.stage h1 { font-size: clamp(3rem, 9vw, 6rem); }
/* The hero's column is wider than the other sections' so each line of the
   heading — Armenian sets wide — stays one line at the full size. */
.hero .narrow { width: min(60rem, 100% - 2.5rem); }
/* The hero's ground is two blurred lights, like police lights: a tilted
   ellipse in accent sitting high on the left, around the title's first line,
   and one in brandAccent tilted the other way and sitting low on the right,
   around the copy, its halo running on behind the top of the devices,
   overlapping off-centre, each softened by a blur so every edge is soft and
   the two colours fuse only where they meet. There is no shape under them —
   the union of the two blurs is the whole ground. They are drawn by the
   block that holds the title and the copy, so they follow its size in every
   language, but they stack in the hero's own context, under everything the
   hero holds: the devices' shells paint over their lower halos, and the
   header stacks above the hero with the haze bleeding up under it. They take
   no pointer events. This is the landing's one identity moment and the
   static pages' one blur: identity only, never depth, a state or an action.
   Both lights are roles, so the dark appearance repaints them. The title and
   the copy are in the scrim role, the one dark value that reads over both
   lights in both appearances; the copy has no ground of its own. In dark the
   scrim is the canvas itself, so the text reads only where a light reaches:
   glyph edges past the lights' cores stay dim, a known limit of the look.
   The button and its fine print sit below the devices, on plain canvas. */
/* Nothing inside the page clips — the lights and an orbiting phone may reach
   past the viewport — so the document clips the landing page sideways
   instead, hiding what crosses the viewport edge with no horizontal scroll.
   The root's overflow passes to the viewport, where clip becomes hidden and
   still scrolls programmatically, so the body clips too: the root having its
   own value keeps the body's clip on the body. */
html:has(> body[data-page="landing"]),
body[data-page="landing"] { overflow-x: clip; }
.hero { padding-bottom: clamp(1.25rem, 3vw, 2.25rem); }
.hero .fine { margin-bottom: 0; }
.hero { isolation: isolate; }
.hero .narrow:first-child {
  --blur: clamp(3.5rem, 5vw, 5.625rem);
  position: relative;
}
.hero .narrow:first-child::before,
.hero .narrow:first-child::after {
  content: "";
  position: absolute;
  z-index: -1;
  border-radius: 50%;
  filter: blur(var(--blur));
  pointer-events: none;
}
.hero .narrow:first-child::before {
  top: -14%;
  left: -6%;
  width: 70%;
  height: 115%;
  background: var(--dramless-accent);
  transform: rotate(-18deg);
}
.hero .narrow:first-child::after {
  top: 12%;
  right: -6%;
  width: 70%;
  height: 130%;
  background: var(--dramless-brand-accent);
  transform: rotate(14deg);
}
.hero h1 {
  max-width: 100%;
  padding-top: .2em;
  margin-bottom: .35em;
  color: var(--dramless-scrim);
}
.hero .lede { margin-bottom: 0; color: var(--dramless-scrim); }
.hero-get { margin-top: 2rem; }
.stage h2 { font-size: clamp(2.25rem, 6vw, 4rem); }
/* Sevan — the money-in-the-black hue — carries the one phrase the privacy
   heading promises. */
.calm { color: var(--dramless-positive); }
/* Apricot carries one word of the currencies and closing headings: accent,
   the button's own apricot, as a landing-only identity word at display size,
   where it sits under the glyph bar on the light canvas by choice. */
h1 .warm, h2 .warm { color: var(--dramless-accent); }
/* Nur, the brand role, carries one phrase of the entry and reports headings:
   an identity word in display type, which clears the large-text bar on both
   canvases. */
h2 .nur { color: var(--dramless-brand-accent); }
.lede {
  width: 100%;
  min-width: 0;
  max-width: 38rem;
  margin: 0 auto 2rem;
  font-size: clamp(1.125rem, 2.2vw, 1.5rem);
  line-height: 1.45;
  color: var(--dramless-text-secondary);
  text-wrap: pretty;
  overflow-wrap: break-word;
}
/* Fine print and the legal paragraph are body text in the secondary role: the
   faint role is for semibold captions at 12pt and up, never running text. */
.fine { margin: 1rem 0 0; font-size: .9375rem; color: var(--dramless-text-secondary); }
.visual { margin-top: 2rem; }
.stores {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 1rem;
  margin-top: 1rem;
}
/* The store badges are the stores' own artwork, carried verbatim from src/badges/
   with their baked colours (the brand-artwork exception): Apple's SVG is a bare
   40-unit badge, Google's PNG carries its own transparent margin, so the two
   heights differ to make the visible badges the same size — level with the
   outlined Web version button beside them. */
.stores { --badge-h: 2.875rem; }
.badge { display: inline-flex; line-height: 0; border-radius: 6px; }
.badge img { height: var(--badge-h); width: auto; display: block; }
/* Google's PNG is 646×250 with the badge itself at rows 41–209 (67.2% of the
   height) and columns 41–605, so the image is scaled up by 1/.672 to put its
   visible badge at the shared height, and its transparent margin is pulled
   back by negative inline margins so the gaps between the three stay even. */
.badge-play img { height: calc(var(--badge-h) / .672); margin-inline: calc(var(--badge-h) / .672 * -0.164); }
/* The Web version link sits beside the two store badges as a third badge in
   the brand's own Nur, by the user's choice — the landing's one filled brand
   control, an identity colour here rather than an action or a state; its
   label is the canvas role, which clears the text bar on Nur in both
   appearances where onAccent would not. */
.stores .button.nur {
  box-sizing: border-box;
  height: var(--badge-h);
  display: inline-flex;
  align-items: center;
  padding: 0 1.5rem;
  border-color: var(--dramless-brand-accent);
  background: var(--dramless-brand-accent);
  color: var(--dramless-canvas);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.0625rem;
  line-height: 1.2;
  border-radius: 6px;
}
.stores .button.nur:hover { background: color-mix(in srgb, var(--dramless-brand-accent) 88%, var(--dramless-scrim)); }

/* Copy beside its screenshots. One column, copy over the stack and centered,
   until there is room for two; then the copy reads left-aligned beside it,
   and `flip` puts the stack first without changing the reading order — the
   sections alternate so the stacks zigzag down the page. */
.split { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2rem; align-items: center; }
/* Below the two-column threshold the closing section's store row follows the
   phones: the copy block dissolves into the grid so heading, copy, stack and
   stores order themselves, the stores last. */
@media (max-width: 51.99rem) {
  .split .copy { display: contents; }
  .split .stack { order: 2; }
  .split .stores { order: 3; margin-top: 0; }
}
@media (min-width: 52rem) {
  .split { grid-template-columns: 1fr 1fr; text-align: left; }
  .split .lede { margin-inline: 0; }
  .split .lede:last-child { margin-bottom: 0; }
  .split .stores { justify-content: flex-start; }
  .split.flip .copy { order: 2; }
}

/* Oversized soft cloud lobes make a close-up sky illustration. Every lobe
   fades to transparent inside its box; only the section crops the cloud mass. */
.cloud {
  /* The cloudMass role of design/colors.yaml: the catalog owns the colour in
     both appearances, shared with the app's Cloud hero. */
  --cloud-mass: var(--dramless-cloud-mass);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  overflow-wrap: anywhere;
  padding-block: clamp(3.5rem, 8vw, 7rem);
  background: var(--dramless-cloud-sky);
}
.cloud::before, .cloud::after {
  content: "";
  position: absolute;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(ellipse 23% 34% at 26% 54%, var(--cloud-mass) 56%, transparent 100%),
    radial-gradient(ellipse 27% 43% at 49% 45%, var(--cloud-mass) 62%, transparent 100%),
    radial-gradient(ellipse 23% 35% at 74% 58%, var(--cloud-mass) 58%, transparent 100%),
    radial-gradient(ellipse 34% 26% at 50% 72%, var(--cloud-mass) 62%, transparent 100%);
}
.cloud::before { width: 76rem; height: 36rem; top: -15rem; right: -25rem; transform: rotate(-12deg); }
.cloud::after { width: max(75rem, 130%); height: 32rem; bottom: -15rem; left: -15%; }
.cloud h2 .nur { color: var(--dramless-text-primary); }
.cloud .lede, .cloud .fine, .cloud-benefits p, .cloud-supporting p { color: var(--dramless-text-primary); }
.cloud-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 3rem; align-items: center; }
.cloud-layout > *, .cloud-benefits li > * { min-width: 0; }
.cloud h2, .cloud-label, .cloud-benefits, .cloud-supporting { overflow-wrap: anywhere; }
.cloud-label {
  margin: 0 0 1.5rem;
  color: var(--dramless-text-primary);
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
}
.cloud .lede { margin-bottom: 1.5rem; }
.cloud-benefits { display: grid; gap: 2rem; margin: 0; padding: 0; list-style: none; text-align: left; }
.cloud-benefits li { display: flex; flex-wrap: wrap; gap: 1rem; align-items: start; }
/* The text gets a full row when its readable measure and the icon no longer
   fit together, including when the reader enlarges the root font size. */
.cloud-benefits li > div { flex: 1 1 12rem; }
.cloud-benefit-icon {
  flex: 0 0 2.75rem;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: .875rem;
  background: var(--dramless-surface);
  color: var(--dramless-text-primary);
}
.cloud-benefit-icon svg { width: 1.5rem; height: 1.5rem; }
.cloud-benefits h3 { margin: 0 0 .25rem; font: 700 1.25rem/1.25 var(--font-display); color: var(--dramless-text-primary); }
.cloud-benefits p { margin: 0; font-size: 1rem; line-height: 1.5; text-wrap: pretty; }
.cloud-supporting {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  gap: 1.5rem;
  margin: 2.5rem 0 0;
  padding: 0;
  list-style: none;
  text-align: left;
}
.cloud-supporting li { min-width: 0; }
.cloud-supporting h3 { margin: 0 0 .375rem; font: 700 1rem/1.3 var(--font-display); color: var(--dramless-text-primary); }
.cloud-supporting p { margin: 0; font-size: .9375rem; line-height: 1.5; text-wrap: pretty; }
/* The narrow intro shares the benefits' reading edge and lets both headline
   phrases breathe; rem bounds preserve enlarged-text preferences. */
@media (max-width: 51.99rem) {
  .cloud-copy { text-align: left; }
  .cloud h2 { font-size: clamp(2rem, 1rem + 5vw, 3rem); line-height: 1.08; }
  .cloud .lede { margin-inline: 0; }
}
@media (min-width: 52rem) {
  .cloud-layout { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 4rem; text-align: left; }
  .cloud .lede { margin-inline: 0; }
}

/* A screenshot framed as a phone. `.device` is the shell and a size container,
   so everything inside is in container units and the frame scales with its
   column: a bezel in the scrim role — the one dark value that holds in both
   appearances — around the capture, the outer corner the device's own radius
   and the screen's corner that radius less the bezel, and over the capture's
   empty status-bar centre the iPhone's Dynamic Island or the Pixel's camera
   hole. The shell is the device's silhouette rather than a surface of the
   page, which is why it is drawn in the scrim and sits outside the three
   radii; it carries no shadow — the one shadow is for overlays. It caps at
   22rem and shrinks with its column, never past the page gutter. */
.device {
  container-type: inline-size;
  width: min(22rem, 100%);
  margin-inline: auto;
}
.phone {
  position: relative;
  display: block;
  padding: 3cqw;
  background: var(--dramless-scrim);
  border-radius: 14cqw;
  line-height: 0;
  /* The scrim is the dark canvas's value, so in the dark appearance the bezel
     would vanish into a canvas section and into a dark capture; a hairline
     of the text role at low alpha edges it on both sides — light text on the
     dark bezel reads, and in light the dark text on the dark bezel does not. */
  outline: 1px solid color-mix(in srgb, var(--dramless-text-primary) 22%, transparent);
}
.phone img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 11cqw;
  outline: 1px solid color-mix(in srgb, var(--dramless-text-primary) 22%, transparent);
  outline-offset: -1px;
}
.device.ios .phone::after {
  content: "";
  position: absolute;
  top: 5.7cqw;
  left: 50%;
  width: 31cqw;
  height: 9cqw;
  transform: translateX(-50%);
  border-radius: 999px;
  background: var(--dramless-scrim);
}
.device.android .phone::after {
  content: "";
  position: absolute;
  top: 4.6cqw;
  left: 50%;
  width: 5cqw;
  height: 5cqw;
  transform: translateX(-50%);
  border-radius: 999px;
  background: var(--dramless-scrim);
}

/* Two phones of one screen as a stack: the iPhone in front and the Android
   phone behind it, 25.6cqw to the side (mirrored in a flipped section, so
   the back phone peeks out at the page's edge), 1.5rem lower and at .92.
   Both share one grid cell three quarters of the stack wide, held to the
   side the back phone peeks away from; `.stack` is a size container, so the
   offsets are in its units and scale with the column, which caps at 24rem.
   Checking the transparent checkbox laid over the stack (a click anywhere
   on it) turns the pair half a revolution around a vertical axis:
   both phones stand on a circle of radius 37.5cqw, the front one at -20deg
   and the back one at 160deg, sideways position the sine of the angle and
   size the depth, the cosine. The phone going back shrinks only as it
   recedes and the one coming forward grows only as it approaches; their
   depths cross at the circle's far points, where they stand the diameter
   apart with a gap between them, and that is when the stacking order flips
   (550ms of 900), so it never changes while they overlap — when they do
   overlap the nearer one is the larger and already in front. The easings
   are the sine and cosine of the turn, the same both ways, so they are
   written once. At the far points a phone swings past the stack and may
   leave the viewport; nothing inside the page clips it, the document clips
   the viewport edge. Everything is a transition, so both directions run and
   nothing plays on load. */
@property --x { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --y { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --s { syntax: "<number>"; inherits: false; initial-value: 1; }
.stack {
  position: relative;
  width: min(24rem, 100%);
  margin-inline: auto;
  container-type: inline-size;
}
/* The checkbox is the stack's own box, transparent and over both phones, so
   it is the click target and focusing it never scrolls the page: it already
   sits where the reader clicked. */
.stack-toggle {
  appearance: none;
  position: absolute;
  inset: 0;
  z-index: 3;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.stack-phones {
  display: grid;
  cursor: pointer;
  border-radius: 1rem;
}
.stack-phones .device {
  --side: 25.6cqw;
  grid-area: 1 / 1;
  width: 75cqw;
  margin: 0;
  justify-self: start;
  translate: var(--x) var(--y);
  scale: var(--s);
  transition: --x 900ms linear(0, .449 10%, .904 20%, 1.319 30%, 1.654 40%, 1.876 50%, 1.964 60%, 1.908 70%, 1.714 80%, 1.402 90%, 1), --y 900ms linear(0, .146 25%, .5 50%, .854 75%, 1), --s 900ms linear(0, -.03 10%, -.013 20%, .06 30%, .17 40%, .31 50%, .49 60%, .65 70%, .80 80%, .92 90%, 1), z-index 0s 550ms;
}
.split.flip .stack-phones .device { --side: -25.6cqw; justify-self: end; }
.stack-phones .device.ios,
.stack-toggle:checked + .stack-phones .device.android {
  --x: 0px;
  --y: 0px;
  --s: 1;
  z-index: 2;
}
.stack-phones .device.android,
.stack-toggle:checked + .stack-phones .device.ios {
  --x: var(--side);
  --y: 1.5rem;
  --s: .92;
  z-index: 1;
}
.stack:has(.stack-toggle:focus-visible) {
  outline: 3px solid color-mix(in srgb, var(--dramless-info) 50%, transparent);
  outline-offset: .5rem;
  border-radius: 1rem;
}
@media (prefers-reduced-motion: reduce) {
  .stack-phones .device.ios,
  .stack-phones .device.android { transition: none; }
}

/* A screenshot of the web app framed as a browser window, drawn like the
   phone in the scrim bezel. The tab strip carries the window controls — three
   circles in the negative, warning and positive fills standing in for the
   traffic lights — one active tab with rounded top corners flaring into the
   strip's floor, holding the lockup, and a new-tab glyph; under it the
   toolbar, edge to edge and continuous with the tab as a browser's is, with
   back, a dimmed forward and reload and a centered address capsule with a
   lock reading the app's address in the mono face; then the capture, its top
   corners square under the toolbar and its bottom corners the window's radius
   less the bezel; the same low-alpha hairline on both edges, no shadow.
   The tab and toolbar are one quiet band — the surface at 10% over the scrim,
   lifted by 5% of textPrimary — and the capsule is the ink at 12% over it.
   The ink is the canvas and textPrimary roles mixed evenly: the scrim holds
   in both appearances while every other role flips, so neither role alone
   reads on it in both, and the even mix is the one mid value of both. The
   band stays dark in both so that ink clears 3:1 on band and capsule alike —
   nearer the surface it turns mid-toned in light, where no ink that also
   reads in dark clears it; the textPrimary share lifts it off the bezel in
   dark. The shell is a size container, so everything is in its units and
   scales with its column — 36px of strip and 34px of toolbar at a 512px
   window — while the glyph strokes never thin below a device pixel. */
.device.web { width: 100%; }
.window {
  --window-ink: color-mix(in srgb, var(--dramless-canvas), var(--dramless-text-primary));
  --window-band: color-mix(in srgb, var(--dramless-text-primary) 5%, color-mix(in srgb, var(--dramless-surface) 10%, var(--dramless-scrim)));
  --flare: 1.6cqw;
  display: block;
  padding: 0 1cqw 1cqw;
  background: var(--dramless-scrim);
  border-radius: 2.5cqw;
  outline: 1px solid color-mix(in srgb, var(--dramless-text-primary) 22%, transparent);
}
.window-strip {
  display: flex;
  align-items: flex-end;
  height: 7cqw;
  padding-inline: 2.2cqw;
}
.window-lights {
  display: flex;
  gap: 1.5cqw;
  align-self: center;
  margin-right: 4.4cqw;
}
.window-lights i {
  width: 2.2cqw;
  height: 2.2cqw;
  border-radius: 999px;
  background: var(--dramless-negative);
}
.window-lights i:nth-child(2) { background: var(--dramless-warning-fill); }
.window-lights i:nth-child(3) { background: var(--dramless-positive-fill); }
.window-tab {
  position: relative;
  display: flex;
  align-items: center;
  width: 34cqw;
  height: 5.6cqw;
  padding-inline: 2.4cqw;
  border-radius: var(--flare) var(--flare) 0 0;
  background: var(--window-band);
  color: var(--window-ink);
}
/* The flare: a square of the tab's colour at each base corner with a quarter
   circle of the strip cut out of it, so the tab's sides curve out into the
   floor the way a browser's active tab does. */
.window-tab::before,
.window-tab::after {
  content: "";
  position: absolute;
  bottom: 0;
  width: var(--flare);
  height: var(--flare);
  background: radial-gradient(circle at var(--cx) 0, transparent calc(var(--flare) - .5px), var(--window-band) var(--flare));
}
.window-tab::before { --cx: 0; right: 100%; }
.window-tab::after { --cx: 100%; left: 100%; }
.window-tab .lockup { gap: .7cqw; margin: 0; }
.window-tab .lockup .mark { height: 2.2cqw; }
.window-tab .lockup .wordmark { font-size: 2.15cqw; line-height: 1; }
.window-glyph {
  flex: none;
  width: 3.2cqw;
  height: 3.2cqw;
  fill: none;
  stroke: var(--window-ink);
  stroke-width: max(1px, .3cqw);
  stroke-linecap: round;
  stroke-linejoin: round;
}
.window-glyph path { vector-effect: non-scaling-stroke; }
.window-new { align-self: center; margin-left: 2.4cqw; translate: 0 .7cqw; }
.window-off { opacity: .45; }
.window-toolbar {
  display: flex;
  align-items: center;
  gap: 2cqw;
  height: 6.6cqw;
  margin-inline: -1cqw;
  padding-inline: 2.6cqw;
  background: var(--window-band);
}
.window-address {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .8cqw;
  flex: 1;
  height: 4.6cqw;
  margin-inline: 2cqw 17.6cqw;
  border-radius: 999px;
  background: color-mix(in srgb, var(--window-ink) 12%, var(--window-band));
  color: var(--window-ink);
  font-family: var(--font-mono);
  font-size: 2cqw;
  font-weight: 500;
  line-height: 1;
  letter-spacing: .02em;
}
.window-lock {
  width: 2cqw;
  height: 2cqw;
  fill: none;
  stroke: currentColor;
  stroke-width: max(1px, .25cqw);
  stroke-linejoin: round;
}
.window-lock path { vector-effect: non-scaling-stroke; }
.window-screen { display: block; line-height: 0; }
.window img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 0 0 1.5cqw 1.5cqw;
  outline: 1px solid color-mix(in srgb, var(--dramless-text-primary) 22%, transparent);
  outline-offset: -1px;
}

/* The hero's three devices showing Home. Wide, one row — the two phones at
   14rem and the window taking the rest: the stack's wrappers step aside
   (display: contents) so its
   phones are the row's first two cells, and its checkbox and swap are off.
   Narrower, the window is hidden — and, being lazy, never fetched — and the
   phones are the same stack as the other sections', one markup in two modes. */
.trio .device.web { display: none; }
@media (min-width: 64rem) {
  .trio {
    display: grid;
    grid-template-columns: 14rem 14rem minmax(0, 1fr);
    align-items: center;
    gap: 2rem;
  }
  .trio .stack,
  .trio .stack-phones { display: contents; }
  .trio .stack-toggle { display: none; }
  .trio .stack .stack-toggle ~ .stack-phones .device {
    width: 100%;
    z-index: auto;
    translate: none;
    scale: none;
    transition: none;
    cursor: auto;
  }
  .trio .stack-phones .device { grid-area: auto; }
  .trio .device.web { display: block; width: 100%; }
}

/* ---- The privacy policy --------------------------------------------------
   A document rather than a surface: it flows like the landing page (the block
   display above) and holds its prose to the same 44rem measure the landing's
   ledes take, so a line of policy text is as readable as a line of copy. */
.section { padding-block: 3rem; border-top: 1px solid var(--dramless-divider); }
h2 {
  margin: 0 0 1rem;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(1.5rem, 4vw, 2.25rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
}
.section-lede { max-width: 44rem; margin: 0 0 1.5rem; }
.policy { max-width: 44rem; }
.policy-head { padding-block: 2rem 1rem; }
.policy ul { padding-left: 1.25rem; display: flex; flex-direction: column; gap: .625rem; }
.policy li strong, .policy p strong { color: var(--dramless-text-primary); }
/* Links in prose take `info`, the role the design system reserves for them;
   left alone they would be the browser's own blue, which is the one colour on
   the page that comes from no role at all. */
.policy a { color: var(--dramless-info); }

.site-footer {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding-block: 2rem 2.5rem;
  border-top: 1px solid var(--dramless-divider);
}
.site-footer .lockup { margin: 0; }
.lockup.small .mark { height: 1.375rem; }
.lockup.small .wordmark { font-size: 1.25rem; }
.footer-note { margin: 0 0 0 auto; color: var(--dramless-text-faint); font-weight: 600; font-size: .875rem; }

/* The landing's neutral footer follows the bounded Cloud sky without a hairline. The legal fine print
   takes a line of its own held to the 44rem measure (by padding, since a
   max-width would let it rejoin the row). */
.landing-footer { border-top: 0; padding-block: 3rem; font-size: .875rem; }
.landing-footer .site-nav { row-gap: .5rem; }
.landing-footer .site-nav a { font-size: .875rem; }
.legal {
  flex-basis: 100%;
  padding-inline-end: max(0px, 100% - 44rem);
  margin: 0;
  font-size: .8125rem;
  color: var(--dramless-text-secondary);
}
