:root{--ink:#192A35;--soft:#4A5560;--muted:#6E6A63;--brand:#0F6B33;--line:#E6E2D9;--ground:#FBFAF6;--surface:#FFFFFF;--sand:#F4F1EA}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--ground);color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  font-size:17px;line-height:1.65;
}
img{max-width:100%;height:auto}
a{color:var(--brand)}

/* --- chrome --------------------------------------------------------------- */
/*
  NOT A BLOG HEADER ANY MORE. .blogTop and .blogFoot were three links and a
  logo while the homepage had the real navigation, and nothing kept them in
  step — adding a section to the site nav would have left the blog advertising
  a different company. The markup and the link list now come from
  site-chrome.ts, which the homepage's data files read too, and these rules
  come with it.
*/

.container{max-width:1200px;margin:0 auto;padding:0 24px}
.header{border-bottom:1px solid var(--line);background:var(--surface)}
.header__inner{display:flex;align-items:center;gap:24px;min-height:72px}
.header__logo{display:block;line-height:0;flex:none}
.header__logo img{display:block;height:32px;width:auto}
.header__nav{flex:1 1 auto}
.header__links{display:flex;gap:28px;list-style:none;margin:0;padding:0}
.header__link{color:var(--soft);text-decoration:none;font-size:15px;font-weight:500}
.header__link:hover,.header__link[aria-current]{color:var(--brand)}
.header__ctas{display:flex;gap:12px;flex:none}
.header__ctas .btn{
  display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;
  padding:10px 20px;border-radius:999px;font-size:15px;font-weight:600;text-decoration:none;
}
.header__ctas .btn--ghost{color:var(--soft);border:1px solid var(--line)}
.header__ctas .btn--ghost:hover{color:var(--ink);background:var(--sand)}
.header__ctas .btn--primary{background:var(--brand);color:#fff;border:1px solid var(--brand)}

.footer{margin-top:72px;background:var(--ink);color:#C9D2D8}
.footer__grid{
  display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:40px;padding:56px 0 32px;
}
.footer__brand img{display:block;height:34px;width:auto;margin-bottom:16px}
.footer__tagline{margin:0;font-size:14px;line-height:1.6;color:#9FB0B9;max-width:46ch}
.footer__heading{
  margin:0 0 14px;font-size:12px;text-transform:uppercase;letter-spacing:.08em;color:#fff;
  font-weight:700;
}
.footer__links{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.footer__links a{color:#C9D2D8;text-decoration:none;font-size:14px}
.footer__links a:hover{color:#fff}
.footer__legal{
  display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
  padding:20px 0 40px;border-top:1px solid rgba(255,255,255,.12);font-size:13px;color:#9FB0B9;
}
.footer__legal p{margin:0}
.footer__legalLinks{display:flex;gap:20px;list-style:none;margin:0;padding:0}
.footer__legalLinks a{color:#9FB0B9;text-decoration:none}
.footer__legalLinks a:hover{color:#fff}

@media (max-width:900px){
  .header__nav{display:none}
  .footer__grid{grid-template-columns:1fr 1fr;gap:28px}
}
@media (max-width:560px){
  .header__inner{gap:12px}
  .header__ctas .btn{padding:9px 14px;font-size:14px}
  .footer__grid{grid-template-columns:1fr}
}

/*
  WIDER THAN AN ARTICLE, BECAUSE THERE IS A RAIL BESIDE IT NOW (point 11).
  The article column inside the grid keeps a reading measure of its own; this
  is the page.
*/
.blogMain{max-width:1200px;margin:0 auto;padding:24px 24px 64px}

/* --- the two-column layout (point 11) -------------------------------------- */
/*
  A POST: article then rail. An INDEX: cards then rail, with the rail on the
  LEFT at desktop width — which is what the reference does, and the order in
  the SOURCE is main-then-rail in both cases so a reader without CSS meets the
  content first.
*/
.blogLayout{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:48px;align-items:start}
.blogLayout--index{grid-template-columns:300px minmax(0,1fr)}
.blogLayout--index .blogLayout__main{order:2}
.blogLayout--index .rail--index{order:1}

/* The rail follows the reader down a long article, and stops before the
   footer. align-self:start is what lets position:sticky work inside a grid
   item -- without it the item stretches and there is nothing to stick. */
.rail{display:grid;gap:20px;align-self:start;position:sticky;top:24px}
.rail__card{
  padding:20px;border:1px solid var(--line);border-radius:12px;background:var(--surface);
}
.rail__title{
  margin:0 0 14px;font-size:13px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);
  font-weight:700;
}
.rail__cats,.rail__recent{list-style:none;margin:0;padding:0;display:grid;gap:2px}
.rail__cats a{
  display:flex;justify-content:space-between;gap:12px;padding:8px 10px;border-radius:8px;
  text-decoration:none;color:var(--soft);font-size:15px;
}
.rail__cats a:hover{background:var(--sand);color:var(--ink)}
.rail__cats a[aria-current]{background:var(--sand);color:var(--brand);font-weight:600}
.rail__cats span{color:var(--muted);font-size:13px;flex:none}
.rail__recent li+li{border-top:1px solid var(--line)}
.rail__recent a{display:block;padding:12px 0;text-decoration:none}
.rail__cat{
  display:block;font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);
  margin-bottom:4px;
}
.rail__postTitle{display:block;color:var(--ink);font-size:15px;line-height:1.4;font-weight:600}
.rail__recent a:hover .rail__postTitle{color:var(--brand)}
.rail__searchBox input{
  width:100%;box-sizing:border-box;padding:10px 12px;font:inherit;font-size:15px;
  border:1px solid var(--line);border-radius:10px;background:var(--ground);color:var(--ink);
}
.rail__searchNote{margin:8px 0 0;font-size:13px;color:var(--muted)}
/*
  THE UTILITY THE APP HAS AND THIS SHEET DID NOT.

  visually-hidden is defined in the application's global.css, and a post page
  loads none of that -- so the screen-reader label on the filter box rendered
  as VISIBLE TEXT, "Filter the posts on this page by title", sitting above the
  input. Found in a screenshot, which is the only place it could be found: the
  markup was correct and the class simply styled nothing.

  Clipped rather than display:none, because a hidden element is not announced
  at all and the point of the label is that it IS announced.
*/
/*
  THE hidden ATTRIBUTE LOSES TO ANY display RULE, AND THAT IS NOT A BROWSER
  BUG.

  It works through a UA stylesheet rule of [hidden]{display:none} -- the
  weakest possible specificity. .blogCard sets display:flex, which wins, so the
  filter script set hidden on five cards and all five stayed on screen.
  Measured: "Expected 0, Received 5".

  !important here rather than display:none in the script, because the attribute
  is also what tells a screen reader the element is gone: the script says WHAT
  is true, the stylesheet makes it look it.
*/
[hidden]{display:none !important}

.visually-hidden{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}
.rail__cta{background:var(--ink);border-color:var(--ink);color:#fff}
.rail__ctaTitle{margin:0 0 10px;font-size:18px;line-height:1.3;color:#fff}
.rail__ctaBody{margin:0 0 16px;font-size:14px;line-height:1.6;color:#C9D2D8}
.rail__ctaBtn{
  display:inline-block;padding:11px 20px;border-radius:999px;background:var(--brand);color:#fff;
  text-decoration:none;font-weight:600;font-size:15px;
}

@media (max-width:980px){
  /* ONE COLUMN, AND THE RAIL GOES UNDER — on a phone a category filter above
     the posts is a filter for something the reader has not seen yet. */
  .blogLayout,.blogLayout--index{grid-template-columns:minmax(0,1fr);gap:32px}
  .blogLayout--index .blogLayout__main{order:1}
  .blogLayout--index .rail--index{order:2}
  .rail{position:static}
}

/* --- breadcrumbs ---------------------------------------------------------- */
.blogCrumbs ol{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin:0 0 20px;padding:0;
  font-size:13px;color:var(--muted)}
.blogCrumbs li+li::before{content:"/";margin-right:8px;color:var(--line)}
.blogCrumbs a{color:var(--muted)}

/* --- a post --------------------------------------------------------------- */
.blogHead{font-size:30px;line-height:1.25;margin:8px 0 28px}
.blogPost__cat{margin:0 0 8px;font-size:13px;text-transform:uppercase;letter-spacing:.06em}
.blogPost__cat a{text-decoration:none}
.blogPost__title{font-size:34px;line-height:1.2;margin:0 0 12px}
.blogPost__meta{margin:0 0 24px;color:var(--muted);font-size:14px}
/* The hero reserves its box via width/height on the element, so nothing shifts. */
.blogPost__hero{display:block;width:100%;border-radius:12px;margin:0 0 32px}
.blogPost__tags{margin:32px 0 0}
.blogChip{
  display:inline-block;padding:4px 12px;margin:0 6px 6px 0;border-radius:999px;
  background:var(--sand);color:var(--soft);font-size:13px;text-decoration:none;
}

/* --- the body ------------------------------------------------------------- */
/*
  NOT WRITTEN HERE ANY MORE. The body's typography comes from
  blogBodyCss('.blogBody'), and the EDITOR calls the same function with
  '.ProseMirror'. Two copies kept in sync by eye is what made the editor box
  look nothing like Preview; one function called twice is what stops a rule
  added for one surface missing the other. See blog-body-css.ts.

  (No backticks in this comment, deliberately: it lives INSIDE a template
  literal, where a backtick ends the string. The same character, in the same
  file, cost a build four hours ago.)
*/

.blogBody{--ink:#192A35;--soft:#4A5560;--muted:#6E6A63;--brand:#0F6B33;--line:#E6E2D9;--ground:#FBFAF6;--surface:#FFFFFF;--sand:#F4F1EA;color:var(--ink);font-size:17px;line-height:1.65;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;}
.blogBody>*+*{margin-top:20px}
.blogBody p{margin:0}
.blogBody a{color:var(--brand)}
.blogBody h2{font-size:25px;line-height:1.3;margin:40px 0 0;font-weight:700}
.blogBody h3{font-size:20px;line-height:1.35;margin:32px 0 0;font-weight:700}
.blogBody h4{font-size:17px;font-weight:700;margin:24px 0 0}
.blogBody h5{font-size:15px;font-weight:700;margin:20px 0 0;text-transform:uppercase;letter-spacing:.04em}
.blogBody h6{font-size:14px;font-weight:700;margin:20px 0 0;color:var(--soft)}
/*
  list-style IS SET EXPLICITLY, AND IT IS NOT REDUNDANT.

  The published page's own sheet does not reset lists, but the EDITOR lives
  inside the application, whose global.css reset sets list-style:none on every
  list -- so the same document showed bullets on the page and none in the
  editor. Stating it here makes the block independent of whatever surrounds it,
  which is the whole point of a stylesheet that has to work in two places.
*/
.blogBody ul{padding-left:24px;margin:0;list-style:disc}
.blogBody ol{padding-left:24px;margin:0;list-style:decimal}
.blogBody ul ul{list-style:circle}
.blogBody li{margin:0}
.blogBody li+li{margin-top:8px}
.blogBody li>p{margin:0}
.blogBody blockquote{
  margin:0;margin-left:0;padding-left:16px;border-left:3px solid var(--brand);color:var(--soft);
}
.blogBody pre{
  padding:16px;border-radius:10px;background:var(--ink);color:#fff;
  overflow-x:auto;font-size:14px;margin:0;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
.blogBody pre code{background:none;color:inherit;padding:0;font-size:inherit}
.blogBody code{background:var(--sand);padding:2px 5px;border-radius:5px;font-size:.9em;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.blogBody hr{border:0;border-top:1px solid var(--line);margin:32px 0 0}
.blogBody img{border-radius:10px;display:block;max-width:100%;height:auto}
.blogBody table{width:100%;border-collapse:collapse;font-size:15px;margin:0;table-layout:fixed}
.blogBody th,.blogBody td{padding:10px 12px;border:1px solid var(--line);text-align:left;
  vertical-align:top}
.blogBody th{background:var(--sand);font-weight:700}
.blogBody .blogSize--small{font-size:0.875em}
.blogBody .blogSize--normal{font-size:1em}
.blogBody .blogSize--large{font-size:1.25em}
.blogBody .blogSize--xlarge{font-size:1.5em}
/* A wide table scrolls inside its wrapper rather than widening the page. */
.blogBody__tableWrap{overflow-x:auto}

/* --- the author box ------------------------------------------------------- */
.blogAuthor{
  margin-top:40px;padding:20px;border:1px solid var(--line);border-radius:12px;
  background:var(--surface);
}
.blogAuthor__name{margin:0 0 6px;font-size:17px}
.blogAuthor__name a{text-decoration:none}
.blogAuthor__bio{margin:0;color:var(--soft);font-size:15px}

/* --- cards ---------------------------------------------------------------- */
.blogGrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:24px}
.blogCard{
  border:1px solid var(--line);border-radius:12px;background:var(--surface);overflow:hidden;
  display:flex;flex-direction:column;
}
.blogCard__media{display:block;line-height:0}
.blogCard__media img{width:100%;display:block}
.blogCard__body{padding:16px}
.blogCard__cat{margin:0 0 6px;font-size:12px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted)}
.blogCard__title{margin:0 0 8px;font-size:18px;line-height:1.35}
.blogCard__title a{text-decoration:none;color:var(--ink)}
.blogCard__title a:hover{color:var(--brand)}
.blogCard__excerpt{margin:0 0 12px;color:var(--soft);font-size:15px}
.blogCard__meta{margin:0;color:var(--muted);font-size:13px}
.blogPost{max-width:760px}
.blogGrid--three{grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:900px){.blogGrid--three{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:620px){.blogGrid--three{grid-template-columns:minmax(0,1fr)}}
.blogRelated__title{font-size:22px;margin:0 0 20px}
.blogRelated{margin-top:56px}
.blogRelated h2{font-size:22px;margin:0 0 20px}
.blogEmpty{color:var(--muted)}

/* --- pagination ----------------------------------------------------------- */
.blogPager{display:flex;gap:8px;margin-top:40px}
.blogPager a,.blogPager span{
  display:inline-block;min-width:38px;padding:8px 10px;text-align:center;
  border:1px solid var(--line);border-radius:8px;text-decoration:none;color:var(--soft);
}
.blogPager span[aria-current]{background:var(--brand);border-color:var(--brand);color:#fff}

/* --- comments ------------------------------------------------------------- */
.blogComments{margin-top:56px;border-top:1px solid var(--line);padding-top:32px}
.blogComments__count{font-size:22px;margin:0 0 20px}
.blogComments__empty{color:var(--muted);margin:0}
.blogComment{padding:16px 0;border-bottom:1px solid var(--line)}
.blogComment:last-child{border-bottom:0}
.blogComment__meta{margin:0 0 6px;font-size:13px;color:var(--muted)}
.blogComment__meta strong{color:var(--ink)}
/*
  pre-wrap AND overflow-wrap. The first keeps the line breaks a commenter
  typed, which is the whole of "plain text with paragraphs"; the second stops a
  300-character unbroken token widening the page -- the exact defect
  pages-are-full-width caught on a pasted article, in a column anyone can type
  into.
*/
.blogComment__body{margin:0 0 10px;white-space:pre-wrap;overflow-wrap:anywhere}
.blogComment__body:last-child{margin-bottom:0}
.blogComments__form{margin-top:28px}
.blogComments__label{display:block;margin-bottom:8px;font-weight:600;font-size:15px}
.blogComments__input{
  width:100%;box-sizing:border-box;padding:12px;font:inherit;font-size:15px;
  border:1px solid var(--line);border-radius:10px;background:#fff;color:var(--ink);
  resize:vertical;
}
.blogComments__input:focus{outline:2px solid var(--brand);outline-offset:1px}
.blogComments__submit{
  margin-top:12px;padding:10px 18px;font:inherit;font-weight:600;cursor:pointer;
  border:0;border-radius:10px;background:var(--brand);color:#fff;
}
.blogComments__submit[disabled]{opacity:.6;cursor:default}
.blogComments__note{margin:10px 0 0;font-size:14px;color:var(--soft)}
.blogComments__signin{margin:0;color:var(--soft)}

@media (max-width:700px){
  .blogPost__title{font-size:27px}
  .blogHead{font-size:25px}
  body{font-size:16px}
}
