/* blog.pickheart.com — long-form reading.
   ==========================================================================
   Palette and form come from tokens.css, which is COPIED from the resume site
   rather than from the portal. That matters: the portal's light theme is a dark
   page with paper cards, which is right for a grid of dashboard tiles and wrong
   here, where there are no cards and the text sits directly on the page. The
   resume's copy is the one that was softened for reading -- 87% ground
   luminance instead of 96.6%, body text at 13:1 rather than a glaring 17:1.

   Everything below is about one thing: making a few thousand words comfortable
   to read. That means a wider type size than a dashboard, a measure that stops
   the eye travelling too far before it wraps, and generous space between
   paragraphs. */

/* MEASURE. ~68 characters. Shorter and the eye jumps lines too often; much
   longer and it loses the start of the next one on the way back. This is the
   single most important number on the page. */
:root { --measure: 34rem; --page: 46rem; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--font);
  /* Bigger than the apps. 15px is right for a table of numbers you scan;
     prose you actually read wants more. */
  font-size: 17px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }

/* ---------------------------------------------------------------- chrome */

header.site {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  max-width: var(--page); margin: 0 auto; padding: 22px clamp(18px, 5vw, 28px);
}
.wordmark {
  font-size: 15px; font-weight: 700; letter-spacing: -.01em;
  color: var(--text); text-decoration: none;
}
.wordmark b { color: var(--accent); font-weight: inherit; }
header.site nav { display: flex; align-items: center; gap: 16px; }
header.site nav a {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  font-weight: 600; color: var(--muted); text-decoration: none;
}
header.site nav a:hover { color: var(--accent); }

/* Both icons ship; CSS shows whichever matches the current theme, so the
   button always pictures the state you are IN rather than the one you would
   move to. */
.icon {
  display: grid; place-items: center; width: 30px; height: 30px; padding: 0;
  color: var(--muted); background: none; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.icon:hover { color: var(--accent); border-color: var(--accent); }
.i-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .i-sun { display: none; }
  :root:not([data-theme="light"]) .i-moon { display: block; }
}
:root[data-theme="dark"] .i-sun { display: none; }
:root[data-theme="dark"] .i-moon { display: block; }
:root[data-theme="light"] .i-sun { display: block; }
:root[data-theme="light"] .i-moon { display: none; }

footer.site {
  max-width: var(--page); margin: 60px auto 0;
  padding: 20px clamp(18px, 5vw, 28px) 48px;
  border-top: 1px solid var(--border);
  font-size: 12.5px; color: var(--muted);
}
footer.site a { color: var(--muted); }
footer.site a:hover { color: var(--accent); }

/* ------------------------------------------------------------------ home */

main.home, main.post {
  max-width: var(--page); margin: 0 auto;
  padding: 8px clamp(18px, 5vw, 28px) 0;
}
.intro { margin-bottom: 40px; max-width: var(--measure); }
.intro h1 { font-size: clamp(28px, 5vw, 36px); line-height: 1.15; margin: 0 0 10px; letter-spacing: -.02em; }
.intro p { color: var(--muted); margin: 0; }

.posts { list-style: none; margin: 0; padding: 0; }
.posts li { border-top: 1px solid var(--border); }
.posts li:last-child { border-bottom: 1px solid var(--border); }
.posts a {
  display: block; padding: 22px 0; color: inherit; text-decoration: none;
}
.posts a:hover h2 { color: var(--accent); }
.posts time, .readtime {
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  font-weight: 600; color: var(--muted);
}
.posts h2 {
  font-size: 21px; line-height: 1.3; letter-spacing: -.01em;
  margin: 6px 0; max-width: var(--measure);
}
.posts p { margin: 0 0 8px; color: var(--muted); max-width: var(--measure); font-size: 15.5px; }
.empty { color: var(--muted); padding: 40px 0; }

/* ------------------------------------------------------------------ post */

.post-head { margin: 8px 0 34px; }
.post-head h1 {
  font-size: clamp(28px, 5.5vw, 40px); line-height: 1.12;
  letter-spacing: -.025em; margin: 0 0 12px; max-width: var(--measure);
}
.post-head .meta {
  margin: 0; font-size: 11.5px; text-transform: uppercase;
  letter-spacing: .07em; font-weight: 600; color: var(--muted);
}
.tag {
  display: inline-block; padding: 2px 8px; margin-left: 5px;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--chip); text-transform: none; letter-spacing: .02em;
}
.draft-note {
  padding: 10px 14px; margin: 0 0 18px;
  border: 1px dashed var(--border); border-radius: var(--radius-sm);
  background: var(--chip); color: var(--muted);
  font-size: 13px; text-transform: none; letter-spacing: 0;
}

/* THE READING COLUMN. Everything the Markdown produces is constrained to the
   measure; the few things that benefit from more room -- code, tables,
   images -- are allowed to break out below. */
.post article > * { max-width: var(--measure); }
.post article > h2,
.post article > h3 { letter-spacing: -.015em; line-height: 1.25; }
.post article > h2 { font-size: 25px; margin: 44px 0 12px; }
.post article > h3 { font-size: 19px; margin: 32px 0 8px; }
.post article > p { margin: 0 0 20px; }
.post article > ul,
.post article > ol { margin: 0 0 20px; padding-left: 22px; }
.post article li { margin-bottom: 7px; }
.post article > hr {
  border: 0; border-top: 1px solid var(--border); margin: 40px 0;
}
/* EMBEDDED VIDEO.
   ------------------------------------------------------------------------
   A YouTube iframe ships with fixed width and height attributes, which on a
   phone means a video wider than the screen and a page that scrolls sideways.
   aspect-ratio holds the shape while the width does what it likes.

   Given the full page rather than the reading measure, for the same reason
   code blocks are: a video squeezed into 68 characters is a video nobody can
   see. The caption underneath goes back to the measure, because it is prose.

   loading="lazy" on the iframe matters more here than for an image -- an
   unplayed YouTube embed still pulls a few hundred KB of player before anyone
   decides to watch it. */
.post article > .video {
  max-width: 100%;
  margin: 0 0 10px;
  aspect-ratio: 16 / 9;
  background: var(--chip);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.post article > .video iframe {
  display: block; width: 100%; height: 100%; border: 0;
}
.post article > .video-caption {
  margin: 0 0 22px;
  font-size: 13.5px; line-height: 1.5; color: var(--muted);
}

/* DEFINITION LISTS, laid out term-left / meaning-right.
   ------------------------------------------------------------------------
   Markdown's `Term` / `:   meaning` gives real <dl><dt><dd>, which browsers
   render stacked and indented by default -- correct markup, wrong shape for a
   list of things being defined. A grid puts the term in its own column so the
   eye can run down the labels without reading the prose beside them.

   The term column is a range rather than a fixed width: it will not shrink
   below 7rem (so "Experience" cannot wrap to two lines) and will not grow past
   11rem (so one long term cannot squeeze the meanings into a gutter).

   It collapses to stacked below 40rem. Two columns inside a phone-width
   reading measure leaves about twelve characters per line, which is worse than
   no columns at all. */
.post article > dl {
  display: grid;
  grid-template-columns: minmax(7rem, 11rem) 1fr;
  gap: 12px 22px;
  margin: 0 0 22px;
}
.post article > dl dt { font-weight: 650; }
.post article > dl dd { margin: 0; }
@media (max-width: 40rem) {
  .post article > dl { grid-template-columns: 1fr; gap: 2px; }
  .post article > dl dd { margin-bottom: 14px; }
  .post article > dl dd:last-child { margin-bottom: 0; }
}

.post article > blockquote {
  margin: 0 0 20px; padding: 2px 0 2px 18px;
  border-left: 2px solid var(--accent); color: var(--muted);
}
.post article > blockquote p:last-child { margin-bottom: 0; }
.post article img { max-width: 100%; height: auto; border-radius: var(--radius-sm); }

/* Wide things get the full page, not the measure -- a code block wrapped to
   68 characters is a code block nobody can read. */
.post article > .code,
.post article > pre,
.post article > .table-wrap { max-width: 100%; }

/* Tables scroll inside their own box rather than pushing the page sideways. */
.post article table {
  width: 100%; border-collapse: collapse; margin: 0 0 20px; font-size: 15px;
}
.post article th, .post article td {
  text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--border);
}
.post article th {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted);
}

.postnav {
  display: flex; gap: 14px; flex-wrap: wrap;
  margin: 56px 0 0; padding-top: 22px; border-top: 1px solid var(--border);
}
.postnav a {
  flex: 1 1 240px; padding: 14px 16px; text-decoration: none; color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius);
  font-size: 15px; line-height: 1.35;
}
.postnav a:hover { border-color: var(--accent); }
.postnav span {
  display: block; margin-bottom: 4px;
  font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  font-weight: 700; color: var(--muted);
}
.postnav .next { text-align: right; }

/* ------------------------------------------------------------------ code */

code, pre, .code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-variant-ligatures: none;
}
/* Inline code. Not a box with a border -- at this size that draws more
   attention to the container than to the word inside it. */
:not(pre) > code {
  font-size: .88em; padding: 2px 5px; border-radius: 4px;
  background: var(--chip); color: var(--text);
}
.code, pre {
  margin: 0 0 22px; padding: 14px 16px; overflow-x: auto;
  background: var(--chip); border: 1px solid var(--border);
  border-radius: var(--radius); font-size: 13.5px; line-height: 1.55;
}
.code pre { margin: 0; padding: 0; border: 0; background: none; }

/* SYNTAX COLOURS ARE DERIVED, NOT DECLARED.
   ------------------------------------------------------------------------
   Pygments ships themes as fixed hex values, which would mean carrying two of
   them here -- one per mode -- and keeping both in sync with a palette that
   already knows how to switch. tokens.css redefines --accent, --pos, --neg and
   --muted per theme, so mapping the token classes onto those means the code
   follows the theme for free and inherits contrast that was already measured.

   The mapping is the conventional one: comments recede, strings are warm,
   keywords carry the accent, numbers and literals stand slightly apart. */
.code .c, .code .c1, .code .cm, .code .cs { color: var(--muted); font-style: italic; }
.code .k, .code .kn, .code .kd, .code .kc, .code .ow { color: var(--accent); font-weight: 600; }
.code .s, .code .s1, .code .s2, .code .sb, .code .sd, .code .se { color: var(--pos); }
.code .m, .code .mi, .code .mf, .code .il { color: var(--neg); }
.code .nf, .code .fm { color: var(--text); font-weight: 600; }
.code .nb, .code .bp { color: var(--accent); }
.code .nc, .code .nn { color: var(--text); font-weight: 600; }
.code .o, .code .p { color: var(--muted); }
.code .err { color: var(--neg); }

/* ---------------------------------------------------------------- motion */

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
