/* ══════════════════════════════════════════════════════════════════════
   blog.css — the blog, on the Apple-style page signature.
   Rewritten 2026-09-05 (Kevin: "apply same design language for about,
   blog, privacy and term").
   ──────────────────────────────────────────────────────────────────────
   ⚠ IT READS ap.css's TOKENS, SO BOTH BLOG PAGES MUST CARRY class="ap".
   `--a-ink`, `--a-ink-2`, `--a-grey`, `--a-hair` and the font stack are all
   defined on `body.ap` in /ap.css.  Without that class this file has no
   palette at all and the blog renders as unstyled text.  Load order on both
   pages is shell.css → ap.css → blog.css.

   ⚠ EVERY CLASS NAME IN HERE IS WRITTEN BY blog.js, NOT BY THE HTML.
   The two pages are near-empty shells; the cards, the hero, the table of
   contents, the share bar and the skeletons are all built in JavaScript
   and matched by class name.  RENAMING A CLASS HERE SILENTLY UNSTYLES A
   BLOCK — nothing errors, the markup simply arrives with no rules.  Change
   blog.js in the same commit or not at all.

   ⚠ THE SECTIONS ALTERNATE WHITE AND GREY, exactly as ap.css does.  A grey
   card on a grey ground disappears, so the cards invert their section:
   white cards on the grey list ground, grey cards on white.

   ⚠ #6E6E73 (--a-ink-2) IS THE LIGHTEST GREY ALLOWED ON TEXT.  4.66:1 on
   the grey, 5.07:1 on white.  The old dark theme's --text-dim was lighter
   still and is remapped, not restored — see the compatibility block at the
   foot of this file, which exists only because blog.js writes a handful of
   inline styles naming the old variables.
   ══════════════════════════════════════════════════════════════════════ */

a{text-decoration:none;color:inherit}
img{max-width:100%;display:block}

/* ══ INDEX: HERO ══════════════════════════════════════ */
.blog-header{text-align:center;padding:64px 22px 0;max-width:1024px;margin:0 auto}
.blog-eyebrow{display:inline-flex;align-items:center;gap:7px;font-size:17px;font-weight:600;
  letter-spacing:-.022em;color:var(--accent);margin-bottom:6px}
.blog-header h1{font-size:clamp(40px,6.4vw,72px);line-height:1.05;letter-spacing:-.015em;
  font-weight:600;margin:0;color:var(--a-ink)}
.blog-header p{font-size:clamp(19px,2vw,21px);line-height:1.381;letter-spacing:.011em;
  color:var(--a-ink);max-width:640px;margin:19px auto 0}

/* ══ INDEX: FILTERS ═══════════════════════════════════
   A search box and a row of pills.  ⚠ THE PILLS ARE OUTLINED, NOT FILLED,
   until one is chosen — a row of filled pills reads as eight equal calls
   to action rather than as a filter nobody has used yet. */
.blog-filters{max-width:1024px;margin:44px auto 0;padding:0 22px}
.blog-search-wrap{position:relative;margin-bottom:16px}
.blog-search-icon{position:absolute;left:17px;top:50%;transform:translateY(-50%);
  color:var(--a-ink-2);pointer-events:none}
#blog-search{width:100%;background:#fff;border:1px solid var(--a-hair);border-radius:980px;
  padding:13px 18px 13px 45px;font-family:inherit;font-size:16px;letter-spacing:-.018em;
  color:var(--a-ink);outline:none;transition:border-color .18s ease}
#blog-search::placeholder{color:var(--a-ink-2)}
#blog-search:focus{border-color:var(--accent)}
.blog-filter-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.blog-filter-label{font-size:13px;font-weight:600;letter-spacing:-.014em;
  color:var(--a-ink-2);margin-right:4px}
.blog-tag-btn,.blog-date-select{font-family:inherit;font-size:13.5px;font-weight:500;
  letter-spacing:-.016em;padding:7px 15px;border-radius:980px;border:1px solid var(--a-hair);
  background:#fff;color:var(--a-ink);cursor:pointer;transition:border-color .15s,background .15s;
  white-space:nowrap;outline:none}
.blog-tag-btn:hover,.blog-date-select:hover{border-color:var(--a-ink-2)}
.blog-tag-btn.active,.blog-date-select.active{background:var(--accent);border-color:var(--accent);
  color:#fff}
.blog-date-select{appearance:none;-webkit-appearance:none;padding-right:32px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236E6E73' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center}
/* ⚠ THE CHEVRON IS BAKED INTO THE BACKGROUND IMAGE, SO IT CANNOT INHERIT
   COLOUR.  On the active (accent-filled) state it would be dark grey on the
   accent, which is why the active select drops the arrow rather than keeping
   an unreadable one. */
.blog-date-select.active{background-image:none;padding-right:15px}

/* ══ INDEX: THE LIST ══════════════════════════════════
   Its own grey band, which is what separates the articles from the hero
   without a rule line.  The cards are white, inverting the ground. */
.blog-content{background:var(--a-grey);margin-top:48px;padding:64px 0 80px}
/* ⚠ THE LIST BAND IS GREY AND SO IS THE FOOTER, so the index closes on a
   WHITE band or the page ends in one undifferentiated grey slab.  That band
   is also the only call to action on the index, which every other page on
   this site ends with. */
.blog-end{background:#fff;padding:100px 22px;text-align:center}
.blog-end h2{font-size:clamp(32px,4.6vw,56px);line-height:1.0714;letter-spacing:-.005em;
  font-weight:600;color:var(--a-ink);margin:0}
.blog-end p{font-size:clamp(19px,2vw,21px);line-height:1.381;letter-spacing:.011em;
  color:var(--a-ink);max-width:640px;margin:19px auto 0}
.blog-end .blog-end-btns{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;
  margin-top:40px}
.blog-end a{display:inline-flex;align-items:center;justify-content:center;padding:12px 22px;
  border-radius:980px;background:var(--accent);border:1px solid var(--accent);color:#fff;
  font-size:17px;letter-spacing:-.022em;transition:opacity .18s ease}
.blog-end a:hover{opacity:.85}
.blog-end a.ghost{background:transparent;color:var(--accent)}
.blog-end a.ghost:hover{background:var(--accent);color:#fff;opacity:1}
.blog-content>*{max-width:1024px;margin-left:auto;margin-right:auto;padding-left:22px;
  padding-right:22px}

/* ── featured post ── */
.featured-post{display:grid;grid-template-columns:1fr 1fr;background:#fff;
  border-radius:var(--a-r);overflow:hidden;margin-bottom:48px;cursor:pointer;
  box-shadow:0 1px 2px rgba(0,0,0,.04),0 8px 30px rgba(0,0,0,.07);
  transition:transform .22s ease,box-shadow .22s ease}
.featured-post:hover{transform:translateY(-3px);
  box-shadow:0 2px 4px rgba(0,0,0,.05),0 16px 44px rgba(0,0,0,.11)}
.featured-post-image{position:relative;overflow:hidden;min-height:320px;
  background:var(--a-grey)}
.featured-post-image img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.featured-post-image-placeholder{position:absolute;inset:0;display:flex;align-items:center;
  justify-content:center;font-size:52px}
.featured-badge{position:absolute;top:16px;left:16px;z-index:1;font-size:11px;font-weight:600;
  letter-spacing:.02em;padding:4px 11px;border-radius:980px;background:#fff;color:var(--accent)}
.featured-post-body{padding:38px 38px 34px;display:flex;flex-direction:column}
.featured-tags{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:15px}
.featured-title{font-size:clamp(22px,2.4vw,28px);line-height:1.15;letter-spacing:.004em;
  font-weight:600;color:var(--a-ink);margin-bottom:12px}
.featured-excerpt{font-size:16px;line-height:1.5;letter-spacing:-.018em;color:var(--a-ink-2);
  flex:1;margin-bottom:20px}
/* ⚠ THE CHEVRON IS A PSEUDO-ELEMENT, matching .a-link in ap.css.  It has to
   inherit the link colour and nudge on hover, and a character does both free. */
.featured-read-link{display:inline-flex;align-items:center;gap:3px;font-size:17px;
  letter-spacing:-.022em;color:var(--accent);margin-top:18px}
.featured-read-link::after{content:'\203A';font-size:1.35em;line-height:1;position:relative;
  top:-.04em;transition:transform .2s ease}
.featured-post:hover .featured-read-link::after{transform:translateX(2px)}

/* ── the tag chip, used on every card ──
   ⚠ ACCENT ON --accent-wash, NEVER --a-ink-2 ON IT.  #6E6E73 measures about
   4.4:1 on the palest washes and fails AA; the accent clears it everywhere. */
.post-tag{display:inline-block;font-size:11.5px;font-weight:600;letter-spacing:.01em;
  padding:3px 10px;border-radius:980px;background:var(--accent-wash);color:var(--accent)}

/* ── the grid ── */
.posts-section-title{font-size:17px;font-weight:600;letter-spacing:-.022em;
  color:var(--a-ink-2);margin-bottom:20px}
.posts-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-bottom:48px}
.post-card{background:#fff;border-radius:var(--a-r);overflow:hidden;display:flex;
  flex-direction:column;cursor:pointer;
  box-shadow:0 1px 2px rgba(0,0,0,.04),0 6px 22px rgba(0,0,0,.06);
  transition:transform .22s ease,box-shadow .22s ease}
.post-card:hover{transform:translateY(-3px);
  box-shadow:0 2px 4px rgba(0,0,0,.05),0 14px 36px rgba(0,0,0,.1)}
.post-card-image{height:172px;position:relative;overflow:hidden;flex-shrink:0;
  background:var(--a-grey)}
.post-card-image img{width:100%;height:100%;object-fit:cover}
.post-card-image-placeholder{width:100%;height:100%;display:flex;align-items:center;
  justify-content:center;font-size:34px}
.post-card-body{padding:22px 22px 20px;display:flex;flex-direction:column;flex:1}
.post-card-tags{margin-bottom:11px;display:flex;gap:6px;flex-wrap:wrap}
.post-card-title{font-size:19px;line-height:1.26;letter-spacing:.012em;font-weight:600;
  color:var(--a-ink);margin-bottom:9px;flex:1}
.post-card-excerpt{font-size:15px;line-height:1.4667;letter-spacing:-.016em;
  color:var(--a-ink-2);margin-bottom:16px;display:-webkit-box;-webkit-line-clamp:3;
  -webkit-box-orient:vertical;overflow:hidden}
.post-meta,.post-card-meta{display:flex;align-items:center;gap:9px;font-size:13px;
  letter-spacing:-.014em;color:var(--a-ink-2)}
.post-card-meta{margin-top:auto}
.post-meta-dot{width:3px;height:3px;border-radius:50%;background:var(--a-ink-2);flex-shrink:0}

/* ── nothing found ── */
.no-results{text-align:center;padding:72px 22px;color:var(--a-ink-2)}
.no-results-icon{font-size:40px;margin-bottom:14px}
.no-results h3{font-size:22px;line-height:1.2;letter-spacing:-.014em;font-weight:600;
  color:var(--a-ink);margin-bottom:8px}
.no-results p{font-size:17px;line-height:1.4706;letter-spacing:-.022em}

/* ── pagination ── */
.blog-pagination{display:flex;align-items:center;justify-content:center;gap:8px}
.page-btn{font-family:inherit;font-size:14px;font-weight:500;letter-spacing:-.016em;
  min-width:38px;height:38px;border-radius:980px;border:1px solid var(--a-hair);background:#fff;
  color:var(--a-ink);cursor:pointer;display:flex;align-items:center;justify-content:center;
  transition:border-color .15s,background .15s}
.page-btn:hover:not(:disabled){border-color:var(--a-ink-2)}
.page-btn.active{background:var(--accent);border-color:var(--accent);color:#fff}
.page-btn:disabled{opacity:.4;cursor:not-allowed}
.page-btn-text{padding:0 16px}

/* ══════════════════════════════════════════════════════
   ONE POST
   ══════════════════════════════════════════════════════ */
.post-hero{max-width:760px;margin:0 auto;padding:52px 22px 0;text-align:center}
.back-btn{display:inline-flex;align-items:center;gap:5px;font-size:17px;letter-spacing:-.022em;
  color:var(--accent);margin-bottom:26px}
.back-btn:hover{text-decoration:underline;text-underline-offset:4px}
.post-hero-tags{display:flex;gap:7px;flex-wrap:wrap;justify-content:center;margin-bottom:18px}
.post-hero h1{font-size:clamp(32px,4.6vw,52px);line-height:1.0714;letter-spacing:-.005em;
  font-weight:600;color:var(--a-ink);margin-bottom:18px}
.post-hero-meta{display:flex;align-items:center;justify-content:center;gap:10px;font-size:14px;
  letter-spacing:-.016em;color:var(--a-ink-2);margin-bottom:36px;flex-wrap:wrap}
.post-hero-image{border-radius:var(--a-r);overflow:hidden;background:var(--a-grey);
  box-shadow:0 1px 2px rgba(0,0,0,.04),0 10px 34px rgba(0,0,0,.1)}
.post-hero-image img{width:100%;max-height:440px;object-fit:cover}
.post-hero-image-placeholder{display:flex;align-items:center;justify-content:center;
  min-height:300px;font-size:64px}

.post-layout{max-width:1024px;margin:0 auto;padding:56px 22px 88px;display:grid;
  grid-template-columns:minmax(0,1fr) 264px;gap:56px;align-items:start}
.post-body{min-width:0}

/* ── the article itself ──
   ⚠ RANGED LEFT, AND THAT IS NOT A BREAK WITH THE HOUSE RULE.  "Centre
   everything" covers headlines, ledes and standalone paragraphs; a 1,500
   word article centred is unreadable, exactly as a bullet list or a
   comparison table is.  The HERO above is centred, which is what makes the
   page read as part of the same site. */
.post-content{font-size:17px;line-height:1.6;letter-spacing:-.018em;color:var(--a-ink-2);
  text-align:left}
.post-content h2{font-size:clamp(24px,2.6vw,30px);line-height:1.16;letter-spacing:-.005em;
  font-weight:600;color:var(--a-ink);margin:52px 0 16px;padding-top:28px;
  border-top:1px solid var(--a-hair)}
.post-content h3{font-size:19px;line-height:1.26;letter-spacing:.012em;font-weight:600;
  color:var(--a-ink);margin:30px 0 11px}
.post-content p{margin-bottom:19px}
.post-content ul,.post-content ol{margin:0 0 19px;padding:0;list-style:none}
.post-content li{position:relative;padding-left:20px;margin-bottom:10px;line-height:1.6}
.post-content ul>li::before{content:'';position:absolute;left:0;top:10px;width:5px;height:5px;
  border-radius:50%;background:var(--accent)}
/* ⚠ A NUMBERED LIST KEEPS ITS NUMBERS.  The bullet above is a pseudo-element,
   so an ordered list has to opt back in or the reader loses the sequence —
   which in a filing guide is the whole point of the list. */
.post-content ol{counter-reset:pc}
.post-content ol>li{counter-increment:pc}
.post-content ol>li::before{content:counter(pc) '.';position:absolute;left:0;top:0;
  font-family:var(--a-mono);font-size:14px;line-height:1.6;letter-spacing:0;color:var(--accent)}
.post-content strong{color:var(--a-ink);font-weight:600}
.post-content a{color:var(--accent);text-decoration:underline;text-underline-offset:3px}
.post-content blockquote{border-left:3px solid var(--accent);padding:4px 0 4px 20px;
  margin:26px 0;color:var(--a-ink);font-size:19px;line-height:1.42;letter-spacing:-.012em}
.post-content blockquote p:last-child{margin-bottom:0}
.post-content img{border-radius:12px;margin:26px 0}
/* ⚠ A WIDE TABLE SCROLLS INSIDE ITS OWN BOX.  THE PAGE BODY NEVER DOES.
   Post bodies come from the database and a three-column rate table cannot
   compress below about 430px, so on a phone it would take the whole
   document sideways with it.  Same trap as .a-win-in in ap.css. */
.post-content table{width:100%;border-collapse:collapse;margin:24px 0;font-size:14.5px;
  display:block;overflow-x:auto;white-space:nowrap}
.post-content th{background:#FAFAFB;padding:11px 14px;text-align:left;font-weight:600;
  color:var(--a-ink);border-bottom:1px solid var(--a-hair)}
.post-content td{padding:11px 14px;border-bottom:1px solid var(--a-hair-2);color:var(--a-ink-2)}
.post-content tr:last-child td{border-bottom:0}

/* ── share ── */
.post-share{margin-top:52px;padding-top:32px;border-top:1px solid var(--a-hair)}
.post-share-title{font-size:15px;font-weight:600;letter-spacing:-.016em;color:var(--a-ink-2);
  margin-bottom:14px}
.share-btns{display:flex;gap:9px;flex-wrap:wrap}
.share-btn{font-family:inherit;font-size:14px;font-weight:500;letter-spacing:-.016em;
  padding:9px 17px;border-radius:980px;border:1px solid var(--a-hair);background:#fff;
  color:var(--a-ink);cursor:pointer;display:flex;align-items:center;gap:7px;
  transition:border-color .15s}
.share-btn:hover{border-color:var(--a-ink-2)}
.share-btn.copied{border-color:var(--accent);color:var(--accent)}

/* ── related ── */
.related-posts{margin-top:56px;padding-top:40px;border-top:1px solid var(--a-hair)}
.related-title{font-size:17px;font-weight:600;letter-spacing:-.022em;color:var(--a-ink-2);
  margin-bottom:20px}
.related-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.related-card{background:var(--a-grey);border-radius:14px;padding:20px;cursor:pointer;
  transition:background .15s}
.related-card:hover{background:#EDEDF0}
.related-card-tag{font-size:11.5px;font-weight:600;letter-spacing:.01em;color:var(--accent);
  margin-bottom:8px}
.related-card-title{font-size:15px;line-height:1.34;letter-spacing:-.014em;font-weight:600;
  color:var(--a-ink);margin-bottom:8px}
.related-card-meta{font-size:13px;letter-spacing:-.014em;color:var(--a-ink-2)}

/* ── sidebar ── */
.post-sidebar{position:sticky;top:84px}
.toc-box{background:var(--a-grey);border-radius:14px;padding:22px;margin-bottom:18px}
.toc-title{font-size:14px;font-weight:600;letter-spacing:-.016em;color:var(--a-ink-2);
  margin-bottom:13px}
.toc-list{list-style:none;display:flex;flex-direction:column;gap:2px;margin:0;padding:0}
.toc-item a{font-size:14px;line-height:1.45;letter-spacing:-.016em;color:var(--a-ink-2);
  display:block;padding:5px 0 5px 13px;border-left:2px solid transparent;
  transition:color .15s,border-color .15s}
.toc-item a:hover{color:var(--a-ink);border-left-color:var(--a-hair)}
.toc-item.active a{color:var(--accent);border-left-color:var(--accent);font-weight:500}
.toc-item.h3 a{padding-left:25px;font-size:13px}

.sidebar-cta{background:var(--a-grey);border-radius:14px;padding:24px;text-align:center}
.sidebar-cta-title{font-size:17px;line-height:1.22;font-weight:600;letter-spacing:-.022em;
  color:var(--a-ink);margin-bottom:8px}
.sidebar-cta-desc{font-size:14px;line-height:1.45;letter-spacing:-.016em;color:var(--a-ink-2);
  margin-bottom:18px}
.sidebar-cta-btn{display:inline-flex;align-items:center;justify-content:center;
  padding:10px 20px;border-radius:980px;background:var(--accent);color:#fff;font-size:15px;
  letter-spacing:-.018em;transition:opacity .18s ease}
.sidebar-cta-btn:hover{opacity:.85}

/* ── the closing banner ──
   ⚠ IT IS A GREY CARD ON A WHITE SECTION, NOT A DARK BLOCK.  The old one
   was a near-black panel with white type inside a light page, which is the
   single thing ap.css's alternating white-and-grey rhythm exists to replace.
   ⚠ AND THE SECTION AROUND IT MUST STAY WHITE.  The footer is grey
   (body.ap footer), so a grey band here would run straight into it and the
   page would end on one undifferentiated grey slab.  Same reason .a-banner
   in ap.css is a card rather than a section. */
.post-cta-banner{background:#fff;padding:64px 22px 80px}
.post-cta-inner{max-width:920px;margin:0 auto;padding:72px 48px;text-align:center;
  background:var(--a-grey);border-radius:var(--a-r-lg)}
.post-cta-inner h2{font-size:clamp(32px,4.6vw,48px);line-height:1.0714;letter-spacing:-.005em;
  font-weight:600;color:var(--a-ink);margin-bottom:19px}
.post-cta-inner p{font-size:clamp(19px,2vw,21px);line-height:1.381;letter-spacing:.011em;
  color:var(--a-ink);max-width:640px;margin:0 auto 34px}
.post-cta-btn{display:inline-flex;align-items:center;justify-content:center;padding:12px 24px;
  border-radius:980px;background:var(--accent);color:#fff;font-size:17px;letter-spacing:-.022em;
  transition:opacity .18s ease}
.post-cta-btn:hover{opacity:.85}

/* ── loading skeletons ── */
@keyframes skeleton-shimmer{0%{background-position:-600px 0}100%{background-position:600px 0}}
.skeleton-pulse{background:linear-gradient(90deg,#EFEFF2 25%,#F7F7F9 50%,#EFEFF2 75%);
  background-size:600px 100%;animation:skeleton-shimmer 1.4s infinite linear;border-radius:8px}
.skeleton-card{pointer-events:none;box-shadow:none}
.skeleton-card .post-card-image{background:#EFEFF2}
.skeleton-card .post-card-image.skeleton-pulse{height:172px}
.skeleton-featured{height:340px;border-radius:var(--a-r);margin-bottom:48px;
  background:linear-gradient(90deg,#EFEFF2 25%,#F7F7F9 50%,#EFEFF2 75%);
  background-size:600px 100%;animation:skeleton-shimmer 1.4s infinite linear}

/* ── responsive ── */
@media(max-width:940px){
  .featured-post{grid-template-columns:1fr}
  .featured-post-image{min-height:220px}
  .posts-grid{grid-template-columns:repeat(2,1fr)}
  .post-layout{grid-template-columns:1fr;gap:0}
  .post-sidebar{display:none}
  .related-grid{grid-template-columns:1fr}
}
@media(max-width:734px){
  .blog-header{padding:44px 20px 0}
  .blog-filters{padding:0 20px}
  .blog-content{margin-top:36px;padding:44px 0 64px}
  .blog-end{padding:64px 20px}
  .blog-content>*{padding-left:20px;padding-right:20px}
  .posts-grid{grid-template-columns:1fr}
  .featured-post-body{padding:26px 22px 24px}
  .post-hero{padding:36px 20px 0}
  .post-layout{padding:40px 20px 64px}
  .post-cta-banner{padding:44px 20px 60px}
  .post-cta-inner{padding:44px 24px;border-radius:var(--a-r)}
}

/* ══════════════════════════════════════════════════════════════════════
   COMPATIBILITY — the old variable names, remapped.
   ⚠ blog.js WRITES A HANDFUL OF INLINE STYLES NAMING THESE (the "couldn't
   load article" panel uses var(--text), var(--text-muted) and
   var(--purple-light) directly).  They are kept pointing at the Apple
   palette rather than chased through the JavaScript, because an inline
   style referring to an undefined variable falls back to the initial value
   — which for `color` is BLACK ON BLACK in some contexts and, worse, looks
   fine in the one state a developer normally sees.
   ══════════════════════════════════════════════════════════════════════ */
body.blog-page{
  --text:var(--a-ink);
  --text-muted:var(--a-ink-2);
  --text-dim:var(--a-ink-2);
  --purple:var(--accent);
  --purple-light:var(--accent);
  --teal:#1F7A5C;
  --border:var(--a-hair);
  --border-accent:var(--accent);
}
