/* ---------- Bill components ---------- */
/* Ported from docs/brand/explorations/a3-the-bill.html (an approved design reference, not code
   to copy wholesale) for KeylineHeading, StageDirection, StatusStamp, RegistrationMarks and
   InstallTicket. Every hex literal from the mockup is replaced with the matching var(--…) token
   emitted by SyntaxCircus.Web. */

/* .mis-type -> .keyline: the "solid vermilion + offset ink keyline" headline treatment
   (BRAND.md §5.3). The base rule also carries the display typography (font-family, weight,
   case) so the component looks correct standalone, without depending on a wrapper class from a
   later task. NEVER give this element padding from any caller - the offset copy is positioned
   via `inset:0` on ::after, so padding on .keyline misaligns the two layers. */
.keyline {
  position: relative;
  isolation: isolate;
  color: var(--spot);
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  line-height: .9;
  margin: 0;
}

/* The " / \"\"" alt text is load-bearing: without it a screen reader would announce this
   generated-content copy of the heading a second time. */
.keyline::after {
  content: attr(data-text) / "";
  position: absolute;
  inset: 0;
  color: transparent;
  -webkit-text-stroke: 1.25px var(--ink);
  transform: translate(.03em, .03em);
  pointer-events: none;
}

@media (max-width: 480px) {
  .keyline::after {
    -webkit-text-stroke-width: 1px;
    transform: translate(.02em, .02em);
  }
}

.keyline--hero {
  font-size: clamp(2.6rem, 15vw, 15.5rem);
}

.keyline--headliner {
  font-size: clamp(2.1rem, 10.5vw, 6.5rem);
}

.keyline--detail {
  font-size: clamp(2.1rem, 10vw, 5.6rem);
}

/* .regmark: decorative poster-corner crosshairs. Always rendered aria-hidden by
   RegistrationMarks.razor - ornamental only, never announced. */
.regmark {
  position: absolute;
  width: 1.4rem;
  height: 1.4rem;
  opacity: .55;
}

.regmark svg {
  width: 100%;
  height: 100%;
  display: block;
}

.regmark.tl {
  top: .9rem;
  left: .9rem;
}

.regmark.tr {
  top: .9rem;
  right: .9rem;
}

.regmark.bl {
  bottom: .9rem;
  left: .9rem;
}

.regmark.br {
  bottom: .9rem;
  right: .9rem;
}

@media (max-width: 640px) {
  .regmark {
    width: 1.05rem;
    height: 1.05rem;
  }
}

/* .ticket: the perforated install-command block used by InstallTicket. The mockup drew its
   punch-hole perforation with ::before/::after circles using border-radius:50%, which the
   brand's "no rounded shapes" rule (BRAND.md, tools/brand/Test-StyleGuards.ps1 rule 4) forbids
   outright - that rule stays absolute, with zero exceptions. The motif itself is kept: a repeating
   radial-gradient paints a row of paper-coloured holes along the top and bottom edges, each circle
   centred exactly on the border so only its inward half shows, reading as a punched/torn edge
   without the CSS property "border-radius" ever appearing. Below ~480px the ticket narrows enough
   that the repeating holes start to look cramped, so they're dropped there rather than left ragged. */
.ticket {
  position: relative;
  border: 1px dashed var(--ink);
  background-color: var(--paper-deep);
  background-image:
    radial-gradient(circle at 50% 0, var(--paper) 0 4px, transparent 4px),
    radial-gradient(circle at 50% 100%, var(--paper) 0 4px, transparent 4px);
  background-repeat: repeat-x, repeat-x;
  background-position: top, bottom;
  background-size: 14px 8px, 14px 8px;
  padding: 1rem 1.2rem;
}

@media (max-width: 480px) {
  .ticket {
    background-image: none;
  }
}

.lib-install code {
  font-size: .85rem;
}

/* .status / .status--live / .status--progress: the StatusStamp badge. --spot is used only as a
   background here (the live badge's text is var(--paper)), never as small text color, per the
   "vermilion never for text below 24px" rule. */
.status {
  font-family: var(--font-label);
  font-weight: 700;
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: .3rem .6rem;
  white-space: nowrap;
}

.status--live {
  background: var(--spot);
  color: var(--paper);
}

.status--progress {
  border: 1px solid var(--ink);
  color: var(--ink);
}

/* .stage-direction: italic aside copy for StageDirection. --font-aside in the mockup maps to
   --font-body (the only body-text token available), set in italic style. */
.stage-direction {
  font-family: var(--font-body);
  font-style: italic;
  color: var(--ink-soft);
  font-size: .95rem;
  margin: 1.6rem 0 0 .3rem;
  max-width: 34rem;
}

.stage-direction + .stage-direction {
  margin-top: .5rem;
}

.sideshow-directions .stage-direction {
  margin: 0;
  max-width: none;
}

/* .ns-index-label / .ns-index / .ns-brace: the namespace index inside InstallTicket. */
.ns-index-label {
  font-family: var(--font-label);
  font-size: .78rem;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: .04em;
  margin: 1.1rem 0 .5rem;
}

.ns-index {
  font-family: var(--font-mono);
  font-size: .78rem;
  line-height: 1.7;
  color: var(--ink-soft);
  margin: 0;
  padding-left: .9rem;
}

.ns-index .ns-brace {
  color: var(--spot-deep);
}

/* .poster / .poster-inner / .poster-kicker / .billhead / .poster-tail / .poster-foot /
   .poster-byline / .program-number: BillHero, ported from a3-the-bill.html lines 226-292. Ink
   band composition below borrows the same "no vermilion" rule (BRAND.md §8) but is a fully
   separate, full-bleed section - never nested inside .poster. */
.poster {
  position: relative;
  padding: clamp(2.6rem, 8vw, 5rem) var(--gutter) clamp(2.2rem, 6vw, 3.4rem);
  border-bottom: 3px solid var(--ink);
  overflow: hidden;
}

.poster-inner {
  max-width: none;
}

.poster-kicker {
  font-family: var(--font-label);
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-size: .82rem;
  color: var(--ink-soft);
  margin: 0 0 1.2rem;
}

/* .billhead is the keyline's caller, not the keyline itself - it must never add padding, only
   spacing that doesn't touch .keyline (see the "NEVER give this element padding" note on
   .keyline above; .billhead's own children carry all their own spacing). */
.billhead {
  margin: 0;
}

.poster-tail {
  display: block;
  font-family: var(--font-billing);
  text-transform: none;
  font-size: clamp(1.6rem, 4.4vw, 2.6rem);
  line-height: 1.1;
  margin-top: .25em;
  text-align: right;
  color: var(--ink);
}

/* .poster-heading-plain: the <h1> BillHero renders instead of the keyline when HeadingText is
   longer than BillHero.HeroKeylineMaxLength. .keyline--hero's type scale (clamp(2.6rem, 15vw,
   15.5rem)) is tuned for a short headline like "SOFTWARE"; a CMS-authored sentence (Headline) or
   the un-migrated Title fallback would otherwise fill multiple screens with giant vermilion type.
   This is a plain, modest heading - same display face as the keyline, but no offset ink copy, no
   data-text, and --ink rather than --spot (vermilion is reserved for the keyline's display-size
   type, never for text this small). */
.poster-heading-plain {
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  line-height: 1.05;
  margin: 0;
  color: var(--ink);
  font-size: clamp(1.6rem, 4vw, 2.6rem);
}

.poster-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 1.4rem 2rem;
  margin-top: 2.4rem;
}

/* Ragged right, per BRAND.md §8 / the mockup's round-2-to-3 change note (was justified). The
   Markdown intro renders its own <p> tags inside this wrapper - margins on those are reset
   here so a single-paragraph intro reads as one flush block. */
.poster-byline {
  font-size: 1.02rem;
  color: var(--ink-soft);
  max-width: var(--measure);
  margin: 0;
  text-align: left;
  flex: 1 1 20rem;
}

.poster-byline p {
  margin: 0 0 1rem;
}

.poster-byline p:last-child {
  margin-bottom: 0;
}

/* The programme-number ticket. --spot-deep only, never --spot - vermilion is reserved for
   display-size type (BRAND.md: "never used for text below 24px; small accents use --spot-deep"). */
.program-number {
  flex: 1 1 16rem;
  min-width: 0;
  max-width: 100%;
  font-family: var(--font-mono);
  font-size: .8rem;
  letter-spacing: .02em;
  color: var(--spot-deep);
  border: 1px solid var(--rule);
  padding: .45rem .7rem;
  margin: 0;
}

/* .band / .band-inner / .band-line / .band-aside: InkBand, ported from a3-the-bill.html's
   ink-band section. The one full-bleed, composition-breaking moment on the page - cream type on
   ink, deliberately not a hero. BRAND.md §8 is explicit that the owner rejected both a giant
   cropped word and vermilion-on-black here during design review, so --spot/--spot-deep must never
   appear anywhere in this block. */
.band {
  position: relative;
  background: var(--ink);
  color: var(--paper);
  border-bottom: 3px solid var(--ink);
  overflow: hidden;
  padding: clamp(2.4rem, 7vw, 3.8rem) 0;
}

.band-inner {
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.band-line {
  font-family: var(--font-billing);
  font-weight: 400;
  text-transform: none;
  font-size: clamp(1.9rem, 5.2vw, 3.7rem);
  line-height: 1.15;
  max-width: 22ch;
  margin: 0;
  color: var(--paper);
}

.band-line em {
  font-family: var(--font-body);
  font-style: italic;
  color: var(--paper);
}

/* StageDirection's own .stage-direction rule sets --ink-soft, which would be nearly invisible on
   the ink background - this is the "cream modifier" the aside needs inside the band, applied by
   descendant selector rather than a Class parameter StageDirection doesn't have. */
.band .stage-direction {
  color: color-mix(in srgb, var(--paper) 82%, transparent);
  margin: 1.2rem 0 0;
  max-width: var(--aside-measure);
}

/* .section / .section--heavy-top / .section-head / .section-num / .section-title /
   .section-intro: the shared shell Headliners and Sideshow both render into, ported from
   a3-the-bill.html lines 304-319 (an approved design reference, not code to copy wholesale).
   Every hex literal from the mockup is replaced with the matching var(--…) token. */
.section {
  position: relative;
  z-index: 1;
  padding: clamp(2.6rem, 6vw, 4.4rem) var(--gutter);
  border-bottom: 1px solid var(--rule);
}

.section--heavy-top {
  border-top: 6px double var(--ink);
}

.section-head {
  display: flex;
  align-items: baseline;
  gap: .9rem;
  margin-bottom: .6rem;
  flex-wrap: wrap;
}

.section-num {
  font-family: var(--font-mono);
  font-size: .85rem;
  color: var(--spot-deep);
}

.section-title {
  font-family: var(--font-label);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  font-size: clamp(1.35rem, 3.4vw, 2rem);
}

.section-intro {
  max-width: 56ch;
  color: var(--ink-soft);
  margin: .8rem 0 2rem;
}

.section-intro p {
  margin: 0 0 1rem;
}

.section-intro p:last-child {
  margin-bottom: 0;
}

/* .headliner*: wide billing rows, paired asides (a3-the-bill.html lines 320-358). Each act's
   name spans the full content width; beneath it a copy + status/aside row shares one grid line.
   Alignment alternates the way a printed bill alternates billing, without moving the shared
   column boundary - .headliner--reverse only flips text-align/align-items, it never touches
   .headliner-row's grid-template-columns, so HeadlinerRow's DOM/grid-track order (and therefore
   keyboard/screen-reader order) never depends on which side a row is mirrored to. The name's own
   type treatment (font, weight, case, size) comes from KeylineHeading's .keyline/.keyline--headliner
   classes, not duplicated here. */
.headliner-list {
  margin-top: .4rem;
}

.headliner {
  padding: 2.2rem 0;
}

.headliner + .headliner {
  border-top: 1px solid var(--rule-light);
}

.headliner-name {
  display: block;
  width: 100%;
  margin-bottom: 1.1rem;
}

.headliner--reverse .headliner-name {
  text-align: right;
}

/* The headliner name now links to the product's own page (Path). Inline in the keyline heading,
   not a separate block-level link, so it keeps .headliner-link's border+hover treatment without
   .headliner-link's own margin/display rules (which are meant for a standalone link below the
   row, not text inside a heading). The name is well over the 24px vermilion floor, so --spot is
   fine for the hover accent here. */
.headliner-name a {
  color: inherit;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: border-color var(--dur-fast) var(--ease-press), text-shadow var(--dur-fast) var(--ease-press);
}

.headliner-name a:hover,
.headliner-name a:focus-visible {
  border-bottom-color: var(--spot);
  text-shadow: 2px 1.5px 0 var(--spot);
}

/* .headliner-tagline: HeadlinerModel.Tagline, a one-line billing phrase above the markdown
   summary - styled distinctly from .headliner-copy's body prose (label face/weight, not the soft
   italic-adjacent body color) so it doesn't get mistaken for the first line of the summary. */
.headliner-copy .headliner-tagline {
  font-family: var(--font-label);
  font-weight: 700;
  font-size: .95rem;
  letter-spacing: .02em;
  color: var(--ink);
  margin: 0 0 .7rem;
}

.headliner-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 18rem;
  gap: 2.5rem;
  align-items: start;
}

@media (max-width: 860px) {
  .headliner-row {
    grid-template-columns: 1fr;
    gap: 1.4rem;
  }
}

.headliner-copy {
  max-width: 58ch;
  color: var(--ink-soft);
  border-left: 2px solid var(--rule-light);
  padding-left: 1.1rem;
}

.headliner-copy p {
  margin: 0 0 1rem;
}

.headliner-copy p:last-child {
  margin-bottom: 0;
}

.headliner--reverse .headliner-copy {
  border-left: none;
  padding-left: 0;
  border-right: 2px solid var(--rule-light);
  padding-right: 1.1rem;
}

.headliner-aside {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
  padding-top: .1rem;
}

.headliner--reverse .headliner-aside {
  align-items: flex-end;
}

.stage-quote {
  font-family: var(--font-body);
  font-style: italic;
  color: var(--ink-soft);
  font-size: 1rem;
  line-height: 1.55;
  border-left: 2px solid var(--spot-deep);
  padding-left: 1rem;
  margin: 0;
}

.headliner--reverse .stage-quote {
  border-left: none;
  border-right: 2px solid var(--spot-deep);
  padding-left: 0;
  padding-right: 1rem;
  text-align: right;
}

/* .sideshow-* / .slip*: pasted handbill slips (a3-the-bill.html lines 398-422). Owner-approved
   exception to the "no cards" anti-pattern. The slip's box-shadow below is the one permitted
   box-shadow in the whole design system - written with color-mix() against --ink rather than
   rgba(), which would need raw colour-channel numbers and reintroduce a literal. Rotation is
   driven purely by the .slip--0/1/2 modifier class Slip.razor computes from `Index % 3`; there is
   no nth-child rule here on purpose, since the class (not DOM position) is the source of truth. */
.sideshow-intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 22rem;
  gap: 2.5rem;
  align-items: start;
  margin: 1.4rem 0 2.2rem;
}

.sideshow-intro .section-intro {
  margin: 0;
}

.sideshow-directions {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* .sideshow-directions .stage-direction's own override already lives in the primitives block
   above (next to .stage-direction itself). */

@media (max-width: 860px) {
  .sideshow-intro {
    grid-template-columns: 1fr;
    gap: 1.4rem;
  }
}

.sideshow-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem 1.6rem;
  margin-top: .5rem;
}

.slip {
  background: var(--paper-deep);
  border: 1px solid var(--ink);
  padding: 1.1rem 1.2rem 1.3rem;
  width: 15.5rem;
  box-shadow: 3px 3px 0 color-mix(in srgb, var(--ink) 18%, transparent);
}

.slip--0 {
  transform: rotate(-1.4deg);
}

.slip--1 {
  transform: rotate(1.1deg);
}

.slip--2 {
  transform: rotate(-.7deg);
}

.slip-name {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 1.25rem;
  color: var(--ink);
  margin: 0 0 .4rem;
}

/* The slip name links to the experiment's own page (Path). slip-name renders at 1.25rem (20px) -
   under the 24px vermilion floor - so the hover accent uses --spot-deep, never --spot, matching
   the "small accents use --spot-deep" rule already applied to .program-number/.section-num. */
.slip-name a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  transition: border-color var(--dur-fast) var(--ease-press);
}

.slip-name a:hover,
.slip-name a:focus-visible {
  border-bottom-color: var(--spot-deep);
  text-shadow: none;
}

.slip-copy {
  font-size: .9rem;
  color: var(--ink-soft);
  margin: 0;
}

.slip-copy p {
  margin: 0 0 .6rem;
}

.slip-copy p:last-child {
  margin-bottom: 0;
}

@media (max-width: 640px) {
  .sideshow-grid {
    flex-direction: column;
    align-items: stretch;
  }

  .slip {
    width: auto;
  }

  .slip--0 {
    transform: rotate(-1deg) translateX(-.4rem);
  }

  .slip--1 {
    transform: rotate(.8deg) translateX(.5rem);
  }

  .slip--2 {
    transform: rotate(-.5deg) translateX(-.3rem);
  }
}

/* .bill-visually-hidden: the standard clip-rect pattern, kept local to this stylesheet rather than
   depending on Bootstrap's .visually-hidden - this library ships on its own and must not assume a
   Bootstrap stylesheet is present. NEVER display:none here - that removes the element from the
   accessibility tree too, defeating the point of a "visible to screen readers only" caption. */
.bill-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* .supporting-intro / .lib-note / .supporting-link: the Supporting Bill's intro row (ported from
   a3-the-bill.html lines 359-397 - a design reference, not code to copy wholesale) and its "All
   libraries" link, sharing .headliner-link's treatment. .project-bill-link (ProjectBill.razor's
   "Visit"/"View source" aside links) shares the same treatment too. */
.supporting-intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 26rem;
  gap: 2.5rem;
  align-items: start;
  margin: 1.4rem 0 2.4rem;
}

.supporting-intro .section-intro {
  margin: 0;
}

.lib-note {
  margin: 0;
  max-width: none;
}

@media (max-width: 860px) {
  .supporting-intro {
    grid-template-columns: 1fr;
    gap: 1.6rem;
  }
}

.headliner-link,
.supporting-link,
.project-bill-link {
  display: inline-block;
  margin-top: .2rem;
  font-family: var(--font-label);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 2px solid var(--spot);
  padding-bottom: .1rem;
  transition: border-bottom-width var(--dur-fast) var(--ease-press), padding-bottom var(--dur-fast) var(--ease-press);
}

.headliner-link:hover,
.supporting-link:hover,
.project-bill-link:hover {
  border-bottom-width: 3px;
  padding-bottom: calc(.1rem - 1px);
}

/* .catalog: the numbered library catalog, a real <table> (LibraryCatalog.razor). Column widths
   were ported from the mockup's .bill-list grid-template-columns (5.2rem 15rem 1fr), but 15rem
   (240px) is too narrow for the package column: the longest real id,
   SyntaxCircus.EntityFrameworkCore.Postgres (41 chars), needs ~335px in the mono face at .85rem,
   so it - and others like SyntaxCircus.AspNetCore.Authentication - wrapped mid-token instead of
   at a '.' boundary. 24rem (384px) fits the longest id on one line with room to spare; the
   description column gives up the difference (15rem -> 24rem) and is still 26.8rem/~429px wide,
   comfortable for prose at .93rem. Ordinals use --spot-deep, never --spot - vermilion is reserved
   for text 24px and up. This desktop table-layout is untouched below 640px, where the
   @media (max-width: 640px) block below restyles rows to stacked blocks instead. */
.catalog {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  margin-top: .5rem;
}

.catalog th:nth-child(1),
.catalog td:nth-child(1) {
  width: 5.2rem;
}

.catalog th:nth-child(2),
.catalog td:nth-child(2) {
  width: 24rem;
}

.catalog thead th {
  font-family: var(--font-label);
  font-size: .78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-soft);
  text-align: left;
  padding: 0 1rem .6rem 0;
  border-bottom: 1px solid var(--rule);
}

.catalog tbody tr {
  border-top: 1px solid var(--rule-light);
}

.catalog tbody tr:last-child {
  border-bottom: 1px solid var(--rule-light);
}

.catalog td {
  padding: .5rem 1rem .5rem 0;
  vertical-align: baseline;
}

.catalog-num {
  font-family: var(--font-mono);
  font-size: .78rem;
  color: var(--spot-deep);
  white-space: nowrap;
}

.catalog-pkg {
  font-family: var(--font-mono);
  font-size: .85rem;
  color: var(--ink);
}

.catalog-pkg a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
}

.catalog-pkg a:hover {
  border-bottom-color: var(--spot);
  text-shadow: none;
}

.catalog-desc {
  color: var(--ink-soft);
  font-size: .93rem;
}

/* Under 640px the rows restyle to stacked blocks. table/thead/tbody/tr/td/th all keep their
   explicit role="..." attributes (set in LibraryCatalog.razor, not here - CSS can't add ARIA
   roles), so switching their display away from the table/table-row/table-cell values never
   strips the implicit table semantics from assistive tech. The header row itself is not
   display:none (that would drop it from the accessibility tree); it uses the same visually-hidden
   clip-rect treatment as .bill-visually-hidden instead, so a screen reader can still read column
   headers at any viewport width. Each stacked cell gets its own printed label from its
   data-label attribute so sighted narrow-viewport readers keep that context too. */
@media (max-width: 640px) {
  .catalog,
  .catalog tbody,
  .catalog tr,
  .catalog td {
    display: block;
    width: auto;
  }

  /* The desktop-only fixed column widths above (.catalog th/td:nth-child(1)/(2): 5.2rem/24rem)
     have higher selector specificity than ".catalog td { width: auto }" just above, so without
     this override they still win the cascade inside this media query and force every stacked
     cell - especially the 24rem (384px) package-id column - to keep its desktop width, pushing
     the whole page wider than the viewport at any width under ~420px. Matching specificity here
     (same nth-child selectors) lets this rule's later source position actually win. */
  .catalog th:nth-child(1),
  .catalog td:nth-child(1),
  .catalog th:nth-child(2),
  .catalog td:nth-child(2) {
    width: auto;
  }

  .catalog thead {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .catalog tbody tr {
    padding: .6rem 0;
  }

  .catalog td {
    padding: .15rem 0;
  }

  .catalog td[data-label]::before {
    /* The " / \"\"" alt text is load-bearing, same reason as .keyline::after: thead is clipped
       (not removed) below 640px, so screen readers still see the real column headers, and this
       generated label would otherwise announce a duplicate of them. */
    content: attr(data-label) ": " / "";
    font-family: var(--font-label);
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ink-soft);
  }
}

/* .prose / .prose-intro / .prose-body / .prose-section / .prose-markdown / .prose-actions /
   .prose-action: the reading layout for prose pages (about, book, writing, contact, privacy,
   custom - ProsePage.razor). Full-width like the other pages (no --measure cap), not the show-bill machinery above -
   this is the reading room, not the poster. No cards, no eyebrows (this brand has neither):
   about-page/book-page's cards and custom-page's sections both arrive here already flattened to
   plain title+body sections by BillContentMapper.MapProse. Section headings are plain h2/h3, never
   .keyline - the solid-vermilion keyline treatment is for display type only, never body text (see
   the "NEVER give this element padding" note on .keyline above for the same "display-only" rule
   applied to spacing). */
.prose {
  padding: clamp(2.6rem, 6vw, 4.4rem) var(--gutter);
  color: var(--ink);
}

.prose > .keyline {
  margin-bottom: 1.4rem;
}

.prose-intro {
  font-size: 1.12rem;
  line-height: 1.65;
  color: var(--ink-soft);
}

.prose-body,
.prose-markdown {
  line-height: 1.65;
  margin-top: 2rem;
}

.prose-intro p,
.prose-body p,
.prose-markdown p {
  margin: 0 0 1.2rem;
}

.prose-intro p:last-child,
.prose-body p:last-child,
.prose-markdown p:last-child {
  margin-bottom: 0;
}

.prose-section {
  margin-top: 2.8rem;
  padding-top: 2rem;
  border-top: 1px solid var(--rule-light);
}

.prose h2 {
  font-family: var(--font-label);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  font-size: clamp(1.3rem, 3vw, 1.7rem);
  color: var(--ink);
  margin: 0 0 1rem;
}

.prose h3 {
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--ink);
  margin: 1.6rem 0 .6rem;
}

/* The brand's link treatment, matching .headliner-link/.supporting-link above: --spot used only
   as a decoration/hover accent, never as small text color (BRAND.md: never for text below 24px).
   Hover/focus thickens the existing underline rather than adding an offset shadow. */
.prose a {
  color: var(--ink);
  text-decoration-line: underline;
  text-decoration-color: var(--spot);
  text-decoration-thickness: 2px;
  text-underline-offset: .18em;
}

.prose a:hover,
.prose a:focus-visible {
  text-decoration-thickness: 3px;
}

.prose-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .75rem 1.5rem;
  margin-top: 2.4rem;
}

.prose-action {
  font-family: var(--font-label);
  font-weight: 700;
  text-decoration-line: underline;
  text-decoration-color: var(--spot);
  text-decoration-thickness: 2px;
  text-underline-offset: .18em;
}

.prose-action:hover,
.prose-action:focus-visible {
  text-decoration-thickness: 3px;
}

/* .project-bill*: the project detail page's billhead (ProjectBill.razor) - "a bill for one act"
   (design spec §5.5). Shaped like HeadlinerRow's own name + copy/aside row (.headliner-row et al.),
   but these classes are the page's own rather than reused from that list-row component, since this
   is a whole page's layout, not one row among many. .project-bill-link's own treatment is shared
   with .headliner-link/.supporting-link above, not duplicated here. */
.project-bill {
  padding: clamp(2.6rem, 6vw, 4.4rem) var(--gutter);
}

/* .project-bill-logo: the project's own logo (ProjectBillModel.LogoUrl), rendered above the title
   rather than inline with it - a plain <img>, never a frame/card wrapper like the deleted
   .project-logo-frame. Omitted entirely (no placeholder) when the model carries no logo. */
.project-bill-logo {
  display: block;
  height: 4.5rem;
  width: auto;
  max-width: 16rem;
  object-fit: contain;
  margin-bottom: 1.2rem;
}

.project-bill-name {
  margin-bottom: .6rem;
}

.project-bill-tagline {
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: .02em;
  color: var(--ink);
  margin: 0 0 2rem;
}

/* .project-bill-tags: a plain list of ProjectBillModel.Tags - deliberately NOT the deleted
   .tag-pill treatment (a bordered/backgrounded chip). Ordinary inline text with a --spot-deep
   separator between entries, same "small accents use --spot-deep, never --spot" rule as
   .section-num/.catalog-num above. */
.project-bill-tags {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem 0;
  list-style: none;
  margin: 0 0 1.6rem;
  padding: 0;
  font-family: var(--font-mono);
  font-size: .82rem;
  color: var(--ink-soft);
}

.project-bill-tags li + li::before {
  content: "/";
  color: var(--spot-deep);
  margin: 0 .5rem;
}

.project-bill-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 18rem;
  gap: 2.5rem;
  align-items: start;
}

@media (max-width: 860px) {
  .project-bill-row {
    grid-template-columns: 1fr;
    gap: 1.4rem;
  }
}

.project-bill-copy {
  max-width: var(--measure);
  color: var(--ink-soft);
  line-height: 1.65;
}

.project-bill-copy p {
  margin: 0 0 1.2rem;
}

.project-bill-copy p:last-child {
  margin-bottom: 0;
}

.project-bill-aside {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
  padding-top: .1rem;
}

/* .feature-list / .feature-row / .feature-num / .feature-title / .feature-body: the project
   detail page's Features, printed as a numbered list in the catalog's own idiom (mono ordinals in
   --spot-deep, rules between rows - matching .catalog/.catalog-num above) rather than a card grid,
   per the brief's explicit "not a card grid" instruction. Renders inside the shared .section/
   .section-head/.section-num/.section-title shell Headliners/SupportingBill/Sideshow already use -
   no new section-shell classes are introduced here. */
.feature-list {
  margin-top: .5rem;
  list-style: none;
  padding: 0;
}

.feature-row {
  display: flex;
  gap: 1.4rem;
  padding: 1.1rem 0;
  border-top: 1px solid var(--rule-light);
}

.feature-row:last-child {
  border-bottom: 1px solid var(--rule-light);
}

.feature-num {
  flex: none;
  font-family: var(--font-mono);
  font-size: .85rem;
  color: var(--spot-deep);
  padding-top: .15rem;
}

/* .feature-copy: the title+body wrapper inside each .feature-row - .feature-row is a flex
   container (see above), so this needs its own flex sizing rather than relying on a block
   default: without it, a long feature title/body can be squeezed against .feature-num's
   flex: none column instead of taking the row's remaining width. */
.feature-copy {
  flex: 1 1 auto;
  min-width: 0;
}

.feature-title {
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--ink);
  margin: 0 0 .35rem;
}

.feature-body {
  color: var(--ink-soft);
  max-width: var(--measure);
}

.feature-body p {
  margin: 0 0 .8rem;
}

.feature-body p:last-child {
  margin-bottom: 0;
}

/* .site-version / .project-children / .prose-reveal: three more live classes that lost their only
   stylesheet when _legacy.scss was deleted alongside the legacy rendering skin - the markup that
   emits them (Web's DynamicPage.razor/Preview.razor) survived the deletion, the rules didn't. Kept
   here rather than in Web's own site.scss because every other Bill-idiom rule already lives in this
   shared stylesheet, and these three render inside content this library owns (ProsePage's
   ChildContent slot, and the project-detail route's child-page nav). */

/* .site-version: the about page's "Site Version: x.y.z" line, rendered inside ProsePage's own
   .prose column (see ProsePage.razor's ChildContent) - so it only needs its own typography, not
   the grid/alignment rules its old .site-version (a cta-panel/profile-panel grid cell) carried. */
.site-version {
  margin-top: 2rem;
  color: var(--ink-soft);
  font-family: var(--font-mono);
  font-size: .8rem;
}

/* .project-children: DynamicPage's "More about {project}" nav, listing a project's child pages.
   Rendered as a direct sibling of ProjectBill (Web's DynamicPage.razor), not inside .project-bill
   itself, so it needs its own copy of .project-bill/.prose's horizontal gutter padding to stay
   aligned with everything above it - a plain bulleted nav in the reading-room idiom, not a card. */
.project-children {
  padding: 2rem var(--gutter) clamp(2.6rem, 6vw, 4.4rem);
  border-top: 1px solid var(--rule-light);
}

.project-children h2 {
  font-family: var(--font-label);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  font-size: clamp(1.3rem, 3vw, 1.7rem);
  color: var(--ink);
  margin: 0 0 1rem;
}

.project-children ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .6rem;
}

/* .prose-reveal: the contact page's progressive email-address <details>/<summary> reveal (Web's
   DynamicPage.razor/Preview.razor). Replaces the native disclosure triangle - which the "keeps its
   default triangle" gap left it stuck with - with a mono +/- cue matching .ns-index/.catalog-num's
   own mono, --spot-deep idiom, rather than leaving the browser's unstyled default. */
.prose-reveal summary {
  cursor: pointer;
  list-style: none;
}

.prose-reveal summary::-webkit-details-marker {
  display: none;
}

.prose-reveal summary::before {
  content: "+ ";
  font-family: var(--font-mono);
  color: var(--spot-deep);
}

.prose-reveal[open] summary::before {
  content: "\2212 ";
}
