/* ============================================================
   BLOG REDESIGN — overrides and integration glue.

   blog-redesign.css ships untouched from the design handoff.
   This file holds:
     - Swiper integration for "What to read next" (mobile carousel,
       desktop grid).
     - Bits the design didn't ship explicitly (.rn-controls layout,
       prev/next button skin, mobile-cta-strip text override).
     - Body class overrides that align the design with our existing
       site shell (header / footer / button styles live in main.css).
   ============================================================ */

/* --- Category badge above the H1 should look like a pill, not just a coloured
       caps label. The design's .article-cat is a flat label; we promote it to
       a rounded chip with a soft lilac wash so it reads as a tag. */
.article-head .article-cat,
.article-meta > .article-cat {
  display: inline-flex;
  align-items: center;
  padding: 0.32rem 0.75rem;
  border-radius: 999px;
  background: rgba(96, 80, 176, 0.08);
  color: var(--color-primary, #6050b0);
  text-decoration: none;
  margin-bottom: 0;
  font-weight: 700;
  letter-spacing: 1.4px;
  line-height: 1;
}
.article-head .article-cat:hover {
  background: var(--color-primary, #6050b0);
  color: #fff;
}

/* --- Action icon buttons next to the author row (Save, Share). The design
       ships round 36px icon buttons on a soft background. Our markup uses
       <button class="icon-btn"> — give it the same look. */
.article-actions {
  display: flex;
  gap: 0.5rem;
  margin-inline-start: auto;
}
.icon-btn {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg-soft, #f5f3f0);
  border: 1px solid var(--color-border, #e6e2dc);
  border-radius: 999px;
  color: var(--color-text, #313330);
  cursor: pointer;
  padding: 0;
  transition: background 0.2s, color 0.2s, border-color 0.2s, transform 0.2s;
}
.icon-btn:hover {
  background: var(--color-primary, #6050b0);
  color: #fff;
  border-color: var(--color-primary, #6050b0);
}
.icon-btn.is-active {
  background: var(--color-primary, #6050b0);
  color: #fff;
  border-color: var(--color-primary, #6050b0);
}
.icon-btn .sr-only {
  position: absolute !important;
  width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* --- Inline CTA — match the design exactly: violet gradient bg, white text,
   white button. The blog-redesign.css rules use --gradient-cta and
   --shadow-primary, which only live in wishes-v2.css and don't load on
   single articles, so we redeclare them here as a fallback. */
:root {
  --gradient-cta: linear-gradient(135deg, #6050b0 0%, #9d80f8 100%);
  --shadow-primary: 0 12px 24px -6px rgba(96, 80, 176, 0.35);
  /* Tokens used by blog-redesign.css that only live in wishes-v2.css.
     Redeclared here so single articles render the same as the design. */
  --radius-pill: 999px;
  --color-bg-soft: #f5f3f0;
  --letter-spacing-eyebrow: 0.12em;
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.04), 0 2px 6px rgba(0,0,0,0.06);
  --shadow-md: 0 8px 24px -8px rgba(0,0,0,0.18);
}
.inline-cta {
  background: var(--gradient-cta);
  color: #fff;
  border: none;
  border-radius: var(--radius-lg, 24px);
  padding: 2rem;
  margin-block: 2.5rem;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.5rem;
  align-items: center;
  box-shadow: var(--shadow-primary);
}
.inline-cta .cta-eyebrow {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  font-weight: 700;
  color: #fff;
  opacity: 0.85;
  margin-bottom: 0.3rem;
}
.inline-cta h3 {
  font-size: 1.35rem;
  font-weight: 800;
  letter-spacing: -0.025em;
  margin: 0 0 0.5rem;
  color: #fff;
}
.inline-cta p {
  font-size: 0.93rem;
  line-height: 1.5;
  color: #fff;
  opacity: 0.92;
  margin: 0;
}
.inline-cta .btn,
.inline-cta .btn.btn-primary {
  background: #fff;
  color: var(--color-primary, #6050b0);
  font-weight: 700;
  white-space: nowrap;
  box-shadow: 0 8px 20px -8px rgba(0,0,0,0.25);
  border: none;
}
.inline-cta .btn:hover,
.inline-cta .btn.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 28px -8px rgba(0,0,0,0.3);
  background: #fff;
  color: var(--color-primary, #6050b0);
}

/* --- Plain <blockquote> fallback. Articles use <blockquote class="callout
       callout--before/--after/--quote"> for the design's tinted boxes. Any
       blockquote WITHOUT a .callout class falls back to a neutral, soft-grey
       quote with a side bar. The :not(.callout) guard is critical — without
       it this rule's specificity (0,0,1,1) would beat .callout--before /
       .callout--after (0,0,1,0) and override their per-class backgrounds
       and rounded borders, producing the same beige box for every quote. */
.article-body blockquote:not(.callout) {
  background: var(--color-bg-soft, #f5f3f0);
  border-inline-start: 4px solid var(--color-primary, #6050b0);
  border-radius: 0 var(--radius-md, 16px) var(--radius-md, 16px) 0;
  padding: 1.1rem 1.4rem;
  margin: 1.5rem 0;
  color: var(--color-text, #313330);
  font-style: normal;
  position: relative;
}
.article-body blockquote:not(.callout) p {
  margin: 0;
}
.article-body blockquote:not(.callout) p + p {
  margin-top: 0.6rem;
}
.article-body blockquote:not(.callout) em {
  display: block;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--color-primary, #6050b0);
  font-style: normal;
  font-weight: 700;
  margin-bottom: 0.4rem;
}

/* The .callout-mark is absolutely positioned at top:0.5rem with font-size:3.5rem,
   so the glyph extends ~3rem down into the box. The default .callout padding-top
   (1.25rem) leaves the first line of body text overlapping the bottom of the
   quote mark. Push the body down so the glyph clears it. */
.callout--quote {
  padding-block-start: 2.5rem;
}

/* TOC list / mobile-list styles intentionally not overridden here.
   The design's blog-redesign.css already ships a complete ToC theme:
   numbered ::before counter, primary-light active background, nested
   border-left list, mobile <details> sticky behaviour. Anything we add
   here would either fight the counter (eats the left padding the number
   sits in) or duplicate the active styling and double up on backgrounds.
   We just need to push the auto-built mobile list inside the <details>
   container. */
.toc-mobile-list {
  padding: 0 1rem 1rem;
}
.toc-mobile-list ol {
  list-style: none;
  padding-inline-start: 0;
  margin: 0;
  counter-reset: toc;
}

/* --- Make sticky actually stick.

   main.css applies `html { overflow-x: hidden }` site-wide, which silently
   turns <html> into a scroll-container and breaks `position: sticky` in every
   descendant on Chromium. `overflow-x: clip` clips the same way visually but
   doesn't create the scroll-container, so children can sticky off the
   document scroll-port again. clip is supported in Chrome/Edge 90+,
   Firefox 90+, Safari 16+ — the main.css `hidden` stays as a fallback for
   older engines. */
html, body {
  overflow-x: clip;
}

/* --- Match the article container to the site shell.
   .site-header .container is 1500/16px; the design's .article-shell ships
   with 32px sides, which makes the article look narrower than header/footer.
   Bring shell padding to 16px so the visible content edges line up. */
.article-shell {
  padding-inline: 1rem;
}
.article-grid {
  /* minmax(0, 1fr) prevents the article cell from expanding to its
     min-content width — without it, an internal Swiper wrapper (which is a
     row of intrinsically-wide slides) pushes the cell wider than the shell. */
  grid-template-columns: 280px minmax(0, 1fr);
}
/* blog-redesign.css ships .article { max-width: 760px } from the design.
   Bump to 780px — same selector, but this file is loaded after the design's,
   so this wins on equal specificity. We don't need a .article-grid > .article
   override: .article-grid above already uses minmax(0, 1fr) to keep the grid
   cell from blowing out, so the cap is enforced from .article alone. */
.article {
  max-width: 780px;
}
.read-next-swiper { overflow: hidden; }

/* Hero figure — the design assumed a 16:9 image, but DALL-E ships our covers
   at 1200×630 (~1.9:1). The 16:9 aspect-ratio left a white strip below the
   image. Match the figure to the actual image ratio and use object-fit:cover
   so any future image of a different aspect still fills cleanly. */
.article-hero {
  aspect-ratio: 1200 / 630;
}
.article-hero img,
.article-hero .hero-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* --- Sticky TOC offset: the design assumes a non-sticky site header, but ours
       is position:fixed at the top with --header-height (~84px). Push the
       sticky anchor below it so the TOC card is fully visible while scrolling.
       Same trick for the article body's heading anchors so jump-links don't
       hide their target under the header. */
.toc {
  top: calc(var(--header-height, 84px) + 16px) !important;
}
.article-body :is(h2, h3) {
  scroll-margin-top: calc(var(--header-height, 84px) + 16px);
}
.toc-mobile {
  top: var(--header-height, 84px);
}

/* Read-next sits inside <article> now (not as a sibling of .article-grid),
   so it inherits the article column. Margins keep it visually separate from
   the share-row above. */
.article > .read-next {
  margin-block: 2.5rem 4rem;
}

/* --- Make .rn-img play nicely with real photos.
       The design used CSS gradients (.rn-img--1, --2, --3); we apply
       background-image inline from the WordPress thumbnail. The base
       .rn-img already has aspect-ratio + rounded corners — just clear
       the gradient defaults so background-position centres the photo. */
.rn-img {
  background: var(--color-bg-soft, #f5f3f0);
  background-size: cover;
  background-position: center;
}

/* --- Read-next controls row (prev / next / all-button).
       Aligned to the right of the section heading, vertically centered. */
.rn-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

.rn-nav-btn {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg-white, #fff);
  border: 1px solid var(--color-border, #e6e2dc);
  border-radius: 999px;
  color: var(--color-text, #313330);
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s, transform 0.2s;
}
.rn-nav-btn:hover {
  background: var(--color-primary, #6050b0);
  border-color: var(--color-primary, #6050b0);
  color: #fff;
}
.rn-nav-btn:disabled,
.rn-nav-btn.swiper-button-disabled {
  opacity: 0.35;
  cursor: not-allowed;
  pointer-events: none;
}

/* --- Swiper × Read-next.

   Swiper is active on every breakpoint now — 3 slides on desktop, 1.15 on
   mobile (config in blog.js). Carousel sits inside <article>, so its width
   matches the .article column (max 760px). Cards never grow beyond their
   slide; image keeps its 16/10 aspect ratio. */
.read-next-swiper {
  overflow: hidden;
  /* Bleed slightly past the column on mobile so the peek of slide 2 isn't
     cut off by .article-body padding. */
}
.read-next-swiper .swiper-wrapper {
  /* Reset any inherited grid in case CSS reset libraries set it. */
  display: flex;
}
.read-next-swiper .rn-card {
  height: auto;             /* let Swiper compute slide height */
}
.read-next-swiper .rn-card .rn-img {
  aspect-ratio: 16/10;
  width: 100%;
}

/* Inside the article column, the carousel needs to claim full width and
   ignore the article's max-width 760 limit visually. */
.article > .read-next {
  margin-inline: 0;
  width: 100%;
}

@media (max-width: 767px) {
  .rn-head {
    flex-wrap: wrap;
  }
  .rn-controls {
    width: 100%;
    justify-content: flex-end;
  }
  .read-next-swiper {
    margin-inline: -1rem;
    padding-inline: 1rem;
  }
}

/* Tag pills styling lives in blog-redesign.css (.tags-section, .tags-label,
   .tag-pills, .tag-pills a). Markup is <ul class="tag-pills"><li><a>…</a></li>.
   The design's default puts the label inline (flex row); we stack it above
   the pills, so "ARTICLE TOPICS" sits as an eyebrow over the pill row. */
.tags-section {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.75rem;
}

/* --- Visually-hidden helper for icon buttons. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

/* Share row uses the design's brand-coloured circular buttons (.share-btn,
   .share-btn--li/--tw/--fb/--copy). Styling lives in blog-redesign.css,
   no override needed here. */
.share-btn.is-copied { transform: scale(0.94); }

/* Author bio styling lives in blog-redesign.css (.author-bio, .bio-avatar,
   .bio-body h3, .bio-stats, .bio-stat, .bio-link). The legacy
   .author-bio__avatar / __body / __name / __text / __meta classes were
   replaced with the design's bio-* set — see single.php. */

/* --- Mobile CTA strip — minor text-mode override.
       The design assumes a multi-line strip with eyebrow/title/button; ours is
       simpler (button only, text-on-button). Keep it visible only after the
       user starts scrolling — blog.js#initMobileCtaStrip toggles .is-visible. */
.mobile-cta-strip {
  transform: translateY(120%);
  transition: transform 0.25s ease;
}
.mobile-cta-strip.is-visible {
  transform: translateY(0);
}
@media (min-width: 768px) {
  .mobile-cta-strip { display: none !important; }
}

/* ============================================================
   ARCHIVE — AJAX loader (mirrors My Wishes loader styling so
   the two pages feel like one product). Scoped to the archive
   wrap so we don't pull all of wishes-v2.css onto /articles/.
   ============================================================ */
/* Wrap covers featured + grid + pagination + load-more + empty-state, so
   the loader overlay drapes the entire content block during AJAX. */
.archive-grid-shell #articles-content-wrap { position: relative; min-height: 200px; }
.archive-grid-shell .wish-grid-loader {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 80px;
  background: rgba(245, 243, 240, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border-radius: var(--radius-md, 16px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
  z-index: 2;
}
.archive-grid-shell #articles-content-wrap.is-loading .wish-grid-loader {
  opacity: 1;
  pointer-events: auto;
}

/* Featured slot — collapse the wrapper completely when empty so it never
   leaves a visual gap above the grid. Same trick on .articles-grid for the
   "1 result becomes featured, grid is empty" case (margin-bottom 3rem on
   the grid would otherwise show as a blank band below featured). */
.archive-grid-shell #featured-slot:empty { display: none; }
.archive-grid-shell .articles-grid:empty { display: none; }
.archive-grid-shell .wish-grid-spinner {
  width: 38px; height: 38px;
  border-radius: 50%;
  border: 3px solid rgba(96, 80, 176, 0.18);
  border-top-color: var(--color-primary, #6050b0);
  animation: dg-archive-spin 0.7s linear infinite;
}
@keyframes dg-archive-spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .archive-grid-shell .wish-grid-spinner { animation-duration: 1.6s; }
}

/* ============================================================
   ARCHIVE — "Show more" button row.
   ============================================================ */
.archive-grid-shell .load-more-wrap {
  display: flex;
  justify-content: center;
  padding: 0.5rem 0 2rem;
}
.archive-grid-shell .load-more-wrap[hidden] { display: none; }
.archive-grid-shell .load-more-btn {
  padding: 0.85rem 2.25rem;
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.archive-grid-shell .load-more-btn:disabled {
  opacity: 0.6;
  cursor: progress;
}

/* Empty-state inside the grid (when AJAX returns 0 items). */
.archive-grid-shell .archive-empty {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--color-text-muted, #767672);
  font-size: 0.95rem;
  line-height: 1.55;
}

/* Empty-state component — blog uses the same look as the My Wishes
   no-results block (.empty-state + .empty-icon from wishes-v2.css), but
   wishes-v2.css isn't loaded on /articles/, so we restate the styles here
   scoped under .archive-grid-shell. */
.archive-grid-shell .empty-state {
  text-align: center;
  padding: 4rem 1rem;
}
.archive-grid-shell .empty-state[hidden] { display: none; }
.archive-grid-shell .empty-state .empty-icon {
  width: 80px; height: 80px;
  border-radius: 50%;
  background: var(--color-primary-light, rgba(96, 80, 176, 0.1));
  color: var(--color-primary, #6050b0);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 1.25rem;
}
.archive-grid-shell .empty-state :is(h2, h3) {
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 0.5rem;
}
.archive-grid-shell .empty-state p {
  color: var(--color-text-muted, #767672);
  font-size: 0.95rem;
  line-height: 1.55;
  max-width: 420px;
  margin: 0 auto;
}

/* Plain `[hidden]` is overridden by display:flex/grid on the grid + featured
   slot — make sure hidden truly hides them. */
.articles-grid[hidden],
.featured-card[hidden],
.load-more-wrap[hidden],
.archive-grid-shell .pagination[hidden] {
  display: none !important;
}

/* Search clear button — small × inside the search field. Mirrors the My
   Wishes clear button so the two pages feel consistent. */
.archive-search { position: relative; }
.archive-search .search-clear {
  background: transparent;
  border: 0;
  cursor: pointer;
  width: 28px; height: 28px;
  display: inline-flex;
  align-items: center; justify-content: center;
  border-radius: 50%;
  color: var(--color-text-muted, #767672);
  margin-inline-start: -0.25rem;
  margin-inline-end: 0.25rem;
  flex-shrink: 0;
  transition: background 0.18s ease, color 0.18s ease;
}
.archive-search .search-clear:hover {
  background: rgba(96, 80, 176, 0.1);
  color: var(--color-primary, #6050b0);
}
.archive-search .search-clear[hidden] { display: none; }

/* ============================================================
   ANIMATIONS — subtle by design, all gated by reduced-motion.
   ============================================================ */

/* Card scroll-reveal убран — пользователи жаловались на «контент
   появляется с задержкой при скролле» на Safari (где IntersectionObserver
   запаздывает или CSP-задержки откладывают `.is-revealed`). Карточки
   теперь рендерятся сразу. blog.js всё ещё навешивает `.is-revealed`,
   но без CSS это no-op. data-reveal атрибуты в template-parts остаются —
   безвредны без сопровождающих стилей. */

/* Eyebrow dot — soft "live" pulse halo. Below 1.6s and 0.5
   max opacity so it reads as ambient, not as flashing UI. */
.archive-eyebrow .dot { position: relative; }
@media (prefers-reduced-motion: no-preference) {
  .archive-eyebrow .dot::after {
    content: "";
    position: absolute;
    inset: -2px;
    border-radius: 50%;
    background: var(--color-primary, #6050b0);
    opacity: 0.45;
    animation: dg-dot-pulse 1.6s ease-in-out infinite;
    pointer-events: none;
  }
  @keyframes dg-dot-pulse {
    0%, 100% { transform: scale(1);   opacity: 0.45; }
    50%      { transform: scale(2.4); opacity: 0;    }
  }
}

/* Card image zoom on hover — overflow:hidden on the parent
   article-card already exists in the design; scaling stays
   contained by the rounded corner. */
@media (prefers-reduced-motion: no-preference) {
  .article-card .ac-img,
  .featured-card .featured-img {
    transition: transform 0.5s var(--ease-standard, cubic-bezier(0.4, 0, 0.2, 1));
    will-change: transform;
  }
  .article-card:hover .ac-img,
  .article-card:focus-visible .ac-img { transform: scale(1.04); }
  .featured-card:hover .featured-img,
  .featured-card:focus-visible .featured-img { transform: scale(1.025); }
}

/* Filter pill — focus ring (a11y). */
.filter-pill:focus-visible {
  outline: 2px solid var(--color-primary, #6050b0);
  outline-offset: 2px;
}

/* === SORT DROPDOWN — match design (pill + custom chevron) ===============
   Chrome/Firefox/Safari render <select> with a wide native arrow that
   doesn't fit the design language. We strip it via -webkit-appearance:none
   + appearance:none and bake a custom chevron SVG into the background.
   Padding-right accounts for the chevron's space.
   ============================================================ */
.archive-sort {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.85rem;
  color: var(--color-text-muted, #767672);
}
.archive-sort > span {
  font-weight: 600;
  color: var(--color-text-muted, #767672);
  white-space: nowrap;
}
.archive-sort select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border: 1px solid var(--color-border, #e6e2dc);
  background-color: var(--color-bg-white, #fff);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236050b0' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 14px 14px;
  border-radius: var(--radius-pill, 999px);
  padding: 0.55rem 2.1rem 0.55rem 1rem;
  font-family: var(--font-primary, inherit);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-text-dark, #313330);
  cursor: pointer;
  line-height: 1.2;
  min-width: 11rem;
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
[dir="rtl"] .archive-sort select {
  background-position: left 0.75rem center;
  padding: 0.55rem 1rem 0.55rem 2.1rem;
}
.archive-sort select:hover,
.archive-sort select:focus {
  border-color: rgba(96, 80, 176, 0.45);
  outline: none;
  box-shadow: 0 0 0 3px rgba(96, 80, 176, 0.12);
}
.archive-sort select:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
/* Strip Firefox's dotted text-shadow + inner focus outline */
.archive-sort select::-moz-focus-inner { border: 0; }
.archive-sort select:-moz-focusring { color: transparent; text-shadow: 0 0 0 var(--color-text-dark, #313330); }
/* Native option list inherits OS look — there's no cross-browser way to
   skin <option>. Most users see the design's chevron + pill on the trigger,
   which is what the mockup shows; the popup is OS-rendered and acceptable. */

/* ============================================================
   MOBILE — archive overrides — 1:1 mirror of the design's
   .mobile-shell rules from blog-redesign.css (lines 1438-1511).
   The design ships those scoped to its Figma artboard wrapper;
   here we promote them to a real @media query so they apply on
   live phone widths.
   ============================================================ */
@media (max-width: 767px) {
  /* Shell padding tightens so cards reach the edge. */
  .archive-grid-shell { padding: 0 1rem; }

  /* Hero — full-bleed on mobile (no border-radius, no margin). */
  .archive-hero {
    border-radius: 0;
    padding: 1rem 1rem 1.25rem;
    margin: 0;
  }
  .archive-hero::before {
    width: 200px; height: 200px;
    inset-inline-end: -80px; top: -80px;
  }
  .archive-title { font-size: 2rem; margin-bottom: 0.65rem; }
  .archive-lede  { font-size: 0.92rem; margin-bottom: 1rem; max-width: none; }
  .archive-search { padding: 0.4rem 0.4rem 0.4rem 0.85rem; max-width: none; }
  .archive-search input { font-size: 0.88rem; }
  /* Submit button is hidden on mobile entirely — search runs via debounced
     input (AJAX), so an explicit submit is redundant on phones. */
  .archive-search button[type="submit"] { display: none; }
  .archive-stats { font-size: 0.75rem; gap: 0.85rem; margin-top: 0.85rem; flex-wrap: wrap; }

  /* Filters row — pills horizontal-scroll, sort below pills, right-aligned.
     Horizontal padding lives on the shell (1rem); the row itself has 0
     horizontal padding so pills can bleed to the screen edge during scroll. */
  .archive-filters-row {
    padding: 0.85rem 0 0.5rem;
    gap: 0.5rem;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
    max-width: 100%;
    flex-wrap: nowrap;
  }
  .archive-filters {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 0.25rem;
    /* The shorthand `padding: 0 1rem` wins over padding-left/right:0 — keeps
       a gutter on the leading/trailing pill so it doesn't kiss the edge. */
    padding-left: 0 !important;
    padding-right: 0 !important;
    padding: 0 1rem !important;
    /* Negative margin lets the strip bleed past the shell padding so pills
       can scroll edge-to-edge; the inner padding restores the visual gutter. */
    margin: 0 -1rem;
    /* width:auto + max-width:none + parent's max-width:100%/min-width:0 lets
       the column-flex parent constrain this child to the row width while
       overflow-x:auto handles the pill-strip scroll inside. */
    max-width: none !important;
    width: auto !important;
    min-width: 0;
    box-sizing: border-box;
    scrollbar-width: none;
  }
  .archive-filters::-webkit-scrollbar { display: none; }
  .filter-pill { white-space: nowrap; flex-shrink: 0; padding: 0.45rem 0.85rem; font-size: 0.8rem; }
  .archive-sort { font-size: 0.78rem; }
  .archive-sort select {
    padding: 0.5rem 1.85rem 0.5rem 0.85rem;
    font-size: 0.78rem;
    min-width: 9rem;
  }

  /* Featured card — stacked on mobile (image on top, body below). */
  .featured-card {
    grid-template-columns: 1fr !important;
    margin-bottom: 1.25rem;
    border-radius: var(--radius-md, 16px);
  }
  /* Card meta rows (cat · date · reading-time) wrap on narrow screens
     instead of forcing the row wider than the card. */
  .featured-meta,
  .ac-meta { flex-wrap: wrap; row-gap: 0.35rem; }
  .featured-card .featured-img { aspect-ratio: 16/10; }
  .featured-card .featured-body { padding: 1.25rem 1.35rem 1.4rem; }
  .featured-card h2 { font-size: 1.3rem; margin-bottom: 0.6rem; }
  .featured-card p { font-size: 0.88rem; margin-bottom: 1rem; }
  .featured-badge { padding: 0.3rem 0.75rem; font-size: 0.62rem; inset-inline-start: 0.85rem; top: 0.85rem; }

  /* Articles grid — single column. */
  .archive-grid-shell .articles-grid {
    grid-template-columns: 1fr;
    gap: 0.85rem;
    margin-bottom: 1.5rem;
  }

  /* Pagination — wrap if too many. */
  .archive-grid-shell .pagination { flex-wrap: wrap; gap: 0.3rem; margin-bottom: 1.25rem; }

  /* About-blog — collapse 1fr/auto grid into a single column; remove the
     240px CTA min-width that would squeeze the text into a ~130px ribbon. */
  .about-blog {
    grid-template-columns: 1fr;
    padding: 1.5rem 1.35rem;
    gap: 1.25rem;
    margin-bottom: 1.5rem;
    border-radius: var(--radius-md, 16px);
  }
  .about-blog h2 { font-size: 1.4rem; }
  .about-blog p  { font-size: 0.9rem; max-width: none; }
  .about-blog-meta { gap: 1rem; }
  .about-blog-meta .item strong { font-size: 1.15rem; }
  .about-blog-cta { min-width: 0; }

  /* Loader / empty-state / show-more — fit a phone screen. */
  .archive-grid-shell .wish-grid-loader { padding-top: 40px; }
  .archive-grid-shell #articles-content-wrap { min-height: 320px; }
  .archive-grid-shell .empty-state { padding: 2.5rem 0.5rem; }
  .archive-grid-shell .empty-state .empty-icon { width: 64px; height: 64px; }
  .archive-grid-shell .empty-state :is(h2, h3) { font-size: 1.2rem; }
  .archive-grid-shell .load-more-btn { padding: 0.7rem 1.5rem; font-size: 0.88rem; }
}

/* ============================================================
   SINGLE ARTICLE — clean alignment with Save button hidden.
   When .article-actions has only Share, it should still sit
   right-aligned at the end of .article-author-row.
   ============================================================ */
.article-actions:empty { display: none; }

/* Article-meta row (cat · date · reading-time) wraps onto a new line when
   there isn't enough horizontal room (narrow screens, RU/HE/AR locales
   with longer category names). row-gap keeps vertical spacing consistent
   with the original 0.65rem horizontal gap. */
.article-meta { flex-wrap: wrap; row-gap: 0.35rem; }

/* ============================================================
   SINGLE ARTICLE — mobile layout fixes.
   Breakpoint 1000px (not 767) — the article shell uses a 280px
   sidebar TOC + 1fr article column with 4rem gap; below ~1000px
   the layout cramps. We collapse to single-column earlier so the
   reading width stays comfortable on tablets and small laptops.
   ============================================================ */
@media (max-width: 1000px) {
  .article-shell {
    padding: 0.85rem 1rem 5rem;
    max-width: none;
  }
  .article-grid {
    /* minmax(0, 1fr) prevents the Swiper carousel's intrinsic slide widths
       from blowing the column out. Plain 1fr falls back to min-content. */
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 0;
  }
  .article {
    width: 100%;
    min-width: 0;
    max-width: 100%;
  }
  /* TOC desktop sidebar collapses on mobile — the JS-generated
     mobile <details> ToC takes over (already handled by blog.js#buildToc). */
  .toc { display: none; }

  /* Mobile ToC — promoted from the design's .mobile-shell .toc-mobile rules
     (blog-redesign.css:1317-1349, 1424-1429) into a real media query.
     Sticky below the site header so the user can jump to any heading
     mid-scroll. */
  .toc-mobile {
    display: block;
    background: var(--color-bg-white, #fff);
    border: 1px solid var(--color-border, #e6e2dc);
    border-radius: 12px;
    margin-bottom: 1rem;
    overflow: hidden;
    position: sticky;
    top: var(--header-height, 84px);
    z-index: 4;
    box-shadow: 0 4px 14px -10px rgba(0, 0, 0, 0.18);
  }
  .toc-mobile summary {
    list-style: none;
    cursor: pointer;
    padding: 0.85rem 1rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }
  .toc-mobile summary::-webkit-details-marker { display: none; }
  .toc-mobile-label {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--color-text-dark, #313330);
    letter-spacing: -0.01em;
    flex: 1;
  }
  .toc-mobile-count {
    font-size: 0.78rem;
    color: var(--color-text-muted, #767672);
    margin-inline-end: 0.4rem;
  }
  .toc-mobile-chev {
    color: var(--color-primary, #6050b0);
    transition: transform 0.25s var(--ease-standard, cubic-bezier(0.4, 0, 0.2, 1));
    flex-shrink: 0;
  }
  .toc-mobile[open] .toc-mobile-chev { transform: rotate(180deg); }
  .toc-mobile[open] summary { border-bottom: 1px solid var(--color-border, #e6e2dc); }

  .article-title {
    font-size: 1.55rem;
    letter-spacing: -0.03em;
  }
  .article-lede {
    font-size: 0.95rem;
    margin-bottom: 1rem;
  }
  .article-hero {
    border-radius: 14px;
    margin-bottom: 1rem;
  }
  .article-author-row { padding-top: 0.85rem; }
  .author-avatar { width: 36px; height: 36px; }
  .author-name { font-size: 0.85rem; }
  .author-role { font-size: 0.72rem; }

  /* Read-next carousel on mobile — Swiper does its own width math, but
     we cap the column so the wrapper itself doesn't push the page wide. */
  .read-next-swiper { max-width: 100%; overflow: hidden; }
  .rn-card .rn-img { aspect-ratio: 16/10; width: 100%; }
  /* Read-next controls: arrows on the left, "view all" on the right
     so they fill the row evenly instead of clustering. */
  .rn-controls {
    width: 100%;
    justify-content: space-between;
    gap: 0.5rem;
  }
  .rn-all-btn { margin-inline-start: auto; }

  /* Body typography */
  .article-body h2 { font-size: 1.4rem; margin: 1.5rem 0 0.6rem; }
  .article-body h3 { font-size: 1.1rem; margin: 1.1rem 0 0.5rem; }
  .article-body p  { font-size: 0.97rem; line-height: 1.65; }

  .key-takeaways { padding: 1rem 1.15rem; margin-bottom: 1.25rem; }
  .kt-list li     { font-size: 0.88rem; }
  .callout        { padding: 1rem 1.15rem; margin: 1.25rem 0; }
  /* Callout--quote padding bumps come AFTER .callout shorthand so they
     aren't reset back to 1rem. The decorative " mark needs ~3rem clearance
     (mark is absolute-positioned at top:0.25rem, font-size 2.5rem). */
  .callout--quote {
    padding-block-start: 3rem;
    padding-inline-start: 3rem;
  }
  .callout--quote .callout-mark { font-size: 2.5rem; top: 0.25rem; }
  .inline-cta     { grid-template-columns: 1fr; padding: 1.5rem 1.35rem; text-align: center; }
  .inline-cta .btn{ width: 100%; justify-content: center; }
  .faq-item summary { padding: 0.95rem 1.1rem; font-size: 0.92rem; }
  .author-bio     { grid-template-columns: 1fr; text-align: center; padding: 1.35rem; gap: 0.85rem; }
  .bio-avatar     { width: 64px; height: 64px; margin: 0 auto; }
  /* Bio-stats — center horizontally on mobile (was justify-flex-start on
     desktop). align-items:center keeps strong+span vertically aligned. */
  .bio-stats {
    justify-content: center;
    align-items: center;
    text-align: center;
    gap: 1.25rem;
  }

  /* Share row — stack label above icons, both centered. The desktop layout
     puts label on the left and icons margin-inline-start:auto on the right;
     on narrow screens the icons would crowd against the label. */
  .share-row {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.75rem;
  }
  .share-row .share-btns {
    margin-inline-start: 0;
    justify-content: center;
  }
}
