/* ==========================================================================
   alexaneale.com — "Partition"
   A glazier's steel-framed glass wall. The grid gaps ARE the glazing bars:
   the ink of the container behind shows through, so bars are structural,
   never borders faked per element. Hierarchy comes from pane size and glass
   colour — never from type weight.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Archivo, self-hosted, variable on the width (62-125) and weight axes.

   The @font-face rules are NOT here. They are inlined in default.hbs, written
   with the {{asset}} helper, so the src is character-for-character the URL the
   <link rel="preload"> asks for. Declared here with a relative url() they
   resolved to the same file WITHOUT the helper's ?v= cache-buster: two URLs,
   one file, 90KB downloaded twice and a preload that bought nothing.
   -------------------------------------------------------------------------- */

@property --glow {
  syntax: "<color>";
  inherits: false;
  initial-value: rgba(0, 0, 0, 0);
}

:root {
  /* --- the only line ink: matte black glazing bar --- */
  --ink: #141414;
  --ink-soft: #45443f;

  /* --- clear + seeded white glass: the calm ground --- */
  --clear: #ecebe5;
  --clear-lit: #fffdf6;
  --frost: rgba(255, 255, 255, .86);   /* translucent white over the ink wall */

  /* --- saturated glass, reserved for what matters now --- */
  --cobalt: #1b4f9c;
  --cobalt-lit: #2a63b6;
  --amber: #c8801f;
  --amber-lit: #d78d24;
  --oxblood: #71232a;
  --oxblood-lit: #852b33;

  /* --- true bar thickness. Does NOT get thinner on mobile. --- */
  --bar: 9px;
  --mullion: 22px;           /* heavier bar bounding the bays */

  --pane-pad: clamp(1.25rem, 2.4vw, 2.25rem);
  --ease: cubic-bezier(.16, 1, .3, 1);
  --backlight: .95s;

  color-scheme: light;
  scrollbar-color: var(--ink) var(--clear);
}

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

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

body {
  margin: 0;
  background: var(--ink);
  color: var(--ink);
  font-family: "Archivo", "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  font-size: 1.0625rem;
  line-height: 1.6;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
}

/* The lit state is kept; only the travel to it is dropped. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }
}

::selection { background: var(--cobalt); color: #fff; }
::-webkit-scrollbar { width: 14px; height: 14px; }
::-webkit-scrollbar-track { background: var(--clear); }
::-webkit-scrollbar-thumb { background: var(--ink); border: 4px solid var(--clear); }
::-webkit-scrollbar-thumb:hover { background: var(--cobalt); }

input, textarea { caret-color: var(--amber); }

img { max-width: 100%; }
figure { margin: 0; }

/* ==========================================================================
   The wall
   ========================================================================== */

.wall {
  display: grid;
  gap: var(--mullion);
  padding: var(--bar);
  background: var(--ink);
  max-width: 1560px;
  margin: 0 auto;
  grid-template-columns: minmax(0, 1fr);
}

/* <main> is itself a run of bays inside the wall */
.wall > main,
.run {
  display: grid;
  gap: var(--mullion);
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
}

.bay {
  display: grid;
  gap: var(--bar);
  background: var(--ink);
  grid-template-columns: minmax(0, 1fr);  /* mobile: one column, true bar thickness */
}

/* grid and flex items must never be floored by intrinsic image width */
.bay > *, .reading > * { min-width: 0; }
.pane img { max-width: 100%; min-width: 0; }

/* ==========================================================================
   A pane
   ========================================================================== */

.pane {
  display: block;
  position: relative;
  isolation: isolate;
  margin: 0;
  padding: var(--pane-pad);
  background-color: var(--glass, var(--clear));
  background-image: radial-gradient(135% 108% at 50% 64%, var(--glow), transparent 74%);
  color: var(--glass-ink, #141414);
  transition:
    --glow var(--backlight) var(--ease),
    background-color var(--backlight) var(--ease);
}

/* hand-rolled sheet glass: shallow reeding, drawn under the type
 *
 * 90deg and a whole-pixel period are both load-bearing. This was previously
 * drawn at 95.5deg on an uneven 34px period, which read as dirt rather than
 * glass: off-axis, every stripe edge lands on a different sub-pixel offset on
 * each scanline, so the browser antialiases it differently row by row and the
 * ribbing smears. At these alphas -- 1 to 5 levels out of 255 -- that
 * antialiasing error is the same size as the effect itself, so what reached the
 * screen was mostly rendering noise. Axis-aligned on an even 6px period, the
 * edges fall on pixel boundaries and the reeding renders as reeding.
 *
 * Keep the period even and an integer. An odd or fractional one reintroduces
 * the drift at fractional browser zoom. */
.pane::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg,
      rgba(255, 255, 255, .020) 0 3px,
      rgba(0, 0, 0, .006) 3px 6px),
    radial-gradient(88% 62% at 22% 16%, rgba(255, 255, 255, .05), transparent 70%);
}

.pane > * { position: relative; }
.pane > :first-child { margin-top: 0; }
.pane > :last-child { margin-bottom: 0; }

/* --- glass colours --- */
.g-clear   { --glass: var(--clear);   --lit: var(--clear-lit);   --glass-ink: var(--ink); }
.g-cobalt  { --glass: var(--cobalt);  --lit: var(--cobalt-lit);  --glass-ink: #fff; }
.g-amber   { --glass: var(--amber);   --lit: var(--amber-lit);   --glass-ink: var(--ink); }
.g-oxblood { --glass: var(--oxblood); --lit: var(--oxblood-lit); --glass-ink: #fff; }

/* frosted: the pane that is not finished yet */
.g-frost {
  --glass: var(--frost);
  --lit: var(--frost);
  --glass-ink: var(--ink-soft);
}
.g-frost::before { opacity: .35; }

/* the void: a missing pane. Used by 404 and by deliberate holes in the wall. */
.pane--void {
  background: transparent;
  background-image: none;
  min-height: 8rem;
}
.pane--void::before { display: none; }

/* ==========================================================================
   Panes that are destinations
   ========================================================================== */

a.pane { text-decoration: none; color: var(--glass-ink, #141414); }

/* SIGNATURE: the glass brightens from within. No lift, no scale, no shadow. */
a.pane:hover,
a.pane:focus-visible,
.pane:focus-within { --glow: var(--lit); }

a.pane:hover { background-color: color-mix(in srgb, var(--glass) 72%, var(--lit)); }

/* current page: the pane floods with cobalt */
a.pane[aria-current="page"],
a.pane.is-current {
  --glass: var(--cobalt);
  --lit: var(--cobalt-lit);
  --glow: var(--cobalt-lit);
  --glass-ink: #fff;
}

/* focus: a two-tone ring, legible on clear glass AND on saturated glass */
a.pane:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
.text-link:focus-visible {
  outline: none;
}
a.pane::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  box-shadow: none;
}
a.pane:focus-visible::after {
  box-shadow:
    inset 0 0 0 3px var(--clear-lit),
    inset 0 0 0 8px var(--ink);
}

/* Anything focusable that is not a pane still gets a two-tone ring. */
:is(a, button, input, textarea, select, summary, [tabindex]):not(.pane):not(.text-link):focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--clear-lit);
}

/* ==========================================================================
   Type
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
  font-weight: 650;
  font-stretch: 116%;
  line-height: 1.1;
  letter-spacing: -.018em;
  margin: 0 0 .5em;
  text-wrap: balance;
}

.display {
  font-size: clamp(2.2rem, 5.4vw, 5.1rem);
  font-weight: 700;
  font-stretch: 120%;
  letter-spacing: -.03em;
  line-height: .95;
  margin: 0 0 .32em;
}
.display--sm { font-size: clamp(1.9rem, 4vw, 3.4rem); }

.lede {
  font-size: clamp(1.15rem, 1.55vw, 1.45rem);
  line-height: 1.42;
  margin: 0 0 .9em;
  font-weight: 500;
}

.pane p { max-width: 72ch; }
.pane .lede { max-width: 40ch; }

.meta {
  font-size: .8125rem;
  font-stretch: 112%;
  letter-spacing: .13em;
  text-transform: uppercase;
  font-weight: 600;
  margin: 0;
}
.g-clear .meta, .g-frost .meta { color: var(--ink-soft); }
.g-cobalt .meta, .g-oxblood .meta { color: rgba(255, 255, 255, .86); }

/* a bay with a stile: one narrow column, then a nested run of panes */
.panes--11 {
  display: grid;
  gap: var(--bar);
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
}

/* the section stile: a narrow pane naming the bay */
.stile {
  display: flex;
  align-items: flex-start;
  padding: var(--pane-pad) 1rem;
}
.stile span,
.stile a {
  font-size: 1rem;
  font-stretch: 118%;
  font-weight: 650;
  letter-spacing: .16em;
  text-transform: uppercase;
  line-height: 1;
  color: inherit;
}

/* inline links inside prose */
.text-link,
.column a:not(.pane):not(.kg-btn):not(.kg-bookmark-container),
.pane p a:not(.pane) {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
  text-decoration-color: var(--cobalt);
  transition: background-color var(--backlight) var(--ease);
}
.text-link:hover,
.column a:not(.pane):not(.kg-btn):not(.kg-bookmark-container):hover,
.pane p a:not(.pane):hover { background-color: rgba(27, 79, 156, .13); }

.g-cobalt .text-link, .g-oxblood .text-link,
.g-cobalt p a:not(.pane), .g-oxblood p a:not(.pane) { text-decoration-color: rgba(255, 255, 255, .7); }
.g-cobalt .text-link:hover, .g-oxblood .text-link:hover,
.g-cobalt p a:not(.pane):hover, .g-oxblood p a:not(.pane):hover { background-color: rgba(255, 255, 255, .16); }

.text-link:focus-visible,
.column a:not(.pane):focus-visible {
  background-color: var(--ink);
  color: var(--clear-lit);
  text-decoration-color: var(--amber);
  outline: none;
  box-shadow: 0 0 0 2px var(--ink), 0 0 0 5px var(--clear-lit);
}

/* ==========================================================================
   The elevation — the homepage's first bay
   ========================================================================== */

.transom { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.transom .pane { padding: .85rem 1rem; }
.transom .pane span {
  font-size: .9375rem;
  font-weight: 600;
  font-stretch: 112%;
  letter-spacing: .04em;
}

.portrait { display: flex; flex-direction: column; gap: 1.1rem; padding: var(--bar); }
.portrait img {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 0;
  object-fit: cover;
  object-position: 50% 22%;
  flex: 1 1 auto;
}
.portrait figcaption {
  padding: 0 calc(var(--pane-pad) - var(--bar)) calc(var(--pane-pad) - var(--bar));
  font-stretch: 116%;
  font-weight: 600;
  font-size: 1.05rem;
  letter-spacing: .01em;
}
.portrait figcaption small {
  display: block;
  font-size: .8125rem;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .84);
  margin-top: .3rem;
}

.identity { display: flex; flex-direction: column; justify-content: center; }
.identity p { font-size: clamp(1.05rem, 1.35vw, 1.28rem); line-height: 1.45; max-width: 46ch; }
.identity p:last-child { margin-bottom: 0; }

.about-pane { display: flex; flex-direction: column; justify-content: space-between; gap: 1.5rem; }

.contact-pane {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 8.5rem;
}
.contact-pane .big {
  font-size: clamp(1.6rem, 2.6vw, 2.4rem);
  font-stretch: 118%;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: .98;
  display: block;
}
.contact-pane p { font-size: .96rem; margin: .6rem 0 0; max-width: 30ch; }

/* ==========================================================================
   Post panes and page panes

   Every selector here is qualified with `.pane`. Ghost's {{post_class}} puts a
   bare `post` class on the <article> of a post, so an unqualified `.post`
   rule leaks onto the whole article: it was overriding the article's gap and
   padding, and setting every paragraph in the article -- including the ones
   inside the amber contact pane -- to .98rem/--ink-soft. That was the source
   of the 3.05:1 contrast failure. A post pane is always `a.pane...post`, so
   `.pane.post` names the component and nothing else.
   ========================================================================== */

.pane.post { display: grid; min-width: 0; grid-template-rows: auto 1fr; gap: .85rem; padding: var(--bar); align-content: start; }
.pane.post img { display: block; width: 100%; height: auto; background: var(--clear-lit); }
.pane.post .post-body { padding: calc(var(--pane-pad) - var(--bar)); padding-top: .2rem; display: flex; flex-direction: column; gap: .6rem; align-self: start; }
.pane.post--text { padding: var(--pane-pad); grid-template-rows: auto; }
.pane.post--text .post-body { padding: 0; }
/* A lead image is a teaser, not the artwork. Capped in height and anchored to
   its top edge, because her images are documents and screenshots whose
   headline is the first thing that must survive a crop. */
.pane.post--lead img { max-height: clamp(12rem, 30vh, 22rem); object-fit: cover; object-position: 50% 0; }
.pane.post h3 {
  font-size: clamp(1.28rem, 2vw, 1.85rem);
  margin: 0;
  font-weight: 650;
  letter-spacing: -.02em;
}
.pane.post--lead h3 { font-size: clamp(1.5rem, 2.8vw, 2.5rem); }
.pane.post p { margin: 0; font-size: .98rem; color: var(--ink-soft); max-width: 58ch; }
/* Excerpts come from Ghost and are whatever length she made them. Clamp the
   pane rather than the string, so a cut always lands on a whole line. */
.pane.post .post-body > p:not(.meta),
.about-pane .lede {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
.about-pane .lede { -webkit-line-clamp: 4; line-clamp: 4; }
.pane.post--lead .post-body > p:not(.meta) { -webkit-line-clamp: 4; line-clamp: 4; }
.pane.post .meta { margin: 0; }
.g-cobalt.pane.post p, .g-oxblood.pane.post p { color: rgba(255, 255, 255, .9); }

.tags { display: flex; flex-wrap: wrap; gap: .45rem; margin: 0; padding: 0; list-style: none; }
.tags li { display: contents; }
.tags a, .tags span {
  display: inline-block;
  font-size: .78rem;
  letter-spacing: .13em;
  text-transform: uppercase;
  font-weight: 650;
  border: 2px solid currentColor;
  padding: .22rem .55rem;
  color: inherit;
  text-decoration: none;
  line-height: 1.3;
}
.tags a:hover { background: var(--ink); color: var(--clear-lit); }

/* ==========================================================================
   Reading run — the wall frames the prose, it does not chop it
   ========================================================================== */

.reading {
  display: grid;
  gap: var(--bar);
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
}

.column {
  padding: clamp(1.5rem, 3.4vw, 3.25rem) var(--pane-pad);
  font-size: 1.1875rem;
  line-height: 1.72;
}
.column > p { max-width: 72ch; margin: 0 0 1.35em; }
.column > :last-child { margin-bottom: 0; }
.column > p:first-child {
  font-size: clamp(1.22rem, 1.9vw, 1.5rem);
  line-height: 1.45;
  font-weight: 500;
  max-width: 44ch;
  margin-bottom: 1.5em;
}
.column em, .column i { font-style: italic; }
.column strong, .column b { font-weight: 700; }

.column h2, .column h3, .column h4, .column h5, .column h6 {
  margin: 2em 0 .6em;
  max-width: 30ch;
}
.column h2 { font-size: clamp(1.55rem, 2.6vw, 2.1rem); }
.column h3 { font-size: clamp(1.3rem, 2vw, 1.6rem); }
.column h4 { font-size: 1.15rem; font-stretch: 120%; letter-spacing: .02em; }
.column h5, .column h6 {
  font-size: .85rem; letter-spacing: .14em; text-transform: uppercase;
}

.column ul, .column ol { max-width: 66ch; margin: 0 0 1.35em; padding-left: 1.3em; }
.column li { margin-bottom: .45em; }
.column li::marker { color: var(--cobalt); }

/* a horizontal rule becomes a real glazing bar across the pane */
.column hr {
  border: 0;
  height: var(--bar);
  background: var(--ink);
  margin: clamp(2rem, 4vw, 3.2rem) calc(-1 * var(--pane-pad));
}

.column pre {
  background: var(--ink);
  color: var(--clear-lit);
  padding: 1.1rem var(--pane-pad);
  margin: 1.8em calc(-1 * var(--pane-pad));
  overflow-x: auto;
  font-size: .9rem;
  line-height: 1.55;
}
.column code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .9em;
  background: rgba(20, 20, 20, .07);
  padding: .1em .3em;
}
.column pre code { background: none; padding: 0; }

.column table {
  width: 100%;
  border-collapse: collapse;
  margin: 1.8em 0;
  font-size: .95rem;
}
.column :is(th, td) { border-bottom: 2px solid var(--ink); padding: .55rem .6rem; text-align: left; }
.column th { font-weight: 700; font-stretch: 114%; }

/* --------------------------------------------------------------------------
   Post prose fills its pane.

   The 72ch measure held body copy to 587px inside a pane that is now 1283px
   wide, leaving roughly 620px of empty glass beside every line -- the pane was
   widened to square up with the hero, and the measure did not follow. Released
   here at the owner's request so the text runs the width of the glass.

   Scoped to .reading--full, which only post.hbs sets, so pages are untouched.
   Doubled on .column because the rules it overrides (.column > p, .pane p)
   share its specificity and would otherwise win on source order alone.

   Measured, not estimated: at this pane width a line holds about 140 characters
   of real prose, against the 45-75 that typography guidance recommends. Worth
   knowing that the 72ch cap this replaces was itself already running at about
   92 -- `ch` measures the 0 glyph, which is wider than the average letter, so
   72ch was never 72 characters. The honest fix for line length is a narrower
   pane, not a narrower measure inside a wide one; see the note on
   .reading--full > .column in the 1400px band.

   The opening paragraph is deliberately left capped at 44ch -- it is set large
   as a lede, and an over-long line costs most at large sizes.
   -------------------------------------------------------------------------- */

.reading--full > .column.column > :is(p, ul, ol, h2, h3, h4, h5, h6) { max-width: none; }
.reading--full > .column.column > p:first-child { max-width: 44ch; }

/* --------------------------------------------------------------------------
   Coloured words

   Ghost has no text-colour control, so the only inline colour the editor can
   produce is highlight, which arrives as <mark>. Unstyled it renders browser
   yellow on the clear glass, which reads as a fault; it is given the amber
   wash here instead.

   The two span utilities are the escape hatch for a genuinely coloured word,
   reachable only through an HTML card. They are deliberately just two. Amber
   is NOT among them: as text on clear glass it measures 2.7:1, which fails
   WCAG AA for body copy. Amber earns its place as a ground with ink on top of
   it -- which is exactly what the highlight below is -- and nowhere else.
   -------------------------------------------------------------------------- */

.column mark {
  background: color-mix(in srgb, var(--amber) 30%, transparent);
  color: inherit;
  padding: .06em .18em;
  border-radius: 1px;
  /* The wash must not swallow the descenders of the line above it. */
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.column .ink-cobalt  { color: var(--cobalt); }
.column .ink-oxblood { color: var(--oxblood); }

/* Inside the statement pane the ground is oxblood and the type is white, so
   both utilities would vanish and the amber wash would fight the glass. Colour
   is already doing its work in there: hand these back to the inherited white
   and let the wash go translucent instead. */
.column :is(blockquote, .kg-callout-card) :is(.ink-cobalt, .ink-oxblood) {
  color: inherit;
}
.column :is(blockquote, .kg-callout-card) mark {
  background: rgba(255, 255, 255, .22);
}

/* --------------------------------------------------------------------------
   The pull statement: the one saturated pane in a reading run, and the only
   place the "hierarchy from pane size and glass colour" rule operates inside
   prose. She reaches it from the editor -- a blockquote, or a callout card --
   so no hand-written markup is needed. Full-bleed to the pane edges and set
   into a glazing-bar reveal, exactly as a figure is.
   -------------------------------------------------------------------------- */
.statement,
.column blockquote,
.column .kg-callout-card {
  margin-inline: calc(-1 * var(--pane-pad));
  margin-block: clamp(1.8rem, 3.6vw, 2.9rem);
  border: 0;
  border-block: var(--bar) solid var(--ink);
  background: var(--oxblood);
  color: #fff;
  padding: clamp(1.6rem, 3.4vw, 2.6rem) var(--pane-pad);
  font-size: clamp(1.25rem, 2vw, 1.55rem);
  line-height: 1.45;
  font-weight: 500;
  max-width: none;
}
.statement p,
.column blockquote p { margin: 0 0 .6em; max-width: 46ch; }
.statement > :last-child,
.column blockquote > :last-child { margin-bottom: 0; }
.column blockquote :is(cite, footer) {
  display: block;
  margin-top: .8em;
  font-size: .62em;
  font-style: normal;
  font-weight: 600;
  font-stretch: 112%;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .86);
}
/* links and code have to survive the dark glass */
.column :is(blockquote, .kg-callout-card) a:not(.pane):not(.kg-btn):not(.kg-bookmark-container) {
  text-decoration-color: rgba(255, 255, 255, .7);
}
.column :is(blockquote, .kg-callout-card) a:not(.pane):not(.kg-btn):not(.kg-bookmark-container):hover {
  background-color: rgba(255, 255, 255, .16);
}
.column :is(blockquote, .kg-callout-card) code { background: rgba(255, 255, 255, .16); }
.column :is(blockquote, .kg-callout-card) :is(b, strong) { font-weight: 700; }

/* --------------------------------------------------------------------------
   A sparse page is a frosted pane, not a thin one. Content-driven: if the
   reading pane holds fewer than five blocks it frosts over, and clears by
   itself the moment there is something to read.
   -------------------------------------------------------------------------- */
.column--auto:not(:has(> :nth-child(5))) {
  --glass: var(--frost);
  --lit: var(--frost);
  --glass-ink: var(--ink-soft);
  min-height: clamp(15rem, 32vh, 24rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.column--auto:not(:has(> :nth-child(5)))::before { opacity: .35; }
.column--auto:not(:has(> :nth-child(5))) > p:first-child { color: var(--ink); }

/* ==========================================================================
   Ghost editor cards (kg-*)
   A figure is two panes with a real bar between them. Quiet enough to
   repeat thirty-three times in one post.
   ========================================================================== */

.column :is(figure, .kg-card) { margin: 0; }

.column :is(.kg-image-card, .kg-gallery-card, .kg-embed-card, .kg-video-card,
            .kg-audio-card, .kg-file-card, .kg-bookmark-card, .kg-product-card,
            .kg-toggle-card, .kg-callout-card, .kg-button-card, .kg-header-card,
            .kg-code-card, .kg-nft-card) {
  margin-block: clamp(1.8rem, 3.6vw, 2.9rem);
}

/* image + gallery + embed: full-bleed of the reading pane, set into an ink reveal */
.column :is(.kg-image-card, .kg-gallery-card, .kg-video-card, .kg-embed-card) {
  margin-inline: calc(-1 * var(--pane-pad));
  padding: var(--bar) 0;
  background: var(--ink);
  display: grid;
  gap: var(--bar);
  grid-template-columns: minmax(0, 1fr);
}

.column .kg-image,
.column .kg-image-card img,
.column .kg-gallery-image img,
.column .kg-video-card video {
  display: block;
  width: 100%;
  height: auto;
  background: var(--clear-lit);
}

/* .pane.post img no longer reaches into the article, so prose images that are
   not inside a Ghost card still need a rule of their own. */
.column img { display: block; max-width: 100%; height: auto; }

.column .kg-gallery-container { display: grid; gap: var(--bar); }
.column .kg-gallery-row { display: flex; gap: var(--bar); }
.column .kg-gallery-image { display: flex; min-width: 0; }
.column .kg-gallery-image img { object-fit: cover; }

/* captions: their own pane of clear glass under the image */
.column figcaption {
  background: var(--clear);
  padding: .85rem var(--pane-pad);
  font-size: .9375rem;
  line-height: 1.5;
  color: var(--ink-soft);
  max-width: none;
  text-align: left;
}
.column figcaption :is(b, strong) { color: var(--ink); font-weight: 650; }
.column figcaption a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--cobalt);
  text-underline-offset: .18em;
}
.column figcaption a:hover { background: rgba(27, 79, 156, .13); }
.column figcaption p { margin: 0; max-width: none; }

/* Ghost's own width modifiers. In a wall a pane cannot spill past its glazing
   bar, so wide and full both resolve to the full width of the reading pane —
   the widest honest answer. */
.column :is(.kg-width-wide, .kg-width-full) { margin-inline: calc(-1 * var(--pane-pad)); }
.column .kg-width-full img { width: 100%; }

/* embeds keep their aspect ratio and never overflow */
.column .kg-embed-card { padding: var(--bar); }
.column .kg-embed-card :is(iframe, video) {
  display: block;
  width: 100%;
  max-width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  border: 0;
  background: var(--ink);
}

/* bookmark card: a small pane of its own */
.column .kg-bookmark-card { margin-inline: calc(-1 * var(--pane-pad)); }
.column .kg-bookmark-container {
  display: flex;
  flex-wrap: wrap;
  text-decoration: none;
  color: var(--ink);
  background: var(--clear-lit);
  border: var(--bar) solid var(--ink);
}
.column .kg-bookmark-content { flex: 1 1 15rem; padding: 1.1rem 1.3rem; min-width: 0; }
.column .kg-bookmark-title { font-weight: 700; font-stretch: 116%; margin-bottom: .3rem; }
.column .kg-bookmark-description { font-size: .95rem; color: var(--ink-soft); margin-bottom: .6rem; }
.column .kg-bookmark-metadata { font-size: .8rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-soft); display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.column .kg-bookmark-icon { width: 18px; height: 18px; }
.column .kg-bookmark-thumbnail { flex: 0 1 14rem; }
.column .kg-bookmark-thumbnail img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* callout, toggle, header, button */
/* `.column :is(figure, .kg-card) { margin: 0 }` is declared after the shared
   statement rule above and would flatten the callout's break-out, so the
   card's own margins are restated here. */
.column .kg-callout-card {
  display: flex;
  gap: .9rem;
  align-items: flex-start;
  margin-inline: calc(-1 * var(--pane-pad));
}
.column .kg-callout-emoji { flex: none; line-height: 1.45; }
.column .kg-callout-text { margin: 0; max-width: 46ch; }
.column .kg-toggle-card { background: var(--clear-lit); padding: 1.1rem 1.3rem; }
.column .kg-toggle-heading { display: flex; justify-content: space-between; align-items: center; gap: 1rem; }
.column .kg-toggle-heading-text { margin: 0; font-size: 1.1rem; }
.column .kg-toggle-card-icon { width: 20px; height: 20px; flex: none; }
.column .kg-toggle-content { margin-top: .8rem; }
.column .kg-toggle-card[data-kg-toggle-state="close"] .kg-toggle-content { display: none; }
.column .kg-header-card { text-align: center; padding: clamp(2rem, 5vw, 3.5rem) 1rem; background: var(--clear-lit); }
.column .kg-button-card { display: flex; }
.column .kg-button-card.kg-align-center { justify-content: center; }
.column .kg-btn {
  display: inline-block;
  font-weight: 700;
  font-stretch: 116%;
  letter-spacing: .04em;
  color: var(--ink);
  background: var(--amber);
  border: 2px solid var(--ink);
  padding: .8rem 1.5rem;
  text-decoration: none;
}
.column .kg-btn:hover { background: var(--amber-lit); }

/* ==========================================================================
   Article furniture
   ========================================================================== */

.article-head { display: flex; flex-direction: column; justify-content: space-between; gap: 1.6rem; }
.article-head .display { max-width: 16ch; }
.head-foot { display: flex; flex-wrap: wrap; align-items: center; gap: .9rem 1.6rem; }

.byline { display: flex; flex-direction: column; justify-content: flex-end; gap: .3rem; }
.byline .lede { font-size: clamp(1.3rem, 2.2vw, 1.9rem); font-stretch: 118%; font-weight: 700; letter-spacing: -.02em; margin: 0 0 .35rem; max-width: none; }
.byline p { font-size: .98rem; margin: 0; color: rgba(255, 255, 255, .9); max-width: 34ch; }
.byline .backlink-wrap { margin-top: 1.1rem; }
.backlink { display: inline-flex; align-items: center; gap: .5rem; font-weight: 600; }
.backlink svg { flex: none; }

/* the hero: the feature image as its own pane in the wall */
/* No padding. The bar of ink this used to carry was invisible against the ink
   wall behind it, so it never read as a frame -- it just pushed the image 9px
   right of the pane above and looked like a misalignment. The gap still parts
   the image from its caption. */
.hero { background: var(--ink); display: grid; gap: var(--bar); grid-template-columns: minmax(0, 1fr); }
.hero img { display: block; width: 100%; height: auto; background: var(--clear-lit); }
.hero figcaption {
  background: var(--clear);
  padding: .85rem var(--pane-pad);
  font-size: .9375rem;
  color: var(--ink-soft);
}
.hero figcaption a { color: var(--ink); text-decoration-color: var(--cobalt); }

/* --- the photo pane ---
   A page's feature image is a portrait of a person, not a landscape banner:
   492px wide is typical, so the hero's 9-column slot only ever upscaled it into
   softness. Here it takes a pane of its own, image flush to a bar of glass on
   every side, exactly as a post pane frames its thumbnail. --- */
.photo-pane { padding: var(--bar); }
.photo-pane img { display: block; width: 100%; height: auto; background: var(--clear-lit); }
.photo-pane figcaption {
  padding: .8rem calc(var(--pane-pad) - var(--bar)) calc(var(--pane-pad) - var(--bar));
  font-size: .9375rem;
  line-height: 1.5;
  color: var(--ink-soft);
}
.photo-pane figcaption a { color: var(--ink); text-decoration-color: var(--cobalt); }

/* ==========================================================================
   Pagination
   ========================================================================== */

.pagination { display: grid; gap: var(--bar); grid-template-columns: minmax(0, 1fr); background: var(--ink); }
.pagination .pane { display: flex; align-items: center; gap: .7rem; }
.page-number { justify-content: center; font-weight: 650; font-stretch: 114%; letter-spacing: .1em; text-transform: uppercase; font-size: .85rem; }
.older-posts { justify-content: flex-end; }
.pagination svg { width: 20px; height: 20px; flex: none; }
.pagination a span { font-weight: 650; font-stretch: 112%; }

/* ==========================================================================
   Footer
   ========================================================================== */

.wordmark {
  font-size: clamp(1.5rem, 3.4vw, 2.9rem);
  font-stretch: 122%;
  font-weight: 700;
  letter-spacing: -.02em;
  margin: 0;
  line-height: 1;
}
.footnote { font-size: .9rem; color: var(--ink-soft); margin: .7rem 0 0; max-width: 46ch; }
.link-pane { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.link-pane span { font-weight: 600; font-stretch: 112%; }
.link-label { display: flex; flex-direction: column; gap: .2rem; min-width: 0; }
/* the ORCID iD itself, under the label: the token an academic actually scans */
.link-id {
  font-size: .78rem;
  font-weight: 600;
  font-stretch: 108%;
  letter-spacing: .1em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}
.link-pane svg { flex: none; width: 20px; height: 20px; }
.wordmark-pane { display: flex; flex-direction: column; justify-content: flex-end; }
.colophon { font-size: .8rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft); display: flex; flex-wrap: wrap; gap: .6rem 1.4rem; }
.colophon a { color: inherit; }

/* ==========================================================================
   Utilities
   ========================================================================== */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 50;
  background: var(--amber);
  color: var(--ink);
  padding: .8rem 1.2rem;
  font-weight: 700;
  text-decoration: none;
}
.skip:focus { left: var(--bar); top: var(--bar); box-shadow: 0 0 0 4px var(--ink); }

.arrow {
  width: .82em;
  height: .82em;
  vertical-align: -.06em;
  margin-left: .12em;
  flex: none;
}

.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ==========================================================================
   The wall opens up at 900px. Below that: one column, same bar thickness.
   ========================================================================== */

@media (min-width: 900px) {
  .bay { grid-template-columns: repeat(12, minmax(0, 1fr)); }

  .transom { grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); grid-template-columns: none; }
  .transom .pane { padding: .95rem var(--pane-pad); }

  .stile {
    grid-column: span 1;
    grid-row: 1 / -1;
    writing-mode: vertical-rl;
    padding: var(--pane-pad) 1rem;
    justify-content: flex-start;
  }

  /* --- the elevation --- */
  .bay--elevation {
    grid-template-rows: minmax(min-content, 1.55fr) minmax(min-content, 1fr);
    min-height: clamp(520px, 74vh, 760px);
  }
  .bay--elevation .portrait     { grid-column: 1 / 5;  grid-row: 1 / 3; }
  .bay--elevation .identity     { grid-column: 5 / 13; grid-row: 1; }
  .bay--elevation .about-pane   { grid-column: 5 / 10; grid-row: 2; }
  .bay--elevation .contact-pane { grid-column: 10 / 13; grid-row: 2; }

  /* nothing to put in the third pane: contact takes the rest of the row */
  .bay--elevation.is-lean .contact-pane { grid-column: 5 / 13; grid-row: 2; }
  .bay--elevation.is-lean.is-portraitless .contact-pane { grid-column: 1 / 13; grid-row: 2; }

  /* no portrait uploaded: the identity takes the whole elevation */
  .bay--elevation.is-portraitless .identity     { grid-column: 1 / 9;  grid-row: 1; }
  .bay--elevation.is-portraitless .about-pane   { grid-column: 1 / 6;  grid-row: 2; }
  .bay--elevation.is-portraitless .contact-pane { grid-column: 6 / 13; grid-row: 2; }

  /* --- panes laid in an unequal repeating rhythm ---
     Six spans that pair to a full row: 7+5, 4+8, 6+6. A pane that lands alone
     on the last row widens to fill it, so the wall never shows a hole it did
     not mean. --- */
  .panes > .pane:not(.stile):nth-child(6n + 1) { grid-column: span 7; }
  .panes > .pane:not(.stile):nth-child(6n + 2) { grid-column: span 5; }
  .panes > .pane:not(.stile):nth-child(6n + 3) { grid-column: span 4; }
  .panes > .pane:not(.stile):nth-child(6n + 4) { grid-column: span 8; }
  .panes > .pane:not(.stile):nth-child(6n + 5) { grid-column: span 6; }
  .panes > .pane:not(.stile):nth-child(6n + 6) { grid-column: span 6; }
  .panes > .pane:not(.stile):nth-child(odd):last-child { grid-column: span 12; }

  /* the same rhythm, eleven wide, beside a stile */
  .bay--stiled { grid-template-columns: minmax(0, 1fr) minmax(0, 11fr); }
  .bay--stiled > .stile { grid-column: 1; grid-row: 1; }
  .panes--11 { grid-template-columns: repeat(11, minmax(0, 1fr)); }
  .panes--11 > .pane:nth-child(6n + 1) { grid-column: span 6; }
  .panes--11 > .pane:nth-child(6n + 2) { grid-column: span 5; }
  .panes--11 > .pane:nth-child(6n + 3) { grid-column: span 4; }
  .panes--11 > .pane:nth-child(6n + 4) { grid-column: span 7; }
  .panes--11 > .pane:nth-child(6n + 5) { grid-column: span 5; }
  .panes--11 > .pane:nth-child(6n + 6) { grid-column: span 6; }
  .panes--11 > .pane:nth-child(odd):last-child { grid-column: span 11; }

  /* --- the reading run shares one left edge and one width with the title
     pane above it: columns 1-7 of the same twelve. --- */
  .bay--article { grid-template-rows: minmax(0, 1fr); min-height: clamp(340px, 44vh, 520px); }
  .bay--article .article-head { grid-column: 1 / 7; }
  .bay--article .byline { grid-column: 7 / 13; }

  .reading { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .reading > * { grid-column: 1 / 7; }
  .reading > .reading--wide { grid-column: 1 / 10; }
  /* a frosted, still-sparse page is not prose: it takes a wider pane */
  .reading:not(.reading--aside) > .column--auto:not(:has(> :nth-child(5))) { grid-column: 1 / 10; }

  .hero { grid-column: 1 / 10; }

  /* --- prose and portrait, side by side on one line. The prose keeps the
     columns 1-7 it shares with the title pane above it; the photo takes three
     of the four that were standing empty beside it. --- */
  .reading--aside > .column { grid-column: 1 / 7; grid-row: 1; }
  .reading--aside > .photo-pane { grid-column: 7 / 10; grid-row: 1; align-self: start; }

  /* --- page and listing heads --- */
  .bay--head .head-pane { grid-column: 1 / 10; }
  .bay--head > .contact-pane { grid-column: 10 / 13; }
  .bay--head-full .head-pane { grid-column: 1 / 13; }

  .pagination { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .pagination .newer-posts { grid-column: 1 / 5; }
  .pagination .page-number { grid-column: 5 / 9; }
  .pagination .older-posts { grid-column: 9 / 13; }

  .bay--foot { grid-template-rows: repeat(3, auto) auto; }
  .bay--foot .wordmark-pane { grid-column: 1 / 7; grid-row: 1 / 4; }
  .bay--foot .link-pane { grid-column: 7 / 13; }
  .bay--foot .colophon { grid-column: 1 / 13; }

  .bay--404 { grid-template-rows: auto auto; min-height: clamp(420px, 60vh, 640px); }
  .bay--404 .void-a { grid-column: 1 / 5; grid-row: 1 / 3; }
  .bay--404 .lost { grid-column: 5 / 13; grid-row: 1; }
  .bay--404 .lost-links { grid-column: 5 / 10; grid-row: 2; }
  .bay--404 > .contact-pane { grid-column: 10 / 13; grid-row: 2; }
}

/* On a 375px viewport a 20px pad on each side is 11% of the whole screen, and
   it comes straight off the measure. The bars stay at true thickness; only the
   pane's own inset gives way. */
@media (max-width: 520px) {
  :root { --pane-pad: 1rem; }
}

@media (max-width: 899px) {
  .stile { padding: 1rem var(--pane-pad); }
  .stile span, .stile a { font-size: .85rem; }
  .portrait { min-height: 0; }
  .portrait img { aspect-ratio: 4 / 5; height: auto; }
  .bay--elevation .identity { padding-block: 2rem; }
  .column { font-size: 1.0625rem; }
  .byline { padding-block: 1.5rem; }
  .pane--void { display: none; }
  .column .kg-gallery-row { flex-direction: column; }

  /* Stacked, a portrait at full bleed is taller than the phone and pushes every
     word of the page below the fold. Hold it to a readable width instead of
     cropping: the photo is of a person, and where to cut a person is not a
     decision a stylesheet should be making sight-unseen. */
  .photo-pane { max-width: 20rem; }
}

/* --------------------------------------------------------------------------
   The measure.

   Six of twelve columns is a comfortable measure only around 1400px. It is
   non-monotonic everywhere else: 768px reads at 72ch, then 900px squeezes to
   43ch the moment the two-column wall engages, which is exactly the band most
   laptops sit in. So the reading column takes more of the twelve as the wall
   narrows, and a max-width holds it at 72ch when the columns themselves grow.

   The title pane above the run moves with it, span for span and cap for cap,
   so the two still share one left edge and one width -- the whole point of the
   pane. The twelve-column wall grid itself is untouched.

   `ch` is Archivo's own zero-width, so a cap written in ch is measured against
   whatever font-size the element actually has. .article-head sits at the body
   size (1.0625rem) and .column at the prose size, so where the two differ the
   head's cap is scaled by the ratio between them.
   -------------------------------------------------------------------------- */

/* 900-1199: nine of twelve, and the prose keeps the smaller step. Stepping the
   type up at 900 while the pane got narrower was what made 900px the worst
   width on the site; the step now waits until there is width to spend it on. */
@media (min-width: 900px) and (max-width: 1199.98px) {
  .column { font-size: 1.0625rem; }

  .bay--article .article-head { grid-column: 1 / 10; }
  .bay--article .byline       { grid-column: 10 / 13; }

  .reading > *     { grid-column: 1 / 10; }
  .reading > .hero { grid-column: 1 / 12; }
  .reading > .column--auto:not(:has(> :nth-child(5))) { grid-column: 1 / 12; }

  /* head and prose are both at 1.0625rem here, so one cap serves both */
  .reading > .column,
  .bay--article .article-head { max-width: calc(72ch + 2 * var(--pane-pad)); }
}

/* 1200-1399: eight of twelve, prose at its full size */
@media (min-width: 1200px) and (max-width: 1399.98px) {
  .bay--article .article-head { grid-column: 1 / 9; }
  .bay--article .byline       { grid-column: 9 / 13; }

  .reading > *     { grid-column: 1 / 9; }
  .reading > .hero { grid-column: 1 / 12; }
  .reading > .column--auto:not(:has(> :nth-child(5))) { grid-column: 1 / 12; }

  .reading > .column          { max-width: calc(72ch + 2 * var(--pane-pad)); }
  .bay--article .article-head { max-width: calc(80.47ch + 2 * var(--pane-pad)); } /* 72ch of 1.1875rem, measured in 1.0625rem */
}

/* 1400 and up: seven of twelve. The columns are wide enough by now that the
   span alone lands the measure; no cap is needed and none is applied, so the
   title pane and the reading column are the same grid span exactly. */
@media (min-width: 1400px) {
  .bay--article .article-head { grid-column: 1 / 8; }
  .bay--article .byline       { grid-column: 8 / 13; }

  .reading > *     { grid-column: 1 / 8; }
  /* The hero takes the article head's span, not a wider one: image, prose and
     title then share both edges, and the article reads as one column. */
  .reading > .hero { grid-column: 1 / 8; }
  .reading > .column--auto:not(:has(> :nth-child(5))) { grid-column: 1 / 11; }

  /* A post's prose pane takes the hero's span exactly, so image and words share
     one right edge and read as a single article -- the "More posts" bay below
     is a different thing and keeps its own full width. Only up here: this is
     the band that drops the 72ch cap.

     Both sit on the article head's span (1/8) rather than anything wider, and
     that is what keeps the line length honest: released of its cap the prose
     fills this pane at roughly 95 characters a line, where at 1/11 it ran to
     140. Below 1400 the cap holds the pane at the measure instead.

     It must track .reading > .hero above. If that span moves, move this. */
  .reading--full > .column { grid-column: 1 / 8; }
}

/* very wide: the measure can afford a little more size */
@media (min-width: 1400px) {
  .column { font-size: 1.25rem; }
}
