/* ===========================================================================
   DvaDoma, BLOG (lb-* namespace). Loaded only on /blog pages, on top of
   tokens.css + dvadoma.css + landing.css (the public shell: nav, footer, the
   body.lp box-sizing reset and the one .dd-container grid).

   Index:    masthead, search, then the articles as plain text rows.
   Article:  a centred reading column with the table of contents in a right rail.
   Both:     one quiet product note at the foot of the page, and nothing else
             selling anything anywhere above it.

   No cover art, no category labels, no tags, no badges, no card walls. The blog
   is writing, so type and hairlines carry it.

   House rules that shape everything below (docs/SESSION-HANDOFF §standing):
     - no coloured stripe pinned to the edge of a card, on any side
     - no emoji, no serif, no tinted pill badges
     - no em dash anywhere, in any language
     - one box model and one content grid, shared with the nav and the footer
   =========================================================================== */

/* ── shared chrome ───────────────────────────────────────────────────── */

.lb-page { padding-block: 2.6rem 4.5rem; }
/* NO max-width here, EVER (settled 2026-08-26 the hard way, four rounds).
   The project rule that tools/audit-layout.js enforces (QA BULGU 34) is:
   every page wrapper shares the nav's exact content edges. Blog content
   therefore FILLS this grid: the list as stacked full-width rows, the
   article as a stretching text column plus the fixed rail (see .lb-art-grid).
   Every earlier variant (left-pinned reading measure, centred 68rem frame,
   narrow list column) made content narrower than the page and was rejected
   by the user. Run `node tools/audit-layout.js` before calling ANY change to
   this file done. */

.lb-crumbs { display:flex; flex-wrap:wrap; align-items:center; gap:.45rem;
  font-size:var(--dd-fs-sm); color:var(--dd-muted); margin:0 0 1.6rem; padding:0; list-style:none; }
.lb-crumbs li { display:flex; align-items:center; gap:.45rem; min-width:0; }
.lb-crumbs li + li::before { content:"/"; color:var(--dd-border-strong); }
.lb-crumbs a { color:var(--dd-muted); text-decoration:none; }
.lb-crumbs a:hover { color:var(--dd-primary); }
.lb-crumbs [aria-current="page"] { color:var(--dd-text-2); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; max-width:34ch; }
/* On a phone an article title is longer than the screen, so the last crumb wraps
   to its own line behind a stray separator and the trail reads as broken. Drop
   it: the H1 sits directly below and says the same thing, and the full trail is
   still published in the BreadcrumbList JSON-LD, so nothing is lost to a
   crawler. Hiding the <li> takes its "/" with it, because the separator is
   drawn by li + li::before. */
@media (max-width:700px){
  .lb-crumbs li:last-child { display:none; }
}

/* One muted line of facts: published, revised, reading time. Never chips. */
.lb-meta { display:flex; flex-wrap:wrap; align-items:center; gap:.5rem; margin:0;
  font-size:var(--dd-fs-sm); color:var(--dd-muted); }
.lb-meta > * + *::before { content:"\00b7"; margin-right:.5rem; color:var(--dd-border-strong); }

/* The article byline spells out "Objavljeno" and "Posodobljeno", so it is long
   enough to wrap, and a dot separator drawn with ::before then lands at the START
   of the wrapped line as a stray bullet. The labels already do the separating
   there, so the dots come off and the items are held apart by a wider gap
   instead. The list rows keep their dots: their dates carry no label. */
.lb-art-head .lb-meta { gap:.3rem 1.35rem; }
.lb-art-head .lb-meta > * + *::before { content:none; margin-right:0; }
/* On a phone the three facts cannot share two lines without one of them ending
   up stranded beside another, so each takes its own row. Predictable at every
   width, and the labels read as a short record rather than a broken sentence. */
@media (max-width:700px){
  .lb-art-head .lb-meta { flex-direction:column; align-items:flex-start; gap:.2rem; }
}
/* Reading time is a different KIND of fact from the two dates: an estimate about
   the reader's time, not a record of the article's. So it is set apart, and the
   three lines stop reading as one grey block.
   The shift is in HUE, not lightness: a lighter grey is the obvious move and it
   is the wrong one, because --dd-faint is marked decorative-only in tokens.css
   and measures about 2.4:1 on this paper, well under the 4.5:1 AA floor for body
   text. The ochre is darker than the greys it sits beside, so it stays legible
   while clearly not being one of them.
   Not --dd-secondary-dark: that token measures exactly 4.50:1 here, the AA floor
   with no margin at all. This is one step darker. It is a literal because there
   is no darker ochre in tokens.css yet; if one is added, swap it in. */
.lb-art-head .lb-meta > span:last-child { color:#7B5E20; }

/* ── masthead ────────────────────────────────────────────────────────── */

.lb-masthead { display:grid; gap:.9rem; max-width:640px; }
.lb-h1 { margin:0; font-size:clamp(2rem, 4.2vw, 2.8rem); line-height:1.08; letter-spacing:-.03em;
  font-weight:var(--dd-fw-bold); color:var(--dd-text); }
.lb-lead { margin:0; font-size:var(--dd-fs-lg); line-height:1.6; color:var(--dd-muted); }

/* ── search ──────────────────────────────────────────────────────────── */

/* A real <label>, kept off-screen rather than removed, so the control is
   announced without adding a second visible heading. */
.lb-sr { 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; }

.lb-search { display:flex; gap:.5rem; margin-top:.6rem; max-width:480px; }
.lb-search-field { position:relative; flex:1; min-width:0; }
/* The magnifier is drawn with a border and a rule: no icon font, no image
   request, so a strict CSP cannot break it. */
.lb-search-field::before { content:""; position:absolute; left:.95rem; top:50%; width:12px; height:12px;
  margin-top:-8px; border:2px solid var(--dd-faint); border-radius:50%; pointer-events:none; }
.lb-search-field::after { content:""; position:absolute; left:1.6rem; top:50%; width:2px; height:7px;
  margin-top:1px; background:var(--dd-faint); transform:rotate(-45deg); border-radius:2px; pointer-events:none; }
.lb-search input { width:100%; min-height:46px; padding:.6rem .9rem .6rem 2.5rem;
  font-family:inherit; font-size:.98rem; color:var(--dd-text); background:var(--dd-surface);
  border:1px solid var(--dd-border-strong); border-radius:var(--dd-radius-input);
  transition:border-color var(--dd-transition), box-shadow var(--dd-transition); }
.lb-search input::placeholder { color:var(--dd-faint); }
.lb-search input:focus { outline:none; border-color:var(--dd-primary); box-shadow:var(--dd-focus-ring); }
.lb-search button { flex:none; min-height:46px; padding:.6rem 1.2rem; font-family:inherit;
  font-size:.95rem; font-weight:var(--dd-fw-semibold); color:var(--dd-text); cursor:pointer;
  background:var(--dd-surface); border:1px solid var(--dd-border-strong);
  border-radius:var(--dd-radius-input); transition:border-color var(--dd-transition), color var(--dd-transition); }
.lb-search button:hover { border-color:var(--dd-primary); color:var(--dd-primary); }
@media (max-width:520px){
  .lb-search { flex-direction:column; max-width:none; }
  .lb-search button { width:100%; }
}

/* ── search result state ─────────────────────────────────────────────── */

.lb-result { margin-top:2.4rem; padding-bottom:.9rem; border-bottom:1px solid var(--dd-border);
  display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between; gap:.5rem 1rem; }
.lb-result p { margin:0; font-size:1rem; color:var(--dd-text-2); }
.lb-result b { font-weight:var(--dd-fw-semibold); color:var(--dd-text); }
.lb-result a { font-size:var(--dd-fs-sm); color:var(--dd-primary); text-decoration:none; }
.lb-result a:hover { text-decoration:underline; text-underline-offset:3px; }

.lb-empty { margin-top:2.4rem; padding:3rem 1.5rem; text-align:center;
  border-top:1px solid var(--dd-border); }
.lb-empty h2 { margin:0 0 .5rem; font-size:1.15rem; font-weight:var(--dd-fw-bold); letter-spacing:-.016em; }
.lb-empty p { margin:0 auto; max-width:44ch; color:var(--dd-muted); font-size:.98rem; line-height:1.6; }

/* ══════════════════════════════════════════════════════════════════════
   THE LIST. Text only: title, one line of summary, the dates.
   ══════════════════════════════════════════════════════════════════════ */

.lb-sec { margin-top:3rem; }
.lb-sec-h { margin:0 0 .2rem; padding-bottom:.8rem; border-bottom:1px solid var(--dd-border); }
.lb-sec-h h2 { margin:0; font-size:var(--dd-fs-xs); text-transform:uppercase; letter-spacing:.13em;
  font-weight:var(--dd-fw-semibold); color:var(--dd-muted); }

.lb-posts { margin:0; padding:0; list-style:none; display:grid; }
.lb-post { border-bottom:1px solid var(--dd-hair); }

/* A row is a STACK: title, one line of summary, then the small meta line.
   Meta beside the title was tried on 2026-08-26 and rejected by the user
   ("iğrenç"); do not bring it back. The row needs no max-width of its own:
   the list page's narrow centred frame (see .lb-page) IS the measure. */
.lb-post-link { display:grid; gap:.4rem; padding:1.7rem 0; text-decoration:none; color:inherit; }
.lb-post-title { margin:0; font-size:1.3rem; line-height:1.28; letter-spacing:-.021em;
  font-weight:var(--dd-fw-semibold); color:var(--dd-text); }
/* No underline on hover: the row is already obviously a link, and the rule
   under a 1.3rem title reads like a 1990s index page. Colour carries it. */
.lb-post-link:hover .lb-post-title { color:var(--dd-primary); }
.lb-post-dek { margin:0; color:var(--dd-muted); font-size:.98rem; line-height:1.58; }
.lb-post-link:focus-visible { outline:none; box-shadow:var(--dd-focus-ring); border-radius:var(--dd-radius-sm); }

/* ══════════════════════════════════════════════════════════════════════
   ARTICLE
   ══════════════════════════════════════════════════════════════════════ */

/* The measure cap sits on the TITLE, not the whole header: the hr below the
   byline must run the full container width so the page's right edge is the
   same line the header and footer already draw. A capped header block left the
   rule hanging mid-air at ~70ch. */
.lb-art-h1 { margin:0 0 .9rem; max-width:70ch; font-size:clamp(1.75rem, 3.2vw, 2.35rem); line-height:1.12;
  letter-spacing:-.03em; font-weight:var(--dd-fw-bold); text-wrap:balance; }
.lb-art-hr { border:0; border-top:1px solid var(--dd-border); margin:1.5rem 0 0; }

/* Reading column first in the source, the rail after it. */
.lb-art-grid { display:grid; grid-template-columns:1fr; gap:2.4rem; margin-top:2.2rem; }
/* A grid item defaults to min-width:auto, so a wide child (a table) would stretch
   its column and scroll the PAGE sideways instead of scrolling itself. */
.lb-art-grid > * { min-width:0; }
/* Fixed columns, not 1fr, so the text keeps its reading measure. The columns
   are pushed APART: prose on the site's one left margin, rail flush with the
   container's right edge, i.e. the same two lines the header and footer draw.
   justify-content:start was wrong: it packed both columns left and left a dead
   hole between the rail and the page's right edge (user report 2026-08-26).
   The spare width now lives BETWEEN text and rail, where a gutter reads as
   intentional; gap is the floor it never shrinks under. */
@media (min-width:1080px){
  .lb-art-grid { grid-template-columns:minmax(0,1fr) 15.5rem; gap:3.5rem;
    align-items:start; }
}

/* ── table of contents ───────────────────────────────────────────────── */

/* The rail sticks as ONE block, so the contents and the product card below it
   travel together. Sticking the <nav> alone would have left the card behind. */
.lb-col-toc { position:sticky; top:5.5rem; }
/* Indented to the same x as the entry text below it. The list sits behind a
   hairline spine and its links carry .85rem of padding, so a heading flush with
   the rail's own edge would hang left of everything it labels. */
.lb-toc-t { margin:0 0 .7rem; padding-left:.85rem; font-size:var(--dd-fs-xs);
  text-transform:uppercase; letter-spacing:.11em;
  font-weight:var(--dd-fw-semibold); color:var(--dd-muted); }
/* Both renderings of the contents share these. The mobile disclosure is a
   SIBLING of .lb-toc, not a child, so rules scoped to .lb-toc alone never
   reached it and the phone got the browser default: decimal markers and blue
   underlined links. Style them together and that cannot happen again. */
.lb-toc ol, .lb-toc-m ol { margin:0; padding:0; list-style:none; display:grid; gap:.1rem; }
.lb-toc a, .lb-toc-m a { display:block; color:var(--dd-text-2); text-decoration:none;
  font-size:.87rem; line-height:1.4; }
.lb-toc .is-sub a, .lb-toc-m .is-sub a { color:var(--dd-muted); font-size:.82rem; }

/* rail only: the hairline spine and its hover marker */
.lb-toc ol { border-left:1px solid var(--dd-border); }
.lb-toc a { padding:.32rem 0 .32rem .85rem; margin-left:-1px;
  border-left:1px solid transparent; }
.lb-toc a:hover { color:var(--dd-primary); border-left-color:var(--dd-primary); }
.lb-toc .is-sub a { padding-left:1.6rem; }

/* ── product card in the rail ────────────────────────────────────────── */
/* Sits well below the contents, with real air between them, so it reads as its
   own thing rather than the last entry of the list. Roomy on purpose: generous
   padding, a line of space between every element, and a full-width button. The
   soft petrol ground marks it as the one promotional block on the page, and the
   solid petrol lands on the button alone, which is the only thing here meant to
   be clicked. */
/* The outline is one tick darker than the ground it sits on, so the card has a
   defined edge instead of bleeding into the tint. Derived from the brand petrol
   at low alpha rather than a fixed grey, so it stays in the same family as the
   fill and the button. */
.lb-rail-cta { margin-top:3.4rem; padding:1.6rem 1.4rem 1.5rem;
  background:var(--dd-primary-softer); border:1px solid rgba(30,78,140,.18);
/* Tight gap by default so the line sits right under the heading it belongs to;
   the button buys its own space back below. */
  border-radius:var(--dd-radius-card); display:grid; gap:.4rem; text-align:center; }
.lb-rail-cta-t { margin:0; font-size:1.16rem; line-height:1.22; letter-spacing:-.02em;
  font-weight:var(--dd-fw-bold); color:var(--dd-text); text-wrap:balance; }
.lb-rail-cta-x { margin:0; font-size:.88rem; line-height:1.5; color:var(--dd-text-2);
  text-wrap:balance; }
.lb-rail-cta-b { margin-top:.85rem; display:flex; align-items:center; justify-content:center;
  min-height:46px; padding:.6rem 1rem; border-radius:var(--dd-radius-input); font-size:.92rem;
  font-weight:var(--dd-fw-semibold); text-decoration:none; text-align:center;
  background:var(--dd-primary); color:#fff; border:1px solid var(--dd-primary);
  transition:background var(--dd-transition); }
.lb-rail-cta-b:hover { background:var(--dd-primary-dark); }
.lb-rail-cta-n { margin:.25rem 0 0; font-size:var(--dd-fs-xs); color:var(--dd-muted); }
/* Under 1080px the rail collapses into a disclosure above the text. No JS. */
.lb-toc-m { border:1px solid var(--dd-border); border-radius:var(--dd-radius-md);
  background:var(--dd-surface); padding:.15rem .95rem; margin-bottom:1.8rem; }
.lb-toc-m > summary { list-style:none; cursor:pointer; padding:.8rem 0; font-weight:var(--dd-fw-semibold);
  font-size:.94rem; display:flex; align-items:center; justify-content:space-between; gap:1rem; }
.lb-toc-m > summary::-webkit-details-marker { display:none; }
.lb-toc-m > summary::after { content:""; width:9px; height:9px; border-right:2px solid var(--dd-muted);
  border-bottom:2px solid var(--dd-muted); transform:rotate(45deg) translateY(-2px); transition:transform var(--dd-transition); }
.lb-toc-m[open] > summary::after { transform:rotate(225deg) translateY(-2px); }
.lb-toc-m ol { padding:0 0 .9rem; gap:.15rem; }
.lb-toc-m a { padding:.3rem 0; }
.lb-toc-m .is-sub a { padding-left:1rem; }
.lb-toc-m a:hover { color:var(--dd-primary); }
@media (min-width:1080px){ .lb-toc-m { display:none; } }
@media (max-width:1079.98px){ .lb-col-toc { display:none; } }

/* ── prose ───────────────────────────────────────────────────────────── */

.lb-prose { max-width:68ch; font-size:1.02rem; line-height:1.75; color:var(--dd-text); }
/* On desktop the GRID COLUMN is the one measure authority (46rem at the type
   size below ≈ 77ch): the extra 68ch cap on top of it left the text stopping
   ~100px short of its own column, which read as a too-narrow article (user
   report 2026-08-26). Below 1080px the rail is gone and the column is the full
   container, so there the 68ch cap above stays in charge. */
@media (min-width:1080px){
  .lb-prose { max-width:none; font-size:1.08rem; }
  /* The FAQ/viri block sits in the same column: it must follow the prose out
     to the column edge, not stay on the old 68ch cap. */
  .lb-after { max-width:none; }
}
.lb-prose > * + * { margin-top:1.3em; }
.lb-prose p { margin:0; }
.lb-prose strong { font-weight:var(--dd-fw-semibold); }
.lb-prose a { color:var(--dd-primary-dark); text-decoration:underline; text-underline-offset:3px;
  text-decoration-thickness:1px; text-decoration-color:rgba(30,78,140,.35); }
.lb-prose a:hover { text-decoration-color:currentColor; }
.lb-prose h2 { margin:2.6em 0 0; padding-top:1.1rem; border-top:1px solid var(--dd-hair);
  font-size:1.32rem; line-height:1.25; letter-spacing:-.022em; font-weight:var(--dd-fw-bold); text-wrap:balance; }
.lb-prose h3 { margin:2em 0 0; font-size:1.08rem; line-height:1.32; letter-spacing:-.014em;
  font-weight:var(--dd-fw-semibold); text-wrap:balance; }
.lb-prose h2 + *, .lb-prose h3 + * { margin-top:.7em; }
.lb-prose h2, .lb-prose h3 { scroll-margin-top:5.5rem; }
.lb-prose h2:target, .lb-prose h3:target { background:linear-gradient(transparent 62%, var(--dd-primary-soft) 0); }
.lb-prose ul, .lb-prose ol { margin:0; padding-left:1.3rem; display:grid; gap:.45em; }
.lb-prose li { padding-left:.15rem; }
.lb-prose ul > li::marker { color:var(--dd-border-strong); }
.lb-prose ol > li::marker { color:var(--dd-muted); font-variant-numeric:tabular-nums; font-weight:var(--dd-fw-semibold); }
.lb-prose blockquote { margin:0; padding:.2rem 0 .2rem 1.3rem; border-left:2px solid var(--dd-border-strong);
  color:var(--dd-text-2); }
.lb-prose figure { margin:0; }
.lb-prose figcaption { margin-top:.6rem; font-size:var(--dd-fs-sm); color:var(--dd-muted); }
.lb-prose img { max-width:100%; height:auto; border-radius:var(--dd-radius-md); border:1px solid var(--dd-border); }
.lb-prose code { font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:.92em;
  background:var(--dd-surface-2); border:1px solid var(--dd-hair); border-radius:6px; padding:.1em .35em; }
.lb-prose hr { border:0; border-top:1px solid var(--dd-border); margin:2.4em 0; }

/* Wide content scrolls inside itself, never widens the page.
   Structure the article HTML as:
     <figure class="lb-tablewrap"><div class="lb-tablescroll"><table>…</table></div>
       <figcaption>…</figcaption></figure>
   The caption sits OUTSIDE the scroller on purpose: inside it, it inherited the
   table's min-width and its right half was cut off on a phone. */
.lb-tablewrap { margin:0; border:1px solid var(--dd-border); border-radius:var(--dd-radius-md);
  background:var(--dd-surface); overflow:hidden; }
.lb-tablescroll { overflow-x:auto; -webkit-overflow-scrolling:touch;
  background:
    linear-gradient(to right, var(--dd-surface) 30%, rgba(255,255,255,0)) left center,
    linear-gradient(to left,  var(--dd-surface) 30%, rgba(255,255,255,0)) right center,
    radial-gradient(farthest-side at 0 50%, rgba(25,27,26,.13), rgba(25,27,26,0)) left center,
    radial-gradient(farthest-side at 100% 50%, rgba(25,27,26,.13), rgba(25,27,26,0)) right center;
  background-repeat:no-repeat; background-size:44px 100%, 44px 100%, 15px 100%, 15px 100%;
  background-attachment:local, local, scroll, scroll; }
.lb-tablewrap table { width:100%; border-collapse:collapse; font-size:.95rem; min-width:34rem; background:transparent; }
.lb-tablewrap figcaption { padding:.8rem 1rem; font-size:var(--dd-fs-sm); color:var(--dd-muted);
  border-top:1px solid var(--dd-hair); background:var(--dd-surface-2); }
.lb-tablewrap th, .lb-tablewrap td { padding:.75rem 1rem; text-align:left; vertical-align:top;
  border-bottom:1px solid var(--dd-hair); line-height:1.5; }
.lb-tablewrap thead th { font-size:var(--dd-fs-sm); font-weight:var(--dd-fw-semibold); color:var(--dd-text-2);
  background:var(--dd-surface-2); border-bottom:1px solid var(--dd-border); position:sticky; top:0; }
.lb-tablewrap tbody tr:last-child th, .lb-tablewrap tbody tr:last-child td { border-bottom:0; }
.lb-tablewrap td.is-num { font-variant-numeric:tabular-nums; white-space:nowrap; }

/* ── after the article: FAQ, sources ─────────────────────────────────── */

.lb-after { max-width:68ch; margin-top:3.4rem; display:grid; gap:2.6rem; }
.lb-block-t { margin:0 0 1rem; font-size:1.15rem; letter-spacing:-.018em; font-weight:var(--dd-fw-bold); }

.lb-faq { display:grid; gap:1.3rem; }
.lb-faq h3 { margin:0 0 .35rem; font-size:1rem; line-height:1.35; font-weight:var(--dd-fw-semibold); }
.lb-faq div { color:var(--dd-text-2); font-size:.98rem; line-height:1.65; }
.lb-faq div > * + * { margin-top:.7em; }
.lb-faq div p { margin:0; }
.lb-faq div a { color:var(--dd-primary-dark); text-decoration:underline; text-underline-offset:3px; }

/* Sources are the trust signal on a blog with no named human expert, so they are
   data rows with a check date, not a sentence someone forgot to update. */
.lb-src { border-top:1px solid var(--dd-border); padding-top:1.3rem; }
.lb-src h2 { margin:0 0 .6rem; font-size:var(--dd-fs-xs); text-transform:uppercase; letter-spacing:.13em;
  font-weight:var(--dd-fw-semibold); color:var(--dd-muted); }
.lb-src ol { margin:0; padding-left:1.2rem; display:grid; gap:.5rem; font-size:var(--dd-fs-sm); line-height:1.55; }
.lb-src a { color:var(--dd-primary-dark); text-decoration:underline; text-underline-offset:3px; word-break:break-word; }
.lb-src span { color:var(--dd-muted); }
.lb-src p { margin:.9rem 0 0; font-size:var(--dd-fs-sm); color:var(--dd-muted); line-height:1.55; }

/* Same right edge as the article block above (42rem + 3rem gap + 13.5rem rail),
   so the page ends on one line rather than three different ones. */
.lb-related { margin-top:3.6rem; max-width:58.5rem; }

/* ══════════════════════════════════════════════════════════════════════
   THE CLOSING PRODUCT NOTE. The only thing on the blog that sells, placed
   at the foot, after the reader has finished. Paper and a hairline, with
   the petrol on the button alone, because the button is the only thing
   meant to be clicked.
   ══════════════════════════════════════════════════════════════════════ */

.lb-close { margin-top:4rem; padding-top:2.4rem; border-top:1px solid var(--dd-border);
  display:grid; justify-items:center; gap:.5rem; text-align:center; }
.lb-close-kick { margin:0; font-size:var(--dd-fs-xs); text-transform:uppercase; letter-spacing:.15em;
  font-weight:var(--dd-fw-semibold); color:var(--dd-faint); }
.lb-close-line { margin:.2rem 0 0; font-size:clamp(1.25rem,2.2vw,1.6rem); line-height:1.2;
  letter-spacing:-.024em; font-weight:var(--dd-fw-bold); color:var(--dd-text); }
.lb-close-text { margin:0; max-width:46ch; font-size:.98rem; line-height:1.6; color:var(--dd-muted); }
.lb-close-btn { margin-top:.9rem; display:inline-flex; align-items:center; justify-content:center;
  min-height:46px; padding:.65rem 1.6rem; border-radius:var(--dd-radius-input);
  font-weight:var(--dd-fw-semibold); font-size:.98rem; text-decoration:none;
  background:var(--dd-primary); color:#fff; border:1px solid var(--dd-primary);
  transition:background var(--dd-transition); }
.lb-close-btn:hover { background:var(--dd-primary-dark); }
.lb-close-note { margin:.2rem 0 0; font-size:var(--dd-fs-xs); color:var(--dd-faint); }

/* ── focus, selection, print ─────────────────────────────────────────── */

.lb-page a:focus-visible { outline:none; box-shadow:var(--dd-focus-ring); border-radius:4px; }
.lb-prose ::selection { background:var(--dd-primary-soft); }

@media print {
  .lp-nav, .lb-col-toc, .lb-toc-m, .lb-related, .lb-close, .lb-search, .lp-footer { display:none !important; }
  .lb-prose { max-width:none; font-size:11pt; }
  .lb-prose a::after { content:" (" attr(href) ")"; font-size:9pt; color:#555; }
}

/* Masthead banner (lb-hero): one warm, full-width image above the blog title.
   Article rows stay text-only by design; this is the page header, not per-post
   cover art. No shadow (project preference), rounded to match the site. */
.lb-hero { margin:0 0 clamp(1.5rem,3vw,2.4rem); border-radius:20px; overflow:hidden; }
.lb-hero img { display:block; width:100%; aspect-ratio:16/6; object-fit:cover; object-position:50% 40%; }
@media (max-width:640px){ .lb-hero img { aspect-ratio:16/9; } }
