/* Market theme — monochrome.
 *
 * Loaded on every public page via web_include_css. The palette lives in custom
 * properties on :root so a second market can restyle by overriding four values
 * rather than shipping a second stylesheet.
 *
 * The script face is a voice layer and nothing else: bylines, pull quotes and
 * the verdict. It is deliberately not available to headings, navigation or body
 * copy — used structurally it stops reading as a hand signing off on the work
 * and starts reading as decoration.
 */

:root {
  --mk-ink: #0A0A0A;
  --mk-paper: #FFFFFF;
  --mk-g1: #1A1A1A;
  --mk-g2: #4A4A4A;
  --mk-g3: #8A8A8A;
  --mk-g4: #C9C9C9;
  --mk-g5: #ECECEC;
  --mk-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --mk-script: "Caveat", "Segoe Script", "Bradley Hand", cursive;
  --mk-measure: 68ch;

  /* Headings default to the sans, bold and tight — the monochrome look. A market
     with a display face (a fashion serif, say) overrides these three in its own
     theme.css without touching this file. */
  --mk-display: var(--mk-sans);
  --mk-display-weight: 800;
  --mk-display-spacing: -0.02em;
}

body {
  font-family: var(--mk-sans);
  color: var(--mk-g1);
  background: var(--mk-paper);
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------- masthead */

.mk-mast {
  background: var(--mk-ink);
  padding: 26px 20px 20px;
  text-align: center;
}
.mk-mast-link { display: block; text-decoration: none; }
.mk-mast-link:hover { text-decoration: none; }
.mk-mark {
  display: block;
  width: 230px;
  max-width: 62%;
  height: auto;
  margin: 0 auto 12px;
}
.mk-word {
  display: block;
  color: #fff;
  font-weight: 800;
  font-size: 20px;
  letter-spacing: 0.3em;
  text-indent: 0.3em;      /* recentre: letter-spacing pads the right only */
  text-transform: uppercase;
}
.mk-tag {
  display: block;
  color: var(--mk-g3);
  font-size: 10px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  margin-top: 9px;
}

/* -------------------------------------------------------------------- nav */

.mk-nav { border-bottom: 4px solid var(--mk-ink); background: var(--mk-paper); }
.mk-nav-toggle {
  display: none;
  width: 100%;
  padding: 13px 20px;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--mk-g4);
  font: inherit;
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mk-g2);
}
.mk-nav-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 26px;
  list-style: none;
  margin: 0;
  padding: 13px 16px;
}
.mk-nav-list a {
  color: var(--mk-g2);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}
.mk-nav-list a:hover { color: var(--mk-ink); text-decoration: none; }

@media (max-width: 720px) {
  .mk-nav-toggle { display: block; }
  .mk-nav-list { display: none; flex-direction: column; align-items: flex-start; gap: 0; }
  .mk-nav-list.is-open { display: flex; }
  .mk-nav-list li { width: 100%; }
  .mk-nav-list a { display: block; padding: 11px 4px; }
}

/* ------------------------------------------------------------- typography */

.page_content, .blog-content, main {
  font-size: 16px;
  line-height: 1.75;
}
.page_content p, .blog-content p { max-width: var(--mk-measure); }
h1, h2, h3 { color: var(--mk-ink); font-family: var(--mk-display); font-weight: var(--mk-display-weight); letter-spacing: var(--mk-display-spacing); line-height: 1.15; }
h1 { font-size: clamp(28px, 4.4vw, 40px); }
h2 { font-size: clamp(21px, 2.6vw, 26px); margin-top: 2em; }
h3 { font-size: 18px; margin-top: 1.6em; }
a { color: var(--mk-ink); text-underline-offset: 3px; }

/* ------------------------------------------------- the voice layer, script */

.mk-byline, .mk-quote, .mk-verdict-text {
  font-family: var(--mk-script);
  font-weight: 500;
}
.mk-byline { font-size: 21px; color: var(--mk-g2); margin-bottom: 18px; }
.mk-quote {
  border-left: 3px solid var(--mk-ink);
  padding: 4px 0 4px 18px;
  margin: 28px 0;
  font-size: 25px;
  line-height: 1.5;
  color: var(--mk-ink);
  max-width: var(--mk-measure);
}
.mk-verdict {
  background: var(--mk-ink);
  padding: 22px 26px;
  margin: 32px 0;
  max-width: var(--mk-measure);
}
.mk-verdict-label {
  color: var(--mk-g3);
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.mk-verdict-text { color: #fff; font-size: 26px; line-height: 1.45; }

/* -------------------------------------------------------------- evidence */

.mk-badges { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 24px; padding: 0; list-style: none; }
.mk-badge {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 5px 10px;
  border: 1px solid var(--mk-ink);
  color: var(--mk-ink);
}
.mk-badge--solid { background: var(--mk-ink); color: #fff; }
.mk-badge--muted { border-color: var(--mk-g4); color: var(--mk-g3); }

/* The evidence badge sits in the post's date/reading-time row, so it needs to
   read as metadata rather than as a button — smaller, and given room on the
   right so the date does not collide with it. */
.mk-evidence { margin-right: 10px; vertical-align: baseline; }

.evidence-notice {
  border: 1px solid var(--mk-g4);
  border-left: 4px solid var(--mk-ink);
  padding: 14px 18px;
  margin: 0 0 26px;
  font-size: 14px;
  color: var(--mk-g2);
  max-width: var(--mk-measure);
}

/* ------------------------------------------------------------ index cards */

.mk-hero { padding: 54px 0 40px; border-bottom: 1px solid var(--mk-g4); }
.mk-hero p { font-size: 18px; color: var(--mk-g2); max-width: 58ch; }

/* Hero with a background image. The art is composed with its left third clear
 * and the objects grouped right, so the copy sits left and the image is
 * anchored right — as the viewport narrows the crop eats the empty side last.
 *
 * The scrim is the load-bearing part: a headline over an image is only legible
 * by luck, and the crop changes with every width. A left-to-right fade from the
 * page colour guarantees the copy has ground under it at any size, without
 * dimming the photograph the way a flat overlay would. */
.mk-hero--image {
  position: relative;
  background-size: cover;
  background-position: right center;
  background-repeat: no-repeat;
  border-bottom: none;
  padding: 0;
  min-height: 340px;
  display: flex;
  align-items: center;
}
.mk-hero--image::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    var(--mk-paper) 0%,
    var(--mk-paper) 26%,
    rgba(0, 0, 0, 0) 62%
  );
}
.mk-hero--image .mk-hero-copy {
  position: relative;      /* above the scrim */
  max-width: 46%;
  padding: 46px 0;
}
.mk-hero--image h1 { margin-top: 0; }

@media (max-width: 780px) {
  /* Narrow enough and there is no room for copy beside the art, so the image
     becomes a band above it rather than a backdrop fighting the text.

     `.mk-hero.mk-hero--image`, not `.mk-hero--image`, and the doubled class is
     load-bearing. A market theme sets `.mk-hero { padding-top: 64px }`, which
     is the same specificity as a single class here — a media query adds none —
     so it won on source order, the theme file being loaded after this one. The
     clearance collapsed to 64px, the headline landed 72px into a 255px-tall
     image, and the homepage shipped with the title unreadable across the art.
     Measured in the browser: the source read correctly on its own. */
  .mk-hero.mk-hero--image {
    display: block;
    min-height: 0;
    background-position: center top;
    background-size: 140% auto;

    /* Width-relative, because the thing it has to clear is width-relative too:
       the image renders at 140% of this box and its height is that over the
       aspect ratio, so 140 / 1.79 ≈ 78% of the width. A fixed pixel clearance
       is only ever correct at one viewport, which is how 200px came to be
       wrong everywhere and 64px wrong visibly. */
    padding-top: 78%;
  }

  /* The gradient stopped where the copy began only by coincidence of element
     height, which varies with how long the copy is. An opaque panel cannot
     drift: whatever the band does, the text is on paper. The gradient stays
     above it to soften the seam. */
  .mk-hero--image .mk-hero-copy {
    max-width: 100%;
    padding: 14px 0 34px;
    background: var(--mk-paper);
  }
  .mk-hero--image::before {
    background: linear-gradient(
      180deg,
      rgba(0, 0, 0, 0) 0%,
      rgba(0, 0, 0, 0) 42%,
      var(--mk-paper) 62%
    );
  }
}

.mk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 1px; background: var(--mk-g4); border: 1px solid var(--mk-g4); margin: 32px 0; }
.mk-card { background: var(--mk-paper); padding: 22px 20px; }
.mk-card a { text-decoration: none; }
.mk-card-kicker { font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--mk-g3); margin-bottom: 10px; }
.mk-card-title { font-size: 19px; font-weight: 500; color: var(--mk-ink); line-height: 1.3; }
.mk-card-sub { font-size: 14px; color: var(--mk-g2); margin-top: 8px; }

.mk-empty { border: 1px dashed var(--mk-g4); padding: 34px 26px; color: var(--mk-g2); margin: 32px 0; }

/* ------------------------------------------------------------------ ticker */
/* A strip of tracked product links above the masthead, carrying each one's
 * search-demand movement.
 *
 * The animation translates the track by exactly -50%, and the track holds two
 * identical copies of the list — so the moment the first copy has fully left,
 * the second sits precisely where the first began and the loop is seamless.
 * Any other percentage jumps.
 *
 * Motion is opt-out by the OS, not by us: an endlessly moving strip pinned to
 * the top of every page is a vestibular trigger and, for some readers, makes
 * the whole site unusable. Under prefers-reduced-motion the animation stops
 * dead and the strip becomes an ordinary horizontal scroller — the same links,
 * still reachable, just still.
 */

:root { --mk-ticker-h: 40px; }

/* The strip is out of flow, so the page reserves its height here. One variable
   drives both, because a mismatch shows up as the masthead sitting under the
   ticker and is exactly the sort of thing that survives review. */
body { padding-top: var(--mk-ticker-h); }

.mk-ticker {
  display: flex;
  align-items: center;
  gap: 16px;
  color: var(--mk-paper);
  padding: 0 0 0 16px;
  overflow: hidden;

  /* Load-bearing, and the reason this strip was invisible for two deploys.
     Frappe's own stylesheet makes body a column flex container with a fixed
     height, so everything in it is a flex item. A flex item's automatic
     minimum size normally protects it at content height — but `overflow:
     hidden`, which the marquee needs, sets that minimum to zero. The ticker
     was the only child free to shrink, and it collapsed to 1px: correct
     colours, correct contents, one pixel tall. Measured in the browser, not
     guessed; the markup had been checking out fine the whole time. */
  flex: 0 0 auto;

  /* Pinned, so it does not scroll away under the browser's own chrome the
     moment the page moves. A ticker visible only at scroll position zero is
     one most readers never see.

     `fixed`, not `sticky`, and that is not a style preference. Sticky was tried
     first and computed as sticky while not sticking at all: Frappe's own
     stylesheet gives body a fixed height as a column flex container, and a
     sticky item can only stick inside its parent's box. Body's box ends around
     370px, so the strip unpinned almost immediately and scrolled away. Measured
     by scrolling the live page and reading the rect — it looks correct in every
     source file involved.

     Taking it out of flow means body has to give the space back, hence the
     padding below. The height is fixed rather than intrinsic so those two
     numbers cannot drift apart; the contents are centred inside it. Permanently
     on screen also means it has to stay slim — big enough to read a moving
     product name, small enough not to be a toolbar.

     z-index clears the page texture layer, which sits at z-index 1 on articles. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--mk-ticker-h);
  z-index: 40;

  /* The masthead below is also --mk-ink, so a plain --mk-ink here made the two
     merge into one unbroken block and the strip effectively vanished — it was
     rendering perfectly and nobody could see it. The overlay darkens whatever
     ink the market uses rather than hardcoding a second colour, so this works
     for any palette, and the hairline gives the seam that was missing. */
  background: var(--mk-ink);
  background-image: linear-gradient(rgba(0, 0, 0, 0.26), rgba(0, 0, 0, 0.26));
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}
.mk-ticker-label {
  flex: 0 0 auto;
  margin: 0;
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mk-paper);
  opacity: 0.72;
  white-space: nowrap;
}
.mk-ticker-window { flex: 1 1 auto; overflow: hidden; }
.mk-ticker-track {
  display: flex;
  width: max-content;
  animation: mk-ticker-scroll 60s linear infinite;
}
.mk-ticker:hover .mk-ticker-track { animation-play-state: paused; }

/* Spacing here is the difference between a strip you can read at a glance and
   one you squint at. The names are product names moving at a constant speed, so
   they get a size that survives motion, room to breathe between them, and
   enough vertical padding that the band is not a slot. */
.mk-ticker-list {
  display: flex;
  align-items: center;
  gap: 32px;
  margin: 0;
  padding: 0 16px;
  list-style: none;
}
.mk-ticker-list a {
  display: inline-flex;
  align-items: baseline;
  gap: 9px;
  padding: 10px 0;
  color: var(--mk-paper);
  font-size: 13px;
  letter-spacing: 0.01em;
  white-space: nowrap;
  text-decoration: none;
}
.mk-ticker-list a:hover { color: #fff; text-decoration: underline; }
.mk-ticker-name { font-weight: 500; }
.mk-ticker-move {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--mk-g3);
}
.mk-ticker-move.is-up { color: #6FBF8B; }
.mk-ticker-move.is-down { color: #D98A8A; }

@keyframes mk-ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .mk-ticker-track { animation: none; width: auto; }
  .mk-ticker-window { overflow-x: auto; }
  /* The duplicate exists only to make the loop seamless. With no loop it is
     just the same links a second time, so it goes. */
  .mk-ticker-list[aria-hidden="true"] { display: none; }
}

/* --------------------------------------------------------- article image */
/* Cropped by height rather than scaled: these are 16:9 banners and an article
   wants a band, not a billboard that pushes the first paragraph off screen. */

.mk-article-img { margin: 0 0 26px; }
.mk-article-img img {
  display: block;
  width: 100%;
  max-height: 260px;
  object-fit: cover;
  border-radius: 2px;
}

/* ---------------------------------------------------------- category hero */
/* The band above a category listing: a wide banner image, a strapline in the
   display face, an intro in the muted grey. All optional — website.py only
   sets category_hero when the category has at least one of the three. The
   image is cropped by height, not scaled: banners render at 16:9 and the band
   should read as a masthead strip, not a full-bleed photo page. */

.mk-cat-hero { border-bottom: 1px solid var(--mk-g4); background: var(--mk-paper); }
.mk-cat-hero-img {
  display: block;
  width: 100%;
  max-height: 300px;
  object-fit: cover;
}
.mk-cat-hero-text {
  max-width: var(--mk-measure);
  margin: 0 auto;
  padding: 30px 20px 34px;
  text-align: center;
}
.mk-cat-hero-head {
  font-family: var(--mk-display);
  font-weight: var(--mk-display-weight);
  letter-spacing: var(--mk-display-spacing);
  font-size: clamp(28px, 5vw, 46px);
  line-height: 1.08;
  color: var(--mk-ink);
  margin: 0 0 10px;
}
.mk-cat-hero-intro {
  font-size: 17px;
  line-height: 1.55;
  color: var(--mk-g2);
  max-width: 58ch;
  margin: 0 auto;
}


/* ------------------------------------------------------------ author photo */
/* The founders, on the About page. Capped in width and centred rather than
 * full-bleed: this is a photograph of people, not a hero, and blowing a phone
 * selfie up to 1400px only shows the compression. */

.mk-author { margin: 30px 0 34px; text-align: center; }
.mk-author img {
  display: block;
  margin: 0 auto;
  max-width: 420px;
  width: 100%;
  height: auto;
  border-radius: 3px;
}
.mk-author figcaption {
  margin-top: 10px;
  font-size: 13px;
  color: var(--mk-g3);
}

/* The About body comes from a rich-text field, so it arrives as whatever
   markup the editor produced. These keep it on the page's own measure and
   rhythm instead of inheriting the editor's defaults. */
.mk-about { max-width: var(--mk-measure); }
.mk-about h2 { margin-top: 34px; }
.mk-about p { margin: 0 0 16px; }
.mk-about ul { margin: 0 0 18px; padding-left: 20px; }
.mk-about li { margin-bottom: 7px; }

/* -------------------------------------------------------------- subscribe */

.mk-sub { background: var(--mk-g5); padding: 32px 26px; margin: 44px 0; }
.mk-sub h2 { margin-top: 0; }
.mk-sub-form { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; max-width: 460px; }
.mk-sub-form input[type=email] {
  flex: 1 1 220px;
  padding: 12px 14px;
  border: 1px solid var(--mk-ink);
  background: var(--mk-paper);
  font: inherit;
}
.mk-sub-form button {
  padding: 12px 22px;
  background: var(--mk-ink);
  color: #fff;
  border: 1px solid var(--mk-ink);
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
}
.mk-sub-note { font-size: 12px; color: var(--mk-g2); margin-top: 12px; }
.mk-sub-msg { margin-top: 12px; font-size: 14px; }

/* ----------------------------------------------------------------- footer */

.mk-foot { background: var(--mk-ink); color: var(--mk-g3); margin-top: 64px; padding: 46px 20px 32px; }
.mk-foot-inner { max-width: 980px; margin: 0 auto; }
.mk-foot-disc {
  font-size: 13px;
  line-height: 1.75;
  max-width: 72ch;
  margin: 0 0 38px;
  padding-bottom: 30px;
  border-bottom: 1px solid #262626;
}

.mk-foot-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 32px 40px;
}
.mk-foot-col--wide { grid-column: span 2; }
/* Nine sections in a single column makes the footer taller than the page it
   sits under, so the wide column splits its own list rather than the grid. */
.mk-foot-col--wide ul { columns: 2; column-gap: 40px; }

.mk-foot-head {
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #6E6E6E;
  margin: 0 0 14px;
}
.mk-foot-col ul { list-style: none; margin: 0; padding: 0; }
.mk-foot-col li { margin-bottom: 9px; break-inside: avoid; }
.mk-foot a { color: var(--mk-g4); }
.mk-foot-col a { color: var(--mk-g4); font-size: 13px; text-decoration: none; }
.mk-foot-col a:hover { color: #fff; text-decoration: none; }

/* The copyright gets its own rule and its own row. Stacked tight under the
   links it read as one more list item. */
.mk-foot-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px 24px;
  margin-top: 44px;
  padding-top: 24px;
  border-top: 1px solid #262626;
}
.mk-foot-legal { font-size: 12px; color: #6E6E6E; margin: 0; letter-spacing: 0.04em; }
.mk-foot-contact { margin: 0; }
.mk-foot-contact a { font-size: 12px; color: #6E6E6E; text-decoration: none; letter-spacing: 0.04em; }
.mk-foot-contact a:hover { color: #fff; }

@media (max-width: 560px) {
  .mk-foot-col--wide { grid-column: auto; }
  .mk-foot-col--wide ul { columns: 1; }
}

/* ------------------------------------------------------- the post signature
 *
 * The blog app closes a post with an avatar and the blogger's name. Set in the
 * script face with a tilde it reads as a hand signing off on the work, which is
 * the one place on a review site that should feel signed rather than published.
 *
 * Scoped on body[data-path^="blog"] because .media is a generic Bootstrap class
 * and this must not reach anything else. The avatar is hidden: a single-initial
 * disc next to a signature is two ways of saying the same thing, and the weaker
 * one wins on visual weight.
 */

body[data-path^="blog"] .media > .avatar { display: none; }
body[data-path^="blog"] .media-body { margin-left: 0 !important; }
body[data-path^="blog"] .media-body h5 { margin: 0; }
body[data-path^="blog"] .media-body h5 a {
  font-family: var(--mk-script);
  font-weight: 500;
  font-size: 27px;
  letter-spacing: 0;
  color: var(--mk-g2);
  text-decoration: none;
}
body[data-path^="blog"] .media-body h5 a::before { content: "~ "; }
body[data-path^="blog"] .media-body h5 a:hover { color: var(--mk-ink); }

/* -------------------------------------------------------------- share row */

.mk-share { margin: 44px 0 8px; padding-top: 22px; border-top: 1px solid var(--mk-g4); }
.mk-share-label {
  font-size: 10px; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--mk-g3); margin: 0 0 12px;
}
.mk-share ul { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; }
.mk-share a, .mk-share-copy {
  display: inline-block;
  padding: 8px 14px;
  border: 1px solid var(--mk-ink);
  background: var(--mk-paper);
  color: var(--mk-ink);
  font: inherit;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
}
.mk-share a:hover, .mk-share-copy:hover { background: var(--mk-ink); color: #fff; text-decoration: none; }

/* ---------------------------------------------------------------- figures */

.mk-figure { margin: 34px 0; }
.mk-figure svg { display: block; width: 100%; height: auto; border: 1px solid var(--mk-g4); }
.mk-figure figcaption {
  font-size: 13px; color: var(--mk-g2); margin-top: 10px; max-width: var(--mk-measure);
}

/* ------------------------------------------------------------- blog cards
 *
 * The listing belongs to the blog app and ships Bootstrap cards: rounded,
 * shadowed, with a "default cover" panel that repeats the title above the
 * title. Squared off, stripped back, and aligned with the grid on the
 * homepage so the two do not look like different websites.
 */

#blog-list.blog-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1px; background: var(--mk-g4); border: 1px solid var(--mk-g4); margin: 32px 0; }
.blog-card { width: 100%; max-width: none; flex: none; padding: 0; }
.blog-card .card {
  height: 100%;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: var(--mk-paper);
  padding: 24px 22px;
}
/* The cover panel is the title again, in a box. One title per card is enough. */
.blog-card .card-img-top { display: none; }
.blog-card .card-body { padding: 0; display: flex; flex-direction: column; height: 100%; }
.blog-card .text-uppercase {
  font-size: 10px !important;
  letter-spacing: 0.2em;
  color: var(--mk-g3) !important;
  margin-bottom: 10px;
}
.blog-card h5 { margin: 0 0 10px; }
.blog-card h5 .text-dark {
  font-size: 20px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--mk-ink) !important;
  letter-spacing: -0.01em;
}
.blog-card .post-description {
  font-size: 14px;
  line-height: 1.65;
  color: var(--mk-g2) !important;
  margin: 0 0 20px;
}
.blog-card .blog-card-footer { margin-top: auto; display: flex; align-items: center; gap: 0; }
.blog-card .blog-card-footer .avatar { display: none; }
.blog-card .blog-card-footer a {
  font-family: var(--mk-script);
  font-size: 20px;
  color: var(--mk-g2);
  text-decoration: none;
}
.blog-card .blog-card-footer a::before { content: "~ "; }
.blog-card .blog-card-footer .small {
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--mk-g3);
  text-transform: uppercase;
}
.blog-card .card:hover { background: var(--mk-g5); }


/* The verdict stamp
 * ─────────────────
 * Rendered only when a post carries a verdict, which a researched piece never
 * does. That is deliberate: a mark on a page written from specifications alone
 * would read as an endorsement the writing has not earned, and on a page with
 * affiliate links in it that is the whole difference between a review and an
 * advert.
 *
 * Built as an inspector's stamp rather than a badge — ruled box, letterspaced
 * capitals, sat slightly off-square — because the thing it has to communicate
 * is a judgement that was made, not a rating that was calculated. It borrows
 * the market's own ink and gold, so it reads as part of the masthead rather
 * than a widget dropped on top.
 */
.mk-stamp {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  margin: 14px 0 22px;
  padding: 9px 20px 8px;
  border: 2px solid currentColor;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px currentColor;
  transform: rotate(-2.5deg);
  transform-origin: left center;
  opacity: 0.92;
}
.mk-stamp-word {
  font-family: var(--mk-display, Georgia, serif);
  font-size: 19px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.13em;
  text-transform: uppercase;
}
.mk-stamp-sub {
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.78;
}

/* Approved takes the market's accent; falls-short takes a muted red that is
   desaturated on purpose. A shouting red would make a considered negative look
   like an error state, and the negative verdict is the one that has to look
   most deliberate. */
.mk-stamp--yes { color: var(--mk-gold, #8A6A2F); }
.mk-stamp--no  { color: #A2564F; }

@media (prefers-reduced-motion: reduce) {
  .mk-stamp { transform: none; }
}

@media (max-width: 560px) {
  .mk-stamp { transform: rotate(-1.5deg); padding: 8px 15px 7px; }
  .mk-stamp-word { font-size: 16px; }
}

/* The narration player
 * ────────────────────
 * Replaces a button that called the browser's speech synthesis. That version
 * cost nothing and stored nothing, and read every article in whatever voice the
 * reader's device happened to ship with — which on most machines is a voice
 * that makes considered prose sound like a form being read back.
 *
 * The note under the control is load-bearing rather than decorative. A good
 * synthetic voice reading first-person copy invites exactly the conclusion this
 * site spends its evidence tiers refusing to invite, so it says plainly that
 * nobody recorded this.
 */
.mk-listen {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  margin: 14px 0 4px;
}
.mk-listen-label {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mk-g3);
}
.mk-listen audio {
  height: 34px;
  flex: 1 1 260px;
  min-width: 0;          /* a flex item with intrinsic width needs telling */
  max-width: 460px;
}
.mk-listen-note {
  flex: 1 1 100%;
  font-size: 12px;
  color: var(--mk-g3);
}
@media (max-width: 560px) {
  .mk-listen audio { flex-basis: 100%; max-width: none; }
}

/* ------------------------------------------------------------ buy button */
/* The one place a reader is asked to leave the page for a product.
 *
 * It used to render as bold body text with the underline suppressed, which
 * made it indistinguishable from the prose around it, and it existed only at
 * the foot of the article — so the reader who came for the product had to
 * scroll the whole argument to find a link they then could not pick out. It is
 * now a pill, it carries the product's name rather than "Check the current
 * price", and there is one at the end of the intro as well as at the end.
 *
 * Outline is the default and solid is the emphasis, the same weighting the
 * evidence badges use: the button after the intro is an early exit and should
 * not shout over the argument it introduces, while the closing one is the
 * terminal ask and has earned the fill by the time a reader reaches it.
 */
.mk-buy-row { margin: 26px 0 10px; }
.mk-buy {
  display: inline-block;
  max-width: 100%;
  padding: 12px 26px;
  border: 1px solid var(--mk-ink);
  border-radius: 999px;
  background: none;
  color: var(--mk-ink);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  text-decoration: none;
}
.mk-buy:hover { background: var(--mk-ink); color: var(--mk-paper); text-decoration: none; }
.mk-buy:focus-visible { outline: 2px solid var(--mk-ink); outline-offset: 3px; }
.mk-buy--solid { background: var(--mk-ink); color: var(--mk-paper); }
.mk-buy--solid:hover { background: none; color: var(--mk-ink); }

/* The price caveat qualifies the button, so it sits under it as a note rather
   than as another paragraph competing with it. */
.mk-buy-note {
  margin: 0 0 8px;
  max-width: var(--mk-measure);
  font-size: 13px;
  color: var(--mk-g2);
}
