/* NCCV — this publication's own use of the design system.
 *
 * The tokens live in assets/ds/ and are the CONSTELLATION's, mirrored here (see
 * assets/ds/MIRROR.md). This file holds only what is this site's: its components, and the
 * two places it deliberately declines what the design system offers.
 *
 * The engine's stylesheets are not loaded at all. This tier is not a journal — it publishes a
 * handful of hand-arranged pages with its own framing, and this is that framing.
 *
 * DEVIATION 1 — ONE HEADER SIZE. typography.css offers a display scale it calls "deliberately
 * enormous", and this publication does not use it. Prominence expressed typographically is
 * precisely what it is correcting: a month with one letter must not be made to look poorer
 * than a month with five, and no story is promoted by being set larger. So `--header` is a
 * size, not a scale, and every heading takes it.
 *
 * DEVIATION 2 — FEWER LINES. A rule is drawn only where one is meant. A line that separates
 * nothing is decoration, and this page has two: the one under the masthead that says the paper
 * starts here, and the hairlines between items in a list.
 */

:root {
  /* The one header size — the smallest the mock-ups used, now used everywhere. */
  --header: 1.3125rem;
  --eyebrow: var(--mono-caption);
  --measure-body: 64ch;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--mono-body);
  line-height: var(--leading-body);
}
a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 4px; }
a:focus-visible { outline: var(--rule) solid var(--ink); outline-offset: 3px; }

/* ---- the spire: everything sets from the same left edge ---------------------------- */
.masthead,
.page,
.colophon { padding-inline: var(--gutter); }

.masthead {
  display: flex;
  align-items: baseline;
  gap: var(--space-5);
  flex-wrap: wrap;
  padding-block: var(--space-4);
  border-bottom: var(--rule) solid var(--ink);
}
.wordmark {
  font-family: var(--font-display);
  font-size: var(--header);
  line-height: var(--leading-snug);
}
.eyebrow, .area {
  font-size: var(--eyebrow);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ---- the areas, as navigation rather than an index --------------------------------- */
/* A reader who has not chosen an area is still inside the publication. Choosing one is the
   thing they do here, so it sits in the masthead and not in the body of the page. */
.areas { display: flex; flex-wrap: wrap; gap: var(--space-5); }
.area {
  white-space: nowrap;
  padding-bottom: 2px;
  border-bottom: 4px solid transparent;
  margin-bottom: -6px;                 /* sit the rule on the masthead's own line */
}
.area:hover { color: var(--ink); text-decoration: none; border-bottom-color: var(--paper-edge); }
.area.here { color: var(--ink); border-bottom-color: var(--ink); }

.page { padding-block: var(--space-6) var(--space-8); }

/* One size at every level. The hierarchy is position and spacing, not scale. */
.page h1, .page h2, .page h3 {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--header);
  line-height: var(--leading-snug);
  margin: 0;
  text-wrap: pretty;
}
.page h1 { margin-bottom: var(--space-2); }
.page h2 { margin-top: var(--space-7); }
.page h3 { margin-top: var(--space-5); }
.page p { margin: 0 0 var(--space-4); max-width: var(--measure-body); color: var(--ink-soft); }
.page > p:first-of-type { color: var(--ink); }

/* An issue list is a list, at every width — a month with one letter is the same object as a
   month with five. */
.page ul { list-style: none; margin: var(--space-3) 0 0; padding: 0; }
.page ul li { padding: var(--space-3) 0; }
.page ul li + li { border-top: var(--rule) solid var(--paper-edge); }
.page em { color: var(--ink-faint); font-style: normal; font-size: var(--mono-small); }

/* ---- the byline, which comes first --------------------------------------------------- */
/* POSITION CARRIES IT, NOT TONE. The name is above the title on both surfaces — the area's
   contents page and the letter itself — because that is the first chance to say who the human
   is. Being first is the emphasis; it does not also need to be the darkest thing on the page,
   and a quiet grey keeps the title as the thing being read.

   Still not an .eyebrow, though it shares its colour: an eyebrow is upper-cased and tracked
   into a label, and a person's name is set the way that person writes it. */
.byline {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--mono-small);
  letter-spacing: 0.01em;
  color: var(--ink-faint);
  margin-bottom: var(--space-1);
}

.piece-head { margin-bottom: var(--space-6); }

/* Where the letter came from and when its author wrote it. Quiet, under the title, and after
   it — a reader wants to know what they are reading before they are told its provenance. It is
   set at caption size because it is the one thing on a letter that genuinely IS metadata. */
.provenance {
  font-family: var(--font-mono);
  font-size: var(--mono-caption);
  color: var(--ink-faint);
  margin: var(--space-2) 0 0;
}
.provenance a { text-decoration: underline; text-underline-offset: 3px; }
/* The title of a letter takes the one header size like every other heading. A month with one
   letter must not look poorer than a month with five, and nor must a short letter. */
.piece-head h1 {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--header);
  line-height: var(--leading-snug);
  margin: 0;
  text-wrap: pretty;
}

/* In a list of letters the name is the first line and the title is the second, so the title
   carries the link and the name simply stands above it. */
.withdrawn { color: var(--ink-faint); }

/* ---- the footer is the branding lockup ---------------------------------------------- */
/* The mark, the wordmark set in two lines, and a short row of links — the site mock-up's
   footer. NOT the area journal's rules band: that one names a place and a time, and this tier
   does not know which area a reader means. */
.colophon {
  background: var(--slate);
  color: var(--cream);
  padding: var(--space-6) var(--gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
}
.lockup { display: flex; align-items: center; gap: var(--space-4); }
.mark { width: 40px; height: 40px; flex: none; }
.lockup-name {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: var(--font-display);
  font-size: var(--header);
  line-height: var(--leading-tight);
  color: var(--cream);
}
.colophon-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  align-items: baseline;
  font-size: var(--eyebrow);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--cream-dim);
}
.colophon-links a:hover { color: var(--cream); }
.colophon-note { color: var(--cream-dim); }


/* The mark trailing a headline, as the mock-up sets it: small, on the baseline, part of the
   sentence rather than an ornament beside it. */
.mark-inline {
  width: 0.5em;
  height: 0.5em;
  margin-left: 0.3em;
  vertical-align: baseline;
}

/* ---- the rules, wherever they are shown --------------------------------------------- */
.rules {
  list-style: none;
  margin: var(--space-4) 0 var(--space-6);
  padding: 0;
  display: grid;
  gap: var(--space-3) var(--space-7);
  counter-reset: rule;
  max-width: var(--measure-body);
}
.rules li {
  display: grid;
  grid-template-columns: 3ch minmax(0, 1fr);
  gap: var(--space-3);
  counter-increment: rule;
}
.rules li::before { content: counter(rule, decimal-leading-zero); color: var(--ink-faint); }

/* The one boxed thing, boxed on purpose. */
.write {
  display: inline-block;
  border: var(--rule) solid var(--ink);
  padding: var(--space-3) var(--space-6);
  font-size: 0.8125rem;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
a.write:hover { background: var(--ink); color: var(--paper); text-decoration: none; }
/* No intake address yet, so it is a label rather than a link to nothing. */
.write[aria-disabled] { color: var(--ink-faint); border-color: var(--paper-edge); }

/* ---- content this site did not write ------------------------------------------------ */
/* A cited piece is a contributor's own markdown and may emit any markup it likes. The policy
   in _headers stops it bringing code — no script, no stylesheet of its own, not even a style
   attribute — which leaves this stylesheet as the only one. So the markup is not a problem to
   be sanitised; it is a problem to be STYLED, and these rules are how our styling reaches in.
   Nothing here is a security control. The security control is the policy. */

/* One header size holds inside a letter too, whatever level the author reached for. A piece
   cannot make itself louder than the page it is published on. */
.cited h1, .cited h2, .cited h3,
.cited h4, .cited h5, .cited h6 {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--header);
  line-height: var(--leading-snug);
  margin: var(--space-6) 0 var(--space-2);
  text-wrap: pretty;
}

/* Nothing escapes the measure or the column. */
.cited { max-width: 100%; overflow-wrap: break-word; }
.cited p, .cited li { max-width: var(--measure-body); }
.cited img, .cited svg, .cited video { max-width: 100%; height: auto; }
.cited pre { overflow-x: auto; max-width: 100%; }

/* Tables and blockquotes are the two things prose actually reaches for. Give them a shape
   rather than leaving them to the browser's defaults. */
.cited table { border-collapse: collapse; display: block; overflow-x: auto; max-width: 100%; }
.cited th, .cited td { border-bottom: var(--rule) solid var(--paper-edge); padding: var(--space-2) var(--space-4); text-align: left; }
.cited blockquote {
  margin: var(--space-5) 0;
  padding-left: var(--space-5);
  border-left: 4px solid var(--ink);
  max-width: var(--measure-body);
}

/* Elements that only make sense as someone else's furniture. The policy already stops them
   doing anything; this stops them taking up room. */
.cited iframe, .cited object, .cited embed, .cited form { display: none; }

/* ---- the safe areas ------------------------------------------------------------------ */
/* The layout declares viewport-fit=cover so the landing map can reach the edges of a phone.
   That is only safe if every band that holds words also holds the inset back — otherwise the
   masthead slides under a notch in landscape and the footer under the home indicator. Folded
   into the shared gutter rule rather than bolted on per band, so a band added later inherits
   it instead of being remembered. */
.masthead,
.page,
.colophon {
  padding-left: max(var(--gutter), env(safe-area-inset-left));
  padding-right: max(var(--gutter), env(safe-area-inset-right));
}
.colophon { padding-bottom: calc(var(--space-6) + env(safe-area-inset-bottom)); }

/* ---- the landing is one page, and the map is all of it -------------------------------- */
/* `layout: nccv` with `full: true`. The masthead sits on top, the footer sits on the bottom
   of the SCREEN rather than under a short column, and the map takes everything between. Flex
   on the body does this without measuring anything, which matters: this site ships no
   JavaScript, so a layout that needed to be computed could not exist here. */
body { min-height: 100svh; display: flex; flex-direction: column; }
.masthead, .colophon { flex: none; }
.page { flex: 1 0 auto; }

/* `flex: 1 1 0` and NOT the `1 0 auto` an ordinary page gets. The map is a replaced element
   with an intrinsic aspect ratio, so `auto` makes this band as tall as the drawing wants to be
   — a portrait plate on a wide screen asked for 1694px and pushed the colophon, and the area's
   own name, below the fold. Basis zero means the band takes the space that is LEFT instead of
   asking for space, which is the whole point of a full-page treatment.

   `min-height: 0` on both is the other half: a flex item's default `min-height: auto` refuses
   to shrink below its intrinsic height, which would reintroduce exactly the same overflow. */
.page.full {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  padding: 0;
  min-height: 0;
  overflow: hidden;                    /* the map is cropped by the frame, not by the page */
}

/* Present for a screen reader and for the document outline, absent to the eye. The map is the
   heading here — but "the map is the heading" is not something a heading element can say. */
.said-not-shown {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- the map --------------------------------------------------------------------------- */
/* Baked by bin/bake-map.mjs into lib/map/nccv-map.html; everything below is the ink it is
   drawn in. Keeping the styling here rather than in the artifact means the drawing can be
   retoned without a rebake — and it has to be here anyway, because the policy on this origin
   blocks inline style outright.

   IT IS A PRINTING PLATE, not a slippy map: greys and hairlines, no colour, no labels except
   the areas that publish here. A name on this map is a claim that a node exists there, so
   nothing else gets one. */
.nccv-map {
  flex: 1 1 0;
  min-height: 0;
  width: 100%;
  height: 100%;
  display: block;
  background: var(--paper-warm);
}
/* Strokes are given in viewBox units and must NOT scale with the plate — a hairline that
   thickens on a large screen stops being a hairline. */
.nccv-map path, .nccv-map line { vector-effect: non-scaling-stroke; }

.nccv-hatch { stroke: #A7AEAF; stroke-width: 1; }

.nccv-layer-forest { fill: url(#nccv-map-hatch); stroke: none; }
.nccv-layer-park   { fill: #D8DEDB; stroke: none; }
.nccv-layer-water  { fill: #AEBBC0; stroke: none; }
/* The street mesh. Paler and finer than anything else on the plate, because it is TEXTURE —
   the thing that gives the inside of a town a fabric instead of leaving it as an outline
   around empty paper. It must never compete with the water, which is what the map is actually
   about below the boundaries. Only local streets are in the data; the highways were left out
   at the source, not toned down here. */
.nccv-layer-street { fill: none; stroke: #A5AEAF; stroke-width: 1; }
.nccv-layer-stream { fill: none; stroke: #5F6D70; stroke-width: 1.4; }
.nccv-layer-place  { fill: var(--ink); fill-opacity: 0.05; stroke: #979E9E; stroke-width: 1; }

/* County lines are the region's frame — the thing that makes "Northern Colorado" legible as a
   region rather than a scatter of towns.

   SOLID, not dashed, and that is a consequence of how they are drawn rather than a taste. Each
   county is a closed polygon, so a shared boundary is stroked TWICE, once from each side. Two
   dashed strokes at different phases fill each other's gaps, so an interior line came out solid
   while the outermost county's edge stayed dashed — the convention read as a rendering fault.
   Deduplicating shared edges is a lot of machinery for a hairline. Solid is honest and even. */
.nccv-layer-county { fill: none; stroke: var(--ink-faint); stroke-width: 1.6; }
.nccv-layer-state  { fill: none; stroke: var(--ink); stroke-width: 2.5; }

/* An area that publishes here. Inked, but washed rather than filled — the point of leaving the
   roads out was to see the land underneath, and blacking out the towns would undo it. */
.nccv-node { fill: var(--ink); fill-opacity: 0.05; stroke: var(--ink); stroke-width: 3.5; }

/* ---- the names, which are the only part of this a reader can touch --------------------- */
.nccv-pin { fill: var(--ink); }
/* THE MONO VOICE, not the display one. A place name on a map is a label rather than a
   headline, and the display face read as a title sitting on top of the drawing instead of a
   name belonging to it. Set the way this site already names an area everywhere else — the
   masthead nav is mono, upper-cased and tracked — so the same object looks like itself in both
   places. Tracked caps is also simply what a printed map does with a settlement name.

   The tracking is load-bearing for more than looks: bin/bake-map.mjs measures these labels to
   place them and to decide how far the frame must pull back, and it takes the per-character
   advance from `label_advance` in _config.yml. Change the tracking here and change that too,
   or the collision test is measuring a different label from the one on screen. */
.nccv-name-text {
  font-family: var(--font-mono);
  font-weight: var(--weight-mono-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  fill: var(--ink);
  /* A knockout halo, so a name stays legible over hatching, water, or a county line. The
     stroke is painted UNDER the fill; without paint-order it would eat the letterforms. */
  paint-order: stroke fill;
  stroke: var(--paper-warm);
  stroke-width: 5px;
  stroke-linejoin: round;
}
.nccv-name { cursor: pointer; }
.nccv-name:hover .nccv-name-text { fill: var(--slate); }
.nccv-name:focus-visible { outline: none; }
.nccv-name:focus-visible .nccv-name-text { fill: var(--slate); stroke: var(--lilac); stroke-width: 7px; }
.nccv-name:focus-visible .nccv-pin { fill: var(--slate); }

/* Fine at any size, but the plate is cropped hardest on a phone — give the names a little more
   air there by letting the halo do more work. */
@media (max-width: 40rem) {
  .nccv-name-text { stroke-width: 6px; }
}
