/* ByteCode.News brand over PUDL. Any change must keep raised/sunken/flat distinct and meet
   WCAG 2.2 AA contrast; the theme workbench (/_specimen, dev profile) checks every scheme. */
:root {
  --accent: #9f3c1b;
  --accent-hover: #86331a;
}

[data-theme="dark"] {
  --accent: #f08a5d;
  --accent-hover: #f5a57f;
}

.article {
  max-width: 72ch;
  margin: 0 auto;
  padding: var(--space-5) var(--space-4);
}

.article-meta,
.article-tags {
  color: var(--text-muted);
}

.board-title {
  margin: 0;
  font-size: var(--text-md);
}

/* Popular Reads: up to three columns when the stage is wide, one on top of another when narrow.
   Each column is at least 16rem, and never narrower than a third of the row. */
.popular {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(max(16rem, calc((100% - 2 * var(--space-3)) / 3)), 1fr));
  gap: var(--space-3);
  padding: var(--space-4);
}

.popular h2 {
  grid-column: 1 / -1;
  margin: 0;
}

/* The detail pane hosts the article windows, as in PUDL's article-reader sample. */
.board-stage {
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
}

/* One pane at a time on a narrow layout (#85): PUDL hides .md-detail on the list pane, but the
   stage's own display above would show it beside the list. */
@container md (max-width: 640px) {
  .md-layout:not([data-md-pane="detail"]) .board-stage { display: none; }
  /* PUDL makes the detail pane a block; the stage stays a column, so its host has a height. */
  .md-layout[data-md-pane="detail"] .md-detail.board-stage { display: flex; }
}

/* A phone's front page (#92): the board rests on the stage, so the masthead is shorter and the
   list is a link away, at the top and after More Stories. PUDL's back link, which minimises the
   windows, only shows while one covers the stage. Neither link shows on a wide layout, where the
   list is beside the stage. */
.front-to-list, .front-all { display: none; }
@container md (max-width: 640px) {
  .md-layout[data-stage-covered="false"] .md-back[data-win-back],
  .md-layout[data-stage-covered="true"] .front-to-list { display: none; }
  .front-to-list { display: inline-flex; margin: var(--space-3) var(--space-4) var(--space-2); }
  .front-all { display: block; margin: 0; padding: var(--space-3) var(--space-4) var(--space-4); font-weight: 600; }
  .masthead { min-height: 6rem; margin-bottom: var(--space-3); }
  .masthead-text { padding: var(--space-3) var(--space-4); }
  .masthead-date { margin-bottom: var(--space-1); }
  .masthead-tagline { margin-top: var(--space-1); }
}

/* A phone's top bar (#85): the feeds show their icons alone (their names stay for screen
   readers), a long name is cut short, and the controls wrap under the site's name rather than
   push the page sideways. */
@media (max-width: 40rem) {
  .topbar { flex-wrap: wrap; gap: var(--space-2); padding: 8px 12px; }
  .topbar-chrome { flex-wrap: wrap; justify-content: flex-end; margin-left: auto; min-width: 0; }
  .feed-pill { padding-inline: 8px; }
  .feed-label {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .topbar .menu-btn { max-width: 9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }
}

.board-stage .md-back {
  margin: var(--space-3) var(--space-4) var(--space-1);
  align-self: flex-start;
}

/* The host stays put and the stage's content scrolls inside it, as PUDL has it, so the windows
   float over the visible stage (#92). The content ends with room for the Site window's strip,
   the bottom 22% of the host but never shorter than PUDL's smallest window, so its last lines
   can scroll clear of it. */
.board-stage .win-host {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.stage-scroll { position: absolute; inset: 0; overflow: auto; }
.stage-scroll:focus-visible { outline: none; box-shadow: inset 0 0 0 3px var(--focus-ring); }
.win-host:has(> .win-layer > .win[data-win="site"]:not([hidden])) > .stage-scroll::after {
  content: "";
  display: block;
  height: max(22%, min(var(--win-min-h, 200px), 100%));
}
@media print {
  .stage-scroll { position: static; overflow: visible; }
}

.win .article {
  padding: var(--space-2) var(--space-2) var(--space-6);
}

.comments {
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

.comment-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.comment-list .comment-list {
  margin-left: var(--space-5);
  padding-left: var(--space-4);
  border-left: 1px solid var(--border);
}

.comment {
  margin: var(--space-4) 0;
}

.comment-meta,
.comments-none,
.comment-deleted {
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.tag-page {
  max-width: 72ch;
  margin: 0 auto;
  padding: var(--space-5) var(--space-4);
}

.tag-sort {
  margin: var(--space-3) 0 var(--space-5);
}

.tag-cloud {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.launcher-icon {
  width: 14px;
  height: 14px;
  flex: none;
}

.error-page {
  padding: var(--space-6) var(--space-4);
}

/* The Site window (#23): the site's own pages. Hidden until pudl-windows.js removes it when the
   reader closed it before, so it doesn't flash on load. */
.bcn-site-closed .win[data-win="site"] {
  display: none;
}

.site-list {
  list-style: none;
  margin: 0;
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
}

/* Entries sit side by side, each description on one line, so every page shows in the strip. */
.site-list li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 14rem;
  max-width: 22rem;
  min-width: 0;
}

.site-desc {
  color: var(--text-muted);
  font-size: var(--text-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The Site window's body stacks its pages over the System line, which it keeps at the bottom. */
section.win[data-win="site"] .win-body { display: flex; flex-direction: column; }

/* The System line (#82): the API's and ui-pudl's versions, as ui-nextjs's footer, tucked into the
   window's lower right corner. */
.site-system {
  margin: 0;
  padding: 0 var(--space-4) var(--space-3);
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin-top: auto;
  gap: var(--space-1) var(--space-4);
  font: var(--text-xs) var(--mono);
  color: var(--text-muted);
}
.site-system-label { color: var(--accent); text-transform: uppercase; letter-spacing: 0.12em; }

.login-page {
  max-width: 28rem;
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

.login-form {
  display: grid;
  gap: var(--space-4);
  margin: var(--space-4) 0;
}

/* A field's help text, tied to it by aria-describedby. PUDL has .form-error but no hint. */
.form-hint {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin: 0;
}

/* The profile: a readable column like sign-in, a little wider for the dialog's text. */
.profile-page {
  max-width: 36rem;
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

.profile-section {
  margin-top: var(--space-6);
}

.profile-section h2 {
  font-size: var(--text-lg);
}

/* A feature that isn't built yet (#44): a short, readable column. */
.placeholder-page {
  max-width: 36rem;
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

/* Submitting a post (#36): a wider column for writing. */
.submit-page {
  max-width: 48rem;
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

.submit-form { display: grid; gap: var(--space-2); }

.submit-tags { display: flex; gap: var(--space-2); }
.submit-tags .form-input { flex: 1; }

.form-optional { font-weight: 400; color: var(--text-muted); }

/* Text that's written as markup reads best in PUDL's monospace face, as in ui-nextjs. */
.form-mono { font-family: var(--mono); font-size: var(--text-sm); line-height: 1.6; }

/* The spam trap: off-screen rather than display:none, which some bots skip. */
.hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* The emailed sign-in code (#48): set like a code, so six digits are plainly what's wanted. */
.form-input.otp-input {
  height: auto;
  padding: var(--space-3) var(--space-4);
  font-family: var(--mono);
  font-size: 1.75rem;
  letter-spacing: 0.4em;
  text-align: center;
}

/* The site's own feeds in the topbar (#54): the standard feed icon marks them as subscriptions,
   not navigation. The icon is decorative; the label says which feed. */
.feed-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.feed-icon { flex: none; }

/* === Post and comment content (#35) =======================================
   Posts and comments are Markdown the API renders (streampack's
   MarkdownRenderingService: flexmark with tables, task lists, strikethrough and
   subscript, footnotes, asides, admonitions and factoid wiki links). PUDL styles
   an application, not prose, so the text is set here from PUDL's tokens, and
   admonitions borrow PUDL's notices. /_specimen shows every construct as the
   API renders it. */
:is(.article-body, .comment-body) {
  font-size: var(--text-base);
  line-height: 1.65;
  overflow-wrap: break-word;
}

:is(.article-body, .comment-body) :is(p, ul, ol, blockquote, pre, table, aside, .adm-block) {
  margin: 0 0 var(--space-4);
}

:is(.article-body, .comment-body) > :last-child,
:is(.article-body, .comment-body) :is(blockquote, aside, li, .adm-body) > :last-child {
  margin-bottom: 0;
}

:is(.article-body, .comment-body) :is(h2, h3, h4, h5, h6) {
  margin: var(--space-6) 0 var(--space-3);
  line-height: 1.3;
  font-weight: 700;
}
:is(.article-body, .comment-body) h2 { font-size: var(--text-2xl); }
:is(.article-body, .comment-body) h3 { font-size: var(--text-xl); }
:is(.article-body, .comment-body) h4 { font-size: var(--text-lg); }
:is(.article-body, .comment-body) h5 { font-size: var(--text-base); }
:is(.article-body, .comment-body) h6 {
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

:is(.article-body, .comment-body) a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
:is(.article-body, .comment-body) a:hover { text-decoration-thickness: 2px; }

/* Inline code, and code blocks like PUDL's pre.code: monospace, flat, scrolling. */
:is(.article-body, .comment-body) code {
  font-family: var(--mono);
  font-size: 0.9em;
  padding: 0.1em 0.35em;
  border-radius: 4px;
  background: var(--surface-alt);
  overflow-wrap: anywhere;
}
:is(.article-body, .comment-body) pre {
  padding: var(--space-3) var(--space-4);
  overflow-x: auto;
  background: var(--surface-alt);
  border-radius: var(--radius-sm);
  font: var(--text-sm)/1.55 var(--mono);
  tab-size: 4;
}
:is(.article-body, .comment-body) pre code {
  padding: 0;
  background: none;
  font-size: inherit;
  overflow-wrap: normal;
}

:is(.article-body, .comment-body) blockquote {
  padding-inline-start: var(--space-4);
  border-inline-start: 3px solid var(--border);
  color: var(--text-muted);
}

:is(.article-body, .comment-body) hr {
  margin: var(--space-6) 0;
  border: 0;
  border-top: 1px solid var(--border);
}

:is(.article-body, .comment-body) :is(ul, ol) { padding-inline-start: 1.5em; }
:is(.article-body, .comment-body) :is(ul, ol) :is(ul, ol) { margin: var(--space-1) 0 0; }
:is(.article-body, .comment-body) li + li { margin-top: var(--space-1); }

/* Task lists: the box is the marker. */
:is(.article-body, .comment-body) li.task-list-item {
  list-style: none;
  margin-inline-start: -1.5em;
}
:is(.article-body, .comment-body) .task-list-item-checkbox {
  margin: 0 0.4em 0 0;
  vertical-align: -0.1em;
  accent-color: var(--accent);
}

/* Tables: ruled like PUDL's data table, and scrolling inside the text when wide. */
:is(.article-body, .comment-body) table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: var(--text-md);
}
:is(.article-body, .comment-body) :is(th, td) {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border);
  text-align: start;
  vertical-align: top;
}
:is(.article-body, .comment-body) :is(th, td)[align="center"] { text-align: center; }
:is(.article-body, .comment-body) :is(th, td)[align="right"] { text-align: end; }
:is(.article-body, .comment-body) thead th {
  background: var(--surface-alt);
  font-weight: 600;
}

:is(.article-body, .comment-body) img {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
}

/* An aside: a note set off from the main text. */
:is(.article-body, .comment-body) aside {
  padding: var(--space-3) var(--space-4);
  border-inline-start: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--accent) 6%, var(--surface));
  font-size: var(--text-md);
}

/* Footnotes: small references, and the notes below the text. */
:is(.article-body, .comment-body) sup { line-height: 0; }
:is(.article-body, .comment-body) a.footnote-ref { text-decoration: none; padding: 0 0.1em; }
:is(.article-body, .comment-body) .footnotes {
  margin-top: var(--space-6);
  font-size: var(--text-sm);
  color: var(--text-muted);
}
:is(.article-body, .comment-body) .footnotes hr { margin: 0 0 var(--space-3); }
:is(.article-body, .comment-body) .footnotes li p { display: inline; }
:is(.article-body, .comment-body) a.footnote-backref { margin-inline-start: 0.3em; }

/* Admonitions, as PUDL notices: a coloured edge and the glyph of their kind. The
   renderer puts an icon sprite (.adm-hidden) at the top of every post and points
   each icon into it, but the API's sanitizer strips those references, so the
   sprite is hidden and PUDL's glyphs stand in for the empty icons. Collapsible
   ones (??? and ???+) stay open, as on bytecode.news. */
:is(.article-body, .comment-body) .adm-hidden,
:is(.article-body, .comment-body) .adm-icon { display: none; }
:is(.article-body, .comment-body) .adm-block {
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border));
  border-inline-start: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--accent) 9%, var(--surface));
  font-size: var(--text-md);
}
:is(.article-body, .comment-body) .adm-heading {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4) 0;
  font-weight: 700;
}
:is(.article-body, .comment-body) .adm-heading::before {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  background: var(--accent);
  -webkit-mask: var(--glyph-info) center / contain no-repeat;
  mask: var(--glyph-info) center / contain no-repeat;
}
:is(.article-body, .comment-body) .adm-body {
  display: block;
  padding: var(--space-1) var(--space-4) var(--space-3);
}
/* Each kind's colour and glyph, written out: brand.css may only set PUDL's theme tokens. */
.article-body :is(.adm-tip, .adm-hint, .adm-success, .adm-faq, .adm-question), .comment-body :is(.adm-tip, .adm-hint, .adm-success, .adm-faq, .adm-question) {
  border-color: color-mix(in srgb, var(--positive) 45%, var(--border));
  border-inline-start-color: var(--positive);
  background: color-mix(in srgb, var(--positive) 9%, var(--surface));
}
.article-body :is(.adm-tip, .adm-hint, .adm-success, .adm-faq, .adm-question) .adm-heading::before, .comment-body :is(.adm-tip, .adm-hint, .adm-success, .adm-faq, .adm-question) .adm-heading::before {
  background: var(--positive);
  -webkit-mask-image: var(--glyph-check);
  mask-image: var(--glyph-check);
}
.article-body :is(.adm-warning, .adm-caution, .adm-attention), .comment-body :is(.adm-warning, .adm-caution, .adm-attention) {
  border-color: color-mix(in srgb, var(--warn) 45%, var(--border));
  border-inline-start-color: var(--warn);
  background: color-mix(in srgb, var(--warn) 9%, var(--surface));
}
.article-body :is(.adm-warning, .adm-caution, .adm-attention) .adm-heading::before, .comment-body :is(.adm-warning, .adm-caution, .adm-attention) .adm-heading::before {
  background: var(--warn);
  -webkit-mask-image: var(--glyph-warning);
  mask-image: var(--glyph-warning);
}
.article-body :is(.adm-danger, .adm-error, .adm-fail, .adm-failure, .adm-bug), .comment-body :is(.adm-danger, .adm-error, .adm-fail, .adm-failure, .adm-bug) {
  border-color: color-mix(in srgb, var(--danger) 45%, var(--border));
  border-inline-start-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 9%, var(--surface));
}
.article-body :is(.adm-danger, .adm-error, .adm-fail, .adm-failure, .adm-bug) .adm-heading::before, .comment-body :is(.adm-danger, .adm-error, .adm-fail, .adm-failure, .adm-bug) .adm-heading::before {
  background: var(--danger);
  -webkit-mask-image: var(--glyph-stop);
  mask-image: var(--glyph-stop);
}
.article-body :is(.adm-example, .adm-quote, .adm-abstract), .comment-body :is(.adm-example, .adm-quote, .adm-abstract) {
  border-color: color-mix(in srgb, var(--text-muted) 45%, var(--border));
  border-inline-start-color: var(--text-muted);
  background: color-mix(in srgb, var(--text-muted) 9%, var(--surface));
}
.article-body :is(.adm-example, .adm-quote, .adm-abstract) .adm-heading::before, .comment-body :is(.adm-example, .adm-quote, .adm-abstract) .adm-heading::before {
  background: var(--text-muted);
}

/* The specimen's post: a readable column, as on an article page. */
.specimen-post { max-width: 46rem; }

/* The knowledge base (#34): the list is PUDL's data table, a factoid its attributes. */
.factoids-page {
  max-width: 60rem;
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}
.factoids-summary, .factoid-meta { color: var(--text-muted); font-size: var(--text-sm); }
.factoids-intro { padding: var(--space-5); max-width: 40rem; }
.factoids-intro h2 { font-size: var(--text-xl); margin: 0 0 var(--space-2); }
.factoid-attributes { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-3) var(--space-5); margin: var(--space-5) 0; }
.factoid-attributes dt { font-weight: 600; color: var(--text-muted); font-size: var(--text-sm); }
.factoid-attributes dd { margin: 0; overflow-wrap: anywhere; line-height: 1.6; }
.factoid-attributes dd .chip { margin-inline-end: var(--space-1); }
@media (max-width: 40rem) {
  .factoid-attributes { grid-template-columns: 1fr; gap: var(--space-1); }
  .factoid-attributes dd { margin-bottom: var(--space-3); }
}

/* The RSS Reader (#64): items as a plain list, each linking out. */
.rss-latest, .rss-feed { padding: var(--space-4) var(--space-5); }
.rss-latest h2 { font-size: var(--text-xl); margin: 0 0 var(--space-3); }
.rss-page { max-width: 48rem; margin: 0 auto; padding: var(--space-6) var(--space-4); }
.rss-items { list-style: none; margin: 0; padding: 0; }
.rss-item { padding: var(--space-2) 0; border-bottom: 1px solid var(--border); }
.rss-item:last-child { border-bottom: 0; }
.rss-item-title { display: block; font-weight: 600; overflow-wrap: anywhere; }
.rss-item-meta, .rss-feed-meta, .rss-none { color: var(--text-muted); font-size: var(--text-sm); }

/* Channel logs (#65): a day of lines, time and sender then what was said. */
.logs-intro, .log-day-window { padding: var(--space-4) var(--space-5); }
.logs-intro { max-width: 40rem; }
.logs-intro h2 { font-size: var(--text-xl); margin: 0 0 var(--space-2); }
.logs-page { max-width: 60rem; margin: 0 auto; padding: var(--space-6) var(--space-4); }
.log-days { display: flex; align-items: center; gap: var(--space-4); margin-bottom: var(--space-3); font-size: var(--text-sm); }
.log-day { color: var(--text-muted); }
.log-lines { list-style: none; margin: 0; padding: 0; font: var(--text-sm)/1.55 var(--mono); }
.log-lines li { padding: 1px 0; overflow-wrap: anywhere; }
.log-time { color: var(--text-muted); text-decoration: none; }
.log-time:hover { text-decoration: underline; }
/* A line opened by its permalink (#72). */
.log-lines li { scroll-margin-top: var(--space-6); }
.log-lines li:target { background: color-mix(in srgb, var(--accent) 16%, transparent); outline: 1px solid var(--accent); }
.log-content a { color: var(--accent); overflow-wrap: anywhere; }
/* Nicks in colour, the same every time (#72): PUDL's syntax colours, checked in both themes. */
.nick-0 { color: var(--syntax-keyword); }
.nick-1 { color: var(--syntax-string); }
.nick-2 { color: var(--syntax-number); }
.nick-3 { color: var(--syntax-name); }
.nick-4 { color: var(--syntax-tag); }
.nick-5 { color: var(--syntax-attr); }
.nick-6 { color: var(--syntax-error); }
.log-sender { font-weight: 700; }
.log-outbound .log-content, .log-system .log-content { color: var(--text-muted); }
.log-system .log-content { font-style: italic; }
.log-none { color: var(--text-muted); }

/* Tags as a board (#66): the cloud on the stage, a tag's posts in its window. */
.tag-stage { padding: var(--space-4) var(--space-5); }
.tag-posts { padding: var(--space-4) var(--space-5); }
.tag-post-list { list-style: none; margin: 0 0 var(--space-3); padding: 0; }
.tag-post-list li { padding: var(--space-2) 0; border-bottom: 1px solid var(--border); }
.tag-post-list li:last-child { border-bottom: 0; }
.tag-post-list a { font-weight: 600; }
.tag-post-list time, .tag-posts-none { display: block; color: var(--text-muted); font-size: var(--text-sm); }

/* The karma leaderboard (#67): highest and lowest side by side, stacked when narrow. */
.karma-page { max-width: 64rem; margin: 0 auto; padding: var(--space-6) var(--space-4); }
.karma-intro { color: var(--text-muted); }
.karma-limit { margin: var(--space-4) 0; }
.karma-boards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr)); gap: var(--space-5); align-items: start; }
.karma-boards caption { text-align: start; font-weight: 700; padding: 0 0 var(--space-2); }
.karma-window { display: grid; gap: var(--space-4); padding: var(--space-3) var(--space-4); }
.karma-window caption { text-align: start; font-weight: 700; padding: 0 0 var(--space-2); }
.karma-none { color: var(--text-muted); }

/* The front page's masthead (#78): the date, the name and the tagline over an ambient animation,
   as the landing content of the board's stage, above Popular. Windows opened over the board
   cover it, and its animation pauses while they do. Colours are PUDL's accent, faint. */
.masthead {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 13rem;
  display: grid;
  place-items: center;
  margin: 0 0 var(--space-4);
  border-top: 3px solid var(--accent);
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
}
.masthead-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  color: color-mix(in srgb, var(--accent) 25%, var(--border));
  opacity: 0.55;
}
.masthead-circuit-traces { fill: none; stroke: url(#masthead-fade); stroke-width: 1.15; stroke-linecap: round; stroke-linejoin: round; }
.masthead-circuit-nodes circle { fill: color-mix(in srgb, var(--accent) 18%, var(--bg)); opacity: 0.5; }
.masthead-glow { stop-color: var(--accent); }
.masthead-spark { fill: var(--accent); }
.masthead-trace { fill: none; stroke: color-mix(in srgb, var(--accent) 45%, var(--border)); stroke-width: 1; }
.masthead-text { text-align: center; padding: var(--space-5) var(--space-4); }
.masthead-date {
  margin: 0 0 var(--space-3);
  font: var(--text-xs) var(--mono);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.masthead-name {
  margin: 0;
  font-size: clamp(2.5rem, 7vw, 4.75rem);
  font-weight: 700;
  line-height: 0.95;
  letter-spacing: -0.04em;
}
.masthead-name a { color: var(--text); text-decoration: none; }
.masthead-dot { color: var(--accent); }
.masthead-tagline {
  margin: var(--space-3) 0 0;
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}
@media (max-width: 40rem) {
  .masthead { min-height: 9rem; }
}

/* Latest Dispatches (#84), under the masthead as on bytecode.news: the lead beside the next two,
   and More Stories in columns under them. Laid out by the stage's width, not the viewport's. */
.dispatches {
  container-type: inline-size;
  padding: 0 var(--space-4) var(--space-4);
  border-bottom: 1px solid var(--border);
}
.dispatches-label,
.dispatch-more-label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
  font: 600 var(--text-xs) var(--font);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.dispatches-label::after,
.dispatch-more-label::after { content: ""; flex: 1; border-top: 1px solid var(--border); }
.dispatch-more-label { margin-top: var(--space-5); }
.dispatches article { min-width: 0; }
.dispatch-byline,
.dispatch-author {
  margin: 0 0 var(--space-2);
  font: var(--text-xs) var(--mono);
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.dispatch-author { margin: var(--space-2) 0 0; }
.dispatch-sep { color: var(--border); }
.dispatch-title { margin: 0; font-weight: 700; line-height: 1.2; }
.dispatch-title a { color: var(--text); text-decoration: none; }
.dispatch-title a:hover,
.dispatch-title a:focus-visible { color: var(--accent); text-decoration: underline; }
.dispatch-lead .dispatch-title { font-size: var(--text-2xl); letter-spacing: -0.02em; }
.dispatch-secondary .dispatch-title { font-size: var(--text-xl); }
.dispatch-more .dispatch-title { font-size: var(--text-base); }
.dispatch-excerpt {
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--text-muted);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.dispatch-lead .dispatch-excerpt { font-size: var(--text-base); max-width: 42rem; margin-top: var(--space-3); }
.dispatch-secondary .dispatch-excerpt { -webkit-line-clamp: 3; line-clamp: 3; }
.dispatch-more .dispatch-excerpt { -webkit-line-clamp: 2; line-clamp: 2; }
.dispatch-more .dispatch-byline { margin: var(--space-2) 0 0; }
.dispatch-tags { display: flex; flex-wrap: wrap; gap: var(--space-1); margin: var(--space-3) 0 0; }
.dispatch-tags a { color: inherit; text-decoration: none; }
.dispatch-read {
  display: inline-block;
  margin-top: var(--space-3);
  font: 600 var(--text-xs) var(--font);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}
.dispatches-top { display: grid; gap: var(--space-5); }
.dispatch-secondary { display: grid; gap: var(--space-4); }
.dispatch-secondary article + article { border-top: 1px solid var(--border); padding-top: var(--space-4); }
.dispatch-more { display: grid; gap: var(--space-4) var(--space-5); }
@container (min-width: 40rem) {
  .dispatch-lead .dispatch-title { font-size: var(--text-3xl); }
  .dispatches-top { grid-template-columns: 3fr 2fr; }
  .dispatch-lead { padding-right: var(--space-5); border-right: 1px solid var(--border); }
  .dispatch-more { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container (min-width: 60rem) {
  .dispatch-more { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ?ambientDebug=1 names the running animation and its seed in the masthead's corner (#97). */
.masthead-debug {
  position: absolute;
  right: var(--space-2);
  bottom: var(--space-1);
  margin: 0;
  font: var(--text-2xs) var(--mono);
  color: var(--text-muted);
}

/* The masthead's variants (#78), as ui-nextjs styles them, in PUDL's accent. */
.masthead-boids { opacity: 0.8; }
.masthead-terrainflight { opacity: 0.78; }
.masthead-terrain-horizon { fill: none; stroke: color-mix(in srgb, var(--accent) 54%, var(--bg)); stroke-width: 1.25; opacity: 0.48; }
.masthead-terrain-ridge { fill: none; stroke: color-mix(in srgb, var(--accent) 68%, var(--bg)); stroke-linecap: round; stroke-linejoin: round; }
.masthead-terrain-glow { fill: none; stroke: var(--accent); stroke-linecap: round; stroke-linejoin: round; filter: blur(2px); }
.masthead-life { opacity: 0.5; }
.masthead-life-cells { fill: color-mix(in srgb, var(--accent) 52%, var(--bg)); shape-rendering: crispEdges; }
.masthead-signalnoise { fill: color-mix(in srgb, var(--accent) 66%, var(--bg)); shape-rendering: crispEdges; }
.masthead-noise-line { opacity: 0.35; }
.masthead-noise-scan { opacity: 0.3; }
.masthead-noise-band { opacity: 0.22; }
.masthead-fractal { fill: none; stroke: var(--accent); stroke-linecap: round; stroke-linejoin: round; }
/* The fractal's lines are fine and the art is squashed to fit, so it's lifted out of the art's
   fade and its lines are a little heavier than ui-nextjs's (#98). */
.masthead[data-masthead="fractal"] .masthead-art { opacity: 0.85; }
.masthead-fractal-glow { opacity: 0.2; stroke-width: 5; }
.masthead-fractal-trunk { opacity: 0.8; stroke-width: 2; }
.masthead-fractal-branches { opacity: 0.66; stroke-width: 1.4; }
.masthead-fractal-twigs { opacity: 0.5; stroke-width: 1; }
.masthead-fractal-tips { opacity: 0.82; stroke: none; }
/* The Solari board in PUDL's own flaps, edges and accent, lifted out of the art's fade but kept
   behind the name. The date and tagline keep a halo where they cross it. */
.masthead[data-masthead="solari"] .masthead-art { opacity: 1; }
/* The small lines keep a halo of the page's background where they cross a flap or a branch. */
.masthead:is([data-masthead="solari"], [data-masthead="fractal"]) :is(.masthead-date, .masthead-tagline) {
  text-shadow: 0 0 3px var(--bg), 0 0 6px var(--bg), 0 0 10px var(--bg);
}
/* The layer (.masthead-solari) holds the board: 0.2, the strength approved when the layer and
   the board, sharing a class, each took 0.45. The board shows a front-page dek (#81). */
.masthead-solari { opacity: 0.2; font: 700 20px var(--mono); }
.masthead-solari-cell { fill: var(--surface-alt); stroke: var(--border); stroke-width: 0.7; }
.masthead-solari-hinge { stroke: var(--border); stroke-width: 0.6; }
.masthead-solari-glyph { fill: var(--accent); }
