/* barehabits.app — components for every page. Values come from tokens.css (linked first);
   rules are in design-system/README.md. Components read colour roles only, so the same
   component wears the brand shell or an app's theme depending on the class around it. */

/* --- fonts ------------------------------------------------------------------
   Apple devices use their own New York and SF Pro (system fonts, never embedded).
   Other devices get the free fallbacks below, served from this site: no third-party requests. */
@font-face {
  font-family: "Newsreader";
  src: url("/fonts/newsreader-latin.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}
/* Georgia resized to Newsreader's width and line metrics: while Newsreader loads, headings already take its
   space, so nothing moves when it arrives. Values measured at weight 400 in Chrome over the site's headings. */
@font-face {
  font-family: "Newsreader Fallback";
  src: local("Georgia");
  size-adjust: 94.8%;
  ascent-override: 77.5%;
  descent-override: 28%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* --- base ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
/* --head-h: the sticky header's height, so anchors and the sticky contents list land below it. */
:root { --head-h: 64px; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-padding-top: var(--head-h); }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: var(--t-body)/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}
h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -.02em;
  margin: 0;
  text-wrap: balance;
}
p { margin: 0; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

.wrap { max-width: var(--page); margin: 0 auto; padding: 0 var(--gutter); }
.kicker { font-size: var(--t-kicker); letter-spacing: .16em; text-transform: uppercase; color: var(--ink2); }
.lede { font-size: var(--t-lede); line-height: 1.55; color: var(--ink2); }
.rule { border-top: 1px solid var(--line); }
.band { padding: 56px 0; }

/* The signature stripe: an app's label. Paints the app's --signature (its one decorative colour).
   In the brand shell it is plain ink2. */
.sig { display: block; width: 56px; height: 4px; border-radius: var(--r-pill); background: var(--signature); }

/* --- header / footer: brand chrome ----------------------------------------- */
/* One row, --head-h high, that stays at the top while the page scrolls. The page shows through,
   blurred, and a hairline appears under the row once the page moves. */
.head {
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(1.4); backdrop-filter: blur(20px) saturate(1.4);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .head { background: var(--bg); }
}
@supports (animation-timeline: scroll()) {
  .head { animation: head-edge linear both; animation-timeline: scroll(); animation-range: 0 var(--s5); }
}
@keyframes head-edge { from { box-shadow: 0 1px 0 transparent; } to { box-shadow: 0 1px 0 var(--line); } }
.head .wrap { display: flex; align-items: center; gap: var(--s5); height: var(--head-h); }
/* The first Tab stop on every page: hidden above the header until it has focus. */
.skip {
  position: absolute; top: var(--s2); left: var(--s2); z-index: 1; padding: var(--s3) var(--s4);
  border-radius: var(--r-pill); background: var(--accent); color: var(--on-accent);
  font-size: var(--t-small); font-weight: 500; translate: 0 calc(-100% - var(--s4));
}
.skip:focus { translate: none; text-decoration: none; }
.mark { display: inline-flex; align-items: center; min-height: 44px; font-family: var(--serif); font-size: 24px; line-height: 1; letter-spacing: -.01em; color: var(--ink); }
.mark:hover { text-decoration: none; }
.nav { display: flex; gap: 26px; margin-left: auto; font-size: 15px; }
.nav a { color: var(--ink2); }
.nav a:hover { color: var(--ink); text-decoration: none; }
.nav a[aria-current="page"] { color: var(--ink); }
/* A nav with more than one link is a popover (Header.astro): a row in the header on wide screens,
   the menu on narrow ones. These lines undo the browser's popover box for the row. */
.nav[popover] {
  position: static; inset: auto; width: auto; height: auto; margin: 0 0 0 auto; padding: 0;
  border: 0; overflow: visible; background: none; color: inherit;
}
/* Round 44 px targets around 20 px icons: theme (scripts/theme.js) and menu. The negative margins
   line the last icon up with the page edge and keep the row's spacing. */
.theme, .menu {
  display: grid; place-items: center; flex: none; width: 44px; height: 44px; padding: 0;
  margin: -12px -12px -12px calc(-1 * var(--s2)); border: 0; border-radius: var(--r-pill);
  background: none; color: var(--ink2); cursor: pointer;
  transition: background-color var(--d-touch) var(--ease-exhale), color var(--d-touch) var(--ease-exhale);
}
.theme:hover, .menu:hover { background: var(--accent-soft); color: var(--ink); }
.theme[hidden] { display: none; }
.menu { display: none; }
/* The menu icon: two lines that cross while the menu is open. */
.menu line { transform-box: fill-box; transform-origin: center; transition: transform var(--d-change) var(--ease-exhale); }
.head:has(.nav:popover-open) .menu { color: var(--ink); }
.head:has(.nav:popover-open) .menu line:first-child { transform: translateY(3px) rotate(45deg); }
.head:has(.nav:popover-open) .menu line:last-child { transform: translateY(-3px) rotate(-45deg); }
/* Header and footer links are small text with a 44 px tap target: the padding grows the target and the
   negative margin keeps the layout. Rows that wrap sit var(--s5) apart, so two targets never overlap. */
.nav a, .foot .links a { padding: var(--s3) var(--s2); margin: calc(-1 * var(--s3)) calc(-1 * var(--s2)); }

.foot { padding: var(--s6) 0 40px; font-size: var(--t-small); color: var(--ink2); }
.foot .wrap { display: flex; justify-content: space-between; gap: 22px; flex-wrap: wrap; }
.foot a { color: var(--ink2); }
.foot .links { display: flex; gap: var(--s5) 20px; flex-wrap: wrap; }
.foot .legal { flex-basis: 100%; padding-top: var(--s4); border-top: 1px solid var(--hair); }
.foot .legal .fine { font-size: 12px; line-height: 1.5; max-width: 100ch; }
.foot .legal .fine + .fine { margin-top: var(--s1); }
.foot .legal a { text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--ink2) 45%, transparent); text-underline-offset: 2px; }

/* --- page head: kicker, h1, lede ------------------------------------------- */
.masthead { padding: 56px 0 64px; }
.masthead .sig { margin-bottom: var(--s5); }
.masthead h1 { margin-top: var(--s4); font-size: var(--t-display); line-height: 1.04; }
.masthead .lede { margin-top: var(--s5); max-width: 36ch; }
.masthead .dates { margin-top: 28px; font-size: var(--t-small); color: var(--ink2); font-variant-numeric: tabular-nums; }
.masthead .when { margin-top: var(--s6); font-size: 15px; color: var(--ink2); }
/* Apple's badge as supplied: never recoloured or redrawn, at least 40 px high, clear space ≥ ¼ of its height. */
.store { margin-top: var(--s6); }
.store a { display: inline-block; }
.store img { display: block; height: 48px; width: auto; }
.store + .when { margin-top: var(--s4); }
/* An app page's head: the text, and beside it the app's main screen, whole. Under 780 px the screen
   sits under the text, still whole, narrower. */
.masthead--app .wrap { display: grid; grid-template-columns: minmax(0, 1fr) clamp(240px, 24vw, 300px); gap: var(--s8); align-items: center; }
.screen { margin: 0; }

/* --- split: a band's text beside its pictures --------------------------------- */
.split { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--s8); align-items: center; }
.split .points-title { margin-bottom: var(--s4); }
.split .lede { max-width: 34ch; }

/* --- points: short titled paragraphs in two columns ------------------------ */
.points-title { font-size: var(--t-section); line-height: 1.06; margin-bottom: var(--s6); }
.points { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6) var(--s7); }
.points--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.points > div { padding-top: 18px; border-top: 1px solid var(--line); }
.points h3 { font-size: var(--t-h3); line-height: 1.25; letter-spacing: -.01em; }
.points p { margin-top: var(--s2); color: var(--ink2); }
.points .tnum { margin-top: var(--s3); font-size: 15px; font-variant-numeric: tabular-nums; }
.points + .fine { margin-top: var(--s7); }

/* --- app icon: the app's own face. iOS shape: radius 22.37 % of the side ---- */
.icon { display: block; width: var(--icon, 64px); height: var(--icon, 64px); border-radius: 22.37%; }
.masthead .icon { --icon: 88px; margin-bottom: var(--s5); }

/* --- shots: real screens, light or dark with the visitor's appearance ------- */
/* One row scrolled sideways, like the App Store: three screens and the edge of the next. */
.shots { display: grid; grid-auto-flow: column; grid-auto-columns: calc((100% - 3 * var(--s6)) / 3.25); gap: var(--s6);
         overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; scrollbar-width: thin; scrollbar-color: var(--line) transparent;
         margin: 0 calc(-1 * var(--gutter)) 0 0; padding: 0 var(--gutter) var(--s4) 0; list-style: none; }
.shots li { scroll-snap-align: start; }
.shots figure { margin: 0; }
.shots img, .screen img { display: block; width: 100%; height: auto; border-radius: var(--r-card); border: 1px solid var(--line); background: var(--surface); }
.shots figcaption { margin-top: var(--s3); font-size: var(--t-small); color: var(--ink2); }
/* Apple Watch: the screen in Apple's bezel (its own transparent edge), smaller than the phone screens. */
.shots.shots--watch { grid-auto-columns: min(180px, 44%); }
.shots--watch img { border: 0; border-radius: 0; background: none; }

/* With a mouse (scripts/shots.js): the row drags, and under it sit ← → and a bar whose thumb shows
   where the row is; drag the thumb or click the bar. Touch screens swipe and never see the controls;
   without the script the row keeps the thin bar in the line colour. */
.shots-bar { display: none; }
@media (hover: hover) and (pointer: fine) {
  .shots[data-controls] { scrollbar-width: none; padding-bottom: 0; cursor: grab; }
  .shots[data-controls]::-webkit-scrollbar { display: none; }
  .shots.dragging { cursor: grabbing; user-select: none; }
  .shots-bar { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s5); }
  .shots-bar[hidden] { display: none; }
  .shots-bar button {
    display: grid; place-items: center; width: 40px; height: 40px; padding: 0;
    border: 1px solid var(--edge); border-radius: var(--r-pill); background: var(--surface); color: var(--ink);
    cursor: pointer; transition: opacity var(--d-change) var(--ease-exhale), background-color var(--d-touch) var(--ease-exhale);
  }
  .shots-bar button:hover:not(:disabled) { background: var(--accent-soft); }
  .shots-bar button:disabled { opacity: .35; cursor: default; }
  /* The bar: a 2 px line in a 24 px tall target; the thumb thickens under the pointer. */
  .shots-bar .track { position: relative; width: 160px; height: 24px; margin-left: var(--s4); cursor: pointer; }
  .shots-bar .track::before { content: ""; position: absolute; inset: 11px 0; border-radius: 1px; background: var(--line); }
  .shots-bar .thumb {
    position: absolute; top: 11px; height: 2px; border-radius: var(--r-pill); background: var(--ink2);
    cursor: grab; transition: top var(--d-touch) var(--ease-exhale), height var(--d-touch) var(--ease-exhale), background-color var(--d-touch) var(--ease-exhale);
  }
  .shots-bar .track:hover .thumb, .shots-bar .track.dragging .thumb { top: 9px; height: 6px; background: var(--ink); }
  .shots-bar .track.dragging, .shots-bar .track.dragging .thumb { cursor: grabbing; }
}

/* --- lift: a linked card answers the pointer -------------------------------------
   It rises 2 px and its edge darkens. Nothing moves on its own. */
.card, .app-card, .tile {
  transition: translate var(--d-touch) var(--ease-exhale), border-color var(--d-touch) var(--ease-exhale);
}
.card:hover, .app-card:hover { translate: 0 -2px; border-color: var(--edge); }
.tile:hover { translate: 0 -2px; }
.store a, .join button { transition: scale var(--d-touch) var(--ease-exhale), opacity var(--d-touch); }
.store a:active, .join button:active { scale: .97; }

/* --- post cards: blog index, an app's page --------------------------------------- */
/* Each card is one link: its title's link covers the card. Three across on desktop, one on a phone. */
.cards {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); gap: var(--s5);
}
.card {
  position: relative; display: flex; flex-direction: column; gap: var(--s3);
  padding: var(--s5); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card);
}
.card :is(h2, h3) { font-size: clamp(24px, 2.4vw, 28px); line-height: 1.12; letter-spacing: -.015em; }
.card :is(h2, h3) a { color: var(--ink); }
.card :is(h2, h3) a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.card :is(h2, h3) a:hover { text-decoration: none; }
.card :is(h2, h3) a:focus-visible { outline: none; }
.card:has(a:focus-visible) { outline: 2px solid var(--accent); outline-offset: 3px; }
.card > p:not(.kicker, .meta) { color: var(--ink2); }
.card .meta {
  margin-top: auto; padding-top: var(--s3); display: flex; align-items: center; gap: var(--s4);
  font-size: var(--t-small); color: var(--ink2);
}
.cards + .more { margin-top: var(--s5); font-size: var(--t-small); }

/* --- post tiles: the blog index -------------------------------------------------- */
/* Soft tiles without an outline: the diagram of what the post is about (PostFigure.astro) on the paper colour,
   then type and reading time, the title and its description. The first post spans the row, its diagram beside
   the text. Each tile is one link: its title's link covers the tile. */
.tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5); }
.tile { position: relative; display: flex; flex-direction: column; padding: var(--s6); background: var(--surface); border-radius: var(--r-card); }
.tile .fig { display: grid; place-items: center; aspect-ratio: 4 / 3; margin: calc(-1 * var(--s3)) calc(-1 * var(--s3)) var(--s5);
             background: var(--bg); border-radius: var(--r-small); }
.tile .kicker { margin-bottom: var(--s3); }
.tile h2 { font-size: 26px; line-height: 1.14; letter-spacing: -.015em; text-wrap: balance; }
.tile h2 a { color: var(--ink); }
.tile h2 a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.tile h2 a:hover { text-decoration: none; }
.tile h2 a:focus-visible { outline: none; }
.tile:has(a:focus-visible) { outline: 2px solid var(--accent); outline-offset: 3px; }
.tile p:not(.kicker) { margin-top: var(--s3); color: var(--ink2); }
.tile--wide { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s7); align-items: center; padding: var(--s7); }
.tile--wide .fig { order: 2; margin: 0; aspect-ratio: auto; padding: var(--s6); }
.tile--wide h2 { font-size: var(--t-section); line-height: 1.06; }
.tile--wide p:not(.kicker) { font-size: var(--t-lede); }
.blog-about { margin-top: var(--s7); }

/* Diagrams (PostFigure.astro): the fasting hours in ink on a line-coloured day, ticks for the hours. */
.diagram { display: block; overflow: visible; }
.diagram .d-off { fill: none; stroke: var(--line); stroke-width: 6; }
.diagram .d-on { fill: none; stroke: var(--ink); stroke-width: 6; stroke-linecap: round; }
.diagram .d-on--1 { stroke: var(--ink2); }
.diagram .d-on--2 { stroke: var(--ink3); }
.diagram .d-tick { stroke: var(--ink3); stroke-width: 1.2; }
.diagram .d-big { font: 400 34px/1 var(--serif); fill: var(--ink); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.diagram .d-mid { font: 400 18px var(--serif); fill: var(--ink); font-variant-numeric: tabular-nums; }
.diagram .d-small { font: 11px var(--sans); fill: var(--ink2); }
.diagram .d-bar { stroke: var(--ink); stroke-width: 8; stroke-linecap: round; }
.diagram .d-bar--far { stroke: var(--ink3); }
.diagram .d-ring { fill: none; stroke: var(--ink2); stroke-width: 1.5; }
.diagram .d-dot { fill: var(--ink); }

/* --- article: one blog post, a single reading column ------------------------ */
.article .wrap { padding-top: var(--s8); padding-bottom: var(--s9); }
.article .prose { max-width: var(--measure); }
/* A post's rail, left of the reading column (the .doc grid): its contents, then its app. It stays in view
   while the post scrolls. Phones have no rail: the post starts with its short answer and ends with its app. */
.rail { position: sticky; top: calc(var(--head-h) + var(--s6)); align-self: start; display: grid; gap: var(--s6); }
.article .body { grid-column: 2; }
.rail .index { position: static; }
/* The app beside a post: a small card in the app's theme, one link to the app's page. */
.app-card {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: center;
  padding: var(--s4); background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-small);
}
.app-card:hover { text-decoration: none; border-color: var(--edge); }
.app-card .icon { --icon: 40px; }
.app-card .name { font: 400 19px/1.15 var(--serif); letter-spacing: -.01em; }
.app-card .what { display: block; margin-top: 2px; font: 13px/1.35 var(--sans); letter-spacing: 0; color: var(--ink2); }
.app-card .go { grid-column: 1 / -1; font-size: var(--t-small); font-weight: 500; color: var(--accent); }
/* Posts are Markdown: no <section> wrappers, so each h2 opens a section with a rule. */
.article .prose > h2 { margin-top: 56px; padding-top: 22px; border-top: 1px solid var(--line); }
.article .prose > .note + h2, .article .prose > .fine + h2 { margin-top: 0; padding-top: 0; border-top: 0; }
.article .prose > .fine { margin-bottom: 40px; }
/* One real app screen in a post (src/lib/shots.mjs), linked to the app's page; the caption sits beside it. */
.prose .shot { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: var(--s5); align-items: center; margin: var(--s6) 0; }
.prose .shot a { display: block; text-decoration: none; border-radius: var(--r-card); }
.prose .shot img { display: block; width: 100%; height: auto; border-radius: var(--r-card); border: 1px solid var(--line); background: var(--surface); }
.prose .shot a:hover img { border-color: var(--edge); }
.prose .shot figcaption { font-size: var(--t-small); color: var(--ink2); }

/* --- app block: the call to action inside a post, in the app's theme -------- */
.app-block {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s4) 20px; align-items: center;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: var(--s5); margin: var(--s7) 0 0; max-width: var(--measure);
}
.app-block h2 { font-size: 28px; line-height: 1.1; }
.app-block p { margin-top: var(--s1); color: var(--ink2); }
.app-block .go { grid-column: 1 / -1; font-weight: 500; }

/* --- document pages: privacy, terms, help ---------------------------------- */
.doc .wrap {
  display: grid; grid-template-columns: 220px minmax(0, var(--measure));
  gap: 72px; padding-top: var(--s8); padding-bottom: var(--s9);
}
.index { position: sticky; top: calc(var(--head-h) + var(--s6)); align-self: start; }
.index ol { list-style: none; margin: var(--s4) 0 0; padding: 0; counter-reset: i; }
.index li { counter-increment: i; padding: 7px 0; border-top: 1px solid var(--hair); font-size: var(--t-small); line-height: 1.4; }
.index li::before {
  content: counter(i, decimal-leading-zero); display: inline-block; width: 28px;
  color: var(--ink3); font-variant-numeric: tabular-nums;
}
.index a { color: var(--ink2); transition: color var(--d-touch) var(--ease-exhale); }
/* The section being read (scripts/contents.js): its number and title in ink. */
.index a[aria-current] { color: var(--ink); }
.index li:has(> a[aria-current])::before { color: var(--ink); }

.prose { font-size: var(--t-prose); line-height: 1.6; }
.prose > section + section { margin-top: 56px; padding-top: 22px; border-top: 1px solid var(--line); }
.prose section { scroll-margin-top: var(--s5); }
.prose h2 { font-size: var(--t-h2); line-height: 1.05; margin-bottom: 20px; }
.prose h3 { font-size: var(--t-h3); line-height: 1.25; letter-spacing: -.01em; margin: var(--s6) 0 var(--s2); }
.prose h2 + h3 { margin-top: 0; }
/* Running text in ink: long reads stay easy on the eyes. ink2 is for captions, ledes and short notes. */
.prose p, .prose ul, .prose ol, .prose .table-wrap { margin: 0 0 14px; color: var(--ink); }
.prose strong { color: var(--ink); font-weight: 500; }
.prose ul, .prose ol { padding-left: 22px; }
.prose li { margin-bottom: 6px; padding-left: 2px; }
.prose li::marker { color: var(--ink3); }
.prose a { text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--accent) 35%, transparent); text-underline-offset: 3px; }

.note {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 22px var(--s5); margin-bottom: 56px;
}
.note p { color: var(--ink); }
.note p + p { margin-top: 10px; }

/* Claim: a sentence quoted from an app, then what each study found. Health sources. */
.claim { margin: 0 0 var(--s6); }
.claim blockquote {
  margin: 0 0 var(--s3); padding-left: var(--s4); border-left: 2px solid var(--accent);
  font-family: var(--serif); font-size: var(--t-lede); line-height: 1.45; color: var(--ink);
}
.claim blockquote p { margin: 0; color: var(--ink); }
.prose .claim ul { list-style: none; padding-left: 18px; }
.prose .claim li { font-size: var(--t-body); }
.prose .claim li a { color: var(--ink); font-weight: 500; }
.refs { font-size: var(--t-small); }
.refs li { scroll-margin-top: var(--s5); border-radius: 6px; }
.refs li:target { background: var(--accent-soft); }

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 15px; line-height: 1.45; }
th { font-size: var(--t-kicker); letter-spacing: .12em; text-transform: uppercase; font-weight: 400; color: var(--ink2); text-align: left; padding: 0 var(--s4) 10px 0; }
td { padding: var(--s3) var(--s4) var(--s3) 0; border-top: 1px solid var(--line); vertical-align: top; color: var(--ink2); }
td:first-child { color: var(--ink); }
.prose .table-wrap { margin-bottom: var(--s5); }

/* plans: what is free and what Pro adds, one row per feature. A mark is read out by its hidden word. */
.plans { max-width: 860px; }
.plans thead th { vertical-align: bottom; }
.plans thead th + th {
  text-transform: none; letter-spacing: -.01em; color: var(--ink);
  font: 400 var(--t-h3)/1.2 var(--serif);
}
.plans .price { display: block; margin-top: var(--s1); font: 400 var(--t-small)/1.4 var(--sans); color: var(--ink2); font-variant-numeric: tabular-nums; }
.plans td + td { width: 28%; color: var(--ink); }
.plans .yes { color: var(--accent); }
.plans .no { color: var(--ink3); }
.plans { margin-bottom: var(--s7); }
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* --- join: the waitlist form on an app page. One email, one platform, one button ---- */
.join { max-width: var(--measure); }
.join .lede { max-width: 40ch; color: var(--ink2); }
.join fieldset { margin: var(--s6) 0 0; padding: 0; border: 0; display: flex; gap: var(--s5); flex-wrap: wrap; align-items: center; }
.join legend { float: left; margin-right: var(--s2); padding: 0; }
.join fieldset label { display: inline-flex; align-items: center; gap: var(--s2); color: var(--ink); }
.join input[type="radio"] { width: 18px; height: 18px; margin: 0; accent-color: var(--accent); }
.join .row { display: flex; gap: var(--s3); align-items: flex-end; flex-wrap: wrap; margin-top: var(--s5); }
.join .field { display: grid; gap: var(--s2); flex: 1 1 260px; }
.join input[type="email"] {
  width: 100%; height: 52px; padding: 0 var(--s4); margin: 0;
  font: var(--t-prose)/1 var(--sans); color: var(--ink);
  background: var(--surface); border: 1px solid var(--edge); border-radius: var(--r-small);
}
.join input[type="email"]::placeholder { color: var(--ink2); }
.join button {
  height: 52px; padding: 0 26px; margin: 0; cursor: pointer;
  font: 500 var(--t-body)/1 var(--sans); color: var(--on-accent);
  background: var(--accent); border: 0; border-radius: var(--r-small);
  transition: opacity var(--d-touch);
}
.join button:hover { opacity: .88; }
.join .fine { margin-top: var(--s5); }
/* The honeypot: present for bots, absent for people and screen readers. */
.join .hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Small print under a page: disclaimers. */
.fine { font-size: 13px; line-height: 1.6; color: var(--ink2); max-width: 70ch; }

/* Text still waiting for the owner's input or a check in the app. Must stay loud. */
.ph {
  background: var(--ph-bg); color: var(--ph-ink);
  border-radius: 5px; padding: 1px 6px; font-weight: 500;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}

/* --- 404 ------------------------------------------------------------------- */
.lost { margin-top: var(--s4); font-size: var(--t-display); line-height: 1.04; }

/* --- home: a quiet poster ---------------------------------------------------- */
/* No overflow rule on .home: the body passes it to the window, which then cannot scroll when the poster is
   taller than the screen. The poster clips the ring itself. */
.home { min-height: 100vh; min-height: 100svh; display: flex; flex-direction: column; }
.poster { flex: 1; position: relative; display: flex; align-items: center; overflow: hidden; }
.poster .wrap { position: relative; z-index: 1; width: 100%; padding-top: var(--s7); padding-bottom: 72px; }
.poster h1 { font-size: var(--t-poster); line-height: .9; letter-spacing: -.045em; }
.poster .lede { margin-top: 28px; font-size: clamp(19px, 2vw, 24px); max-width: 22ch; }

/* The shelf: one row per app. The row carries the app's class, so its name and stripe wear
   the app's colours while the page stays in the brand shell. */
.shelf { margin-top: 56px; max-width: 460px; }
.shelf ul { list-style: none; margin: var(--s3) 0 0; padding: 0; }
.shelf li { border-top: 1px solid var(--line); }
.shelf li:last-child { border-bottom: 1px solid var(--line); }
.app {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
  column-gap: var(--s4); padding: 18px 0; min-height: 44px; color: var(--ink);
}
.app:hover { text-decoration: none; }
.app .icon { --icon: 52px; }
.app .name { font-family: var(--serif); font-size: 28px; line-height: 1.1; letter-spacing: -.02em; }
.app .what { display: block; margin-top: var(--s1); font-family: var(--sans); font-size: 15px; letter-spacing: 0; color: var(--ink2); }
.app .go { font-size: 20px; color: var(--accent); transition: transform var(--d-touch) var(--ease-exhale); }
.app:hover .go, .app:focus-visible .go { transform: translateX(4px); }
.shelf .more { margin-top: var(--s4); font-size: var(--t-small); color: var(--ink2); }
.shelf + .shelf { margin-top: var(--s7); }
/* A post row on home: same row, no icon. */
.app--post { grid-template-columns: minmax(0, 1fr) auto; }
.app--post .name { font-size: 24px; }

/* Home has no mark in its header (the poster is the name), only the nav. */
.home .head .wrap { justify-content: flex-end; }

/* The family mark: a bare ring and the "now" dot, cropped by the right edge like a label.
   Neutral ink only — an app's signature never appears in the brand mark. */
.loop { position: absolute; right: -14vw; top: 50%; width: min(78vw, 860px); height: auto; transform: translateY(-50%); color: var(--line); }
.loop .track { stroke: currentColor; }
.loop .arc { stroke: var(--ink2); }
.loop .dot { fill: var(--ink); }
.loop .halo { fill: var(--ink); opacity: .12; animation: breathe var(--d-breath) ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes breathe {
  0%, 100% { transform: scale(1); opacity: .14; }
  50% { transform: scale(1.6); opacity: .05; }
}
@media (prefers-reduced-motion: reduce) {
  .index a { transition: none; }
  .menu line { transition: none; }
  .loop .halo { animation: none; }
  .app .go { transition: none; }
  .shots { scroll-behavior: auto; }
  .card, .app-card, .tile, .store a, .join button { transition: none; }
  .card:hover, .app-card:hover, .tile:hover { translate: none; }
}

/* --- menu: a nav of several links on a narrow screen ------------------------- */
/* The links drop down under the header as a list, on the same blurred glass. The browser opens and
   closes it (popover): the button, Esc, a tap outside. Browsers without popovers wrap the row instead. */
@supports selector(:popover-open) {
  @media (max-width: 780px) {
    .menu { display: grid; margin-left: var(--s1); }
    .nav[popover] + .theme { margin-left: auto; }
    .nav[popover] {
      position: fixed; inset: var(--head-h) 0 auto; width: auto; margin: 0;
      flex-direction: column; gap: 0; padding: 0 var(--gutter) var(--s3); font-size: 17px;
      background: color-mix(in srgb, var(--bg) 92%, transparent);
      -webkit-backdrop-filter: blur(20px) saturate(1.4); backdrop-filter: blur(20px) saturate(1.4);
      box-shadow: 0 1px 0 var(--line), 0 24px 40px -24px rgb(0 0 0 / .25);
      transition: opacity var(--d-touch) var(--ease-exhale), translate var(--d-touch) var(--ease-exhale),
                  display var(--d-touch) allow-discrete, overlay var(--d-touch) allow-discrete;
    }
    .nav[popover]:not(:popover-open) { display: none; opacity: 0; translate: 0 -6px; }
    @starting-style { .nav[popover]:popover-open { opacity: 0; translate: 0 -6px; } }
    .nav[popover] a { margin: 0; padding: 14px 0; border-top: 1px solid var(--hair); }
    .nav[popover] a:first-child { border-top: 0; }
  }
  @media (max-width: 780px) and (prefers-reduced-motion: reduce) { .nav[popover] { transition: none; } }
}
@supports not selector(:popover-open) {
  @media (max-width: 780px) {
    .head .wrap { flex-wrap: wrap; height: auto; min-height: var(--head-h); padding-top: var(--s3); padding-bottom: var(--s3); }
    .nav { flex-wrap: wrap; gap: var(--s3) 16px; }
  }
}

/* --- narrow ---------------------------------------------------------------- */
@media (max-width: 780px) {
  :root { --gutter: 20px; --head-h: 56px; }
  .band { padding: 40px 0; }
  .mark { font-size: 22px; }
  .masthead { padding: 28px 0 44px; }
  .masthead--app .wrap, .split { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .masthead .screen { width: min(62%, 240px); }
  .rail { display: none; }
  .article .body { grid-column: auto; }
  .points, .points--3 { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .shots { grid-auto-columns: 68%; gap: var(--s4); }
  .tiles { grid-template-columns: minmax(0, 1fr); }
  .tile--wide { grid-template-columns: minmax(0, 1fr); gap: var(--s5); padding: var(--s6); }
  .tile--wide .fig { order: 0; }
  .prose .shot { grid-template-columns: min(240px, 72%); gap: var(--s3); }
  .article .wrap { padding-top: 40px; padding-bottom: var(--s8); }
  .doc .wrap { grid-template-columns: minmax(0, 1fr); gap: 40px; padding-top: 40px; padding-bottom: var(--s8); }
  .index { position: static; }
  .prose { font-size: var(--t-body); }
  .prose > section + section { margin-top: 44px; }
  .note { padding: 18px; margin-bottom: 44px; border-radius: var(--s4); }
  .foot .wrap { flex-direction: column; gap: 14px; }
  /* Above the name, so the dot never sits on text. */
  .loop { right: -30vw; width: 84vw; top: 0; transform: translateY(-22%); }
  .poster { align-items: flex-end; }
  .shelf { margin-top: 40px; }
}
