/* ==========================================================================
   johnrnelson.com - 2026 redesign
   --------------------------------------------------------------------------
   One hand-written stylesheet replacing the whole Astra theme bundle
   (theme.min.css, theme-inline-*.css, blocks.css, addon.css, addon-inline-*.css,
   megamenu-inline.css).

   Most of this still styles the EXISTING WordPress-mirror markup rather than
   replacing it - Astra's and Gutenberg's class names are the hooks, not a
   dependency. The exception is the homepage, which is hand-written now that
   the blog is gone (2026-08-28).

   Palette is blue and red on light surfaces (John, 2026-08-28). The duck keeps
   its own yellow because it is a photograph; nothing in the interface is
   yellow. There is no dark theme.

   Trimmed 2026-08-28 with the blog: the archive-heading, post-card and
   pagination sections matched nothing once the 14 posts and their 34 index
   pages went, and the hero section was replaced by the home intro.
   ========================================================================== */

/* ----------------------------------------------------------------- 1. tokens */

:root {
  /* Brand: blue primary, red accent (John's call, 2026-08-28).
     There is deliberately NO yellow in this palette. The duck is yellow
     because the duck is a photograph, and that is the only yellow on the
     site - do not reintroduce it as a UI colour. */
  --accent:        #1d4ed8;
  --accent-deep:   #15379b;
  --accent-soft:   #cfdefa;
  --accent-wash:   #eef3fd;
  --accent-2:      #cf2e2e;
  --accent-2-soft: #f7d9d9;

  /* Surfaces. Every one of these is light, on purpose - there is no dark
     theme any more, so nothing here flips. */
  --paper:       #f6f8fc;
  --card:        #ffffff;
  --card-2:      #eef2f9;
  --line:        #dde3ee;
  --line-strong: #c2ccdd;

  /* text */
  --ink:         #131720;
  --ink-2:       #39414f;
  --muted:       #667287;

  /* links */
  --link:        var(--accent);
  --link-hover:  var(--accent-deep);

  /* Buttons are solid blue. They were never yellow and still are not. */
  --btn-bg:       var(--accent);
  --btn-fg:       #ffffff;
  --btn-bg-hover: var(--accent-deep);

  /* quiet hover for outline buttons: pagination, post nav, menu entries */
  --btn-surface-hover: #e6edfc;
  --btn-border-hover:  var(--accent-soft);

  /* The footer is a light band now, like everything else. The rule that
     survived from 2026-08-27 still applies: a fixed-colour background gets a
     fixed-colour foreground. Pairing one fixed value with one that moves is
     what put near-white text on a near-white footer last time. */
  --footer-bg:   #e9eef8;
  --footer-fg:   #39414f;

  /* text sitting on a filled --accent / --accent-2 surface */
  --on-accent:   #ffffff;

  /* shape */
  --radius:      14px;
  --radius-sm:   9px;
  --radius-pill: 999px;

  --shadow-sm:   0 1px 2px rgba(22, 24, 29, .05);
  --shadow:      0 4px 14px -4px rgba(22, 24, 29, .10), 0 2px 4px rgba(22, 24, 29, .04);
  --shadow-lg:   0 18px 40px -18px rgba(22, 24, 29, .28), 0 4px 10px rgba(22, 24, 29, .05);

  /* --measure (68ch) was removed 2026-08-28. It capped the article text
     narrower than its own card and, being left-aligned, showed up as uneven
     margins. Reading width is `#primary`'s max-width now - one control. */
  --shell:       1180px;
  --gutter:      clamp(1rem, 4vw, 2.25rem);

  --sans:    'Source Sans 3', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --display: 'Space Grotesk', var(--sans);

  /* The duck jpeg has a white background. `multiply` drops it onto the page
     without a cutout, and that works here because every surface is light.
     Never put `filter` on the same element - Chrome then treats it as a
     backdrop root, silently ignores mix-blend-mode, and the white rectangle
     comes back. The computed style still reads `multiply`, so only the
     rendered page shows the bug. Put filters on a wrapper. */
  --duck-blend: multiply;
}

/* There is no dark theme. John asked for light backgrounds everywhere on
   2026-08-28, and the site no longer reacts to prefers-color-scheme at all.
   The old --duck-chip / --duck-pad tokens existed only to rescue the duck on a
   dark surface and went with it. */

/* ------------------------------------------------------------- 2. foundation */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.7;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-wrap: break-word;
}

/* A cool wash behind everything, so the page is not flat white. Kept very
   faint - it should read as light paper, not as a blue page. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(70rem 34rem at 12% -8%,  rgba(29, 78, 216, .07), transparent 60%),
    radial-gradient(52rem 30rem at 92%  2%,  rgba(207, 46, 46, .04), transparent 62%);
}

img, svg, video { max-width: 100%; height: auto; display: block; }

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

:focus-visible {
  outline: 3px solid var(--accent-2);
  outline-offset: 2px;
  border-radius: 4px;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--display);
  color: var(--ink);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.15;
  margin: 0 0 .5em;
  text-wrap: balance;
}

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

strong, b { font-weight: 650; color: var(--ink); }

hr {
  height: 1px;
  border: 0;
  margin: 1.75rem 0;
  background: linear-gradient(90deg, var(--line-strong), transparent);
}

::selection { background: var(--accent); color: var(--on-accent); }

.screen-reader-text {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: 50%;
  top: 0;
  z-index: 200;
  transform: translate(-50%, -120%);
  background: var(--btn-bg);
  color: var(--btn-fg);
  padding: .7rem 1.25rem;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  font-weight: 600;
  text-decoration: none;
}
.skip-link:focus {
  transform: translate(-50%, 0);
  clip: auto;
  clip-path: none;
  width: auto; height: auto;
  margin: 0;
  overflow: visible;
  white-space: normal;
  color: var(--btn-fg);
}

/* ------------------------------------------------------------------ 3. shell */

#page { display: flex; flex-direction: column; min-height: 100vh; }
#content { flex: 1 0 auto; }

.ast-container {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* One column. The sidebar was removed on 2026-08-28 (John: the calendar made
   no sense, and the rail went with it), so there is no second track any more
   and no 1000px breakpoint that adds one. */
#content > .ast-container {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 2.5rem;
  padding-block: clamp(2rem, 5vw, 3.5rem);
}

/* Full width would give very long lines on a wide screen, so the reading
   column is capped rather than the container. */
#primary {
  min-width: 0;
  width: 100%;
  max-width: 54rem;
  margin-inline: auto;
}

/* ----------------------------------------------------------------- 4. header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--paper) 86%, transparent);
  backdrop-filter: saturate(1.6) blur(12px);
  -webkit-backdrop-filter: saturate(1.6) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease, box-shadow .2s ease, background .2s ease;
}
.site-header.jrn-stuck {
  border-bottom-color: var(--line);
  box-shadow: var(--shadow-sm);
  background: color-mix(in srgb, var(--paper) 94%, transparent);
}

/* the header bar rows Astra emits */
.ast-main-header-wrap { width: 100%; }

.site-primary-header-wrap,
#ast-mobile-header .ast-primary-header-bar {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding: .7rem var(--gutter);
}

.ast-builder-grid-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.site-header-section { display: flex; align-items: center; gap: 1rem; }

/* branding */
.site-branding { display: block; }
.ast-site-identity { display: flex; align-items: center; gap: .7rem; }

.site-logo-img a { display: block; line-height: 0; }

.custom-logo {
  width: auto;
  height: 42px;
  mix-blend-mode: var(--duck-blend);
  border-radius: 10px;
  transition: transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.custom-logo-link:hover .custom-logo { transform: translateY(-2px) rotate(-4deg); }

.site-title {
  display: block;
  font-family: var(--display);
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -.025em;
  line-height: 1.1;
  margin: 0;
}
.site-title a {
  color: var(--ink);
  text-decoration: none;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: 0 88%;
  background-size: 0% .3em;
  transition: background-size .3s ease;
}
.site-title a:hover { background-size: 100% .3em; color: var(--ink); }

/* The duck-plus-name header used to be hidden on the homepage alone (see git
   history), to stop it repeating an <h1>John R Nelson</h1> right below it.
   John reviewed both and preferred the header exactly as it looks on every
   other page - duck next to the name, like on Privacy Policy - over having it
   disappear on Home (2026-08-28). So the header is uniform again: every page
   shows the duck and the name, no exceptions, no body.home special case.

   The duplication is resolved on the content side instead: the homepage's own
   <h1> no longer restates the name (the header already says it) - it uses the
   tagline. See .jrn-intro-title below. */

/* show one header, hide the other - Astra ships both in the markup */
#ast-desktop-header { display: none; }
#ast-mobile-header  { display: block; }

@media (min-width: 922px) {
  #ast-desktop-header { display: block; }
  #ast-mobile-header  { display: none; }
}

/* mobile menu trigger */
.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.menu-toggle:hover { background: var(--btn-surface-hover); border-color: var(--btn-border-hover); }
.menu-toggle svg { width: 22px; height: 22px; }

.mobile-menu-toggle-icon { display: flex; }
.menu-toggle .ast-close-svg { display: none; }
.menu-toggle[aria-expanded="true"] .ast-menu-svg  { display: none; }
.menu-toggle[aria-expanded="true"] .ast-close-svg { display: block; }
.menu-toggle[aria-expanded="true"] {
  background: var(--btn-bg);
  border-color: var(--btn-bg);
  color: var(--btn-fg);
}

/* mobile menu panel */
.ast-mobile-header-content {
  display: none;
  padding: .25rem var(--gutter) 1rem;
  border-top: 1px solid var(--line);
}
.ast-mobile-header-content.jrn-open { display: block; }

#ast-hf-mobile-menu .main-header-menu {
  list-style: none;
  margin: .75rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .35rem;
}
#ast-hf-mobile-menu .menu-link {
  display: block;
  padding: .6rem .85rem;
  border-radius: var(--radius-sm);
  background: var(--card);
  border: 1px solid var(--line);
  color: var(--ink);
  font-family: var(--display);
  font-weight: 500;
  text-decoration: none;
}
#ast-hf-mobile-menu .menu-link:hover {
  background: var(--btn-surface-hover);
  border-color: var(--btn-border-hover);
  color: var(--ink);
}

/* ------------------------------------------------------------- 5. home intro */
/* The homepage IS the "about me" now (2026-08-28). Deliberately short: John's
   stated audience is someone who already has his email address and types the
   domain in to see what is there, so the answer should land without a scroll
   or a click.

   No max-width on any of this. Capping one block narrower than the column it
   sits in is exactly what produced the lopsided margins he caught earlier -
   #primary is the only width control. */

.jrn-intro { padding-block: clamp(.5rem, 3vw, 2rem); }

/* The header now always shows "John R Nelson" (2026-08-28, see the header
   comment above), so this <h1> carries the tagline instead of the name - one
   heading, not a restatement of what the header already said. Same large,
   bold treatment every other page's <h1> gets (.ast-article-single
   .entry-title), so Home reads consistently with Contact me and Privacy
   Policy rather than looking like a smaller, secondary line. */
.jrn-intro-title {
  font-size: clamp(2rem, 6vw, 3.1rem);
  letter-spacing: -.035em;
  margin: 0 0 2rem;
}
.jrn-intro-title::after {
  content: "";
  display: block;
  width: 3.5rem;
  height: .35rem;
  margin-top: 1.25rem;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}

.jrn-intro-body {
  font-size: clamp(1.15rem, 2.6vw, 1.35rem);
  line-height: 1.6;
  color: var(--ink);
  margin: 0 0 2rem;
}

.jrn-interests {
  list-style: none;
  margin: 0 0 2.25rem;
  padding: 0;
  display: grid;
  gap: .75rem;
}
@media (min-width: 640px) {
  .jrn-interests { grid-template-columns: repeat(3, 1fr); gap: 1rem; }
}
.jrn-interests li {
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: .85rem 1.1rem;
  font-family: var(--display);
  font-weight: 500;
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}

.jrn-intro-actions { margin: 0; }
.jrn-intro-actions a {
  display: inline-block;
  padding: .7rem 1.5rem;
  border-radius: var(--radius-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--display);
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: background .18s ease, transform .18s ease;
}
.jrn-intro-actions a:hover {
  background: var(--btn-bg-hover);
  color: var(--btn-fg);
  transform: translateY(-2px);
}

/* ---------------------------------------------------- 6. single post or page */

.ast-article-single {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: clamp(1.5rem, 5vw, 3.25rem);
}

.ast-article-single .entry-header {
  margin: 0 0 2rem;
  padding: 0 0 1.5rem;
  border-bottom: 1px solid var(--line);
}

.ast-article-single .entry-title {
  font-size: clamp(1.9rem, 5.5vw, 3rem);
  letter-spacing: -.032em;
  margin: 0 0 .75rem;
}

.ast-article-single .entry-meta { font-size: .92rem; }
.posted-on .published { white-space: nowrap; }

/* ------------------------------------------------------ 7. article body type */

/* No max-width here. It used to be capped at `--measure` (68ch) while the card
   around it was wider, and because the cap is left-aligned that put 53px of
   margin on the left and 209px on the right. The narrow sidebar-era card hid
   it; going to one column made it obvious (John, 2026-08-28).

   The reading width is now decided in exactly ONE place - `#primary`'s
   max-width - instead of two caps fighting each other. Widen the column, and
   the text follows it symmetrically. */
.entry-content {
  font-size: 1.115rem;
  line-height: 1.75;
}

.entry-content > *:first-child { margin-top: 0; }
.entry-content > *:last-child  { margin-bottom: 0; }

.entry-content h2 { font-size: clamp(1.5rem, 3.6vw, 1.95rem); margin: 2.25rem 0 .75rem; }
.entry-content h3 { font-size: clamp(1.25rem, 3vw, 1.5rem);    margin: 2rem 0 .6rem; }
.entry-content h4 { font-size: 1.2rem;                          margin: 1.75rem 0 .5rem; }

/* a small yellow tick to the left of section headings */
.entry-content h2::before,
.entry-content h3::before {
  content: "";
  display: block;
  width: 2.25rem;
  height: .3rem;
  margin-bottom: .7rem;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}

.entry-content p:empty { display: none; }

.entry-content a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--link) 40%, transparent);
  text-underline-offset: 3px;
}
.entry-content a:hover { text-decoration-color: currentColor; }

.entry-content ul,
.entry-content ol { padding-left: 1.35rem; margin: 0 0 1.15em; }
.entry-content li { margin-bottom: .4em; }
.entry-content ul li::marker { color: var(--accent-2); }

.entry-content blockquote {
  margin: 1.75rem 0;
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--line);
  border-left: 5px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--accent-wash);
  font-size: 1.15rem;
  font-style: italic;
  color: var(--ink);
}
.entry-content blockquote p { margin-bottom: .5em; }
.entry-content blockquote cite {
  display: block;
  font-style: normal;
  font-family: var(--display);
  font-weight: 500;
  font-size: .92rem;
  color: var(--muted);
}

.entry-content figure,
.wp-block-image {
  margin: 2rem 0;
}
.wp-block-image img {
  border-radius: var(--radius);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  max-width: 100%;
  height: auto;
}
.wp-block-image figcaption {
  margin-top: .7rem;
  font-size: .9rem;
  color: var(--muted);
  text-align: center;
}

.entry-content code,
.entry-content pre {
  font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  font-size: .93em;
}
.entry-content code {
  background: var(--card-2);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: .1em .35em;
}
.entry-content pre {
  background: var(--card-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 1rem 1.15rem;
  overflow-x: auto;
}
.entry-content pre code { background: none; border: 0; padding: 0; }

.entry-content table {
  width: 100%;
  border-collapse: collapse;
  margin: 1.5rem 0;
  font-size: .97rem;
}
.entry-content th,
.entry-content td {
  border: 1px solid var(--line);
  padding: .55rem .7rem;
  text-align: left;
}
.entry-content th { background: var(--card-2); font-weight: 650; color: var(--ink); }

/* ------------------------------------------------------ 8. footer navigation */
/* The sidebar is gone. It held the categories, a dead calendar, and a stray
   "Home" link. Removing it stranded two pages, because the desktop top nav was
   removed on 2026-08-27 and the footer only ever held an email address - so
   the category links and the three page links live down here now.

   No headings are invented: the two lists are told apart by shape, page links
   as plain text, categories as chips. That keeps the "change no text" rule. */

.jrn-footer-nav {
  max-width: var(--shell);
  margin-inline: auto;
  padding: 2.25rem var(--gutter) 0;
}

.jrn-footer-nav-inner {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding-bottom: 1.75rem;
  border-bottom: 1px solid color-mix(in srgb, var(--footer-fg) 18%, transparent);
}

@media (min-width: 720px) {
  .jrn-footer-nav-inner {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-start;
    gap: 2.5rem;
  }
}

.jrn-footer-pages,
.jrn-footer-cats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.5rem;
}

.jrn-footer-pages a {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  padding-bottom: 2px;
  transition: border-color .18s ease, color .18s ease;
}
.jrn-footer-pages a:hover {
  color: var(--accent-deep);
  border-bottom-color: var(--accent);
}

.jrn-footer-cats { gap: .5rem; }
.jrn-footer-cats a {
  display: inline-block;
  padding: .2rem .7rem;
  border-radius: var(--radius-pill);
  background: var(--accent-wash);
  border: 1px solid var(--accent-soft);
  color: var(--ink);
  font-family: var(--display);
  font-size: .82rem;
  font-weight: 500;
  text-decoration: none;
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.jrn-footer-cats a:hover,
.jrn-footer-cats a[aria-current="page"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

/* ----------------------------------------------------------------- 9. footer */

.site-footer {
  flex: none;
  margin-top: 3rem;
  background: var(--footer-bg);
  color: var(--footer-fg);
  border-top: 4px solid var(--accent);
}

.site-below-footer-wrap {
  max-width: var(--shell);
  margin-inline: auto;
  padding: 2.25rem var(--gutter);
}

.site-below-footer-inner-wrap {
  display: flex;
  justify-content: center;
  text-align: center;
}

/* Scoped to the email line, NOT `.site-footer a`. A blanket footer-link rule
   sits later in this file than the footer-nav rules above and would override
   them at equal specificity, putting an underline on every chip.

   The hover here used to be #fff, which worked only because the footer was a
   dark band. The footer is light now, so white-on-light would be the same
   invisible-text bug as 2026-08-27 - both ends of this pair are dark. */
.ast-builder-html-element p { margin: 0; font-size: 1rem; }
.ast-builder-html-element a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
}
.ast-builder-html-element a:hover {
  color: var(--accent-deep);
  border-bottom-color: var(--accent-deep);
}

/* --------------------------------------------------------- 10. scroll to top */

#ast-scroll-top {
  position: fixed;
  right: clamp(.9rem, 3vw, 1.75rem);
  bottom: clamp(.9rem, 3vw, 1.75rem);
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.9rem;
  height: 2.9rem;
  border-radius: 50%;
  background: var(--btn-bg);
  color: var(--btn-fg);
  box-shadow: var(--shadow-lg);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity .22s ease, transform .22s ease, visibility .22s;
}
#ast-scroll-top.jrn-visible { opacity: 1; visibility: visible; transform: none; }
#ast-scroll-top:hover { background: var(--btn-bg-hover); }
#ast-scroll-top svg {
  width: 20px;
  height: auto;
  fill: currentColor;
  transform: rotate(180deg);
}

/* ---------------------------------------------------------------- 11. motion */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
