/* ===================================================================
   hostna OS — the Journal
   -------------------------------------------------------------------
   The blog drawn as an OS SCREEN, not as a document.

   The first version of this sheet dressed the blog like a service
   page: a hero band with a 3D globe, a column of prose in a card, a
   call to action reading "Open Hostna" underneath. That is the right
   shape for /vps-hosting/, whose job is to argue and then hand the
   visitor to the desktop. It is the wrong shape for a blog — and on
   the index it produced a stack of headings with nothing to look at.

   So this file builds the listing out of the pieces the desktop's own
   Home screen is built from, and almost nothing else:

     .bento          the twelve-column grid            os.css:373
     .tile           the glass card + its hover lift   os.css:378
     .tile-h         a card's header row               os.css:384
     .tile-lead      the muted line under a heading    os.css:387
     .chips / .chip  the topic rail                    os.css:336
     .pill-mini      the label on a cover              os.css:388
     .stagger        the entrance                      os.css:299
     .os-faq         the questions                     os-page.css:319

   What is written below is only what did not exist: a 16:9 cover that
   crops rather than distorts, a whole-tile hit area, the article's
   reading column, a sticky contents rail and a pager.

   THE CALL TO ACTION IS GONE. Not restyled — removed, on the owner's
   instruction. The dock is on screen at all times and every article
   still carries the one product it implies, priced live from the
   catalogue. Nothing is lost but the shove.

   LOAD ORDER. Enqueued in hostna_blog_assets() against `hostna-os-tablet`,
   so this is the LAST sheet on a blog page: os.css, os-chrome.css,
   os-page.css, os-desktop.css, os-tablet.css, then this. Ties are decided
   by print order, so a rule here beats the same specificity anywhere else.
   os-tablet.css still loads last of the SHARED sheets — the ones it was
   written to correct — and none of its rules address the bl-* components,
   which did not exist when it was written; the pointer:coarse block at the
   end of this file is what covers them.

   SPECIFICITY. Every rule is `body.hostna-os-page .bl-…` = (0,2,1), the
   same shape every os-page component uses. No !important anywhere.

   THE TRAP THIS FILE IS WRITTEN AROUND. There is NO bare `a` rule in
   os.css. An anchor outside .os-doc renders as the browser default —
   blue and underlined, in both themes. Every anchor below therefore
   states its own colour and text-decoration. Same bug os.css:190
   documents for .mb-chip.
   =================================================================== */


/* ── 1. the screen ──────────────────────────────────────────────────
   One rhythm for everything the two views stack. */
body.hostna-blog .os-scroll--doc > * + * { margin-top: 20px; }
body.hostna-os-page .bl-screen { display: flex; flex-direction: column; gap: 18px; }


/* ── 2. the header strip ────────────────────────────────────────────
   Shaped like an application screen header — title, count and the
   controls on one line — rather than like a page hero. There is no 3D
   art here on purpose: the covers are the pictures on this screen. */
body.hostna-os-page .bl-top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
body.hostna-os-page .bl-top__copy h1 {
  font-size: clamp(26px, 2.8vw, 38px);
  line-height: 1.04;
  letter-spacing: -.035em;
  margin-bottom: 6px;
}
body.hostna-os-page .bl-top__copy p {
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 58ch;
}
body.hostna-os-page .bl-top__acts { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
body.hostna-os-page .bl-count {
  font-size: 11.5px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The search well. The same sunk-field shape os.css gives .spot-in, so
   searching the Journal reads as the same control as searching plans. */
body.hostna-os-page .bl-find {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 13px;
  height: 38px;
  border-radius: 12px;
  background: var(--sunk);
  border: 1px solid var(--stroke-2);
  min-width: 250px;
  transition: border-color .2s, box-shadow .2s;
}
body.hostna-os-page .bl-find:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
}
body.hostna-os-page .bl-find__i { width: 16px; height: 16px; flex: 0 0 auto; color: var(--ink-3); }
body.hostna-os-page .bl-find input[type="search"] {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  font-size: 13px;
  color: var(--ink);
  background: none;
  border: 0;
}
body.hostna-os-page .bl-find input[type="search"]::placeholder { color: var(--ink-3); }
/* The well already shows focus; an inner ring would be a second box
   inside the first. */
body.hostna-os-page .bl-find input[type="search"]:focus-visible { outline: none; }


/* ── 3. the topic rail ──────────────────────────────────────────────
   .chip is a class, not an element rule, so an anchor chip needs its
   colour and its underline stated — this is exactly the .mb-chip bug
   os.css:190 records. */
body.hostna-os-page .bl-topics { gap: 7px; }
body.hostna-os-page .bl-topics .chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ink-2);
  text-decoration: none;
}
body.hostna-os-page .bl-topics .chip:hover { color: var(--ink); }
body.hostna-os-page .bl-topics .chip.on { color: var(--ink); }
body.hostna-os-page .bl-topics .chip em {
  font-style: normal;
  font-size: 10.5px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
body.hostna-os-page .bl-topics .chip.on em { color: var(--accent); }


/* ── 4. the grid ────────────────────────────────────────────────────
   .bento carries min-height:100% so it fills the application window.
   On a document that stretches the rows and opens the gaps the tablet
   note describes (os-tablet.css:406). A listing is content-height, so
   both are turned off here — at every width, not just on tablets. */
body.hostna-os-page .bl-bento {
  min-height: 0;
  align-content: start;
  grid-auto-rows: minmax(0, auto);
  gap: 14px;
}


/* ── 5. an article tile ─────────────────────────────────────────────
   .tile supplies the glass, the radius, the hover lift and overflow:
   clip. Only the padding is dropped, so the cover can reach the edge;
   the text pads itself. */
body.hostna-os-page .bl-tile { padding: 0; gap: 0; }
body.hostna-os-page .bl-tile__hit {
  display: flex;
  flex-direction: column;
  height: 100%;
  color: var(--ink);
  text-decoration: none;
}

body.hostna-os-page .bl-tile__cover {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  flex: 0 0 auto;
  background: var(--sunk);
  overflow: clip;
}
body.hostna-os-page .bl-tile__cover img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  transition: transform .5s var(--ease);
}
body.hostna-os-page .bl-tile:hover .bl-tile__cover img { transform: scale(1.035); }

/* The label sits on the cover. .tile is overflow:clip and os.css:2260
   records what happens when a badge is pinned outside a clipped box —
   it was read as "NV" at every width. This one is inside the cover,
   which is the box it is pinned to. */
body.hostna-os-page .bl-tile__flag {
  position: absolute;
  left: 11px;
  bottom: 11px;
  color: var(--ink);
  background: color-mix(in srgb, var(--bg-base) 58%, transparent);
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  border: 1px solid var(--stroke-2);
}

body.hostna-os-page .bl-tile__body {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 14px 16px 15px;
  flex: 1 1 auto;
  min-height: 0;
}
body.hostna-os-page .bl-tile__kicker {
  font-size: 10.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ink-3);
}
/* h2/h3 are clamp()-sized globally (os.css:314) and far too large for a
   card title, which is why the title is a <b> — the same choice
   .os-cards and .os-siblings make. */
body.hostna-os-page .bl-tile__body > b {
  font-size: 15px;
  font-weight: 620;
  line-height: 1.28;
  letter-spacing: -.014em;
  color: var(--ink);
}
body.hostna-os-page .bl-tile:hover .bl-tile__body > b { color: var(--accent); }
body.hostna-os-page .bl-tile__dek {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-3);
}
body.hostna-os-page .bl-tile .bl-meta { margin-top: auto; padding-top: 10px; }


/* ── 6. the promoted tile ───────────────────────────────────────────
   Same tile, laid on its side: at span-8 the cover takes the left half
   and the copy is centred against it. */
body.hostna-os-page .bl-tile--lead .bl-tile__hit {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
}
body.hostna-os-page .bl-tile--lead .bl-tile__cover { aspect-ratio: auto; height: 100%; min-height: 260px; }
body.hostna-os-page .bl-tile--lead .bl-tile__body {
  justify-content: center;
  gap: 9px;
  padding: clamp(18px, 2vw, 28px);
}
body.hostna-os-page .bl-tile--lead .bl-tile__body > b {
  font-size: clamp(18px, 1.7vw, 23px);
  line-height: 1.2;
  letter-spacing: -.022em;
}
body.hostna-os-page .bl-tile--lead .bl-tile__dek { font-size: 13.5px; color: var(--ink-2); }
body.hostna-os-page .bl-tile--lead .bl-meta { margin-top: 4px; padding-top: 0; }


/* ── 7. covers, and the art that stands in for one ──────────────────
   object-fit appears nowhere in the OS layer; there is no cover-crop
   utility to inherit. A post with no featured image gets its 3D piece
   instead of a grey rectangle — the pipeline that fills this blog can
   fail to attach an image and the tile must still look finished.

   ABSOLUTE, and this is not cosmetic: in flow the art is a child with
   height:100% inside a box whose height comes from aspect-ratio, the
   two resolve against each other, and the SVG's intrinsic height wins.
   Measured: every cover with art was 250px tall in a 141px box. */
body.hostna-os-page .blog-cover__art {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 7%;
  background:
    radial-gradient(120% 100% at 26% 12%, color-mix(in srgb, var(--accent) 17%, transparent), transparent 62%),
    radial-gradient(110% 90% at 82% 88%, color-mix(in srgb, var(--accent-2) 16%, transparent), transparent 60%),
    var(--sunk);
}
body.hostna-os-page .blog-cover__art svg { width: 100%; height: auto; max-height: 100%; display: block; }


/* ── 8. meta lines, empty state, pager ──────────────────────────────*/
body.hostna-os-page .bl-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 11.5px;
  /* --ink-2, not --ink-3: at .42 alpha on --tile this measured about
     3.4:1 and 11.5px text needs 4.5:1 — and a publication date is not
     incidental. */
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
/* The separator is an element rather than a ::before on the item after
   it, so a wrapped line never begins with a stray dot. */
body.hostna-os-page .bl-meta i {
  width: 3px; height: 3px; border-radius: 50%;
  background: currentColor; opacity: .5; flex: 0 0 auto;
}

body.hostna-os-page .bl-empty { padding: clamp(24px, 3vw, 40px); gap: 12px; }
body.hostna-os-page .bl-empty h2 { font-size: clamp(20px, 2vw, 26px); }
body.hostna-os-page .bl-empty .chip { color: var(--ink-2); text-decoration: none; }
body.hostna-os-page .bl-empty .chip:hover { color: var(--ink); }

body.hostna-os-page .bl-pager ul {
  display: flex; justify-content: center; align-items: center;
  flex-wrap: wrap; gap: 7px; list-style: none; padding: 0; margin: 0;
}
body.hostna-os-page .bl-pager .page-numbers {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 34px; padding: 0 12px;
  border-radius: 99px; font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2); text-decoration: none;
  background: var(--tile); border: 1px solid var(--stroke-2);
  transition: .2s;
}
body.hostna-os-page .bl-pager a.page-numbers:hover {
  background: var(--tile-hover); color: var(--ink); transform: translateY(-1px);
}
body.hostna-os-page .bl-pager .page-numbers.current {
  color: var(--ink);
  background: linear-gradient(180deg, rgba(255, 255, 255, .24), rgba(255, 255, 255, .08));
  border-color: var(--stroke);
  box-shadow: inset 0 1px 0 var(--spec);
}
html[data-theme="light"] body.hostna-os-page .bl-pager .page-numbers.current { background: #fff; }
body.hostna-os-page .bl-pager .page-numbers.dots { background: none; border-color: transparent; }


/* ── 9. the article header ──────────────────────────────────────────*/
body.hostna-os-page .bl-head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: 22px;
  align-items: center;
}
body.hostna-os-page .bl-head__copy { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
body.hostna-os-page .bl-head__cat { color: var(--ink-2); text-decoration: none; }
body.hostna-os-page .bl-head__cat:hover { color: var(--ink); }
body.hostna-os-page .bl-head h1 {
  font-size: clamp(25px, 2.7vw, 38px);
  line-height: 1.06;
  letter-spacing: -.032em;
  max-width: 20ch;
}
body.hostna-os-page .bl-head__lead {
  font-size: 14.5px;
  line-height: 1.58;
  color: var(--ink-2);
  max-width: 48ch;
}
/* No cover, no second column — see the note in hostna_blog_render_article_head().
   The measures widen with it: 20ch is right for a title beside an image and
   cramped for one that owns the row. */
body.hostna-os-page .bl-head--bare { grid-template-columns: 1fr; }
body.hostna-os-page .bl-head--bare h1 { max-width: 26ch; }
body.hostna-os-page .bl-head--bare .bl-head__lead { max-width: 62ch; font-size: 15px; }

body.hostna-os-page .bl-cover { padding: 0; overflow: clip; aspect-ratio: 16 / 9; }
body.hostna-os-page .bl-cover img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 0; }


/* ── 10. the reading column ─────────────────────────────────────────
   The rail leads, because it is a contents list and a contents list
   that comes after its contents is decoration. */
body.hostna-os-page .bl-cols {
  display: grid;
  grid-template-columns: 252px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
body.hostna-os-page .bl-main { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
body.hostna-os-page .bl-rail { display: flex; flex-direction: column; gap: 14px; }


/* ── 11. the contents rail ──────────────────────────────────────────
   z-index 6, above .win::before (os.css:245, z-index 5) and far below
   the menubar at 30 that it has to scroll under. The offset is the
   menubar's own height: it is position:sticky;top:0 here
   (os-page.css:52). */
body.hostna-os-page .bl-toc {
  position: sticky;
  top: calc(var(--bar-h) + 14px);
  z-index: 6;
  padding: 13px 6px 13px 14px;
  max-height: calc(100dvh - var(--bar-h) - 44px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
body.hostna-os-page .bl-toc ol {
  list-style: none; padding: 0; margin: 0;
  border-left: 1px solid var(--stroke-2);   /* the guide the markers sit against */
}
body.hostna-os-page .bl-toc li { position: relative; }
body.hostna-os-page .bl-toc a {
  display: block;
  padding: 5px 10px 5px 12px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink-3);
  text-decoration: none;
  border-left: 2px solid transparent;
  margin-left: -1px;
  transition: color .2s, border-color .2s;
}
body.hostna-os-page .bl-toc li.lv-3 a { padding-left: 24px; font-size: 12px; }
body.hostna-os-page .bl-toc a:hover { color: var(--ink-2); }
/* Set by assets/js/os-blog.js. Without that file every entry is a plain
   working anchor and only this highlight is missing. */
body.hostna-os-page .bl-toc a.is-here { color: var(--ink); border-left-color: var(--accent); }

/* Headings must clear the sticky menubar when an anchor is followed.
   76px is the value .sv-sec already uses (os-page.css:930). */
body.hostna-os-page .bl-article :where(h2, h3) { scroll-margin-top: 76px; }


/* ── 12. the product this article implies ───────────────────────────*/
body.hostna-os-page .bl-promo {
  align-items: flex-start;
  gap: 7px;
  background:
    linear-gradient(160deg, color-mix(in srgb, var(--accent) 11%, transparent), transparent 58%),
    var(--tile);
}
body.hostna-os-page .bl-promo > b { font-size: 15px; font-weight: 620; color: var(--ink); }
body.hostna-os-page .bl-promo p { margin: 0; }
body.hostna-os-page .bl-promo p.bl-promo__price {
  display: flex; align-items: baseline; gap: 5px; margin-top: 2px;
}
body.hostna-os-page .bl-promo__price span { font-size: 11.5px; color: var(--ink-3); }
body.hostna-os-page .bl-promo__price em {
  font-style: normal; font-size: 22px; font-weight: 640;
  letter-spacing: -.03em; color: var(--ink);
}
body.hostna-os-page .bl-promo__price i { font-style: normal; font-size: 11.5px; color: var(--ink-3); }
/* Not fine print. § 19 (1) UStG is what makes the number above the final
   number; the sentence is part of the price, not a footnote to it. */
body.hostna-os-page .bl-promo p.bl-promo__vat { font-size: 10.5px; line-height: 1.45; color: var(--ink-3); }
body.hostna-os-page .bl-promo .prime-btn { margin-top: 6px; color: #fff; text-decoration: none; }


/* ── 13. article prose ──────────────────────────────────────────────
   .os-doc covers h2, h3, p, li, a, table, img, pre, dl. It does not
   cover h4, h5, blockquote, figure, figcaption, hr, inline code, mark,
   small, sup or strong — and `*{margin:0;padding:0}` (os.css:9) means
   those have no browser default left either.

   Every rule is (0,2,1), the same as the .os-doc :where(…) rule it
   extends, and prints later — so it wins the tie by source order. */
body.hostna-os-page .bl-article {
  padding: clamp(22px, 3vw, 40px);
  background: var(--tile);
  gap: 0;
}

/* Measure. Nothing constrains line length inside .os-doc, so a
   paragraph at 1440px runs to about 90 characters. The house measures
   are 54-68ch; 68 is the widest and right for long-form. */
body.hostna-os-page .bl-article :where(p, li, blockquote, dd) { max-width: 68ch; }

body.hostna-os-page .bl-article :where(h4) {
  font-size: 15.5px; line-height: 1.35; font-weight: 620;
  letter-spacing: -.01em; color: var(--ink); margin: 20px 0 6px;
}
body.hostna-os-page .bl-article :where(h5, h6) {
  font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-3); margin: 18px 0 6px;
}
body.hostna-os-page .bl-article :where(strong, b) { color: var(--ink); font-weight: 620; }

body.hostna-os-page .bl-article :where(blockquote) {
  margin: 20px 0; padding: 4px 0 4px 18px;
  border-left: 3px solid var(--accent);
  font-size: 15.5px; line-height: 1.55; color: var(--ink);
}
body.hostna-os-page .bl-article :where(blockquote p) { margin-bottom: 8px; font-size: inherit; color: inherit; }
body.hostna-os-page .bl-article :where(blockquote p:last-child) { margin-bottom: 0; }
body.hostna-os-page .bl-article :where(blockquote cite) {
  display: block; font-style: normal; font-size: 12px; color: var(--ink-3);
}

body.hostna-os-page .bl-article :where(figure) { margin: 22px 0; }
body.hostna-os-page .bl-article :where(figcaption) {
  margin-top: 8px; font-size: 12px; line-height: 1.5; color: var(--ink-3);
}
body.hostna-os-page .bl-article :where(hr) {
  height: 1px; border: 0; background: var(--stroke-2); margin: 28px 0;
}

/* The inline monospace token, matching .path (os.css:984). */
body.hostna-os-page .bl-article :where(code) {
  font: 12.5px/1.5 "SF Mono", ui-monospace, Menlo, Consolas, monospace;
  padding: 2px 6px; border-radius: 7px;
  background: var(--sunk); border: 1px solid var(--stroke-2);
  color: var(--ink-2); word-break: break-word;
}
body.hostna-os-page .bl-article :where(pre) code {
  padding: 0; border: 0; background: none; font-size: 13px; word-break: normal;
}
/* <pre> is overflow-x:auto (os-page.css:203) but os-chrome.css:231
   removes every scrollbar on this surface, so a wide code block scrolls
   with nothing to say that it can. The fade is the only cue left. */
body.hostna-os-page .bl-article :where(pre) {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
          mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
}

body.hostna-os-page .bl-article :where(mark) {
  background: color-mix(in srgb, var(--warn) 26%, transparent);
  color: var(--ink); padding: 1px 4px; border-radius: 5px;
}
body.hostna-os-page .bl-article :where(small) { font-size: 12px; color: var(--ink-3); }
body.hostna-os-page .bl-article :where(sup, sub) { font-size: 10px; line-height: 0; }

/* A table wide enough to push the window is the one failure mode that
   breaks the whole layout rather than one block; .os-doc styles tables
   but wraps nothing. */
body.hostna-os-page .bl-article :where(table) { display: block; overflow-x: auto; max-width: 100%; }

body.hostna-os-page .bl-article :where(p, li, dd) a {
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent);
  text-underline-offset: 3px;
}
body.hostna-os-page .bl-article :where(p, li, dd) a:hover { text-decoration-color: var(--accent); }
/* An outbound link opened in a new tab, announced. */
body.hostna-os-page .bl-article a[target="_blank"]::after {
  content: "↗"; font-size: .78em; margin-left: 2px; color: var(--ink-3); text-decoration: none;
}


/* ── 14. the in-body promotional box ────────────────────────────────
   Rendered by inc/blog-ingest.php from a [promo:slug] token when the
   page is served, so its price is always the catalogue's. Two per
   article, capped in the resolver.

   Styled to read as an ADVERT and not as a paragraph. That is the
   § 5a UWG point in visual form: editorial-looking content promoting
   the trader's own goods is the offence, so the box that promotes has
   to look unlike the prose around it. */
body.hostna-os-page .blog-inline-promo {
  display: block;
  clear: both;
  margin: 26px 0;
  padding: 18px 20px;
  border-radius: var(--r-tile);
  background:
    linear-gradient(150deg, color-mix(in srgb, var(--accent) 12%, transparent), transparent 60%),
    var(--tile);
  border: 1px solid var(--stroke-2);
  box-shadow: inset 0 1px 0 var(--spec);
  max-width: none;
}
body.hostna-os-page .blog-inline-promo .eyebrow { margin-bottom: 6px; }
body.hostna-os-page .blog-inline-promo > b {
  display: block; font-size: 16px; font-weight: 620; color: var(--ink); margin-bottom: 4px;
}
body.hostna-os-page .blog-inline-promo p { margin: 0 0 6px; font-size: 13.5px; color: var(--ink-2); max-width: 62ch; }
body.hostna-os-page .blog-inline-promo p.blog-inline-promo__price {
  display: flex; align-items: baseline; gap: 5px; margin: 8px 0 2px;
}
body.hostna-os-page .blog-inline-promo__price span { font-size: 12px; color: var(--ink-3); }
body.hostna-os-page .blog-inline-promo__price em {
  font-style: normal; font-size: 24px; font-weight: 640; letter-spacing: -.03em; color: var(--ink);
}
body.hostna-os-page .blog-inline-promo__price i { font-style: normal; font-size: 12px; color: var(--ink-3); }
body.hostna-os-page .blog-inline-promo p.blog-inline-promo__vat {
  font-size: 11px; color: var(--ink-3); margin-bottom: 12px;
}
/* .os-doc :where(a) is (0,2,1) and repaints button labels accent blue —
   the trap os-page.css:843 documents. Same shape of fix. */
body.hostna-os-page .blog-inline-promo a.prime-btn { color: #fff; text-decoration: none; }

/* The AI-assistance line. Quiet, but present on every article and not
   collapsible: a disclosure the reader has to open is not a disclosure. */
body.hostna-os-page .blog-disclosure {
  margin-top: 26px; padding-top: 14px;
  border-top: 1px solid var(--stroke-2); max-width: none;
}
body.hostna-os-page .blog-disclosure small { font-size: 11.5px; line-height: 1.55; color: var(--ink-3); }


/* ── 15. questions, tags, prev/next, related ────────────────────────*/
body.hostna-os-page .bl-faqs { padding: clamp(18px, 2.2vw, 26px); gap: 4px; }
body.hostna-os-page .bl-faqs .tile-h { margin-bottom: 6px; }
body.hostna-os-page .bl-faqs .tile-h span { font-size: 15px; font-weight: 620; }
body.hostna-os-page .bl-faqs .os-faq:last-child { border-bottom: 0; padding-bottom: 0; }
/* .os-faq's summary has no focus treatment of its own and list-style:none
   removes the marker, so keyboard focus had nothing to land on visibly. */
body.hostna-os-page .bl-faqs .os-faq summary:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 8px;
}

body.hostna-os-page .bl-taglist .chip { color: var(--ink-2); text-decoration: none; }
body.hostna-os-page .bl-taglist .chip:hover { color: var(--ink); }

body.hostna-os-page .bl-nav {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px;
}
body.hostna-os-page .bl-nav__link { color: var(--ink); text-decoration: none; gap: 4px; }
body.hostna-os-page .bl-nav__link .eyebrow { margin-bottom: 0; }
body.hostna-os-page .bl-nav__link b { font-size: 14px; font-weight: 600; line-height: 1.35; }
body.hostna-os-page .bl-nav__link:hover b { color: var(--accent); }
body.hostna-os-page .bl-nav__link--next { text-align: right; align-items: flex-end; }
/* :only-child, not :last-child — with both neighbours present the second
   card must stay in its own column. */
body.hostna-os-page .bl-nav__link--next:only-child { grid-column: -2; }

body.hostna-os-page .bl-related__h { font-size: clamp(18px, 1.7vw, 23px); margin-bottom: 12px; }
body.hostna-os-page .bl-related__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(228px, 1fr)); gap: 12px;
}
body.hostna-os-page .bl-related__card {
  color: var(--ink); text-decoration: none; gap: 6px; padding: 15px 17px;
}
body.hostna-os-page .bl-related__card b { font-size: 14px; font-weight: 620; line-height: 1.3; }
body.hostna-os-page .bl-related__card:hover b { color: var(--accent); }


/* ── 16. reading progress ───────────────────────────────────────────
   A hairline across the foot of the window's title bar. Written by
   assets/js/os-blog.js into .winbar, which is position:relative in
   os.css; with the script blocked the element never exists. */
body.hostna-os-page .blog-progress {
  position: absolute; left: 0; bottom: 0;
  height: 2px; width: 0;
  border-radius: 0 2px 2px 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  pointer-events: none; z-index: 6;
}


/* ── 17. wide desktops ──────────────────────────────────────────────*/
@media (min-width: 1440px) {
  body.hostna-os-page .bl-cols { grid-template-columns: 276px minmax(0, 1fr); gap: 28px; }
}


/* ── 18. one column ─────────────────────────────────────────────────
   1180 is os.css's own two-column collapse (os.css:1311) and the width
   at which a 252px rail plus 68ch of prose stops fitting.

   The rail does not simply move: display:contents dissolves the wrapper
   so its two children can be ordered around the article — contents
   first, where a reader looks for it, promo last, after the argument it
   follows from. No markup is duplicated, so there is one set of anchors
   and one tab order at every width. */
@media (max-width: 1180px) {
  body.hostna-os-page .bl-cols {
    display: flex; flex-direction: column;
    /* stretch, and it is load-bearing: the grid needs `start` so the
       sticky rail does not stretch to the article's height, and
       carrying that into the flex fallback made every child
       shrink-to-fit — the rail then sized to the max-content width of a
       row of nowrap chips and the page scrolled 355px sideways. */
    align-items: stretch;
    gap: 18px;
  }
  body.hostna-os-page .bl-rail { display: contents; }
  body.hostna-os-page .bl-toc { order: 1; }
  body.hostna-os-page .bl-main { order: 2; }
  body.hostna-os-page .bl-promo { order: 3; align-self: stretch; }

  /* Sticky is switched off rather than re-anchored: a horizontal rail
     pinned under the menubar covers the paragraph the reader is on. */
  body.hostna-os-page .bl-toc {
    position: static;
    max-height: none;
    overflow: hidden;
    min-width: 0;
    max-width: 100%;
    padding: 12px 14px;
    flex-direction: row;
    align-items: center;
    gap: 12px;
  }
  body.hostna-os-page .bl-toc .tile-h { flex: 0 0 auto; }
  body.hostna-os-page .bl-toc ol {
    display: flex; gap: 6px;
    /* min-width:0 — a flex item's automatic minimum size is its content,
       and an overflow scroller is exempt only once it is told so. */
    min-width: 0; flex: 1 1 auto;
    overflow-x: auto;
    border-left: 0;
    scroll-snap-type: x proximity;
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 20px), transparent);
            mask-image: linear-gradient(90deg, #000 calc(100% - 20px), transparent);
  }
  /* H3s are the fine grain of the outline; as chips in a row they turn
     a navigation aid into forty of them. The anchors still exist in the
     document — only this rail stops listing them. */
  body.hostna-os-page .bl-toc li.lv-3 { display: none; }
  body.hostna-os-page .bl-toc a {
    white-space: nowrap; scroll-snap-align: start;
    padding: 6px 12px; border-radius: 99px;
    border: 1px solid var(--stroke-2); border-left-width: 1px;
    margin-left: 0; background: var(--sunk);
  }
  body.hostna-os-page .bl-toc a.is-here {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 14%, transparent);
  }

  body.hostna-os-page .bl-head { grid-template-columns: 1fr; gap: 16px; }
  body.hostna-os-page .bl-head h1 { max-width: none; }
}


/* ── 19. tablet and below ───────────────────────────────────────────
   .span-N already reflows through os-tablet.css (901-1200) and os.css
   (≤900, ≤560); only the lead tile's internal split needs saying. */
@media (max-width: 900px) {
  body.hostna-os-page .bl-tile--lead .bl-tile__hit { grid-template-columns: 1fr; }
  body.hostna-os-page .bl-tile--lead .bl-tile__cover { aspect-ratio: 16 / 9; min-height: 0; }
  body.hostna-os-page .bl-top { align-items: flex-start; }
  body.hostna-os-page .bl-top__acts { width: 100%; }
  body.hostna-os-page .bl-find { flex: 1 1 auto; min-width: 0; }
}

@media (max-width: 700px) {
  /* ONE WINDOW BOX. The window keeps its 6px margin and 20px corner;
     the inner inset is --os-pad horizontally and the document's own
     clamp vertically (os-chrome.css:361). Nothing goes full-bleed. */
  body.hostna-blog .os-scroll--doc > * + * { margin-top: 16px; }
  body.hostna-os-page .bl-screen { gap: 14px; }
  body.hostna-os-page .bl-bento { gap: 12px; }
  body.hostna-os-page .bl-article { padding: 18px 16px; }
  body.hostna-os-page .bl-nav { grid-template-columns: 1fr; }
  body.hostna-os-page .bl-nav__link--next { text-align: left; align-items: flex-start; }
  /* The menubar is display:none below 700 (os-chrome.css:268), so the
     anchor offset that cleared it is a gap with nothing in it. */
  body.hostna-os-page .bl-article :where(h2, h3) { scroll-margin-top: 16px; }
}

@media (max-width: 560px) {
  body.hostna-os-page .bl-toc { flex-direction: column; align-items: stretch; gap: 8px; }
  body.hostna-os-page .bl-pager .page-numbers { min-width: 40px; height: 40px; }
}


/* ── 20. touch ──────────────────────────────────────────────────────
   The same correction os-tablet.css makes for every other hover
   surface: a tap sets :hover and leaves it set, so a tile the reader
   merely passed through stays lifted and lit. The :not() guard on the
   contents rail is load-bearing for the same reason os-tablet.css:150
   gives — .is-here is a state declared before this block, and a flat
   override would put it out. */
@media (pointer: coarse) {
  body.hostna-os-page .bl-tile:hover .bl-tile__cover img { transform: none; }
  body.hostna-os-page .bl-tile:hover .bl-tile__body > b,
  body.hostna-os-page .bl-nav__link:hover b,
  body.hostna-os-page .bl-related__card:hover b { color: var(--ink); }
  body.hostna-os-page .bl-pager a.page-numbers:hover { transform: none; background: var(--tile); }
  body.hostna-os-page .bl-toc a:not(.is-here):hover { color: var(--ink-3); }

  /* 44px is the target size os.css:2052 uses everywhere else. */
  body.hostna-os-page .bl-topics .chip,
  body.hostna-os-page .bl-taglist .chip,
  body.hostna-os-page .bl-toc a { min-height: 44px; display: flex; align-items: center; }
  body.hostna-os-page .bl-pager .page-numbers { min-width: 44px; height: 44px; }
}


/* ── 21. reduced motion ─────────────────────────────────────────────*/
@media (prefers-reduced-motion: reduce) {
  body.hostna-os-page .bl-tile__cover img,
  body.hostna-os-page .bl-pager .page-numbers { transition: none; }
  body.hostna-os-page .bl-tile:hover .bl-tile__cover img { transform: none; }
  body.hostna-os-page .bl-pager a.page-numbers:hover { transform: none; }
  body.hostna-os-page .bl-toc ol { scroll-snap-type: none; }
}


/* ── 22. the desktop chrome lives in assets/css/os-desktop.css ──────
   The window, the wallpaper, the glass and the print unwind used to be
   here, scoped to body.hostna-blog. They now apply to every document
   surface, so they moved to os-desktop.css rather than being copied —
   two definitions of one window is how the Journal and the service
   pages start drifting apart. This file keeps only what is the blog's:
   the bento listing, the article's reading column and its prose. */
