/* breathlab.org secondary pages
   Components shared by the generated blog/library pages and the hand-owned
   pillar, legal, roundup and Android pages. Loaded after site.css, which owns
   the tokens, chrome (nav, menu, footer), buttons, .card and .prose.
   GUTTER RULE still applies: .wrap* owns padding-inline, sections padding-block. */

/* ---------- widths ---------- */
.wrap-mid{max-width:calc(960px + 2 * var(--gutter));margin-inline:auto;padding-inline:var(--gutter)}
/* the roundup: one 1120px column shared by its hero, contents row, ranking
   cards, criteria and table, so every block has the same two edges */
.wrap-wide{max-width:calc(1120px + 2 * var(--gutter));margin-inline:auto;padding-inline:var(--gutter)}

/* ---------- page hero (light top, nav sits transparent over it) ---------- */
.page-hero{position:relative;padding-top:calc(var(--nav-h) + clamp(36px,5vw,64px));padding-bottom:clamp(32px,4.5vw,56px);isolation:isolate}
.page-hero::before{content:"";position:absolute;inset:0 0 -40% 0;z-index:-1;pointer-events:none;
  background:radial-gradient(60% 70% at 8% -10%,rgba(47,180,84,.16),transparent 65%)}
.page-hero h1{font-size:clamp(40px,5.5vw,72px);margin-top:18px;max-width:18ch;font-variation-settings:"opsz" 72}
.page-hero .lead{margin-top:clamp(16px,2vw,24px);max-width:58ch}
.page-hero.center{text-align:center}
.page-hero.center h1,.page-hero.center .lead{margin-inline:auto}
.page-hero.center .eyebrow{justify-content:center}
.page-hero.center .byline{justify-content:center}

/* byline row: date, author, reading time, last updated. Metadata reads in
   the body face, sentence case and muted; mono is kept for the eyebrow and
   the numeric readouts only */
.byline{--sep:33px;display:flex;flex-wrap:wrap;align-items:center;gap:10px 0;margin-top:clamp(22px,3vw,32px);
  margin-left:calc(-1 * var(--sep));clip-path:inset(-6px -6px -6px var(--sep));
  font-family:var(--font-body);font-size:14px;letter-spacing:0;text-transform:none;color:var(--muted);font-variant-numeric:tabular-nums}
.byline b{font-weight:500;color:var(--ink)}
.byline span{display:inline-flex;align-items:center;gap:.5em;white-space:nowrap}
/* every item carries a dot; the row starts --sep to the left of the column
   and clip-path hides that strip, so the dot that would open a line (the
   first, and the first of any wrapped line) is never seen and every line
   starts flush with the column */
.byline span::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--leaf);margin-inline:14px calc(14px - .5em);flex:none}
.page-hero.center .byline{margin-left:0;clip-path:none}
.page-hero.center .byline span:first-child::before{display:none}
@media (max-width:480px){.byline{font-size:13.5px}}
/* a one-sentence note under a hero (the roundup's data line) */
.hero-note{margin-top:clamp(22px,3vw,32px);font-size:14px;line-height:1.5;color:var(--muted);max-width:60ch;font-variant-numeric:tabular-nums}
.hero-note b{font-weight:500;color:var(--ink)}
/* small outlined pills for the feed links in an index byline */
.byline .pills{gap:8px}
.byline .pills::before{margin-inline:14px 6px}
.byline a.pill{display:inline-flex;align-items:center;gap:6px;min-height:30px;padding:5px 13px;border-radius:999px;
  border:1px solid var(--line-strong);color:var(--ink);font-size:13px;font-weight:500;letter-spacing:0;text-decoration:none;
  background:rgba(255,255,255,.4);transition:background .2s ease,border-color .2s ease,color .2s ease}
.byline a.pill:hover{background:var(--white);border-color:var(--ink);color:var(--ink)}
.byline a.pill svg{width:12px;height:12px;flex:none}

/* ---------- article layout: one centred measure, contents rail in the right gutter ---------- */
/* the measure is one column system for the whole page: the body sits in it,
   centred in the 1120px container, so the left and right margins are equal.
   The article and pillar heroes share the centre line but their title block
   may run to --title-measure (880px): a display title at 52 to 56px needs the
   room, or it stacks four deep and breaks a phrase mid-way. The compact hero
   (support, privacy, terms) has one-word titles and stays on the measure */
:root{--measure:680px;--title-measure:880px}
.article-hero .wrap-mid,.pillar-hero .wrap-mid{max-width:calc(var(--title-measure) + 2 * var(--gutter))}
.page-hero.compact .wrap-mid{max-width:calc(var(--measure) + 2 * var(--gutter))}
/* a title over ~30 characters (build-site.py adds .long) drops from 72px to
   the 52 to 56px band, gets the whole title block, and balances its lines so
   the last line is never a single word */
.page-hero h1.long{font-size:clamp(44px,4.2vw,56px);max-width:none;text-wrap:balance;font-variation-settings:"opsz" 56}
/* phones: the same 36px the article hero already uses for every title there */
@media (max-width:640px){.page-hero h1.long{font-size:36px}}
.article{padding-block:clamp(32px,5vw,64px) clamp(72px,9vw,128px)}
/* a hero with no cover (support, privacy, terms) ends on its byline; the
   gap to the rail is the cover's 48px, not the article's 120 */
.page-hero.compact{padding-bottom:clamp(16px,2vw,24px)}
.page-hero.compact+.article{padding-top:clamp(20px,2.5vw,32px)}
.article-grid{display:grid;grid-template-columns:minmax(0,1fr);row-gap:40px;
  max-width:calc(1120px + 2 * var(--gutter));margin-inline:auto;padding-inline:var(--gutter)}
.article-grid>.prose{grid-column:1;min-width:0}
.article-grid>.prose>h2:first-child{margin-top:0}
.article-grid>.article-foot{grid-column:1/-1}
@media (min-width:1100px){
  /* symmetric side columns either side of the measure: the measure is
     centred, the rail hangs in the RIGHT column, flush against the measure,
     and the left column stays empty (a rail on the left with nothing on the
     right read as the page listing to one side). The side columns bottom
     out at 120px, which still leaves the measure its full width at 1100
     (1020 inner, less 680 and two 44px gaps, is 126 a side) */
  .article-grid{grid-template-columns:minmax(120px,1fr) minmax(0,var(--measure)) minmax(120px,1fr);column-gap:44px;align-items:start}
  .article-grid>.prose,.article-grid>.article-foot{grid-column:2}
}

/* cover, the full width of the hero column */
.cover{position:relative;margin-top:clamp(28px,4vw,48px);isolation:isolate}
.cover::before{content:"";position:absolute;inset:12% -3% -8% -3%;z-index:-1;border-radius:50%;
  background:radial-gradient(50% 50% at 50% 60%,rgba(47,180,84,.22),transparent 70%);filter:blur(28px)}
.cover img{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:var(--r-lg);box-shadow:var(--shadow-soft);background:var(--dew-2)}
.cover figcaption{margin-top:14px;font-size:13.5px;line-height:1.5;color:var(--muted);max-width:70ch}

/* table of contents. Its base form is a row of outlined chips (the byline
   pill) that scrolls sideways and bleeds to the viewport edges, the active
   chip filled. The strip carries a full gutter of trailing padding past the
   gutter, and its right edge fades over 64px, so a chip that runs under the
   edge dissolves rather than being cut mid-word (a 36px fade was too short
   to read as one). The roundup keeps the row at every width (.toc-row); the
   article pages turn it into the sticky rail from 1100px */
.toc{line-height:1.4}
.toc-title{font-size:13px;font-weight:500;color:var(--muted-2);margin-bottom:10px}
.toc ol{list-style:none;margin:0;display:flex;flex-wrap:nowrap;gap:8px;overflow-x:auto;scrollbar-width:none;
  margin-inline:calc(-1 * var(--gutter));padding-inline:var(--gutter) calc(2 * var(--gutter));padding-block:2px;
  scroll-padding-inline:var(--gutter);-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 64px),transparent);
  mask-image:linear-gradient(90deg,#000 calc(100% - 64px),transparent)}
.toc ol::-webkit-scrollbar{display:none}
.toc li{margin:0;flex:none}
.toc a{display:inline-flex;align-items:center;min-height:30px;padding:5px 13px;margin:0;border-radius:999px;
  border:1px solid var(--line-strong);background:rgba(255,255,255,.4);color:var(--ink);text-decoration:none;
  font-size:13px;font-weight:500;letter-spacing:0;white-space:nowrap;
  transition:background .2s ease,border-color .2s ease,color .2s ease}
.toc a:hover{background:var(--white);border-color:var(--ink)}
.toc a.is-active{background:var(--ink);border-color:var(--ink);color:var(--white)}
/* the roundup's contents row sits between the hero and the first heading;
   the hero has no cover, so the article starts closer to it */
.toc-row{margin-bottom:clamp(28px,4vw,44px)}
.article.roundup{padding-top:clamp(20px,2.5vw,32px)}
@media (min-width:1100px){
  /* the rail: 15px in the full ink so the entries read at a glance (14px
     in the second ink read as low contrast); the active entry is one weight
     up on a leaf tick, and the title one step darker than the chip row's */
  .toc:not(.toc-row){position:sticky;top:calc(var(--nav-h) + 28px);grid-column:3;grid-row:1;justify-self:start;width:100%;max-width:180px;font-size:15px}
  .toc:not(.toc-row) .toc-title{margin-bottom:14px;color:var(--muted)}
  .toc:not(.toc-row) ol{display:block;overflow:visible;margin-inline:0;padding:0;border-left:1px solid var(--line-strong);
    -webkit-mask-image:none;mask-image:none}
  .toc:not(.toc-row) a{display:block;min-height:0;padding:6px 0 6px 16px;margin-left:-1px;border:0;border-left:1px solid transparent;
    border-radius:0;background:none;color:var(--ink);font-size:15px;font-weight:400;white-space:normal;
    transition:color .25s ease,border-color .25s ease,padding-left .3s var(--ease-out)}
  .toc:not(.toc-row) a:hover{color:var(--ink);background:none;border-color:transparent}
  .toc:not(.toc-row) a.is-active{color:var(--ink);font-weight:500;background:none;border-left-color:var(--leaf);padding-left:20px}
}

/* display headings: no ff / fi ligatures at display size ("Different").
   site.css sets this on h1 to h4; repeated here for the headings pages.css
   owns so the rule travels with them. The f in Bricolage Grotesque still
   touches a following f by design (its crossbar overhangs), which no
   ligature setting changes. */
.page-hero h1,.prose h2,.post-card h2,.post-card h3{font-variant-ligatures:no-common-ligatures}

/* prose refinements on top of site.css */
.prose h2[id],.prose h3[id]{scroll-margin-top:calc(var(--nav-h) + 24px)}
.prose h2{font-size:clamp(28px,3vw,38px)}
.prose blockquote{border:0;padding:6px 0 6px 30px;position:relative;font-family:var(--font-display);font-weight:500;
  font-size:clamp(22px,2.2vw,28px);letter-spacing:-.02em;line-height:1.3;color:var(--ink);margin-block:1.6em}
.prose blockquote::before{content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:3px;background:linear-gradient(var(--leaf),var(--violet))}
.prose blockquote p{font-size:inherit}
.prose table{width:100%;border-collapse:collapse;font-size:15px}
.prose th,.prose td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:top}
.prose th{font-size:13px;color:var(--muted);font-weight:500}
.prose .note{font-size:15.5px}

/* buttons inside prose keep their own colour and no underline (.prose a
   would otherwise paint them green and underlined) */
.prose a.btn{text-decoration:none}
.prose a.btn-primary{color:#fff}
.prose .dark a.btn-primary{color:var(--ink)}
.prose a.btn-leaf{color:#04150A}
.prose a.btn-ghost{color:inherit}

/* soft callout card */
.note{background:rgba(255,255,255,.62);border:1px solid rgba(255,255,255,.85);border-radius:var(--r-md);padding:18px 22px;
  box-shadow:var(--shadow-soft);color:var(--ink-2);font-size:15.5px;line-height:1.6}
.note b{color:var(--ink)}
.note.warn{border-left:3px solid var(--gold)}

/* ---------- CTA band: dark glass card ---------- */
.cta-card{position:relative;overflow:hidden;border-radius:var(--r-xl);padding:clamp(32px,5vw,56px);
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:28px 40px;align-items:center;
  box-shadow:var(--shadow-deep);isolation:isolate}
.cta-card::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(55% 80% at 100% 0%,rgba(47,180,84,.30),transparent 65%),
    radial-gradient(40% 60% at 0% 100%,rgba(124,108,240,.22),transparent 70%),
    linear-gradient(180deg,var(--deep-2),var(--deep))}
.cta-card .grain{z-index:0}
.cta-card>:not(.grain){position:relative;z-index:1}
/* eyebrow to headline is a fixed 24px wherever the card sits. Inside .prose
   the site-wide `.prose h3{margin-top:1.8em}` would otherwise open a ~75px
   gap above the headline, so the margin is pinned here with the same
   specificity the prose rule has */
.cta-card .eyebrow{display:flex;margin-bottom:0}
.cta-card h3,.prose .cta-card h3{font-size:clamp(26px,3.2vw,42px);line-height:1.05;letter-spacing:-.03em;max-width:18ch;color:#fff;margin-top:24px}
.cta-card p,.prose .cta-card p{color:var(--on-dark-muted);margin-top:12px;max-width:44ch;font-size:16.5px}
.cta-card .cta-actions{display:flex;flex-direction:column;align-items:flex-start;gap:12px}
.cta-card .cta-actions .mono{font-family:var(--font-body);font-size:13px;letter-spacing:0;color:var(--on-dark-muted)}
@media (max-width:720px){.cta-card{grid-template-columns:1fr}}
/* in the measure (the prose column, or the article foot that shares it) the
   card is 42rem wide at most: stack it */
.prose .cta-card,.article-foot .cta-card{grid-template-columns:1fr;gap:28px}
.prose .cta-card .cta-actions,.article-foot .cta-card .cta-actions{flex-direction:row;align-items:center;gap:20px;flex-wrap:wrap}
.prose .cta-card h3,.article-foot .cta-card h3{max-width:22ch}

/* ---------- index pages: post cards ---------- */
.post-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(18px,2.5vw,28px)}
.post-card{display:flex;flex-direction:column;overflow:hidden;text-decoration:none;color:inherit;padding:0;min-width:0}
.post-card .media{aspect-ratio:16/9;overflow:hidden;background:linear-gradient(135deg,var(--deep-2),var(--deep-3));position:relative;flex:none}
.post-card .media img{width:100%;height:100%;object-fit:cover;transition:transform 1.1s var(--ease-out)}
.post-card:hover .media img{transform:scale(1.045)}
.post-card .media .glyph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--font-display);font-weight:500;font-size:clamp(64px,8vw,120px);letter-spacing:-.05em;color:rgba(255,255,255,.08);user-select:none}
.post-card .media .glyph::after{content:"";position:absolute;inset:0;background:radial-gradient(50% 60% at 70% 30%,rgba(47,180,84,.35),transparent 70%)}
.post-card .body{padding:clamp(22px,2.6vw,30px) clamp(22px,2.6vw,30px) clamp(24px,2.8vw,32px);display:flex;flex-direction:column;gap:12px;flex:1}
.post-card time{font-size:13.5px;color:var(--muted);font-variant-numeric:tabular-nums}
.post-card h2{font-size:clamp(22px,2vw,27px);line-height:1.12;letter-spacing:-.025em;font-variation-settings:"opsz" 36}
.post-card p{color:var(--muted);font-size:15.5px;line-height:1.55}
.post-card .read{margin-top:auto;padding-top:8px;color:var(--leaf-deep)}
.post-card.feature{grid-column:1/-1;display:grid;grid-template-columns:1.15fr 1fr}
.post-card.feature .media{aspect-ratio:auto;min-height:360px;height:100%}
.post-card.feature .body{padding:clamp(28px,4vw,52px);justify-content:center;gap:16px}
.post-card.feature h2{font-size:clamp(28px,3.4vw,46px);font-variation-settings:"opsz" 72}
.post-card.feature p{font-size:17px}
.post-card.feature .read{margin-top:12px}
@media (max-width:820px){
  .post-grid{grid-template-columns:1fr}
  .post-card.feature{display:flex}
  .post-card.feature .media{aspect-ratio:16/9;min-height:0;height:auto}
}
/* a shelf with one or two pieces: full-width rows, cover left, text right,
   instead of a lone card at the left of an empty grid */
.post-list{display:grid;grid-template-columns:1fr;gap:clamp(14px,2vw,20px)}
.post-card.row{display:grid;grid-template-columns:320px minmax(0,1fr);align-items:center}
.post-card.row .media{aspect-ratio:auto;align-self:stretch;height:auto;min-height:180px}
.post-card.row .media img{position:absolute;inset:0}
.post-card.row .body{padding:clamp(22px,2.8vw,32px) clamp(24px,3vw,36px);gap:10px;justify-content:center}
.post-card.row h2{font-size:clamp(22px,2.2vw,28px);max-width:26ch}
.post-card.row p{max-width:62ch}
.post-card.row .read{margin-top:4px;padding-top:0}
@media (max-width:820px){.post-card.row{grid-template-columns:260px minmax(0,1fr)}.post-card.row .media{min-height:146px}}
@media (max-width:640px){
  .post-card.row{display:flex;flex-direction:column;align-items:stretch}
  .post-card.row .media{aspect-ratio:16/9;min-height:0}
  .post-card.row .media img{position:static}
}
.empty{color:var(--muted);font-size:17px;padding:48px 0;text-align:center;border:1px dashed var(--line-strong);border-radius:var(--r-lg)}

/* ---------- vertical stepper (technique steps) ---------- */
.stepper{list-style:none;padding:0;margin:0;counter-reset:step}
.stepper li{counter-increment:step;position:relative;display:grid;grid-template-columns:48px minmax(0,1fr);column-gap:22px;padding-bottom:clamp(26px,3vw,36px)}
.stepper li:last-child{padding-bottom:0}
.stepper li::before{content:counter(step,decimal-leading-zero);grid-column:1;justify-self:center;
  font-family:var(--font-mono);font-size:13.5px;font-weight:500;letter-spacing:.02em;color:var(--leaf-deep);
  width:48px;height:48px;border-radius:50%;border:1.5px solid var(--leaf);background:var(--white);
  display:flex;align-items:center;justify-content:center;position:relative;z-index:1;
  box-shadow:0 0 0 6px rgba(47,180,84,.10),0 6px 18px -8px var(--leaf-glow)}
.stepper li::after{content:"";position:absolute;left:23.5px;top:52px;bottom:4px;width:1px;
  background:linear-gradient(var(--leaf),rgba(47,180,84,.15))}
.stepper li:last-child::after{display:none}
.stepper li>div{padding-top:9px}
.stepper b{display:block;font-family:var(--font-display);font-weight:500;font-size:clamp(20px,2vw,24px);letter-spacing:-.02em;line-height:1.15;color:var(--ink);margin-bottom:6px}
.stepper li>div{color:var(--ink-2);font-size:17px;line-height:1.6}

/* two-line ratio figure used on the pillar pages */
.ratio{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-block:8px 0}
.ratio>div{padding:18px 16px;border-radius:var(--r-md);background:rgba(255,255,255,.62);border:1px solid rgba(255,255,255,.85);box-shadow:var(--shadow-soft);text-align:center}
.ratio .n{font-family:var(--font-mono);font-size:48px;font-weight:500;letter-spacing:-.04em;line-height:1;color:var(--ink)}
.ratio .l{font-size:14px;color:var(--ink);margin-top:10px}
.ratio>div:nth-child(2) .n{color:var(--leaf-deep)}

/* ---------- FAQ: native details, animated ---------- */
.faq{border-top:1px solid var(--line-strong)}
.faq details{border-bottom:1px solid var(--line-strong)}
.faq summary{list-style:none;cursor:pointer;display:flex;justify-content:space-between;align-items:center;gap:24px;padding:22px 0;
  font-family:var(--font-display);font-weight:500;font-size:clamp(18px,1.7vw,21px);letter-spacing:-.015em;line-height:1.25;color:var(--ink);
  transition:color .2s ease}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--leaf-deep)}
.faq summary::after{content:"";flex:none;width:30px;height:30px;border-radius:50%;border:1px solid var(--line-strong);color:var(--ink);
  background:linear-gradient(currentColor,currentColor) center/12px 1.5px no-repeat,linear-gradient(currentColor,currentColor) center/1.5px 12px no-repeat;
  transition:transform .5s var(--ease-out),background-color .25s ease,border-color .25s ease,color .25s ease}
.faq details[open]>summary::after{transform:rotate(135deg);background-color:var(--leaf);border-color:var(--leaf);color:#04150A}
.faq-body{display:grid;grid-template-rows:1fr;opacity:1;transition:grid-template-rows .5s var(--ease-out),opacity .4s ease}
.faq-body>div{overflow:hidden;min-height:0}
.faq-body p{padding-bottom:26px;color:var(--ink-2);max-width:64ch;font-size:16.5px;line-height:1.65}
.faq-body p+p{margin-top:-10px}
.faq-body a{color:var(--leaf-deep);text-decoration:underline;text-underline-offset:3px;text-decoration-color:rgba(29,122,56,.4)}
@starting-style{.faq details[open] .faq-body{grid-template-rows:0fr;opacity:0}}
.faq details.is-closing .faq-body{grid-template-rows:0fr;opacity:0}
@media (prefers-reduced-motion:reduce){.faq-body,.faq summary::after{transition:none}}

/* ---------- roundup: ranked rows ---------- */
/* every card has one skeleton at every width: rank, name, a row of fact
   chips, the verdict, then the store link as the last line. Phones stack
   the five; from 600px the rank takes its own column; from 1100px the chips
   move into a right-hand column so the 1120px card carries its width */
.rank-list{display:grid;gap:14px}
.rank-row{display:grid;grid-template-columns:1fr;row-gap:12px;padding:clamp(22px,3vw,30px) clamp(22px,3vw,32px);
  grid-template-areas:"rank" "name" "facts" "text" "link"}
.rank-row .rank{grid-area:rank;font-family:var(--font-mono);font-size:26px;font-weight:500;letter-spacing:-.05em;line-height:1;color:var(--leaf-deep);padding-top:2px;font-variant-numeric:tabular-nums}
.rank-row.ours{border-color:rgba(47,180,84,.55);background:rgba(255,255,255,.8);
  box-shadow:0 1px 2px rgba(11,20,16,.05),0 30px 70px -30px rgba(47,180,84,.45)}
.rank-row h3{grid-area:name;font-size:clamp(20px,1.7vw,22px);margin:0;line-height:1.15}
.rank-row .ours-badge{font-size:11.5px;letter-spacing:.01em;color:#04150A;background:var(--leaf);border-radius:999px;padding:3px 9px;margin-left:10px;vertical-align:middle;font-weight:600;font-family:var(--font-body);display:inline-block;line-height:1.3;position:relative;top:-2px}
.facts{grid-area:facts;display:flex;flex-wrap:wrap;gap:6px;font-size:13px;color:var(--muted)}
.facts span{border:1px solid var(--line-strong);border-radius:999px;padding:3px 10px;white-space:nowrap;line-height:1.4}
.facts b{font-weight:500;color:var(--ink)}
/* .prose p:first-of-type would otherwise size the verdict at 19px */
.rank-row p,.prose .rank-row p{grid-area:text;color:var(--ink-2);font-size:17px;line-height:1.6;margin:0;max-width:70ch}
.rank-row p b{color:var(--ink);font-weight:600}
/* the store link: the site's arrow link, one size down, on the card's last line */
.rank-row .store{grid-area:link;justify-self:start;font-size:14px;color:var(--leaf-deep);margin-top:2px}
.prose .rank-row .store{text-decoration:none}
.rank-row .store svg{width:14px;height:14px}
@media (min-width:600px){
  .rank-row{grid-template-columns:56px minmax(0,1fr);column-gap:20px;
    grid-template-areas:"rank name" "rank facts" "rank text" "rank link"}
  .rank-row .rank{font-size:clamp(28px,3vw,40px)}
}
@media (min-width:1100px){
  .rank-row{grid-template-columns:56px minmax(0,1fr) 300px;column-gap:20px;
    grid-template-areas:"rank name facts" "rank text facts" "rank link facts";grid-template-rows:auto 1fr auto}
  .facts{flex-direction:column;align-items:flex-start;gap:8px;padding:4px 0 0 20px}
  .rank-row .store{margin-top:6px}
}

.cmp-wrap{position:relative;border-radius:var(--r-lg);background:rgba(255,255,255,.66);border:1px solid rgba(255,255,255,.8);box-shadow:var(--shadow-soft);isolation:isolate}
.cmp-wrap::after{content:"";position:absolute;top:0;right:0;bottom:0;width:72px;z-index:2;pointer-events:none;
  border-radius:0 var(--r-lg) var(--r-lg) 0;opacity:0;transition:opacity .25s ease;
  background:linear-gradient(90deg,rgba(243,246,242,0),rgba(243,246,242,.92) 60%,var(--dew))}
.cmp-wrap.is-scrollable::after{opacity:1}
.cmp-wrap.is-scrollable.at-end::after{opacity:0}
.cmp-hint{display:none;align-items:center;gap:8px;padding:12px 16px 0;font-size:13px;color:var(--muted)}
.cmp-hint::after{content:"";flex:none;width:7px;height:7px;margin-left:2px;transform:rotate(-45deg);
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor}
.prose .cmp-hint{margin:0}
@media (min-width:720px) and (max-width:900px){
  .cmp-wrap.is-scrollable .cmp-hint,.no-js .cmp-wrap .cmp-hint{display:flex}
}
.cmp{overflow-x:auto;border-radius:var(--r-lg);-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}
.cmp table{border-collapse:separate;border-spacing:0;width:100%;min-width:820px;font-size:15px}
.cmp th,.cmp td{padding:13px 16px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}
.cmp th{font-size:13px;color:var(--muted);font-weight:500;background:rgba(11,20,16,.03)}
.cmp td:first-child,.cmp td:nth-child(3),.cmp td:nth-child(4),.cmp td:nth-child(5){font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:14px}
.cmp td:nth-child(2){min-width:200px}
@media (min-width:1100px){.cmp td:nth-child(2){white-space:nowrap}}
.cmp tr:last-child td{border-bottom:0}
.cmp tr.oursrow td{background:rgba(47,180,84,.08)}
/* the rank and the app name stay put while the rest scrolls. At rest the
   sticky cells are transparent, so a row reads as one row: the same tint
   edge to edge, and only a 1px hairline after the name column. They take an
   opaque ground only once the table has actually scrolled (pages.js sets
   .is-scrolled), because then other cells slide under them. That ground is
   the frame's own colour (the .66 white over --dew resolves to #FBFCFB),
   not --dew, so nothing changes hue when the scroll starts */
.cmp th:nth-child(1),.cmp td:nth-child(1){position:sticky;left:0;z-index:1;width:48px;min-width:48px}
.cmp th:nth-child(2),.cmp td:nth-child(2){position:sticky;left:48px;z-index:1;
  box-shadow:1px 0 0 var(--line);transition:box-shadow .25s ease}
.cmp th:nth-child(1),.cmp th:nth-child(2){z-index:3}
.cmp-wrap.is-scrolled .cmp td:nth-child(1),.cmp-wrap.is-scrolled .cmp td:nth-child(2){background:#FBFCFB}
.cmp-wrap.is-scrolled .cmp th:nth-child(1),.cmp-wrap.is-scrolled .cmp th:nth-child(2){background:#F4F5F4}
.cmp-wrap.is-scrolled .cmp tr.oursrow td:nth-child(1),.cmp-wrap.is-scrolled .cmp tr.oursrow td:nth-child(2){background:#EBF6EE}
.cmp-wrap.is-scrolled .cmp th:nth-child(2),.cmp-wrap.is-scrolled .cmp td:nth-child(2){box-shadow:1px 0 0 var(--line),10px 0 16px -10px rgba(11,20,16,.28)}
/* phones: the same data as one card per app, a two-column definition list
   under a rank + name header; the table is not rendered below 720px */
.cmp-cards{display:grid;gap:10px}
@media (min-width:720px){.cmp-cards{display:none}}
@media (max-width:719px){.cmp-wrap{display:none}}
.cmp-card{padding:18px 20px 20px;border-radius:var(--r-md);background:rgba(255,255,255,.62);border:1px solid rgba(255,255,255,.85);box-shadow:var(--shadow-soft)}
.cmp-card.ours{background:rgba(47,180,84,.08);border-color:rgba(47,180,84,.45)}
.cmp-card-head{display:flex;align-items:baseline;gap:12px;padding-bottom:12px;border-bottom:1px solid var(--line)}
.cmp-card-head .rank{font-family:var(--font-mono);font-size:13px;font-weight:500;color:var(--leaf-deep);font-variant-numeric:tabular-nums;flex:none}
.cmp-card-head b{font-family:var(--font-display);font-weight:500;font-size:18px;letter-spacing:-.015em;line-height:1.2;color:var(--ink)}
.cmp-card dl{display:grid;grid-template-columns:104px minmax(0,1fr);column-gap:14px;row-gap:9px;margin:12px 0 0;padding:0}
.cmp-card dt{font-size:13px;color:var(--muted);font-weight:500;padding-top:1px}
.cmp-card dd{margin:0;font-size:15px;line-height:1.45;color:var(--ink-2)}
/* every value in the body face; the numbers only take tabular figures */
.cmp-card dd.num{font-variant-numeric:tabular-nums;color:var(--ink)}
/* the criteria: ruled text columns, no boxes, so uneven copy lengths rag
   naturally instead of leaving a card half empty. One column on phones,
   two on tablets, four from 1100px; the fifth spans its own row at every
   width, since five abreast at 1440 was too tight a measure. The columns
   end at different heights, so the list closes on one shared bottom rule */
.method{list-style:none;padding:0 0 24px;margin:0;display:grid;grid-template-columns:1fr;gap:20px;counter-reset:m;border-bottom:1px solid var(--line-strong)}
.method li{counter-increment:m;padding-top:16px;border-top:1px solid var(--line-strong);font-size:15px;color:var(--ink-2);line-height:1.55}
.method li::before{content:counter(m,decimal-leading-zero);display:block;font-family:var(--font-mono);font-size:11.5px;letter-spacing:.14em;color:var(--leaf-deep);margin-bottom:10px}
.prose .method li+li{margin-top:0}
.method li b{display:block;color:var(--ink);font-family:var(--font-display);font-weight:500;font-size:18px;letter-spacing:-.015em;margin-bottom:6px}
@media (min-width:600px){.method{grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}.method li:last-child{grid-column:1/-1;max-width:60ch}
  /* abreast, each item is a subgrid of its three rows (number, heading,
     body), so the bodies of a row start on one baseline whether or not a
     heading wraps, with no fixed reservation under the ones that do not */
  .method li{display:grid;grid-template-rows:subgrid;grid-row:span 3;row-gap:0;align-content:start}
  .method li b{line-height:1.25}}
@media (min-width:1100px){.method{grid-template-columns:repeat(5,minmax(0,1fr));gap:24px}.method li:last-child{grid-column:auto;max-width:none}}

/* ---------- section heading inside long pages ---------- */
.sec{padding-block:clamp(40px,6vw,72px)}
.sec>.wrap-mid>h2,.sec-head h2{font-size:clamp(30px,3.4vw,44px);margin:12px 0 clamp(20px,3vw,32px)}
.sec-head{display:flex;flex-direction:column;align-items:flex-start;margin-bottom:clamp(22px,3vw,36px)}
.sec-head h2{margin-bottom:0}
.sec-head p{color:var(--muted);margin-top:12px;max-width:56ch}

/* generic reveal stagger helper */
.stagger>*{--d:0ms}
.stagger>*:nth-child(2){--d:80ms}.stagger>*:nth-child(3){--d:160ms}.stagger>*:nth-child(4){--d:240ms}
.stagger>*:nth-child(5){--d:320ms}.stagger>*:nth-child(6){--d:400ms}

/* ---------- chrome overrides for the secondary pages ---------- */
/* mobile menu foot: the label reads in the body face, the CTA is the white
   pill (.menu carries .dark so site.css paints .btn-primary white) */
.menu-foot .mono{font-family:var(--font-body);font-size:13px;letter-spacing:.06em;text-transform:uppercase}
/* light pages: the scrolled nav needs a denser ground so a photo behind the
   blur does not smear through it */
.nav.is-scrolled:not(.on-dark){background:rgba(243,246,242,.86)}

/* the support page's primary button: lighter fill and a 1px lift, quick */
.contact .btn-primary{transition:transform .15s var(--ease-out),box-shadow .15s var(--ease-out),background .15s ease}
.contact .btn-primary:hover{background:var(--ink-2);transform:translateY(-1px);box-shadow:0 1px 0 rgba(255,255,255,.12) inset,0 14px 32px -12px rgba(11,20,16,.5)}
.contact .btn-primary:active{transform:scale(.97)}

/* body copy on phones: 18px everywhere, including the opening paragraph */
@media (max-width:640px){
  .prose{font-size:18px;line-height:1.7}
  .prose p:first-of-type{font-size:18px}
}


/* "ff" in a display title: build-site.py wraps the FIRST f of the pair
   only, so the tracking parts the two crossbars without opening a gap
   before the letter after them. .035em is the smallest value that
   separates them at 72px; .05em already reads as "Dif ferent". */
.ff{letter-spacing:.035em}
