/* ============================================================================
   Handrip Book — Unified Specialty Coffee & Journal Stylesheet
   ========================================================================== */

:root {
  --reference-w: 480;
  --reference-h: 848;
  --card-w: min(81.7vw, 980px, calc(26svh * 16 / 9));
  --card-h: calc(var(--card-w) * 9 / 16);
  --edge: clamp(14px, 8.96vw, 76px);
  --transition-ms: 800ms;
  --motion-ease: cubic-bezier(0.77, 0, 0.175, 1);
  --kiwi-page: #c4c07d;
  --berry-page: #faa8a2;
  --mango-page: #fad278;
  --blueberry-page: #cfb0d5;
  --kiwi-card: #827330;
  --berry-card: #f8372d;
  --mango-card: #ec9a00;
  --blueberry-card: #8d4a9c;
  --ink: 20 20 20;
  --display-font: "Fredoka", system-ui, sans-serif;
  --ui-font: "Poppins", sans-serif;
  --shell-shadow: rgb(57 32 24 / 22%);
}

*, *::before, *::after { box-sizing: border-box; }
html, body { min-height: 100%; }
html { -webkit-text-size-adjust: 100%; }

body {
  min-height: 100svh;
  margin: 0;
  overflow-x: hidden;
  background-color: #f0e8dd;
  color: #2a1d14;
  font-family: var(--ui-font);
  -webkit-font-smoothing: antialiased;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* ------------------------------------------------------------- Unified Loading Screen */
/* The Journal's entry loader. Byte-for-byte the same screen the Beans page
   builds inline, down to the pour-over: crossing between the two sections
   should not look like crossing between two sites.

   It sits UNDER the site header (z-index 15 against the header's 20) for the
   same reason Beans does — the header is already painted and already correct,
   so covering it up only to redraw the wordmark underneath was two logos on
   one screen half a second apart. */
.j-loader {
  position: fixed; inset: 0; z-index: 15;
  --fill: 0%;
  display: grid;
  place-items: center;
  overflow: hidden;
  color: #2a1d14;
  text-align: center;
  padding: clamp(20px, 5vh, 48px) 24px;
  background: #f0e8dd url("/assets/background/bg_1.webp") center / cover no-repeat;
  /* Opacity and transform only. A blur across a full-screen sheet looks
     lovely and re-rasterises every frame of it on the phone this runs on. */
  transition: opacity .6s ease, transform .6s cubic-bezier(.4,0,.2,1);
}
.j-loader--out {
  opacity: 0;
  pointer-events: none;
  transform: scale(1.02);
}
.j-loader--out .boot-card { transform: translateY(-14px) scale(1.03); }

/* The weave of the sheet, then light on its middle and shade at its edges —
   which is what makes the brewer the first thing found on a page that has no
   hierarchy of its own yet. */
.j-loader::before {
  content: "";
  position: absolute; inset: 0;
  background-image:
    linear-gradient(90deg, rgba(122,95,42,.04) 1px, transparent 1px),
    linear-gradient(0deg, rgba(122,95,42,.032) 1px, transparent 1px);
  background-size: 9px 9px;
  opacity: .55;
}
.j-loader::after {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(56% 44% at 50% 40%, rgba(255,253,247,.72), rgba(255,253,247,0) 72%),
    radial-gradient(128% 96% at 50% 50%, rgba(42,29,20,0) 44%, rgba(42,29,20,.14) 100%);
}

.boot-botanical,
.boot-corner {
  position: absolute;
  pointer-events: none;
}
.boot-botanical {
  right: -40px; top: -34px;
  width: min(30vw, 400px);
  opacity: .26;
  color: #bda06e;
}
.boot-corner {
  left: -46px; bottom: -44px;
  width: min(27vw, 360px);
  min-width: 200px;
  opacity: .3;
  filter: drop-shadow(0 24px 40px rgba(112,84,40,.16));
}

.boot-card {
  position: relative;
  z-index: 2;
  display: grid;
  justify-items: center;
  gap: clamp(20px, 3.2vh, 36px);
  width: min(640px, calc(100vw - 44px));
  transition: transform .6s cubic-bezier(.4,0,.2,1);
}

/* ---- the brewer ----
   Not decoration: the carafe fills from the same --fill the meter reads, so
   the one thing moving on this screen is also the one thing reporting
   progress. */
.boot-stage {
  position: relative;
  display: grid;
  place-items: center;
  width: clamp(132px, 21vh, 196px);
  aspect-ratio: 1;
}
.boot-halo {
  position: absolute; inset: -28%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 44%, rgba(184,153,103,.26), rgba(184,153,103,0) 66%);
  animation: boot-halo 5.2s ease-in-out infinite;
}
.boot-ring {
  position: absolute; inset: -4%;
  border-radius: 50%;
  border: 1px dashed rgba(122,95,42,.2);
  animation: boot-spin 30s linear infinite;
}
.boot-ring::after {
  content: "";
  position: absolute; inset: 8%;
  border-radius: 50%;
  border: 1px solid rgba(122,95,42,.09);
}
.boot-brewer {
  position: relative;
  width: 74%;
  overflow: visible;
  color: #7a5f2a;
  filter: drop-shadow(0 14px 26px rgba(112,84,40,.14));
}
.bw-line {
  fill: none; stroke: currentColor;
  stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
}
.bw-hair {
  fill: none; stroke: currentColor;
  stroke-width: 1.3; stroke-linecap: round;
  opacity: .4;
}
.bw-bed { fill: rgba(110,80,34,.26); }
.bw-shine {
  fill: none; stroke: #fffdf8;
  stroke-width: 3.4; stroke-linecap: round;
  opacity: .5;
}
/* `fill-box` makes the percentage resolve against the rect's own height, so
   translateY(100%) parks it below the carafe and 0% fills it. --fill inherits
   from the overlay, which is where the counter writes it. */
.bw-liquid {
  fill: url(#bwBrew);
  transform-box: fill-box;
  transform: translateY(calc(100% - var(--fill, 0%)));
  transition: transform .6s cubic-bezier(.22,.61,.28,1);
}
.bw-drop {
  fill: currentColor;
  transform-box: fill-box;
  animation: boot-drop 1.6s cubic-bezier(.5,.02,.78,.3) infinite;
}
.bw-wisp {
  fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: boot-wisp 3.6s ease-in-out infinite;
}
.bw-wisp:nth-child(2) { animation-delay: .75s; }
.bw-wisp:nth-child(3) { animation-delay: 1.5s; }

/* ---- the words ---- */
.boot-copy {
  display: grid;
  justify-items: center;
  gap: clamp(10px, 1.4vh, 16px);
}
.boot-copy h2 {
  margin: 0;
  font-family: "Noto Serif", Georgia, "Times New Roman", serif;
  font-size: clamp(30px, 4vw, 46px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -.015em;
  color: #2a1d14;
}
.boot-copy h2 em {
  color: #7a5f2a;
  font-style: italic;
  font-weight: 600;
}
.j-loader p {
  margin: 0;
  max-width: 46ch;
  color: #4a3b30;
  font-size: clamp(13px, 1.05vw, 15px);
  font-weight: 400;
  line-height: 1.62;
  letter-spacing: .01em;
}

/* ---- the meter ----
   A hairline and a small tabular number. The percentage is a reassurance, not
   the headline — the carafe above already says the same thing in the language
   of the page. Label left, count right, rule above both: hanging the number
   off the end of a centred bar pulled the group off the page's centre line. */
.boot-meter {
  display: grid;
  gap: 12px;
  width: min(420px, 76vw);
  margin-top: clamp(4px, 1vh, 10px);
}
.boot-meter__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}
.boot-progress {
  position: relative;
  height: 3px;
  border-radius: 999px;
  background: rgba(122,95,42,.15);
  overflow: hidden;
}
.boot-progress::before {
  content: "";
  position: absolute; inset: 0 auto 0 0;
  width: var(--fill, 0%);
  border-radius: inherit;
  background: linear-gradient(90deg, #c0a271, #7a5f2a);
  transition: width .6s cubic-bezier(.22,.61,.28,1);
}
/* A slow pass of light along the track, so a stall at 99% still reads as
   working rather than stuck. */
.boot-progress::after {
  content: "";
  position: absolute; inset: 0;
  width: 42%;
  background: linear-gradient(90deg, transparent, rgba(255,253,247,.75), transparent);
  transform: translateX(-130%);
  animation: boot-sheen 2.6s cubic-bezier(.4,0,.3,1) infinite;
}
.boot-percent {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .1em;
  color: #6b4f1f;
  font-variant-numeric: tabular-nums;
  transition: color .4s ease;
}
.boot-percent.is-done { color: #2a1d14; }
.boot-label {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .4em;
  text-transform: uppercase;
  color: rgba(107,88,74,.62);
}

/* ---- arriving ---- */
.boot-stage,
.boot-copy > * {
  animation: boot-rise .95s cubic-bezier(.22,.61,.28,1) both;
}
.boot-stage { animation-delay: .05s; }
.boot-copy h2 { animation-delay: .18s; }
.boot-copy p { animation-delay: .28s; }
.boot-meter { animation-delay: .38s; }

@keyframes boot-rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
@keyframes boot-spin {
  to { transform: rotate(360deg); }
}
@keyframes boot-halo {
  0%,100% { opacity: .75; transform: scale(.97); }
  50%     { opacity: 1;   transform: scale(1.04); }
}
@keyframes boot-drop {
  0%       { opacity: 0; transform: translateY(0) scaleY(.7); }
  12%      { opacity: 1; transform: translateY(4px) scaleY(1); }
  72%      { opacity: 1; transform: translateY(46px) scaleY(1.5); }
  86%,100% { opacity: 0; transform: translateY(54px) scaleY(.6); }
}
@keyframes boot-wisp {
  0%   { opacity: 0;   transform: translateY(6px) scaleY(.62); }
  28%  { opacity: .45; }
  62%  { opacity: .28; }
  100% { opacity: 0;   transform: translateY(-15px) scaleY(1.18); }
}
@keyframes boot-sheen {
  0%       { transform: translateX(-130%); }
  62%,100% { transform: translateX(330%); }
}

@media (max-width: 720px) {
  .boot-botanical { width: 250px; right: -92px; opacity: .2; }
  .boot-corner { width: 240px; left: -78px; opacity: .26; }
  .boot-stage { width: clamp(112px, 19vh, 158px); }
  .boot-copy h2 { font-size: clamp(26px, 7.6vw, 38px); }
  .boot-label { letter-spacing: .26em; font-size: 9px; }
}
@media (prefers-reduced-motion: reduce) {
  .boot-stage,
  .boot-copy > *,
  .boot-halo,
  .boot-ring,
  .bw-drop,
  .bw-wisp,
  .boot-progress::after { animation: none; }
  .bw-wisp { opacity: .3; }
  .j-loader--out,
  .j-loader--out .boot-card { transform: none; }
}



/* ------------------------------------------------------------- Site header */

/* The header used to be redefined here, as a near-copy of the one the Beans
   page carried inline — and the copies had drifted, which is what made the bar
   jump when you crossed between the two sections. It now lives in
   /site-header.css, which both documents load; see the note at the top of that
   file. Nothing about the bar belongs in this stylesheet any more. */

/* ============================================================================
   THE JOURNAL — listing

   Rebuilt to be the same publication as the front of the site. It used to be a
   two-column magazine mock: a sticky "JOURNAL INDEX" rail, a zig-zag mosaic,
   floating bean and botanical decorations, and an ambient colour-shift script.
   Three problems with that, in order of weight.

   1. Most of what it showed was invented. Category counts were computed as
      `total / n` when the database had none, the issue tag read ISSUE 01 / 2026,
      the sub-navigation offered four sections that all linked back to /blog, and
      a "BREW NOTE #07" card carried a quote nobody wrote.
   2. The decorations were drawn for a near-black ground. On the botanical sheet
      the site now prints on, translucent brown beans over a printed leaf is two
      textures fighting for the same space.
   3. It was a different design system from the coffee pages one nav link away —
      different card, different type scale, different gold.

   What replaced it is a centred editorial column on the same paper, using the
   same card stock, serif and gold gradient as the shelf. Everything on it comes
   from the database or is not shown.
   ========================================================================== */
body.blog-shell {
  --cream-card: #f7efe2;
  --cream-text: #2a1d14;
  --espresso-dark: #2a1d14;
  --espresso-mid: #4a3b30;
  --espresso-soft: #6b584a;
  --gold-deep: #7a5f2a;
  --gold-ink: #6b4f1f;
  --rule: #e8e0cf;
  --amber-accent: #d97736;
  --serif-font: "Noto Serif", Georgia, serif;
  --ease-slide: cubic-bezier(.22,.61,.28,1);

  /* The same botanical sheet the hero is printed on. Fixed, so a long index
     scrolls over one continuous sheet rather than tiling a new one per screen. */
  background: #f0e8dd url("/assets/background/bg_1.webp") center / cover no-repeat fixed;
  color: var(--espresso-dark);
  font-family: 'Poppins', sans-serif;
  min-height: 100vh;
  position: relative;
  overflow-x: hidden;
}

/* Card stock, shared with the coffee cards on the shelf so a reader crossing
   between the two halves of the site stays on one surface. */
.journal-lead,
.journal-card,
.article-toc-card,
.article-main-card,
.widget-card {
  background: linear-gradient(180deg, #fffdf8, #fbf6ec);
  border: 1px solid rgba(122, 95, 42, .16);
  box-shadow:
    0 1px 2px rgba(90, 66, 30, .1),
    0 10px 24px -8px rgba(90, 66, 30, .16),
    0 34px 70px -20px rgba(90, 66, 30, .24),
    inset 0 1px 0 #fff;
  color: var(--espresso-dark);
}

.journal {
  position: relative;
  z-index: 1;
  width: min(1180px, 100%);
  margin: 0 auto;
  padding: clamp(18px, 3vh, 40px) clamp(20px, 4.2vw, 74px)
           calc(clamp(56px, 9vh, 104px) + env(safe-area-inset-bottom, 0px));
}

/* ---------------------------------------------------------------- masthead */
.journal-head {
  text-align: center;
  max-width: 760px;
  margin: 0 auto clamp(26px, 4vh, 48px);
}

.journal-kicker {
  margin: 0 0 clamp(10px, 1.4vh, 18px);
  font-size: clamp(9px, .66vw, 11px);
  font-weight: 600;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--gold-deep);
}

/* The four golds of the hero wordmark, on the same axis. drop-shadow and not
   text-shadow: with the fill transparent a text-shadow paints on top of the
   element's own background and hides the gradient underneath it. */
.journal-title {
  margin: 0;
  font-family: var(--serif-font);
  font-weight: 800;
  font-size: clamp(38px, 6.2vw, 84px);
  line-height: .96;
  letter-spacing: -.035em;
  color: #b89967;
  background: linear-gradient(176deg, #c2a874 0%, #b89967 34%, #c0aa84 68%, #ae8f5b 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter:
    drop-shadow(0 -1px 0 rgba(255, 253, 247, .92))
    drop-shadow(0 2px 3px rgba(112, 84, 40, .4));
}

.journal-sub {
  margin: clamp(12px, 1.8vh, 20px) auto 0;
  max-width: 48ch;
  font-size: clamp(13px, .92vw, 16px);
  line-height: 1.65;
  color: var(--espresso-mid);
}

.journal-rule {
  display: block;
  width: clamp(54px, 6vw, 86px);
  height: 1px;
  margin: clamp(16px, 2.4vh, 26px) auto 0;
  background: linear-gradient(90deg, transparent, rgba(122, 95, 42, .5), transparent);
}

/* ------------------------------------------------------- category filters */
.journal-filters {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 0 0 clamp(26px, 4vh, 46px);
}

.journal-filter {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 20px;
  border-radius: 999px;
  border: 1px solid rgba(122, 95, 42, .22);
  background: rgba(255, 252, 244, .55);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--espresso-mid);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background .24s ease, color .24s ease, border-color .24s ease;
}

.journal-filter .count {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--espresso-soft);
}

.journal-filter:hover {
  background: rgba(255, 252, 244, .92);
  color: var(--espresso-dark);
}

.journal-filter.is-active {
  background: var(--espresso-dark);
  border-color: var(--espresso-dark);
  color: #f6efe2;
}

.journal-filter.is-active .count { color: rgba(246, 239, 226, .7); }

/* -------------------------------------------------------------- lead story */
.journal-lead {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(20px, 2.6vw, 40px);
  align-items: center;
  border-radius: 26px;
  padding: clamp(18px, 1.6vw, 26px);
  margin-bottom: clamp(20px, 2.6vw, 38px);
}

.journal-lead__img {
  display: block;
  border-radius: 18px;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--rule);
}

.journal-lead__img img,
.journal-card__img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: scale .6s var(--ease-slide);
}

.journal-lead:hover .journal-lead__img img,
.journal-card:hover .journal-card__img img { scale: 1.04; }

.journal-lead__copy { padding: clamp(4px, 1vw, 18px) clamp(4px, 1vw, 16px); }

.journal-lead__copy h2 {
  font-family: var(--serif-font);
  font-weight: 700;
  font-size: clamp(24px, 2.6vw, 38px);
  line-height: 1.14;
  letter-spacing: -.02em;
  margin: 14px 0 12px;
}

.journal-lead__copy p {
  font-size: clamp(13px, .95vw, 15.5px);
  line-height: 1.7;
  color: var(--espresso-mid);
  margin: 0 0 18px;
}

/* -------------------------------------------------------------- story grid */
.journal-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: clamp(18px, 2.1vw, 32px);
}

.journal-card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: 22px;
  padding: clamp(14px, 1.2vw, 18px);
  transform: translateY(0);
  transition: transform .34s var(--ease-slide),
              box-shadow .34s ease,
              border-color .28s ease;
}

.journal-card:hover,
.journal-lead:hover {
  transform: translateY(-6px);
  border-color: rgba(184, 153, 103, .55);
  box-shadow:
    0 1px 2px rgba(90, 66, 30, .1),
    0 16px 34px -10px rgba(90, 66, 30, .2),
    0 48px 90px -26px rgba(90, 66, 30, .3),
    inset 0 1px 0 #fff;
}

.journal-lead { transition: transform .34s var(--ease-slide), box-shadow .34s ease, border-color .28s ease; }

.journal-card__img {
  display: block;
  border-radius: 15px;
  overflow: hidden;
  aspect-ratio: 16 / 11;
  background: var(--rule);
  margin-bottom: 16px;
}

.journal-card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 0 4px 4px;
}

.journal-card__body h3 {
  font-family: var(--serif-font);
  font-weight: 700;
  font-size: clamp(17px, 1.3vw, 21px);
  line-height: 1.24;
  letter-spacing: -.015em;
  margin: 12px 0 10px;
}

.journal-card__body p {
  font-size: 13.5px;
  line-height: 1.62;
  color: var(--espresso-mid);
  margin: 0 0 16px;
}

.journal-card h3 a,
.journal-lead__copy h2 a {
  color: inherit;
  text-decoration: none;
}

/* The whole card is the target. A stretched link keeps that true without
   wrapping a heading and a paragraph inside an <a>, which would flatten the
   article's structure for anything reading the page rather than looking at it. */
.journal-card h3 a::after,
.journal-lead__copy h2 a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.journal-chip {
  display: inline-block;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid rgba(122, 95, 42, .24);
  background: rgba(240, 232, 221, .7);
  color: var(--gold-ink);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  text-decoration: none;
  position: relative;
  z-index: 1;
}

.journal-meta {
  margin-top: auto;
  padding-top: 13px;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  font-size: 11px;
  letter-spacing: .06em;
  color: var(--espresso-soft);
}

.journal-meta .dot {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: rgba(107, 88, 74, .45);
}

.journal-meta time { font-variant-numeric: tabular-nums; }

.journal-read {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gold-ink);
  text-decoration: none;
}

.journal-read::after {
  content: "→";
  font-size: 15px;
  letter-spacing: 0;
  transition: translate .3s var(--ease-slide);
}

.journal-lead:hover .journal-read::after,
.journal-card:hover .journal-read::after { translate: 5px 0; }

.journal-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 70px 0;
  color: var(--espresso-soft);
  font-style: italic;
}

/* ------------------------------------------------------------- pagination */
.blog-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: clamp(32px, 5vh, 60px);
  font-size: 13px;
  font-weight: 600;
  color: var(--espresso-soft);
}

.blog-pagination a,
.blog-pagination span:first-child,
.blog-pagination span:last-child {
  padding: 11px 20px;
  border-radius: 999px;
  border: 1px solid rgba(122, 95, 42, .22);
  background: rgba(255, 252, 244, .55);
  text-decoration: none;
  color: var(--gold-ink);
}

.blog-pagination a:hover {
  background: rgba(255, 252, 244, .95);
  color: var(--espresso-dark);
}

/* A <span> in the prev/next slots means "there is no page that way". */
.blog-pagination span:first-child,
.blog-pagination span:last-child {
  opacity: .4;
  cursor: default;
}

/* ------------------------------------------------- breadcrumb / 404 / misc */

/* The trail itself is the shared component in /site-header.css — the Beans
   page draws the same one. Only where it sits on this page belongs here. */
.journal .breadcrumb,
.blog-page .breadcrumb { margin-bottom: 18px; }

.blog-page {
  position: relative;
  z-index: 1;
  width: min(760px, 100%);
  margin: 0 auto;
  padding: clamp(40px, 10vh, 120px) clamp(20px, 4.2vw, 74px) 100px;
  text-align: center;
}

.blog-hero p {
  font-family: var(--serif-font);
  font-size: clamp(48px, 9vw, 96px);
  font-weight: 800;
  line-height: 1;
  color: rgba(122, 95, 42, .3);
  margin: 0 0 12px;
}

.blog-hero h1 {
  font-family: var(--serif-font);
  font-size: clamp(26px, 3.4vw, 40px);
  margin: 0 0 14px;
}

.blog-hero div {
  color: var(--espresso-mid);
  line-height: 1.7;
  margin-bottom: 26px;
}

.blog-button {
  display: inline-block;
  padding: 13px 26px;
  border-radius: 999px;
  background: var(--espresso-dark);
  color: #f6efe2;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}

/* ------------------------------------------------------------- responsive */
@media (max-width: 860px) {
  .journal-lead { grid-template-columns: 1fr; }
  .journal-lead__img { aspect-ratio: 16 / 10; }
}

@media (max-width: 640px) {
  .journal-grid { grid-template-columns: 1fr; gap: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .journal-card,
  .journal-lead,
  .journal-card__img img,
  .journal-lead__img img { transition: none; }
  .journal-card:hover,
  .journal-lead:hover { transform: none; }
  .journal-lead:hover .journal-lead__img img,
  .journal-card:hover .journal-card__img img { scale: 1; }
}

/* =========================================================
   SINGLE ARTICLE DETAIL VIEW (RECREATED MATCHING REFERENCE)
   ========================================================= */

.article-page-wrapper {
  min-height: 100vh;
  padding-top: clamp(80px, 9vw, 110px);
  padding-bottom: 80px;
  /* Transparent: the article sits on the sheet the body already carries. It
     used to paint its own dark ground on top of it. */
  background: transparent;
  color: var(--espresso-dark);
}

/* TOP HERO BANNER AREA */
.article-hero-area {
  max-width: 1400px;
  margin: 0 auto;
  padding: 20px clamp(24px, 4vw, 60px) 36px;
  display: grid;
  grid-template-columns: 1fr minmax(360px, 520px);
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
}

/* No cover image, no second column — otherwise the title sits in half the page
   next to an empty box. */
.article-hero-area:not(:has(.article-hero-right)) {
  grid-template-columns: 1fr;
  max-width: 900px;
}

.article-hero-left {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.article-hero-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-deep);
  margin-bottom: 14px;
}

.article-hero-meta .meta-dot {
  opacity: 0.5;
}

.article-hero-title {
  font-family: "Noto Serif", Georgia, serif;
  font-weight: 700;
  font-size: clamp(32px, 3.8vw, 54px);
  line-height: 1.15;
  color: #2a1d14;
  margin: 0 0 16px;
  letter-spacing: -0.01em;
}

.article-hero-lead {
  font-family: "Noto Serif", Georgia, serif;
  font-style: italic;
  font-size: clamp(16px, 1.35vw, 20px);
  line-height: 1.55;
  color: rgba(74, 59, 48, 0.88);
  margin: 0;
  max-width: 680px;
}

.article-cover-frame {
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: 24px;
  overflow: hidden;
  box-shadow:
    0 10px 24px -8px rgba(90, 66, 30, .18),
    0 34px 70px -20px rgba(90, 66, 30, .26);
}

.article-cover-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* 3-COLUMN EDITORIAL GRID */
.article-editorial-grid {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 clamp(24px, 4vw, 60px);
  display: grid;
  grid-template-columns: 230px 1fr 310px;
  gap: 28px;
  align-items: start;
}

/* COLUMN 1: STICKY TOC CARD */
.article-toc-card {
  position: sticky;
  top: 100px;
  border-radius: 22px;
  padding: 26px 20px;
  display: flex;
  flex-direction: column;
}

.toc-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 18px;
  color: #7a6552;
}

.toc-title {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.toc-nav {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.toc-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  text-decoration: none;
  color: #5c4838;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.35;
  transition: color 0.18s ease, transform 0.18s ease;
}

.toc-item:hover {
  color: #c4682b;
  transform: translateX(3px);
}

.toc-num {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  color: #9c826b;
  flex-shrink: 0;
  margin-top: 1px;
}

.toc-botanical-art {
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px dashed #ded3c1;
  display: grid;
  place-items: center;
  color: #9c826b;
}

.toc-botanical-art svg {
  width: 54px;
  height: 54px;
  opacity: 0.45;
}

/* COLUMN 2: MAIN ARTICLE READING CARD */
.article-main-card {
  border-radius: 26px;
  padding: clamp(26px, 3.4vw, 48px) clamp(24px, 3.8vw, 52px);
}

.article-rich-content {
  font-family: "Noto Serif", Georgia, serif;
  font-size: 16px;
  line-height: 1.85;
  color: #3d2b1f;
}

.article-rich-content > p:first-of-type::first-letter {
  font-family: "Noto Serif", Georgia, serif;
  font-size: 4.6rem;
  float: left;
  line-height: 0.78;
  margin-right: 14px;
  margin-top: 6px;
  font-weight: 700;
  color: #2a190c;
}

.article-rich-content h2 {
  font-family: "Noto Serif", Georgia, serif;
  font-weight: 700;
  font-size: clamp(22px, 2.2vw, 30px);
  color: #25160b;
  margin: 38px 0 16px;
  letter-spacing: -0.01em;
  scroll-margin-top: 110px;
}

.article-rich-content h3 {
  font-family: "Noto Serif", Georgia, serif;
  font-weight: 700;
  font-size: clamp(18px, 1.8vw, 24px);
  color: #382416;
  margin: 28px 0 12px;
  scroll-margin-top: 110px;
}

.article-rich-content p {
  margin-bottom: 22px;
}

.article-rich-content img {
  max-width: 100%;
  height: auto;
  border-radius: 18px;
  margin: 24px 0 12px;
  box-shadow: 0 12px 30px rgba(90, 66, 30, 0.08);
}

.article-rich-content blockquote {
  background: rgba(235, 224, 206, 0.55);
  border-left: 3px solid #c4682b;
  border-radius: 0 16px 16px 0;
  padding: 22px 26px;
  margin: 32px 0;
  font-style: italic;
  font-size: 18px;
  line-height: 1.6;
  color: #2e1e12;
}

.article-rich-content blockquote cite,
.article-rich-content blockquote footer {
  display: block;
  font-style: normal;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #8c725c;
  margin-top: 12px;
}

/* COLUMN 3: SIDE WIDGET CARDS */
.article-widgets-col {
  display: flex;
  flex-direction: column;
  gap: 20px;
  position: sticky;
  top: 100px;
}

.widget-card {
  border-radius: 20px;
  padding: 22px 20px;
}

.widget-label {
  display: block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #7a6552;
  margin-bottom: 14px;
}

/* Author Widget */
.author-profile {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 12px;
}

.author-avatar {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid #e2d5c1;
  flex-shrink: 0;
}

.author-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.author-name {
  font-family: "Noto Serif", Georgia, serif;
  font-weight: 700;
  font-size: 16px;
  color: #2a1b10;
  margin: 0;
}

.author-title {
  font-size: 11px;
  color: #7a6552;
}

.author-bio {
  font-size: 12.5px;
  line-height: 1.5;
  color: #5a4738;
  margin: 0 0 14px;
}

.author-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 12px;
  border-top: 1px dashed #ded3c1;
  font-size: 11px;
  color: #8c7662;
  font-weight: 500;
}

/* Tags Widget */
.tags-chips-cloud {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.tag-chip {
  padding: 5px 13px;
  border-radius: 18px;
  background: #ede4d4;
  color: #4a3625;
  font-size: 11px;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.18s ease, color 0.18s ease;
}

.tag-chip:hover {
  background: #c4682b;
  color: #ffffff;
}

/* Takeaways Widget */
.takeaways-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.takeaways-list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.takeaway-icon {
  font-size: 16px;
  flex-shrink: 0;
  line-height: 1.3;
}

.takeaways-list p {
  font-size: 12px;
  line-height: 1.45;
  color: #4a382a;
  margin: 0;
}

/* Share Widget */
.share-buttons-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.share-btn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid #ded3c1;
  background: #fdfaf4;
  color: #4a3625;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: all 0.18s ease;
}

.share-btn:hover {
  background: #4a3625;
  color: #ffffff;
  border-color: #4a3625;
}

.share-btn svg {
  width: 16px;
  height: 16px;
  display: block;
}

/* The "author" panel only renders when the post actually names one, so the
   avatar is the site mark rather than a stock portrait of nobody. */
.author-avatar {
  background: #f0e8dd;
  display: grid;
  place-items: center;
}

.author-avatar img {
  width: 62%;
  height: 62%;
  object-fit: contain;
}

/* Related Thumb Widget */
.related-thumb-item {
  display: flex;
  gap: 12px;
  align-items: center;
}

.related-thumb-item img {
  width: 64px;
  height: 64px;
  border-radius: 12px;
  object-fit: cover;
  flex-shrink: 0;
}

.related-thumb-copy h5 {
  font-family: "Noto Serif", Georgia, serif;
  font-weight: 700;
  font-size: 13.5px;
  color: #2a1b10;
  margin: 0 0 4px;
  line-height: 1.3;
}

.related-thumb-copy a {
  font-size: 11px;
  font-weight: 700;
  color: #c4682b;
  text-decoration: none;
}

/* A post with no headings gets no table of contents, so the column it would
   have occupied is not reserved for it either. */
.article-editorial-grid.no-toc {
  grid-template-columns: 1fr 310px;
}

.toc-icon svg {
  display: block;
  width: 16px;
  height: 16px;
}

.article-hero-left .breadcrumb {
  margin-bottom: 14px;
}

/* Related is a list now rather than a single pick — findRelatedPosts already
   returns three and the widget was throwing two of them away. */
.widget-related-thumb .related-thumb-item {
  display: flex;
  gap: 12px;
  align-items: center;
  text-decoration: none;
  color: inherit;
  padding: 10px 0;
  border-bottom: 1px dashed #ded3c1;
}

.widget-related-thumb .related-thumb-item:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.widget-related-thumb .related-thumb-item:first-of-type { padding-top: 0; }

.related-thumb-copy span {
  font-size: 11px;
  font-weight: 700;
  color: #c4682b;
}

.related-thumb-item:hover .related-thumb-copy h5 { color: #c4682b; }

/* Confirmation for a button whose whole job is invisible. */
.share-btn { position: relative; text-decoration: none; }

.share-btn.is-copied {
  background: #4a3625;
  color: #ffffff;
  border-color: #4a3625;
}

.share-btn.is-copied::after {
  content: "Copied";
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  translate: -50% 0;
  padding: 5px 10px;
  border-radius: 8px;
  background: #2a1d14;
  color: #f6efe2;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  white-space: nowrap;
}

/* RESPONSIVE LAYOUT */
@media (max-width: 1200px) {
  .article-editorial-grid {
    grid-template-columns: 200px 1fr;
  }
  .article-editorial-grid.no-toc { grid-template-columns: 1fr; }
  .article-widgets-col {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    position: static;
  }
}

@media (max-width: 860px) {
  .article-hero-area {
    grid-template-columns: 1fr;
  }
  .article-editorial-grid,
  .article-editorial-grid.no-toc {
    grid-template-columns: 1fr;
  }
  .article-toc-card {
    position: static;
  }
  .article-main-card {
    padding: 28px 24px;
  }
}

/* ============================================================================
   /flavours — the aroma wheel
   ==========================================================================
   The wheel itself is server-rendered SVG (see routes/web/flavours.ts), so
   everything below is type and chrome. Nothing here loads, nothing here
   animates on arrival: the page's whole argument is that a reference should be
   legible the instant it appears.
   ========================================================================== */
.fw-stage {
  margin: 0 auto clamp(30px, 5vh, 58px);
  padding: clamp(10px, 2vw, 26px);
  width: min(880px, 100%);
}

.fw-wheel {
  position: relative;
}

.fw-svg {
  display: block;
  width: 100%;
  height: auto;
  touch-action: manipulation;
  /* A tap that lands on a slice must not also paint iOS's grey selection box
     over it, or leave the label half-selected on a slightly-dragged finger. */
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
  /* The wheel is the one thing on this page that has to feel physical. */
  filter: drop-shadow(0 24px 48px rgba(90, 66, 30, .18));
}

/* ---- what the pointer is on ----
   The whole ring dims to the family under the cursor, and within it to the one
   slice. Opacity rather than colour: every one of these 105 shapes is already
   carrying meaning in its fill, and there is no second colour to move it to
   that would not read as a different flavour. */
.fw-svg [data-fi] {
  transition: opacity .16s ease;
}

.fw-svg.is-picking [data-fi] {
  opacity: .22;
}

.fw-svg.is-picking [data-fi].is-kin {
  opacity: .7;
}

.fw-svg.is-picking [data-fi].is-hot {
  opacity: 1;
}

/* Heavier than it was under hover: this outline now has to hold a selection
   the reader has walked away from, not just mark where a cursor is resting. */
.fw-svg.is-picking .fw-arc.is-hot {
  stroke: var(--espresso-dark);
  stroke-width: 3;
}

/* There is a real click here now, so the cursor may say so. `manipulation`
   drops the double-tap-to-zoom wait Safari otherwise puts in front of every
   tap, which on a wheel you are tapping repeatedly is the difference between
   responsive and sluggish. */
.fw-arc {
  cursor: pointer;
  touch-action: manipulation;
}

/* ---- the hollow middle ----
   Absolutely centred on the wheel rather than drawn into it: this text changes
   on hover and has to wrap, and SVG <text> does neither. pointer-events are
   off so the hub never eats a hover meant for the ring behind it. */
.fw-hub {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 3px;
  /* The hub circle is 2 x 162 units across a 992-unit viewBox. Slightly under
     that, so the longest coffee list still lands on paper. */
  width: 30%;
  margin: 0 auto;
  text-align: center;
  pointer-events: none;
}

.fw-hub p {
  margin: 0;
}

.fw-hub__kicker {
  font-size: clamp(8px, .72vw, 10px);
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--gold-deep);
}

.fw-hub__name {
  font-family: var(--serif-font);
  font-size: clamp(15px, 1.5vw, 22px);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.01em;
  color: var(--espresso-dark);
  overflow-wrap: anywhere;
}

.fw-hub__note {
  max-width: 22ch;
  font-size: clamp(9px, .78vw, 11.5px);
  line-height: 1.45;
  color: var(--espresso-mid);
  overflow-wrap: anywhere;
}

.fw-family {
  font-family: 'Poppins', sans-serif;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .02em;
  fill: #fffdf8;
}

.fw-leaf {
  font-family: 'Poppins', sans-serif;
  font-size: 10.5px;
  font-weight: 500;
  fill: var(--espresso-dark);
}

/* A flavour actually in the cup is the only thing on the outer ring that gets
   any weight. The rest is vocabulary — present, legible, quiet. */
.fw-leaf.is-on {
  font-weight: 700;
}

.fw-leaf.is-off {
  fill: rgba(74, 59, 48, .5);
}

.fw-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px clamp(16px, 3vw, 34px);
  margin-top: clamp(14px, 2.4vh, 24px);
  color: var(--espresso-mid);
  font-size: clamp(11.5px, .8vw, 13px);
}

.fw-legend span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.fw-legend__dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: rgba(122, 95, 42, .16);
  border: 1px solid rgba(122, 95, 42, .3);
}

.fw-legend__dot.is-on {
  background: var(--gold-deep);
  border-color: var(--gold-deep);
}

/* ---------------------------------------------------------- the word index */
.fw-index {
  margin-top: clamp(12px, 2vh, 26px);
}

.fw-index__title {
  margin: 0;
  font-family: var(--serif-font);
  font-size: clamp(22px, 2.6vw, 34px);
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--espresso-dark);
}

.fw-index__lead {
  margin: 10px 0 clamp(20px, 3vh, 32px);
  max-width: 62ch;
  font-size: clamp(13px, .92vw, 15px);
  line-height: 1.65;
  color: var(--espresso-mid);
}

.fw-index__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
  gap: clamp(12px, 1.6vw, 18px);
}

.fw-family-card {
  padding: 16px 18px 18px;
  border-radius: 16px;
  background: linear-gradient(180deg, #fffdf8, #fbf6ec);
  border: 1px solid rgba(122, 95, 42, .16);
  box-shadow:
    0 1px 2px rgba(90, 66, 30, .08),
    0 10px 24px -12px rgba(90, 66, 30, .18);
}

/* A family we are pouring something from sits a little more solidly on the
   page than one we are not. Enough to find at a glance, not enough to make
   the others look like errors. */
.fw-family-card[data-has] {
  border-color: rgba(122, 95, 42, .3);
  box-shadow:
    0 1px 2px rgba(90, 66, 30, .1),
    0 14px 30px -14px rgba(90, 66, 30, .26);
}

.fw-family-card header {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 12px;
}

.fw-swatch {
  width: 11px;
  height: 11px;
  border-radius: 3px;
  flex: none;
}

.fw-family-card h3 {
  margin: 0;
  flex: 1;
  font-family: var(--serif-font);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--espresso-dark);
}

.fw-count {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  color: var(--espresso-soft);
  white-space: nowrap;
}

.fw-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fw-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px dashed rgba(122, 95, 42, .3);
  color: rgba(74, 59, 48, .72);
  font-size: 11.5px;
  line-height: 1.5;
}

.fw-chip__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  opacity: .35;
  flex: none;
}

/* Filled in means we are pouring it. The dashed outline on the rest reads as
   "a word we know" rather than as something missing. */
.fw-chip.is-on {
  border-style: solid;
  border-color: rgba(122, 95, 42, .38);
  background: rgba(255, 252, 244, .9);
  color: var(--espresso-dark);
  font-weight: 600;
}

.fw-chip.is-on .fw-chip__dot {
  opacity: 1;
}

.fw-chip__n {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 700;
  color: var(--gold-ink);
  font-variant-numeric: tabular-nums;
}

/* Ninety-two radial labels cannot be legible on a wheel 340px across, at any
   font size — the arithmetic does not allow it. So below this they come off
   rather than being shrunk into a grey haze, the wheel becomes the colour
   diagram it can be at that width, and the index underneath carries every word
   it was carrying. The families stay: there are thirteen of them and they have
   the room. */
@media (max-width: 620px) {
  .fw-leaf { display: none; }
  .fw-family { font-size: 15px; }
  .fw-stage { padding: 0; }
  /* The wheel is a colour diagram at this width, so the hub goes back to
     being its caption rather than a read-out. */
  .fw-hub { width: 34%; }
}

@media (prefers-reduced-motion: reduce) {
  .fw-svg [data-fi] { transition: none; }
}


/* ============================================================================
   Blog: the PDF download card
   ==========================================================================
   Written into an article as ::pdf[Label](url) and rendered by the server (see
   backend/src/lib/markdown.ts). A link, not an embedded viewer: a PDF iframed
   into an article is a second scrolling surface inside a page that already
   scrolls, it is unusable on a phone, and it pulls the whole file down before
   showing page one.
   ========================================================================== */
.article-rich-content .blog-pdf,
.blog-pdf {
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.6vw, 18px);
  margin: clamp(20px, 3vh, 32px) 0;
  padding: clamp(14px, 1.8vw, 20px);
  border: 1px solid rgba(122, 95, 42, .22);
  border-radius: 14px;
  background: linear-gradient(180deg, #fffdf8, #fbf6ec);
  box-shadow:
    0 1px 2px rgba(90, 66, 30, .08),
    0 10px 24px -14px rgba(90, 66, 30, .22);
  color: var(--espresso-dark);
  text-decoration: none;
  transition: box-shadow .2s, transform .2s, border-color .2s;
}

.blog-pdf:hover {
  border-color: rgba(122, 95, 42, .4);
  transform: translateY(-1px);
  box-shadow:
    0 1px 2px rgba(90, 66, 30, .1),
    0 16px 34px -16px rgba(90, 66, 30, .3);
}

.blog-pdf__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 54px;
  border-radius: 8px;
  background: #b04e46;
  color: #fffdf8;
  font-family: 'Poppins', sans-serif;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .06em;
}

.blog-pdf__body {
  display: grid;
  gap: 3px;
  min-width: 0;
}

.blog-pdf__name {
  font-family: var(--serif-font);
  font-size: clamp(15px, 1.3vw, 19px);
  font-weight: 700;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.blog-pdf__hint {
  font-size: clamp(11.5px, .85vw, 13px);
  color: var(--espresso-soft);
}

@media (prefers-reduced-motion: reduce) {
  .blog-pdf { transition: none; }
  .blog-pdf:hover { transform: none; }
}
