/*
 * Wireframe-fidelity styles. Every value is a token from tokens.css, so the real brand look
 * arrives by changing tokens and the [data-theme] overrides there, not markup.
 */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--color-background-primary);
  color: var(--color-content-primary);
  font: var(--type-body);
  letter-spacing: var(--tracking-body);
}

h1, h2, h3 { margin: 0 0 var(--space-3); letter-spacing: 0; }
/* The strong display styles (hero, display large) use the condensed Android settings, in capitals; the rest stay on regular axes. */
h1 { font: var(--type-hero-small); font-variation-settings: var(--font-variation-strong); text-transform: var(--text-transform-strong); }
h2 { font: var(--type-display-medium); }
h3 { font: var(--type-header-small); }
@media (min-width: 48rem) {
  h1 { font: var(--type-hero-large); font-variation-settings: var(--font-variation-strong); text-transform: var(--text-transform-strong); }
  h2 { font: var(--type-display-large); font-variation-settings: var(--font-variation-strong); text-transform: var(--text-transform-strong); }
}
p { margin: 0 0 var(--space-3); }
/* Content-primary, not the accent: orange and green fail contrast on the light background. */
a { color: var(--color-content-primary); text-decoration-color: var(--color-border-primary); text-underline-offset: 0.2em; } /* a quiet underline at rest, solid in the text color on hover */
a:hover { text-decoration-color: currentColor; }
:focus-visible { outline: 3px solid var(--color-content-primary); outline-offset: 3px; }

.container { width: 100%; max-width: var(--width); margin-inline: auto; padding-inline: var(--space-3); }
.container--narrow { max-width: var(--width-narrow); }

.skip-link { position: absolute; left: var(--space-3); top: -4rem; background: var(--color-brand-accent); color: var(--color-brand-on-accent); padding: var(--space-2) var(--space-3); z-index: 10; }
.skip-link:focus { top: var(--space-3); }

.site-header, .site-footer { border-color: var(--color-border-secondary); border-style: solid; border-width: 0; }
.site-header { border-bottom-width: var(--hairline); position: sticky; top: 0; z-index: 20; background: color-mix(in srgb, var(--color-background-primary) var(--header-fill), transparent); -webkit-backdrop-filter: blur(var(--header-blur)); backdrop-filter: blur(var(--header-blur)); transition: background-color 0.2s, border-color 0.2s, backdrop-filter 0.2s, -webkit-backdrop-filter 0.2s; }
/* Without backdrop-filter a see-through header would be unreadable over scrolling content, so it stays solid. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) { .site-header { background: var(--color-background-primary); } }
/* At the top of the page the header is transparent (the stroke stays) and sits over the hero; scrolling gives it a translucent fill and a blur. The script in site-header sets [data-top]; without it the header just stays filled. */
.site-header[data-top] { background: transparent; -webkit-backdrop-filter: blur(0); backdrop-filter: blur(0); }
.site-footer { border-top-width: var(--hairline); margin-top: var(--space-5); color: var(--color-content-secondary); font: var(--type-utility); letter-spacing: var(--tracking-utility); }
.site-header__inner, .site-footer__inner { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; justify-content: space-between; }
.site-header__inner, .site-footer__inner { padding-block: var(--header-padding); } /* the footer is never taller than the header: same padding, and its text and logo are no bigger */
.brand { font: var(--type-nav-title); color: var(--color-content-primary); text-decoration: none; margin: 0; display: flex; }
.brand__logo { display: block; height: 1.5rem; width: auto; } /* 648:160 viewBox; the paths fill with currentColor, so the logo follows the brand link's color */
.site-footer .brand { color: inherit; } /* the footer's logo is secondary content, like its links; it follows the footer's color */

.nav, .footer-links { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-4); list-style: none; margin: 0; padding: 0; }
.nav { font: var(--type-label); letter-spacing: var(--tracking-label); }
.nav a, .footer-links a { color: inherit; }
.site-header .nav a, .site-footer .footer-links a { text-decoration-color: transparent; } /* underlined but invisible, so on hover the line fades in instead of popping */
.nav a:hover, .footer-links a:hover { color: var(--color-content-primary); text-decoration-color: currentColor; } /* nav and footer links: the underline fades in, and secondary links step forward to primary */
.brand:hover { opacity: 0.7; }

.hero { --hero-padding: calc(var(--section-gap) * 1.4); padding-block: var(--hero-padding); } /* sized by its content: 7rem above and below (about 5rem stacked), on every page */
.hero:not(:has(.media-split)) { --hero-padding: calc(var(--section-gap) * 2.8); } /* text only: twice that (14rem, about 10rem stacked), so it takes space the way a hero with an image does */
.lede { font-size: 1.25rem; color: var(--color-content-secondary); max-width: 40rem; }
.section { padding-block: var(--section-gap); }
.section:not(.section--wide) + .section:not(.section--wide) { padding-top: 0; } /* stacked sections share one gap instead of adding their paddings (a wide section has none of its own to share) */
.section:has(+ .section--tight) { padding-bottom: var(--card-gap); } /* sibling cards sit closer than separate sections */

/* Three types of button, each with its own colors and its own hover. Only opacity and colors change, so the fades are smooth; hover: hover keeps a hover
   from sticking after a tap, and a press looks like a hover. */
.button {
  position: relative;
  isolation: isolate; /* the ::before fill sits under the label */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--button-height);
  border: 0;
  border-radius: var(--radius-pill);
  padding: 0 var(--space-4);
  font: var(--type-label-strong);
  letter-spacing: var(--tracking-label);
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.25s ease-out;
}
.button[disabled] { opacity: 0.6; cursor: progress; }

/* Gradient and fill: the fill is a layer under the label, so hover fades the fill to 75% and the label stays solid. Gradient is the product's gradient (its flat
   accent without one); fill is the flat accent. */
.button--fill { color: var(--color-brand-on-accent); }
.button--gradient { color: var(--color-brand-on-fill, var(--color-brand-on-accent)); }
.button--gradient::before, .button--fill::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none; transition: opacity 0.25s ease-out; }
.button--gradient::before { background: var(--color-brand-fill, var(--color-brand-accent)); }
.button--fill::before { background: var(--color-brand-accent); }
@media (hover: hover) { :is(.button--gradient, .button--fill):not([disabled]):hover::before { opacity: 0.75; } }
:is(.button--gradient, .button--fill):not([disabled]):active::before { opacity: 0.75; }

/* Outline: a hairline in the content color. Hover fills it with the primary surface; the border and the label stay. */
.button--outline { background-color: transparent; color: var(--color-content-primary); border: var(--hairline) solid var(--color-content-primary); padding: 0 calc(var(--space-4) - var(--hairline)); }
@media (hover: hover) { .button--outline:not([disabled]):hover { background-color: var(--color-surface-primary); } }
.button--outline:not([disabled]):active { background-color: var(--color-surface-primary); }
/* Fades only, nothing moves, so they run under reduced motion too (like the header's). */
a { transition: color 0.2s ease-out, text-decoration-color 0.2s ease-out; }
.brand { transition: opacity 0.2s ease-out; }

.card-grid ul { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); list-style: none; padding: 0; margin: 0; }
.card-grid li { background: var(--color-surface-primary); border: var(--hairline) dashed var(--color-border-secondary); border-radius: var(--radius-card); padding: var(--space-4); }

/* Signup: the same translucent card as <content-card>, padded a step less than a feature card since it holds a narrow form. Fields are as tall as the button,
   and the product's accent marks the checkbox and the focused field. */
.signup { background: var(--color-surface-primary); border: var(--hairline) solid var(--color-border-secondary); border-radius: var(--radius-card); -webkit-backdrop-filter: blur(var(--card-blur)); backdrop-filter: blur(var(--card-blur)); padding: var(--space-5); }
@media (max-width: 47.99rem) { .signup { padding: var(--card-padding); } }
.signup > p { margin-bottom: var(--card-stack); color: var(--color-content-secondary); }
.signup > h2, .signup > p { text-align: center; } /* a symmetric card: the heading and the button centered, the fields full width between them */
.signup [type="submit"] { display: flex; margin-inline: auto; }
.field { display: grid; gap: var(--space-2); margin-bottom: var(--space-4); }
.field label { font: var(--type-label-strong); letter-spacing: var(--tracking-label); }
.field input, .field select {
  width: 100%;
  min-height: var(--button-height);
  font: var(--type-body);
  letter-spacing: var(--tracking-body);
  color: var(--color-content-primary);
  background: var(--color-background-primary);
  border: var(--hairline) solid var(--color-border-primary);
  border-radius: var(--radius-tile);
  padding: var(--space-2) var(--space-3);
}
.field input::placeholder { color: var(--color-content-secondary); opacity: 1; }
.field input:focus-visible, .field select:focus-visible { outline: 2px solid var(--color-brand-accent); outline-offset: 2px; border-color: var(--color-brand-accent); }
/* Our own chevron, drawn in the text color with two gradients, inset like the text. Until a choice is made the select is :invalid and shows its placeholder
   in the secondary color, chevron included; the options in the open list stay primary. */
.field select { appearance: none; padding-right: calc(var(--space-3) * 2 + 0.75rem); background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%); background-position: calc(100% - var(--space-3) - 0.375rem) 50%, calc(100% - var(--space-3)) 50%; background-size: 0.375rem 0.375rem; background-repeat: no-repeat; }
.field select:invalid { color: var(--color-content-secondary); }
.field select option { color: var(--color-content-primary); }
.field--check { grid-template-columns: auto 1fr; align-items: start; gap: var(--space-2); margin-bottom: var(--card-stack); }
.field--check input { width: 1.25rem; height: 1.25rem; min-height: 0; margin-top: 0.2rem; accent-color: var(--color-brand-accent); }
.field--check label { font: var(--type-body); letter-spacing: var(--tracking-body); }
.form-status { margin: var(--space-3) 0 0; }
.form-status--error { color: var(--color-feedback-danger); }
.form-success { padding: var(--space-3); background: var(--color-brand-tint); border: var(--hairline) solid var(--color-brand-accent); border-radius: var(--radius-card); }

/* Honeypot: off-screen, not display:none, so naive bots still fill it in. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Legal copy runs the full container width: the 42rem reading measure above is for marketing pages. */
.section .prose p { max-width: none; }

/* Markdown tables arrive bare: always the full container width, and on narrow screens the table itself scrolls sideways instead of widening the page. */
.prose table { display: table; width: 100%; border-collapse: collapse; margin-block: var(--space-4); font: var(--type-label); }
@media (max-width: 48rem) { .prose table { display: block; overflow-x: auto; } }
.prose th, .prose td { min-width: 10rem; padding: var(--space-2) var(--space-3); border: var(--hairline) solid var(--color-border-primary); text-align: left; vertical-align: top; }
.prose th { background: var(--color-surface-secondary); font-weight: 500; }

/* Headings only carry a bottom margin, so in long copy give each section room above it. */
.prose h2 { margin-top: var(--space-5); }
.prose h3 { margin-top: var(--space-4); }
.prose h1 + p { margin-top: 0; }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }

/* Markdown copy: keep long text readable, and let the generated sections breathe. */
.section p, .hero p { max-width: 42rem; }
.hero p:not(:has(> .button)) { font-size: 1.25rem; color: var(--color-content-secondary); }
.card-grid a { font-weight: 500; }

/* Wireframe layout blocks. Components never set their own width: the container around them does. */

/* Landscape, full width, but never taller than 80vh: past that the ratio gives way. The explicit width stops the browser turning max-height into a max-width through the ratio. The 32rem floor keeps the text inside on short viewports. */
.hero--backdrop { width: 100%; background: var(--color-surface-tertiary); } /* no height of its own: the backdrop covers whatever the content and the padding make */
.hero--backdrop:has(+ .section--overlap) { padding-bottom: calc(var(--overlap) + var(--section-gap)); } /* the section pulled over the bottom still starts a section gap below the text */
/* Video backdrop. The media is its own stacking context so the gradient blends with the video only, then the whole block is masked: visible at the top, transparent at the bottom.
   Tune with --hero-gradient, --hero-blend, --hero-tint (gradient strength), --hero-saturate (how much of the footage's own color is kept, 0 to 1) and --hero-fade-start (where the fade begins). */
/* Slides up under the transparent sticky header; the extra min-height and padding keep the visible area and the text where they were. */
.hero--video { --hero-lift: var(--header-height); margin-top: calc(var(--hero-lift) * -1); padding-top: calc(var(--hero-padding) + var(--hero-lift)); position: relative; color: var(--color-content-primary); background: none; } /* follows the visitor's scheme: dark footage in dark mode, washed-out footage in light mode */
.hero--backdrop.hero--video { background-image: none; }
.hero--video > .container { position: relative; z-index: 1; }
.hero__media { position: absolute; inset: 0; isolation: isolate; overflow: hidden; background: var(--color-background-primary); -webkit-mask-image: linear-gradient(to bottom, #000 var(--hero-fade-start, 40%), transparent); mask-image: linear-gradient(to bottom, #000 var(--hero-fade-start, 40%), transparent); }
.hero__media video { display: block; width: 100%; height: 100%; object-fit: cover; filter: saturate(var(--hero-saturate, 0.35)) brightness(0.5); }
@media (prefers-color-scheme: light) { .hero__media video { filter: saturate(var(--hero-saturate, 0.35)); opacity: 0.3; } } /* light: the footage washed out over the white page, for dark text */
.hero__media::after { content: ""; position: absolute; inset: 0; background: var(--hero-gradient, var(--gradient-home)); mix-blend-mode: var(--hero-blend, color); opacity: var(--hero-tint, 0.55); }
.hero--neutral { --hero-saturate: 0; } /* fully black and white: neither the gradient nor the footage adds any color */
.hero--video p:not(:has(> .button)) { color: light-dark(rgb(0 0 0 / 0.75), rgb(255 255 255 / 0.8)); } /* the grey secondary text is too faint over footage */
.hero--center { text-align: center; }
.hero--center p { margin-inline: auto; }
.hero--backdrop > .container > :last-child { margin-bottom: 0; }

.hero:is(:not(.hero--backdrop), .hero--video) + .section:not(.section--overlap, .section--wide) { padding-top: 0; } /* the hero's own bottom gap is enough; a video fades out, so there is no edge to clear (a plain backdrop block keeps both) */
@media (min-width: 48rem) { .hero:is(:not(.hero--backdrop), .hero--video) + .section:has(.media-layers__device > img):not(.section--overlap, .section--wide) { padding-top: 4rem; } } /* a phone card right under the hero: the gap is measured to the phone, which rises 4rem above its card (stacked, the card's own top margin makes that room) */
.section--overlap { position: relative; margin-top: calc(var(--overlap) * -1); padding-top: 0; }
.section--tight { padding-top: 0; }
.section--center > .container > h2 { text-align: center; }
.section--center > .container > p { margin-inline: auto; }

/* Breaks out of the page container but stays capped; holds full-bleed <media-split> rows. */
.section--wide { padding-block: 0; }
.hero--backdrop + .section--wide { padding-top: var(--space-5); } /* keep the first row's media from merging into the backdrop */
.section--wide > .container { max-width: var(--width-wide); padding-inline: 0; }
.section--wide .media-split { aspect-ratio: 3 / 1; }
.section--wide .media-split__content { display: flex; flex-direction: column; justify-content: center; }

/* A full-width background band. Cards inside take the band's surface color. */
/* Surfaces and media are translucent, so they adapt to the band without overrides. */
.band--secondary { background: var(--color-background-secondary); }
main:has(> .band:last-child) + .site-footer, main:has(> .section:not(.section--wide):last-child) + .site-footer { margin-top: 0; } /* the band or the section already ends with its own gap */
main:has(> .section--wide:last-child) + .site-footer { margin-top: var(--section-gap); } /* a wide section has no bottom padding to add to the footer's */

.content-card { background: var(--color-surface-primary); border: var(--hairline) solid var(--color-border-secondary); border-radius: var(--radius-card); -webkit-backdrop-filter: blur(var(--card-blur)); backdrop-filter: blur(var(--card-blur)); }
/* A card holding only text (headings and paragraphs): it pads itself and hugs its text (the paragraph's measure) instead of filling the row, centered under a centered section. */
.content-card:not(:has(> :not(h2, h3, p, .content-card__texture))) { width: fit-content; margin-inline: auto; padding: var(--card-padding); }
.content-card:not(:has(> :not(h2, h3, p, .content-card__texture))) > :last-child { margin-bottom: 0; }
.section--center .content-card:not(:has(> :not(h2, h3, p, .content-card__texture))) { text-align: center; }
.section--center .content-card:not(:has(> :not(h2, h3, p, .content-card__texture))) > p { margin-inline: auto; }

/* Content takes --content-ratio of the row; the media takes the rest, at the content's height. */
.media-split { display: flex; flex-direction: row-reverse; align-items: stretch; } /* media on the left; content stays first in the DOM */
.media-split--flip { flex-direction: row; }
.media-split__content { flex: 0 0 calc(var(--content-ratio) * 100%); padding: var(--card-padding); }
.media-split__content > :last-child { margin-bottom: 0; }
/* Product card rhythm: a title with a small secondary line tucked under it, then clear air before the copy and again before the button. */
.content-card .media-split__content > h2:has(+ h3) { margin-bottom: var(--space-1); }
.content-card .media-split__content > h2:not(:has(+ h3)) { margin-bottom: var(--space-4); } /* a plain title gets room before its copy */
.section > .container > h2:has(+ :is(.content-card, .point-list)) { margin-bottom: var(--space-5); } /* a section heading gets room before its card or its list */
.content-card .media-split__content > h2 + h3 { margin-bottom: var(--card-stack); font: var(--type-label); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-content-secondary); }
.content-card .media-split__content > p:has(+ p > .button) { margin-bottom: var(--card-stack); }
.media-split__media { flex: 1; min-width: 0; background: var(--color-surface-tertiary); }
.media-split__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.media-split--align-end .media-split__media > img { object-position: 100% 30%; } /* the right edge always in frame; vertically, the upper third where faces usually sit */
/* The card does not clip (a tooltip may leave it), so the media rounds its own outer corners, inside the card's hairline: left side by default, right when flipped, top when stacked. */
.content-card .media-split__media { overflow: hidden; border-radius: calc(var(--radius-card) - var(--hairline)) 0 0 calc(var(--radius-card) - var(--hairline)); }
.content-card .media-split--flip .media-split__media { border-radius: 0 calc(var(--radius-card) - var(--hairline)) calc(var(--radius-card) - var(--hairline)) 0; }
/* Bare: no background of its own. The media is a small framed graphic, centered in its column, always readable on any backdrop. */
.media-split--bare .media-split__media { display: flex; align-items: center; justify-content: center; background: none; }
.media-split--bare .media-split__media:empty::before { content: ""; width: 100%; max-width: 16rem; aspect-ratio: 3 / 4; border: var(--hairline) solid var(--color-border-secondary); border-radius: var(--radius-card); background-color: var(--color-surface-primary); background-image: linear-gradient(to top right, transparent calc(50% - 1px), var(--color-border-primary) 50%, transparent calc(50% + 1px)), linear-gradient(to bottom right, transparent calc(50% - 1px), var(--color-border-primary) 50%, transparent calc(50% + 1px)); }
.media-split--bare .media-split__content { display: flex; flex-direction: column; justify-content: center; padding: 0 var(--space-4); } /* centered on a taller image; no padding above or below, so the hero's own gaps hold */
@media (max-width: 47.99rem) { .media-split--bare .media-split__content { padding-top: var(--card-padding); } } /* stacked: room between the image above and the text */
.media-split--bare .media-split__media > img { width: auto; max-width: 100%; height: auto; max-height: min(36rem, 70vh); object-fit: contain; } /* bare: the image keeps its own proportions, e.g. a phone mockup */
@media (max-width: 47.99rem) { .media-split--bare .media-split__media > img { max-height: 45vh; } } /* stacked above the text: leave the headline room above the fold */
@media (max-width: 47.99rem) {
  .media-split, .media-split--flip { flex-direction: column-reverse; }
  .section--wide .media-split { aspect-ratio: auto; }
  .media-split__content { flex: none; padding: var(--card-padding); }
  .media-split__media { flex: none; min-height: 12rem; }
  .content-card .media-split__media, .content-card .media-split--flip .media-split__media { border-radius: calc(var(--radius-card) - var(--hairline)) calc(var(--radius-card) - var(--hairline)) 0 0; }
}

/* Layered card: a card whose media is a <media-layers>, on its plain surface or a gradient. No overflow clip and no blur: the device layer may leave the card, and blur would
   turn the card into a clipping context. */
.content-card:has(.media-layers) { position: relative; isolation: isolate; -webkit-backdrop-filter: none; backdrop-filter: none; } /* positioned: the texture layer covers the whole card, not just the media */
.content-card:has(.media-layers__device > img) { margin-bottom: var(--space-4); } /* room for a phone, which hangs below the card; the icons hang less than a section gap */
.content-card:has(.media-layers) .media-split { min-height: 30rem; } /* the design's 480px as a floor so a short text doesn't leave a squat card: otherwise the text sets the height and the layers follow */
@media (min-width: 48rem) { .content-card:has(.app-icons) .media-split { min-height: 20rem; } } /* with app icons for now, not the app: a thinner card, the icons overflowing it */
.content-card:has(.media-layers) .media-split__content { display: flex; flex-direction: column; justify-content: center; } /* centered when the floor is taller than the text */
.content-card:has(.media-layers) .media-split__media { display: grid; overflow: visible; background: none; container-type: inline-size; } /* not positioned, so the texture reaches past it to the card; a grid so the layers fill it. Container: the device layer is also capped by the media's width */
.content-card:has(.media-layers) h2 { font: var(--type-display-large); font-variation-settings: var(--font-variation-strong); text-transform: var(--text-transform-strong); } /* the condensed display title at every width, not just from 48rem */

/* Gradient card: a tint, not a paint. The card keeps its surface and its text colors; the native OKLCH gradient washes over it as light from the media side,
   easing off in an ellipse to a softer wash behind the text (--tint-at is the corner it rises from), and a hairline of the same gradient catches the edge. */
.content-card--gradient { position: relative; isolation: isolate; background: none; } /* no surface of its own: the tint sits straight on the page, so it reads pure instead of greyed by the card color */
.content-card--gradient::before, .content-card--gradient::after { content: ""; position: absolute; inset: calc(var(--hairline) * -1); z-index: -1; border-radius: inherit; background: var(--card-gradient); pointer-events: none; }
.content-card--gradient::before { opacity: 0.65; -webkit-mask-image: radial-gradient(ellipse 85% 140% at var(--tint-at, 0% 100%), #000 20%, rgb(0 0 0 / 0.4) 100%); mask-image: radial-gradient(ellipse 85% 140% at var(--tint-at, 0% 100%), #000 20%, rgb(0 0 0 / 0.4) 100%); }
.content-card--gradient:has(.media-split--flip)::before { --tint-at: 100% 100%; }
@media (prefers-color-scheme: light) { .content-card--gradient::before { opacity: 0.25; } } /* on a white page the same tint reads much stronger, so it is lighter */
.content-card--gradient::after { padding: var(--hairline); opacity: 0.3; -webkit-mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); }
@media (max-width: 47.99rem) { .content-card--gradient::before, .content-card--gradient:has(.media-split--flip)::before { --tint-at: 50% 0%; } } /* stacked: the media is on top */

/* Layers of the media, bottom to top. The text column sets the card's height; the layers never size it. The device layer fills the media box and its contents are absolutely
   placed in it. The numbers are the Figma frames (1024 x 480 cards, the media being their outer 56% for Grinta and 54% for basketball) and are all proportions of the media, so the
   composition scales with the card. */
.media-layers { display: grid; pointer-events: none; }
.media-layers__device { position: relative; }
.media-layers img { display: block; max-width: none; }
/* Texture: a greyscale photo, full bleed over the whole card (its containing block is the card, past the unpositioned media), 15% soft light over the gradient (10% on a text card). Behind the text
   (z-index -1 in the card's stacking context, above the gradient that comes earlier in it) and clipped to the card's rounded corners, inside its hairline. */
.media-layers__texture, .content-card__texture { position: absolute; inset: 0; z-index: -1; overflow: hidden; border-radius: calc(var(--radius-card) - var(--hairline)); mix-blend-mode: soft-light; opacity: 0.15; pointer-events: none; }
.media-layers__texture img, .content-card__texture img { display: block; width: 100%; height: 100%; max-width: none; object-fit: cover; }
.content-card__texture { opacity: 0.1; } /* on a text card (texture="…"): fainter still, the text sits right on it */
@media (prefers-color-scheme: light) { .media-layers__texture { opacity: 0.08; } .content-card__texture { opacity: 0.05; } } /* light: under the paler tint the photo would grey it out, so it steps back too */
/* Device, a phone: the image is cropped to the phone, which is centered on the media and taller than the card, so it pops out above and below. It leans toward the content,
   so it is mirrored when the media is on the right. */
.media-layers__device > img { position: absolute; left: 59.2%; top: 50%; height: min(127.1%, 106.1cqw); width: auto; translate: -50% -50%; }
.media-split--flip .media-layers__device > img { left: 40.8%; }
.section:has(+ .section .media-layers__device > img) { padding-bottom: calc(var(--card-gap) * 2); } /* a phone overhangs its card, so the card above sits further away than cards usually do */
.section:has(+ .section:not(.section--tight) .media-layers__device > img) { padding-bottom: calc(var(--card-gap) * 3); } /* and a section of text gets more room still before the first phone card */
@media (min-width: 48rem) { .section:has(.media-layers__device > img):has(+ .section:not(.section--tight)) { padding-bottom: calc(var(--card-gap) * 3); } } /* the same room after the last one, which the phone overhangs (stacked, it only overhangs above) */
/* Centered split: the media and the text are one group, centered in the row, rather than each taking its share of the width. Made for a portrait phone in
   <media-layers>: the media is as wide as the phone (38rem tall at the screenshots' 720 x 1472, so 4rem over a 30rem card above and below). Stacked, it is a plain split. */
@media (min-width: 48rem) {
  .media-split--centered { justify-content: center; }
  .media-split--centered .media-split__media { flex: 0 0 18.6rem; }
  .media-split--centered .media-split__content { flex: 0 1 34rem; }
  .media-split--centered .media-layers__device > img { left: 50%; height: 38rem; }
}
/* Device, a pair of app icons: a box with the proportions of the group in the design (481 x 381), the icon behind first. It is taller than the card, so it hangs out above and below; its
   share of the height is bigger than the phone's but the card is thinner, so the icons stay the smaller visual. */
.app-icons { position: absolute; left: 46%; top: 50%; height: min(118%, 71.3cqw); aspect-ratio: 481.28 / 381.43; translate: -50% -50%; }
.app-icons img { position: absolute; height: auto; }
.app-icons img:first-child { left: 49.4%; top: 37.7%; width: 50.55%; }
.app-icons img:last-child { left: 0; top: 0; width: 70%; }
.media-split--bare .app-icons { position: relative; left: auto; top: auto; translate: none; width: min(100%, 26rem); height: auto; } /* in a hero: a plain block in the media column, its height from the group's proportions */
@media (max-width: 47.99rem) {
  /* Stacked: the media is a band above the text. A phone is bigger than the band and sits on its bottom edge, so it pops out
     above the card only; the card's top margin leaves room for that (a quarter of the band, so about 5rem) clear of the section above. */
  .content-card:has(.media-layers__device > img) { margin-top: var(--space-6); margin-bottom: 0; }
  .content-card:has(.app-icons) { margin-top: var(--space-4); margin-bottom: 0; }
  .content-card:has(.media-layers) .media-split { min-height: 0; }
  .content-card:has(.media-layers) .media-split__media { min-height: 22rem; }
  .content-card:has(.app-icons) .media-split__media { min-height: 16rem; }
  .media-layers__device > img, .media-split--flip .media-layers__device > img { left: 50%; top: auto; bottom: 2.6%; width: auto; height: min(122.4%, 120cqw); translate: -50% 0; } /* the band is set in rem, so a larger default font makes it taller: the cqw cap keeps the phone inside the card's width */
  .app-icons { left: 50%; top: auto; bottom: 4%; height: min(112%, 78cqw); translate: -50% 0; }
}

/* Points: beliefs straight on the page (no card), a single narrow column centered under the section heading, each a circle beside its heading and text.
   On a phone the circle sits above its text. */
.point-list { max-width: 46rem; margin: 0 auto var(--space-5); padding-top: var(--space-4); } /* air above (padding, so it adds to the heading's gap instead of collapsing into it) and below, so the list stands apart from the title and the block after */
.point-item { display: flex; align-items: center; gap: var(--space-5); padding-block: var(--space-4); } /* no dividers, so the rows sit closer */
.point-item:first-child { padding-top: 0; }
.point-item:last-child { padding-bottom: 0; }
.point-item__media { position: relative; flex: none; width: 10rem; aspect-ratio: 1; border-radius: 50%; overflow: hidden; background: var(--color-surface-tertiary); } /* 160px circle: big enough for a photo's subject to read */
.point-item__media::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 var(--hairline) var(--color-border-secondary); pointer-events: none; } /* an inner stroke, drawn over the photo so it holds the edge on any image */
.point-item__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.point-item__content { min-width: 0; }
.point-item__content > :last-child { margin-bottom: 0; }
.point-item__content > p { color: var(--color-content-secondary); } /* the heading in primary, its text a step back */
@media (max-width: 47.99rem) { .point-item { flex-direction: column; align-items: flex-start; gap: var(--space-4); padding-block: var(--space-4); } .point-item__media { width: 7.5rem; } } /* stacked above its text, a smaller circle keeps the list short */
.point-item h3 { margin-bottom: var(--space-2); }

/* Placeholder media: a cross corner to corner, so an empty block reads as an image slot. Gradients, not an image, so the lines follow any ratio. */
.hero--backdrop,
.media-split__media,
.point-item__media {
  background-image:
    linear-gradient(to top right, transparent calc(50% - 1px), var(--color-border-primary) 50%, transparent calc(50% + 1px)),
    linear-gradient(to bottom right, transparent calc(50% - 1px), var(--color-border-primary) 50%, transparent calc(50% + 1px));
}

/* Text for screen readers only. */
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* <redacted-text>: "invisible ink", like a hidden iMessage. No letters show: the decoy word (never the real name) is transparent and only gives the
   ink its width. The ink is a soft glow with two layers of random speckle (SVG noise thresholded into dots, tileable) drifting against each other,
   all in the text color, faded at the edges. The speckle holds still for reduced motion. */
.redacted { position: relative; display: inline-block; }
.redacted__ink { position: relative; display: inline-block; vertical-align: baseline; user-select: none; padding-inline: 0.15em; margin-inline: -0.15em; } /* the side fades sit outside the text box, so the ink's dense part lines up with the text around it */
.redacted__decoy { display: inline-block; color: transparent; }
.redacted__ink::before, .redacted__ink::after { content: ""; position: absolute; inset: 0.08em -0.05em 0.12em; pointer-events: none; background: currentColor; }
.redacted__ink::before { opacity: 0.22; filter: blur(0.18em); border-radius: 0.3em; } /* the glow: mass under the speckle, so it reads as a word-shaped cloud */
.redacted__ink::after {
  --ink-fine: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='64' height='64'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.1' numOctaves='1' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 -10.6'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --ink-coarse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='1' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 -12.4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  -webkit-mask-image: var(--ink-fine), var(--ink-coarse); -webkit-mask-size: 64px 64px, 80px 80px;
  mask-image: var(--ink-fine), var(--ink-coarse); mask-size: 64px 64px, 80px 80px; mask-composite: add; }
.redacted__ink { -webkit-mask-image: linear-gradient(to right, transparent, #000 0.4em, #000 calc(100% - 0.4em), transparent), linear-gradient(transparent 0.02em, #000 0.3em, #000 calc(100% - 0.3em), transparent calc(100% - 0.02em)); -webkit-mask-composite: source-in; mask-image: linear-gradient(to right, transparent, #000 0.4em, #000 calc(100% - 0.4em), transparent), linear-gradient(transparent 0.02em, #000 0.3em, #000 calc(100% - 0.3em), transparent calc(100% - 0.02em)); mask-composite: intersect; } /* a soft cloud: every edge fades out */
@media (prefers-reduced-motion: no-preference) { .redacted__ink::after { animation: redacted-shimmer 5s linear infinite; } }
@keyframes redacted-shimmer { from { -webkit-mask-position: 0 0, 0 0; mask-position: 0 0, 0 0; } to { -webkit-mask-position: 64px -64px, -80px -80px; mask-position: 64px -64px, -80px -80px; } } /* each layer drifts one whole tile, its own way: a seamless shimmer */
/* Hover explanation, centered above the bar and free to extend past the card. Under 48rem it is left aligned with the bar instead, so it stays on screen.
   Reset the heading's caps and condensed axes: it is small body text. */
.redacted__tip { position: absolute; z-index: 2; left: 50%; bottom: calc(100% + var(--space-2)); width: max-content; padding: var(--space-1) var(--space-2); background: var(--color-background-secondary); border: var(--hairline) solid var(--color-border-primary); border-radius: var(--radius-sm); color: var(--color-content-primary); font: var(--type-utility); font-variation-settings: normal; letter-spacing: var(--tracking-utility); text-transform: none; white-space: nowrap; pointer-events: none; opacity: 0; visibility: hidden; transform: translateX(-50%); }
.redacted:hover .redacted__tip { opacity: 1; visibility: visible; }
@media (max-width: 47.99rem) { .redacted__tip { left: 0; transform: none; white-space: normal; max-width: min(14rem, 70vw); } } /* wraps, so a hidden tooltip never widens the page */
@media (prefers-reduced-motion: no-preference) {
  .redacted__tip { transition: opacity 0.15s, transform 0.15s, visibility 0.15s; }
  @media (min-width: 48rem) { .redacted__tip { transform: translateX(-50%) translateY(2px); } .redacted:hover .redacted__tip { transform: translateX(-50%); } }
  @media (max-width: 47.99rem) { .redacted__tip { transform: translateY(2px); } .redacted:hover .redacted__tip { transform: none; } }
}

/* Numbered steps: a Markdown <ol> drawn as a centered timeline, numbered circles joined by a hairline. Stacked by default: each step's circle, title and
   detail centered, the line running down through the gap to the next circle. From 64rem: four columns, the line running across from circle to circle. */
.step-list ol { --step-circle: 3rem; --step-gap: var(--space-5); display: grid; gap: var(--step-gap); counter-reset: step; list-style: none; margin: var(--space-5) 0; padding: 0; text-align: center; }
.step-list:last-child ol { margin-bottom: 0; } /* closing a section: the section gap is enough */
.step-list li { position: relative; counter-increment: step; text-wrap: balance; }
.step-list li > strong:first-child { display: block; } /* the step's title on its own line, its detail under it */
.step-list li::before { content: counter(step); display: grid; place-items: center; width: var(--step-circle); height: var(--step-circle); margin: 0 auto var(--space-3); border-radius: 50%; background: var(--color-brand-tint); color: var(--color-brand-accent); font: var(--type-display-medium); font-variation-settings: var(--font-variation-strong); } /* the product's accent: a 15% fill and the condensed display number */
.step-list li:not(:last-child)::after { content: ""; position: absolute; left: calc(50% - var(--hairline) / 2); top: calc(100% + var(--space-2)); height: calc(var(--step-gap) - var(--space-2) * 2); width: var(--hairline); background: var(--color-border-primary); }
@media (min-width: 64rem) {
  .step-list ol { grid-template-columns: repeat(4, 1fr); }
  /* From just past this circle to just before the next one, a column and a gap away; the percentages are of the step's width. */
  .step-list li:not(:last-child)::after { top: calc((var(--step-circle) - var(--hairline)) / 2); left: calc(50% + var(--step-circle) / 2 + var(--space-3)); right: calc(var(--step-circle) / 2 + var(--space-3) - var(--step-gap) - 50%); width: auto; height: var(--hairline); }
}

.product-legal { margin-top: var(--space-4); }
.product-legal .footer-links { justify-content: center; font: var(--type-label); letter-spacing: var(--tracking-label); color: var(--color-content-secondary); } /* fine print under the form */

.section > .container > h2:has(+ p > .note:only-child) { margin-bottom: var(--space-1); } /* a note right under a title belongs to it */
.note { display: block; text-align: center; font: var(--type-label); letter-spacing: var(--tracking-label); color: var(--color-content-secondary); }
