/* ═══════════════════════════════════════════════════════════════════════════
   wcn-pressroom — shared design tokens and components

   The design system of record is wcn-mainpage/index.html. This file is ported
   from wcn-calendar/assets/css/wcn.css, which is itself the maintained port of
   it — taking it second-hand is deliberate: the calendar's copy has already had
   its token values re-derived against this exact teal ground (see --muted below),
   which is the same ground this site uses. Porting from the mainpage directly
   would mean redoing that arithmetic.

   The token block is copied verbatim INCLUDING its comments, because those
   comments are the accessibility derivations — a number without its derivation
   gets "cleaned up" by the next person.

   WHAT THIS REPLACED
       assets/css/brand.css, which Publii's theme wore. That file opened with
       `@import url('https://fonts.googleapis.com/css2?family=Raleway…')`, making
       this the last WCN public page calling a third party on every load —
       against CANON's zero-third-party rule, and the exact thing ILBTYD and the
       mainpage self-host Raleway to avoid. Retiring the Publii theme retires
       that call as a side effect rather than as a separate errand.

       It also retires _rebrand.sh: Publii rewrote </head> on every publish and
       dropped the brand.css link, so a sudo script had to run on production
       afterwards to put it back. Nothing patches production any more.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Type ─────────────────────────────────────────────────────────────────────
   Variable font, self-hosted. CANON's zero-third-party-request rule outranks the
   brand kit's Google Fonts sourcing note. This closes WCN-TODO.md:224 for this
   surface — the page this replaces called fonts.googleapis.com on every load. */

/* The file's wght axis is 100–900 (verified against its fvar table). ILBTYD and
   the walkthrough page declare `200 400` because that is all they use; copying
   that descriptor here would silently lock out every weight above 400 on a page
   that needs 600 for the stat figures. Same 43 KB file, full range. */
@font-face {
  font-family: 'Raleway';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/raleway-latin-var.woff2') format('woff2');
}

/* Metric-matched fallback so the swap changes letterforms without reflowing.
   102% is measured (derivation on the ILBTYD site) — Raleway at weight 200 sets
   ~2% wider than the local grotesque. */
@font-face {
  font-family: 'Raleway Fallback';
  src: local('Helvetica Neue'), local('Arial');
  size-adjust: 102%;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* Company teal + off-white is the brand kit's designed pairing for the company
     mark. Off-white is #f4f4f4, NOT white — "the distinction matters." */
  --teal:      #216869;
  --teal-deep: #1a5354;
  --fg:        #f4f4f4;

  /* ── Why 0.82 and not ILBTYD's 0.55 ──────────────────────────
     This token could not be ported directly. On ILBTYD's pure black,
     rgba(255,255,255,0.55) composites to ~#8c8c8c and clears AA at 5.3:1.
     On teal the background is far lighter (relative luminance 0.113 vs 0.000),
     so the same 55% lands at 2.92:1 — failing AA for both normal AND large text,
     while being used for form labels, table cells, and body copy.
     0.82 composites to ~#ced9d9 and measures 4.54:1. Still visibly recessive
     against #f4f4f4, and actually readable. Do not lower it. */
  --muted:     rgba(244, 244, 244, 0.82);

  /* Decorative only — non-text, or text that is redundant with a real label.
     Never used for anything a reader must actually read.

     It has a second job on this page: it is the universal pill edge. Composited
     on teal it measures 3.20:1, which clears WCAG 1.4.11's 3:1 floor for the
     boundary of a non-text UI component. That matters because two of the pill
     fills below (sage 2.03:1, coral 2.09:1) do NOT clear 3:1 against the ground
     on their own — without this edge those pills would be shapes you have to
     hunt for. Every pill gets it, including the ones that don't need it, so the
     row reads as one system. */
  --muted-dim: rgba(244, 244, 244, 0.6);
  --hairline:  rgba(244, 244, 244, 0.16);

  /* Catalyst amber. Amber-on-teal measures 3.13:1 — it clears WCAG AA for LARGE
     text only, so it is used on display figures (≥24px) and never on body copy,
     small links, or pill labels. */
  --amber:     #f4a261;

  /* ── Pill fills, and why the ink is not brand charcoal ───────
     Event pills invert the page: brand hue as FILL, dark ink as TEXT. The obvious
     approach — brand hue as colored text on the teal ground — was measured and
     abandoned. On #216869, sage lands at 2.03:1 and coral at 2.09:1 as
     foreground. Both fail AA for every text size. Only --fg (5.87:1) and --muted
     (4.54:1) survive as text directly on the ground, which is not enough hues to
     carry a six-value taxonomy.

     The ink is #0e1614, not the brand kit's Charcoal #2d3436. Charcoal was tried
     first and reaches only 3.97:1 on sage and 4.10:1 on coral — under AA for the
     small text a pill label is. #0e1614 clears every fill with room to spare.
     Measured, against each fill:
       amber  #f4a261 → 8.91:1      gold  #EAAA00 → 8.96:1
       sage   #49a078 → 5.76:1      coral #e76f51 → 5.94:1
       fg     #f4f4f4 → 16.70:1
     If you add a fill, measure it against this ink before shipping it. */
  --ink:       #0e1614;
  --sage:      #49a078;
  --coral:     #e76f51;
  --gold:      #EAAA00;

  --pad: clamp(1.75rem, 5vw, 4.5rem);
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  background: var(--teal);
  color: var(--fg);
  font-family: 'Raleway', 'Raleway Fallback', system-ui, -apple-system, sans-serif;
  font-weight: 300;
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* ── Ghost watermark ──────────────────────────────────────────────────────────
   The master "?" mark, bleed-cropped off the lower-left, as texture rather than
   decoration. position:fixed so it stays put while the page scrolls past it.

   The main site uses 0.065 at this exact geometry. This page uses 0.045, and that
   is a deliberate re-derivation, not a copying error. Equal alpha is not equal
   presence: on the main site the mark sits behind a sparse hero, whereas here it
   passes behind a stat row and a six-column data table. Rendered at 0.065 the
   curve of the "?" cut visibly through the table's hairline rules and behind the
   tabular figures — texture becoming interference. 0.045 keeps it as ground.

   If you change the watermark's SIZE, or put denser content over it, re-render
   before trusting this number. */
.watermark {
  position: fixed;
  left: -8vmin;
  bottom: -18vmin;
  height: min(120vh, 160vw);
  width: auto;
  fill: var(--fg);
  opacity: 0.045;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}

/* ── Nav, top right ───────────────────────────────────────────────────────────
   Quiet by design: findable when looked for, not announced. pointer-events:none
   on the container so the bar never eats clicks meant for the page beneath it;
   the links themselves re-enable it. */
.nav {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 10;
  display: flex;
  gap: clamp(1.1rem, 2.6vw, 2.25rem);
  padding: var(--pad);
  pointer-events: none;
}

.nav a {
  pointer-events: auto;
  color: var(--fg);
  text-decoration: none;
  font-weight: 300;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  opacity: 0.5;
  transition: opacity 200ms ease;
}

.nav a:hover,
.nav a:focus-visible,
.nav a[aria-current="page"] { opacity: 1; }

/* ── Focus ring, universal and deliberate ─────────────────────────────────── */
:focus-visible {
  outline: 2px solid var(--fg);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ── Layout ───────────────────────────────────────────────────────────────── */
main {
  position: relative;
  z-index: 1;
  padding: var(--pad);
  padding-top: clamp(5rem, 14vh, 8rem);
}

.wrap  { width: 100%; max-width: 76rem; margin-inline: auto; }

section + section {
  margin-top: clamp(3rem, 8vh, 5rem);
  padding-top: clamp(3rem, 8vh, 5rem);
  border-top: 1px solid var(--hairline);
}

/* ── Type scale ───────────────────────────────────────────────────────────── */
h1 {
  font-weight: 200;
  font-size: clamp(1.75rem, 4.5vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h2 {
  font-weight: 200;
  font-size: clamp(1.4rem, 3vw, 2rem);
  line-height: 1.15;
  letter-spacing: -0.015em;
}

h3 { font-weight: 400; font-size: 1rem; }

.lede {
  font-weight: 300;
  font-size: clamp(1.05rem, 2vw, 1.3rem);
  max-width: 44rem;
  color: var(--muted);
  margin-top: 0.75rem;
}

/* The single most repeated motif in the system: tiny, uppercase, wide-tracked. */
.eyebrow,
.section-label {
  font-size: 0.68rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--muted);
}

.section-label { display: block; margin-bottom: 0.9rem; }

/* ── The card: hairline box, no fill, no radius, no shadow ────────────────────
   This is the only card in the system. Resist adding a background or a radius —
   the whole visual identity is that surfaces are defined by a 1px line and
   nothing else. */
.box {
  border: 1px solid var(--hairline);
  padding: clamp(1.25rem, 3vw, 2rem);
}

/* ── Stat tiles ───────────────────────────────────────────────────────────── */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  border: 1px solid var(--hairline);
}

/* Hairline dividers via borders on the cells rather than gap-over-background:
   the grid reflows at every breakpoint and a faked-gap approach leaves stray
   lines dangling at the wrap points. */
.stat {
  padding: clamp(1.1rem, 3vw, 1.6rem);
  border-right: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}

.stat:last-child { border-right: none; }

.stat-figure {
  display: block;
  font-size: clamp(2rem, 6vw, 3.25rem);
  font-weight: 200;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

/* Amber is legal here and nowhere else on this page: these figures are ≥32px,
   which is comfortably inside "large text" where 3.13:1 clears AA. */
.stat-figure.accent { color: var(--amber); }

/* An un-instrumented figure renders as an em dash. It is deliberately --muted-dim
   rather than --muted: the dash is not information the reader must extract, the
   footnote beneath it is. */
.stat-figure.unset { color: var(--muted-dim); font-weight: 100; }

.stat-label {
  display: block;
  margin-top: 0.6rem;
  font-size: 0.65rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
}

.stat-note {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.65rem;
  color: var(--muted-dim);
  font-style: italic;
  letter-spacing: 0.02em;
}

/* ── Em-dash list — the system's bullet ───────────────────────────────────── */
.contract { list-style: none; }
.contract li { position: relative; padding-left: 1.5rem; margin-bottom: 0.5rem; }
.contract li::before { content: "—"; position: absolute; left: 0; color: var(--muted); }
.contract li.pending::before { content: "○"; }

/* ── Ghost button ─────────────────────────────────────────────────────────── */
.btn {
  background: none;
  border: 1px solid var(--fg);
  color: var(--fg);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  padding: 0.85rem 1.75rem;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  transition: background 180ms ease, color 180ms ease;
}

.btn:hover:not(:disabled) { background: var(--fg); color: var(--teal); }

/* ── Footer ───────────────────────────────────────────────────────────────── */
.foot {
  margin-top: clamp(3rem, 8vh, 5rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--hairline);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  align-items: baseline;
  font-size: 0.68rem;
  color: var(--muted-dim);
  letter-spacing: 0.06em;
}

.foot a { color: var(--muted); }
.foot .domain { margin-left: auto; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.err {
  border: 1px solid var(--amber);
  padding: 0.9rem 1.1rem;
  color: var(--muted);
  font-size: 0.85rem;
}

/* ── Motion and density guards ────────────────────────────────────────────── */
@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;
  }
}

@media (max-width: 40rem) {
  .nav { position: static; padding: 0 0 1.5rem; justify-content: flex-start; }
  main { padding-top: var(--pad); }
  .stat:nth-child(2n) { border-right: none; }
}

/* ── Release list ─────────────────────────────────────────────────────────────
   The index is a list of dated releases and nothing else. No cards, no
   thumbnails, no excerpt-with-"read more" — a press room's job is to let someone
   find the announcement they came for and read it, and every one of those
   devices puts furniture between the reader and that.

   Rows are separated by the same 1px hairline that defines every other surface
   in the system. The date leads, because for a press release the date IS part of
   the claim. */
.releases { list-style: none; }

.release {
  display: grid;
  grid-template-columns: 8.5rem 1fr;
  gap: 0 clamp(1rem, 3vw, 2.5rem);
  padding: clamp(1.4rem, 3.5vh, 2.1rem) 0;
  border-bottom: 1px solid var(--hairline);
}

.release:last-child { border-bottom: none; }
.release:first-child { padding-top: 0; }

/* The date column collapses under the title on narrow screens rather than
   squeezing — a wrapped date reads as two dates. */
@media (max-width: 34rem) {
  .release { grid-template-columns: 1fr; gap: 0.4rem; }
}

.release-date {
  font-size: 0.68rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
  padding-top: 0.45rem;   /* optically aligns the small caps to the title's cap-height */
  white-space: nowrap;
}

.release-title {
  font-weight: 300;
  font-size: clamp(1.1rem, 2.2vw, 1.45rem);
  line-height: 1.25;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.release-title a {
  color: var(--fg);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 180ms ease;
}

.release-title a:hover { border-bottom-color: var(--fg); }

.release-summary {
  margin-top: 0.5rem;
  color: var(--muted);
  font-size: 0.95rem;
  max-width: 46rem;
}

/* ── Article prose ────────────────────────────────────────────────────────────
   Scoped to .prose so it only ever applies to authored release bodies, never to
   page chrome. The bodies carry Publii-era markup — h2/h3/hr/p/strong/a/br — and
   that is left exactly as published. Restyling it is fair; rewriting the text of
   a released announcement is not.

   The measure is capped at 42rem. These are press releases: they are read
   start-to-finish by a person, not scanned, and long teal-on-off-white lines are
   where that falls apart. */
.prose {
  max-width: 42rem;
  font-size: 1.02rem;
  line-height: 1.75;
}

.prose > * + * { margin-top: 1.15rem; }

.prose h2 {
  font-weight: 200;
  font-size: clamp(1.3rem, 2.6vw, 1.75rem);
  margin-top: 2.4rem;
  text-wrap: balance;
}

/* "FOR IMMEDIATE RELEASE" and the boilerplate headings. Small, tracked, muted —
   the same eyebrow motif, because that is exactly what they are. */
.prose h3 {
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--muted);
  margin-top: 2rem;
}

/* Publii used <hr> as a section divider between the release, the boilerplate and
   the contact block. Kept as a hairline rather than deleted: it is load-bearing
   structure in a press release, marking where the announcement stops and the
   About/Contact matter starts. */
.prose hr {
  border: none;
  border-top: 1px solid var(--hairline);
  margin: 2.2rem 0;
}

.prose a {
  color: var(--fg);
  text-decoration: none;
  border-bottom: 1px solid var(--muted-dim);
  transition: border-color 180ms ease;
}

.prose a:hover { border-bottom-color: var(--fg); }

/* The dateline — "ARDMORE, PA — May 27, 2026" — and the boilerplate labels.
   Weight, not colour: amber on teal is 3.15:1 and fails AA at body size. */
.prose strong { font-weight: 600; color: var(--fg); }

.prose ul, .prose ol { padding-left: 1.4rem; }
.prose li + li { margin-top: 0.4rem; }

.prose img { max-width: 100%; height: auto; }

/* ── Release header ───────────────────────────────────────────────────────── */
.release-head { margin-bottom: clamp(2rem, 5vh, 3rem); }

.release-head .eyebrow { display: block; margin-bottom: 0.9rem; }

/* Back link, above the release title. */
.back {
  display: inline-block;
  margin-bottom: clamp(1.75rem, 4vh, 2.5rem);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
  text-decoration: none;
}

.back:hover { color: var(--fg); }

/* ── Release hero image ───────────────────────────────────────────────────────
   Publii's featured image, carried forward. Constrained to the prose measure
   rather than run full-bleed: these are event photos and press artwork, not
   editorial photography, and a full-width crop makes a flyer look like a banner
   ad. Sitting at text width keeps it as illustration of the release.

   No border and no radius — the system defines surfaces with a hairline, and an
   image already has its own edge. */
.hero-figure {
  max-width: 42rem;
  margin: 0 0 clamp(2rem, 5vh, 2.75rem);
}

.hero-figure img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--hairline);
}

/* ── What's next ──────────────────────────────────────────────────────────────
   The one dynamic thing on the page. It is a hairline box like every other
   surface in the system — resisting the urge to make it a "hero" is the point.
   A press room that shouts about its own countdown reads as marketing; one that
   states the date in the same voice as everything else reads as a record. */
.next { border: 1px solid var(--hairline); padding: clamp(1.25rem, 3vw, 2rem); }

.next h2 { font-weight: 200; }

.next-when {
  margin-top: 0.75rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  font-size: clamp(1.05rem, 2vw, 1.3rem);
  font-weight: 300;
}

/* Amber is reserved for the one number that is the point of the panel. It
   measures 3.15:1 on teal — AA for LARGE text only — so it is used here at
   display size and never on the body copy below it. */
.next-countdown {
  color: var(--amber);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.16em;
}
