/* alda-apps.com
   Colours are the Canopy values from ../04-colors/colors.css, copied here so this folder can be
   uploaded on its own. If a colour changes there, change it here too.
   The theme is set on <html data-theme="light|dark"> by theme.js; without JavaScript the page
   follows the system. Nothing here may need a style="" attribute or an inline <style>: the pages'
   Content-Security-Policy allows only this file. */

@font-face {
  font-family: "Sora";
  src: url("assets/fonts/Sora.woff2") format("woff2");   /* weights 300 to 500, Latin: tools/font.py */
  font-weight: 300 500;
  font-display: swap;
}

:root {
  color-scheme: light dark;

  --bg:          light-dark(#fafdfb, #09120d);   /* Paper / Forest night */
  --card:        light-dark(#ffffff, #101a14);   /* dark: Canopy's card (neutral 2) */
  --well:        light-dark(#f1f6f3, #17221c);   /* the drawing area of a card: neutral 2 / 3 */
  --ink:         light-dark(#141f19, #ecf2ee);
  --ink-dim:     light-dark(#59645d, #a8b0ab);   /* 4.5:1 or more */
  --ink-faint:   light-dark(#9aa49e, #4f5a54);   /* decoration only, never text */
  --line:        light-dark(rgb(20 31 25 / 9%), rgb(255 255 255 / 8%));
  --line-strong: light-dark(rgb(20 31 25 / 18%), rgb(255 255 255 / 16%));
  --dot:         light-dark(rgb(20 31 25 / 13%), rgb(255 255 255 / 9%));
  --glow:        light-dark(rgb(20 31 25 / 4%), rgb(255 255 255 / 4%));
  --shadow:      light-dark(rgb(16 40 28 / 7%), rgb(0 0 0 / 40%));
  --accent:      light-dark(#1f4a3a, #9fd3c3);   /* Evergreen / Pale sage */
  --live:        light-dark(#28713d, #83d494);
  --amber:       #c8963e;
  /* Small doses of the house green: the fill behind a rule's icon, and the title's second line, which
     runs from Evergreen to Deep sage (in dark from Pale ink to Pale sage). */
  --accent-soft: light-dark(rgb(31 74 58 / 10%), rgb(159 211 195 / 14%));
  --title-from:  light-dark(#1f4a3a, #ecf2ee);
  --title-to:    light-dark(#3f7f6e, #9fd3c3);
  /* The leaves in the page's ground (leaves.js): Deep sage, Moss and Sage, and a few in
     Amber; in dark Sage, Moss and Pale sage. Faint: they are a ground, not a picture. */
  --leaf-1:      light-dark(rgb(63 127 110 / 38%), rgb(79 148 130 / 44%));
  --leaf-2:      light-dark(rgb(78 138 79 / 36%), rgb(78 138 79 / 46%));
  --leaf-3:      light-dark(rgb(79 148 130 / 34%), rgb(159 211 195 / 26%));
  --leaf-4:      light-dark(rgb(200 150 62 / 44%), rgb(200 150 62 / 40%));
  --band:        light-dark(#f1f6f3, #0d1711);   /* a section's own ground: Mist / between the page and a card */
  --window-bar:  light-dark(#f7faf8, #141f19);   /* the browser window drawn round a web app's screenshot */
  --stage-dim:   light-dark(transparent, rgb(9 18 13 / 38%));   /* over a screenshot's stage */
  --stage-shadow: light-dark(rgb(10 24 17 / 38%), rgb(0 0 0 / 60%));

  /* Glass: the Canopy recipe (../02-design-language/tokens.css and foundations.md 3.6, the same
     numbers as the desktop apps' glass.rs). The tint is 04-colors' thin glass, and thicker, towards
     its panel, only over the columns where a screenshot is under the header: site.js sets
     --glass-cells, as Feedscape's glass.js does. Without scripts the page can't tell, so the panel
     tint is used throughout. */
  --glass-tint:  light-dark(rgb(255 255 255 / 45%), rgb(22 36 29 / 42%));   /* 04-colors' glass */
  --glass-dense: light-dark(rgb(250 253 251 / 78%), rgb(16 26 20 / 80%));   /* and its panel */
  --glass-filter: blur(20px) saturate(1.35);
  --glass-edge:  light-dark(rgb(255 255 255 / 75%), rgb(255 255 255 / 16%));
  /* The edge, lit from above: full on top, 15 % on the sides, 50 % at the bottom; in dark lifted
     towards the ink so the top still catches the light. */
  --edge-up:     light-dark(var(--glass-edge), color-mix(in srgb, var(--glass-edge) 75%, var(--ink)));
  --edge-side:   color-mix(in srgb, var(--edge-up) 15%, transparent);
  --edge-down:   color-mix(in srgb, var(--edge-up) 50%, transparent);
  /* The sheen: from the top, 16.5 % white in light and 7 % in dark, fading as (1 − t)² over 220 px */
  --sheen-top:   light-dark(rgb(255 255 255 / 16.5%), rgb(255 255 255 / 7%));
  --sheen: linear-gradient(180deg,
    var(--sheen-top) 0,
    color-mix(in srgb, var(--sheen-top) 64%, transparent) 44px,
    color-mix(in srgb, var(--sheen-top) 36%, transparent) 88px,
    color-mix(in srgb, var(--sheen-top) 16%, transparent) 132px,
    color-mix(in srgb, var(--sheen-top) 4%, transparent) 176px,
    transparent 220px);
  --grain: 0.035;
  --grain-image: url("assets/grain.svg");
  /* Elevation 2, glass floating over the page: a little shadow above, reaching 4 px, the rest below,
     reaching 12 px; in 04-colors' shadow colour. Elevation 1 for what stands on a surface. */
  --glass-shadow: light-dark(rgb(16 40 28 / 12%), rgb(0 0 0 / 45%));
  --elevation-1:
    0 1px 2px color-mix(in srgb, var(--glass-shadow) 90%, transparent),
    0 2px 6px -2px var(--glass-shadow);
  --elevation-2:
    0 -1px 4px -1px var(--glass-shadow),
    0 1px 2px -1px var(--glass-shadow),
    0 4px 10px -3px var(--glass-shadow),
    0 6px 12px -6px var(--glass-shadow);
  /* On glass: weak text leaned 40 % towards the ink (4.5:1 over the screenshot under the thickened
     tint); controls on a track of ink at 8 %, the chosen one raised out of it with a rail outline
     (04-colors' border-strong); hover a film of ink. */
  --ink-dim-on-glass: color-mix(in srgb, var(--ink-dim) 60%, var(--ink));
  --track:       color-mix(in srgb, var(--ink) 8%, transparent);
  --raised:      light-dark(var(--card), color-mix(in srgb, var(--ink) 22%, transparent));
  --rail:        light-dark(rgb(20 31 25 / 50%), rgb(255 255 255 / 40%));
  --film-hover:  color-mix(in srgb, var(--ink) 7%, transparent);
  --film-press:  color-mix(in srgb, var(--ink) 12%, transparent);
  --motion: 150ms;
  --motion-slow: 220ms;    /* a dialog opens */
  --motion-enter: 300ms;   /* a sheet rises */
  --ease-settle: cubic-bezier(0.2, 0.7, 0.3, 1);
  /* A dialog: elevation 3 over a scrim, black at 43 % (light) or 60 % (dark), the page behind blurred. */
  --elevation-3:
    0 2px 4px -2px var(--glass-shadow),
    0 12px 28px -10px var(--glass-shadow),
    0 36px 72px -28px var(--glass-shadow);
  --scrim: light-dark(rgb(0 0 0 / 43%), rgb(0 0 0 / 60%));
  --scrim-filter: blur(16px) saturate(1.1);

  --wrap: 1120px;
  --gutter: clamp(20px, 5vw, 64px);
  --radius: 24px;
  --ease: cubic-bezier(.2, .7, .2, 1);
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark; }

/* The system's accessibility settings, as in Canopy's tokens.css. Reduce transparency: the header's
   glass becomes a solid plate in the card colour, without blur or grain; its edge, sheen and shadow
   stay, so it is still a bar. */
@media (prefers-reduced-transparency: reduce) {
  :root { --glass-tint: var(--card); --glass-dense: var(--card); --glass-filter: none; --scrim-filter: none; --grain: 0; }
}
/* Increase contrast: the solid header as above, dim text halfway to the ink, the lines and the
   header's edge at 04-colors' border-strong (3:1), and the theme switch's track at 16 %. */
@media (prefers-contrast: more) {
  :root {
    --glass-tint: var(--card);
    --glass-dense: var(--card);
    --glass-filter: none;
    --scrim-filter: none;
    --grain: 0;
    --ink-dim: color-mix(in srgb, light-dark(#59645d, #a8b0ab) 50%, light-dark(#141f19, #ecf2ee));
    --line: light-dark(rgb(20 31 25 / 50%), rgb(255 255 255 / 40%));
    --line-strong: var(--line);
    --edge-up: var(--line);
    --edge-side: var(--line);
    --edge-down: var(--line);
    --track: color-mix(in srgb, var(--ink) 16%, transparent);
  }
}
/* Without scripts nothing measures what is under the header, so it takes the dense tint. */
:root:not(.js) { --glass-tint: var(--glass-dense); }

/* Show the logo drawn for the current theme */
.only-dark { display: none !important; }
:root[data-theme="dark"] .only-dark { display: block !important; }
:root[data-theme="dark"] .only-light { display: none !important; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .only-dark { display: block !important; }
  :root:not([data-theme]) .only-light { display: none !important; }
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 96px; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Sora", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background-color 300ms ease, color 300ms ease;
}

h1, h2, h3, p, ul, ol { margin: 0; padding: 0; }
ul, ol { list-style: none; }
img { display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
/* Canopy's focus ring: 2 px in the accent, 2 px out */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

.wrap {
  width: 100%;
  max-width: calc(var(--wrap) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip {
  position: absolute; left: 16px; top: -48px; z-index: 20;
  padding: 8px 14px; border-radius: 999px; background: var(--ink); color: var(--bg);
}
.skip:focus { top: 16px; }

/* Header: a floating glass bar, a little wider than the content, 12 px from the top (Canopy's inset) */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  padding: 12px max(8px, calc(var(--gutter) - 20px)) 0;
}
.bar {
  position: relative;
  max-width: calc(var(--wrap) + 40px);
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 8px 8px 8px 16px;
  border-radius: 999px;
}

/* Canopy's glass, for the two things that float: the header's bar and the dialog's close button.
   Each places and shapes itself; only the bar thickens (site.js). */
.bar,
.sheet-close {
  isolation: isolate;
  --ink-dim: var(--ink-dim-on-glass);
  background-image:
    var(--sheen),
    var(--glass-cells, linear-gradient(var(--glass-tint), var(--glass-tint)));
  -webkit-backdrop-filter: var(--glass-filter);
  backdrop-filter: var(--glass-filter);
  box-shadow: var(--elevation-2);
}
.bar::before, .bar::after,
.sheet-close::before, .sheet-close::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
}
.bar::before,
.sheet-close::before {                /* the edge, lit from above */
  padding: 1px;
  background: linear-gradient(180deg, var(--edge-up), var(--edge-side) 50%, var(--edge-down)) border-box;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
.bar::after,
.sheet-close::after {                 /* the grain */
  background-image: var(--grain-image);
  background-size: 128px;
  opacity: var(--grain);
}
/* The brand: the tree and the name in Sora Medium, set as text so it sits with the nav's words */
.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1;
  white-space: nowrap;
}
.brand img { height: 32px; width: auto; }
.site-nav {
  display: flex;
  gap: 4px;
  margin-left: auto;
  font-size: 14px;
}
.site-nav a {
  padding: 7px 14px;
  border-radius: 999px;
  color: var(--ink-dim);
  transition: color var(--motion) ease, background-color var(--motion) ease;
}
/* Bar items: no fill at rest, a film of ink on hover, a step more when pressed */
.site-nav a:hover { color: var(--ink); background-color: var(--film-hover); }
.site-nav a:active { background-color: var(--film-press); }

/* Theme switch: Canopy's segmented control, as in Feedscape's top bar. Three buttons in a track, the
   chosen one raised out of it, the thumb sliding to it in 0.15 s. */

.theme-switch {
  position: relative;
  display: flex;
  padding: 3px;
  border-radius: 999px;
  background: var(--track);
}
.theme-switch button {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--ink-dim);
  cursor: pointer;
  transition: color var(--motion) ease;
}
.theme-switch button:hover,
.theme-switch button[aria-pressed="true"] { color: var(--ink); }
.theme-switch svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.theme-thumb {
  position: absolute;
  top: 3px; left: 3px;
  width: 30px; height: 30px;
  border-radius: 999px;
  background: var(--raised);
  box-shadow: var(--elevation-1), inset 0 0 0 1px var(--rail);
  transition: transform var(--motion) var(--ease-settle);
}
:root[data-pref="system"] .theme-thumb { transform: translateX(30px); }
:root[data-pref="dark"] .theme-thumb { transform: translateX(60px); }
:root:not(.js) .theme-switch { display: none; }

/* Hero */

.hero {
  position: relative;
  margin-top: -60px;               /* run under the floating header */
  padding: clamp(120px, 16vh, 176px) 0 clamp(56px, 8vh, 88px);
  overflow: hidden;
  text-align: center;
}
.hero-grid,
.contact-grid {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--dot) 1px, transparent 1.2px);
  background-size: 22px 22px;
  pointer-events: none;
}
.hero-grid {
  -webkit-mask-image: radial-gradient(ellipse 60% 62% at 50% 40%, #000 10%, transparent 75%);
  mask-image: radial-gradient(ellipse 60% 62% at 50% 40%, #000 10%, transparent 75%);
}
/* With scripts the grid's dots give way to leaves (leaves.js draws them on a canvas it adds), which
   reach a little further before they fade. */
.js [data-leaves] { background-image: none; }
[data-leaves] canvas {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
}
.js .hero-grid[data-leaves] {
  -webkit-mask-image: radial-gradient(ellipse 72% 74% at 50% 44%, #000 25%, transparent 82%);
  mask-image: radial-gradient(ellipse 72% 74% at 50% 44%, #000 25%, transparent 82%);
}
.hero-inner {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* Still, as everything else on the page: a dot needs no motion to be seen */
.live-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--live);
  flex: none;
}
/* What is new, over the title: a small capsule that goes to it */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 34px;
  margin-bottom: 28px;
  padding: 0 12px 0 13px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: color-mix(in srgb, var(--card) 80%, transparent);
  font-size: 13.5px;
  color: var(--ink-dim);
  transition: color var(--motion) ease, border-color var(--motion) ease;
}
.pill:hover { color: var(--ink); border-color: var(--ink-faint); }
.pill img { width: 20px; height: 20px; margin-left: -6px; border-radius: 6px; }
.pill svg {
  width: 14px; height: 14px;
  fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}

.hero h1 {
  font-size: clamp(46px, 7.6vw, 100px);
  font-weight: 300;
  line-height: 1.02;
  letter-spacing: -0.045em;
}
.hero h1 .fade {
  background: linear-gradient(100deg, var(--title-from) 15%, var(--title-to) 85%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.lede {
  margin-top: 26px;
  max-width: 40ch;
  font-size: clamp(16px, 1.5vw, 19px);
  color: var(--ink-dim);
  line-height: 1.65;
}
.actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 36px;
}

/* The 404 page: the hero, smaller, filling the window */
.not-found { min-height: calc(100svh - 120px); display: grid; align-content: center; }
.not-found h1 { margin-top: 18px; font-size: clamp(40px, 6vw, 76px); }
.not-found .lede { margin-top: 20px; }

/* Buttons */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 46px;
  padding: 0 22px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 15px;
  font-weight: 450;
  cursor: pointer;
  white-space: nowrap;
  flex: none;
  transition: background-color 200ms ease, border-color 200ms ease, opacity 200ms ease;
}
.btn svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.btn-primary {
  background: var(--ink);
  color: var(--bg);
}
.btn-primary:hover { opacity: .86; }
.btn-ghost {
  background: color-mix(in srgb, var(--card) 80%, transparent);
  border-color: var(--line-strong);
}
.btn-ghost:hover { border-color: var(--ink-faint); }
.btn-small { height: 40px; padding: 0 18px; font-size: 14px; }

/* Sections */

.section { padding-bottom: clamp(88px, 13vh, 144px); }
.section-last { padding-bottom: clamp(64px, 10vh, 112px); }
/* A section on its own ground, edge to edge */
.section-band {
  margin-bottom: clamp(88px, 13vh, 144px);
  padding-block: clamp(72px, 11vh, 120px);
  background: var(--band);
  border-block: 1px solid var(--line);
}
.section-head { margin-bottom: 40px; }
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  font-weight: 450;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.eyebrow::before {
  content: "";
  width: 20px; height: 1.5px;
  background: var(--amber);
}
.section-head h2,
.how-head h2,
.contact h2 {
  margin-top: 14px;
  font-size: clamp(30px, 4vw, 48px);
  font-weight: 300;
  line-height: 1.1;
  letter-spacing: -0.035em;
}

/* Cards */

.card {
  position: relative;
  border-radius: var(--radius);
  background: var(--card);
  border: 1px solid var(--line);
  box-shadow: 0 1px 2px var(--shadow), 0 14px 32px -22px var(--shadow);
  overflow: hidden;
  isolation: isolate;
}
/* A card is not a control: nothing about it changes under the pointer (the owner, 2026-11-12). */

.apps {
  display: grid;
  gap: 16px;
}

/* An app: its screenshot whole, on a stage that follows the card's corners, then what it does. The
   stage is the photo the app shows, out of focus (an image made once, see the README), under the
   glass's grain; in dark it is dimmed towards Forest night. */
.shot {
  position: relative;
  margin: 10px 10px 0;
  padding: clamp(18px, 4.4vw, 52px) clamp(14px, 4.8vw, 56px) 0;
  border-radius: calc(var(--radius) - 10px);
  background: var(--well);
  overflow: hidden;
  isolation: isolate;
}
.stage {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%; height: 100%;
  object-fit: cover;
}
.shot::before, .shot::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.shot::before { background: var(--stage-dim); }
.shot::after {                       /* the grain, which also keeps the soft colours from banding */
  background-image: var(--grain-image);
  background-size: 128px;
  opacity: var(--grain);
}
/* A web app's screenshot stands in a plain browser window, which runs off the well's lower edge */
.window {
  border-radius: 12px 12px 0 0;
  border: 1px solid light-dark(rgb(255 255 255 / 55%), rgb(255 255 255 / 14%));
  border-bottom: 0;
  background: var(--window-bar);
  box-shadow: 0 30px 70px -24px var(--stage-shadow), 0 2px 10px color-mix(in srgb, var(--stage-shadow) 45%, transparent);
  overflow: hidden;
}
.window-bar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 38px;
  border-bottom: 1px solid var(--line);
}
.window-dots {
  position: absolute;
  left: 14px;
  display: flex;
  gap: 7px;
}
.window-dots i {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 14%, transparent);
}
.window-address {
  padding: 3px 16px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 5%, transparent);
  font-size: 12px;
  color: var(--ink-dim);
}
.window img { width: 100%; height: auto; }
.window-phone {                      /* a phone's screen, whole: no bar, rounder corners */
  display: none;
  width: min(100%, 264px);
  margin-inline: auto;
  border-radius: 26px 26px 0 0;
}

.showcase-info {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: 32px clamp(32px, 6vw, 80px);
  padding: 40px 38px 36px;
}
.showcase-lead {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.card-title {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 18px;
}
.card-title img { width: 48px; height: 48px; }
.card-title h2 {
  font-size: 32px;
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.1;
}
.badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-left: 2px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  font-size: 12px;
  color: var(--ink-dim);
  white-space: nowrap;
}
.showcase-lead > p:not(.eyebrow) {
  margin-top: 18px;
  color: var(--ink-dim);
  font-size: 17px;
  max-width: 38ch;
}
.card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
  margin-top: auto;
  padding-top: 28px;
  font-size: 14px;
}
.meta { color: var(--ink-dim); }

/* What the app does: three lines, each with a small line icon */
.facts { display: grid; align-content: center; }
.facts li {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: 16px;
  padding-block: 18px;
}
.facts li + li { border-top: 1px solid var(--line); }
.facts li:first-child { padding-top: 4px; }
.facts li:last-child { padding-bottom: 4px; }
.facts svg {
  width: 24px; height: 24px;
  fill: none; stroke: var(--accent); stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
}
.facts h3 { font-size: 16px; font-weight: 500; letter-spacing: -0.01em; line-height: 1.5; }
.facts p { margin-top: 2px; font-size: 14.5px; color: var(--ink-dim); }

.card-more {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 26px 28px 26px 38px;
  background: transparent;
  border-style: dashed;
  border-color: var(--line-strong);
  box-shadow: none;
}
.card-more h2 { font-size: 17px; font-weight: 500; letter-spacing: -0.01em; }
.card-more p { margin-top: 4px; font-size: 14.5px; color: var(--ink-dim); }

/* How we work: the heading on the left, the five rules as numbered rows of one card on the right */

.how {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: start;
  gap: 40px clamp(32px, 6vw, 88px);
}
.how-head > p:not(.eyebrow) { margin-top: 20px; max-width: 34ch; color: var(--ink-dim); }
/* One of the maker's own photos: the work the apps are for */
.how-photo { margin: 32px 0 0; }
.how-photo img {
  width: 100%; height: auto;
  border-radius: 14px;
}
.values {
  padding: 6px 30px;
  counter-reset: rule;
}
.value {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto;
  gap: 2px 18px;
  padding-block: 22px;
  counter-increment: rule;
}
.value + .value { border-top: 1px solid var(--line); }
.value::after {                      /* its number, at the end of the row */
  content: "0" counter(rule);
  grid-column: 3; grid-row: 1 / span 2;
  align-self: center;
  padding-left: 6px;
  font-size: 12.5px;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-dim);
}
.value-icon {
  grid-row: 1 / span 2;
  align-self: center;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border-radius: 13px;
  background: var(--accent-soft);
}
.value-icon svg {
  width: 22px; height: 22px;
  fill: none; stroke: var(--accent); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.value-icon svg .fill { fill: var(--accent); }
.value h3 { grid-column: 2; align-self: end; font-size: 17px; font-weight: 500; letter-spacing: -0.015em; }
.value p { grid-column: 2; font-size: 15px; color: var(--ink-dim); }

/* Contact: the words on the left, the tree on the right over a patch of the dot grid */

.contact {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 32px 48px;
  padding: clamp(36px, 6vw, 72px) clamp(26px, 7vw, 88px) clamp(36px, 6vw, 72px) clamp(26px, 6vw, 72px);
}
.contact-grid {
  -webkit-mask-image: radial-gradient(ellipse 34% 90% at 86% 50%, #000 0%, transparent 100%);
  mask-image: radial-gradient(ellipse 34% 90% at 86% 50%, #000 0%, transparent 100%);
  z-index: -1;
}
.contact-intro { margin-top: 14px; max-width: 44ch; color: var(--ink-dim); }
.contact .actions { margin-top: 32px; justify-content: flex-start; }
.contact-mark img { width: auto; height: clamp(120px, 15vw, 176px); }

/* A page of text: the privacy page */

.doc-page { padding-block: clamp(56px, 10vh, 112px) clamp(80px, 12vh, 140px); }
.doc { max-width: calc(680px + 2 * var(--gutter)); }
.doc h1 {
  font-size: clamp(38px, 5vw, 60px);
  font-weight: 300;
  line-height: 1.08;
  letter-spacing: -0.04em;
}
.doc .updated {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  font-size: 13px;
  color: var(--ink-dim);
}
.doc .updated::before {
  content: "";
  width: 20px; height: 1.5px;
  background: var(--amber);
}
.doc .lead {
  margin-top: 32px;
  font-size: clamp(17px, 1.6vw, 19px);
  line-height: 1.65;
}
.doc h2 {
  margin-top: 48px;
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -0.015em;
}
.doc h2 + p { margin-top: 10px; }
.doc p + p { margin-top: 14px; }
.doc p:not(.lead):not(.updated) { color: var(--ink-dim); }
.doc a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--accent) 35%, transparent);
  text-underline-offset: 3px;
  overflow-wrap: anywhere;
  transition: text-decoration-color 160ms ease;
}
.doc a:hover { text-decoration-color: currentColor; }

/* A page in a dialog (sheet.js): the privacy page's article in an opaque plate in the middle of the
   window, over the page dimmed and softened. Canopy's dialog, as Feedscape's sheet: 16 px corners, a
   1 px edge, elevation 3, a close button of glass at the top right. On a phone, a sheet from the
   bottom (below). */
.sheet {
  flex-direction: column;
  width: min(704px, calc(100% - 32px));
  max-width: none;
  max-height: min(768px, calc(100% - 64px));
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--card);
  color: var(--ink);
  box-shadow: var(--elevation-3);
  overflow: hidden;
}
.sheet[open] { display: flex; animation: sheet-in var(--motion-slow) var(--ease-settle); }
.sheet::backdrop {
  background: var(--scrim);
  -webkit-backdrop-filter: var(--scrim-filter);
  backdrop-filter: var(--scrim-filter);
}
.sheet[open]::backdrop { animation: fade-in var(--motion-slow) var(--ease-settle); }
/* Let go after a swipe down that doesn't close it (sheet.js), it slides back up. */
.sheet { transition: translate var(--motion-slow) var(--ease-settle); }
/* Closing, it fades and sinks a little and the backdrop clears, where the browser can keep a closed
   dialog in the top layer for that (`overlay`); elsewhere it goes at once. */
@supports (overlay: auto) {
  .sheet, .sheet::backdrop {
    transition:
      opacity var(--motion) var(--ease-settle),
      translate var(--motion) var(--ease-settle),
      display var(--motion) allow-discrete,
      overlay var(--motion) allow-discrete;
  }
  .sheet:not([open]) { opacity: 0; translate: 0 8px; }
  .sheet:not([open])::backdrop { opacity: 0; }
}
.sheet-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
/* The text fades out where it scrolls under the top and bottom edges, over 48 px where there is more
   to scroll; at either end there is none. Browsers that can't animate with scrolling get fixed fades no
   taller than the article's padding. The strip on the right, where the scroll bar is, stays clear. */
@property --fade-top { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --fade-bottom { syntax: "<length>"; inherits: false; initial-value: 0px; }
.sheet-body {
  --fade-top: 24px;
  --fade-bottom: 24px;
  mask-image:
    linear-gradient(transparent, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent),
    linear-gradient(#000, #000);
  mask-size: calc(100% - 16px) 100%, 16px 100%;
  mask-position: left, right;
  mask-repeat: no-repeat;
}
@supports (animation-timeline: scroll()) {
  .sheet-body {
    animation: sheet-fade-top linear both, sheet-fade-bottom linear both;
    animation-timeline: scroll(self);
    animation-range: 0 48px, calc(100% - 48px) 100%;
  }
}
.sheet .doc { max-width: none; padding: 40px 40px 48px; }
.sheet .doc h1 { margin-right: 48px; font-size: clamp(32px, 4vw, 44px); }
/* A circle of glass, 36 px, as the bar: the text scrolls under it. Hovered, a plain fill on it. It
   keeps clear of the text's scroll bar where that takes room (--sheet-scrollbar, sheet.js). */
.sheet-close {
  position: absolute;
  top: 12px;
  right: calc(max(var(--sheet-scrollbar, 0px), 16px) + 8px);
  z-index: 1;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: transparent;
  color: var(--ink-dim);
  cursor: pointer;
  transition: background-color var(--motion) ease, color var(--motion) ease;
}
.sheet-close:hover { background-color: var(--film-hover); color: var(--ink); }
.sheet-close:active { background-color: var(--film-press); }
.sheet-close svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round;
}
/* On a touch screen the scroll bar floats over the text while it moves: the button sits as far in from
   the side as from the top, and the fades reach the edge. */
@media (pointer: coarse) {
  .sheet-close { right: calc(var(--sheet-scrollbar, 0px) + 12px); }
  .sheet-body { mask-size: 100% 100%, 0 100%; }
}
@keyframes sheet-in { from { opacity: 0; translate: 0 8px; } }
@keyframes sheet-up { from { translate: 0 100%; } }
@keyframes fade-in { from { opacity: 0; } }
@keyframes sheet-fade-top { from { --fade-top: 0px; } to { --fade-top: 48px; } }
@keyframes sheet-fade-bottom { from { --fade-bottom: 48px; } to { --fade-bottom: 0px; } }

/* Footer */

.site-footer {
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-dim);
}
.footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  padding-block: 28px 40px;
}
.footer-brand { display: flex; align-items: center; gap: 12px; }
.footer-brand img { height: 22px; width: auto; }
.footer-meta { display: flex; flex-wrap: wrap; gap: 8px 24px; }
.footer-meta a {
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 3px;
  transition: color 160ms ease, text-decoration-color 160ms ease;
}
.footer-meta a:hover,
.footer-meta a[aria-current="page"] { color: var(--ink); text-decoration-color: currentColor; }

/* Arrival: items fade up as they scroll in (only with JavaScript and motion allowed) */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 700ms var(--ease) var(--delay, 0ms), transform 700ms var(--ease) var(--delay, 0ms);
}
.js [data-reveal].in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .js [data-reveal] { opacity: 1; transform: none; }
}

/* Narrow screens */

@media (max-width: 900px) {
  .showcase-info { grid-template-columns: 1fr; padding: 32px 28px 28px; }
  .card-foot { margin-top: 0; }
  .how { grid-template-columns: 1fr; }
  .how-head > p:not(.eyebrow) { max-width: 44ch; }
}
@media (max-width: 760px) {
  .showcase-info { padding: 28px 22px 24px; }
  .card-title h2 { font-size: 28px; }
  .window-wide { display: none; }
  .window-phone { display: block; }
  .shot { padding-top: 32px; }
  .site-nav { display: none; }
  .theme-switch { margin-left: auto; }
  .card-more { flex-direction: column; align-items: flex-start; padding: 24px 22px; }
  .contact { grid-template-columns: 1fr; }
  .contact-mark { display: none; }
  .contact-grid { display: none; }
  /* The dialog is a sheet from the bottom, 32 px top corners, with a handle: it can be swiped down. */
  .sheet {
    width: 100%;
    max-height: calc(100% - 32px);
    margin: auto 0 0;
    padding-bottom: env(safe-area-inset-bottom);
    border-bottom: 0;
    border-radius: 32px 32px 0 0;
  }
  .sheet[open] { animation: sheet-up var(--motion-enter) var(--ease-settle); }
  .sheet::before {
    content: "";
    flex: none;
    width: 36px;
    height: 5px;
    margin: 8px auto 0;
    border-radius: 999px;
    background: color-mix(in srgb, var(--ink) 22%, transparent);
  }
  @supports (overlay: auto) {
    .sheet { transition-duration: var(--motion-slow); }
    .sheet:not([open]) { opacity: 1; translate: 0 100%; }
  }
  .sheet .doc { padding: 24px 20px 40px; }
}
@media (max-width: 520px) {
  .values { padding: 4px 22px; }
  .value { column-gap: 16px; padding-block: 20px; }
  .value-icon { align-self: start; }
  .value p { grid-column: 2 / -1; }
  .value::after { grid-row: 1; }
  .pill { font-size: 13px; }
  .brand { gap: 8px; font-size: 15.5px; }
  .brand img { height: 29px; }
}
