/* ==========================================================================
   Shared stylesheet for stevespindler.com, cartographyclass.com and
   katespindler.com.
   --------------------------------------------------------------------------
   THIS IS THE ONLY COPY YOU SHOULD EDIT. Run `npm run css` to push it into each
   site, including Kate's separate repo. Editing a site's own
   src/css/style.css works until the next sync overwrites it, which is exactly
   how the archive notice and list header styling got lost once already.

   Sites differ by markup and site.config.json, not by having different CSS.
   ========================================================================== */

:root {
  --ink: #1c1c1a;
  --ink-soft: #5d5c57;
  --rule: #ddd9d0;
  --paper: #fbfaf7;         /* the page behind everything */
  --panel: #fdfcfa;         /* the reading column, a shade lighter than paper */
  --frame: #ffffff;         /* framed photos, code blocks, inputs */
  --accent: #1f5f4f;        /* contour green */
  --accent-soft: #f0f4f2;
  --measure: 38rem;         /* text column */
  --measure-wide: 56rem;    /* photo and video pages */
  --radius: 6px;

  /* The reading panel sits a shade lighter than the page behind it, so the
     writing reads as a sheet laid on the background rather than printed
     straight onto it. Deliberately not pure white: framed photos, code blocks
     and the search field are white, and they have to stay distinguishable from
     the sheet they sit on. */
  --panel-pad: 1.75rem;

  /* Listing thumbnails. Square, and set as one value so the grid column and the
     image can never disagree about the size -- which is what let a landscape
     photo render as a tall sliver. */
  --thumb: 4rem;
  --thumb-wide: 5rem;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 0 1.25rem 4rem;
  background: var(--paper);
  color: var(--ink);
  font: 1.0625rem/1.65 Georgia, "Iowan Old Style", "Times New Roman", serif;
}

main, .site-header, .site-footer, .post-nav { max-width: var(--measure); margin-inline: auto; }

/* The panel. Widened by its own padding so the text column stays exactly
   --measure wide: the reading line length should not change just because the
   writing now sits on a sheet. */
main {
  max-width: calc(var(--measure) + var(--panel-pad) * 2);
  background: var(--panel);
  padding: var(--panel-pad);
  border-radius: var(--radius);
}

@media (max-width: 30rem) {
  /* On a narrow screen the padding costs more than the effect is worth. */
  main { padding: 1.1rem; max-width: calc(var(--measure) + 2.2rem); }
}

img, video, iframe { max-width: 100%; }

/* ==========================================================================
   Header
   --------------------------------------------------------------------------
   Title and nav sit side by side only when there is genuinely room. Below that
   the nav drops to its own line, because squeezing four labels beside a
   two-word title wrapped both of them and looked cramped.
   ========================================================================== */
.site-header {
  padding: 2.5rem 0 1.5rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 2rem;
}

.site-header-row {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.site-title {
  display: block;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  line-height: 1.3;
  color: var(--ink);
  text-decoration: none;
}
.site-title:hover { color: var(--accent); }

.site-tagline {
  margin: 0.35rem 0 0;
  color: var(--ink-soft);
  font-style: italic;
  font-size: 0.95rem;
}

/* Nav: pill-shaped links, wrapping cleanly, no cramped underlines. */
.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
}

.site-nav a,
.site-search-link {
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-decoration: none;
  padding: 0.34rem 0.7rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--frame);
  white-space: nowrap;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.site-nav a:hover,
.site-search-link:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
}

.site-nav a[aria-current="page"] {
  color: var(--ink);
  border-color: var(--ink-soft);
}

@media (min-width: 46rem) {
  .site-header-row {
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1.5rem;
  }
  .site-nav { justify-content: flex-end; max-width: 60%; }
}

/* ==========================================================================
   Archive notice
   --------------------------------------------------------------------------
   Shown when archiveNotice is set in site.config.json. Quiet, once, near the
   top: an honest expectation, not an alarm.
   ========================================================================== */
.archive-notice {
  max-width: var(--measure);
  margin: 0 auto 2.25rem;
  padding: 0.8rem 1rem;
  background: #fdf7e8;
  border: 1px solid #e9dcbe;
  border-left: 3px solid #c9a648;
  border-radius: var(--radius);
}

.archive-notice p {
  margin: 0;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.85rem;
  line-height: 1.55;
  color: #6b6350;
}

/* ==========================================================================
   List header
   --------------------------------------------------------------------------
   Names the post list, so landing on the home page makes clear this is the full
   archive rather than a few recent items.
   ========================================================================== */
.list-header { max-width: var(--measure); margin: 0 auto 1.75rem; }

.list-header h1 {
  margin: 0 0 0.25rem;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.list-header p {
  margin: 0;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

/* ==========================================================================
   Post list
   ========================================================================== */
.post-list { list-style: none; margin: 0; padding: 0; }

.post-list-item {
  padding-bottom: 1.75rem;
  margin-bottom: 1.75rem;
  border-bottom: 1px solid var(--rule);
}
.post-list-item:last-child { border-bottom: 0; }

.post-list-item.has-thumb {
  display: grid;
  grid-template-columns: var(--thumb) 1fr;
  gap: 1rem;
  align-items: start;
}

/* align-self so the thumbnail never stretches to the height of the text beside
   it, and an explicit width AND height rather than aspect-ratio, so the square
   does not depend on the browser resolving a ratio. A landscape photo is
   cropped to the middle by object-fit, which is the intent -- without the fixed
   height it rendered as a tall magnified sliver instead. */
.post-list-thumb {
  display: block;
  align-self: start;
  width: var(--thumb);
  height: var(--thumb);
}
.post-list-thumb img {
  width: var(--thumb);
  height: var(--thumb);
  object-fit: cover;
  border-radius: var(--radius);
  display: block;
}

.post-list-date,
.post-meta {
  display: block;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.74rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.post-list-title { margin: 0.3rem 0 0.45rem; font-size: 1.3rem; line-height: 1.28; }
.post-list-title a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.post-list-title a:hover { color: var(--accent); text-decoration-color: var(--accent); }

.post-list-excerpt { margin: 0; color: var(--ink-soft); font-size: 1rem; }

@media (min-width: 40rem) {
  :root { --thumb: var(--thumb-wide); }
  .post-list-item.has-thumb { gap: 1.1rem; }
  .post-list-title { font-size: 1.4rem; }
}

/* ==========================================================================
   Search
   ========================================================================== */
.search-page { margin-bottom: 2rem; }

.search-label {
  display: block;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 0.5rem;
}

.search-input {
  width: 100%;
  font: inherit;
  font-size: 1rem;
  padding: 0.7rem 1rem;
  background: var(--frame);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 999px;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.search-input::placeholder { color: #a8a49a; }
.search-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* Safari draws its own clear button on type=search; keep it inside the pill. */
.search-input::-webkit-search-cancel-button { margin-right: 0.2rem; }

.search-status {
  margin: 0.55rem 0 0;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

mark { background: #f6e7a8; color: inherit; padding: 0 0.1em; border-radius: 2px; }

/* ==========================================================================
   Single post or page
   ========================================================================== */
.post-header { margin-bottom: 1.75rem; }
.post-header h1 { margin: 0 0 0.4rem; font-size: 1.6rem; line-height: 1.22; }
.post-meta time + .post-categories::before { content: " \00b7  "; }

@media (min-width: 40rem) {
  .post-header h1 { font-size: 2rem; }
}

.post-lead-image { margin: 0 0 1.75rem; }
.post-lead-image img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
}

.post-body h2, .post-body h3 { line-height: 1.3; margin-top: 2rem; }
.post-body h3 { font-size: 1.15rem; }
.post-body p { margin: 0 0 1.2rem; }
.post-body a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

.post-body img, .post-body figure img {
  display: block;
  height: auto;
  margin: 1.25rem auto;
  border-radius: 2px;
}

.post-body figure { margin: 1.75rem 0; }

.post-body figure > figcaption,
.post-body .wp-element-caption {
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--ink-soft);
  margin-top: 0.5rem;
}

/* Tables scroll rather than forcing the page sideways on a phone. */
.post-body table {
  border-collapse: collapse;
  width: 100%;
  margin: 1.25rem 0;
  font-size: 0.95rem;
}
.post-body th, .post-body td {
  border-bottom: 1px solid var(--rule);
  padding: 0.45rem 0.6rem;
  text-align: left;
}

.post-body blockquote {
  margin: 1.25rem 0;
  padding-left: 1.1rem;
  border-left: 3px solid var(--rule);
  color: var(--ink-soft);
  font-style: italic;
}

.post-body pre {
  overflow-x: auto;
  background: var(--frame);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.8rem;
  font-size: 0.88rem;
}

.post-body .button {
  display: inline-block;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.85rem;
  line-height: 1.3;
  color: var(--paper);
  background: var(--accent);
  padding: 0.55rem 0.95rem;
  border-radius: 999px;
  text-decoration: none;
  margin: 0.25rem 0.4rem 0.25rem 0;
}
.post-body .button:hover { background: var(--ink); }

.post-body .box {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  margin: 1.75rem 0;
  background: var(--frame);
}

/* A photo standing on its own, linked to the full-size file. */
.post-body .photo-full {
  display: block;
  margin: 1.75rem 0;
  background: var(--frame);
  padding: 0.5rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 1px 3px rgba(28, 28, 26, 0.07);
  line-height: 0;
  text-decoration: none;
  transition: box-shadow 0.18s ease;
}
.post-body .photo-full:hover { box-shadow: 0 4px 14px rgba(28, 28, 26, 0.15); }
.post-body .photo-full:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.post-body .photo-full img { margin: 0; width: 100%; border-radius: 3px; }
.post-body p > .photo-full { margin: 0; }

.post-body video {
  display: block;
  width: 100%;
  margin: 1.75rem 0;
  background: #000;
  border-radius: var(--radius);
}

/* ==========================================================================
   Video
   --------------------------------------------------------------------------
   A poster image plus a play badge, inside a link to the video host. js/video.js
   swaps in the real player on click, so nothing loads from Vimeo until asked.
   The aspect ratio comes from the host and rides on --ratio, because assuming
   16:9 letterboxed these 16:10 videos into thick black bars.
   ========================================================================== */
.post-body .video { margin: 1.75rem 0; }

.post-body .video-play,
.post-body .video-frame {
  display: block;
  width: 100%;
  aspect-ratio: var(--ratio, 16 / 9);
  border: 0;
  border-radius: var(--radius);
  overflow: hidden;
}

.post-body .video-play {
  position: relative;
  background: var(--rule);
  line-height: 0;
  text-decoration: none;
}

.post-body .video-play img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  margin: 0;
  display: block;
  border-radius: 0;
}

.post-body .video-play-badge {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 3.2rem;
  height: 3.2rem;
  border-radius: 50%;
  background: rgba(28, 28, 26, 0.62);
  transition: background 0.18s ease, transform 0.18s ease;
}
.post-body .video-play-badge::after {
  content: "";
  position: absolute;
  left: 54%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 0.58rem 0 0.58rem 1rem;
  border-color: transparent transparent transparent #fff;
}
.post-body .video-play:hover .video-play-badge {
  background: var(--accent);
  transform: translate(-50%, -50%) scale(1.06);
}
.post-body .video-play:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.post-body .video-duration {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.72rem;
  line-height: 1;
  color: #fff;
  background: rgba(28, 28, 26, 0.75);
  padding: 0.22rem 0.4rem;
  border-radius: 3px;
}

.post-body .video-label {
  margin: 0.5rem 0 0;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.84rem;
  line-height: 1.4;
  color: var(--ink);
}

/* A list of videos is a grid, not bullet points. */
.post-body ul:has(> .video-item) {
  list-style: none;
  margin: 1.25rem 0 2.25rem;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.4rem 1.1rem;
}
.post-body .video-item { margin: 0; }
.post-body .video-item .video { margin: 0; }

@media (min-width: 34rem) {
  .post-body ul:has(> .video-item) { grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
}
@media (min-width: 58rem) {
  .post-body ul:has(> .video-item) {
    width: calc(100% + 9rem);
    margin-left: -4.5rem;
    margin-right: -4.5rem;
  }
}

/* ==========================================================================
   Photo galleries
   --------------------------------------------------------------------------
   WordPress gallery blocks: a .wp-block-gallery wrapper around one nested
   figure per photo. Unstyled, every photo renders full width and the page
   becomes an endless column.
   ========================================================================== */
.wp-block-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0.7rem;
  margin: 1.75rem 0;
  padding: 0;
  list-style: none;
}

.wp-block-gallery > .wp-block-image {
  margin: 0;
  background: var(--frame);
  padding: 0.4rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 1px 3px rgba(28, 28, 26, 0.07);
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}
.wp-block-gallery > .wp-block-image:hover {
  box-shadow: 0 4px 14px rgba(28, 28, 26, 0.14);
  transform: translateY(-2px);
}

.wp-block-gallery > .wp-block-image img {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  margin: 0;
  border-radius: 3px;
}

.wp-block-gallery .photo,
.post-body .gallery .photo {
  display: block;
  text-decoration: none;
  border: 0;
  line-height: 0;
}
.wp-block-gallery .photo:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.wp-block-gallery figcaption {
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.76rem;
  line-height: 1.4;
  color: var(--ink-soft);
  margin: 0.45rem 0.1rem 0.1rem;
}

/* Galleries recovered from the old Themify builder. */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0.7rem;
  margin: 1.75rem 0;
}
.gallery img { margin: 0; width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 3; }

.image-compare { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.image-compare img { margin: 0; }

@media (min-width: 40rem) {
  .wp-block-gallery,
  .gallery { grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); gap: 1rem; }
  .wp-block-gallery > .wp-block-image { padding: 0.5rem; }
}

/* Photo-led pages get a wider column; prose inside stays readable. */
body.page main { max-width: var(--measure-wide); }
body.page .post-body > p,
body.page .post-header,
body.page .archive-notice { max-width: var(--measure); }

/* ==========================================================================
   Tags, navigation, footer
   ========================================================================== */
.post-tags { margin: 1.75rem 0 0; }
.tag {
  display: inline-block;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.74rem;
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.15rem 0.6rem;
  margin: 0 0.3rem 0.3rem 0;
}

.back-link {
  display: inline-block;
  margin-bottom: 1.25rem;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  text-decoration: none;
}
.back-link:hover { color: var(--accent); }

.post-nav,
.page-nav {
  margin: 2.5rem auto 0;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  align-items: baseline;
}
.page-nav { max-width: var(--measure-wide); }

.post-nav a,
.page-nav a,
.page-nav span,
.site-footer {
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.82rem;
  color: var(--ink-soft);
}
.post-nav a, .page-nav a { text-decoration: none; }
.post-nav a:hover, .page-nav a:hover { color: var(--accent); }

.page-nav span[aria-current="page"] { color: var(--ink); font-weight: 600; }
.page-nav .page-nav-home { margin-right: auto; }

.site-footer {
  margin-top: 3rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
}

/* ==========================================================================
   Inline video links
   --------------------------------------------------------------------------
   A video mentioned inside a sentence ("here's a link to the video"). Turning it
   into a player would break the sentence, and leaving it a plain link gives no
   clue it is a video. A small play glyph calls attention to it without showing a
   preview in the middle of the prose.
   ========================================================================== */
.post-body a.video-link {
  white-space: normal;
  text-decoration-color: var(--accent);
}

.post-body a.video-link::before {
  content: "";
  display: inline-block;
  width: 0.95em;
  height: 0.95em;
  margin-right: 0.32em;
  vertical-align: -0.11em;
  border-radius: 50%;
  background-color: var(--accent);
  /* A white play triangle, drawn rather than loaded. */
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M4.4 3.2 8.6 6l-4.2 2.8z' fill='%23fff'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100%;
}

/* The fallback when a video has no poster yet: a standalone link, set apart from
   the surrounding paragraphs so it does not read as body text. */
.post-body .video-inline {
  margin: 1.5rem 0;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 0.9rem;
}
