/* Red Hills QC — Brand Kit v1, the "Datum" system (DAA-342).
   Layout is DAA-341's and stays; this file replaces the placeholder tokens with the real ones
   and restyles every surface to the system below.

   A datum is the reference surface a measurement is taken from. The site is built like a
   controlled engineering document: hairline rules instead of shadows, square edges instead of
   rounded cards, metadata set like a drawing's title block, and nothing on the page that is not
   carrying information.

   Three rules the audit behind this ticket earned (docs/research/audience-and-design-language.md):

   1. NO HERO PHOTOGRAPHY, anywhere. 18 of the 24 competitors audited open on a stock photo, and
      most of the ones that went dark got there by dimming one until the text showed. Only three
      of the 24 are built from type instead, and only one of those, ACSI, is a dark consultancy.
      Photography is the single thing that makes the rest interchangeable. The page carries
      itself on type and rules.
   2. THE ACCENT IS A FILL, NOT A COLOUR SCHEME. It marks the primary action and the current
      page, the way red marks the out-of-limit point on a control chart — and nothing else.
      Accent-as-text uses --accent-text, which is lighter; see the contrast note on the tokens.
   3. MONO IS FOR DATA. Dates, reading time, counts, code. Not labels, not headings, not
      atmosphere — monospace used as a costume for "technical" is the tell of a page that is
      imitating engineering rather than doing it. */

/* ----------------------------------------------------------------------------------------
   Type — self-hosted, no runtime CDN (ticket acceptance criterion).

   Archivo and IBM Plex are both SIL OFL 1.1; see assets/fonts/OFL-NOTICE.txt. Archivo and Plex
   Sans are variable fonts, so one file each covers every weight used — three files, ~95 KB
   total. `font-display: swap` so text is readable before the face lands.
   ---------------------------------------------------------------------------------------- */
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-variable-latin.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/ibm-plex-sans-variable-latin.woff2') format('woff2-variations');
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('../fonts/ibm-plex-mono-500-latin.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

:root {
  /* --- palette ---------------------------------------------------------------------------
     Neutrals are deliberately cool against a warm accent. A blueprint, a steel bench and a
     CMM room are all cold light; warming the greys to match the accent would make the page
     cosy, which is the one thing this audience does not read as competence.

     Contrast, measured rather than assumed, all against --bg-read (the worst case, because it
     is the lightest surface body text sits on):
       --text on --bg-read   14.76:1   (AA needs 4.5, AAA needs 7)
       --text-2 on --bg-read  6.29:1   (AA for normal text)
     And the accent, which is why there are two of it:
       --accent on --bg       4.02:1   — fails AA as text, so it is never used as text
       #fff on --accent       4.87:1   — passes, so white-on-accent buttons are fine
       --accent-text on --bg  4.98:1   — passes, so this is the one used for accent-coloured text
       --accent-text on --bg-read 4.17:1 — FAILS. So links inside the reading surface are --text
                                         with an underline, not accent; see .post-content a.
       #fff on --accent-hover 5.92:1   — hover goes DARKER, so the button keeps passing under the
                                         pointer. A lighter hover (#e3674a) measured 3.33:1.
  */
  --accent: #c8442a;          /* fills: primary button, current page. Never text. */
  --accent-text: #d9563a;     /* accent as text on a dark ground */
  --accent-hover: #b33a22;    /* hover for accent fills; darker, so white text still passes */
  --bg: #0b0c0e;              /* canvas */
  --bg-card: #14171a;         /* surface: sidebar, contact card, grid cells */
  --bg-read: #1c2024;         /* lifted reading surface, long-form only */
  --text: #f2f3f5;
  --text-2: #9ba1a8;
  --border: #262b30;          /* hairline */
  --line: #3a4148;            /* construction line: secondary borders, text-link underlines. 1.89:1 on
                                 --bg, so it never carries meaning alone (DESIGN.md) */

  --font-display: var(--gh-font-heading, 'Archivo', ui-sans-serif, system-ui, 'Segoe UI', sans-serif);
  --font-body: var(--gh-font-body, 'IBM Plex Sans', ui-sans-serif, system-ui, 'Segoe UI', sans-serif);
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --sidebar-w: 248px;
  /* The page's width, not the measure. A Post's line length is held separately on the reading
     surface; see "The measure" under single post (DAA-352). */
  --content-w: 820px;
  --gutter: clamp(20px, 4vw, 48px);
  /* The system is square. Kept as a token so any exception has to be deliberate. */
  --radius: 0;
}

*, *::before, *::after { box-sizing: border-box; }
html { color-scheme: dark; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.65 var(--font-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* --- browser surfaces ---
   Selection, caret, scrollbars and the focus ring ship with defaults that belong to no design
   system. On a page this quiet they are a large share of what a Visitor actually sees move. */
::selection { background: var(--accent); color: #fff; }
html { caret-color: var(--accent-text); scrollbar-color: var(--border) var(--bg); scrollbar-width: thin; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--border); border: 3px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: #333a40; }
:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }

a { color: inherit; text-decoration: none; }
a:hover { color: var(--accent-text); }
img { max-width: 100%; height: auto; display: block; }

h1, h2, h3 {
  font-family: var(--font-display);
  line-height: 1.1;
  margin: 0 0 .5em;
  font-weight: 700;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
h1 { font-size: clamp(2rem, 4.6vw, 3.1rem); }
h2 { font-size: clamp(1.3rem, 2.4vw, 1.5rem); letter-spacing: -0.02em; }
h3 { font-size: 1.125rem; font-family: var(--font-body); font-weight: 600; letter-spacing: -0.01em; }
p { margin: 0 0 1em; }
small { color: var(--text-2); font-size: .85rem; }

/* Data, and only data: dates, reading time, counts, code. */
.data, time, .reading-time, .post-card-meta, .post-meta {
  font-family: var(--font-mono);
  font-size: .75rem;
  font-weight: 500;
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
}

.skip { position: absolute; left: -999px; top: 0; background: var(--accent); color: #fff; padding: .5rem 1rem; z-index: 100; }
.skip:focus { left: 0; }

/* --- layout --- */
.sidebar {
  position: fixed; inset: 0 auto 0 0; width: var(--sidebar-w);
  background: var(--bg-card); border-right: 1px solid var(--border);
  padding: 30px 22px; display: flex; flex-direction: column; gap: 30px; overflow-y: auto;
}
.main {
  margin-left: var(--sidebar-w);
  padding: clamp(36px, 6vw, 76px) var(--gutter);
  max-width: calc(var(--content-w) + 2 * var(--gutter));
}

/* --- sidebar --- */
.brand { display: flex; flex-direction: column; gap: 12px; }
.brand-mark { width: 100%; max-width: 172px; height: auto; }
.brand-logo { max-height: 44px; width: auto; }
/* Only shown once the site is renamed away from "Red Hills QC"; see partials/brand.hbs. */
.brand-wordmark {
  font-family: var(--font-display); font-size: 1.15rem; font-weight: 700;
  letter-spacing: .02em; text-transform: uppercase; color: var(--text);
}
.brand-tagline { font-size: .78rem; color: var(--text-2); letter-spacing: .01em; }

.nav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.nav-link {
  display: block; padding: 9px 12px; font-size: .93rem; color: var(--text-2);
  border-left: 1px solid var(--border); margin-left: 1px;
  transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}
.nav-link:hover { color: var(--text); border-left-color: var(--text-2); background: rgba(255,255,255,.02); }
/* The current page is the one place in the navigation the accent is allowed: it is a state,
   not an ornament. 1px, because a thicker coloured bar is the cheap version of this. */
.nav-link.is-current { color: var(--text); border-left-color: var(--accent); background: rgba(255,255,255,.03); }
.nav-heading {
  display: block; font-family: var(--font-display); font-size: .68rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text-2); padding: 0 12px 8px;
}
.nav-social { border-top: 1px solid var(--border); padding-top: 18px; }
.sidebar-cta { margin-top: auto; text-align: center; }

/* --- top bar (900px and below) ---
   Hidden on a laptop, where the sidebar is always there. Below the breakpoint the sidebar is
   off-screen, and before this bar the first screen of every page but Home carried no brand at
   all — only a menu button floating over the content. */
.topbar { display: none; }
.topbar .brand-mark { width: 148px; max-width: none; }
.topbar .brand-logo { max-height: 30px; }
.topbar .brand-wordmark { font-size: 1rem; }

.nav-toggle {
  width: 44px; height: 44px; border: 1px solid var(--border); background: transparent;
  cursor: pointer; padding: 12px; display: flex; flex-direction: column; justify-content: space-between;
}
.nav-toggle:hover { border-color: var(--text-2); }
/* Three 1px rules in an 18px box sit at 0, 8.5 and 17px, so ±8.5px brings the outer two onto
   the centre line to cross. */
.nav-toggle span { display: block; height: 1px; background: var(--text); transition: transform .2s cubic-bezier(.2,.8,.25,1), opacity .15s ease; }
.nav-toggle[aria-expanded='true'] span:nth-child(1) { transform: translateY(8.5px) rotate(45deg); }
.nav-toggle[aria-expanded='true'] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded='true'] span:nth-child(3) { transform: translateY(-8.5px) rotate(-45deg); }

/* --- buttons, labels --- */
.btn {
  display: inline-block; padding: 11px 18px;
  border: 1px solid var(--border); background: transparent; color: var(--text);
  font-family: var(--font-display); font-size: .88rem; font-weight: 600; letter-spacing: .02em;
  cursor: pointer; transition: border-color .15s ease, background-color .15s ease;
}
.btn:hover { border-color: var(--text-2); color: var(--text); background: rgba(255,255,255,.03); }
.btn-accent { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-accent:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
.btn[disabled], .btn[aria-disabled='true'] { opacity: .45; cursor: not-allowed; }

.badge {
  display: inline-block; font-family: var(--font-display); font-size: .7rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  padding: 4px 9px; border: 1px solid var(--border); color: var(--text-2);
}
/* The Kind is classification, not measurement, so it is display type rather than mono — and
   it is not the accent, because the accent is a fill. */
.kind {
  font-family: var(--font-display); font-size: .68rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--text);
}
.section-link { font-size: .78rem; color: var(--text-2); letter-spacing: .04em; }

/* --- hero ---
   No kicker above the heading. The name carries itself; a label over it is the thing every
   template in this category does. */
.hero { margin-bottom: 64px; }
.hero-title { margin-bottom: 16px; }
/* The one authored moment on the page: a datum rule drawn once under the name. */
.hero-title::after {
  content: ''; display: block; width: 84px; height: 2px; background: var(--accent);
  margin-top: 20px; transform-origin: left center; animation: datum .5s cubic-bezier(.2,.8,.25,1) both;
}
@keyframes datum { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) {
  .hero-title::after { animation: none; }
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}
/* Sits under the heading, above the accent rule's own margin — a subtitle, not a kicker. */
.hero-subtitle {
  font-family: var(--font-display); font-size: 1rem; font-weight: 600;
  letter-spacing: .01em; color: var(--text-2); margin: -4px 0 14px;
}
.hero-lede { color: var(--text-2); font-size: 1.05rem; max-width: 62ch; margin-top: 16px; }
.hero-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 26px; }

/* --- blocks ---
   A container, so a block's contents can respond to the width they actually get: at 1000px the
   sidebar takes a quarter of the screen, and a viewport query would lay out for room that is not
   there. */
.block { margin-bottom: 64px; container-type: inline-size; }
.block-header {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin-bottom: 22px; border-bottom: 1px solid var(--border); padding-bottom: 10px;
}
.block-header h2 { margin: 0; }
.block-more { font-family: var(--font-display); font-size: .8rem; font-weight: 600; letter-spacing: .06em; color: var(--text-2); }
.block-more:hover { color: var(--accent-text); }
.page-header { margin-bottom: 36px; }
.page-lede { color: var(--text-2); font-size: 1.05rem; max-width: 62ch; text-wrap: pretty; }
/* An empty Section is a row on the same ruled sheet the Posts would sit on, in body type. It was
   a dashed, centred box set in mono: a placeholder look, and mono on a sentence rather than data.
   The button gives the Visitor somewhere to go from a page with nothing on it. */
.empty-state {
  border-top: 1px solid var(--border); border-bottom: 1px solid var(--border);
  padding: 28px 0;
}
.empty-state p { color: var(--text-2); margin: 0 0 18px; max-width: 62ch; }
.empty-state .btn { margin: 0; }

/* --- what we do ---
   Rows on a ruled sheet, not a stack of cards. */
.practice-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; border-top: 1px solid var(--border); }
.practice-list a {
  display: flex; flex-direction: column; gap: 3px; padding: 16px 14px;
  border-bottom: 1px solid var(--border); transition: background-color .15s ease;
}
.practice-list a:hover { background: rgba(255,255,255,.025); color: var(--text); }
/* The row's contents step right on hover, not its padding: animating padding relays out the
   whole list on every frame, and the transform moves only what the eye is following anyway. */
.practice-list span, .practice-list small { transition: transform .15s ease; }
.practice-list a:hover span, .practice-list a:hover small { transform: translateX(6px); }
.practice-list span { font-family: var(--font-display); font-weight: 600; font-size: 1rem; letter-spacing: -0.01em; }
.practice-list small { color: var(--text-2); }

/* --- post cards ---
   The title leads. Kind, Section and date sit under it as a title block, because a label
   stacked above a heading is an eyebrow however it is dressed. */
/* auto-fit, not auto-fill: with one Featured post, auto-fill reserves the empty columns and the
   grid's hairline background paints them as a visible dead cell beside the card. */
.post-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); }
.post-list { display: flex; flex-direction: column; border-top: 1px solid var(--border); }
.post-card { background: var(--bg-card); display: flex; flex-direction: column; }
.post-list .post-card {
  flex-direction: row-reverse; background: transparent;
  border-bottom: 1px solid var(--border); padding: 20px 0; gap: 22px;
  transition: background-color .15s ease;
}
.post-list .post-card:hover { background: rgba(255,255,255,.02); }
.post-card.is-dense { background: transparent; border-bottom: 1px solid var(--border); padding: 16px 0; }
/* 16:9, the shape the Sample Post artwork is drawn at (1200x675). At 4:3 the list thumbnails
   cropped the Section name off the left of every plate. */
.post-card-media { flex: 0 0 196px; aspect-ratio: 16/9; overflow: hidden; }
.post-grid .post-card-media { flex: none; }
/* One Featured Post alone in the grid lies on its side: full width and stacked, its artwork was
   a third of a laptop screen tall and pushed What we do below the fold. */
@container (min-width: 560px) {
  .post-grid > .post-card:only-child { flex-direction: row; }
  /* Centred, not stretched: when the text column runs taller than a 16:9 image (a tablet's
     narrower card), stretching made object-fit crop both sides of the artwork. */
  .post-grid > .post-card:only-child .post-card-media { flex: 0 0 55%; align-self: center; }
  .post-grid > .post-card:only-child .post-card-body { justify-content: center; padding: 24px; }
}
.post-card-media img { width: 100%; height: 100%; object-fit: cover; }
.post-card-body { padding: 18px; flex: 1; display: flex; flex-direction: column; }
.post-list .post-card-body, .post-card.is-dense .post-card-body { padding: 0; }
.post-card-title { margin: 0 0 8px; font-size: 1.08rem; }
.post-card-title a:hover { color: var(--accent-text); }
/* order:-1 is not needed — the title is first in the markup and the meta follows it. */
.post-card-meta { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin: 0 0 10px; }
.post-card-excerpt { color: var(--text-2); font-size: .94rem; margin: 0; max-width: 62ch; text-wrap: pretty; }

/* --- single post ---
   Two layouts, chosen by the Kind (partials/post-body.hbs). A Project or Case Study is work to
   look at: the picture opens the page and a title block records what it is. A Tutorial or Guide
   is something to read: the words open the page and the metadata ends in how long it takes.
   Metadata sits under the title in both, never above it. */
.post-header { margin-bottom: 32px; }
.post-standfirst { color: var(--text-2); font-size: 1.1rem; max-width: 62ch; text-wrap: pretty; margin: 0; }
.post-meta { display: flex; gap: 8px 14px; align-items: center; flex-wrap: wrap; margin-top: 20px; }
.post-feature { margin: 0 0 32px; }
/* width:100%, because the srcset alone let the browser draw a 1200px file at 600px.
   The platform gives a theme no size for a feature image, so the browser could not hold its
   space and the words below jumped as it loaded (layout shift 0.19 on a phone, DAA-356).
   `auto 16 / 9` holds a 16:9 box until the picture arrives, then takes the picture's own shape:
   nothing is cropped, and a 16:9 picture — the size the Publisher guide asks for — moves nothing. */
.post-feature img { width: 100%; height: auto; aspect-ratio: auto 16 / 9; border: 1px solid var(--border); }
.post-feature figcaption { color: var(--text-2); font-size: .82rem; margin-top: 10px; font-family: var(--font-mono); letter-spacing: .04em; }
.post-feature.is-lead { margin-bottom: 36px; }

/* The title block: Kind, Section, Published, in ruled cells like the corner of a drawing. The
   labels are display type and the values are what they are — the Kind in its own face, the
   Section a link, the date in mono because it is data. */
.title-block {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 26px 0 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border);
}
.title-block-cell { padding: 12px 16px 14px; border-left: 1px solid var(--border); min-width: 0; }
.title-block-cell:first-child { padding-left: 0; border-left: 0; }
.title-block dt {
  font-family: var(--font-display); font-size: .68rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text-2);
}
.title-block dd { margin: 6px 0 0; line-height: 1.35; color: var(--text); }
.title-block .section-link { font-size: .93rem; letter-spacing: 0; color: var(--text); }
.title-block .section-link:hover { color: var(--accent-text); }
.title-block time { font-size: .8rem; color: var(--text); }

.post-content {
  --read-pad: clamp(22px, 4vw, 40px);
  background: var(--bg-read); border: 1px solid var(--border);
  padding: var(--read-pad); font-size: 1.05rem; line-height: 1.75;
}
/* The measure. At 820px the surface's text ran to about 95 characters a line on a laptop; the
   comment on --content-w counted 66 but was counting the wrong box. Words are held to 34rem,
   about 70 characters of body type (640px measured 80-83), centred. A length, not ch, so a
   heading and the paragraph under it share a left edge. What is looked at rather than read —
   pictures, galleries, video, code, callouts — keeps the surface's full width. About Us (.page)
   was left at 95 by DAA-352 and brought to the same measure by launch QA (DAA-356). */
.post .post-content { --kg-content-w: 34rem; }
.post-content > :is(figure, pre, hr, table, .kg-card) { max-width: 100%; }
/* A Tutorial or Guide is a reading column: narrower than a Project's page, so the difference
   between the two layouts shows before a word is read. 640px holds that 34rem inside the
   surface's padding. */
.post-reading:not(.page) { max-width: 640px; }
.post-content > * + * { margin-top: 1.1em; }
.post-content h2, .post-content h3 { margin-top: 1.9em; }
/* A Case Study reads as problem → approach → outcome, and the Publisher writes those as
   headings (ADR-0003). Each one starts a ruled stage, so the structure shows at a glance. */
.post-kind-case-study .post-content h2 { border-top: 1px solid var(--border); padding-top: 1.1em; margin-top: 2.2em; }
.post-kind-case-study .post-content > h2:first-child { border-top: 0; padding-top: 0; margin-top: 0; }
/* --text, not --accent-text: the accent measures 4.17:1 on --bg-read and fails AA as body text.
   The underline carries the link, which also keeps the accent a fill rather than a colour. */
.post-content a { color: var(--text); text-decoration: underline; text-underline-offset: .18em; text-decoration-thickness: 1px; }
.post-content a:hover { text-decoration-thickness: 2px; }
.post-content pre { background: var(--bg); border: 1px solid var(--border); padding: 16px; overflow-x: auto; font: .88rem/1.55 var(--font-mono); }
.post-content code { font-family: var(--font-mono); font-size: .9em; }
/* Quieter than body text, so the rule is muted too — an accent bar would pull the eye
   toward the one element that is meant to recede. */
.post-content blockquote { border-left: 1px solid var(--border); margin-bottom: 0; margin-inline: auto; padding-left: 20px; color: var(--text-2); font-style: italic; }
/* --- end-of-Post call to action (DAA-381) ---
   DESIGN.md → Components → "End-of-Post call to action", drawn in docs/design/comps/case-study.html.
   A steel-card panel after the reading surface: the ask on the left, with the email address as
   the biggest thing in it, and "What happens after you write" on the right, so writing is not a
   leap. Two halves need room: a Project or Case Study page has it, a Tutorial or Guide's 640px
   reading column does not, so the halves are decided by the panel's own width, not the screen's. */
.post-cta { margin-top: 64px; container-type: inline-size; background: var(--bg-card); border: 1px solid var(--border); }
.post-cta-grid { display: grid; grid-template-columns: minmax(0, 1fr); }
.post-cta-main, .post-cta-next { padding: clamp(24px, 5cqi, 44px); }
.post-cta-main { border-bottom: 1px solid var(--border); }
.post-cta-main h2 { margin: 0; font-size: clamp(1.9rem, 6cqi, 2.9rem); line-height: 1; letter-spacing: -0.035em; }
.post-cta-main p { margin: 16px 0 0; color: var(--text-2); max-width: 40ch; text-wrap: pretty; }
.post-cta-email {
  display: block; width: fit-content; max-width: 100%; margin-top: 26px; padding-bottom: 6px;
  font: 600 clamp(1.2rem, 3.4cqi, 1.4rem)/1.15 var(--font-display); letter-spacing: -0.02em;
  color: var(--text); border-bottom: 1px solid var(--line); overflow-wrap: anywhere;
  transition: border-color .15s ease, color .15s ease;
}
.post-cta-email:hover { color: var(--text); border-bottom-color: var(--accent-text); }
.post-cta-main .post-cta-phone { margin-top: 12px; font-size: .95rem; }
.post-cta-phone a { color: var(--text); font-variant-numeric: tabular-nums; border-bottom: 1px solid var(--line); padding-bottom: 2px; }
.post-cta-phone a:hover { color: var(--text); border-bottom-color: var(--accent-text); }
/* DESIGN.md → Buttons, primary: 48px tall, Archivo 600 at .95rem, square, a drawn arrow. Scoped to
   the panel; the site's other buttons move to it with their own tickets. */
.post-cta-button {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  min-height: 48px; margin-top: 24px; padding: 0 22px;
  background: var(--accent); color: #fff;
  font: 600 .95rem/1 var(--font-display); letter-spacing: .01em;
  transition: background-color .15s ease;
}
.post-cta-button:hover { background: var(--accent-hover); color: #fff; }
.post-cta-arrow { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: square; transition: transform .15s ease; }
.post-cta-button:hover .post-cta-arrow { transform: translateX(6px); }
.post-cta-next h3 {
  margin: 0 0 20px; color: var(--text-2);
  font: 600 .72rem/1.3 var(--font-display); letter-spacing: .16em; text-transform: uppercase;
}
/* Ruled numbered rows. The numbers are data (a sequence the reader needs), so they are mono. */
.post-cta-next ol { list-style: none; margin: 0; padding: 0; counter-reset: step; }
.post-cta-next li {
  counter-increment: step; display: grid; grid-template-columns: 32px minmax(0, 1fr); column-gap: 14px;
  padding: 12px 0; border-top: 1px solid var(--border); line-height: 1.45;
}
.post-cta-next li::before {
  content: counter(step); grid-row: span 2;
  font: 500 .8rem/1.9 var(--font-mono); color: var(--text-2); font-variant-numeric: tabular-nums;
}
.post-cta-step { font-weight: 600; }
.post-cta-detail { display: block; margin-top: 3px; color: var(--text-2); font-size: .92rem; }
@container (min-width: 720px) {
  .post-cta-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .post-cta-main { border-bottom: 0; border-right: 1px solid var(--border); }
}
@media (prefers-reduced-motion: reduce) {
  .post-cta-arrow, .post-cta-button:hover .post-cta-arrow { transition: none; transform: none; }
}

.more-in-section { margin: 64px 0 0; }
/* The block header already draws the rule the list would open with. */
.more-in-section .post-list { border-top: 0; }

/* --- editor (Koenig) cards ---
   What the Publisher inserts in the Dashboard: images, galleries, embeds, callouts,
   bookmarks, buttons, dividers. .kg-width-wide / .kg-width-full are required by Ghost. */
.gh-content { --kg-content-w: 100%; }
.gh-content > * { max-width: var(--kg-content-w); margin-left: auto; margin-right: auto; }

/* The column is already the page's width, so "wide" and "full" both mean the reading surface's
   own edges: out through its padding, and no further. They were drawn no wider than normal. */
.post-content > .kg-width-wide,
.post-content > .kg-width-full { max-width: none; margin-inline: calc(-1 * var(--read-pad)); }
.kg-width-wide img, .kg-width-full img { width: 100%; }
/* The platform's card styles round their corners. This system is square (--radius). */
.gh-content [class^='kg-'], .gh-content [class*=' kg-'] { border-radius: var(--radius); }

.kg-card { margin-top: 1.6em; margin-bottom: 1.6em; }
.kg-image-card figcaption,
.kg-gallery-card figcaption,
.kg-embed-card figcaption { color: var(--text-2); font-size: .82rem; text-align: center; margin-top: 10px; font-family: var(--font-mono); letter-spacing: .04em; }
.kg-image { margin-inline: auto; }

.kg-gallery-container { display: flex; flex-direction: column; gap: 6px; }
.kg-gallery-row { display: flex; gap: 6px; }
.kg-gallery-image img { width: 100%; height: 100%; object-fit: cover; }

.kg-embed-card { display: flex; flex-direction: column; align-items: center; }
.kg-embed-card iframe { max-width: 100%; }
/* A video arrives at a fixed 560x315. Scaled to the column instead, at its own shape. */
.kg-embed-card iframe[src*='youtube'], .kg-embed-card iframe[src*='vimeo'] { width: 100%; height: auto; aspect-ratio: 16 / 9; }

/* No background here: the Publisher picks a colour in the editor and Ghost sets it via
   .kg-callout-card-{grey,white,blue,green,yellow,red,pink,purple}. The emoji is the marker. */
.kg-callout-card { display: flex; gap: 12px; padding: 16px 18px; border: 1px solid var(--border); }
.kg-callout-emoji { flex: 0 0 auto; font-size: 1.1em; line-height: 1.5; }
.kg-callout-text { margin: 0; }

.kg-bookmark-card a.kg-bookmark-container { display: flex; border: 1px solid var(--border); overflow: hidden; background: var(--bg-card); color: inherit; }
.kg-bookmark-content { flex: 1 1 auto; padding: 16px; }
.kg-bookmark-title { font-family: var(--font-display); font-weight: 600; }
.kg-bookmark-description { color: var(--text-2); font-size: .9rem; }
.kg-bookmark-metadata { display: flex; align-items: center; gap: 8px; font-size: .78rem; color: var(--text-2); margin-top: 10px; font-family: var(--font-mono); }
.kg-bookmark-icon { width: 18px; height: 18px; }
.kg-bookmark-thumbnail img { width: 180px; height: 100%; object-fit: cover; }

.kg-button-card { display: flex; justify-content: center; }
.kg-btn { display: inline-block; padding: 11px 20px; background: var(--accent); color: #fff; font-family: var(--font-display); font-weight: 600; font-size: .88rem; letter-spacing: .02em; }
.kg-btn:hover { background: var(--accent-hover); color: #fff; }

.kg-toggle-card { border: 1px solid var(--border); padding: 14px 18px; }
.kg-toggle-heading { display: flex; justify-content: space-between; align-items: center; gap: 12px; cursor: pointer; }
.kg-toggle-content { color: var(--text-2); }

hr, .kg-divider { border: 0; border-top: 1px solid var(--border); }

@media (max-width: 700px) {
  .kg-gallery-row { flex-direction: column; }
  .kg-bookmark-thumbnail { display: none; }
}

/* --- contact card --- */
.contact-card { margin-top: 28px; padding: 30px; background: var(--bg-card); border: 1px solid var(--border); }
.contact-card h2 { margin-bottom: .4em; }
.contact-card p { color: var(--text-2); }
.contact-list { display: flex; gap: 36px; flex-wrap: wrap; margin: 0 0 22px; }
.contact-list dt {
  font-family: var(--font-display); font-size: .68rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text-2);
}
.contact-list dd { margin: 5px 0 0; font-weight: 500; font-variant-numeric: tabular-nums; }

/* --- pagination, footer --- */
/* Three columns so the count holds the centre whichever link is missing; see partials/pagination.hbs. */
.pagination { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px; margin-top: 24px; }
.pagination-count { font-family: var(--font-mono); font-size: .75rem; font-weight: 500; letter-spacing: .06em; font-variant-numeric: tabular-nums; color: var(--text-2); }
.pagination-link {
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px; justify-self: start;
  font-family: var(--font-display); font-size: .88rem; font-weight: 600; letter-spacing: .02em; color: var(--text);
}
.pagination-link.is-next { justify-self: end; }
.pagination-arrow { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.5; transition: transform .15s ease; }
.pagination-link:hover .pagination-arrow { transform: translateX(-3px); }
.pagination-link.is-next:hover .pagination-arrow { transform: translateX(3px); }
.site-footer { margin-top: 72px; padding-top: 22px; border-top: 1px solid var(--border); font-family: var(--font-mono); font-size: .75rem; letter-spacing: .06em; color: var(--text-2); }

/* --- responsive --- */
@media (max-width: 900px) {
  .topbar {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    position: sticky; top: 0; z-index: 60; height: 60px;
    padding: 0 12px 0 var(--gutter); background: var(--bg-card); border-bottom: 1px solid var(--border);
  }
  /* The menu opens below the bar rather than over it, so the brand and the close button stay
     where the thumb left them. The sidebar's own brand would repeat the bar's, so it goes. */
  .sidebar {
    inset: 60px auto 0 0; transform: translateX(-100%); transition: transform .2s ease;
    z-index: 50; width: min(var(--sidebar-w), 80vw); padding-top: 22px;
  }
  .sidebar .brand { display: none; }
  body.nav-open { overflow: hidden; }
  body.nav-open .sidebar { transform: none; box-shadow: 0 0 0 100vw rgba(0,0,0,.55); }
  .main { margin-left: 0; padding-top: 40px; }
  .post-card-media { flex-basis: 168px; }
}

@media (max-width: 600px) {
  .post-list .post-card { flex-direction: column; gap: 14px; }
  .post-card-media { flex: none; }
  /* A phone list of pictures pushes the titles apart. Home's Latest and a Post's "More in" drop them. */
  .is-latest .post-card-media, .more-in-section .post-card-media { display: none; }
  /* Too narrow for count and both links on one line: the count takes its own row above them. */
  .pagination { grid-template-columns: 1fr 1fr; row-gap: 4px; }
  .pagination-count { grid-column: 1 / -1; grid-row: 1; }
  /* The reading surface runs to the screen edges. Inside the page gutter its own padding left
     About Us about 34 characters to a line. */
  .post-content { margin-inline: calc(-1 * var(--gutter)); border-inline: 0; }
  /* The lead picture runs to the screen edges too, so it lines up with the surface below it. */
  .post-feature.is-lead { margin-inline: calc(-1 * var(--gutter)); }
  .post-feature.is-lead img { border-inline: 0; }
  .post-feature.is-lead figcaption { padding-inline: var(--gutter); }
  /* Three cells are too narrow for "Customer Quality Engineering". Each becomes a ruled row,
     label left and value right, the way a title block reads in portrait. */
  .title-block { grid-template-columns: 1fr; border-bottom: 0; }
  .title-block-cell {
    display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
    padding: 11px 0; border-left: 0; border-bottom: 1px solid var(--border);
  }
  .title-block dd { margin: 0; text-align: right; }
  .contact-card { padding: 24px 20px; }
  /* The call to action runs to the screen edges like the reading surface above it, and its
     button takes the full width so a thumb cannot miss it (DESIGN.md). */
  .post-cta { margin-inline: calc(-1 * var(--gutter)); border-inline: 0; }
  .post-cta-main, .post-cta-next { padding-inline: var(--gutter); }
  .post-cta-button { display: flex; width: 100%; }
}
