/* Yado site, a sibling of hina.day and mole.fit: warm paper, near-black ink and
   one editorial serif, with tokens, the type ladder and the 84px section pause
   taken from Hina's stylesheet, which measured them off mole.fit.

   The product pictures carry their own wallpaper and the app's own window
   corners, so nothing here draws a frame around them. The page stays light down
   to the footer, which is the family's dark band in the app's night tide. Chinese
   gets its own Source Han Serif subset (build_fonts.py), since iOS has no Chinese
   serif and fell through to PingFang. */
@font-face {
  font-family: "Yado Serif SC";
  src: local("Source Han Serif SC"), local("Noto Serif CJK SC"),
       url("/fonts/yado-serif-sc-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+201C-201D, U+2026, U+2E80-2EFF, U+3000-303F, U+3400-4DBF, U+4E00-9FFF, U+F900-FAFF, U+FE30-FE4F, U+FF00-FFEF;
}
@font-face {
  font-family: "Yado Serif SC";
  src: local("Source Han Serif SC SemiBold"), local("Noto Serif CJK SC SemiBold"),
       url("/fonts/yado-serif-sc-semibold.woff2") format("woff2");
  font-weight: 500 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+201C-201D, U+2026, U+2E80-2EFF, U+3000-303F, U+3400-4DBF, U+4E00-9FFF, U+F900-FAFF, U+FE30-FE4F, U+FF00-FFEF;
}
/* 宿 rides inside this stylesheet as its one glyph, copied from
   fonts/yado-mark.woff2 that build_fonts.py cuts. Fetched on its own it arrived after first paint,
   so on Hina the hero and footer drew Songti first and then swapped (2026-10-25). */
@font-face {
  font-family: "Yado Mark";
  src: url("data:font/woff2;base64,d09GMk9UVE8AAAWcAA8AAAAACdAAAAVKAAIAxAAAAAAAAAAAAAAAAAAAAAAAAAAAGYFeDYdiGyAcgRwGYA4IADQBNgIkAwgEBgWEAAcgFyQYCBvLCFGUUE4YwI+EzO0azSbl3FTaditIbwuvfs3/0mnvS3IAcIMIG1uOFZBCVB9QnekPuAOgFqg6LpqbUVA8//7Gzn2fSCAGGiQM0c2imzoJnW5MNmuh/8n+8hmcauMLLAAd7ulO3l4dpu79dyx1vHXAB3zQF2mlcO9pGEsEA9K61QIcowgGRKMyNkC9UeTs/CYQwIGNhcR+rW3uRvJ9fWEGpc8FeRqlL65OIjkEBT7A773zJRWl7ACAQBImUqxtWyQe5MKDjyOotwtSqxXof0j8OG+zdWL/LSkWWVvQZtWmqk+EALJEeHgTgKwFUoFCgWPBafVc7ZIXFGt3Vco9mgyAn1WoB+shJ13C9FDSwwQ9XNQDpMP1w2shzvMh9p6msESUjeGhgGG4ROql7nqlS8zuoEu0XusJ+wKx4+a6DzjJh/LO9bOczDXVkw0zIkfKSokRFGbxS0HDSO/gtsaRyJ2w2mHZSWPYeWV8RShTV6TiUtkPrXfy40KGcz5Mdd9eUcfsPXHVkqYt3CDJXLtiPVdZv2ll3VxZ5eoOMnOPWgW6VP91p9zdbDlMpcEiazfc/75FgOa7BFAgFogYEpyYmz49IgkSIdvUmm5DEslD9MxfqIeYMHIpkvEIkPfw561v0d9uYEvo2giY3GxUXVWQLjdAtt2zUFmDX50od2WESlLov5ueYTkvfusaoN6wtLW8v6gdk3yYm52anSR3rzqi5b9kXARg+g9EAqmmLpU3Mc39It5X39vR1Y+ZoBxUWV2Qmih3dRsVJGelJWfeyRVv6K4dqBoq+5ObmZqF6W3iKJLknOAf+wK/+vzhVdYrnP2sLbGqqL64oTdxDbOE4Nt7T6+9fpb7Xby7fLqjoaE4MScpI91uSzw+DtChC1iRkp2VmKucLU4FaSP6W/Cn8FcR5tUdWcciX783PWuNyrghsRI3QmRpQBWmRUYib/+letzxvfZK4vXnT68zX+Kcly2JFUW4pqSm5+8SZinC9/efX3/7POe7eGf5ZHt9fXFiTmJGuu2meEICYKvDv/l/8n8VYjLIHhYZI1vOfQyTj1FBGTAH1xX8YXlL1XBxBzsL5mVBMr0mojnwCA6G6rfwKRUCVhE04P93ka1jEbpFTPVxWMcTIKX3Msbku4hmazDV16ca5voSuV96m3t7OockGM8cVFnVj7GFcFe1rrdmoGK4/E/O1ZZwgxBy9NSZS+yZ3TkvPULcatFr96/v7pYPCOAkRBian+QdSCS6YcCE2TluY36DzcXmYnOxudjczbn1OVvYKloZPC5tnQwBK0xm/SARds08AzdK+YC7iRrYsWNv43SwdULvsav6DsT2PalMIHyrH0ATP59uyEw2IJQESCwH6KpYK9tQfn0knyHOGX9AOiis+UpCCV8AA9JhTN1xLEAE+BCRniJhSAIqDf0Ng6Jnl65AeNjzT+nN7mPuxf8dRPEfwI9XoXViYD9476/zU3vP+nuEKruk4/AHOP8QpIOuXUCk91P75yFaPLSDCLA3SESDI4BtMHNJrG2uwM1DrqjT+40SjmvSn7CD7KRnBZcwmZmYDHlSnpspG1PBQjNBxsSzWbJkTqE0GbuaTcXF35vKTDMrTYJkzCrFEhumk2yRbMEKmQVTS6NawrTiZsmYOF00yxaYyeKk2h3H1ONUTFfdBhVWTLeqJvz2pGUzuAWZUqVLl6VIhWqV2hRxE1nJSFukcFP1ehKuVKOXnFyktPdm1pRGG80Ss6t9JYQMszpYZBY3TUa1WsnWyHVw5NZlbdsrKJK0GjdkqqcJdB66jFWcXsG2aQZIxxMRYgE=") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
  unicode-range: U+5BBF;
}
:root {
  --parchment:    #f5f4ed;
  --ivory:        #faf9f5;
  --warm-sand:    #e8e6dc;

  /* 苍蓝 from the 526 Chinese traditional colours, the deep end of the app's
     night tide; provisional until the maintainer picks from rendered candidates. */
  --brand:        #134857;
  --brand-light:  #1F5869;
  --brand-tint:   #EDF1F0;

  --near-black:   #363433;
  --dark-warm:    #3d3d3a;
  --olive:        #504e49;
  --stone:        #6b6a64;

  --line:         #d8d5c8;
  --line-faint:   #edebe1;
  --border-card:  color-mix(in srgb, #f1eee5 70%, var(--line));


  /* The app's night tide ground, closing the page as each family site closes on its own dark. */
  --yado-dark:    #0F1317;
  --detail-ground: #1A1F25;
  --foot-ink:     #f4f2ec;
  --feature-media-width: 430px;

  --serif: Charter, Georgia, "Yado Serif SC", "Songti SC", serif;

  /* One pause between the hero, every top-level section, and the footer.
     It has to beat the 24px head-to-content gap by a wide margin, or a section
     head reads as the tail of the section above it. */
  --section-gap: 84px;
  --page-inset: 24px;
  --nav-outset: 14px;
  --page: min(992px, calc(100vw - 2 * var(--page-inset)));
  /* Four text sizes, set by role (maintainer 2026-10-23). The hero wordmark is a
     drawn mark and keeps its own size. */
  /* Lines are half a point on 2x screens; a 0.5px line on a 1x screen rounds to 1px
     or disappears, so 1x keeps 1px. */
  --line-width: 1px;
  --text-small: 13px;
  --text-body: 16px;
  --text-title: 21px;
  --text-display: 32px;
  --body-copy: var(--text-body);
  --body-leading: 1.6;
  --shot-bg: #141318;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html {
  /* Below a short page's footer the canvas shows the footer's dark, not parchment. */
  min-height: 100%;
  background: linear-gradient(var(--parchment) 50%, var(--yado-dark) 50%);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  /* Nav anchors glide to their section, as on pake.run and kaku.fun. */
  scroll-behavior: smooth;
}
body {
  font-family: var(--serif);
  color: var(--near-black);
  background: var(--parchment);
  line-height: var(--body-leading);
  font-size: var(--body-copy);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* Every line fills the column, as on mole.fit (maintainer 2026-10-25): no
   pretty, balance, strict breaking or glued tails, which all wrapped phone lines
   early. A comma or full stop that does not fit hangs at the edge (WebKit). */
html[lang^="zh"] body { hanging-punctuation: allow-end; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; height: auto; display: block; }

:focus-visible {
  outline: 2px solid var(--brand-light);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 8px;
  z-index: 100;
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--brand);
  color: var(--ivory);
  font-size: var(--text-small);
}
.skip:focus { left: 24px; }

/* margin-inline, not the margin shorthand: `margin: 0 auto` also sets
   margin-bottom, and a class beats the `section` element selector whatever the
   source order, so every section gap collapsed to 0 and --section-gap was
   dead code. */
.wrap { width: var(--page); margin-inline: auto; }

/* Nav: Mole's current pill, a quiet translucent track with a hairline border
   and no drop shadow (~/www/mole-mac/site/styles.css, .site-nav). */
.nav-wrap {
  position: sticky;
  top: 16px;
  z-index: 60;
  width: calc(var(--page) + 2 * var(--nav-outset));
  margin: 16px auto 0;
}
/* A full-bleed parchment veil behind the pill, solid across it and fading out
   below, so text scrolling under the sticky nav is covered instead of showing
   through the glass. */
.nav-wrap::before {
  content: "";
  position: absolute;
  left: 50%;
  top: -40px;
  transform: translateX(-50%);
  width: 100vw;
  height: calc(100% + 40px + 22px);
  background: linear-gradient(180deg, var(--parchment) 0%, var(--parchment) 72%, transparent 100%);
  z-index: -1;
  pointer-events: none;
}
.site-nav {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 52px;
  padding: 8px calc(var(--nav-outset) - 1px);
  border-radius: 999px;
  background: rgba(250, 249, 245, 0.8);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: var(--line-width) solid var(--line-faint);
  color: var(--near-black);
}
.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: none;
}
.brand img { width: 24px; height: 24px; }
.brand span {
  font-size: var(--text-body);
  font-weight: 600;
  letter-spacing: 0.1px;
  line-height: 1;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: 10px;
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--olive);
}
.nav-links a { line-height: 1; white-space: nowrap; padding: 8px 11px; border-radius: 999px; }
@media (hover: hover) {
  .nav-links a:hover { color: var(--near-black); background: var(--line-faint); }
}
.nav-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
  margin-left: auto;
}
.lang { position: relative; flex: none; font-size: var(--text-small); }
.lang summary { display: flex; align-items: center; gap: 6px; min-height: 34px; padding: 0 4px; list-style: none; cursor: pointer; color: var(--stone); }
.lang summary::-webkit-details-marker { display: none; }
.lang summary::after { content: ""; width: 4px; height: 4px; margin: -2px 2px 0 0; border-right: 1px solid currentColor; border-bottom: 1px solid currentColor; transform: rotate(45deg); }
.lang[open] summary { color: var(--brand); }
.lang[open] summary::after { transform: rotate(225deg); margin-top: 2px; }
.lang-menu { position: absolute; top: calc(100% + 8px); right: 0; width: 150px; padding: 6px; border: var(--line-width) solid var(--line-faint); border-radius: 12px; background: var(--ivory); box-shadow: 0 8px 24px rgba(20,19,19,.08); }
.lang-menu a { display: flex; align-items: center; min-height: 36px; padding: 6px 10px; border-radius: 6px; color: var(--olive); }
.lang-menu a.is-on { background: var(--line-faint); color: var(--near-black); }
@media (hover: hover) { .lang summary:hover, .lang-menu a:hover { color: var(--brand); } }
.nav-download {
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 16px;
  border-radius: 999px;
  background: var(--brand);
  color: var(--ivory);
  font-size: var(--text-small);
  font-weight: 500;
}
@media (hover: hover) {
  .nav-download:hover { background: var(--brand-light); }
}

/* Hero follows Mole: wordmark, product sentence, facts, then actions. */
.hero { padding: 60px 0 0; margin-bottom: var(--section-gap); }
/* The wordmark is ink, not gold: in the brand color the biggest type on the
   page read as loud next to the buttons (maintainer 2026-10-18). */
.hero h1 {
  margin: 0 0 40px;
  font-size: 96px;
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: -1.4px;
  color: var(--near-black);
}
.hero h1 .cn-orbit { position: relative; display: inline-block; margin-left: 18px; }
.hero h1 .cn {
  display: inline-block;
  font-family: "Yado Mark", "Yado Serif SC", "Songti TC", serif;
  font-weight: 400;
  letter-spacing: 0;
}
/* One small dot skims over 宿 the way a swallow skims under the eaves, swooping
   low in the middle and rising at each end; each family site keeps its own path. */
@property --mark-orbit {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
.hero h1 .cn-orbit::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 5px;
  height: 5px;
  margin: -2.5px 0 0 -2.5px;
  border-radius: 50%;
  background: var(--brand);
  transform: translate(calc(sin(var(--mark-orbit)) * 0.62em), calc(-0.5em - sin(var(--mark-orbit)) * sin(var(--mark-orbit)) * 0.16em));
  animation: mark-orbit 9s linear infinite;
  pointer-events: none;
}
@keyframes mark-orbit {
  to { --mark-orbit: 360deg; }
}
/* Wide tracking belongs to the Chinese couplet; spread Latin reads dated */
.poem {
  margin: 0 0 14px;
  font-size: var(--text-body);
  letter-spacing: 0.3px;
  color: var(--stone);
}
html[lang^="zh"] .poem { letter-spacing: 0.12em; }
.tagline {
  margin: 0 0 16px;
  max-width: none;
  font-size: var(--text-title);
  line-height: 1.4;
  color: var(--olive);
}
/* Han runs a full em against Charter's half-em x-height, so 21px reads
   oversized in Chinese; Mole steps it down the same way */
html[lang^="zh"] .tagline { font-size: var(--text-body); line-height: 1.6; }
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
/* the separator hangs off the item before it, not the one after: when the row
   wraps, a trailing dot stays at the end of the first line instead of opening
   the second one */
.trust {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 0;
  margin: 0 0 24px;
  font-size: var(--text-small);
  color: var(--stone);
}
.trust span:not(:last-child)::after {
  content: "·";
  margin: 0 10px;
  color: var(--line);
}
.cta { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.btn {
  display: inline-flex;
  font-family: inherit;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 158px;
  padding: 12px 28px;
  border-radius: 999px;
  font-size: var(--text-body);
  font-weight: 500;
  line-height: 1.55;
  border: var(--line-width) solid transparent;
  transition: background 0.15s ease, transform 0.12s ease;
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--brand); color: var(--ivory); letter-spacing: 0.2px; }
.btn-ghost { border-color: var(--line); color: var(--near-black); background: var(--ivory); }
@media (hover: hover) {
  .btn-primary:hover { background: var(--brand-light); }
  .btn-ghost:hover { background: var(--warm-sand); }
}
/* Until Yado ships, the download is a grey button that says so on hover, focus
   or tap, as pake.run's did before its release; there is no link to follow. */
.download-pending { position: relative; display: inline-flex; }
.btn-pending, .btn-pending:hover {
  color: var(--stone);
  background: var(--warm-sand);
  border-color: var(--line);
  cursor: default;
  transform: none;
}
.download-hint {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  padding: 6px 10px;
  border-radius: 8px;
  background: var(--near-black);
  color: var(--ivory);
  font-size: var(--text-small);
  line-height: 1.5;
  white-space: nowrap;
  visibility: hidden;
}
.download-pending:hover .download-hint,
.download-pending:focus-within .download-hint { visibility: visible; }

/* Sections: title and description rhythm, no eyebrow above the title */
section { margin-bottom: var(--section-gap); }
#see, #does, #faq { scroll-margin-top: 90px; }
.section-head { margin-bottom: 24px; }
.section-title {
  margin: 0;
  font-size: var(--text-display);
  font-weight: 500;
  color: var(--dark-warm);
  line-height: 1.2;
  letter-spacing: -0.3px;
}
html[lang^="zh"] .section-title { letter-spacing: 0; }
.section-lede {
  margin: 12px 0 0;
  color: var(--olive);
  font-size: var(--text-body);
  line-height: 1.55;
}

/* Screenshots share a fixed wallpaper and shadow-free window bounds. */
.gallery { display: grid; grid-template-columns: minmax(0, 1fr) max-content; column-gap: 24px; align-items: start; margin: 0; }
.gallery-frame {
  --shot-width: 2574; --shot-height: 1862;
  grid-column: 1 / -1; position: relative;
  aspect-ratio: var(--shot-width) / var(--shot-height);
  line-height: 0; touch-action: pan-y;
  background: var(--parchment);
}
.gallery-panel { position: absolute; inset: 0; margin: 0; }
.gallery-panel img { display: block; width: 100%; height: 100%; object-fit: contain; cursor: pointer; }
.gallery-panel[hidden], .gallery-tabs[hidden] { display: none; }
.gallery-caption { grid-column: 1; grid-row: 2; display: flex; align-items: baseline; gap: 14px; min-height: 48px; padding-top: 12px; font-size: var(--text-small); color: var(--olive); }
.gallery-caption .title { flex: none; margin: 0; color: var(--brand); font-size: var(--text-body); font-weight: 500; }
.gallery-caption .line { margin: 0; }
.gallery-tabs { grid-column: 2; grid-row: 2; display: flex; flex-wrap: nowrap; gap: 6px; justify-content: flex-end; min-width: 0; max-width: 100%; overflow-x: auto; scrollbar-width: none; margin-top: 12px; }
.gallery-tabs::-webkit-scrollbar { display: none; }
.gallery-tabs button { flex: none; white-space: nowrap; appearance: none; border: var(--line-width) solid var(--line-faint); border-radius: 999px; background: transparent; color: var(--olive); font: 13px/1 var(--serif); padding: 8px; cursor: pointer; }
.gallery-tabs button[aria-selected="true"] { background: var(--brand); border-color: var(--brand); color: var(--ivory); }
.gallery-tabs button:focus-visible { outline: 2px solid currentColor; outline-offset: -4px; }
@media (hover: hover) { .gallery-tabs button:not([aria-selected="true"]):hover { color: var(--brand); border-color: var(--line); } }
/* Without JavaScript the tab switcher cannot run, so the noscript copy shows
   every screenshot instead of one static overview. */
html:not(.js) .gallery { display: none; }
.gallery-noscript { display: grid; gap: 20px; margin-top: 8px; }
.gallery-noscript figure { margin: 0; }
.gallery-noscript img { display: block; width: 100%; height: auto; border-radius: 14px; }
.gallery-noscript figcaption { margin-top: 8px; font-size: var(--text-small); color: var(--olive); }
.gallery-caption[aria-live] { min-height: 48px; }
@media (max-width: 880px) {
  .gallery { grid-template-columns: minmax(0, 1fr); }
  .gallery-tabs { grid-column: 1; width: max-content; justify-self: end; justify-content: flex-start; }
  .gallery-caption { grid-row: 3; min-height: 36px; padding-top: 8px; }
}

/* Product details, each beside a small drawn page of the app. */
.fcards { margin-top: 8px; }
.fcard {
  display: grid;
  grid-template-columns: minmax(0, var(--feature-media-width)) minmax(0, 1fr);
  align-items: center;
  gap: 32px 48px;
  padding: 28px 0;
}
.fcard:nth-child(even) { grid-template-columns: minmax(0, 1fr) minmax(0, var(--feature-media-width)); }
.fcard:nth-child(even) .fcard-media { order: 2; }
.fcard-media {
  margin: 0;
  position: relative;
  overflow: hidden;
  border-radius: 12px;
  background: var(--detail-ground);
  aspect-ratio: 2.2;
  display: grid;
  place-items: center;
}
/* Each card draws a small page of the app in its own type, at a size that reads at
   the card's width, straight on the card's ground with no box around it. One unit,
   --k, is 1px at the desktop card's 430px and shrinks with a narrower card. */
.fcard-media.mock { container-type: inline-size; }
.mock .m {
  --k: 1px;
  --m-ink: rgba(237, 236, 238, 0.94);
  --m-ink-2: rgba(237, 236, 238, 0.68);
  --m-ink-3: rgba(237, 236, 238, 0.56);
  --m-fill: rgba(237, 236, 238, 0.08);
  --m-sand: #D9C29C;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", "Helvetica Neue", sans-serif;
  font-size: calc(13 * var(--k));
  line-height: 1.35;
  color: var(--m-ink);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(12 * var(--k));
}
@supports (width: 1cqw) { .mock .m { --k: calc(100cqw / 430); } }
.mock .m p { margin: 0; }
.m-2 { color: var(--m-ink-2); }
.m-strong { font-weight: 600; }
.m-row { display: flex; align-items: center; gap: calc(8 * var(--k)); }
.m-pill { display: inline-flex; align-items: center; height: calc(28 * var(--k)); padding: 0 calc(16 * var(--k)); border-radius: 999px; background: var(--m-fill); font-size: calc(12 * var(--k)); font-weight: 600; color: var(--m-ink-2); }
.m-danger { color: #FF7B7B; }
.m-tick { flex: none; display: grid; place-items: center; width: calc(16 * var(--k)); height: calc(16 * var(--k)); border-radius: calc(4 * var(--k)); background: var(--m-sand); }
.m-tick::after { content: ""; width: calc(7 * var(--k)); height: calc(4 * var(--k)); border: solid #1A1F25; border-width: 0 0 calc(1.6 * var(--k)) calc(1.6 * var(--k)); transform: translateY(calc(-1 * var(--k))) rotate(-45deg); }
.m-box { flex: none; width: calc(16 * var(--k)); height: calc(16 * var(--k)); border-radius: calc(4 * var(--k)); box-shadow: inset 0 0 0 calc(1.2 * var(--k)) var(--m-ink-3); }
.m-thumbs { display: flex; gap: calc(8 * var(--k)); }
.m-thumbs + div { text-align: center; }
.m-thumb { position: relative; width: calc(64 * var(--k)); height: calc(64 * var(--k)); border-radius: calc(8 * var(--k)); background: center / cover; }
.m-thumb .m-tick { position: absolute; right: calc(5 * var(--k)); bottom: calc(5 * var(--k)); border-radius: 50%; }
.m-title { font-size: calc(15 * var(--k)); font-weight: 600; }
.m-pair { display: grid; grid-template-columns: repeat(2, calc(168 * var(--k))); gap: calc(14 * var(--k)); }
.m-pair img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: calc(8 * var(--k)); }
.m-pair .m-row { justify-content: space-between; margin-top: calc(8 * var(--k)); font-size: calc(12 * var(--k)); }
.m-list { width: calc(360 * var(--k)); display: grid; gap: calc(10 * var(--k)); }
.m-list .m-row { gap: calc(12 * var(--k)); }
.m-list img { width: calc(36 * var(--k)); height: calc(36 * var(--k)); border-radius: calc(8 * var(--k)); }
.m-list .m-name { flex: 1; min-width: 0; display: grid; gap: calc(2 * var(--k)); }
.m-list .m-name span:last-child { font-size: calc(12 * var(--k)); color: var(--m-ink-2); white-space: nowrap; }
.m-phones { display: flex; gap: calc(40 * var(--k)); }
.m-phones figure { margin: 0; display: grid; justify-items: center; gap: calc(6 * var(--k)); font-size: calc(12 * var(--k)); color: var(--m-ink-2); }
.m-phones img { display: block; height: calc(150 * var(--k)); width: auto; }
.m-panel { width: calc(360 * var(--k)); display: grid; gap: calc(10 * var(--k)); }
.m-panel .m-detail { font-size: calc(12 * var(--k)); color: var(--m-ink-2); margin-top: calc(-6 * var(--k)); }
.m-dot { width: calc(6 * var(--k)); height: calc(6 * var(--k)); border-radius: 50%; background: currentColor; }
.m-bar { display: flex; gap: calc(3 * var(--k)); height: calc(10 * var(--k)); }
.m-bar i { border-radius: calc(5 * var(--k)); }
.m-legend { display: flex; flex-wrap: wrap; gap: calc(6 * var(--k)) calc(16 * var(--k)); font-size: calc(12 * var(--k)); color: var(--m-ink-2); }
.m-legend span { display: inline-flex; align-items: center; gap: calc(6 * var(--k)); white-space: nowrap; }
.m-legend b { font-weight: 500; color: var(--m-ink); }
.m-facts { display: grid; grid-template-columns: repeat(2, auto); justify-content: start; gap: calc(12 * var(--k)) calc(40 * var(--k)); margin-top: calc(4 * var(--k)); }
.m-facts div { display: grid; gap: calc(2 * var(--k)); }
.m-facts span { font-size: calc(12 * var(--k)); color: var(--m-ink-2); }
.m-facts b { font-size: calc(16 * var(--k)); font-weight: 600; }
.fcard-body { min-width: 0; }
.fcard-body h3 {
  margin: 0 0 12px;
  font-size: var(--text-title);
  font-weight: 500;
  line-height: 1.3;
  color: var(--dark-warm);
}
.fcard-body p {
  margin: 0;
  font-size: var(--text-body);
  line-height: 1.65;
  color: var(--olive);
}
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Links read by colour alone, as on mole.fit (maintainer 2026-10-20: the
   underlines on the blog were ugly). This selector also outranks
   `.article-card-item a`, which is how every blog card once got underlined. */
.legal a:not(.btn) { color: var(--brand); }

/* FAQ: Mole's collapsed rows, a thin plus that turns into an x */
.faq { border-top: var(--line-width) solid var(--line-faint); interpolate-size: allow-keywords; }
.faq-item { border-bottom: var(--line-width) solid var(--line-faint); padding: 20px 0; }
.faq-item > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  cursor: pointer;
  list-style: none;
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item h3 {
  margin: 0;
  font-size: var(--text-body);
  font-weight: 500;
  line-height: 1.35;
  color: var(--dark-warm);
}
.faq-chevron {
  position: relative;
  flex: none;
  width: 15px;
  height: 15px;
  margin-right: 10px;
  transition: transform 0.25s ease-out;
}
.faq-item[open] .faq-chevron { transform: rotate(135deg); }
.faq-chevron::before,
.faq-chevron::after {
  content: "";
  position: absolute;
  /* Whole pixels: a 1.4px bar centred with translate(-50%) landed on a
     fractional row, so on 1x and 1.5x screens one plus drew heavier than the
     next. The bar now sits on row 7 of the 15px box and turns about its centre. */
  top: 7px;
  left: 0;
  width: 15px;
  height: 1px;
  background: var(--stone);
}
.faq-chevron::after { transform: rotate(90deg); }
@media (hover: hover) {
  .faq-item > summary:hover h3 { color: var(--near-black); }
  .faq-item > summary:hover .faq-chevron::before,
  .faq-item > summary:hover .faq-chevron::after { background: var(--brand-light); }
}
.faq-item::details-content {
  height: 0;
  overflow: clip;
  opacity: 0;
  transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.26s ease, content-visibility 0.3s allow-discrete;
}
.faq-item[open]::details-content { height: auto; opacity: 1; }
.faq-answer {
  /* Padding, not margin: the open/close transition animates the height of
     ::details-content, and margins sit outside it, so they used to snap 12px
     in on the first frame and 12px out on the last. */
  margin: 0;
  padding: 12px 0 4px;
  font-size: var(--text-body);
  line-height: 1.6;
  color: var(--olive);
}
.faq-answer a { color: var(--brand); }
.faq-answer code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--text-small);
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--line-faint);
  color: var(--near-black);
}

/* Author contact under the FAQ, the same block as mole.fit's (2026-10-20).
   The X and GitHub counts are static: update them together with mole.fit's. */
.contact { margin-top: 48px; text-align: left; }
.contact-heading { display: flex; align-items: center; gap: 12px; }
.contact-author { display: block; flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%; object-fit: cover; }
.contact .contact-title { margin: 0; padding: 0; font-family: var(--serif); font-size: var(--text-title); font-weight: 500; line-height: 1.2; color: var(--near-black); transform: translateY(1.5px); }
.contact .contact-sub { margin: 8px 0 0; padding: 0; font-family: var(--serif); font-size: var(--text-body); line-height: 1.55; color: var(--olive); }
.contact-sub a { color: var(--brand); text-decoration: none; }
.contact-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 24px; }
.contact-card {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 18px 20px;
  border: var(--line-width) solid var(--border-card, var(--line));
  border-radius: 14px;
  background: linear-gradient(180deg, var(--parchment) 0%, var(--ivory) 100%);
  color: inherit;
  text-decoration: none;
  transition: border-color 0.18s ease-out;
}
.contact-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.contact-channel {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--ivory);
  border: var(--line-width) solid var(--line);
  color: var(--near-black);
}
.contact-glyph { width: 22px; height: 22px; transition: opacity 0.18s ease; }
.contact-avatar { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 0.18s ease; }
.contact-meta { display: flex; flex-direction: column; min-width: 0; }
.contact-head b { font-family: var(--ui, var(--serif)); font-size: var(--text-small); font-weight: 600; line-height: 1.3; color: var(--near-black); }
.contact-handle { font-family: var(--ui, var(--serif)); font-size: var(--text-small); line-height: 1.3; color: var(--stone); }
.contact-stat {
  margin-left: auto;
  flex: 0 0 auto;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--brand-tint);
  color: var(--brand);
  font-family: var(--mono, ui-monospace, "SF Mono", Menlo, monospace);
  font-size: var(--text-small);
  font-weight: 700;
  white-space: nowrap;
}
.contact .contact-desc { margin: 4px 0 0; padding: 0; font-family: var(--serif); font-size: var(--text-small); line-height: 1.55; color: var(--olive); }
@media (hover: hover) {
  .contact-card:hover { border-color: var(--line); }
  .contact-card:hover .contact-glyph { opacity: 0; }
  .contact-card:hover .contact-avatar { opacity: 1; }
  .contact-sub a:hover { color: var(--brand-light); }
}
.contact-card:active { border-color: var(--line); background: linear-gradient(180deg, var(--ivory) 0%, var(--parchment) 100%); }
@media (prefers-reduced-motion: reduce) { .contact-glyph, .contact-avatar { transition: none; } }
@media (max-width: 560px) { .contact-cards { grid-template-columns: 1fr; } }
@media (max-width: 340px) {
  .contact-head { display: grid; grid-template-columns: 44px minmax(0, 1fr); }
  .contact-channel { grid-column: 1; grid-row: 1 / span 2; }
  .contact-meta { grid-column: 2; grid-row: 1; }
  .contact-stat { grid-column: 2; grid-row: 2; margin-left: 0; justify-self: start; }
}

/* Chinese prose runs looser than Latin: a full-em Han line at 1.6 reads packed.
   Mole sets its CJK body at 1.75 for the same reason. */
html[lang^="zh"] {
  --body-leading: 1.75;
  /* The Chinese face leads so its marks win; Latin still falls to Charter. */
  --serif: "Yado Serif SC", Charter, Georgia, "Songti SC", serif;
}
:is(.faq-answer, .legal p, .legal li) { font-size: var(--body-copy); line-height: var(--body-leading); }
html[lang^="zh"] .fcard-body p { line-height: var(--body-leading); }
/* Leads 1.6 and long reading (articles, legal pages) 1.8, as on mole.fit. */
html[lang^="zh"] .section-lede { line-height: 1.6; }
html[lang^="zh"] :is(.legal p, .legal li) { line-height: 1.8; }

/* Legal pages */
/* The article keeps .wrap's centred page column so the title lines up with the
   nav, and its text fills that column like mole.fit's legal pages (maintainer
   2026-10-21; it was capped at 660px). */
.legal { padding: 56px 0 80px; }
/* A file path is one unbreakable word with nowrap, and at 320px
   a long Application Support path pushed the page sideways */
.legal code { white-space: normal; overflow-wrap: anywhere; }
.legal h1 { margin: 0 0 8px; font-size: var(--text-display); font-weight: 500; line-height: 1.2; letter-spacing: -0.3px; }
html[lang^="zh"] .legal h1 { letter-spacing: 0; }
.legal .meta { color: var(--stone); font-size: var(--text-small); margin-bottom: 36px; }
.legal .cta { margin-top: 28px; }
.legal h2 { margin: 32px 0 8px; font-size: var(--text-body); font-weight: 500; color: var(--dark-warm); }
.legal p, .legal li { color: var(--olive); font-size: var(--text-body); line-height: 1.7; }
.legal ul { padding-left: 1.2em; }
/* Privacy tables: a quiet two-column reference, not a data dashboard. */
.legal table {
  width: 100%;
  margin: 4px 0 24px;
  border-collapse: collapse;
  font-size: var(--text-small);
  line-height: 1.6;
  color: var(--olive);
}
.legal th, .legal td {
  padding: 10px 12px;
  text-align: left;
  vertical-align: top;
  border-bottom: var(--line-width) solid var(--line-faint);
}
.legal thead th {
  padding-top: 0;
  color: var(--stone);
  font-size: var(--text-small);
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
html[lang^="zh"] .legal thead th { letter-spacing: 0; }
.legal tbody th {
  width: 28%;
  color: var(--dark-warm);
  font-weight: 500;
  white-space: nowrap;
}
.legal td code { white-space: normal; overflow-wrap: anywhere; }
@media (max-width: 600px) {
  .legal table { font-size: var(--text-small); }
  .legal th, .legal td { padding: 8px; }
  .legal tbody th { width: 32%; white-space: normal; }
}

/* Footer: mole.fit's dark band in Yado's night tide, the same text steps as
   Mole's footer (white name, 92% titles, 68% links, 62% secondary). */
.foot-band {
  background: var(--yado-dark);
  color: color-mix(in srgb, var(--foot-ink) 62%, transparent);
  margin-top: var(--section-gap);
}
.foot {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 24px;
  padding: 60px 0 48px;
  font-size: var(--text-small);
}
.foot-brand { max-width: 22em; }
.foot-brand .name {
  margin: 0;
  color: #fff;
  font-size: var(--text-title);
  font-weight: 500;
  line-height: 1.1;
}
/* The family mark, as Mole · 鼴, Kaku · 書 and Pake · 殼 set theirs. */
.foot-mark { font-family: "Yado Mark", "Yado Serif SC", "Songti TC", serif; font-weight: 400; }
/* One line on what Yado does; languages switch only in the nav. */
.foot-sub { margin: 10px 0 0; font-size: var(--text-small); line-height: 1.5; }
.foot-links { display: flex; gap: 44px; }
.foot-links div { display: grid; gap: 12px; align-content: start; }
/* Small, quiet column titles in both languages. */
.foot-links b {
  margin-bottom: 2px;
  color: color-mix(in srgb, #fff 92%, transparent);
  font-size: var(--text-small);
  font-weight: 500;
  letter-spacing: 0.2px;
}
html[lang^="zh"] .foot-links b { letter-spacing: 0.6px; }
.foot a { color: color-mix(in srgb, var(--foot-ink) 68%, transparent); }
@media (hover: hover) {
  .foot a:hover { color: #fff; }
}

@media (max-width: 880px) {
  :root { --page-inset: 28px; --section-gap: 72px; }
  .hero { padding-top: 40px; }
  .hero h1 { font-size: 64px; letter-spacing: -1px; }
  .tagline { font-size: var(--text-body); }
  .section-title { font-size: var(--text-title); }
  .gallery-caption { gap: 0; }
  /* Tablets keep the desktop zigzag with the picture at 46% of the row: the
     fixed 430px picture left a 234px text column at 768, and the old stacked
     430px column sat centred under left-aligned heads with wide empty sides. */
  .fcard { grid-template-columns: minmax(0, 46fr) minmax(0, 54fr); gap: 20px 32px; padding: 24px 0; }
  .fcard:nth-child(even) { grid-template-columns: minmax(0, 54fr) minmax(0, 46fr); }
  .fcard-body h3 { font-size: var(--text-title); margin-bottom: 10px; }
}

@media (max-width: 720px) {
  .fcard { column-gap: 24px; }
  .foot { flex-direction: column; }
  /* Stacked under the brand, the columns share the full width as on mole.fit;
     at their natural widths they huddled left of an empty half (OPPO Pad mini). */
  .foot-links { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px 16px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .btn, .faq-chevron, .faq-item::details-content { transition: none; }
  .btn:active { transform: none; }
  .hero h1 .cn-orbit::after { animation: none; }
}

/* Tablets keep the section links. With the download pill showing, Android's
   Noto Serif (none of these fonts ship Charter) needs 610px, and 664px while
   the language name shows, so the links go below 620 and the name below 680;
   OPPO Pad mini portrait (640) keeps all four links beside the globe. */
@media (max-width: 620px) {
  .nav-links { display: none; }
}
@media (max-width: 680px) {
  .lang summary { gap: 4px; }
  .lang summary span { display: none; }
}

@media (max-width: 600px) {
  .gallery-tabs { gap: 4px; }
  .gallery-tabs button { font-size: var(--text-small); padding: 6px 8px; }
  .site-nav { gap: 8px; }
  .nav-download { padding-inline: 12px; }
}

/* Phones stack each feature, the picture full width above its text and
   left-aligned with the section head. The cut is Mole's 560: OPPO Pad mini
   portrait reports 640 CSS px (dpr 2.625) and keeps the tablet zigzag. */
@media (max-width: 560px) {
  .fcard, .fcard:nth-child(even) { grid-template-columns: minmax(0, 1fr); gap: 20px; padding: 22px 0; }
  .fcard:nth-child(even) .fcard-media { order: 0; }
}
/* Below the desktop card's 430px a card grows taller, so its drawing shrinks less and
   its 12px words stay readable on a tablet's half column and a phone's full width. */
@media (max-width: 880px) { .fcard-media.mock { aspect-ratio: 1.8; } }
@supports (width: 1cqw) {
  @media (max-width: 880px) { .mock .m { --k: min(1px, calc(100cqw / 380)); } }
}

/* Match Mole's compact type and inset rhythm, keeping controls on one row. */
@media (max-width: 640px) {
  html[lang^="zh"] { --body-copy: 14px; --body-leading: 1.7; }
  html[lang^="zh"] .tagline { font-size: var(--text-body); line-height: 1.6; }
  html[lang^="zh"] .section-lede { font-size: var(--text-body); line-height: 1.6; }
  html[lang^="zh"] :is(.legal p, .legal li) { line-height: 1.7; }
  .fcard-body p { font-size: var(--body-copy); line-height: var(--body-leading); }
}
@media (max-width: 480px) {
  :root { --page-inset: 22px; --nav-outset: 11px; }
  html[lang^="zh"] { --page-inset: 20px; }
  .site-nav { min-height: 48px; padding-block: 6px; }
  .brand img { width: 28px; height: 28px; }
  .brand span { font-size: var(--text-body); }
  .hero { padding-top: 32px; }
  .hero h1 { margin-bottom: 32px; }
  html[lang^="zh"] .hero { padding-top: 36px; }
  html[lang^="zh"] .hero h1 { margin-bottom: 28px; }
  .tagline { font-size: var(--text-body); }
  .trust { gap: 4px 12px; font-size: var(--text-small); }
  .trust span { white-space: nowrap; }
  .trust span:not(:last-child)::after { content: none; }
  /* Phone hero buttons keep their label's width with 24px sides and wrap to a
     second row when a long label does not fit; stretched halves left a wide
     empty band around a short label. 44px tall, the touch minimum, rather than
     the desktop 51 (maintainer 2026-10-23). */
  .hero-actions { flex-wrap: wrap; gap: 8px; }
  .hero-actions .btn { flex: 0 0 auto; min-width: 0; padding: 10px 24px; font-size: 15px; white-space: nowrap; }
  .nav-download { font-size: var(--text-small); }
  .gallery-caption { display: none; }
}
/* Collapse the unused action slot; the bar's minimum height stays constant. */
.site-nav.hero-actions-visible .nav-download { display: none; }
