/* ==========================================================================
   Bryan Forby — public site
   A warm, editorial two-column layout: who he is on the left, what he wrote
   on the right. Inter throughout.
   ========================================================================== */

:root {
  --ink:        #041626;
  --ink-mid:    #374557;
  --muted:      #748296;
  --page:       #fcfcfc;
  --warm:       #faf9f5;
  --subtle:     #f0efe9;
  --line:       #e9e7dd;
  --line-soft:  #f1efe7;
  --accent:     #0b4fff;
  --tan:        #a18a6f;

  --r-card: 16px;
  --r-img:  12px;
  --r-pill: 999px;
  --r-sm:   8px;

  --nav-h:   66px;
  --gutter:  42px;
  --top-pad: 124px;
  --stream-gap: 76px;

  --ease: cubic-bezier(0.44, 0, 0.34, 0.98);
}

/* --- reset ---------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  /* The nav is fixed, so an anchor jump would otherwise park the target's
     first 66px underneath it — "Subscribe" landed on a beheaded card. The
     extra breathing room stops the heading sitting flush against the bar. */
  scroll-padding-top: calc(var(--nav-h) + 28px);
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               Helvetica, Arial, sans-serif;
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; }
img { display: block; max-width: 100%; }

/* Author styles beat the user-agent sheet, so `img { display: block }` above
   would otherwise defeat the `hidden` attribute. */
[hidden] { display: none !important; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.icon {
  width: 16px; height: 16px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sep {
  color: var(--line);
  font-size: 11px;
  user-select: none;
}

.dot {
  width: 12px; height: 12px;
  border-radius: var(--r-pill);
  background: var(--accent);
  flex: none;
  display: block;
}

.rule { height: 1px; background: var(--line); width: 100%; }

/* --- navigation ----------------------------------------------------------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 20;
  height: var(--nav-h);
  background: var(--warm);
  border-bottom: 1px solid var(--line);
}

.nav-inner {
  max-width: 1180px;
  height: 100%;
  margin: 0 auto;
  padding: 0 var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.brand-name {
  font-weight: 600;
  font-size: 14px;
  letter-spacing: -0.015em;
}

.brand-tag {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

.nav-right {
  display: flex;
  align-items: center;
  gap: 16px;
}

.nav-link {
  font-size: 13px;
  color: var(--muted);
  transition: color 0.2s var(--ease);
}

.nav-link:hover { color: var(--tan); }

/* --- pills / buttons ------------------------------------------------------ */

.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 18px;
  border-radius: var(--r-pill);
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease),
              color 0.2s var(--ease), transform 0.2s var(--ease);
}

.pill-ghost {
  background: var(--warm);
  border-color: var(--line);
  color: var(--ink-mid);
}

.pill-ghost:hover {
  background: var(--subtle);
  border-color: var(--tan);
  color: var(--ink);
  transform: translateY(-1px);
}

.pill-ghost:active { transform: translateY(0); }

/* Ink rather than the accent blue: against a warm off-white page the bright
   blue read as a stray UI control. The blue stays for the small dots, where
   it works as punctuation. */
.pill-solid {
  background: var(--ink);
  color: #fff;
  box-shadow: 0 1px 2px rgba(4, 22, 38, 0.18);
}

.pill-solid:hover {
  background: var(--tan);
  transform: translateY(-1px);
  box-shadow: 0 8px 18px -8px rgba(4, 22, 38, 0.45);
}

.pill-solid:active {
  transform: translateY(0);
  box-shadow: 0 1px 2px rgba(4, 22, 38, 0.18);
}

.pill-solid:disabled {
  opacity: 0.5;
  cursor: default;
  transform: none;
  box-shadow: none;
}

.pill:focus-visible,
.field:focus-visible,
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- page shell ----------------------------------------------------------- */

.page {
  padding: var(--top-pad) var(--gutter) 24px;
}

.container {
  max-width: 1180px;
  margin: 0 auto;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 34px;
}

/* --- left column: who he is ----------------------------------------------- */

.bio {
  position: sticky;
  top: var(--top-pad);
  flex: 1 1 0;
  max-width: 370px;
  height: 80vh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 32px;
}

.bio-top {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
}

.portrait {
  width: 106px;
  height: 106px;
  border-radius: var(--r-pill);
  background: var(--warm);
  border: 1px solid var(--line);
  padding: 2px;
  overflow: hidden;
  flex: none;
  display: grid;
  place-items: center;
}

.portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--r-pill);
}

.portrait-initials {
  font-size: 36px;
  font-weight: 600;
  color: var(--tan);
  letter-spacing: -0.02em;
}

.bio-words {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.bio-heading {
  font-size: clamp(28px, 3.1vw, 42px);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.bio-text {
  font-size: 15px;
  line-height: 1.55;
  color: var(--muted);
}

/* --- books ---------------------------------------------------------------- */

.books {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}

.books-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.books-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.book-link {
  padding: 9px 15px;
  font-size: 13px;
}

.book-link .icon { width: 15px; height: 15px; }

.bio-newsletter {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  width: 100%;
  max-width: 400px;
}

.newsletter-pitch {
  font-size: 15px;
  color: var(--muted);
  max-width: 260px;
}

.newsletter-note {
  font-size: 11px;
  color: var(--muted);
}

/* --- the hairline between the columns ------------------------------------- */

.divider {
  position: sticky;
  top: var(--top-pad);
  flex: none;
  width: 1px;
  height: 80vh;
  background: var(--line);
  overflow: hidden;
}

.divider-fill {
  display: block;
  width: 100%;
  height: 0;
  background: var(--tan);
  transition: height 0.15s linear;
}

/* --- right column: the stories -------------------------------------------- */

.stream {
  flex: 1 1 0;
  max-width: 620px;
  display: flex;
  flex-direction: column;
  gap: var(--stream-gap);
  min-width: 0;
}

.section {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* --- folder filters ------------------------------------------------------- */

/* Plain links across the top of the stream, one per folder. The stream's own
   gap is the space between two runs of stories, which is far too much air
   under a row of links — hence pulling the first section back up. */
.filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: calc(24px - var(--stream-gap));
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--warm);
  color: var(--ink-mid);
  font-size: 13px;
  line-height: 1.2;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease),
              color 0.2s var(--ease);
}

.chip:hover { border-color: var(--tan); color: var(--ink); }

.chip.is-on {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--page);
}

.chip-count { font-size: 11px; color: var(--muted); }
.chip.is-on .chip-count { color: rgba(252, 252, 252, 0.65); }

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.section-title {
  display: flex;
  align-items: center;
  gap: 12px;
}

.section-title h2 {
  font-size: clamp(18px, 1.7vw, 21px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

/* Smaller heading, so the dot alongside it comes down to match. */
.section-title .dot { width: 9px; height: 9px; }

/* Tan rather than blue, so "Today's pick" reads as a different kind of thing
   from the chronological sections either side of it. */
.dot-tan { background: var(--tan); }

.section-count {
  font-size: 12px;
  color: var(--muted);
}

.section-list {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

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

.card {
  position: relative;
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 20px;
  padding: 20px;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--warm);
  transition: border-color 0.25s var(--ease), transform 0.25s var(--ease),
              box-shadow 0.25s var(--ease);
}

.card:hover {
  border-color: var(--tan);
  transform: translateY(-2px);
  box-shadow: 0 12px 28px -18px rgba(4, 22, 38, 0.35);
}

.card-main {
  display: flex;
  gap: 16px;
  flex: 1 1 0;
  min-width: 0;
}

.card-text {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 28px;
  min-width: 0;
  flex: 1 1 0;
}

.card-head {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.card-title {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-lead .card-title { font-size: 21px; }

.card-excerpt {
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 12px;
  color: var(--muted);
}

.tag-draft {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--tan);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: 2px 8px;
}

.card-draft { border-style: dashed; }

/* date chip */
.datebadge {
  width: 50px;
  height: 54px;
  flex: none;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--page);
}

.datebadge-month {
  height: 20px;
  background: var(--line);
  color: var(--ink-mid);
  font-size: 11px;
  letter-spacing: -0.01em;
  display: grid;
  place-items: center;
}

.datebadge-day {
  flex: 1;
  display: grid;
  place-items: center;
  font-size: 15px;
  letter-spacing: 0.03em;
  color: var(--muted);
}

/* The card is `align-items: stretch`, so a photo left to find its own
   height filled whatever the text happened to make the card — a long
   excerpt gave a tall photo, a short one gave a squat photo, and no two
   cards down the page agreed. The shape is pinned here instead, so every
   story's photo is the same size whatever is written beside it.

   `align-self: center` is what stops the stretch: a flex item is only
   stretched while its height is auto, and centring leaves the spare
   height split evenly above and below rather than all of it underneath. */
.card-photo {
  width: 138px;
  aspect-ratio: 7 / 6;
  align-self: center;
  flex: none;
  border-radius: var(--r-img);
  overflow: hidden;
  background: var(--subtle);
}

.card-lead .card-photo { width: 172px; }

/* `cover` scales the photo down until it just fills the box and crops off
   what is over — never stretched out of shape — and `object-position`,
   which the focus classes further down set, decides which part of it that
   crop keeps. Both are on the image rather than the box, because it is
   the image that is being placed inside the shape above. */
.card-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.load-more-row {
  display: flex;
  justify-content: center;
  padding-top: 8px;
}

/* --- empty state ---------------------------------------------------------- */

.empty {
  border: 1px dashed var(--line);
  border-radius: var(--r-card);
  padding: 48px 32px;
  text-align: center;
  background: var(--warm);
}

.empty h2 {
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.03em;
  margin-bottom: 8px;
}

.empty p { color: var(--muted); font-size: 14px; }

/* --- subscribe form ------------------------------------------------------- */

.subscribe {
  display: flex;
  align-items: stretch;
  flex-wrap: wrap;
  gap: 8px;
  width: 100%;
  /* The highlight below draws outside the form's own box. */
  position: relative;
  border-radius: 12px;
}

/* Clicking "Subscribe" in the header or footer lights up whichever form it
   sent you to — a pastel yellow panel with a matching border. On a wide
   screen that form is often already on screen, so without this the click
   looks like it did nothing at all.

   Done with the form's own background and a spread box-shadow rather than an
   absolutely-positioned pseudo-element: the shadow paints the padding and
   the border in one go, sits behind the field and the button without any
   z-index argument, and costs no layout shift. */
.subscribe.is-highlighted {
  animation: subscribe-glow 2.6s var(--ease) forwards;
}

@keyframes subscribe-glow {
  0% {
    background: rgba(253, 245, 200, 0);
    box-shadow: 0 0 0 0 rgba(253, 245, 200, 0), 0 0 0 0 rgba(242, 223, 133, 0);
  }
  10%, 75% {
    background: #fdf5c8;
    box-shadow: 0 0 0 14px #fdf5c8, 0 0 0 16px #f2df85;
  }
  100% {
    background: rgba(253, 245, 200, 0);
    box-shadow: 0 0 0 14px rgba(253, 245, 200, 0), 0 0 0 16px rgba(242, 223, 133, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Still show it, just without the fade in and out. */
  .subscribe.is-highlighted {
    animation: none;
    background: #fdf5c8;
    box-shadow: 0 0 0 14px #fdf5c8, 0 0 0 16px #f2df85;
  }
}

.field {
  flex: 1 1 auto;
  min-width: 0;
  padding: 12px 16px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--subtle);
  color: var(--ink);
  font-size: 15px;
  line-height: 1.2;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}

.field::placeholder { color: var(--muted); }

.field:hover { border-color: #ddd8c8; }

.field:focus {
  outline: none;
  border-color: var(--tan);
  background: var(--page);
  box-shadow: 0 0 0 3px rgba(161, 138, 111, 0.14);
}

.subscribe .pill { border-radius: 10px; padding: 12px 20px; }

.subscribe-stacked { flex-direction: column; }
.subscribe-stacked .pill { width: 100%; }

/* Sits on its own row under the field. Empty it has no height, so the
   layout only shifts once there is something to say. */
.subscribe-status {
  flex: 0 0 100%;
  font-size: 12px;
  line-height: 1.4;
  color: var(--muted);
  margin: 0;
}

.subscribe-status:not(:empty) { margin-top: 2px; }
.subscribe-status.is-error { color: #b4342b; }
.subscribe-status.is-ok { color: var(--tan); }

/* --- newsletter band ------------------------------------------------------ */

.newsletter-card {
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--subtle);
  padding: 38px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  align-items: flex-start;
}

.newsletter-card h2 {
  font-size: clamp(22px, 2.4vw, 30px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.2;
  max-width: 22ch;
}

.newsletter-card .subscribe { max-width: 420px; }

/* The left column carries the form on wide screens; the band takes over
   below 1200px where the sticky column collapses. */
.newsletter-band { display: none; }

/* --- article -------------------------------------------------------------- */

.page-article { padding-bottom: 40px; }

.article {
  max-width: 680px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.backlink {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
  align-self: flex-start;
  transition: color 0.2s var(--ease), gap 0.2s var(--ease);
}

.backlink:hover { color: var(--tan); gap: 10px; }

.article-head {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.article-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 12px;
  color: var(--muted);
}

/* The folder in a story's byline, which links back to that filter. */
.meta-link {
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 3px;
}

.meta-link:hover { color: var(--tan); }

.article-title {
  font-size: clamp(28px, 4.6vw, 44px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.article-standfirst {
  font-size: 18px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 60ch;
}

.article-cover {
  border-radius: var(--r-img);
  overflow: hidden;
  background: var(--subtle);
}

.article-cover img { width: 100%; height: auto; }

/* --- prose ---------------------------------------------------------------- */

.prose {
  font-size: 17px;
  line-height: 1.75;
  color: var(--ink-mid);
}

.prose > * + * { margin-top: 1.15em; }

.prose p { max-width: 68ch; }

.prose h2,
.prose h3,
.prose h4 {
  color: var(--ink);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.25;
  margin-top: 1.8em;
}

.prose h2 { font-size: 26px; }
.prose h3 { font-size: 20px; }
.prose h4 { font-size: 18px; }

.prose a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--tan);
  text-underline-offset: 3px;
  transition: color 0.2s var(--ease);
}

.prose a:hover { color: var(--tan); }

.prose ul, .prose ol { padding-left: 1.3em; max-width: 66ch; }
.prose li + li { margin-top: 0.4em; }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }

.prose blockquote {
  border-left: 2px solid var(--tan);
  padding-left: 20px;
  color: var(--ink);
  font-size: 19px;
  line-height: 1.6;
}

.prose img {
  width: 100%;
  height: auto;
  border-radius: var(--r-img);
  margin-top: 1.6em;
  margin-bottom: 1.6em;
}

.prose figure { margin: 1.6em 0; }
.prose figure img { margin: 0; }

/* Two photos across, half each, sharing a row and a caption. */
.prose figure.pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
  gap: 12px;
}

/* Both halves are the same shape, so the row has a straight top and bottom
   — and `contain`, so what sits in that shape is the whole photograph.
   The two wrong answers were both tried: cropping to fill the box cut the
   top and bottom off anything portrait, and letting each photo keep its
   own height left a step of several hundred pixels beside a wide one.
   A margin around a photo costs nothing; half a photo costs half a photo. */
.prose figure.pair img {
  width: 100%;
  aspect-ratio: 4 / 3;
  height: auto;
  object-fit: contain;
  background: var(--subtle);
}

/* Two photos that both stand taller than they are wide: a landscape row
   would strand them, small, in the middle of it. */
.prose figure.pair-tall img { aspect-ratio: 3 / 4; }

.prose figure.pair figcaption { grid-column: 1 / -1; }

/* On a phone there isn't room for two, and half a photo is worth less than
   the whole of it one after the other. Nothing to line up with any more,
   so each photo goes back to its own shape at full width. */
@media (max-width: 599.98px) {
  .prose figure.pair { grid-template-columns: 1fr; }

  .prose figure.pair img {
    aspect-ratio: auto;
    object-fit: fill;
    background: none;
  }
}

.prose figcaption {
  font-size: 12px;
  color: var(--muted);
  margin-top: 10px;
}

.prose hr {
  border: 0;
  height: 1px;
  background: var(--line);
  margin: 2.4em 0;
}

.signoff {
  display: flex;
  flex-direction: column;
  gap: 16px;
  color: var(--muted);
  font-size: 14px;
}

.signoff-rule { width: 48px; height: 1px; background: var(--tan); }

.article-subscribe { margin-top: 8px; }

/* --- pager ---------------------------------------------------------------- */

.pager {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  border-top: 1px solid var(--line);
  padding-top: 24px;
}

.pager-link {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 46%;
}

.pager-next { text-align: right; align-items: flex-end; }

.pager-label {
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.pager-title {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  transition: color 0.2s var(--ease);
}

.pager-link:hover .pager-title { color: var(--tan); }

/* --- notices -------------------------------------------------------------- */

.page-narrow { min-height: 60vh; }

.notice {
  max-width: 560px;
  margin: 0 auto;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--warm);
  padding: 40px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.notice h1 {
  font-size: clamp(24px, 3.4vw, 34px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.15;
}

.notice p { color: var(--muted); }
.notice .pill { margin-top: 8px; }

.notice-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; }

/* --- flash messages ------------------------------------------------------- */

.flash-stack {
  position: fixed;
  top: calc(var(--nav-h) + 16px);
  right: var(--gutter);
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 360px;
}

.flash {
  padding: 12px 16px;
  border-radius: 10px;
  font-size: 13px;
  border: 1px solid var(--line);
  background: var(--warm);
  box-shadow: 0 12px 30px -18px rgba(4, 22, 38, 0.5);
}

.flash-error { border-color: #e5b9b4; color: #8c2b23; background: #fdf5f4; }
.flash-success { border-color: var(--tan); }

/* --- footer --------------------------------------------------------------- */

.footer {
  position: relative;
  margin-top: 96px;
  overflow: hidden;
}

.footer-mark {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  text-align: center;
  font-size: clamp(56px, 15vw, 170px);
  font-weight: 700;
  letter-spacing: -0.05em;
  line-height: 0.9;
  color: var(--line);
  white-space: nowrap;
  user-select: none;
}

.footer-panel {
  position: relative;
  padding-top: 128px;
  background: rgba(250, 249, 245, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-top: 1px solid transparent;
}

.footer-inner {
  max-width: 1248px;
  margin: 0 auto;
  padding: 0 var(--gutter) 40px;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.footer-top {
  display: flex;
  justify-content: space-between;
  gap: 48px;
  flex-wrap: wrap;
}

.footer-blurb {
  max-width: 320px;
  font-size: 13px;
  color: var(--muted);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.footer-mail {
  color: var(--ink-mid);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 3px;
}

.footer-mail:hover { color: var(--tan); }

.footer-links {
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--muted);
}

.footer-links a { transition: color 0.2s var(--ease); }
.footer-links a:hover { color: var(--tan); }

.footer-bottom {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 11px;
  color: var(--muted);
}

.bullet {
  width: 5px; height: 5px;
  border-radius: var(--r-pill);
  background: var(--line);
  display: block;
}

.footer-signin {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--muted);
  background: var(--warm);
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease),
              background 0.2s var(--ease), transform 0.2s var(--ease);
}

.footer-signin:hover {
  color: var(--ink);
  border-color: var(--tan);
  background: var(--subtle);
  transform: translateY(-1px);
}

.footer-signin .icon { width: 14px; height: 14px; }

/* --- reveal ---------------------------------------------------------------
   Content is visible by default and simply eases in on load. JavaScript
   hides only what is below the fold and reveals it on scroll, so a slow or
   failed script can never leave a blank page.
   -------------------------------------------------------------------------- */

@keyframes rise {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}

[data-reveal] { animation: rise 0.7s var(--ease) both; }

/* A light stagger down the two columns. */
.bio-words [data-reveal] { animation-delay: 0.08s; }
.bio-newsletter { animation-delay: 0.16s; }
.section-list > *:nth-child(2) { animation-delay: 0.06s; }
.section-list > *:nth-child(3) { animation-delay: 0.12s; }
.section-list > *:nth-child(n + 4) { animation-delay: 0.18s; }

.js [data-reveal].will-reveal {
  animation: none;
  opacity: 0;
  transform: translateY(20px);
}

.js [data-reveal].will-reveal.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal],
  .js [data-reveal].will-reveal {
    animation: none;
    opacity: 1;
    transform: none;
  }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

/* ==========================================================================
   Tablet — the sticky column unpins and the newsletter moves into the feed
   ========================================================================== */

@media (max-width: 1199.98px) {
  :root { --gutter: 32px; --nav-h: 65px; --top-pad: 120px; --stream-gap: 60px; }

  .container { flex-direction: column; gap: 56px; }

  .bio {
    position: static;
    height: auto;
    max-width: none;
    width: 100%;
    gap: 0;
  }

  .bio-heading { max-width: 18ch; }
  .bio-text { max-width: 62ch; }
  .bio-newsletter { display: none; }

  .divider { display: none; }

  .stream { max-width: none; width: 100%; }

  .newsletter-band { display: flex; }
}

/* ==========================================================================
   Phone — cards stack, photo on top with the date chip over it
   ========================================================================== */

@media (max-width: 809.98px) {
  :root { --gutter: 16px; --top-pad: 108px; --stream-gap: 48px; }

  .container { gap: 48px; }

  .brand-tag,
  .brand .sep { display: none; }

  .flash-stack { left: var(--gutter); right: var(--gutter); max-width: none; }

  .card {
    flex-direction: column;
    gap: 20px;
    padding: 16px;
  }

  .card-main { flex-direction: column; gap: 16px; }

  .card-photo,
  .card-lead .card-photo {
    order: -1;
    width: 100%;
    height: 200px;
  }

  /* The chip rides on the corner of the photo, as in the original layout. */
  .datebadge {
    position: absolute;
    top: 24px;
    right: 24px;
    background: var(--page);
    box-shadow: 0 6px 18px -10px rgba(4, 22, 38, 0.6);
  }

  .card-text { gap: 16px; }

  .card-title { -webkit-line-clamp: 3; }

  .card-meta {
    border-top: 1px solid var(--line);
    padding-top: 14px;
    font-size: 11px;
  }

  .newsletter-card { padding: 24px; }
  .notice { padding: 28px; }

  .prose { font-size: 16px; }
  .article { gap: 24px; }

  .pager { flex-direction: column; gap: 20px; }
  .pager-link { max-width: none; }
  .pager-next { text-align: left; align-items: flex-start; }

  .footer-top { gap: 28px; }
  .footer-panel { padding-top: 110px; }
}

/* Cards with no photo shouldn't reserve the overlay corner. */
.card:not(:has(.card-photo)) .datebadge { position: static; }


/* --- sharing a story ------------------------------------------------------ */

.article-narrow { max-width: 620px; }

.sharelink {
  font-size: 14px;
  color: var(--muted);
  text-align: center;
  margin-top: 8px;
}

.sharelink a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--tan);
  text-underline-offset: 3px;
}

.sharelink a:hover { color: var(--tan); }

.shareform {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-width: 460px;
}

.sharefield { display: flex; flex-direction: column; gap: 7px; }
.sharefield > span { font-size: 14px; font-weight: 500; }
.shareform .pill { align-self: flex-start; padding: 13px 26px; font-size: 15px; }

/* Explains the missing message box before anyone looks for it. */
.sharenote {
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted);
  border-top: 1px solid var(--line);
  padding-top: 16px;
  margin: 0;
}


/* --- which part of a cover photo survives the crop ------------------------
   A card is a fixed shape and a photograph is not, so something has to go.
   `object-fit: cover` throws away the edges and keeps the middle, which is
   wrong whenever the subject isn't in the middle — the roof of a ute, a
   face near the top. These pick the corner to keep instead.

   Classes rather than a style attribute on the img: the page's
   Content-Security-Policy has no 'unsafe-inline', so an inline style would
   be ignored by the browser and the crop would silently stay centred.
   -------------------------------------------------------------------------- */

.focus-top-left     { object-position: 0%   0%; }
.focus-top          { object-position: 50%  0%; }
.focus-top-right    { object-position: 100% 0%; }
.focus-left         { object-position: 0%   50%; }
.focus-center       { object-position: 50%  50%; }
.focus-right        { object-position: 100% 50%; }
.focus-bottom-left  { object-position: 0%   100%; }
.focus-bottom       { object-position: 50%  100%; }
.focus-bottom-right { object-position: 100% 100%; }
