/* ══ BLOG ("Słowo") · ten.sebelski.pl ═══════════════════════════════════
   Ported from the design project (blog.css) and adapted to this site:
   every colour/font here comes from the tokens already declared in
   site.css :root, so the blog inherits the dark skin automatically.

   Where it renders:
   • listings → template-parts/blog-archive.php, shared by home.php (the /slowo/
                index) and archive.php (rubrics, tags, dates) — one layout, so
                switching between them can't shift anything
   • single   → child-theme single.php (.post-head / .prose / …)
   • home     → the "ostatnie teksty" module (.mod-slowo)

   Loaded after site.css (see sebelski_enqueue_assets), so it may override it.
   ══════════════════════════════════════════════════════════════════════ */

/* ── token collision guard ────────────────────────────────────────────
   site.css uses --display for the display typeface, but Elementor sets
   `--display: flex` on EVERY container it renders. Inside one of those — which
   is everything on /slowo/ — `font-family: var(--display)` resolves to the
   literal string `flex`, an invalid font stack, and the browser silently falls
   back. That's why the heading, card titles and CTA rendered in the wrong face
   there while the PHP archives looked right.

   Aliasing at :root captures the real value before any container can shadow it,
   and keeps site.css as the single source of truth for the stack itself. Use
   --sbl-display anywhere in this file that could sit inside a container. */
:root{--sbl-display:var(--display)}

/* ── page canvas ──────────────────────────────────────────────────────
   The Elementor-built pages each carry their dark background as a per-page
   setting (body.elementor-page-XXXX{background-color:#0f0d0b}). The blog's PHP
   templates have no such setting and would otherwise fall back to Mokko's own
   dark grey (#1b1d1c) — close, but not our paper. Pin them to the site tokens. */
body.sbl-single,
body.sbl-archive{background-color:var(--paper);color:var(--ink)}

/* ── section head ─────────────────────────────────────────────────────
   Same column as the rest of the site: site.css sections are
   `max-width:var(--maxw); padding-inline:var(--pad)`, i.e. 1320 − 2×32 = 1256px
   of content. These are the numbers the Elementor version of this page used to
   carry as container settings (boxed 1256, padding 116/32/0/32 and so on); they
   live here now, once, for every blog listing. */
body.sbl-archive .b-head,
body.sbl-archive .b-filters,
body.sbl-archive .b-archive,
body.sbl-archive .b-cta-wrap{max-width:var(--maxw);margin-inline:auto;padding-inline:var(--pad)}
body.sbl-archive .b-head{padding-top:116px;padding-bottom:0}
body.sbl-archive .b-archive{padding-top:64px;padding-bottom:0}
body.sbl-archive .b-cta-wrap{padding-top:72px;padding-bottom:96px}
@media (max-width:900px){
  body.sbl-archive .b-head{padding-top:96px}
  body.sbl-archive .b-archive{padding-top:40px}
  body.sbl-archive .b-cta-wrap{padding-top:48px;padding-bottom:64px}
}

.b-head .h-display{font-size:clamp(56px,8vw,124px)}
.b-head-grid{max-width:60ch}
.b-head-grid .lead{max-width:52ch}

/* Vertical rhythm of the head (label 116, heading 169, lead 313 at 1600px).
   Both rules replace something the surrounding CSS would otherwise impose:
   site.css renders .label as inline-flex, so it sits on a text baseline and
   picks up ~7px of leading it doesn't need here; and .h-display carries its own
   em-relative margins, which drift with the clamped font size. */
body.sbl-archive .b-head .label{display:flex;width:fit-content;line-height:1}
body.sbl-archive .b-head .h-display{margin:42px 0 20px}

/* ── rubric filters — plain links to the category archives ───────────
   One row, rendered by template-parts/blog-filters.php on every listing. It was
   previously shadowed on the index by three Elementor Buttons, which is why the
   chip styling here used to be duplicated for .elementor-button wrappers. */
.b-filters{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
/* top offset only — width/side padding come from the shared rule above */
body.sbl-archive .b-filters{margin-top:28px}
@media (max-width:900px){body.sbl-archive .b-filters{margin-top:22px}}
/* "archiwum od …" sits opposite the chips */
.b-filters-note{margin-left:auto}
/* On phones the chips already wrap to two rows, and the note then dropped onto
   a third full-width line — a decorative caption pushing the first card further
   below the fold. It is a nicety, not information, so it goes instead of
   wrapping (this replaces the old margin-left:0;width:100% rule). */
@media (max-width:680px){.b-filters-note{display:none}}
a.b-chip{
  font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  padding:9px 15px;border:1px solid var(--line);border-radius:999px;color:var(--ink-2);
  background:transparent;cursor:pointer;
  transition:color .2s,border-color .2s,background-color .2s,transform .2s;
}
a.b-chip:hover{transform:translateY(-2px);border-color:var(--ink);color:var(--ink)}
a.b-chip.on{background-color:var(--ink);border-color:var(--ink);color:var(--paper)}
.b-chip .n{opacity:.5;margin-left:8px}
.b-chip.on .n{opacity:.6}

/* ── Elementor widget mapping ─────────────────────────────────────────
   Only the "ostatnie teksty" home-page module is still built with Elementor
   widgets; the listings are plain templates now. Elementor puts a widget's CSS
   class on its WRAPPER, not on the element inside, so the type has to be mapped
   onto .elementor-heading-title itself — otherwise the heading keeps the browser
   default scale and the parent theme's light-skin colour (black on our dark). */
.mod-slowo .elementor-heading-title{color:var(--ink)}
.mod-slowo .h-2 .elementor-heading-title{
  font-family:var(--sbl-display);font-weight:var(--display-weight);letter-spacing:var(--display-tracking);
  font-size:inherit;line-height:1;margin:0;
}
.mod-slowo .h-2 .elementor-heading-title em{font-style:italic}

/* ── post grid ────────────────────────────────────────────────────── */
/* Row gap carries the whole vertical separation now. It used to be 8px because
   each card added 34px of its own top/bottom padding outside the box; boxed
   cards end at their border, so the air has to come from the grid. */
.b-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px 34px;margin-top:8px}
[data-bcols="2"] .b-grid{grid-template-columns:repeat(2,1fr);gap:20px 56px}
@media (max-width:1080px){.b-grid,[data-bcols="2"] .b-grid{grid-template-columns:repeat(2,1fr);gap:20px 34px}}
@media (max-width:680px){.b-grid,[data-bcols="2"] .b-grid{grid-template-columns:1fr}}

/* One card treatment, everywhere it renders. Cards used to be flat — a single
   hairline on top and nothing else — so on a dark background a photo card had no
   edge at all and neighbouring cards ran into each other. Only the typographic
   variant got a filled box, and only on two of the three surfaces, which is why
   the same post looked different in the archive and under an article.
   The box also fixes the alignment problem that scoping was working around: when
   every card carries the same 26px inset, none of them sits ragged next to a
   filled one. */
.b-card{
  display:flex;flex-direction:column;overflow:hidden;
  background:var(--paper-2);border:1px solid var(--line);padding:26px;
  transition:border-color .25s ease;
}
.b-card:hover{border-color:rgba(255,255,255,.22)}
/* The photo bleeds to the card's edges — pulled back out of the padding on three
   sides, keeping only the 20px gap down to the text. */
.b-card-media{position:relative;overflow:hidden;background:#1a1410;aspect-ratio:3/2;margin:-26px -26px 20px}
/* .b-card qualifier is load-bearing: Elementor ships `.elementor img{height:auto}`
   at the same specificity as a bare `.b-card-media img`, and its stylesheet wins on
   order — the photo then keeps its own ratio inside the fixed-ratio box and leaves
   an empty band at the bottom (measured 55px on the featured card). */
.b-card .b-card-media img{width:100%;height:100%;object-fit:cover;transition:transform .9s ease,filter .4s ease}
.b-card:hover .b-card-media img{transform:scale(1.04);filter:brightness(1.05)}
.b-card h3,.b-card .b-card-title{
  font-family:var(--sbl-display);font-weight:var(--display-weight);letter-spacing:var(--display-tracking);
  font-size:29px;line-height:1.08;margin:.2em 0 .35em;text-wrap:balance;
  background-image:linear-gradient(var(--accent),var(--accent));background-repeat:no-repeat;
  background-size:0% 1px;background-position:0 100%;transition:background-size .45s cubic-bezier(.2,.7,.2,1);
  display:inline;padding-bottom:2px;color:var(--ink);
}
.b-card:hover h3,.b-card:hover .b-card-title{background-size:100% 1px}
.b-card h3 em{font-style:italic}
.b-card p{font-size:16px;line-height:1.6;color:var(--ink-2);margin:10px 0 0;text-wrap:pretty}
.b-card .b-meta{margin-top:auto;padding-top:18px}

/* typographic variant — no featured image (used by felietony). Nothing to do but
   drop the media box; the card treatment above is already shared. The italic
   pull-quote that used to sit under the blurb went with the ACF field's change of
   job — `cytat` is the lede on the post now, not a card ornament. */
.b-card.is-text .b-card-media{display:none}

/* ── first card of the archive reads as the "featured" entry ─────────
   The design has a dedicated featured block above the grid. Elementor free
   has no offset control, so instead of pinning a post by hand (which would
   need editing on every publish) the newest card simply spans the grid and
   switches to the two-column featured layout. Stays fully dynamic.

   It is the one card that stays unboxed: it is the section's hero, spanning the
   full column, and a frame around something that wide reads as a panel rather
   than a card. */
@media (min-width:1081px){
  .b-archive .b-grid > .b-card:first-child{
    grid-column:1/-1;display:grid;grid-template-columns:1.05fr .95fr;gap:52px;
    align-items:center;background:transparent;border:0;padding:16px 0 34px;
  }
  .b-archive .b-grid > .b-card:first-child:hover{border-color:transparent}
  .b-archive .b-grid > .b-card:first-child .b-card-media{margin:0;aspect-ratio:4/3}
  .b-archive .b-grid > .b-card:first-child .b-card-body{display:flex;flex-direction:column}
  .b-archive .b-grid > .b-card:first-child h3,
  .b-archive .b-grid > .b-card:first-child .b-card-title{font-size:clamp(34px,3.6vw,58px);line-height:1.02}
  .b-archive .b-grid > .b-card:first-child p{font-size:17px;max-width:52ch}
  .b-archive .b-grid > .b-card:first-child.is-text{grid-template-columns:1fr}
}

/* ── rubric + meta line ───────────────────────────────────────────── */
.b-rubric{font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--accent)}
.b-rubric.alt{color:var(--muted)}
.b-meta{font-family:var(--mono);font-size:11px;letter-spacing:.08em;color:var(--muted);
  display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.b-meta .dot{opacity:.45}
.b-meta a{color:inherit}
.b-meta a:hover{color:var(--accent)}

/* ── pagination (WP paginate_links inside the loop widget) ────────── */
.b-pager,.b-archive .pagination,.b-archive .nav-links{
  display:flex;gap:6px;align-items:center;justify-content:center;margin-top:56px;flex-wrap:wrap}
.b-pager .b-page,.b-archive .page-numbers{
  font-family:var(--mono);font-size:12px;line-height:1;min-width:38px;height:38px;padding:0 14px;
  display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);
  border-radius:999px;background:transparent;color:var(--ink-2);
  transition:border-color .2s,color .2s,background .2s}
.b-pager a.b-page:hover,.b-archive a.page-numbers:hover{border-color:var(--ink);color:var(--ink)}
.b-pager .b-page.on,.b-archive .page-numbers.current{background:var(--ink);border-color:var(--ink);color:var(--paper)}

/* ── CTA strip ────────────────────────────────────────────────────────
   Row layout used to be configured on the Elementor container; it belongs here
   now, together with the button, whose look is carried over from the builder
   (#EFEAE1 fill, JetBrains Mono 12px, 6px radius) to match the home page. */
/* The rules run the full width of the column, so with no side padding the title
   started exactly where the line starts and the button ended exactly where it
   ends — the text read as sitting ON the rules rather than inside them. The
   inset pulls both ends off the corners; the rules stay full width. */
.b-cta{
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:40px var(--pad);
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:28px;
}
.b-cta h4{
  font-family:var(--sbl-display);font-weight:var(--display-weight);font-size:34px;line-height:1.05;
  margin:0 0 8px;color:var(--ink)}
.b-cta p{margin:0;font-size:16px;line-height:1.6;color:var(--ink-2);max-width:56ch}
/* site.css has `.ts a{color:inherit}` at (0,1,1); a bare .b-cta-btn (0,1,0)
   would lose to it and leave the label light-on-light. Qualify with the element. */
a.b-cta-btn{
  display:inline-flex;align-items:center;white-space:nowrap;
  font-family:var(--mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;
  padding:14px 22px;border:1px solid #efeae1;border-radius:6px;
  background:#efeae1;color:#0f0d0b;
  transition:background .2s,border-color .2s,color .2s,transform .2s;
}
a.b-cta-btn:hover{background:transparent;color:#efeae1;transform:translateY(-2px)}
@media (max-width:680px){.b-cta{gap:20px}.b-cta h4{font-size:28px}}

/* ══ SINGLE POST ═══════════════════════════════════════════════════ */
.post-head{max-width:1100px;margin:0 auto;padding:180px var(--pad) 0}
.post-head .kicker{display:flex;gap:12px;align-items:center;margin-bottom:22px;flex-wrap:wrap}
.post-head .kicker-sep{font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--muted);opacity:.55}
.post-head h1{
  font-family:var(--sbl-display);font-weight:var(--display-weight);letter-spacing:var(--display-tracking);
  text-transform:var(--display-case);font-size:clamp(42px,5.6vw,86px);line-height:1;margin:0;
  max-width:16ch;text-wrap:balance;color:var(--ink);
}
.post-head h1 em{font-style:italic;color:var(--accent)}
.post-lede{font-family:var(--serif);font-size:clamp(21px,2vw,28px);line-height:1.4;color:var(--ink-2);
  max-width:52ch;margin:28px 0 0;text-wrap:pretty}
.post-meta{display:flex;flex-wrap:wrap;gap:14px;align-items:center;margin-top:36px;padding-top:16px;
  border-top:1px solid var(--line);
  font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
@media (max-width:900px){
  .post-head{padding-top:130px}
  /* 16ch is a deliberate measure for the huge desktop display size; once the
     title drops to its 42px minimum that cap wastes ~half the row (measured:
     277px of text in a 528px column, 4 lines). Let it use the full width. */
  .post-head h1{max-width:none}
}

/* ── head with a featured image ────────────────────────────────────────
   The picture sits beside the words, not above them. It used to run the full
   1100px column between the head and the text, which made it a second hero: the
   reader met the title, then a wall of photograph, and only then the article.
   Capping it at half the viewport fixed the height but left a tall scan as a
   narrow strip floating in the middle of an empty row — a portrait frame simply
   has no business filling a horizontal band.

   Two columns solve both at once: the frame fills a column it can actually use,
   and the height is bounded by the head instead of by a magic number. Words get
   the wider share; text is what the page is for. */
.post-head.has-cover{
  display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);
  gap:clamp(28px,3.4vw,56px);align-items:center;
}
/* The cover is a grid child now, so it brings none of its own page geometry. */
.post-head .post-cover{margin:0;max-width:none;padding:0}
/* No crop and no background: the frame keeps its own proportions, and a tall one
   simply shrinks in both directions until it fits under the half-viewport ceiling,
   leaving its column part empty rather than being cut down to a band. This is a
   photographer's site — the cadre is the work, so the layout gives way, not the
   picture. Centred in the leftover space; a background here would show up as
   lighter panels beside a narrow frame. */
.post-head .post-cover figure{margin:0;position:relative;display:flex;justify-content:center}
.post-head .post-cover img{width:auto;max-width:100%;height:auto;max-height:50vh;display:block}
/* The display size is tuned for a full-width column; in half of one the same
   clamp overflows its measure and breaks the title into a stack of short lines.
   16ch stops being the limit here — the column already is. */
.post-head.has-cover h1{font-size:clamp(38px,3.6vw,62px);max-width:none}
.post-head.has-cover .post-lede{font-size:clamp(19px,1.5vw,23px);margin-top:22px}
.post-head.has-cover .post-meta{margin-top:28px}

@media (max-width:900px){
  /* One column: title first, picture under it. The cover is first in the source
     because that is the desktop reading order (left to right); on a phone it has
     to move below, or a photograph would sit above the title of the piece the
     reader just opened. Hence flex + order rather than plain block flow. */
  .post-head.has-cover{display:flex;flex-direction:column}
  .post-head .post-cover{order:2;margin-top:32px}
  .post-head.has-cover h1{font-size:clamp(42px,5.6vw,86px)}
}

/* ── reading column ───────────────────────────────────────────────── */
.prose{max-width:68ch;margin:0 auto;padding:64px var(--pad) 0;font-size:19px;line-height:1.72;color:var(--ink)}
.prose p{margin:0 0 1.35em;text-wrap:pretty}
.prose h2{font-family:var(--sbl-display);font-weight:var(--display-weight);letter-spacing:var(--display-tracking);
  font-size:38px;line-height:1.05;margin:2em 0 .5em;color:var(--ink)}
.prose h3{font-family:var(--serif);font-size:24px;line-height:1.2;margin:1.8em 0 .4em;color:var(--ink)}
.prose em{font-style:italic}
.prose a{color:var(--accent);border-bottom:1px solid rgba(200,49,42,.35)}
.prose a:hover{border-bottom-color:var(--accent)}
.prose hr{border:0;height:1px;background:var(--line);margin:2.4em 0}
.prose ul,.prose ol{margin:0 0 1.35em;padding-left:1.4em}
.prose li{margin:0 0 .5em}
.prose blockquote{margin:2em 0;padding-left:28px;border-left:2px solid var(--accent);
  font-family:var(--serif);font-style:italic;font-size:26px;line-height:1.35;color:var(--ink)}
.prose blockquote p{margin:0}
.prose figure{margin:2.4em 0}
.prose figure img,.prose img{width:100%;height:auto;display:block}
.prose figcaption{font-family:var(--mono);font-size:11px;color:var(--muted);margin-top:8px}
/* drop cap on the opening paragraph */
.prose > p:first-of-type::first-letter{
  float:left;font-family:var(--sbl-display);font-weight:var(--display-weight);font-size:5.4em;line-height:.78;
  padding:.06em .1em 0 0;color:var(--accent);
}
.prose-end{font-family:var(--mono);font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);
  margin:48px 0 0;display:flex;align-items:center;gap:12px}
.prose-end::before{content:'';width:26px;height:1px;background:var(--accent)}

/* full-bleed pull quote */
.pullwide{max-width:960px;margin:64px auto;padding:0 var(--pad);text-align:center}
.pullwide q{font-family:var(--sbl-display);font-weight:var(--display-weight);letter-spacing:var(--display-tracking);
  font-size:clamp(30px,4vw,54px);line-height:1.08;quotes:'„' '"';display:block;text-wrap:balance}
.pullwide .who{font-family:var(--mono);font-size:11px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--muted);margin-top:18px}

/* ── tags, author, prev/next ──────────────────────────────────────── */
.post-tags{max-width:68ch;margin:36px auto 0;padding:0 var(--pad);display:flex;flex-wrap:wrap;gap:8px}
.post-tags a{font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--muted);
  border:1px solid var(--line);border-radius:999px;padding:7px 13px;transition:.2s}
.post-tags a:hover{color:var(--accent);border-color:var(--accent)}

.author-box{max-width:var(--maxw);margin:72px auto 0;padding:0 var(--pad)}
.author-inner{display:grid;grid-template-columns:120px 1fr auto;gap:28px;align-items:center;
  background:var(--paper-2);border:1px solid var(--line);padding:28px}
.author-inner img{width:120px;height:150px;object-fit:cover}
.author-inner .name{font-family:var(--serif);font-size:26px;line-height:1.1;margin-bottom:6px;color:var(--ink)}
.author-inner p{margin:0;font-size:16px;line-height:1.55;color:var(--ink-2);max-width:56ch}

/* Buycoffee pill — same as the one in the "postaw mi kawę" callout on
   /o-mnie/#off (white fill, accent text, same mono/size/padding/radius), instead
   of inheriting the footer's .socials-coffee rules, which are built for a
   completely different layout.

   One deliberate difference: the hover. On /o-mnie/ the pill sits ON the red
   callout, so it inverts to near-black. Here the author box is dark (--paper-2)
   and that same inversion would make the button all but disappear, so it inverts
   to accent red instead — the motion is identical, the target suits the ground.

   Selector note: site.css has `.ts a{color:inherit}` — specificity (0,1,1),
   which outranks a bare `.author-coffee` (0,1,0) and would leave the label
   inheriting the page's light text, i.e. white on white. Qualifying the class
   with the element and its box wins on specificity without !important. */
.author-box a.author-coffee{
  display:inline-flex;align-items:center;gap:10px;align-self:center;justify-self:end;white-space:nowrap;
  font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;
  padding:11px 16px;border:1px solid #fff;border-radius:999px;
  background:#fff;color:var(--accent);
  transition:background .2s,color .2s,border-color .2s,transform .2s;
}
.author-box a.author-coffee:hover{background:var(--accent);border-color:var(--accent);color:#fff;transform:translateY(-2px)}

@media (max-width:820px){
  .author-inner{grid-template-columns:96px 1fr;gap:20px}
  .author-inner img{width:96px;height:120px}
  /* two columns left → the button is the third child and would land in a cramped
     cell under the photo; give it its own full-width row instead. Same selector
     weight as the desktop rule above — a media query adds no specificity, so a
     bare .author-coffee here would lose to it and stay pinned right.
     Centred on its own row: left-aligned it sat under the photo and read as
     hanging off the text column, with a long ragged gap to its right. */
  .author-box a.author-coffee{grid-column:1/-1;justify-self:center;align-self:start}
}

/* The label is a URL — one unbreakable token — so the pill has a fixed ~250px
   width whatever the screen. Below ~290px that is wider than the card itself
   (viewport − 2×--pad) and it escapes to the right, starting a horizontal
   scroll. Only there, let the line wrap: a two-line pill is homely, a page that
   scrolls sideways is a bug. Wider phones keep the single line untouched. */
@media (max-width:300px){
  .author-box a.author-coffee{white-space:normal;overflow-wrap:anywhere;max-width:100%;text-align:center}
}

.post-nav{max-width:var(--maxw);margin:64px auto 0;padding:0 var(--pad);
  display:grid;grid-template-columns:1fr 1fr;gap:8px}
.post-nav a{border:1px solid var(--line);padding:26px;display:block;transition:.25s}
.post-nav a:hover{border-color:var(--ink)}
.post-nav .dir{font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
.post-nav .t{font-family:var(--sbl-display);font-weight:var(--display-weight);font-size:24px;line-height:1.1;
  margin-top:10px;color:var(--ink)}
.post-nav .next{text-align:right}
@media (max-width:680px){.post-nav{grid-template-columns:1fr}.post-nav .next{text-align:left}}

/* ── "ostatnie teksty" module (home page) ─────────────────────────── */
.mod-slowo-head{display:grid;grid-template-columns:1fr auto;align-items:end;gap:20px;margin-bottom:12px}
.mod-slowo .b-grid{gap:20px 34px}
.mod-list{border-top:1px solid var(--line)}
.mod-row{display:grid;grid-template-columns:130px 1fr auto;gap:26px;align-items:baseline;
  padding:24px 2px;border-bottom:1px solid var(--line);transition:padding-left .3s ease,background .3s ease}
.mod-row:hover{padding-left:12px}
.mod-row .t{font-family:var(--sbl-display);font-weight:var(--display-weight);letter-spacing:var(--display-tracking);
  font-size:30px;line-height:1.08;text-wrap:balance;color:var(--ink)}
.mod-row:hover .t{color:var(--accent-soft)}
.mod-row .t em{font-style:italic}
.mod-row .ex{font-size:15px;color:var(--ink-2);margin-top:6px;max-width:64ch}
.mod-row .arrow{font-family:var(--mono);font-size:14px;color:var(--muted);transition:transform .3s}
.mod-row:hover .arrow{transform:translateX(6px);color:var(--accent)}
@media (max-width:720px){.mod-row{grid-template-columns:1fr;gap:6px}.mod-row .arrow{display:none}}
