/* Shared styles for StickyFriend's sub-pages (privacy, changelog).
   Mirrors the landing page's design tokens so the pages read as one site.
   index.html keeps its styles inline; this file exists so the two sub-pages
   don't each carry their own duplicated copy of the same system. */
:root{
  --yellow:#FFE58A; --pink:#FFB9CF; --focus:#C2185B; --cyan:#AEE6FF; --lime:#CDEFA8;
  --purple:#DBCFFF; --orange:#FFD3A3;
  --ink:#3D3D4A;
  --ink-strong:#2E2E3A;
  --line:#DCE8F5;
  --paper:#FFFFFF;
  /* One step off --paper, for the insets that must read as "not the page":
     code, pre and the quote block. Added as a token rather than a literal so
     the three of them can never drift apart. */
  --paper-2:#F5F8FC;
  --shadow:4px 4px 0 rgba(61,61,74,.18);
  --shadow-sm:3px 3px 0 rgba(61,61,74,.18);
  --border:2px solid var(--ink);
  --border-sm:1.5px solid var(--ink);
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  font-family:'Nunito',sans-serif;background:var(--paper);color:var(--ink);overflow-x:hidden;
  background-image:linear-gradient(to bottom, transparent 33px, var(--line) 33px, var(--line) 34px, transparent 34px);
  background-size:100% 34px;
  position:relative;
  /* THE FOOTER GOES TO THE BOTTOM. On a short page — the blog index, refunds —
     the footer ended where the content ended and the ruled paper carried on
     below it for the rest of the viewport, which reads as the page having
     fallen over. Not mirrored into index.html's inline sheet: the landing page
     is never shorter than the viewport, so the rule would be dead weight there
     and this is the one place the two sheets are allowed to differ. */
  display:flex;flex-direction:column;min-height:100vh;
}
footer{margin-top:auto}
/* An AUTO side margin on a column flex item switches align-items:stretch OFF —
   so the moment body became a flex column, .pagehead and .wrap (both
   margin:0 auto) stopped filling the width and shrank to their own widest line.
   The visible symptom was a page title floating in the middle of the screen
   while the panel underneath it stayed put. width:100% restores the fill;
   max-width and the auto margins then centre it exactly as they did before. */
body > *{width:100%}
/* The red notebook margin rule, same as the landing page. */
body::before{
  content:"";position:fixed;top:0;bottom:0;left:58px;width:1.5px;
  background:rgba(255,138,168,.4);z-index:0;pointer-events:none;
}
.display{font-family:'Bangers',cursive;letter-spacing:.035em;font-weight:400;color:var(--ink-strong)}
/* .hand used to sit here. Nothing on any page carried the class — the
   handwriting face reaches the two places that want it (.stickynote and .note)
   from those rules directly. A styled class nobody applies is the same dead
   weight as an applied class nobody styles. */

.btn{display:inline-flex;align-items:center;gap:8px;font-weight:900;text-decoration:none;color:var(--ink-strong);
  border:var(--border);box-shadow:var(--shadow-sm);padding:10px 22px;border-radius:14px;
  background:var(--pink);cursor:pointer;transition:transform .12s, box-shadow .12s;font-size:1rem;
  font-family:'Nunito',sans-serif}
.btn:hover{transform:translate(-2px,-2px);box-shadow:6px 6px 0 rgba(61,61,74,.18)}
.btn:active{transform:translate(2px,2px);box-shadow:1px 1px 0 rgba(61,61,74,.18)}
.btn.yellow{background:var(--yellow)}.btn.cyan{background:var(--cyan)}
.btn.lime{background:var(--lime)}.btn.white{background:#fff}
.btn:disabled{opacity:.4;cursor:not-allowed;transform:none;box-shadow:var(--shadow-sm)}

/* NAV — matches index.html */
nav.topnav{position:sticky;top:0;z-index:100;background:rgba(255,255,255,.92);backdrop-filter:blur(4px);
  border-bottom:var(--border);display:flex;align-items:center;justify-content:space-between;
  gap:12px;padding:13px 28px}
.logo{font-family:'Bangers',cursive;font-size:1.7rem;text-decoration:none;color:var(--ink-strong);
  background:var(--yellow);border:var(--border);box-shadow:var(--shadow-sm);
  padding:2px 14px;transform:rotate(-2deg);display:inline-block;transition:transform .15s;white-space:nowrap}
.logo:hover{transform:rotate(1.5deg) scale(1.04)}
/* The <img> carries its intrinsic 268x297 as width/height attributes so the
   browser reserves the right box before the PNG arrives; CSS then sizes it.
   It used to be an inline style — 60px on the landing page, 32px on every
   other one. */
.logo img{height:34px;width:auto;object-fit:contain;vertical-align:middle;margin-right:4px}
.nav-links{display:flex;gap:6px;align-items:center;flex-wrap:wrap;justify-content:flex-end}
.nav-links a{text-decoration:none;color:var(--ink);font-weight:800;font-size:.92rem;
  padding:8px 14px;border:2px solid transparent;border-radius:999px;transition:.15s}
.nav-links a:hover{border-color:var(--ink);background:var(--cyan)}
.nav-links a.here{border-color:var(--ink);background:var(--yellow)}

/* The hamburger. Hidden on desktop AND whenever the script has not run — see
   the 920px block below: without JS the links wrap instead, so a dead button
   never shows. These sub-pages used to have neither the button nor the script,
   which is why the same header behaved differently depending on which page you
   were standing on. */
.nav-toggle{display:none;align-items:center;gap:8px;font-family:inherit;font-weight:900;
  font-size:.9rem;color:var(--ink-strong);background:var(--yellow);border:var(--border);
  box-shadow:var(--shadow-sm);border-radius:999px;padding:7px 14px;cursor:pointer}
.nav-toggle .bars{display:inline-block;width:16px;height:2px;background:var(--ink-strong);
  position:relative;transition:.15s}
.nav-toggle .bars::before,.nav-toggle .bars::after{content:"";position:absolute;left:0;
  width:16px;height:2px;background:var(--ink-strong);transition:.15s}
.nav-toggle .bars::before{top:-5px}.nav-toggle .bars::after{top:5px}
.nav-toggle[aria-expanded="true"] .bars{background:transparent}
.nav-toggle[aria-expanded="true"] .bars::before{top:0;rotate:45deg}
.nav-toggle[aria-expanded="true"] .bars::after{top:0;rotate:-45deg}

/* PAGE HEADER */
.pagehead{max-width:1150px;margin:0 auto;padding:60px 28px 22px;position:relative;z-index:1}
.kicker{display:inline-block;background:var(--cyan);border:var(--border);box-shadow:var(--shadow-sm);
  padding:6px 18px;border-radius:999px;font-weight:900;font-size:.83rem;
  transform:rotate(-1.5deg);margin-bottom:18px;text-transform:uppercase;letter-spacing:.05em}
.pagehead h1{font-family:'Bangers',cursive;font-weight:400;font-size:clamp(2.6rem,6vw,4.2rem);
  line-height:1;color:var(--ink-strong);margin-bottom:14px}
.pagehead .lead{font-size:1.12rem;font-weight:700;max-width:680px}
.pagehead .updated{margin-top:16px;font-weight:800;font-size:.86rem;opacity:.75}
/* A reading page's header has to sit over the SAME column as its article.
   Left at the full 1150px it started at the far-left margin while the 840px
   article sat centred underneath it, and the title visibly did not belong to
   the text below. Pairs with .wrap.reading; the two widths are one decision. */
.pagehead.reading{max-width:768px}
.pagehead.reading .lead{max-width:none}

.wrap{max-width:1150px;margin:0 auto;padding:10px 28px 80px;position:relative;z-index:1}

/* CARD — the white bordered panel used everywhere on this site */
.card{background:#fff;border:var(--border);box-shadow:var(--shadow);border-radius:20px;
  padding:30px;margin-bottom:26px}
.card h2{font-family:'Bangers',cursive;font-weight:400;font-size:clamp(1.7rem,3.6vw,2.3rem);
  line-height:1.05;margin-bottom:6px;color:var(--ink-strong)}
.card h3{font-family:'Bangers',cursive;font-weight:400;font-size:1.35rem;margin:22px 0 6px;color:var(--ink-strong)}
.card p{font-weight:600;font-size:1rem;line-height:1.6;margin-bottom:12px}
.card p:last-child{margin-bottom:0}
.card ul,.card ol{margin:6px 0 12px 22px}
.card li{font-weight:600;font-size:1rem;line-height:1.6;margin-bottom:7px}
.card a{color:var(--ink-strong);font-weight:800}
.card .sub{font-weight:700;opacity:.72;font-size:.95rem;margin-bottom:16px}

/* A pull-out sticky note, used for the "plain English" summaries. */
.stickynote{background:var(--yellow);border:var(--border);box-shadow:var(--shadow);
  padding:26px 22px;font-family:'Kalam',cursive;transform:rotate(-.7deg);margin-bottom:34px;
  position:relative}
.stickynote.cyan{background:var(--cyan);transform:rotate(.6deg)}
.stickynote::before{content:"";position:absolute;top:-13px;left:50%;translate:-50% 0;
  width:76px;height:22px;background:rgba(255,255,255,.65);border:1.5px solid var(--ink);transform:rotate(-2deg)}
.stickynote h2{font-family:'Kalam',cursive;font-weight:700;font-size:1.4rem;margin-bottom:10px;color:var(--ink-strong)}
.stickynote p{font-weight:400;font-size:1.05rem;line-height:1.5;margin-bottom:9px}
.stickynote ul{margin:4px 0 8px 20px}
.stickynote li{font-weight:400;font-size:1.02rem;line-height:1.5;margin-bottom:5px}
.stickynote p:last-child,.stickynote li:last-child{margin-bottom:0}

/* Tags — "default off", "not built yet", etc. */
.tag{display:inline-block;border:var(--border-sm);border-radius:999px;padding:2px 11px;
  font-family:'Nunito',sans-serif;font-weight:900;font-size:.72rem;text-transform:uppercase;
  letter-spacing:.04em;background:#fff;color:var(--ink-strong);white-space:nowrap;vertical-align:middle}
.tag.off{background:var(--lime)}
.tag.soon{background:var(--purple)}
.tag.new{background:var(--pink)}

/* CHANGELOG */
.release{background:#fff;border:var(--border);box-shadow:var(--shadow);border-radius:20px;
  padding:0;margin-bottom:26px;overflow:hidden}
.release-head{background:var(--cyan);border-bottom:var(--border);padding:15px 26px;
  display:flex;align-items:baseline;gap:14px;flex-wrap:wrap}
.release:nth-of-type(even) .release-head{background:var(--yellow)}
.release-head .ver{font-family:'Bangers',cursive;font-size:1.9rem;color:var(--ink-strong);line-height:1}
.release-head .when{font-weight:800;font-size:.84rem;opacity:.8}
.release-head .spacer{flex:1}
.release-body{padding:24px 26px 26px}
.release-body h3{font-family:'Bangers',cursive;font-weight:400;font-size:1.25rem;
  margin-bottom:14px;color:var(--ink-strong);letter-spacing:.03em}
.feat{display:flex;gap:13px;align-items:flex-start;margin-bottom:16px}
.feat:last-child{margin-bottom:0}
.feat .fic{width:38px;height:38px;flex-shrink:0;border:var(--border-sm);border-radius:12px;
  display:grid;place-items:center;font-size:1.1rem;box-shadow:2px 2px 0 rgba(61,61,74,.14);background:var(--lime)}
.feat:nth-child(3n) .fic{background:var(--pink)}
.feat:nth-child(3n+1) .fic{background:var(--yellow)}
.feat b{display:block;font-weight:900;font-size:1rem;color:var(--ink-strong);margin-bottom:2px}
.feat span{font-weight:600;font-size:.95rem;line-height:1.5}

/* Pagination — one version per page, so this list can grow for years. */
.pager{display:flex;gap:12px;align-items:center;justify-content:center;flex-wrap:wrap;margin:6px 0 40px}
.pager .pgstatus{font-weight:900;font-size:.9rem;padding:0 6px}
.pager .btn{padding:9px 18px;font-size:.9rem}
.pgdots{display:flex;gap:7px;flex-wrap:wrap;justify-content:center}
.pgdot{border:var(--border-sm);background:#fff;border-radius:10px;padding:5px 12px;
  font-family:'Nunito',sans-serif;font-weight:900;font-size:.8rem;color:var(--ink);cursor:pointer;
  box-shadow:2px 2px 0 rgba(61,61,74,.14);transition:.12s}
.pgdot:hover{background:var(--cyan)}
.pgdot.on{background:var(--yellow)}
/* No-JS fallback: without the script nothing is hidden, so every version is
   readable and the pager (which only makes sense with JS) is not shown. */
.pager{display:none}
.js .pager{display:flex}

/* ROADMAP */
.roadmap-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(265px,1fr));gap:24px}
.rm{background:#fff;border:2px dashed var(--ink);box-shadow:var(--shadow-sm);border-radius:18px;
  padding:24px;transition:transform .15s}
.rm:hover{transform:translate(-2px,-3px) rotate(-.3deg)}
.rm .rmic{width:48px;height:48px;border:var(--border-sm);border-radius:14px;display:grid;place-items:center;
  font-size:1.4rem;margin-bottom:14px;background:var(--purple);box-shadow:2px 2px 0 rgba(61,61,74,.14)}
.rm h3{font-family:'Bangers',cursive;font-weight:400;font-size:1.4rem;margin-bottom:7px;color:var(--ink-strong)}
.rm p{font-weight:600;font-size:.95rem;line-height:1.5}
.rm .tag{margin-bottom:10px}

/* Anchor offset so sticky-nav doesn't cover jumped-to headings. */
.anchor{scroll-margin-top:90px}

/* ── BLOG ───────────────────────────────────────────────────────────────────
   Deliberately built out of what is already here: a post is a .card, a callout
   is a .stickynote, a label is a .tag. No new palette, no new shadow — the
   only additions are layout for the index list and reading rhythm for long
   prose, both expressed in the variables at the top of this file. */
.crumbs{font-weight:800;font-size:.86rem;margin-bottom:20px;opacity:.9}
.crumbs a{color:var(--ink-strong);text-decoration:none;border-bottom:var(--border-sm)}
.crumbs a:hover{background:var(--yellow)}
.crumbs .sep{opacity:.5;padding:0 7px}
/* The last crumb is the page you are on. It was the same weight as the two
   links before it, so the trail read as three links, one of which did nothing. */
.crumbs [aria-current="page"]{opacity:.7;font-weight:700}

.postlist{list-style:none;display:grid;gap:22px;margin:0;padding:0}
.postcard{background:var(--paper);border:var(--border);box-shadow:var(--shadow);
  border-radius:20px;padding:24px 28px 22px;transition:transform .15s}
.postcard:hover{transform:translate(-2px,-3px) rotate(-.3deg)}
.postcard h2{font-family:'Bangers',cursive;font-weight:400;
  font-size:clamp(1.5rem,3.2vw,1.95rem);line-height:1.06;margin-bottom:8px;color:var(--ink-strong)}
.postcard h2 a{color:inherit;text-decoration:none}
.postcard h2 a:hover{color:var(--focus)}
.postcard p{font-weight:600;font-size:1rem;line-height:1.62;margin-bottom:16px}
/* The date was grey-on-white at .78 opacity and read as disabled text. It is
   the one fact on the card a reader actually scans for, so it is now ink, and
   the "N min read" tag beside it carries the tint instead. */
.postmeta{display:flex;gap:10px;flex-wrap:wrap;align-items:center;
  font-weight:800;font-size:.8rem;margin-bottom:10px;color:var(--ink-strong)}
.postmeta time{letter-spacing:.02em}
.postmeta .tag{background:var(--cyan)}
.readmore{display:inline-block;font-weight:900;font-size:.92rem;text-decoration:none;
  color:var(--ink-strong);border-bottom:3px solid var(--focus)}
.readmore:hover{background:var(--yellow)}

/* THE READING COLUMN. A post is read, not scanned, so its column is narrower
   than the wide .wrap the marketing pages use. 768px here minus the wrapper's
   56px of padding and the card's 76px leaves about 636px of text — roughly 75
   characters of Nunito at the size below, which is the measure this is for. It
   was 840px, and 840 minus the old padding was ~95 characters: a wall.
   The constraint sits on the WRAPPER, not on the article, so the callout and
   the next/previous links below it line up with the panel instead of jutting
   out — and .pagehead.reading above matches it so the title lines up too. */
.wrap.reading{max-width:768px}

/* The article itself. .card already gives the panel; this is the rhythm. */
.post{padding:34px 38px 30px}
.post p,.post li{font-size:1.03rem;line-height:1.72}
.post h2{font-family:'Bangers',cursive;font-weight:400;font-size:clamp(1.5rem,3.4vw,2rem);
  line-height:1.08;margin:42px 0 12px;color:var(--ink-strong);position:relative}
/* A short stroke under each section head. The sections used to be separated by
   whitespace alone, so a scroll through 3,000 words showed no structure at all.
   Two pixels of --focus is enough to make the rhythm visible without turning
   the notebook into a corporate document. */
.post h2::after{content:"";display:block;width:52px;height:3px;margin-top:9px;
  background:var(--focus);border-radius:3px;opacity:.55}
.post h2:first-child{margin-top:0}
.post h3{margin:28px 0 8px}
.post h3::after{content:none}
.post>p:first-child,.post>h2:first-child+p{margin-top:0}
.post p{margin-bottom:16px}
.post ul,.post ol{margin:10px 0 20px 26px}
.post li{margin-bottom:11px}
.post li::marker{color:var(--focus)}
.post li>strong:first-child{color:var(--ink-strong)}
.post hr{border:none;border-top:var(--border);opacity:.35;margin:34px 0}
.post .stickynote{margin:30px 0}
.post .stickynote h2{font-family:'Kalam',cursive;font-weight:700;font-size:1.35rem;margin:0 0 10px}
.post .stickynote h2::after{content:none}
.post>*:last-child{margin-bottom:0}

/* CODE AND QUOTES. <code> is used in a post and several times on the privacy
   page and had no rule at all, so a filename or a header name rendered as
   ordinary prose in the middle of a sentence. <pre> and <blockquote> are styled
   with it so the next one that gets written already has somewhere to land. */
.card code,.card kbd{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.88em;background:var(--paper-2);border:var(--border-sm);border-radius:7px;
  padding:1px 6px;white-space:nowrap}
.card pre{background:var(--paper-2);border:var(--border-sm);border-radius:12px;
  padding:16px 18px;margin:0 0 18px;overflow-x:auto;box-shadow:2px 2px 0 rgba(61,61,74,.12)}
.card pre code{background:none;border:0;padding:0;white-space:pre;font-size:.9rem}
.card blockquote{margin:22px 0;padding:4px 0 4px 20px;border-left:4px solid var(--focus);
  font-family:'Kalam',cursive;font-size:1.08rem;line-height:1.55}
.card blockquote p{font-weight:400;margin-bottom:8px}
.card blockquote p:last-child{margin-bottom:0}

/* Prev/next between posts, and the "more posts" rail at the foot of one.
   .postnav-head was three identical inline style attributes, one per post —
   the shape a rule takes just before the fourth post gets a slightly different
   copy of it. */
.postnav-head{font-size:1.6rem;margin:38px 0 14px}
.postnav{display:flex;gap:14px;flex-wrap:wrap;justify-content:space-between;margin-top:8px}
.postnav a{flex:1 1 260px;text-align:left;justify-content:flex-start;
  font-size:.95rem;line-height:1.3;padding:14px 18px}
/* The closing callout on the index and at the foot of a post wants air above it
   and none of its own below — the .wrap already ends the page. Was an inline
   style="margin-top:34px" on the index only, so the post pages sat tighter than
   the index for no reason anyone chose. */
.wrap > .stickynote{margin-top:34px;margin-bottom:0}

/* FOOTER — matches index.html character for character.
   Twelve links in one 22px-gapped row wrapped into a ragged block with no
   grouping and no hit area: the hover was a colour change on the glyphs alone.
   They are chips now, on a measure narrow enough to wrap evenly, and the
   copyright line and the language picker each get their own row instead of
   colliding on one. */
footer{background:#4A4A5E;color:#F4F5FA;padding:44px 28px 32px;text-align:center;
  position:relative;z-index:1;border-top:var(--border)}
footer .flinks{display:flex;gap:6px 8px;justify-content:center;flex-wrap:wrap;
  max-width:780px;margin:20px auto 16px}
footer .flinks a{color:#F4F5FA;font-weight:800;text-decoration:none;font-size:.92rem;
  padding:5px 11px;border-radius:999px;border:2px solid transparent;transition:.15s}
footer .flinks a:hover{color:var(--ink-strong);background:var(--yellow);border-color:var(--yellow)}
footer small{opacity:.75;font-weight:700;display:block}
footer .foot-lang{margin-top:16px}

@media (max-width:920px){
  body::before{display:none}

  /* Baseline (no JS): the links WRAP onto their own full-width row. Wrapped,
     the bar is ~3 rows tall, and pinning that to the top of a phone screen
     costs more than it gives — so the baseline scrolls away and only the
     enhanced one-row bar stays sticky. Identical to index.html's block. */
  nav.topnav{position:static;flex-wrap:wrap;row-gap:10px;padding:13px 18px}
  body[data-nav="js"] nav.topnav{position:sticky}
  .nav-links{flex-wrap:wrap;justify-content:flex-start;width:100%;order:3;gap:6px 4px}
  .nav-links a{padding:7px 11px;font-size:.85rem}
  .nav-links a.btn{margin-right:0!important}

  /* Enhanced (JS ran): collapse the same links into a real toggle menu. Keyed
     off body[data-nav="js"] so the baseline above is what ships if /nav.js
     never executes. */
  body[data-nav="js"] .nav-toggle{display:inline-flex}
  body[data-nav="js"] .nav-links{display:none;flex-direction:column;align-items:stretch;
    padding-top:4px;border-top:2px dashed rgba(61,61,74,.25);margin-top:2px}
  body[data-nav="js"] .nav-links.open{display:flex}
  body[data-nav="js"] .nav-links a{text-align:center;font-size:.95rem;padding:10px 12px}

  .pagehead{padding:42px 20px 18px}
  .wrap{padding:10px 20px 60px}
  .card{padding:23px}
  .release-body{padding:20px}
  .release-head{padding:13px 20px}
}
@media (max-width:520px){
  .nav-links a:not(.btn){padding:5px 8px;font-size:.8rem}
  .logo{font-size:1.35rem}
  .stickynote{transform:none}
  .feat .fic{width:32px;height:32px;font-size:.95rem}
}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
:focus-visible{outline:3px dashed var(--focus);outline-offset:3px}

/* ── LANGUAGE PICKER ────────────────────────────────────────────────────────
   One component, two homes: the header and the footer. Anchored to its own
   .lang-pick rather than to the nav, so the footer copy inherits nothing it
   should not.

   NOT A LISTBOX. It is a disclosure button (aria-expanded + aria-controls)
   revealing a plain list of links — see the header comment in lang.js for why
   the role="listbox"/role="option" it used to declare was a lie. */

/* Read by a screen reader, invisible on screen. Used for the "Language:" prefix
   on the picker button, so its accessible name is "Language: English" and still
   comes from real text — no aria-label to drift out of sync with what is drawn.
   Not display:none and not visibility:hidden: both remove it from the
   accessibility tree, which is the one place it needs to exist. */
.sf-vh{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);
  white-space:nowrap;border:0;
}
.lang-pick{position:relative;display:inline-flex;align-items:center}
.lang-btn{
  display:inline-flex;align-items:center;gap:6px;
  font:inherit;font-size:.85rem;font-weight:700;
  padding:7px 11px;border:2px solid currentColor;border-radius:999px;
  background:transparent;color:inherit;cursor:pointer;line-height:1;
}
.lang-btn:hover{background:rgba(0,0,0,.06)}
.lang-btn:focus-visible{outline:3px solid #00B8D4;outline-offset:2px}
.lang-menu{
  position:absolute;top:calc(100% + 6px);right:0;z-index:60;margin:0;padding:6px;
  list-style:none;min-width:170px;
  background:#fff;color:#222;border:2px solid #222;border-radius:12px;
  box-shadow:4px 4px 0 rgba(0,0,0,.18);
}
/* The FOOTER menu opens UPWARD — dropping it below the last element on the page
   puts it past the bottom of the document, where it either clips or extends the
   scroll height for no reason. */
.foot-lang .lang-menu{top:auto;bottom:calc(100% + 6px)}
.lang-menu li{margin:0}
.lang-menu a{
  display:block;padding:8px 12px;border-radius:8px;
  text-decoration:none;color:inherit;font-size:.9rem;white-space:nowrap;
}
.lang-menu a:hover,.lang-menu a:focus-visible{background:#FFE58A}
.lang-menu a.on{font-weight:800}
.lang-menu a.on::after{content:" ✓"}

@media (max-width:520px){
  /* On a phone the header menu would otherwise run off the right edge, because
     the picker sits at the end of a wrapped nav row. */
  .lang-menu{right:auto;left:0}
  .foot-lang{margin-top:10px}
}

/* ── CJK DISPLAY TEXT ────────────────────────────────────────────────────────
 *
 * Bangers carries NO Chinese or Japanese glyphs. Every display heading asked
 * for it anyway, so on zh-CN and ja the browser silently fell through to a
 * default system face — thin, light-weight, and still wearing the
 * letter-spacing that only makes sense for Latin capitals. The result was a
 * hero headline that looked weaker than the body text beneath it, in exactly
 * the two languages where the brand voice had to carry itself without the
 * comic lettering.
 *
 * So CJK gets its own display stack: the heaviest system face each platform
 * actually ships, at a real bold weight, with the Latin tracking removed.
 * Scoped by :lang(), which <html lang> already carries and lang.js already
 * stamps on every switch — so this follows the picker with no extra wiring.
 */
:lang(ja) .display, :lang(ja) .hero h1, :lang(ja) .section h2,
:lang(ja) .card h2, :lang(ja) .card h3, :lang(ja) .postcard h2, :lang(ja) .post h2,
:lang(zh-CN) .display, :lang(zh-CN) .hero h1, :lang(zh-CN) .section h2,
:lang(zh-CN) .card h2, :lang(zh-CN) .card h3, :lang(zh-CN) .postcard h2, :lang(zh-CN) .post h2 {
  font-family: "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Yu Gothic",
               "Noto Sans JP", "Noto Sans SC", "Source Han Sans SC",
               "Microsoft YaHei", "PingFang SC", sans-serif;
  font-weight: 800;
  /* Latin tracking on CJK reads as broken spacing, not as style. */
  letter-spacing: 0;
  /* NO font-size HERE. The headings size themselves with clamp(); an `em` on
     top of that multiplies against the clamped value and collapsed the hero to
     body size. A CJK face does read heavier than Bangers at the same size, but
     that is paid for with line-height, not by shrinking the headline. */
  line-height: 1.4;
}
/* The kicker/eyebrow uppercases and tracks out — both are Latin-only ideas. */
:lang(ja) .kicker, :lang(zh-CN) .kicker {
  text-transform: none; letter-spacing: 0;
}

/* ── NAV DROPDOWN ─────────────────────────────────────────────────────────
   Opens on click, not hover: a hover menu is unusable on touch and fires by
   accident on the way to the button beside it. */
.navdrop{position:relative;display:inline-block}
.navdrop-btn{
  font:inherit;font-weight:800;font-size:.92rem;color:var(--ink);
  background:none;border:2px solid transparent;border-radius:999px;
  padding:7px 13px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;
}
.navdrop-btn::after{content:"";width:6px;height:6px;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:rotate(45deg);margin-top:-3px;opacity:.6}
.navdrop-btn:hover{border-color:var(--ink);background:var(--cyan)}
.navdrop-btn[aria-expanded="true"]{border-color:var(--ink);background:var(--cyan)}
.navdrop-menu{
  position:absolute;top:calc(100% + 8px);left:0;z-index:60;
  list-style:none;margin:0;padding:6px;min-width:196px;
  background:#fff;border:var(--border);box-shadow:var(--shadow);border-radius:14px;
}
.navdrop-menu[hidden]{display:none}
.navdrop-menu li{margin:0}
.navdrop-menu a{display:block;padding:9px 12px;border-radius:9px;text-decoration:none;
  color:var(--ink);font-weight:800;font-size:.9rem}
.navdrop-menu a:hover,.navdrop-menu a:focus-visible{background:var(--yellow)}

/* The extension CTA reads as its own thing, not a second copy of the app one. */
.btn.ext{background:var(--lime)}
.btn.big.lime{background:var(--lime)}

/* Footer: the CTA pair and the support address. */
.foot-cta{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin:18px 0 6px}
.foot-mail{margin:8px 0 0}
.foot-mail a{color:#F4F5FA;font-weight:800;text-decoration:none;border-bottom:2px solid rgba(244,245,250,.4)}
.foot-mail a:hover{color:var(--yellow);border-bottom-color:var(--yellow)}

/* Below the nav's collapse point the dropdown is a plain block — a floating
   menu inside an already-open hamburger panel is a menu inside a menu. */
@media (max-width:920px){
  .navdrop{display:block;width:100%}
  .navdrop-btn{width:100%;justify-content:space-between;text-align:left}
  .navdrop-menu{position:static;box-shadow:none;border:0;padding:0 0 0 10px;min-width:0;background:transparent}
}

/* [hidden] IS NOT ENOUGH ON ITS OWN. The UA stylesheet gives it display:none,
   but ANY author rule that sets `display` wins — and .btn sets inline-flex, so
   a hidden button stayed on screen. This is the fix for the extension CTA
   showing before its store link exists. */
[hidden]{display:none!important}
