/*!
 * dleaps-theme.css — D'leaps site theme overrides
 * -----------------------------------------------------------------------------
 * Loaded AFTER the compiled Tailwind bundle, so it wins on specificity-equal
 * declarations without touching a hashed build artefact. Nothing here depends
 * on a Tailwind utility class, so a `craco build` can never purge it.
 *
 * r18 — page background goes from mint (#eff6f2) to white. The turquoise grid
 * stays exactly as it was; it is now the only texture carrying the page, so it
 * is nudged up slightly to keep the same optical weight it had on mint.
 *
 * Everything downstream of --paper follows automatically:
 *   --background  -> --paper      (body)
 *   --muted       -> --paper-2    (chips, badges, quiet sections)
 *   --secondary   -> --paper-2
 *   .dot-grid-subtle background-color -> --paper
 *
 * v1.0.0 — 2026-08-07
 */

:root {
  /* ---- the page itself ------------------------------------------------- */
  --paper: 0 0% 100%;              /* was 152 26% 95% — mint */

  /* Quiet surfaces keep a whisper of cool tint so muted chips, badges and
     alternating bands still separate from a pure-white page instead of
     dissolving into it. Neutral-cool, never mint. */
  --paper-2: 200 24% 96.5%;        /* was 152 20% 91% */

  /* ---- grid ------------------------------------------------------------ */
  /* On mint the dots sat on a tinted field; on white they need a touch more
     presence to read at the same strength. Same hues, same geometry. */
  --grid-dot: hsl(var(--brand-turquoise) / 0.30);
  --grid-dot-2: hsl(var(--brand-turquoise-deep) / 0.14);

  /* ---- hairlines and lift ---------------------------------------------- */
  /* White cards on a white page can no longer rely on fill contrast, so the
     hairline does the separating and the drop shadow does the lifting. */
  --line: 210 16% 88%;
  --line-strong: 210 16% 80%;
  --shadow-sm: 0 1px 0 hsl(var(--line-strong) / 0.55), 0 8px 24px hsl(210 24% 12% / 0.05);
  --shadow-md: 0 1px 0 hsl(var(--line-strong) / 0.6), 0 18px 46px hsl(210 24% 12% / 0.08);
}

/* --------------------------------------------------------------------------
 * Grid on white
 * ------------------------------------------------------------------------ */
/* The compiled `.dot-grid` rule ships a hardcoded fallback pair for browsers
   without custom properties; every browser we support resolves the var form,
   so the tokens above are enough. These two rules only restate the ruled-line
   weights, which are baked into the gradient stops rather than into a token. */

.dot-grid {
  background-image:
    repeating-linear-gradient(to bottom, transparent 0, transparent 35px,
      hsl(var(--brand-turquoise-deep) / 0.10) 35px, hsl(var(--brand-turquoise-deep) / 0.10) 36px),
    repeating-linear-gradient(to right, transparent 0, transparent 107px,
      hsl(var(--brand-turquoise-deep) / 0.07) 107px, hsl(var(--brand-turquoise-deep) / 0.07) 108px),
    radial-gradient(var(--grid-dot) 1px, transparent 1px),
    radial-gradient(var(--grid-dot-2) 1px, transparent 1px);
  background-position: 0 0, 0 0, 0 0, 9px 9px;
  background-size: auto, auto, 18px 18px, 72px 72px;
}

.dot-grid-subtle {
  background-color: hsl(var(--paper));
  background-image:
    repeating-linear-gradient(to bottom, transparent 0, transparent 35px,
      hsl(var(--brand-turquoise-deep) / 0.075) 35px, hsl(var(--brand-turquoise-deep) / 0.075) 36px),
    radial-gradient(hsl(var(--brand-turquoise) / 0.16) 1px, transparent 1px);
  background-size: auto, 20px 20px;
}

/* --------------------------------------------------------------------------
 * Repairs for elements that were relying on the mint field for contrast
 * ------------------------------------------------------------------------ */

/* Body: belt-and-braces against the compiled hardcoded fallback. */
body { background-color: hsl(var(--paper)); }

/* The sticky header used to sit on mint and separate by colour alone. On white
   it needs a real hairline once the page has scrolled under it. */
header.sticky,
header[class*="sticky"],
#dl-chrome {
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
}

/* Quiet/alternating sections: any band that was painted with the muted token
   now reads as a faint cool wash rather than mint. Nothing to do — the token
   swap covers it — but pin the border so band edges stay visible. */
.bg-muted, .bg-secondary { border-color: hsl(var(--line)); }

/* --------------------------------------------------------------------------
 * Widget namespaces that hardcoded the mint value
 * ------------------------------------------------------------------------ */
/* dleaps-project.js and dleaps-polish.js each bake `hsl(152 26% 95%)` into a
   hero fade-out gradient. The shipped widget files in this release are patched
   at source; these rules are the safety net if an older cached copy is served
   from the edge before the purge lands. */
:root {
  --dlp-paper: hsl(0 0% 100%);
  --dl-paper: hsl(0 0% 100%);
}

/* --------------------------------------------------------------------------
 * Print
 * ------------------------------------------------------------------------ */
@media print {
  .dot-grid, .dot-grid-subtle { background-image: none !important; }
}

/* ==========================================================================
 * r19 — Magazine article: white reading sheet, floating rails, prose system
 *
 * All of this is static CSS on purpose. r19 first shipped it inside
 * dleaps-article.js, and when the two-line seo.php wiring was missed the
 * widget never loaded and none of it applied. Anything that does not need
 * JavaScript now lives here, in the one stylesheet that is loaded directly
 * from index.html and therefore reaches every route.
 *
 * dleaps-article.js still handles what genuinely needs scripting: building
 * the full-bleed hero, the Instagram profile card, and wrapping tables in a
 * scroller. Everything below works with or without it.
 * ====================================================================== */

/* --------------------------------------------------------------------------
 * Floating rails
 *
 * React lays the article out as a three-track grid with `items-start`, which
 * collapses every track to its own content height — so the aside holding the
 * share rail was only as tall as the rail itself and `position:sticky` had
 * nowhere to travel. It stuck for ~200px and then left with the column.
 *
 * Matching on the arbitrary-value class avoids needing a JS-applied hook.
 * ------------------------------------------------------------------------ */
@media (min-width: 1024px) {
  /* Matched on the article grid's exact track definition. A looser
     `[class*="lg:grid-cols-["]` also caught the portfolio grid, whose aside
     already sticks correctly at top-24 — this would have nudged it to 6.5rem
     for no reason.
     ---------------------------------------------------------------------
     React ships three tracks: 1fr | 720px | 1fr. Inside `.container-wide`
     (80vw, max 1600px) that gave the article only 720 of 1600 — 45% — while
     a 408px track sat on the left holding nothing but a 56px share rail.
     Two tracks now: content takes everything the sidebar does not. */
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] {
    grid-template-columns: minmax(0, 1fr) 320px;
    /* 20px of visible gutter, plus the 2.5rem the white reading sheet extends
       past the article box. With a plain 20px gap the sheet ran 40px into the
       sidebar's track, and because the aside paints later it landed on top of
       the content. */
    column-gap: calc(20px + 2.5rem);
    align-items: stretch;
  }
  /* The left rail leaves the flow entirely and floats against the viewport
     edge, the way /projects/{slug} does it. The aside stays in the DOM at
     zero size so React never sees its subtree move — `display:none` here
     would take the fixed rail down with it. */
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > aside.dla-rail-l {
    grid-area: 1 / 1 / 2 / 2;
    width: 0;
    height: 0;
    overflow: visible;
  }
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > article {
    grid-area: 1 / 1 / 2 / 2;
  }
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > aside.dla-rail-r {
    grid-area: 1 / 2 / 2 / 3;
    height: 100%;
  }
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > aside.dla-rail-r > div {
    position: sticky;
    top: 6.5rem;
    width: 320px;
  }
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > aside.dla-rail-l > div {
    position: fixed;
    left: clamp(0.6rem, 2.2vw, 2.4rem);
    top: 50%;
    z-index: 44;
    /* Held back until the hero has scrolled past — sharing an article you have
       not started reading is not a thing anyone does, and on the photo it just
       competed with the headline. Same behaviour as #dlp-share. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-50%) translateX(-140%);
    transition: opacity 0.35s ease, transform 0.45s cubic-bezier(0.22, 1, 0.36, 1),
      visibility 0s linear 0.35s;
  }
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > aside.dla-rail-l.on > div {
    opacity: 1;
    visibility: visible;
    transform: translateY(-50%) translateX(0);
    transition-delay: 0s;
  }
}
@media (min-width: 1024px) and (prefers-reduced-motion: reduce) {
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > aside.dla-rail-l > div,
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > aside.dla-rail-l.on > div {
    transition: none;
    transform: translateY(-50%);
  }

  /* Fallback: if the widget never loads, the asides carry no `dla-rail-*`
     class. Keep the old sticky behaviour rather than a broken layout. */
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > aside:not([class*="dla-rail"]) {
    height: 100%;
  }
  main div[class*="lg:grid-cols-[1fr_minmax(0,720px)_1fr]"] > aside:not([class*="dla-rail"]) > div {
    position: sticky;
    top: 6.5rem;
  }
}

/* --------------------------------------------------------------------------
 * The reading sheet
 *
 * Article copy sits on white; the turquoise grid frames it rather than
 * running underneath it. Drawn as a pseudo-element with negative insets so
 * the text measure is unchanged — padding the article itself would have
 * narrowed the column.
 * ------------------------------------------------------------------------ */
/* `<article>` is also used for founder cards, team members and process steps.
   The Magazine article is the one that contains `.prose-d`, so the sheet is
   applied by the widget adding `.dl-sheet` rather than by element name. */
main article.dl-sheet {
  position: relative;
  isolation: isolate;
}
main article.dl-sheet::before {
  content: "";
  position: absolute;
  inset: -2.75rem -2.5rem;
  background: hsl(var(--paper));
  border-radius: 1.5rem;
  box-shadow: 0 1px 0 hsl(var(--line-strong) / 0.4), 0 24px 60px -40px hsl(210 24% 12% / 0.28);
  z-index: 0;
}
main article.dl-sheet > * {
  position: relative;
  z-index: 1;
}
@media (max-width: 1023px) {
  main article.dl-sheet::before {
    inset: -1.5rem -1.25rem;
    border-radius: 1.1rem;
  }
}

/* --------------------------------------------------------------------------
 * Prose
 *
 * What existed before this: rules for h2, p, ul, ol and strong. Tables had
 * no styling at all — a table in an article rendered as bare browser default.
 * ------------------------------------------------------------------------ */

.prose-d {
  color: hsl(var(--ink-2));
  font-size: 1.06rem;
  line-height: 1.78;
}
.prose-d > p:first-of-type {
  font-size: 1.2rem;
  line-height: 1.68;
  color: hsl(var(--ink));
}

/* ---- headings ---- */
.prose-d h2 {
  font-family: "Poiret One", ui-sans-serif, system-ui, sans-serif;
  font-weight: 400;
  font-size: clamp(1.65rem, 3vw, 2.15rem);
  line-height: 1.16;
  letter-spacing: -0.005em;
  color: hsl(var(--ink));
  margin: 3rem 0 1rem;
  padding-left: 0.95rem;
  position: relative;
  scroll-margin-top: 6.5rem;
}
.prose-d h2::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.18em;
  bottom: 0.18em;
  width: 3px;
  border-radius: 999px;
  background: linear-gradient(to bottom, hsl(var(--brand-turquoise)), hsl(var(--brand-magenta)));
}
.prose-d h3 {
  font-size: 1.28rem;
  font-weight: 800;
  line-height: 1.32;
  letter-spacing: -0.005em;
  color: hsl(var(--ink));
  margin: 2.2rem 0 0.7rem;
  scroll-margin-top: 6.5rem;
}
.prose-d h4 {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: hsl(var(--brand-turquoise-deep));
  margin: 1.9rem 0 0.55rem;
}
.prose-d h2 + p,
.prose-d h3 + p,
.prose-d h4 + p { margin-top: 0; }

/* ---- body ---- */
.prose-d p {
  margin: 0 0 1.3rem;
  color: hsl(var(--ink-2));
  font-size: inherit;
  line-height: inherit;
}
.prose-d strong, .prose-d b { color: hsl(var(--ink)); font-weight: 700; }
.prose-d em { font-style: italic; }
.prose-d a {
  color: hsl(var(--brand-turquoise-deep));
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: hsl(var(--brand-turquoise) / 0.7);
  transition: color 0.15s, text-decoration-color 0.15s;
}
.prose-d a:hover {
  color: hsl(var(--brand-magenta));
  text-decoration-color: hsl(var(--brand-magenta));
}
.prose-d mark {
  background: hsl(var(--brand-turquoise) / 0.28);
  color: hsl(var(--ink));
  padding: 0.06em 0.22em;
  border-radius: 0.2em;
}
.prose-d small { font-size: 0.86rem; color: hsl(var(--muted-tone)); }

/* ---- lists ---- */
.prose-d ul, .prose-d ol {
  margin: 0 0 1.35rem;
  padding-left: 0;
  color: hsl(var(--ink-2));
}
.prose-d ul { list-style: none; }
.prose-d ul li {
  position: relative;
  padding-left: 1.6rem;
  margin: 0.5rem 0;
}
.prose-d ul li::before {
  content: "";
  position: absolute;
  left: 0.15rem;
  top: 0.62em;
  width: 7px;
  height: 7px;
  border-radius: 999px;
  border: 1.5px solid hsl(var(--brand-magenta) / 0.75);
  background: transparent;
}
.prose-d ol {
  list-style: none;
  counter-reset: dl-ol;
}
.prose-d ol > li {
  position: relative;
  padding-left: 2.3rem;
  margin: 0.7rem 0;
  counter-increment: dl-ol;
}
.prose-d ol > li::before {
  content: counter(dl-ol);
  position: absolute;
  left: 0;
  top: 0.06em;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 999px;
  display: grid;
  place-items: center;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.72rem;
  font-weight: 600;
  color: hsl(var(--brand-turquoise-deep));
  background: hsl(var(--brand-turquoise) / 0.16);
}
.prose-d li > ul, .prose-d li > ol { margin: 0.45rem 0 0.2rem; }
.prose-d li > p { margin: 0 0 0.5rem; }
.prose-d li > p:last-child { margin-bottom: 0; }

/* ---- blockquote ---- */
.prose-d blockquote {
  margin: 2rem 0;
  padding: 0.2rem 0 0.2rem 1.6rem;
  position: relative;
  border-left: 2px solid hsl(var(--brand-magenta) / 0.35);
}
.prose-d blockquote::before {
  content: "\201C";
  position: absolute;
  left: 0.55rem;
  top: -0.55rem;
  font-family: "Poiret One", ui-sans-serif, system-ui, sans-serif;
  font-size: 3.4rem;
  line-height: 1;
  color: hsl(var(--brand-magenta) / 0.26);
  pointer-events: none;
}
.prose-d blockquote p {
  font-family: "Poiret One", ui-sans-serif, system-ui, sans-serif;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  line-height: 1.4;
  color: hsl(var(--ink));
  margin: 0 0 0.5rem;
}
.prose-d blockquote p:last-child { margin-bottom: 0; }
.prose-d blockquote cite,
.prose-d blockquote footer {
  display: block;
  margin-top: 0.7rem;
  font-style: normal;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: hsl(var(--muted-tone));
}

/* ---- tables ---- */
.prose-d .dl-tw {
  margin: 1.9rem 0;
  border: 1px solid hsl(var(--line));
  border-radius: 0.95rem;
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.prose-d .dl-tw > .sc {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
/* Also style a bare table, so an article reads correctly before the widget
   has wrapped it — or if the widget never loads at all. */
.prose-d table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.93rem;
  background: hsl(var(--paper));
  margin: 1.9rem 0;
  border: 1px solid hsl(var(--line));
  border-radius: 0.95rem;
  overflow: hidden;
}
.prose-d .dl-tw table {
  margin: 0;
  border: 0;
  border-radius: 0;
  min-width: 30rem;
}
.prose-d thead th {
  background: hsl(var(--brand-turquoise) / 0.12);
  color: hsl(var(--brand-turquoise-deep));
  text-align: left;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 0.85rem 1rem;
  white-space: nowrap;
  border-bottom: 1px solid hsl(var(--brand-turquoise) / 0.3);
}
.prose-d tbody td,
.prose-d tbody th {
  padding: 0.85rem 1rem;
  border-bottom: 1px solid hsl(var(--line));
  vertical-align: top;
  color: hsl(var(--ink-2));
}
.prose-d tbody th {
  text-align: left;
  font-weight: 700;
  color: hsl(var(--ink));
  white-space: nowrap;
}
.prose-d tbody tr:last-child td,
.prose-d tbody tr:last-child th { border-bottom: 0; }
.prose-d tbody tr:nth-child(2n) { background: hsl(var(--paper-2) / 0.6); }
.prose-d tbody tr:hover { background: hsl(var(--brand-turquoise) / 0.05); }
.prose-d table caption {
  caption-side: bottom;
  padding: 0.7rem 1rem;
  font-size: 0.78rem;
  color: hsl(var(--muted-tone));
  text-align: left;
  border-top: 1px solid hsl(var(--line));
}
.prose-d .dl-scroll-hint {
  display: none;
  padding: 0.5rem 1rem;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: hsl(var(--muted-tone));
  border-top: 1px solid hsl(var(--line));
  background: hsl(var(--paper-2));
}
@media (max-width: 700px) {
  .prose-d .dl-tw.scrolls .dl-scroll-hint { display: block; }
}

/* ---- figures, images ---- */
.prose-d figure { margin: 2.1rem 0; }
.prose-d img {
  max-width: 100%;
  height: auto;
  display: block;
  border-radius: 0.95rem;
  box-shadow: var(--shadow-sm);
}
.prose-d p > img { margin: 1.7rem 0; }
.prose-d figure img { margin: 0; }
.prose-d figcaption {
  margin-top: 0.7rem;
  font-size: 0.82rem;
  line-height: 1.55;
  color: hsl(var(--muted-tone));
  padding-left: 0.85rem;
  border-left: 2px solid hsl(var(--brand-turquoise) / 0.5);
}

/* ---- code ---- */
.prose-d code {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.86em;
  background: hsl(var(--paper-2));
  border: 1px solid hsl(var(--line));
  border-radius: 0.35rem;
  padding: 0.1em 0.38em;
  color: hsl(var(--brand-turquoise-deep));
}
.prose-d pre {
  margin: 1.7rem 0;
  padding: 1.1rem 1.2rem;
  border-radius: 0.95rem;
  overflow-x: auto;
  background: hsl(210 24% 12%);
  color: hsl(200 20% 92%);
  font-size: 0.86rem;
  line-height: 1.65;
}
.prose-d pre code {
  background: none;
  border: 0;
  padding: 0;
  color: inherit;
  font-size: inherit;
}
.prose-d kbd {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.78em;
  border: 1px solid hsl(var(--line-strong));
  border-bottom-width: 2px;
  border-radius: 0.35rem;
  padding: 0.12em 0.4em;
  background: hsl(var(--paper));
  color: hsl(var(--ink));
}

/* ---- rules, definition lists, callouts ---- */
.prose-d hr {
  border: 0;
  height: 1px;
  margin: 2.6rem 0;
  background: linear-gradient(to right, hsl(var(--line-strong)), hsl(var(--line)) 40%, transparent);
}
.prose-d dl { margin: 1.6rem 0; }
.prose-d dt { font-weight: 700; color: hsl(var(--ink)); margin-top: 1rem; }
.prose-d dd { margin: 0.25rem 0 0; padding-left: 1rem; border-left: 2px solid hsl(var(--line)); }
.prose-d .callout, .prose-d .note {
  margin: 1.9rem 0;
  padding: 1.15rem 1.3rem;
  border-radius: 0.95rem;
  background: hsl(var(--brand-turquoise) / 0.07);
  border: 1px solid hsl(var(--brand-turquoise) / 0.28);
  color: hsl(var(--ink-2));
}
.prose-d .callout > :last-child, .prose-d .note > :last-child { margin-bottom: 0; }

/* --------------------------------------------------------------------------
 * Measure
 *
 * The article column is now ~1,260px on a large screen. Prose set to that
 * width runs past 110 characters a line, which is genuinely hard to read, so
 * the running text is capped and the elements that benefit from width —
 * tables, images, figures, the FAQ block — break back out to fill it.
 * ------------------------------------------------------------------------ */
@media (min-width: 1024px) {
  .prose-d > p,
  .prose-d > ul,
  .prose-d > ol,
  .prose-d > h2,
  .prose-d > h3,
  .prose-d > h4,
  .prose-d > blockquote,
  .prose-d > dl {
    max-width: 58rem;
  }
  .prose-d > .dl-tw,
  .prose-d > figure,
  .prose-d > img,
  .prose-d > pre,
  .prose-d > table {
    max-width: none;
  }
}

@media (max-width: 640px) {
  .prose-d { font-size: 1.02rem; }
  .prose-d > p:first-of-type { font-size: 1.1rem; }
}

/* ==========================================================================
 * r22 — Recommended reading
 *
 * The blog cards were 16:10 thumbnails with the text stacked underneath.
 * `/projects/{slug}` uses a much stronger card: a tall 3:4 photograph with a
 * small white tile lifted over its bottom edge. Same treatment here, applied
 * entirely by restyling React's own markup — no DOM rewriting.
 *
 * React's structure:
 *   a[data-testid="blog-recommended-card"]  .sketch-card .overflow-hidden
 *     > div.relative.overflow-hidden.aspect-[16/10]   -> the photo
 *         > img
 *         > span                                       -> the tag chip
 *     > div.p-4                                        -> title + date
 * ====================================================================== */

[data-testid="blog-recommended"] {
  gap: 2rem 1.5rem;
}

a[data-testid="blog-recommended-card"] {
  /* neutralise .sketch-card so the tile can lift out of the photo */
  background: none;
  border: 0;
  box-shadow: none;
  overflow: visible;
  border-radius: 0;
  display: block;
  text-decoration: none;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
a[data-testid="blog-recommended-card"]:hover {
  transform: translateY(-6px);
}
a[data-testid="blog-recommended-card"]:focus-visible {
  outline: 2px solid hsl(var(--brand-turquoise));
  outline-offset: 6px;
  border-radius: 26px;
}

/* ---- the photograph ---- */
a[data-testid="blog-recommended-card"] > div:first-child {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: 24px;
  background: hsl(var(--brand-turquoise) / 0.08);
  box-shadow: 0 24px 60px -28px hsl(196 62% 9% / 0.55);
}
@media (min-width: 1024px) {
  a[data-testid="blog-recommended-card"] > div:first-child {
    aspect-ratio: 3 / 4;
  }
}
a[data-testid="blog-recommended-card"] > div:first-child::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(to top, hsl(196 62% 9% / 0.42), hsl(196 62% 9% / 0) 42%);
  pointer-events: none;
}
a[data-testid="blog-recommended-card"] img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 0;
  box-shadow: none;
  transition: transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
a[data-testid="blog-recommended-card"]:hover img {
  transform: scale(1.06);
}

/* ---- the category chip ---- */
a[data-testid="blog-recommended-card"] > div:first-child > span {
  top: 1rem;
  left: 1rem;
  z-index: 2;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: hsl(var(--ink));
  background: hsl(0 0% 100% / 0.94);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid hsl(0 0% 100% / 0.7);
  padding: 0.42rem 0.8rem;
  border-radius: 999px;
  box-shadow: 0 10px 26px -14px hsl(196 62% 9% / 0.6);
}

/* ---- the white tile lifted over the photo ---- */
a[data-testid="blog-recommended-card"] > div:last-child {
  position: relative;
  z-index: 2;
  margin: -2.6rem 1rem 0;
  padding: 1rem 1.2rem 1.05rem;
  background: hsl(var(--paper));
  border: 1px solid hsl(var(--line));
  border-radius: 18px;
  box-shadow: 0 18px 44px -22px hsl(196 62% 9% / 0.4);
  transition: box-shadow 0.45s ease;
}
a[data-testid="blog-recommended-card"]:hover > div:last-child {
  box-shadow: 0 26px 56px -22px hsl(196 62% 9% / 0.5);
}
a[data-testid="blog-recommended-card"] h3 {
  margin: 0;
  font-size: 1.08rem;
  font-weight: 700;
  line-height: 1.3;
  color: hsl(var(--ink));
}
a[data-testid="blog-recommended-card"] > div:last-child p {
  margin: 0.4rem 0 0;
  padding: 0;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: hsl(var(--muted-tone));
}

@media (prefers-reduced-motion: reduce) {
  a[data-testid="blog-recommended-card"],
  a[data-testid="blog-recommended-card"]:hover,
  a[data-testid="blog-recommended-card"]:hover img {
    transform: none;
  }
}
