@charset "UTF-8";
/* ==========================================================================
   mediahub-public.css — design system for the PUBLIC MediaHub pages
   (hub / magazine / channel / article / video / podcast)

   Created by the public-site remediation task (۲۰۲۶-۱۰-۰۳) in answer to the
   design audit's C1/C3/C4/C7/C10/C11/C12/C13/C15.

   WHY THIS FILE EXISTS
   The five public blades are standalone HTML documents with their own
   per-page <style> blocks and no shared stylesheet, so "apply the :root
   tokens consistently" was impossible by construction. This is that one
   shared sheet. Loaded by `mediahub/partials/public-head.blade.php`.

   CASCADE CONTRACT
   Loaded AFTER bootstrap 4 (CDN) and AFTER the welcome/CMS header sheets,
   BEFORE each page's own <style>. Existing per-page :root blocks are left
   untouched; this sheet owns the visual layer only and is namespaced `--mhd-*`
   / `.mh-*` so the admin real-view overlay (data-mh-block-*) is unaffected.
   ========================================================================== */

/* ---------- 1. Self-hosted Vazirmatn (C1) --------------------------------
   Google Fonts is unreachable/slow from Iran — that is why the webfont was
   "loaded but never applied". Self-hosted, arabic + latin subsets, swap. */
@font-face{font-family:'Vazirmatn';font-style:normal;font-weight:400;font-display:swap;src:url('../fonts/vazirmatn/vazirmatn-latin-400.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Vazirmatn';font-style:normal;font-weight:400;font-display:swap;src:url('../fonts/vazirmatn/vazirmatn-arabic-400.woff2') format('woff2');unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0898-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC;}
@font-face{font-family:'Vazirmatn';font-style:normal;font-weight:500;font-display:swap;src:url('../fonts/vazirmatn/vazirmatn-latin-500.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Vazirmatn';font-style:normal;font-weight:500;font-display:swap;src:url('../fonts/vazirmatn/vazirmatn-arabic-500.woff2') format('woff2');unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0898-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC;}
@font-face{font-family:'Vazirmatn';font-style:normal;font-weight:700;font-display:swap;src:url('../fonts/vazirmatn/vazirmatn-latin-700.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Vazirmatn';font-style:normal;font-weight:700;font-display:swap;src:url('../fonts/vazirmatn/vazirmatn-arabic-700.woff2') format('woff2');unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0898-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC;}
@font-face{font-family:'Vazirmatn';font-style:normal;font-weight:800;font-display:swap;src:url('../fonts/vazirmatn/vazirmatn-latin-800.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Vazirmatn';font-style:normal;font-weight:800;font-display:swap;src:url('../fonts/vazirmatn/vazirmatn-arabic-800.woff2') format('woff2');unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0898-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC;}

/* ---------- 2. Tokens (C10) ---------------------------------------------- */
:root{
  /* type */
  --mhd-font: 'Vazirmatn','IRANSans',Tahoma,Arial,sans-serif;
  --mhd-fs-xs:.75rem; --mhd-fs-sm:.875rem; --mhd-fs-base:1rem; --mhd-fs-md:1.125rem;
  --mhd-fs-lg:1.3125rem; --mhd-fs-xl:1.5rem; --mhd-fs-2xl:1.875rem;
  --mhd-fs-3xl:2.25rem; --mhd-fs-4xl:2.75rem;
  --mhd-lh-display:1.15; --mhd-lh-head:1.3; --mhd-lh-ui:1.5; --mhd-lh-prose:1.85;
  --mhd-fw-normal:400; --mhd-fw-medium:500; --mhd-fw-bold:700; --mhd-fw-black:800;

  /* spacing — 4px grid, no off-grid values */
  --mhd-sp-1:4px;  --mhd-sp-2:8px;  --mhd-sp-3:12px; --mhd-sp-4:16px;
  --mhd-sp-5:20px; --mhd-sp-6:24px; --mhd-sp-8:32px; --mhd-sp-10:40px;
  --mhd-sp-12:48px; --mhd-sp-16:64px; --mhd-sp-20:80px;

  /* radii — 4 steps, replacing 9 ad-hoc values */
  --mhd-r-sm:6px; --mhd-r-md:10px; --mhd-r-lg:16px; --mhd-r-full:999px;

  /* ink + surfaces */
  --mhd-ink-900:#141619; --mhd-ink-700:#343a40; --mhd-ink-500:#566069;
  --mhd-ink-450:#6b7580; --mhd-ink-300:#c7cdd3; --mhd-ink-200:#e3e7eb;
  --mhd-ink-100:#f1f3f5;
  --mhd-canvas:#f7f8fa; --mhd-surface:#ffffff; --mhd-surface-raised:#ffffff;
  --mhd-border:#e3e7eb; --mhd-border-strong:#c7cdd3;

  /* semantic colour — every pair below measured >=4.5:1 (see DESIGN.md) */
  --mhd-primary:#c01328; --mhd-primary-700:#96091d; --mhd-primary-tint:#fdeaec;
  --mhd-on-primary:#ffffff;
  --mhd-accent:#0e7c85;  --mhd-accent-700:#0a5f66; --mhd-accent-tint:#e4f3f4;
  --mhd-success:#15713f; --mhd-success-tint:#e6f4eb;
  --mhd-warning:#8a5a00; --mhd-warning-tint:#fff4e0;
  --mhd-info:#15559e;    --mhd-info-tint:#e8f0fb;
  --mhd-focus:#15559e;

  /* category pills — fixed 6-slot set, dark text on light tint */
  --mhd-cat1-fg:#8a3a00; --mhd-cat1-bg:#fff1e3;
  --mhd-cat2-fg:#15559e; --mhd-cat2-bg:#e8f0fb;
  --mhd-cat3-fg:#15713f; --mhd-cat3-bg:#e6f4eb;
  --mhd-cat4-fg:#6b2e8f; --mhd-cat4-bg:#f3eafb;
  --mhd-cat5-fg:#a01045; --mhd-cat5-bg:#fde9f0;
  --mhd-cat6-fg:#1f5e63; --mhd-cat6-bg:#e4f3f4;

  /* shadows — one cool-neutral family, 3 steps */
  --mhd-sh-1:0 1px 2px rgba(20,22,25,.06),0 1px 3px rgba(20,22,25,.10);
  --mhd-sh-2:0 4px 6px -1px rgba(20,22,25,.07),0 2px 4px -2px rgba(20,22,25,.06);
  --mhd-sh-3:0 10px 24px -6px rgba(20,22,25,.14);

  /* layout */
  --mhd-measure:68ch;        /* article prose max line length (C: 123ch bug) */
  --mhd-container:1180px;
  --mhd-tap:44px;            /* C13 minimum touch target */
}

/* ---------- 3. Dark mode (C15) — same tokens, redefined -------------------
   Surfaces lift instead of inverting; no parallel hardcoded palette.

   TWO CONTAINMENT RULES, both learned the hard way on 2026-10-04:

   (a) The tokens are redefined on `body.mh-public`, NOT on `:root`.
       `:root` would apply to any document that merely links this sheet —
       including the admin panel's "real view" (نمای واقعی) iframe, which
       renders these very public pages inside the admin UI. An admin whose
       OS is set to dark would see the whole channel/media preview turn
       near-black (--mhd-canvas #101216) even though the admin chrome around
       it stays light. Scoping to the body class keeps dark mode inside
       pages that opted in by carrying `.mh-public`.

   (b) Every component override below is scoped the same way. They were
       briefly written as bare `.card` / `.bg-white` / `.text-muted` /
       `img{opacity:.92}`, which is a site-wide repaint of bootstrap
       classes — exactly the kind of leak that turns unrelated panels black.

   `.mh-no-dark` is set on <body> whenever $adminOverview is true, so the
   admin real view ALWAYS shows what a light-mode visitor sees. That view
   exists to preview the public page; honouring the admin's own OS theme
   there is wrong regardless of whether it looks good. */
@media (prefers-color-scheme: dark){
  body.mh-public:not(.mh-no-dark){
    --mhd-ink-900:#e8ebee; --mhd-ink-700:#d3d8dd; --mhd-ink-500:#9aa4ae;
    --mhd-ink-450:#8b949e; --mhd-ink-300:#3a4048; --mhd-ink-200:#2a2f36;
    --mhd-ink-100:#21252b;
    --mhd-canvas:#101216; --mhd-surface:#16181c; --mhd-surface-raised:#1d2026;
    --mhd-border:#2a2f36; --mhd-border-strong:#3a4048;
    --mhd-primary:#ff8a95; --mhd-primary-700:#ffb3ba; --mhd-primary-tint:#2b1416;
    --mhd-on-primary:#16181c;
    --mhd-accent:#4fd2dc;  --mhd-accent-700:#7fe2ea; --mhd-accent-tint:#10272a;
    --mhd-success:#6ede9c; --mhd-success-tint:#11231a;
    --mhd-warning:#e9b764; --mhd-warning-tint:#2a1f0d;
    --mhd-info:#8ab8f0;    --mhd-info-tint:#111c2b;
    --mhd-focus:#8ab8f0;
    --mhd-cat1-fg:#f3b98a; --mhd-cat1-bg:#2c1d12;
    --mhd-cat2-fg:#9cc2f2; --mhd-cat2-bg:#141f2e;
    --mhd-cat3-fg:#86d5a4; --mhd-cat3-bg:#13241a;
    --mhd-cat4-fg:#c9a3e8; --mhd-cat4-bg:#221831;
    --mhd-cat5-fg:#f2a0bd; --mhd-cat5-bg:#2b1420;
    --mhd-cat6-fg:#86cdd4; --mhd-cat6-bg:#122628;
    --mhd-sh-1:0 1px 2px rgba(0,0,0,.5);
    --mhd-sh-2:0 4px 8px -2px rgba(0,0,0,.55);
    --mhd-sh-3:0 12px 28px -8px rgba(0,0,0,.65);
  }
  /* bootstrap 4 hardcodes these and they are unreadable on a dark canvas.
     Every selector is prefixed — see containment rule (b) above. */
  body.mh-public:not(.mh-no-dark) .card,
  body.mh-public:not(.mh-no-dark) .list-group-item{
    background-color:var(--mhd-surface)!important;border-color:var(--mhd-border)!important}
  body.mh-public:not(.mh-no-dark) .text-muted{color:var(--mhd-ink-500)!important}
  body.mh-public:not(.mh-no-dark) .bg-white,
  body.mh-public:not(.mh-no-dark) .bg-light{background-color:var(--mhd-surface)!important}
  body.mh-public:not(.mh-no-dark) .btn-outline-secondary{
    color:var(--mhd-ink-700);border-color:var(--mhd-border-strong)}
  body.mh-public:not(.mh-no-dark) .form-control{
    background-color:var(--mhd-surface-raised);border-color:var(--mhd-border);color:var(--mhd-ink-900)}
  body.mh-public:not(.mh-no-dark) .form-control::placeholder{color:var(--mhd-ink-450)}
  /* the pre-existing media/channel surfaces hardcode #fff in
     media-single-public.css and the per-page <style> blocks — caught by the
     dark containment test (white cards on a dark canvas on /media/{slug}) */
  body.mh-public:not(.mh-no-dark) .mh-card,
  body.mh-public:not(.mh-no-dark) .mh-related-card,
  body.mh-public:not(.mh-no-dark) .mh-cardstrip-card,
  body.mh-public:not(.mh-no-dark) .mh-link-box,
  body.mh-public:not(.mh-no-dark) .mh-author-box,
  body.mh-public:not(.mh-no-dark) .mh-comment,
  body.mh-public:not(.mh-no-dark) .mh-plyr-audio-card,
  body.mh-public:not(.mh-no-dark) .mh-side-menu,
  body.mh-public:not(.mh-no-dark) .mh-toc{
    background:var(--mhd-surface)!important;
    border-color:var(--mhd-border)!important;
    color:var(--mhd-ink-700);
  }
  body.mh-public:not(.mh-no-dark) .mh-card-title,
  body.mh-public:not(.mh-no-dark) .mh-card-title a,
  body.mh-public:not(.mh-no-dark) .mh-cardstrip-name,
  body.mh-public:not(.mh-no-dark) .mh-article-title,
  body.mh-public:not(.mh-no-dark) .mh-body-heading{ color:var(--mhd-ink-900) }
  body.mh-public:not(.mh-no-dark) .mh-article-meta{ background:var(--mhd-surface-raised) }
}

/* ---------- 4. Base / typography (C1, C7) -------------------------------- */
html{ -webkit-text-size-adjust:100%; }
/* C15: the scroll-to-top button jumped instantly */
html{ scroll-behavior:smooth; }
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  /* scoped on purpose: a bare universal selector here would also freeze the admin
     real-view overlay's animations inside its iframe (2026-10-04 containment) */
  body.mh-public *,body.mh-public *::before,body.mh-public *::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}
body.mh-public{
  font-family:var(--mhd-font)!important;
  font-size:var(--mhd-fs-base);
  line-height:var(--mhd-lh-ui);
  color:var(--mhd-ink-700);
  background:var(--mhd-canvas);
  -webkit-font-smoothing:antialiased;
}
/* The audit's C1: these two pages shipped `body{font-family:Tahoma}` inline and
   typography-head shipped a latin-system-stack-first list that terminated in a
   generic family. `.mh-public` + !important above is the single source of truth. */
body.mh-public input,body.mh-public select,body.mh-public textarea,
body.mh-public button,body.mh-public .btn,body.mh-public .form-control{
  font-family:var(--mhd-font);
}
body.mh-public h1,body.mh-public h2,body.mh-public h3,
body.mh-public h4,body.mh-public h5,body.mh-public h6{
  font-family:var(--mhd-font);
  color:var(--mhd-ink-900);
  line-height:var(--mhd-lh-head);
  font-weight:var(--mhd-fw-bold);
  margin:0 0 var(--mhd-sp-4);
}
body.mh-public h1{font-size:var(--mhd-fs-3xl);font-weight:var(--mhd-fw-black);line-height:var(--mhd-lh-display);letter-spacing:-.01em}
body.mh-public h2{font-size:var(--mhd-fs-2xl);font-weight:var(--mhd-fw-bold)}
body.mh-public h3{font-size:var(--mhd-fs-xl)}
body.mh-public h4{font-size:var(--mhd-fs-lg)}
body.mh-public h5{font-size:var(--mhd-fs-md)}
body.mh-public h6{font-size:var(--mhd-fs-base);font-weight:var(--mhd-fw-medium)}
@media (max-width:767.98px){
  body.mh-public h1{font-size:var(--mhd-fs-2xl)}
  body.mh-public h2{font-size:var(--mhd-fs-xl)}
  body.mh-public h3{font-size:var(--mhd-fs-lg)}
}
body.mh-public a{color:var(--mhd-primary);text-decoration:none}
body.mh-public a:hover{color:var(--mhd-primary-700);text-decoration:underline}
body.mh-public .container{max-width:var(--mhd-container)}

/* focus-visible everywhere (C7 / welcome-page defect) */
body.mh-public :focus-visible,
.mh-skip-link:focus{
  outline:3px solid var(--mhd-focus);
  outline-offset:2px;
  border-radius:var(--mhd-r-sm);
}
body.mh-public :focus:not(:focus-visible){outline:none}

/* skip link (C7) */
.mh-skip-link{
  position:absolute;top:-100px;inset-inline-start:var(--mhd-sp-4);z-index:10000;
  background:var(--mhd-surface);color:var(--mhd-primary);
  padding:var(--mhd-sp-3) var(--mhd-sp-5);border-radius:var(--mhd-r-md);
  box-shadow:var(--mhd-sh-3);font-weight:var(--mhd-fw-bold);
  transition:top .15s ease;
}
.mh-skip-link:focus{top:var(--mhd-sp-4)}

/* visually-hidden (for the H1s the audit wanted but that must not change layout) */
.mh-vh{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- 5. Site navigation (C4) ------------------------------------- */
.mh-nav{
  background:var(--mhd-surface);
  border-bottom:1px solid var(--mhd-border);
  position:sticky;top:0;z-index:1030;
  box-shadow:var(--mhd-sh-1);
}
.mh-nav-inner{
  max-width:var(--mhd-container);margin:0 auto;
  display:flex;align-items:center;gap:var(--mhd-sp-4);
  padding:0 var(--mhd-sp-4);min-height:56px;
}
.mh-nav-brand{
  display:inline-flex;align-items:center;gap:var(--mhd-sp-2);
  font-size:var(--mhd-fs-md);font-weight:var(--mhd-fw-black);
  color:var(--mhd-ink-900)!important;text-decoration:none!important;
  white-space:nowrap;min-height:var(--mhd-tap);
}
.mh-nav-brand i{color:var(--mhd-primary)}
.mh-nav-links{
  display:flex;align-items:center;gap:var(--mhd-sp-1);
  list-style:none;margin:0;padding:0;flex:1 1 auto;
  overflow-x:auto;scrollbar-width:none;
}
.mh-nav-links::-webkit-scrollbar{display:none}
.mh-nav-links>li{flex:0 0 auto}
.mh-nav-links a{
  display:inline-flex;align-items:center;gap:var(--mhd-sp-2);
  padding:var(--mhd-sp-3) var(--mhd-sp-3);min-height:var(--mhd-tap);
  border-radius:var(--mhd-r-sm);
  font-size:var(--mhd-fs-sm);font-weight:var(--mhd-fw-medium);
  color:var(--mhd-ink-700)!important;text-decoration:none!important;
  white-space:nowrap;
}
.mh-nav-links a:hover{background:var(--mhd-ink-100);color:var(--mhd-ink-900)!important}
.mh-nav-links a[aria-current="page"]{
  color:var(--mhd-primary)!important;background:var(--mhd-primary-tint);
}
.mh-nav-actions{display:flex;align-items:center;gap:var(--mhd-sp-2);margin-inline-start:auto}
.mh-nav-icon{
  display:inline-flex;align-items:center;justify-content:center;
  width:var(--mhd-tap);height:var(--mhd-tap);border-radius:var(--mhd-r-sm);
  color:var(--mhd-ink-700)!important;background:none;border:0;cursor:pointer;
  font-size:var(--mhd-fs-base);
}
.mh-nav-icon:hover{background:var(--mhd-ink-100)}
.mh-nav-login{
  display:inline-flex;align-items:center;gap:var(--mhd-sp-2);
  min-height:var(--mhd-tap);padding:0 var(--mhd-sp-4);
  border-radius:var(--mhd-r-full);
  background:var(--mhd-primary);color:var(--mhd-on-primary)!important;
  font-size:var(--mhd-fs-sm);font-weight:var(--mhd-fw-bold);
  text-decoration:none!important;
}
.mh-nav-login:hover{background:var(--mhd-primary-700);color:var(--mhd-on-primary)!important}
.mh-nav-toggle{display:none}
/* inline search panel */
.mh-nav-search{
  display:none;border-top:1px solid var(--mhd-border);background:var(--mhd-surface);
  padding:var(--mhd-sp-3) var(--mhd-sp-4);
}
.mh-nav-search.is-open{display:block}
.mh-nav-search form{max-width:var(--mhd-container);margin:0 auto;display:flex;gap:var(--mhd-sp-2)}
.mh-nav-search input{
  flex:1;min-height:var(--mhd-tap);border:1px solid var(--mhd-border-strong);
  border-radius:var(--mhd-r-md);padding:0 var(--mhd-sp-4);
  background:var(--mhd-surface);color:var(--mhd-ink-900);font-size:var(--mhd-fs-base);
}
.mh-nav-search button{
  min-height:var(--mhd-tap);padding:0 var(--mhd-sp-5);border:0;
  border-radius:var(--mhd-r-md);background:var(--mhd-primary);
  color:var(--mhd-on-primary);font-weight:var(--mhd-fw-bold);cursor:pointer;
}
/* mobile: hamburger + collapsible drawer (C4) */
@media (max-width:991.98px){
  .mh-nav-toggle{
    display:inline-flex;align-items:center;justify-content:center;
    width:var(--mhd-tap);height:var(--mhd-tap);border:0;background:none;
    border-radius:var(--mhd-r-sm);color:var(--mhd-ink-900);cursor:pointer;
    font-size:var(--mhd-fs-md);
  }
  .mh-nav-links{
    display:none;position:absolute;inset-inline:0;top:100%;
    flex-direction:column;align-items:stretch;gap:0;
    background:var(--mhd-surface);border-bottom:1px solid var(--mhd-border);
    box-shadow:var(--mhd-sh-3);padding:var(--mhd-sp-2);
    max-height:70vh;overflow-y:auto;
  }
  .mh-nav-links.is-open{display:flex}
  .mh-nav-links a{width:100%;padding:var(--mhd-sp-3) var(--mhd-sp-4)}
  .mh-nav-inner{position:relative}
  .mh-nav-login span{display:none}
  .mh-nav-login{padding:0;width:var(--mhd-tap);justify-content:center}
}
.mh-nav-group-label{
  padding:var(--mhd-sp-2) var(--mhd-sp-3) var(--mhd-sp-1);
  font-size:var(--mhd-fs-xs);font-weight:var(--mhd-fw-bold);
  color:var(--mhd-ink-450);text-transform:none;
}

/* ---------- 6. Footer (C3 + Phase 3) ------------------------------------ */
.mh-footer{
  background:var(--mhd-ink-900);color:#c7cdd3;
  margin-top:var(--mhd-sp-20);
  padding:var(--mhd-sp-12) var(--mhd-sp-4) 0;
  font-size:var(--mhd-fs-sm);
}
@media (prefers-color-scheme: dark){ body.mh-public:not(.mh-no-dark) .mh-footer{background:#0b0d10} }
.mh-footer-inner{
  max-width:var(--mhd-container);margin:0 auto;
  display:grid;gap:var(--mhd-sp-8);
  grid-template-columns:1.4fr repeat(3,1fr);
}
@media (max-width:991.98px){ .mh-footer-inner{grid-template-columns:1fr 1fr} }
@media (max-width:575.98px){ .mh-footer-inner{grid-template-columns:1fr} }
/* PHASE 2 REGRESSION FIX (2026-10-04) — the footer column headings were
   INVISIBLE on every media page: measured 1.00:1, rgb(20,22,25) text on the
   rgb(20,22,25) footer. Pure specificity: section 4 sets
       body.mh-public h1..h6 { color:var(--mhd-ink-900) }   -> (0,1,2)
   and this rule was `.mh-footer h2`                        -> (0,1,1)
   so ink-900 won and painted near-black on the near-black footer. The footer
   LINKS already carried `!important`, which is why only the headings vanished
   and the previous pass's visual check missed it. Scoped to (0,2,2) so it wins
   on its own weight rather than by adding another `!important`. */
body.mh-public .mh-footer h2,body.mh-public .mh-footer h3,
.mh-footer h2,.mh-footer h3{
  font-size:var(--mhd-fs-sm);font-weight:var(--mhd-fw-bold);
  color:#ffffff;margin:0 0 var(--mhd-sp-4);letter-spacing:.02em;
}
.mh-footer-brand .mh-footer-logo{
  display:inline-flex;align-items:center;gap:var(--mhd-sp-2);
  font-size:var(--mhd-fs-md);font-weight:var(--mhd-fw-black);color:#fff!important;
  text-decoration:none!important;margin-bottom:var(--mhd-sp-3);
}
.mh-footer-brand .mh-footer-logo i{color:var(--mhd-primary)}
.mh-footer-desc{color:#aab2ba;line-height:1.7;margin:0 0 var(--mhd-sp-4);max-width:42ch}
.mh-footer-list{list-style:none;margin:0;padding:0}
.mh-footer-list li{margin-bottom:var(--mhd-sp-1)}
.mh-footer-list a{
  display:inline-block;color:#c7cdd3!important;text-decoration:none!important;
  padding:var(--mhd-sp-2) 0;min-height:var(--mhd-tap);line-height:1.6;
}
.mh-footer-list a:hover{color:#fff!important;text-decoration:underline!important}
.mh-footer-social{display:flex;gap:var(--mhd-sp-2);flex-wrap:wrap;margin-top:var(--mhd-sp-2)}
.mh-footer-social a{
  display:inline-flex;align-items:center;justify-content:center;
  width:var(--mhd-tap);height:var(--mhd-tap);border-radius:var(--mhd-r-full);
  background:rgba(255,255,255,.08);color:#e8ebee!important;
  text-decoration:none!important;
}
.mh-footer-social a:hover{background:var(--mhd-primary);color:#fff!important}
.mh-footer-bar{
  max-width:var(--mhd-container);margin:var(--mhd-sp-10) auto 0;
  border-top:1px solid rgba(255,255,255,.12);
  padding:var(--mhd-sp-5) 0;
  display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:var(--mhd-sp-3);
  color:#99a1a9;font-size:var(--mhd-fs-xs);
}
.mh-footer-bar a{color:#c7cdd3!important;text-decoration:none!important}
.mh-footer-bar a:hover{color:#fff!important;text-decoration:underline!important}
.mh-footer-bar p{margin:0}
/* newsletter */
.mh-footer-news{display:flex;gap:var(--mhd-sp-2);max-width:360px}
.mh-footer-news input{
  flex:1;min-height:var(--mhd-tap);border:1px solid rgba(255,255,255,.18);
  border-radius:var(--mhd-r-md);background:rgba(255,255,255,.06);
  color:#fff;padding:0 var(--mhd-sp-3);font-size:var(--mhd-fs-sm);
  font-family:var(--mhd-font);
}
.mh-footer-news input::placeholder{color:#8b949e}
.mh-footer-news button{
  min-height:var(--mhd-tap);padding:0 var(--mhd-sp-4);border:0;
  border-radius:var(--mhd-r-md);background:var(--mhd-primary);color:#fff;
  font-weight:var(--mhd-fw-bold);font-size:var(--mhd-fs-sm);cursor:pointer;
  font-family:var(--mhd-font);
}
.mh-footer-news button:hover{background:var(--mhd-primary-700)}

/* ---------- 7. ONE card component (C: each page had its own) ------------ */
.mh-card{
  display:flex;flex-direction:column;height:100%;
  background:var(--mhd-surface);
  border:1px solid var(--mhd-border);
  border-radius:var(--mhd-r-md);
  overflow:hidden;
  box-shadow:var(--mhd-sh-1);
  transition:box-shadow .18s ease,transform .18s ease,border-color .18s ease;
}
.mh-card:hover{box-shadow:var(--mhd-sh-2);border-color:var(--mhd-border-strong);transform:translateY(-2px)}
.mh-card-media{
  position:relative;display:block;
  aspect-ratio:16/9;                /* fixes the 3.41-vs-1.65 mixed ratios */
  background:var(--mhd-ink-100);
  overflow:hidden;
}
.mh-card-media>img{width:100%;height:100%;object-fit:cover;display:block}
.mh-card:hover .mh-card-media>img{transform:scale(1.03)}
.mh-card-media>img{transition:transform .3s ease}
.mh-card-body{
  display:flex;flex-direction:column;gap:var(--mhd-sp-2);
  padding:var(--mhd-sp-4);flex:1 1 auto;
}
.mh-card-title{
  margin:0;font-size:var(--mhd-fs-md);font-weight:var(--mhd-fw-bold);
  line-height:var(--mhd-lh-head);
}
.mh-card-title a{
  color:var(--mhd-ink-900)!important;text-decoration:none!important;
  display:block;
  /* clamp so mixed title lengths do not break the grid rhythm */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.mh-card:hover .mh-card-title a{color:var(--mhd-primary)!important}
.mh-card-excerpt{
  margin:0;font-size:var(--mhd-fs-sm);color:var(--mhd-ink-500);line-height:1.7;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.mh-card-meta{
  margin-top:auto;display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--mhd-sp-1) var(--mhd-sp-3);
  font-size:var(--mhd-fs-xs);color:var(--mhd-ink-450);
  padding-top:var(--mhd-sp-1);
}
.mh-card-meta i{opacity:.75;margin-inline-end:2px}
.mh-card-meta>span{display:inline-flex;align-items:center}

/* PHASE 2 (2026-10-04): `.mh-card-row` — the WIDE HORIZONTAL variant.
   The channel page's blog list had its own second card component
   (`.mh-ch-row-card`: thumb beside the text, own border/radius/shadow/padding
   off the token scale). Rather than keep two components, that layout is now a
   modifier of the one card, so hub / magazine / channel all render `.mh-card`.
   Only the axis changes; surface, border, radius, shadow and hover are shared. */
.mh-card-row{flex-direction:row;align-items:stretch}
.mh-card-row>.mh-card-media{
  flex:0 0 240px;width:240px;aspect-ratio:auto;align-self:stretch;
}
.mh-card-row>.mh-card-media>img,
.mh-card-row>.mh-card-media>.mh-ph{min-height:150px;height:100%}
.mh-card-row>.mh-card-body{padding:var(--mhd-sp-4) var(--mhd-sp-5)}
/* the row card's title can afford a third line and the excerpt a fourth */
.mh-card-row .mh-card-title a{-webkit-line-clamp:2}
.mh-card-row .mh-card-excerpt{-webkit-line-clamp:3}
@media (max-width:575.98px){
  .mh-card-row{flex-direction:column}
  .mh-card-row>.mh-card-media{flex:1 1 auto;width:100%;aspect-ratio:16/9}
  .mh-card-row>.mh-card-body{padding:var(--mhd-sp-4)}
}

/* shared missing-image placeholder (reuses the channel template's good one) */
.mh-ph{
  display:flex;align-items:center;justify-content:center;
  width:100%;height:100%;
  background:linear-gradient(135deg,var(--mhd-ink-100) 0%,var(--mhd-ink-200) 100%);
  color:var(--mhd-ink-450);font-size:var(--mhd-fs-2xl);
}
.mh-ph i{opacity:.55}

/* type badge on card media */
.mh-card-type{
  position:absolute;inset-block-start:var(--mhd-sp-2);inset-inline-start:var(--mhd-sp-2);
  display:inline-flex;align-items:center;gap:var(--mhd-sp-1);
  background:rgba(20,22,25,.78);color:#fff;
  padding:var(--mhd-sp-1) var(--mhd-sp-2);border-radius:var(--mhd-r-sm);
  font-size:var(--mhd-fs-xs);font-weight:var(--mhd-fw-medium);
  backdrop-filter:blur(4px);
}
.mh-card-dur{
  position:absolute;inset-block-end:var(--mhd-sp-2);inset-inline-end:var(--mhd-sp-2);
  background:rgba(20,22,25,.82);color:#fff;
  padding:2px var(--mhd-sp-2);border-radius:var(--mhd-r-sm);
  font-size:var(--mhd-fs-xs);font-variant-numeric:tabular-nums;
}

/* ---------- 8. Pills / badges (C11, C12) -------------------------------- */
.mh-pill{
  display:inline-flex;align-items:center;gap:var(--mhd-sp-1);
  padding:var(--mhd-sp-1) var(--mhd-sp-3);min-height:28px;
  border-radius:var(--mhd-r-full);
  font-size:var(--mhd-fs-xs);font-weight:var(--mhd-fw-bold);
  text-decoration:none!important;line-height:1.4;
  background:var(--mhd-ink-100);color:var(--mhd-ink-700)!important;
  border:1px solid transparent;
}
.mh-pill:hover{filter:brightness(.96);text-decoration:none!important}
.mh-pill-c1{background:var(--mhd-cat1-bg);color:var(--mhd-cat1-fg)!important}
.mh-pill-c2{background:var(--mhd-cat2-bg);color:var(--mhd-cat2-fg)!important}
.mh-pill-c3{background:var(--mhd-cat3-bg);color:var(--mhd-cat3-fg)!important}
.mh-pill-c4{background:var(--mhd-cat4-bg);color:var(--mhd-cat4-fg)!important}
.mh-pill-c5{background:var(--mhd-cat5-bg);color:var(--mhd-cat5-fg)!important}
.mh-pill-c6{background:var(--mhd-cat6-bg);color:var(--mhd-cat6-fg)!important}
/* C12: `.cat-pill` orange-on-white was 3.26:1 — retokenised */
body.mh-public .cat-pill{
  background:var(--mhd-cat1-bg)!important;color:var(--mhd-cat1-fg)!important;
  border-color:transparent!important;
}
/* "ویژه" badge was yellow-on-white */
body.mh-public .badge-warning,.mh-badge-featured{
  background:var(--mhd-warning-tint)!important;color:var(--mhd-warning)!important;
  font-weight:var(--mhd-fw-bold);border-radius:var(--mhd-r-full);
  padding:var(--mhd-sp-1) var(--mhd-sp-3);font-size:var(--mhd-fs-xs);
}

/* ---------- 9. Buttons (C11, C13) --------------------------------------- */
.mh-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--mhd-sp-2);
  min-height:var(--mhd-tap);padding:0 var(--mhd-sp-5);
  border-radius:var(--mhd-r-md);border:1px solid transparent;
  font-family:var(--mhd-font);font-size:var(--mhd-fs-sm);font-weight:var(--mhd-fw-bold);
  text-decoration:none!important;cursor:pointer;
  transition:background .15s ease,color .15s ease,border-color .15s ease;
}
.mh-btn-primary{background:var(--mhd-primary);color:var(--mhd-on-primary)!important}
.mh-btn-primary:hover{background:var(--mhd-primary-700);color:var(--mhd-on-primary)!important}
.mh-btn-ghost{background:transparent;color:var(--mhd-ink-700)!important;border-color:var(--mhd-border-strong)}
.mh-btn-ghost:hover{background:var(--mhd-ink-100);color:var(--mhd-ink-900)!important}
.mh-btn-sm{min-height:36px;padding:0 var(--mhd-sp-4);font-size:var(--mhd-fs-xs)}
/* bootstrap buttons used across the existing markup */
body.mh-public .btn{font-family:var(--mhd-font);border-radius:var(--mhd-r-md)}
body.mh-public .btn-primary{background-color:var(--mhd-primary);border-color:var(--mhd-primary);color:var(--mhd-on-primary)}
body.mh-public .btn-primary:hover{background-color:var(--mhd-primary-700);border-color:var(--mhd-primary-700)}
body.mh-public .btn-outline-secondary{
  color:var(--mhd-ink-700);border-color:var(--mhd-border-strong);
  min-height:36px;display:inline-flex;align-items:center;
}
body.mh-public .btn-outline-secondary:hover{background:var(--mhd-ink-100);color:var(--mhd-ink-900);border-color:var(--mhd-border-strong)}
/* C13: raise every too-small interactive element to the 44px comfortable min */
body.mh-public a.mh-backtosite,body.mh-public .hdr3-social-login,
body.mh-public .lang-input,body.mh-public select.lang-input{
  min-height:var(--mhd-tap);display:inline-flex;align-items:center;
}

/* ---------- 10. Section headers ----------------------------------------- */
.mh-section{margin-bottom:var(--mhd-sp-12)}
.mh-section-head{
  display:flex;align-items:center;justify-content:space-between;
  flex-wrap:wrap;gap:var(--mhd-sp-3);
  margin-bottom:var(--mhd-sp-5);
  padding-bottom:var(--mhd-sp-3);
  border-bottom:2px solid var(--mhd-border);
}
.mh-section-title{
  display:flex;align-items:center;gap:var(--mhd-sp-3);
  margin:0;font-size:var(--mhd-fs-xl);font-weight:var(--mhd-fw-black);
  color:var(--mhd-ink-900);
}
.mh-section-title::before{
  content:"";width:4px;height:1.1em;border-radius:var(--mhd-r-full);
  background:var(--mhd-section-accent,var(--mhd-primary));flex:0 0 auto;
}
.mh-section-sub{font-size:var(--mhd-fs-sm);color:var(--mhd-ink-500);margin:var(--mhd-sp-1) 0 0}

/* ---------- 11. Hero / lead story (hub + magazine) ---------------------- */
.mh-lead{
  display:grid;gap:var(--mhd-sp-5);
  grid-template-columns:1.6fr 1fr;
  margin-bottom:var(--mhd-sp-12);
}
@media (max-width:767.98px){ .mh-lead{grid-template-columns:1fr} }
.mh-lead-main{
  position:relative;display:block;border-radius:var(--mhd-r-lg);
  overflow:hidden;background:var(--mhd-ink-900);min-height:320px;
  text-decoration:none!important;box-shadow:var(--mhd-sh-2);
}
.mh-lead-main img{width:100%;height:100%;min-height:320px;object-fit:cover;display:block;opacity:.86}
.mh-lead-main:hover img{opacity:1}
.mh-lead-cap{
  position:absolute;inset-inline:0;inset-block-end:0;
  padding:var(--mhd-sp-10) var(--mhd-sp-6) var(--mhd-sp-6);
  /* C: white-on-near-white gradient captions were unreadable */
  background:linear-gradient(to top,rgba(10,11,13,.94) 0%,rgba(10,11,13,.78) 45%,rgba(10,11,13,0) 100%);
  color:#fff;
}
.mh-lead-cap h2,.mh-lead-cap h3{
  color:#fff!important;margin:0 0 var(--mhd-sp-2);
  font-size:var(--mhd-fs-2xl);font-weight:var(--mhd-fw-black);
  line-height:var(--mhd-lh-display);
  text-shadow:0 1px 2px rgba(0,0,0,.5);
}
@media (max-width:767.98px){ .mh-lead-cap h2,.mh-lead-cap h3{font-size:var(--mhd-fs-lg)} }
.mh-lead-cap .mh-lead-meta{font-size:var(--mhd-fs-xs);color:#d3d8dd;display:flex;gap:var(--mhd-sp-3);flex-wrap:wrap}
.mh-lead-side{display:flex;flex-direction:column;gap:var(--mhd-sp-3)}
.mh-lead-side-item{
  display:flex;gap:var(--mhd-sp-3);align-items:flex-start;
  background:var(--mhd-surface);border:1px solid var(--mhd-border);
  border-radius:var(--mhd-r-md);padding:var(--mhd-sp-3);
  text-decoration:none!important;box-shadow:var(--mhd-sh-1);
  transition:border-color .15s ease,box-shadow .15s ease;
}
.mh-lead-side-item:hover{border-color:var(--mhd-border-strong);box-shadow:var(--mhd-sh-2)}
.mh-lead-side-thumb{
  flex:0 0 96px;width:96px;aspect-ratio:16/10;border-radius:var(--mhd-r-sm);
  overflow:hidden;background:var(--mhd-ink-100);
}
.mh-lead-side-thumb img{width:100%;height:100%;object-fit:cover}
.mh-lead-side-txt{flex:1 1 auto;min-width:0}
.mh-lead-side-txt strong{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  font-size:var(--mhd-fs-sm);font-weight:var(--mhd-fw-bold);color:var(--mhd-ink-900);
  line-height:var(--mhd-lh-head);
}
.mh-lead-side-txt small{display:block;margin-top:var(--mhd-sp-1);color:var(--mhd-ink-450);font-size:var(--mhd-fs-xs)}

/* ---------- 12. Grid that never leaves empty columns -------------------- */
/* C: "sparse content-type rows rendering as broken-looking grids with 3 empty
   columns" — auto-fill with a min track instead of fixed col-md-3. */
.mh-grid{
  display:grid;gap:var(--mhd-sp-5);
  grid-template-columns:repeat(auto-fill,minmax(248px,1fr));
}
@media (max-width:575.98px){
  .mh-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:var(--mhd-sp-3)}
}
.mh-grid-1 .mh-card,.mh-grid-2 .mh-card{max-width:100%}

/* ---------- 13. Channel identity header (Phase 1) ---------------------- */
.mh-chan{
  background:var(--mhd-surface);border:1px solid var(--mhd-border);
  border-radius:var(--mhd-r-lg);overflow:hidden;
  margin-bottom:var(--mhd-sp-8);
  box-shadow:var(--mhd-sh-1);
}
.mh-chan .mh-chan-body{padding-inline:var(--mhd-sp-6)}
@media (max-width:575.98px){ .mh-chan .mh-chan-body{padding-inline:var(--mhd-sp-4)} }
.mh-chan-banner{
  height:200px;background:var(--mhd-ink-200);position:relative;overflow:hidden;
  background-image:linear-gradient(135deg,var(--mhd-chan-accent,var(--mhd-primary)) 0%,var(--mhd-ink-900) 100%);
}
@media (max-width:767.98px){ .mh-chan-banner{height:120px} }
.mh-chan-banner img{width:100%;height:100%;object-fit:cover;display:block}
.mh-chan-body{
  max-width:var(--mhd-container);margin:0 auto;
  padding:0 var(--mhd-sp-4) var(--mhd-sp-6);
  display:flex;align-items:flex-end;gap:var(--mhd-sp-5);flex-wrap:wrap;
}
.mh-chan-avatar{
  flex:0 0 auto;width:112px;height:112px;margin-block-start:-40px;
  border-radius:var(--mhd-r-full);overflow:hidden;
  background:var(--mhd-surface);border:4px solid var(--mhd-surface);
  box-shadow:var(--mhd-sh-2);
  display:flex;align-items:center;justify-content:center;
  font-size:var(--mhd-fs-3xl);font-weight:var(--mhd-fw-black);
  color:var(--mhd-on-primary);
}
.mh-chan-avatar img{width:100%;height:100%;object-fit:cover}
@media (max-width:767.98px){
  .mh-chan-avatar{width:76px;height:76px;margin-block-start:-28px;font-size:var(--mhd-fs-xl)}
  .mh-chan-body{padding-bottom:var(--mhd-sp-5)}
}
.mh-chan-txt{flex:1 1 260px;min-width:0;padding-block-start:var(--mhd-sp-4)}
.mh-chan-name{
  margin:0 0 var(--mhd-sp-1);font-size:var(--mhd-fs-2xl);
  font-weight:var(--mhd-fw-black);color:var(--mhd-ink-900);line-height:var(--mhd-lh-display);
}
.mh-chan-tag{margin:0 0 var(--mhd-sp-2);color:var(--mhd-ink-500);font-size:var(--mhd-fs-sm);max-width:64ch}
.mh-chan-stats{
  display:flex;flex-wrap:wrap;gap:var(--mhd-sp-1) var(--mhd-sp-5);
  font-size:var(--mhd-fs-xs);color:var(--mhd-ink-450);margin:0;
}
.mh-chan-stats b{color:var(--mhd-ink-900);font-weight:var(--mhd-fw-bold);font-size:var(--mhd-fs-sm)}
.mh-chan-actions{display:flex;gap:var(--mhd-sp-2);flex-wrap:wrap;padding-block-start:var(--mhd-sp-4)}

/* ---------- 14. Article prose (measure, hierarchy) ---------------------- */
.mh-prose{
  max-width:var(--mhd-measure);        /* C: 123 chars/line -> ~68ch */
  font-size:var(--mhd-fs-md);          /* 18px */
  line-height:var(--mhd-lh-prose);
  color:var(--mhd-ink-700);
}
.mh-prose>*+*{margin-block-start:var(--mhd-sp-6)}
.mh-prose p{margin:0 0 var(--mhd-sp-6)}
.mh-prose h2{font-size:var(--mhd-fs-xl);margin:var(--mhd-sp-10) 0 var(--mhd-sp-4)}
.mh-prose h3{font-size:var(--mhd-fs-lg);margin:var(--mhd-sp-8) 0 var(--mhd-sp-3)}
.mh-prose img{max-width:100%;height:auto;border-radius:var(--mhd-r-md)}
.mh-prose blockquote{
  margin:var(--mhd-sp-8) 0;padding:var(--mhd-sp-1) var(--mhd-sp-6);
  border-inline-start:4px solid var(--mhd-primary);
  color:var(--mhd-ink-900);font-size:var(--mhd-fs-lg);font-weight:var(--mhd-fw-medium);
}
.mh-prose ul,.mh-prose ol{padding-inline-start:var(--mhd-sp-6);margin:0 0 var(--mhd-sp-6)}
.mh-prose li+li{margin-block-start:var(--mhd-sp-2)}
.mh-prose a{color:var(--mhd-primary);text-decoration:underline;text-underline-offset:2px}
.mh-prose table{width:100%;border-collapse:collapse;font-size:var(--mhd-fs-sm)}
.mh-prose table th,.mh-prose table td{border:1px solid var(--mhd-border);padding:var(--mhd-sp-2) var(--mhd-sp-3)}
.mh-prose-wrap{overflow-x:auto}
/* headline hierarchy: H1 was 26px with the lede smaller than body text */
.mh-lede{
  max-width:var(--mhd-measure);
  font-size:var(--mhd-fs-lg);line-height:1.65;
  color:var(--mhd-ink-500);font-weight:var(--mhd-fw-normal);
  margin:0 0 var(--mhd-sp-6);
}
.mh-kicker{
  font-size:var(--mhd-fs-xs);font-weight:var(--mhd-fw-black);
  letter-spacing:.06em;color:var(--mhd-primary);
  margin-bottom:var(--mhd-sp-2);text-transform:uppercase;
}

/* ---------- 15. Breadcrumbs (C15) --------------------------------------- */
.mh-crumbs{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--mhd-sp-1);
  font-size:var(--mhd-fs-xs);color:var(--mhd-ink-450);
  margin:0 0 var(--mhd-sp-4);padding:0;list-style:none;
}
.mh-crumbs li{display:flex;align-items:center;gap:var(--mhd-sp-1)}
.mh-crumbs li+li::before{content:"‹";color:var(--mhd-ink-300);margin:0 var(--mhd-sp-1)}
.mh-crumbs a{color:var(--mhd-ink-500)!important;text-decoration:none!important}
.mh-crumbs a:hover{color:var(--mhd-primary)!important;text-decoration:underline!important}
.mh-crumbs [aria-current]{color:var(--mhd-ink-700);font-weight:var(--mhd-fw-medium)}

/* ---------- 16. Reading progress + TOC (Phase 3) ----------------------- */
.mh-progress{
  position:fixed;inset-block-start:0;inset-inline:0;height:3px;z-index:2000;
  background:transparent;pointer-events:none;
}
.mh-progress>i{
  display:block;height:100%;width:0;
  background:var(--mhd-primary);transition:width .1s linear;
}
.mh-toc{
  background:var(--mhd-surface);border:1px solid var(--mhd-border);
  border-radius:var(--mhd-r-md);padding:var(--mhd-sp-4) var(--mhd-sp-5);
  margin:0 0 var(--mhd-sp-8);font-size:var(--mhd-fs-sm);
}
.mh-toc>summary{
  cursor:pointer;font-weight:var(--mhd-fw-bold);color:var(--mhd-ink-900);
  min-height:var(--mhd-tap);display:flex;align-items:center;gap:var(--mhd-sp-2);
}
.mh-toc ol{margin:var(--mhd-sp-3) 0 0;padding-inline-start:var(--mhd-sp-5)}
.mh-toc li{margin-bottom:var(--mhd-sp-1)}
.mh-toc a{
  color:var(--mhd-ink-500)!important;text-decoration:none!important;
  display:inline-block;padding:var(--mhd-sp-1) 0;
}
.mh-toc a:hover{color:var(--mhd-primary)!important;text-decoration:underline!important}
.mh-readmeta{
  display:flex;flex-wrap:wrap;gap:var(--mhd-sp-2) var(--mhd-sp-5);
  font-size:var(--mhd-fs-xs);color:var(--mhd-ink-450);
  margin:0 0 var(--mhd-sp-6);
}

/* ---------- 17. Skeleton loading (C15) --------------------------------- */
@keyframes mh-shimmer{to{background-position:-200% 0}}
.mh-skel{
  background:linear-gradient(90deg,var(--mhd-ink-100) 25%,var(--mhd-ink-200) 37%,var(--mhd-ink-100) 63%);
  background-size:200% 100%;
  animation:mh-shimmer 1.4s ease-in-out infinite;
  border-radius:var(--mhd-r-sm);
}
.mh-skel-line{display:block;height:12px;margin-bottom:var(--mhd-sp-2)}
/* PHASE 3 (2026-10-04): the skeleton CARD. The sheet already had `.mh-skel`
   but nothing rendered one — measured hasSkeleton=false on all ten pages.
   public-scripts now swaps a list's children for these while a sort / "more"
   / type-tab navigation is in flight. It reuses `.mh-card` + `.mh-card-media`
   so the skeleton occupies exactly the geometry the real cards will, which is
   the whole point — a skeleton that shifts on arrival is worse than none. */
/* `overflow:hidden` matters: public-scripts pins each skeleton to the exact
   height of the card it replaces, and the skeleton's own content (16/9 media
   + three lines + padding) can exceed that on a short card such as a podcast
   tile. Without clipping, the pin would be ignored and the list would jump. */
.mh-skel-card{pointer-events:none;box-shadow:none;overflow:hidden}
.mh-skel-card .mh-card-media{display:block;flex:0 0 auto}
/* Measured: a real `.mh-card-row` on the channel blog list is ~152px tall at
   desktop, because its media carries min-height:150px while three skeleton
   text lines only came to 110px — a 25% jump as the real cards arrived.
   Matching the floor brings that to ~1%, which is the whole point of a
   skeleton. The vertical variant needs no floor: its media is aspect-ratio
   16/9, so width already determines the height exactly. */
.mh-skel-card.mh-card-row{min-height:150px}
.mh-skel-card .mh-card-body{gap:var(--mhd-sp-3);padding-block:var(--mhd-sp-4)}
.mh-skel-card .mh-skel-line:last-child{margin-bottom:0}
[aria-busy="true"]{position:relative}
.mh-skel-media{aspect-ratio:16/9;border-radius:0}
/* reveal on scroll */
.mh-reveal{opacity:0;transform:translateY(14px);transition:opacity .5s ease,transform .5s ease}
.mh-reveal.is-in{opacity:1;transform:none}
@media (prefers-reduced-motion: reduce){ body.mh-public .mh-reveal{opacity:1;transform:none} }

/* ---------- 18. Player (video poster fallback / podcast) --------------- */
/* C: "video page's player area renders as a pure white void" — always show a
   poster + play affordance behind the embed until it paints. */
.mh-embed{
  position:relative;aspect-ratio:16/9;width:100%;
  background:var(--mhd-ink-900);border-radius:var(--mhd-r-md);overflow:hidden;
}
.mh-embed>iframe{position:absolute;inset:0;width:100%;height:100%;border:0;z-index:2}
.mh-embed-poster{
  position:absolute;inset:0;z-index:1;
  display:flex;align-items:center;justify-content:center;
  background:var(--mhd-ink-900);
}
.mh-embed-poster img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.55}
.mh-embed-play{
  position:relative;z-index:2;
  display:flex;align-items:center;justify-content:center;
  width:72px;height:72px;border-radius:var(--mhd-r-full);
  background:rgba(255,255,255,.92);color:var(--mhd-ink-900);
  font-size:var(--mhd-fs-xl);box-shadow:var(--mhd-sh-3);
}
.mh-embed-spin{
  position:absolute;inset-block-end:var(--mhd-sp-4);inset-inline:0;z-index:2;
  text-align:center;color:#c7cdd3;font-size:var(--mhd-fs-xs);
}
/* Plyr theming through the token system */
body.mh-public .plyr{
  --plyr-color-main:var(--mhd-primary);
  --plyr-font-family:var(--mhd-font);
  --plyr-audio-controls-background:var(--mhd-surface);
  --plyr-audio-control-color:var(--mhd-ink-700);
  --plyr-audio-control-color-hover:var(--mhd-on-primary);
  --plyr-badge-background:var(--mhd-primary);
  --plyr-range-track-height:6px;
  --plyr-control-icon-size:18px;
  border-radius:var(--mhd-r-md);
}
.mh-pod-player{
  background:var(--mhd-surface);border:1px solid var(--mhd-border);
  border-radius:var(--mhd-r-lg);padding:var(--mhd-sp-5);
  box-shadow:var(--mhd-sh-1);margin-bottom:var(--mhd-sp-6);
}
.mh-pod-top{display:flex;gap:var(--mhd-sp-4);align-items:center;margin-bottom:var(--mhd-sp-4)}
.mh-pod-art{
  flex:0 0 72px;width:72px;height:72px;border-radius:var(--mhd-r-md);
  overflow:hidden;background:var(--mhd-ink-100);
  display:flex;align-items:center;justify-content:center;color:var(--mhd-ink-450);
}
.mh-pod-art img{width:100%;height:100%;object-fit:cover}
.mh-pod-txt{min-width:0;flex:1 1 auto}
.mh-pod-txt .mh-pod-kicker{font-size:var(--mhd-fs-xs);color:var(--mhd-primary);font-weight:var(--mhd-fw-bold)}
.mh-pod-txt h2{margin:var(--mhd-sp-1) 0 0;font-size:var(--mhd-fs-md);font-weight:var(--mhd-fw-bold)}
.mh-pod-fallback{
  background:var(--mhd-warning-tint);color:var(--mhd-warning);
  border-radius:var(--mhd-r-md);padding:var(--mhd-sp-4);
  font-size:var(--mhd-fs-sm);margin:0;
}

/* ---------- 19. Contrast repairs the audit listed (C12) ---------------- */
body.mh-public .mh-comment-date,
body.mh-public .mh-author-sum-hint{color:var(--mhd-ink-450)!important}
body.mh-public .mh-author-link{color:var(--mhd-primary)!important}
/* white-on-white watermark */
body.mh-public .mh-cover-watermark{
  color:#fff!important;
  text-shadow:0 1px 3px rgba(0,0,0,.75);
  background:rgba(20,22,25,.42);
  padding:var(--mhd-sp-1) var(--mhd-sp-3);border-radius:var(--mhd-r-sm);
  backdrop-filter:blur(2px);
}
/* share row: 10 identical pink circles before any content */
body.mh-public .mh-share-row{
  display:flex;flex-wrap:wrap;gap:var(--mhd-sp-2);align-items:center;
  margin:var(--mhd-sp-5) 0;
}
body.mh-public .mh-share-btn{
  width:var(--mhd-tap);height:var(--mhd-tap);
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:var(--mhd-r-full);
  background:var(--mhd-ink-100)!important;color:var(--mhd-ink-500)!important;
  border:1px solid var(--mhd-border);
  font-size:var(--mhd-fs-sm);text-decoration:none!important;
}
body.mh-public .mh-share-btn:hover{
  background:var(--mhd-primary)!important;color:#fff!important;border-color:var(--mhd-primary);
}
/* the two orphan orange accent bars were left-borders of invisible widgets */
body.mh-public .box.shear-link,body.mh-public .box.about{border:0!important}

/* ---------- 20. 404 / empty states ------------------------------------- */
.mh-state{
  max-width:620px;margin:0 auto;padding:var(--mhd-sp-20) var(--mhd-sp-4);
  text-align:center;
}
.mh-state-icon{
  width:88px;height:88px;margin:0 auto var(--mhd-sp-6);
  border-radius:var(--mhd-r-full);background:var(--mhd-primary-tint);
  display:flex;align-items:center;justify-content:center;
  color:var(--mhd-primary);font-size:var(--mhd-fs-3xl);
}
.mh-state h1{font-size:var(--mhd-fs-3xl);margin-bottom:var(--mhd-sp-3)}
.mh-state-code{
  font-size:var(--mhd-fs-sm);font-weight:var(--mhd-fw-bold);
  color:var(--mhd-ink-450);letter-spacing:.14em;margin-bottom:var(--mhd-sp-2);
}
.mh-state p{color:var(--mhd-ink-500);font-size:var(--mhd-fs-md);margin-bottom:var(--mhd-sp-8)}
.mh-state-search{display:flex;gap:var(--mhd-sp-2);max-width:420px;margin:0 auto var(--mhd-sp-8)}
.mh-state-search input{
  flex:1;min-height:var(--mhd-tap);border:1px solid var(--mhd-border-strong);
  border-radius:var(--mhd-r-md);padding:0 var(--mhd-sp-4);
  font-family:var(--mhd-font);font-size:var(--mhd-fs-base);
  background:var(--mhd-surface);color:var(--mhd-ink-900);
}
.mh-state-links{display:flex;flex-wrap:wrap;gap:var(--mhd-sp-2);justify-content:center}
.mh-empty{
  text-align:center;padding:var(--mhd-sp-12) var(--mhd-sp-4);
  color:var(--mhd-ink-450);background:var(--mhd-surface);
  border:1px dashed var(--mhd-border-strong);border-radius:var(--mhd-r-md);
}
.mh-empty i{font-size:var(--mhd-fs-2xl);display:block;margin-bottom:var(--mhd-sp-3);opacity:.6}

/* ---------- 21. Legacy-markup repairs ---------------------------------- */
/* C5 — the duplicate language switcher.
   Measured cause: media pages rendered TWO controls. (1) their own
   `partials.visitor-language-switcher` in a position:fixed box that floated
   over the content, and (2) the CMS header's `select.lang-input`, which on a
   media page has ZERO <option>s (the CMS header's $languages variable is not
   provided by the MediaHub controllers) and therefore painted as a bare maroon
   chevron peeking out from under (1).
   Fix: the real switcher now lives inside .mh-nav (no fixed overlay), and the
   CMS header's utility row is suppressed on media pages — it only ever carried
   that broken select plus a login link the nav already provides. */
body.mh-public .hdr3-utility{display:none!important}
body.mh-public select.lang-input:not(:has(option)){display:none!important}
/* the nav-hosted switcher inherits the design system instead of bootstrap */
.mh-nav .visitor-lang-switcher select{
  min-height:var(--mhd-tap);border:1px solid var(--mhd-border);
  border-radius:var(--mhd-r-sm);background:var(--mhd-surface);
  color:var(--mhd-ink-700);font-family:var(--mhd-font);font-size:var(--mhd-fs-sm);
  padding:0 var(--mhd-sp-2);max-width:150px;
}
/* the shared partial carries an inline `style="display:inline-block"`, so the
   mobile sizing below needs !important to win against it */
@media (max-width:767.98px){
  .mh-nav .visitor-lang-switcher select{max-width:84px!important;padding:0 var(--mhd-sp-1);font-size:var(--mhd-fs-xs)}
}
/* deliberately NOT hidden on small screens: this is the only language control
   left on the page after C5 removed the broken duplicate, and hiding it would
   strip a real feature from phones rather than fix a layout problem. */
/* C6 — the CMS brand logo 404s on some tenants; never leave a broken box */
body.mh-public .hdr3-brand-logo img[src=""]{display:none}
/* C6: the "سایر وبسایت‌های من" strip scaled 640-1024px sources to 34px */
body.mh-public .hdr3-portal-list img{width:34px;height:34px;object-fit:contain}
/* the hub/magazine cards used bootstrap defaults with unstyled link-blue titles */
body.mh-public .card{border-color:var(--mhd-border);border-radius:var(--mhd-r-md);background:var(--mhd-surface)}
body.mh-public .card-body>a:not(.btn){color:var(--mhd-ink-900);font-weight:var(--mhd-fw-bold)}
/* ---------- 22. Article/video/podcast legacy-template repairs -----------
   These three templates predate the design system and carry their own
   per-page <style> blocks that load AFTER this sheet. Each rule below is
   a measured failure from the verification pass, not a blanket override;
   the two-class specificity (body.mh-public .x) is what beats the page block. */

/* prose measure — measured 120 ch/line on article 24 (target 45–85) */
body.mh-public .mh-article-body,
body.mh-public .mh-block-content,
body.mh-public .mh-article-subtitle{
  max-width:var(--mhd-measure);
  font-size:var(--mhd-fs-md);
  line-height:var(--mhd-lh-prose);
  color:var(--mhd-ink-700);
}
body.mh-public .mh-article-subtitle{
  font-size:var(--mhd-fs-lg);line-height:1.65;
  color:var(--mhd-ink-500);font-weight:var(--mhd-fw-normal);
}
/* headline hierarchy — H1 was 26px with the lede smaller than body text */
body.mh-public .mh-article-title{
  font-size:var(--mhd-fs-3xl);font-weight:var(--mhd-fw-black);
  line-height:var(--mhd-lh-display);letter-spacing:-.01em;
  margin-bottom:var(--mhd-sp-3);max-width:20ch;
}
@media (max-width:767.98px){ body.mh-public .mh-article-title{font-size:var(--mhd-fs-2xl);max-width:none} }
body.mh-public .mh-body-heading{
  font-size:var(--mhd-fs-xl);font-weight:var(--mhd-fw-bold);
  color:var(--mhd-ink-900);margin:var(--mhd-sp-10) 0 var(--mhd-sp-4);
  max-width:var(--mhd-measure);
}
body.mh-public .mh-article-body blockquote{
  margin:var(--mhd-sp-8) 0;padding:var(--mhd-sp-1) var(--mhd-sp-6);
  border-inline-start:4px solid var(--mhd-primary);
  color:var(--mhd-ink-900);font-size:var(--mhd-fs-lg);font-weight:var(--mhd-fw-medium);
}
body.mh-public .mh-article-body code{
  background:var(--mhd-ink-100);border-radius:var(--mhd-r-sm);
  padding:2px 6px;font-size:.92em;
}

/* C12 — the exact low-contrast selectors the verification pass reported */
body.mh-public .mh-article-meta,
body.mh-public .mh-article-meta *,
body.mh-public .mh-side-menu-count,
body.mh-public .mh-comment-date,
body.mh-public .mh-author-sum-hint,
body.mh-public .mh-comment-form .mh-hint,
body.mh-public .text-muted{ color:var(--mhd-ink-500)!important }
body.mh-public .mh-btn-save,
body.mh-public .mh-comment-form button[type="submit"]{
  background:var(--mhd-primary)!important;color:var(--mhd-on-primary)!important;
  border-color:var(--mhd-primary)!important;min-height:var(--mhd-tap);
}
/* watermark needed >0.5 alpha to actually carry its own contrast */
body.mh-public .mh-cover-watermark{ background:rgba(20,22,25,.58) }

/* C13 — every remaining sub-44px control the pass named */
body.mh-public .type-tab-btn,
body.mh-public .mh-sort-select,
body.mh-public .cat-pill,
body.mh-public .mh-more-link,
body.mh-public .mh-side-menu-link,
body.mh-public .hdr3-portal-list a,
body.mh-public .mh-btn-sm,
body.mh-public .btn-sm{
  min-height:var(--mhd-tap);
  display:inline-flex;align-items:center;justify-content:center;
}
body.mh-public .hdr3-portal-list a{min-width:var(--mhd-tap)}
body.mh-public .mh-footer-list a{min-height:var(--mhd-tap)}

/* channel list thumbnails — measured aspect ratios 3.41 vs 1.65 in one group.
   PHASE 2: the channel list now renders `.mh-card`, whose `.mh-card-media`
   already pins 16/9, so the per-page overrides this used to need are gone.
   What remains is `.no-cover-icon`, still emitted by article.blade.php's
   related-media strip — keep it on the shared placeholder treatment. */
body.mh-public .no-cover-icon{
  display:flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,var(--mhd-ink-100),var(--mhd-ink-200));
  color:var(--mhd-ink-450);font-size:var(--mhd-fs-2xl);
}

/* share row sits before the reader has read anything — make it secondary */
body.mh-public .mh-share-row{opacity:.92}

/* ---------- 23. Second-pass C12/C13 repairs ----------------------------
   Everything below was found by a live probe of every <44px interactive
   element and every sub-4.5:1 text node, after the first pass — i.e. these
   are measured leftovers, not speculative additions. */

/* contrast */
body.mh-public .mh-readmeta,
body.mh-public .mh-readmeta *,
body.mh-public .mh-cardstrip-meta,
body.mh-public .mh-comment-form p,
body.mh-public .mh-comment-form .mh-check,
body.mh-public .mh-privacy-note{ color:var(--mhd-ink-500)!important }

/* touch targets */
body.mh-public .mh-side-menu-list a,
body.mh-public .mh-side-menu-sublist a,
body.mh-public .mh-mustread a,
body.mh-public .mh-linkbox-cta,
body.mh-public .mh-cardstrip-nav,
body.mh-public .mh-comment-reply-btn,
body.mh-public .mh-input,
body.mh-public .mh-comment-form input:not([type="checkbox"]):not([type="radio"]),
body.mh-public .mh-comment-form textarea{
  min-height:var(--mhd-tap);
}
body.mh-public .mh-side-menu-list a,
body.mh-public .mh-side-menu-sublist a,
body.mh-public .mh-mustread a,
body.mh-public .mh-comment-reply-btn{
  display:inline-flex;align-items:center;
}
body.mh-public .mh-cardstrip-nav{
  width:var(--mhd-tap);height:var(--mhd-tap);
  display:inline-flex;align-items:center;justify-content:center;
}
/* Plyr's own controls ship at 32px; the audit's 44px floor applies to the
   podcast player too, and 44px is in line with YouTube/Spotify web. */
body.mh-public .plyr__control{min-width:var(--mhd-tap);min-height:var(--mhd-tap)}
body.mh-public .plyr__control svg{width:18px;height:18px}
/* range inputs: the pointer target is the full track width, so only the
   height is raised — a 44px-tall scrubber would dominate the player. */
body.mh-public .plyr input[type="range"]{min-height:24px}

/* Deliberate exception: a 44px checkbox BOX looks broken. The label is the
   touch target instead, which is the standard resolution for this rule. */
body.mh-public .mh-check{
  display:flex;align-items:center;gap:var(--mhd-sp-2);
  min-height:var(--mhd-tap);cursor:pointer;
}
body.mh-public .mh-check input[type="checkbox"]{width:18px;height:18px;flex:0 0 auto}

/* third probe pass — the last height failures */
body.mh-public .mh-comment-reply-btn{min-width:64px;justify-content:center}
.mh-footer-logo{min-height:var(--mhd-tap);align-items:center}
.mh-footer-bar a{display:inline-flex;align-items:center;min-height:var(--mhd-tap)}
.mh-footer-list a{padding-inline:var(--mhd-sp-2);margin-inline-start:calc(var(--mhd-sp-2) * -1)}
/* Remaining sub-44 elements are width-only and intentional: a short text
   link ("مجله") is as wide as its text, and the Plyr scrubber's target is
   its full track. Both satisfy the spirit of the 44px rule on the axis that
   matters for a thumb. */

/* scroll-to-top */
.mh-totop{
  position:fixed;inset-block-end:var(--mhd-sp-5);inset-inline-end:var(--mhd-sp-5);
  z-index:1040;width:var(--mhd-tap);height:var(--mhd-tap);
  display:none;align-items:center;justify-content:center;
  border:1px solid var(--mhd-border);border-radius:var(--mhd-r-full);
  background:var(--mhd-surface);color:var(--mhd-ink-700);
  box-shadow:var(--mhd-sh-2);cursor:pointer;
}
.mh-totop.is-on{display:flex}
.mh-totop:hover{background:var(--mhd-ink-100)}

/* ---------- 24. PHASE 2 design-pass leftovers (2026-10-04) --------------
   Every rule here is a value measured live after the Phase 0/1 pass, not a
   speculative addition. The measurement script is visual-tests/_p2-diag2.js
   (off-scale font sizes, sub-4.5:1 text, overflow) and _p2-compare.js
   (baseline-vs-now deltas per page/viewport). */

/* --- 24a. type scale: the last off-scale sizes ------------------------
   After retokenising media-single-public.css the only off-scale sizes left
   on a media page came from the CMS header partial, which MediaHub renders
   but does not own: 17px brand title and 11.5px tagline. Snapped to the
   scale rather than left as the two odd values out. */
body.mh-public .hdr3-brand-title{font-size:var(--mhd-fs-md)}
body.mh-public .hdr3-brand-tagline{font-size:var(--mhd-fs-xs)}
/* article.blade.php's own <style> block still sets these three; they are the
   inline-link-box and the excerpt, measured at 16.8 / 14.7 / 14.4 / 15px. */
body.mh-public .mh-ilb-title{font-size:var(--mhd-fs-md)}
body.mh-public .mh-ilb-desc{font-size:var(--mhd-fs-sm)}
body.mh-public .mh-ilb-btn{font-size:var(--mhd-fs-sm)}
body.mh-public .mh-excerpt{font-size:var(--mhd-fs-base)}
body.mh-public .mh-side-menu-count,
body.mh-public .mh-cardstrip-badge,
body.mh-public .mh-cardstrip-name,
body.mh-public .mh-cardstrip-meta{font-size:var(--mhd-fs-xs)}
/* the last 13px holdouts, traced by printing each off-scale element's
   ancestor chain. Both are declared in the per-page <style> blocks, which
   load after this sheet, so the two-class scope is what wins -- not an
   !important. */
body.mh-public .mh-side-menu-list a,
body.mh-public .mh-side-menu-list a span,
body.mh-public .mh-side-menu-sublist a,
body.mh-public .mh-btn-save{font-size:var(--mhd-fs-sm)}
/* Plyr draws its own tooltip/time/badge at 13px. It exposes these as custom
   properties, so the scale can be handed to it rather than overridden. */
body.mh-public .plyr{
  --plyr-font-size-base:var(--mhd-fs-sm);
  --plyr-font-size-small:var(--mhd-fs-xs);
  --plyr-font-size-large:var(--mhd-fs-md);
  --plyr-font-size-time:var(--mhd-fs-xs);
  --plyr-font-size-badge:var(--mhd-fs-xs);
  --plyr-font-size-menu:var(--mhd-fs-sm);
}
body.mh-public .plyr__tooltip,
body.mh-public .plyr__time{font-size:var(--mhd-fs-xs)}

/* --- 24b. Plyr's buffer bar: a DELIBERATE contrast exception ----------
   The audit reports `progress.plyr__progress__buffer` at ~1.6:1 and wants
   4.5:1, because its heuristic reads the element's textContent ("% بافرشده").
   Measured what that element actually is before acting on it:
       tag=PROGRESS  box=274x6  appearance=none  aria-hidden="true"
       painted text rectangles: NONE
   So the string is a <progress> element's legacy fallback content, which no
   current browser paints, and the element is explicitly aria-hidden, so it
   is not exposed to assistive tech either. WCAG 1.4.3 (4.5:1 for TEXT) does
   not apply — there is no text. The rule that does apply is 1.4.11 (3:1 for
   non-text UI components).

   It is left light ON PURPOSE rather than darkened to 3:1. The buffer sits
   UNDERNEATH the played-progress fill, and audio buffers almost instantly,
   so a 3:1 grey would paint nearly the whole scrubber dark and read as
   "already played" — i.e. satisfying the number here would actively
   mislead. Kept on --mhd-ink-300 so it is at least a system token and not
   Plyr's own 60%-alpha grey, which is what it was before.
   This is the same class of reasoned exception as the 18px checkbox box and
   inline prose links in §23/§24d, not an oversight. */
body.mh-public .plyr--full-ui input[type=range]::-webkit-slider-runnable-track,
body.mh-public .plyr__progress__buffer{color:var(--mhd-ink-300)}
body.mh-public .plyr{--plyr-audio-progress-buffered-background:var(--mhd-ink-300)}

/* --- 24c. the `ویژه` / featured pill on a card ------------------------
   `.mh-card-type` sits on the image, so its contrast depends on the photo.
   The 78% ink-900 scrim it already had measures >=4.5:1 against white text
   over any cover we serve; this only pins the token so a future palette
   change cannot silently break it. */
.mh-card-type{background:rgba(20,22,25,.78)}

/* --- 24d. touch targets: the standalone controls still under 44px -----
   Measured at 390px. Deliberately NOT included: inline links inside prose
   (a 44px-tall inline link breaks the line box and is not what the rule is
   for) and the 18px checkbox BOX (its label is the target — see §23). */
body.mh-public .mh-more-link,
body.mh-public .mh-ilb-btn,
body.mh-public .mh-author-link,
body.mh-public .hdr3-brand,
body.mh-public .mh-channel-switch select,
body.mh-public .mh-sort-select{
  min-height:var(--mhd-tap);
  display:inline-flex;align-items:center;
}

/* --- 24e. podcast player at 390px: the 44px rule overflowed the row ---
   Measured, by bisecting scrollWidth on /fa/media-podcast/8 at 390px:
   the page scrolled sideways by exactly 17px, and hiding ANY ONE of the
   44px Plyr buttons collapsed scrollWidth back to 390. Cause: §23 raised
   `.plyr__control` to the 44px touch minimum, but Plyr's audio control row
   is a single nowrap flex line — play + rewind + forward + time + volume +
   speed at 44px each no longer fit, so the row pushed the document wide.
   The same squeeze had collapsed `.plyr__progress__container` to 3px, i.e.
   the scrubber was effectively unusable on a phone.

   Fix: let the row wrap below 576px and give the scrubber its own full-width
   line above the buttons — which is what every mobile podcast player does
   (Spotify, Pocket Casts, Apple Podcasts all put the scrubber on its own
   row). Touch targets stay at 44px; nothing is shrunk back below the floor.

   Done with wrap + a real flex-basis rather than a width breakpoint, so the
   scrubber drops to its own line exactly when the buttons stop fitting and
   not at an arbitrary px value. Two things this must NOT do, both of which
   a first attempt got wrong and the measurement caught:
     * `.plyr__controls>*{min-width:0}` also matched the buttons and shrank
       them to 32px wide — straight back under the 44px floor;
     * a flat `min-width` on the scrubber left it at 97px on a 768px tablet,
       where the row still fits on one line and it should be flexing. */
body.mh-public .plyr--audio .plyr__controls{
  flex-wrap:wrap;
  row-gap:var(--mhd-sp-2);
}
/* grows to fill the line, but carries a basis big enough that it wraps to a
   row of its own instead of being squeezed into a sliver. The floor is
   deliberately NOT applied at phone widths: there the scrubber already owns a
   full row, and a 180px floor there instead pushed the document to 514px. */
body.mh-public .plyr--audio .plyr__progress__container{flex:1 1 220px}
@media (min-width:576px){
  body.mh-public .plyr--audio .plyr__progress__container{min-width:180px}
}
/* buttons keep the §23 touch floor on BOTH axes, and never shrink */
body.mh-public .plyr--audio .plyr__control{
  flex:0 0 auto;min-width:var(--mhd-tap);min-height:var(--mhd-tap);
}
@media (max-width:575.98px){
  /* on a phone the scrubber reads better above the transport, as in
     Spotify / Pocket Casts / Apple Podcasts */
  body.mh-public .plyr--audio .plyr__progress__container{order:-1;flex:1 0 100%;min-width:0}
  body.mh-public .plyr--audio .plyr__controls{justify-content:center}
}

/* --- 24g. touch targets: the GENUINE misses, after classifying them ---
   The leftover sub-44px elements were nearly all unclassed <a>, and the easy
   assumption was "inline links inside prose -- documented exception". That
   assumption was WRONG, and a probe that printed each element's ancestor
   chain (_p2-targets.js / the chain dump) is what showed it. The biggest
   group was the CARD TITLE link on every list page: a primary navigation
   target at 27px tall. Listing each with what it measured:

     140x27 / 326x27   a inside h3.mh-card-title   hub, magazine, channel
     310x42 + 52x42    .hdr3-search-input / -btn   every page (2px short)
     44x18 / 18x18     a inside ol.mh-crumbs       breadcrumbs
     59x29 / 48x29     a inside details.mh-toc     table of contents
     79x20             a inside .mh-article-meta   author link

   The card-title fix is a min-height rather than a stretched-link overlay
   covering the whole card. A stretched `::after` would be the better pointer
   UX, but these cards carry the real-view overlay's data-mh-block-* hooks
   and an absolutely-positioned layer over them risks swallowing the
   overlay's own clicks -- not worth the regression risk for a card whose
   image is already a large second target. */
body.mh-public .mh-card-title a{
  /* keeps display:-webkit-box from §7 so the line clamp still works */
  min-height:var(--mhd-tap);
}
body.mh-public .hdr3-search-input,
body.mh-public .hdr3-search-btn{min-height:var(--mhd-tap)}
body.mh-public .mh-crumbs a,
body.mh-public .mh-crumbs [aria-current]{
  display:inline-flex;align-items:center;
  min-height:var(--mhd-tap);
}
body.mh-public .mh-toc a,
body.mh-public .mh-article-meta a{
  display:inline-flex;align-items:center;
  min-height:var(--mhd-tap);
}

/* --- 24i. two utility classes, to retire the last INLINE styles -------
   article.blade.php and media-single.blade.php carried
       <p style="font-size:12px;color:#889">   (the comment-form privacy note)
       <p style="font-size:13px;color:#556">   (author bio / link-box desc)
   Inline styles beat every stylesheet short of !important, which is why the
   privacy note kept measuring 3.28:1 even after the sheets were retokenised:
   #889 on the canvas. They are also the last off-scale sizes on the article,
   video and podcast pages (12px/13px). Replaced in the markup by these. */
body.mh-public .mh-note{
  font-size:var(--mhd-fs-xs);color:var(--mhd-ink-500);margin:0;
}
body.mh-public .mh-bio{
  font-size:var(--mhd-fs-sm);color:var(--mhd-ink-500);margin:0;line-height:1.7;
}
body.mh-public .mh-privacy-note{font-size:var(--mhd-fs-xs)}

/* --- 24j. one card, three pages --------------------------------------
   `.mh-card` is now the only card component on hub / magazine / channel.
   This guard keeps the bootstrap `.card-body` padding from leaking into it
   if a legacy template ever nests one inside the other. */
body.mh-public .mh-card .card-body{padding:var(--mhd-sp-4)}
