/* bcbyvish.com
   Single stylesheet. Tokens declared once, below.
   Top-level section padding is set in exactly one grouped rule (see
   "section rhythm"). Do not add padding to individual sections elsewhere,
   that is how these rules end up silently cancelling each other out.

   Base styles render the RESOLVED state of everything. main.js animates
   backwards from there, so the page is complete and readable with no JS
   and under prefers-reduced-motion. */

:root {
  --paper:  #FBFBF7;
  --ink:    #16231C;
  --muted:  #5C6B60;
  --rule:   #C3CFC0;
  --accent: #9E2B25;
  /* Added 2026-08-18 with reason, per Section 3. The counterpart to --accent:
     red marks what does not reconcile, this marks what does. Kept muted and in
     the palette's existing green family rather than a bright dashboard green.
     5.78:1 on paper, so it passes AA on its own. */
  --agree:  #2E6F4E;

  /* Tints derived from the five above, not new palette entries:
     a cooler paper for closing blocks, a white ground so ledger surfaces
     read as a screen rather than the page, and a lighter row rule. */
  --paper-2:    #F5F6F0;
  --ground:     #FFFFFF;
  --rule-light: #E8ECE5;

  --display: "Fraunces", Georgia, "Times New Roman", serif;
  --body:    "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --mono:    "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --measure: 34rem;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --pad-block: clamp(4rem, 10vw, 7.5rem);
}

/* ---------- fonts, self-hosted ---------- */

/* Served from this site rather than fonts.googleapis.com. The site has no
   cookie banner by design, and a third-party request on every page load is
   exactly the sort of thing that would eventually need one. Files are the
   same WOFF2 Google serves, latin subset only. Fraunces and IBM Plex Sans are
   variable, so one file each covers the weights in use. */

@font-face {
  font-family: "Fraunces";
  src: url(fonts/fraunces-var.woff2) format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url(fonts/plex-sans-var.woff2) format("woff2");
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url(fonts/plex-mono-400.woff2) format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url(fonts/plex-mono-500.woff2) format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url(fonts/plex-mono-600.woff2) format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* ---------- base ---------- */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

/* The hidden attribute is only a UA display:none, so any display declaration
   silently beats it. The archive relies on [hidden] for filtering, and
   .filters sets display:grid, so without this the empty filter bar shows. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* opsz stays low deliberately. Fraunces at high optical sizes goes
   thin-stroke and fashion-magazine, the wrong register for this. */
h1, h2, h3 {
  font-family: var(--display);
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 24;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.012em;
  text-wrap: balance;
  margin: 0;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

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

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 20;
  background: var(--ink); color: var(--paper);
  padding: 0.75rem 1rem;
  font-family: var(--mono); font-size: 0.8125rem;
}
.skip:focus { left: 0; }

.wrap {
  width: 100%; max-width: 62rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---------- shared type devices ---------- */

.eyebrow {
  font-family: var(--mono);
  font-size: 0.75rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 1.5rem;
}

h2 { font-size: clamp(1.75rem, 1.2rem + 2.4vw, 2.75rem); max-width: 20ch; }
h3 { font-size: clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem); max-width: 24ch; }

.prose-line { max-width: var(--measure); color: var(--muted); }
h2 + .prose-line { margin-top: 1.5rem; }

.note {
  font-family: var(--mono);
  font-size: 0.6875rem; letter-spacing: 0.04em;
  color: var(--muted);
  margin-top: 0.9rem;
}

.btn {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.8125rem; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase;
  text-decoration: none;
  color: var(--paper); background: var(--ink);
  padding: 0.9rem 1.5rem;
  transition: background 120ms ease;
}
.btn:hover { background: var(--accent); }
.cta-row { margin-top: 2.25rem; }

/* ---------- section rhythm (the only place block padding is set) ---------- */

.hero, .reorg, .positioning, .pillars, .exploring, .route, .close {
  padding-block: var(--pad-block);
}
.hero { padding-block: clamp(5rem, 13vw, 9rem) clamp(4rem, 10vw, 7rem); }

/* No rules between sections and no tinted blocks. The page reads as one
   continuous surface; the eyebrow labels and the whitespace carry the rhythm
   instead. The hairlines were also chopping the full-width scenes in half. */

/* ---------- masthead ---------- */

/* Sticky, because a header that scrolls away on a page this long is a header
   most people never see. Solid paper rather than a translucent blur: the
   scenes run underneath it and a blurred bar over moving artwork is noise. */
.masthead {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.masthead-inner {
  display: flex; flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  align-items: center; justify-content: space-between;
  padding-block: 0.9rem;
}

/* The mark is an account-code chip, the same object the ledger and the bin
   labels are made of. It belongs to this site's own vocabulary rather than
   being a logo bolted on. */
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--mono);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--ink);
}
.mark {
  display: inline-grid;
  place-items: center;
  width: 1.85rem; height: 1.85rem;
  background: var(--ink);
  color: var(--paper);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  transition: background 140ms ease;
}
.wordmark .tld { color: var(--muted); }
.wordmark:hover { color: var(--ink); }
.wordmark:hover .mark { background: var(--accent); }
.masthead-meta { font-family: var(--mono); font-size: 0.75rem; color: var(--muted); letter-spacing: 0.02em; }

/* ---------- sticky section rail ---------- */

/* The rail sits in the page margin, which is only (100vw - 62rem) / 2 wide.
   Showing the labels needs ~143px of margin, i.e. a 1278px viewport, so at
   anything narrower they would sit on top of the content. Numbers alone need
   ~52px, which fits from 72rem. So: numbers by default, label revealed on
   hover or keyboard focus, where a moment of overlap is the user's own doing. */
.rail { display: none; }

@media (min-width: 72rem) {
  .rail {
    display: block;
    position: fixed;
    right: 1.75rem;
    top: 50%;
    transform: translateY(-50%);
    z-index: 5;
  }
  .rail a {
    display: flex; gap: 0.6rem; align-items: baseline; justify-content: flex-end;
    font-family: var(--mono); font-size: 0.6875rem;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--muted); text-decoration: none;
    /* Paper behind each label. The scenes are full-bleed now and run under the
       rail; without this the numbers sit on top of ledger rows and racking. */
    background: var(--paper);
    padding: 0.3rem 0.5rem;
    opacity: 0.75;
    white-space: nowrap;
    transition: opacity 160ms ease, color 160ms ease;
  }
  .rail a:hover, .rail a:focus-visible { opacity: 1; }
  .rail ol { display: grid; gap: 0.15rem; justify-items: end; }
  .rail a.is-current { opacity: 1; color: var(--ink); }

    /* --rule here measured 1.56:1 against paper, and below 80rem these
     numbers are the only thing the rail shows. Muted is 5.43:1. */
  .rail-n { color: var(--muted); order: 2; }
  .rail a.is-current .rail-n { color: var(--accent); }

  /* Label collapses to nothing until asked for. clip-path rather than
     display:none so it stays in the accessibility tree. */
  .rail-label {
    max-width: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-width 200ms ease, opacity 200ms ease;
  }
  .rail a:hover .rail-label,
  .rail a:focus-visible .rail-label { max-width: 10rem; opacity: 1; }
}

@media (min-width: 80rem) {
  /* Enough margin for the labels to live there permanently. */
  .rail-label { max-width: 10rem; opacity: 1; }
}

/* ---------- hero ---------- */

.hero { position: relative; overflow: hidden; }

.hero-field {
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 0;
}
.hero-field span {
  position: absolute;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--accent);
  white-space: nowrap;
  /* per-element opacity is set in main.js, for depth */
}

.hero-inner { position: relative; z-index: 1; }

.claim {
  font-size: clamp(2.25rem, 1.1rem + 4.9vw, 4.5rem);
  max-width: 16ch;
  margin-bottom: 1.75rem;
}
.lede {
  max-width: var(--measure);
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.25rem);
  color: var(--muted);
  line-height: 1.5;
}

/* ---------- 01 the reconciliation scene ---------- */

.reorg .note { margin-top: 1.25rem; }

.rec-frame { fill: none; stroke: var(--accent); stroke-width: 1; stroke-dasharray: 5 4; }
.rec-frame-label { fill: var(--accent); }
.rec-rule { stroke: var(--rule-light); stroke-width: 1; }
.rec-cell {
  font-family: var(--mono);
  font-size: 19px;
  font-variant-numeric: tabular-nums;
  fill: var(--ink);
}
.rec-wrong { fill: var(--accent); }
/* Twice the row size and properly semibold, sitting under the table rather
   than off in a corner. 600 is a real weight now, not synthesised. */
/* Two classes deliberately: .scene-fig is declared later in this file and at
   equal specificity would win. Twice the 19px row size. */
.scene-fig.rec-meter { font-size: 38px; font-weight: 600; }
/* Red while it does not reconcile, green the moment it does. Toggled in
   main.js at the exact point the figure reaches zero, rather than tweened, so
   the colour change lands on the number and not near it. */
.scene-fig.rec-meter { fill: var(--accent); }
.scene-fig.rec-meter.is-agreed { fill: var(--agree); }
.rec-meter-label { letter-spacing: 0.18em; }

/* ---------- positioning ---------- */

.positioning-inner {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: center;
}
@media (min-width: 48rem) {
  .positioning-inner { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); }
}

/* White plate, so the photo's own white background matches its surround
   exactly instead of showing as a pale rectangle on the paper. */
.portrait { margin: 0; }
.portrait img {
  display: block;
  width: 100%; height: auto;
  background: var(--ground);
  border: 1px solid var(--rule);
}
.portrait figcaption {
  font-family: var(--mono);
  font-size: 0.6875rem; letter-spacing: 0.06em;
  color: var(--muted);
  margin-top: 0.75rem;
}

.pull { margin: 0; }
.pull p {
  font-family: var(--display);
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 24;
  font-weight: 600;
  font-size: clamp(1.3rem, 1rem + 1.5vw, 2rem);
  line-height: 1.25;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.pull-close {
  margin-top: 2rem;
  margin-bottom: 2rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--rule);
  max-width: 40rem;
}
.pull-close p { font-size: clamp(1.15rem, 1rem + 0.9vw, 1.5rem); }

/* ---------- 02 pillars ---------- */

/* Copy sits in a full-width band ABOVE its scene, not in a column beside it.
   That frees the drawing to use the entire viewport width and removes the need
   to mask artwork out from under the text at all. */
.pillar { position: relative; padding-block: clamp(3rem, 7vw, 5.5rem) 0; }

.pillar-inner { position: relative; z-index: 1; }

.pillar-text { max-width: 46rem; }
.pillar-text h3 { max-width: 26ch; }
.pillar-text p {
  color: var(--muted);
  margin-top: 1.1rem;
  max-width: 40rem;
}
.pillar-text h3 + p { margin-top: 1.4rem; }

/* The stage: full viewport width, in normal flow beneath the copy. */
/* The stage sticks while its section scrolls past, and is capped to the
   viewport height. Before this the map was taller than the screen, so you only
   ever saw a slice of it travelling upward: the animation felt cut in half
   rather than watched. Sticky keeps the whole drawing in frame for the whole
   run. Native sticky, not a GSAP pin, so there is no spacer shifting every
   trigger below it. */
.pillar-art {
  position: sticky;
  top: 5.25rem;
  height: 74vh;
  width: 100%;
  margin-top: clamp(1.25rem, 3vw, 2.25rem);
}
.pillar-art .scene { height: 100%; }

/* The section is taller than the sticky stage, and the difference is how much
   scroll the animation has to play out over. */
.reorg, .pillar { min-height: 195vh; }
.pillar--tall { min-height: 260vh; }

@media (max-width: 52rem) {
  /* Sticky plus a short viewport leaves no room for the copy, so on phones the
     scene just sits in the flow at its natural height. */
  .pillar-art { position: static; height: auto; }
  .reorg, .pillar, .pillar--tall { min-height: 0; }
}

/* Scenes, not panels. No border, no card: the drawing sits on the paper.
   Colour lives here rather than in main.js, so the palette stays in one file. */
.pillar-art { min-width: 0; }

/* Clipped to its own frame. Scattered crates and incoming map pieces travel
   well outside the viewBox, and with overflow visible they land on the
   headline in the next column. */
.scene { display: block; width: 100%; height: auto; overflow: hidden; }

.scene-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  fill: var(--muted);
}
/* Was 8px, which is near-illegible at 100% zoom on a small laptop. */
.scene-micro { font-family: var(--mono); font-size: 11px; fill: var(--muted); }
.scene-fig {
  font-family: var(--mono);
  font-size: 38px;
  font-variant-numeric: tabular-nums;
  fill: var(--ink);
}

/* Every scene ends on two things agreeing: count equals ledger, region total
   equals department total, migration reaches 100%, variance reaches zero.
   Green marks that agreement, red marks its absence, and the pair reads the
   same way in all four scenes. Not Business Central blue: Section 3 rules out
   standing in Microsoft's colours or the partners'. */
.fig-result { fill: var(--agree); font-weight: 600; }

/* Scene 1, warehouse */
.wh-floor { stroke: var(--ink); stroke-width: 1.5; }
.wh-upright { stroke: var(--muted); stroke-width: 3; stroke-linecap: square; }
.wh-beam { stroke: var(--muted); stroke-width: 2; stroke-linecap: square; }
.wh-carton { fill: var(--ground); stroke: var(--ink); stroke-width: 1; }
.wh-deck { fill: var(--paper-2); stroke: var(--ink); stroke-width: 1; }
.wh-strap { stroke: var(--rule); stroke-width: 1; }
.wh-rule { stroke: var(--rule); stroke-width: 1; }
.wh-agree { fill: var(--agree); font-size: 16px; letter-spacing: 0.1em; }

/* Scene 2, map. White fill against the paper, muted hairline: at this size a
   rule-coloured border on a paper-2 fill disappears entirely. */
/* fill-opacity is set per country in main.js from the illustrative share
   tier. Ink at four strengths, not a new hue: accent already means "does not
   reconcile" everywhere else on this site. */
.map-country { fill: var(--ink); stroke: var(--muted); stroke-width: 0.8; stroke-linejoin: round; }
.map-link { stroke: var(--rule); stroke-width: 1; }
.dept-chip { fill: var(--ground); stroke: var(--ink); stroke-width: 1; }
.dept-text { fill: var(--ink); }

/* Scene 3, migration */
.mig-binder { fill: var(--paper-2); stroke: var(--ink); stroke-width: 1; }
.mig-spine { stroke: var(--ink); stroke-width: 1; }
.mig-spine-label { fill: var(--ground); stroke: var(--muted); stroke-width: 1; }
.mig-sheet { stroke: var(--accent); stroke-width: 1; opacity: 0.55; }
.mig-feed { stroke: var(--rule); stroke-width: 1; stroke-dasharray: 4 4; }
.mig-hopper { fill: none; stroke: var(--ink); stroke-width: 1.5; stroke-linejoin: round; }
.mig-panel { fill: var(--ground); stroke: var(--muted); stroke-width: 1; }
.mig-panel-bar { fill: var(--paper-2); stroke: var(--muted); stroke-width: 1; }
.mig-panel-title { fill: var(--ink); }
.mig-pct { font-size: 46px; }
/* Landed records sit back. At full ink they read as solid black bars. */
.mig-row { fill: var(--rule); }
.mig-gate-label { fill: var(--ink); font-size: 17px; letter-spacing: 0.2em; }

/* ---------- 03 currently exploring ---------- */

.explore-list {
  margin-top: 2.75rem;
  display: grid; gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}
@media (min-width: 52rem) {
  .explore-list { grid-template-columns: repeat(3, 1fr); }
}
.explore-list li { background: var(--paper); padding: 1.6rem; }
.explore-list h3 { font-size: 1.0625rem; max-width: none; }
.explore-list p { color: var(--muted); font-size: 0.9375rem; line-height: 1.55; margin-top: 0.6rem; }

/* ---------- 04 timeline ---------- */

.timeline { margin-top: 2.75rem; border-top: 1px solid var(--rule); max-width: 46rem; }
.timeline li {
  display: grid; gap: 0.5rem 2rem;
  padding: 1.4rem 0;
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 40rem) {
  .timeline li { grid-template-columns: 5rem minmax(0, 1fr); }
}
.t-year {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.8125rem; font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--accent);
}
.t-body { color: var(--muted); }

/* ---------- 03 questions ---------- */

/* Native details/summary, no JS. The answers are in the HTML whether or not
   they are open, so search engines read them either way, which is the entire
   point of putting an FAQ on a site like this. */
.faq { margin-top: 2.75rem; border-top: 1px solid var(--rule); max-width: 52rem; }
.faq details { border-bottom: 1px solid var(--rule); }

.faq summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  gap: 1.5rem;
  align-items: baseline;
  justify-content: space-between;
  padding: 1.35rem 0;
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
  font-weight: 500;
  line-height: 1.4;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent); }

.faq summary::after {
  content: "+";
  font-family: var(--mono);
  font-weight: 400;
  color: var(--accent);
  flex: none;
}
.faq details[open] summary::after { content: "\2212"; }

.faq-answer { padding-bottom: 1.6rem; max-width: 44rem; }
.faq-answer p { color: var(--muted); }
.faq-answer p + p { margin-top: 1rem; }

/* ---------- variance tracker ---------- */

/* The scene's own variance readout scrolls away with the scene, so the moment
   it lands on zero is easy to miss. This one is fixed to the bottom of the
   viewport and lives only while the reconciliation is on screen. */
.variance {
  position: fixed;
  left: 1.75rem;
  bottom: 1.5rem;
  z-index: 6;
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: 0.55rem 0.9rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 260ms ease;
}
.variance.is-on { opacity: 1; }

.variance-label {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.variance-value {
  font-family: var(--mono);
  font-size: 1.0625rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  transition: color 320ms ease;
}

/* Agreed. The colour is the flourish; the number reaching 0.00 is the actual
   signal, which matters because red and green sit at almost identical
   luminance and are the classic pair people cannot tell apart. */
.variance.is-agreed { border-color: var(--agree); }
.variance.is-agreed .variance-value { color: var(--agree); }
.variance.is-agreed .variance-label { color: var(--agree); }

@media (max-width: 40rem) {
  .variance { left: 1rem; bottom: 1rem; padding: 0.45rem 0.7rem; }
  .variance-value { font-size: 0.9375rem; }
}

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

.footer { border-top: 1px solid var(--rule); padding-block: 2.5rem; }
.footer-inner { display: flex; flex-wrap: wrap; gap: 0.5rem 2rem; justify-content: space-between; }
.footer p { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.02em; color: var(--muted); }
.footer-links a { color: var(--muted); }
.footer-links a:hover { color: var(--accent); }
.sep { padding-inline: 0.6rem; color: var(--rule); }

/* Verified, not aspirational: the site sets no cookies, uses no storage and
   makes no off-domain requests. Worth saying out loud in this niche. */
.footer-privacy { color: var(--muted); }

/* ---------- reduced motion ----------
   Base styles already render every resolved state, so this only needs to
   stop transitions and smooth scrolling. main.js skips animation entirely
   and marks the body, which keeps the hero field static rather than drifting. */

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

/* ---------- masthead nav (multi-page) ---------- */

.masthead-nav { display: flex; gap: 1.5rem; }
.masthead-nav a {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
}
.masthead-nav a:hover { color: var(--accent); }
.masthead-nav a[aria-current="page"] { color: var(--ink); }
.masthead-nav a[aria-current="page"]::after {
  content: "";
  display: block;
  height: 1px;
  margin-top: 0.35rem;
  background: var(--accent);
}

/* ---------- writing archive ---------- */

.archive-head { padding-block: clamp(4rem, 10vw, 7rem) clamp(2rem, 5vw, 3rem); }
.archive-head h1 {
  font-size: clamp(1.9rem, 1.2rem + 3vw, 3.25rem);
  max-width: 20ch;
  margin-bottom: 1.5rem;
}

.archive { padding-block: 0 clamp(4rem, 10vw, 7rem); }

.filters { display: grid; gap: 0.75rem; margin-bottom: 3rem; }
.filter-row { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; }
.filter-label {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  min-width: 4rem;
}
.filter {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  color: var(--muted);
  background: none;
  border: 1px solid var(--rule);
  padding: 0.3rem 0.65rem;
  cursor: pointer;
}
.filter:hover { color: var(--ink); border-color: var(--muted); }
.filter.is-on { color: var(--paper); background: var(--ink); border-color: var(--ink); }

.group-head {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  max-width: none;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--rule);
}

.entries { margin: 0; }
.entry { border-bottom: 1px solid var(--rule); padding-block: 2rem; }

.entry-meta {
  display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; align-items: baseline;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin-bottom: 0.9rem;
}
.tag { border: 1px solid var(--rule); padding: 0.15rem 0.5rem; }
.tag-type { color: var(--ink); }

.entry-title { font-size: clamp(1.15rem, 1rem + 0.9vw, 1.5rem); max-width: 30ch; }
.entry-title a { color: var(--ink); text-decoration: none; }
.entry-title a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 0.18em; }

.entry-note {
  max-width: var(--measure);
  color: var(--muted);
  margin-top: 0.75rem;
  font-size: 0.9375rem;
  line-height: 1.6;
}

.empty-note { color: var(--muted); padding-block: 2rem; }

.archive-close {
  padding-block: clamp(3.5rem, 8vw, 5.5rem);
}
.archive-close h2 { margin-bottom: 1.25rem; }
