/* ══════════════════════════════════════════════════════════════════════
   TNAADO site chrome: header, footer, breaking-news ticker, and The
   Dispatch secondary bar.

   SINGLE SOURCE OF TRUTH. Every page links this file; no page restyles
   .eh-* / .ef-* / .dxsub-* inline.

   Self-contained by design. Every colour below resolves against a --tnc-*
   token declared in this file, never against a page's own palette. The old
   inline copies each borrowed whatever tokens their page happened to
   define (--ink / --text-rgb / --tn-fg-rgb / --chrome-fg / …), which is
   why no two of them rendered the same. Do not reintroduce a page token
   here: if the chrome needs a new colour, add a --tnc-* for it.

   Load it LAST in <head> so it out-ranks any inline chrome CSS a page has
   not yet had removed.

   COPIED VERBATIM from tnaado-media-next/css/chrome.css on 2026-09-08 for
   tnaado.ca (PROJECT REBOOT site 2). Two edits only: em dashes removed from
   these comments per the Reboot copy rule, and nothing else. It deliberately
   still carries the ticker, search-panel and Dispatch sub-bar rules this site
   never uses, because keeping the file byte-comparable with the newsroom's is
   worth more than the few unused kilobytes: chrome drift across properties is
   the exact failure this file was written to end.
   ══════════════════════════════════════════════════════════════════════ */

:root {
  --tnc-bg: #0a0a0a;                 /* chrome surface base */
  --tnc-bg-rgb: 10, 10, 10;
  --tnc-fg: #f5f1e8;                 /* chrome primary text */
  --tnc-fg-rgb: 245, 241, 232;
  --tnc-surface: #080808;            /* footer + thin bars */
  --tnc-input-tint-rgb: 255, 255, 255;
  --tnc-red: #c8102e;                /* constant brand accent, both themes */
  --tnc-red-rgb: 200, 16, 46;
  /* #c8102e is only 3.4:1 on the dark chrome surface, so it may style borders,
     underlines and chips but never small red TEXT. --tnc-red-text is the same
     hue lifted to 5.1-5.7:1 for the few places red is the type colour (raised
     2026-08-05 from #e5334f/4.64:1, real headroom over the 4.5 floor, and
     now the same value as base/variables.css's --red-text and retention.css's
     --tn-red-text, so header, page eyebrows and author bylines all match); in
     light mode #c8102e already clears 5.8:1, so it reverts there.

     2026-09-10: six rules in this file broke that rule and coloured TEXT with
     --tnc-red. The dropdown caret was the visible one, on every page in its
     default state, measured at 3.37:1 against composited pixels. The other five
     are hover and open states of the same chrome. All six now take
     --tnc-red-text, which reverts to #c8102e in light mode where that is
     correct, so nothing changes on a light surface. */
  --tnc-red-text: #e8455a;
}
/* Opt-in light mode only, never OS prefers-color-scheme. Set by the head
   script from localStorage['tn-theme']; anything other than 'dark' is light,
   so a first-time visitor gets light. */
[data-theme="light"] {
  --tnc-bg: #faf6ee;
  --tnc-bg-rgb: 250, 246, 238;
  --tnc-fg: #1a1510;
  --tnc-fg-rgb: 26, 21, 16;
  --tnc-surface: #f1ebdd;
  --tnc-input-tint-rgb: 26, 21, 16;
  --tnc-red-text: #c8102e;
}


/* ── breaking-news ticker, the strip above the header bar ───────────────
   Markup lives inside the header region; hidden until the fetch fills it,
   and it fails closed to hidden rather than to an empty bar. */
.eh-header:has(.tn-ticker:not([hidden])) { height: auto; flex-direction: column; align-items: stretch; }
.tn-ticker {
  display: flex; align-items: stretch; height: 30px; width: 100%;
  background: var(--tnc-surface); border-bottom: 1px solid rgba(var(--tnc-fg-rgb),.12);
  overflow: hidden;
}
.tn-ticker[hidden] { display: none; }
.tn-ticker-label {
  flex-shrink: 0; display: flex; align-items: center; padding: 0 1rem;
  font-family: "JetBrains Mono", monospace; font-size: .6rem; letter-spacing: .22em;
  text-transform: uppercase; color: var(--tnc-red-text);
  border-right: 1px solid rgba(var(--tnc-fg-rgb),.12);
}
.tn-ticker-viewport { flex: 1; min-width: 0; overflow: hidden; display: flex; align-items: stretch; }
.tn-ticker-track {
  display: flex; align-items: center; width: max-content; flex-shrink: 0;
  animation: tn-ticker-marquee 38s linear infinite;
}
.tn-ticker:hover .tn-ticker-track { animation-play-state: paused; }
@keyframes tn-ticker-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.tn-ticker-half { display: flex; align-items: center; flex-shrink: 0; }
.tn-ticker-item {
  display: flex; align-items: center; white-space: nowrap; flex-shrink: 0;
  font-family: "JetBrains Mono", monospace; font-size: .62rem; letter-spacing: .06em;
  /* .62 alpha, not .65: measured 7.6:1 dark / 5.3:1 light on the bar's real
     composited surface. */
  color: rgba(var(--tnc-fg-rgb),.78); transition: color .25s ease;
}
.tn-ticker-item:hover { color: var(--tnc-fg); }
.tn-ticker-cat { color: var(--tnc-red-text); text-transform: uppercase; letter-spacing: .16em; margin-right: .55rem; }
.tn-ticker-sep { color: var(--tnc-red-text); padding: 0 1rem; }
@media (prefers-reduced-motion: reduce) { .tn-ticker-track { animation: none; } }

/* Chrome links never inherit a page's link styling. Pages differ on whether
   they reset `a { text-decoration }` at all, and a page that doesn't was
   underlining every nav item and ticker headline. The chrome states it. */
.eh-header a,
.eh-search-panel a,
.eh-mobile-overlay a,
.ef-footer a,
.dxsub a { text-decoration: none; }

/* Sticky, so it always sits above scrolling content by design, but a page
   whose hero is itself near-black (the /areas boundary map, any full-bleed
   dark photo section) used to read as "the map is overlapping the header":
   the old .92-opacity background + a 12%-alpha hairline gave almost no
   visual edge against content that dark, so header and content visually
   fused into one black field instead of reading as chrome-above-content.
   Root-cause fix, not a per-page patch: raise the header's own opacity so
   the blur has less to see through, and add a real (if soft) drop shadow.
   A shadow's own gradient still reads as depth against dark content, where
   a flat hairline border does not. */
.eh-header {
  position: sticky;
  top: 0;
  z-index: 100;
  height: 64px;
  /* No background/backdrop-filter on the sticky element itself. See ::before
     below. The previous fix (transform: translateZ(0) + will-change:
     transform, kept below as a cheap extra compositing hint) promotes the
     element to its own GPU layer but does NOT stop iOS Safari from
     re-deciding that layer's contents mid-scroll, and it measurably still
     drops the header on a real iPhone. The verified fix (confirmed working
     on service.tnaado.ca, commit e9c22d1) is to never let the sticky/fixed
     element itself paint a background or backdrop-filter at all; put both
     on an absolutely positioned ::before behind its content instead.
     `!important` on the next two lines is deliberate, not a style hack: 34
     pages still carry a stale, pre-chrome.css inline `<style id="tn-chrome-
     css">` copy of this exact selector (dead weight this fix doesn't clean
     up, see commit message) that independently declares `background` and
     `backdrop-filter` on `.eh-header`. Cascade resolves those two properties
     per-declaration, not per-rule-block, so once this rule stopped
     contesting them the stale copy silently won them back, which measurably
     reintroduced the bug's exact precondition (backdrop-filter directly on
     the sticky element) on every page still carrying that leftover style.
     `!important` here is the one-file guarantee that this fix cannot be
     undone by dead CSS anyone (including a future edit) leaves lying around
     elsewhere on the page. */
  background: transparent !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  will-change: transform;
  border-bottom: 1px solid rgba(var(--tnc-fg-rgb),.3);
  box-shadow: 0 10px 24px -14px rgba(0,0,0,.65);
  display: flex;
  align-items: center;
}
.eh-header::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(var(--tnc-bg-rgb),.97);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  pointer-events: none;
}
.eh-inner {
  max-width: 1140px;
  margin: 0 auto;
  padding: 0 clamp(1rem,4vw,2.5rem);
  width: 100%;
  display: flex;
  align-items: center;
  gap: 2rem;
}
.eh-logo { flex-shrink: 0; display: flex; align-items: center; }
.eh-logo img { height: 28px; width: auto; display: block; }
.eh-nav {
  display: flex;
  align-items: center;
  gap: 2rem;
  flex: 1;
  justify-content: center;
}
.eh-nav a {
  font-family: "IBM Plex Sans", sans-serif;
  font-size: .82rem;
  font-weight: 400;
  letter-spacing: .04em;
  color: rgba(var(--tnc-fg-rgb),.78);
  transition: color .2s;
  white-space: nowrap;
}
.eh-nav a:hover { color: var(--tnc-fg); }
.eh-actions {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  flex-shrink: 0;
}
.eh-theme-btn {
  background: none;
  border: none;
  color: rgba(var(--tnc-fg-rgb),.72);
  padding: .3rem;
  display: flex;
  align-items: center;
  transition: color .2s;
}
.eh-theme-btn:hover, .eh-theme-btn:focus-visible { color: var(--tnc-fg); outline: none; }
.eh-theme-ico-moon { display: none; }
html[data-theme="light"] .eh-theme-ico-sun { display: none; }
html[data-theme="light"] .eh-theme-ico-moon { display: block; }
.eh-search-btn {
  background: none;
  border: none;
  color: rgba(var(--tnc-fg-rgb),.72);
  padding: .3rem;
  display: flex;
  align-items: center;
  transition: color .2s;
}
.eh-search-btn:hover { color: var(--tnc-fg); }
.eh-hamburger {
  display: none;
  background: none;
  border: none;
  color: rgba(var(--tnc-fg-rgb),.75);
  padding: .3rem;
  flex-direction: column;
  gap: 5px;
}
.eh-hamburger span {
  display: block;
  width: 22px;
  height: 1.5px;
  background: currentColor;
  transition: transform .3s, opacity .3s;
}
.eh-hamburger.is-open span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.eh-hamburger.is-open span:nth-child(2) { opacity: 0; }
.eh-hamburger.is-open span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* ── THE COMPANY dropdown (desktop) ── */
.eh-dropdown { position: relative; display: flex; align-items: center; }
.eh-dropdown-toggle {
  background: none;
  border: none;
  font-family: "IBM Plex Sans", sans-serif;
  font-size: .82rem;
  font-weight: 400;
  letter-spacing: .04em;
  color: rgba(var(--tnc-fg-rgb),.78);
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: 1.2rem 0;
  transition: color .2s;
  white-space: nowrap;
}
.eh-dropdown-toggle:hover,
.eh-dropdown-toggle:focus-visible { color: var(--tnc-fg); outline: none; }
.eh-dd-caret {
  font-size: .6rem;
  color: var(--tnc-red-text);
  transition: transform .25s cubic-bezier(0.16, 1, 0.3, 1);
}
.eh-dropdown:hover .eh-dd-caret,
.eh-dropdown:focus-within .eh-dd-caret,
.eh-dropdown.is-open .eh-dd-caret { transform: rotate(180deg); }
.eh-dropdown-panel {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  min-width: 200px;
  background: rgba(var(--tnc-bg-rgb),.92);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(var(--tnc-fg-rgb),.12);
  border-top: 1px solid rgba(var(--tnc-red-rgb),.55);
  padding: .5rem 0;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .2s ease, transform .25s cubic-bezier(0.16, 1, 0.3, 1), visibility .2s;
}
.eh-dropdown:hover .eh-dropdown-panel,
.eh-dropdown:focus-within .eh-dropdown-panel,
.eh-dropdown.is-open .eh-dropdown-panel {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
.eh-dropdown-panel a {
  display: block;
  padding: .55rem 1.2rem;
  font-family: "JetBrains Mono", monospace;
  font-size: .66rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(var(--tnc-fg-rgb),.65);
  transition: color .15s, background .15s;
}
.eh-dropdown-panel a:hover,
.eh-dropdown-panel a:focus-visible {
  color: var(--tnc-red-text);
  background: rgba(var(--tnc-red-rgb),.07);
  outline: none;
}

/* ── THE COMPANY group (mobile overlay) ── */
.eh-mob-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.1rem;
}
.eh-mob-group-toggle {
  background: none;
  border: none;
  font-family: "Fraunces", serif;
  font-size: clamp(1.4rem,5vw,2rem);
  font-weight: 400;
  color: var(--tnc-fg);
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  transition: color .2s;
}
.eh-mob-group-toggle:hover,
.eh-mob-group-toggle[aria-expanded="true"] { color: var(--tnc-red-text); }
.eh-mob-group-toggle .eh-dd-caret { font-size: .9rem; }
.eh-mob-group-toggle[aria-expanded="true"] .eh-dd-caret { transform: rotate(180deg); }
.eh-mob-group-links {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding-bottom: .4rem;
}
.eh-mobile-overlay .eh-mob-group-links a {
  font-family: "JetBrains Mono", monospace;
  font-size: .72rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(var(--tnc-fg-rgb),.7);
}
.eh-mobile-overlay .eh-mob-group-links a:hover { color: var(--tnc-red-text); }

/* Mobile overlay nav. Always in the flex layout (never display:none) so it can
   transition. The old display:none/flex toggle made open/close an instant
   snap with zero animation, the one thing that made it feel worse than the
   slide-down search panel a few rules up. visibility+opacity+transform is
   the same recipe .eh-search-panel already uses, same 380ms cubic-bezier. */
.eh-mobile-overlay {
  display: flex;
  position: fixed;
  inset: var(--tnc-header-h, 64px) 0 0 0;
  background: rgba(var(--tnc-bg-rgb),.97);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  z-index: 99;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2.5rem;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-14px);
  transition: opacity 300ms ease, transform 380ms cubic-bezier(0.16,1,0.3,1), visibility 380ms;
}
.eh-mobile-overlay.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0);
}
/* keep the header (logo, close button, breaking-news ticker) pinned on top while the mobile menu is open (fixes menu-open header scroll-away + banner overlap) */
body:has(.eh-mobile-overlay.is-open) .eh-header { position: fixed; top: 0; left: 0; right: 0; z-index: 2000; }
.eh-mobile-overlay a {
  font-family: "Fraunces", serif;
  font-size: clamp(1.4rem,5vw,2rem);
  font-weight: 400;
  color: var(--tnc-fg);
}
.eh-mobile-overlay a:hover { color: var(--tnc-red-text); }
/* Per-item cascade: links arrive a beat after the sheet itself instead of
   all popping in at once with it. transition lives here (not on `.eh-mobile-
   overlay a` above) so this one rule owns opacity/transform/color for every
   direct child without two rules fighting over the transition shorthand. */
.eh-mobile-overlay > * {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 260ms ease, transform 320ms cubic-bezier(0.16,1,0.3,1), color .2s;
}
.eh-mobile-overlay.is-open > * { opacity: 1; transform: translateY(0); }
.eh-mobile-overlay.is-open > *:nth-child(1) { transition-delay: 70ms; }
.eh-mobile-overlay.is-open > *:nth-child(2) { transition-delay: 110ms; }
.eh-mobile-overlay.is-open > *:nth-child(3) { transition-delay: 150ms; }
.eh-mobile-overlay.is-open > *:nth-child(4) { transition-delay: 190ms; }
.eh-mobile-overlay.is-open > *:nth-child(5) { transition-delay: 230ms; }
.eh-mobile-overlay.is-open > *:nth-child(6) { transition-delay: 270ms; }
@media (prefers-reduced-motion: reduce) {
  .eh-mobile-overlay, .eh-mobile-overlay > * { transition-duration: 1ms !important; transition-delay: 0ms !important; }
}

@media (max-width: 768px) {
  .eh-nav { display: none; }
  .eh-hamburger { display: flex; }
}

/* tn-nav-gap */
@media (max-width: 960px) {
  .eh-nav { gap: 1rem; }
}

.ef-footer {
  background: var(--tnc-surface);
  border-top: 1px solid rgba(var(--tnc-fg-rgb),.12);
  padding: 3rem 0 0;
}
.ef-footer-inner {
  max-width: 1140px;
  margin: 0 auto;
  padding: 0 clamp(1rem,4vw,2.5rem);
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 3rem;
  padding-bottom: 2.5rem;
}
.ef-col-logo img { height: 26px; width: auto; margin-bottom: 1rem; }
.ef-tagline {
  font-family: "JetBrains Mono", monospace;
  font-size: .65rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(var(--tnc-fg-rgb),.72);
}
.ef-social { display: flex; align-items: center; gap: 16px; margin-top: 1.4rem; }
.ef-social a { display: inline-flex; color: rgba(var(--tnc-fg-rgb),.7); transition: color .2s ease, transform .2s ease; }
.ef-social a:hover, .ef-social a:focus-visible { color: var(--tnc-fg); transform: translateY(-1px); outline: none; }
.ef-social svg { display: block; width: 18px; height: 18px; fill: currentColor; }
.ef-col-heading {
  font-family: "JetBrains Mono", monospace;
  font-size: .65rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(var(--tnc-fg-rgb),.72);
  margin-bottom: 1.2rem;
}
.ef-col nav { display: flex; flex-direction: column; gap: .7rem; }
.ef-col nav a {
  font-size: .88rem;
  color: rgba(var(--tnc-fg-rgb),.78);
  transition: color .2s;
}
.ef-col nav a:hover { color: var(--tnc-fg); }
.ef-bottom {
  border-top: 1px solid rgba(var(--tnc-fg-rgb),.06);
  padding: 1.2rem clamp(1rem,4vw,2.5rem);
  max-width: 1140px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.ef-copy {
  font-family: "JetBrains Mono", monospace;
  font-size: .62rem;
  letter-spacing: .1em;
  color: rgba(var(--tnc-fg-rgb),.72);
}
/* was an inline style="color:#c8102e" on the anchor, 3.4:1 on the footer
   surface. Class + --tnc-red-text instead, so it is styled here like the rest
   of the chrome and clears AA in both themes. */
.ef-bottom-support { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; font-size: .85em; }
.ef-support { color: var(--tnc-red-text); font-weight: 600; letter-spacing: .04em; }
.ef-bottom-links { display: flex; gap: 1.4rem; }
.ef-bottom-links a {
  font-family: "JetBrains Mono", monospace;
  font-size: .62rem;
  letter-spacing: .1em;
  color: rgba(var(--tnc-fg-rgb),.78);
  transition: color .2s;
}
.ef-bottom-links a:hover { color: var(--tnc-fg); }

@media (max-width: 768px) {
  .ef-footer-inner { grid-template-columns: 1fr; gap: 2rem; }
}

.skip-link { position: absolute; top: -100%; left: 1rem; background: var(--tnc-red); color: #fff; padding: .5rem 1rem; font-size: .85rem; z-index: 9999; }
.skip-link:focus { top: 1rem; }

/* tn slide-down search */
.eh-search-panel {
  position: fixed; top: var(--tnc-header-h, 64px); left: 0; right: 0; z-index: 98;
  background: rgba(var(--tnc-bg-rgb),.97);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  border-bottom: 1px solid rgba(var(--tnc-red-rgb),.45);
  transform: translateY(-110%); opacity: 0; visibility: hidden;
  transition: transform 380ms cubic-bezier(0.16,1,0.3,1), opacity 300ms ease, visibility 380ms;
  max-height: calc(100vh - var(--tnc-header-h, 64px)); max-height: calc(100svh - var(--tnc-header-h, 64px)); overflow-y: auto;
}
.eh-search-panel.is-open { transform: translateY(0); opacity: 1; visibility: visible; }
.eh-search-panel-inner {
  max-width: 680px; margin: 0 auto; padding: 1.4rem clamp(1rem,4vw,2.5rem);
  display: flex; align-items: center; gap: .9rem;
}
.eh-search-panel-inner svg { color: var(--tnc-red); flex-shrink: 0; }
.eh-search-input {
  flex: 1; min-height: 44px; background: rgba(var(--tnc-input-tint-rgb),.06);
  border: 1px solid rgba(var(--tnc-input-tint-rgb),.15); color: var(--tnc-fg);
  font-family: "IBM Plex Sans", sans-serif; font-size: 1rem;
  padding: 0 1.1rem; border-radius: 4px; outline: none; transition: border-color .2s;
}
.eh-search-input::placeholder { color: rgba(var(--tnc-fg-rgb),.3); }
.eh-search-input:focus { border-color: var(--tnc-red); }
.eh-search-close {
  background: none; border: none; color: rgba(var(--tnc-fg-rgb),.55);
  font-size: 1.5rem; line-height: 1; min-width: 44px; min-height: 44px;
  display: flex; align-items: center; justify-content: center; transition: color .2s;
}
.eh-search-close:hover { color: var(--tnc-fg); }
.eh-search-results { max-width: 680px; margin: 0 auto; padding: 0 clamp(1rem,4vw,2.5rem) 1rem; text-align: left; }
.eh-search-results .search-hit {
  display: block; padding: .8rem 1rem; border-top: 1px solid rgba(var(--tnc-input-tint-rgb),.06);
  text-decoration: none; color: inherit; transition: background .15s;
}
.eh-search-results .search-hit:hover { background: rgba(var(--tnc-red-rgb),.07); }
.eh-search-results .search-hit-cat {
  font-family: "JetBrains Mono", monospace; font-size: .58rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--tnc-red-text); margin: 0 0 .25rem;
}
.eh-search-results .search-hit-title { font-size: .9rem; color: var(--tnc-fg); margin: 0; }
.eh-search-results .search-hit-empty { padding: 1rem; font-size: .85rem; color: rgba(var(--tnc-fg-rgb),.45); text-align: center; }


.eh-theme-btn, .eh-search-btn, .eh-hamburger, .eh-dropdown-toggle { min-width: 44px; min-height: 44px; align-items: center; justify-content: center; }
.eh-nav a { padding-top: .75rem; padding-bottom: .75rem; min-height: 44px; display: inline-flex; align-items: center; }
.eh-mobile-overlay a, .eh-mob-group-toggle { min-height: 44px; display: inline-flex; align-items: center; }

/* ── The Dispatch secondary bar ─────────────────────────────────────────
   The product sub-header that sits under the site header on every Dispatch
   surface: the wordmark plus the section links. Every item is a link to
   another page, so there are no controls in here and nothing in this bar can
   be mistaken for the category FILTER buttons further down /dispatch.
   The current section is marked with .is-current + aria-current="page".

   Sticky, pinned directly under the main header via --tnc-header-h (set by
   partials/header.html's ResizeObserver, recomputed live on ticker show/hide
   and any header-height change). The exact hazard that used to block making
   this sticky is now handled centrally by that variable, the same one
   .eh-mobile-overlay and .eh-search-panel already depend on. */
.dxsub { position: sticky; top: var(--tnc-header-h, 64px); z-index: 89; }
.dxsub-bar {
  display: flex; align-items: center; gap: 20px;
  padding: 11px clamp(1rem, 4vw, 2.5rem);
  background: var(--tnc-surface);
  border-bottom: 1px solid rgba(var(--tnc-fg-rgb),.12);
  font-family: "IBM Plex Sans", -apple-system, system-ui, sans-serif;
}
.dxsub-mark {
  flex-shrink: 0;
  font-family: "Fraunces", Georgia, serif; font-weight: 600; font-size: 20px;
  color: var(--tnc-fg); text-decoration: none;
}
.dxsub-mark i { font-style: normal; color: var(--tnc-red-text); }
.dxsub-nav {
  display: flex; align-items: center; gap: 18px;
  font-size: 13px;
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.dxsub-nav::-webkit-scrollbar { display: none; }
.dxsub-link {
  padding: 3px 0; white-space: nowrap; text-decoration: none;
  /* .70 alpha: 8.9:1 dark / 6.1:1 light composited on --tnc-surface. */
  color: rgba(var(--tnc-fg-rgb),.78);
  border-bottom: 2px solid transparent;
  transition: color .2s ease, border-color .2s ease;
}
.dxsub-link:hover, .dxsub-link:focus-visible { color: var(--tnc-fg); outline: none; }
.dxsub-link.is-current { color: var(--tnc-fg); border-bottom-color: var(--tnc-red); }
@media (max-width: 560px) {
  .dxsub-bar { gap: 14px; }
  .dxsub-nav { gap: 14px; }
  .dxsub-link { min-height: 44px; display: inline-flex; align-items: center; }
  /* All four sections do not fit beside the wordmark on a phone, and the one
     that fell off the edge was whichever section you were currently in. The
     wordmark is the thing to drop: the site logo is directly above it. */
  .dxsub-mark { display: none; }
}

/* == SYNCED FORWARD from tnaado-media-next/css/chrome.css on 2026-09-09 =====
   Everything from here down is the newsroom's current chrome, taken as it
   stands rather than reinvented: the brand column, the Firm dropdown, the
   mobile sheet and the box-sizing reset. Chrome drift across properties is the
   exact failure this file exists to end, so the only edits are the Reboot copy
   rule's: em dashes rewritten out of the comments, nothing else touched. */

/* == REBOOT 2026-09-08: brand column on the left, bigger centre nav ==========
   Ethan: "links and the firm need to be moved to under tnaado logo on the left
   and size of the 3 remaining middle links increased."

   Every selector here is deliberately prefixed with `.eh-header`. 35 pages
   still carry the stale inline `<style id="tn-chrome-css">` copy described
   above, which declares `.eh-nav a { font-size: .82rem }` at specificity
   (0,1,1). A bare `.eh-nav a` here would tie and lose to the later inline
   copy on those pages, so the size change would silently apply on 7 pages and
   not on 35. `.eh-header .eh-nav a` is (0,2,1) and wins everywhere. */

.eh-header .eh-brand {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 1rem;
  flex-shrink: 0;
}
/* Beside the wordmark, not under it, and stacked: Links above The Firm.
   Under the logo they read as a caption hanging off it. */
.eh-header .eh-brand-nav {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: .3rem;
  padding-left: 1rem;
  border-left: 1px solid rgba(var(--tnc-fg-rgb),.18);
}
.eh-header .eh-brand-nav a,
.eh-header .eh-brand-nav .eh-dropdown-toggle {
  font-family: "JetBrains Mono", monospace;
  font-size: .62rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(var(--tnc-fg-rgb),.62);
  padding: 0;
  min-height: 0;
  white-space: nowrap;
}
.eh-header .eh-brand-nav a:hover,
.eh-header .eh-brand-nav .eh-dropdown-toggle:hover {
  color: var(--tnc-fg);
}
.eh-header .eh-brand-nav .eh-dropdown { align-items: center; }
.eh-header .eh-brand-nav .eh-dropdown-toggle { padding: 0; line-height: 1.1; }
.eh-header .eh-brand-nav a { line-height: 1.1; }
.eh-header .eh-brand-nav .eh-dd-caret { font-size: .5rem; }

/* The three that remain in the centre carry the site now, so they read larger. */
.eh-header .eh-nav a {
  font-family: "Fraunces", Georgia, serif;
  font-size: 1.02rem;
  letter-spacing: .005em;
  color: rgba(var(--tnc-fg-rgb),.86);
}
.eh-header .eh-nav { gap: 2.4rem; }

/* The brand column is two rows now, so a fixed 64px would clip it. Height goes
   auto with a floor. --tnc-header-h is measured by the ResizeObserver in the
   header partial, so the search panel and mobile overlay follow automatically. */
.eh-header { height: auto; min-height: 68px; }

@media (max-width: 768px) {
  /* The mobile overlay already carries Links and the Firm group, so the brand
     column collapses back to just the logo rather than duplicating them. */
  .eh-header .eh-brand-nav { display: none; }
  .eh-header { min-height: 64px; }
}
@media (max-width: 960px) {
  .eh-header .eh-nav { gap: 1.4rem; }
  .eh-header .eh-nav a { font-size: .92rem; }
}

/* == Migrated 2026-09-08 from the stale inline <style id="tn-chrome-css"> block ==
   That block sat in the head of 35 pages, duplicating most of this file and
   silently winning every cascade tie because it came later. It caused three
   separate bugs in one night. These are the rules it carried that this file did
   NOT, so they had to move here before the block could be deleted. The .tn-hdr
   rules it also carried were dropped: no .tn-hdr markup exists anywhere. */

.eh-theme-icon { pointer-events: none; }
.eh-theme-icon--moon { display: none; }
[data-theme="light"] .eh-theme-icon--sun { display: none; }
[data-theme="light"] .eh-theme-icon--moon { display: block; }
html, body { overflow-x: hidden; overflow-x: clip; max-width: 100%; }
img, video, iframe, svg, canvas { max-width: 100%; }
h1 { font-size: clamp(2.4rem, 6vw, 5rem) !important; line-height: 1.08; overflow-wrap: break-word; }
h2 { font-size: clamp(1.8rem, 4vw, 3rem) !important; line-height: 1.15; overflow-wrap: break-word; }
.inner { max-width: 1140px; margin-left: auto; margin-right: auto; padding-left: clamp(1rem,4vw,2.5rem); padding-right: clamp(1rem,4vw,2.5rem); }

/* == REBOOT 2026-09-08: the Firm dropdown, and the mobile sheet =============
   Ethan: "drop down menu needs work for the firm ... and make sure its built
   beautfulli for mobile."

   The panel was centred on its trigger (left:50% + translateX(-50%)). That was
   fine when the trigger sat in a centred nav, but the brand column moved it to
   the far left, so the panel hung out to the right and overlapped the hero. It
   now anchors to the trigger's left edge. */

.eh-header .eh-brand-nav .eh-dropdown-panel {
  left: 0;
  right: auto;
  transform: translateY(6px) scale(.98);
  transform-origin: top left;
  min-width: 210px;
  padding: .4rem;
  border: 1px solid rgba(var(--tnc-fg-rgb),.10);
  border-top: 2px solid var(--tnc-red);
  border-radius: 2px;
  background: rgba(var(--tnc-bg-rgb),.97);
  box-shadow: 0 18px 40px -20px rgba(0,0,0,.85), 0 2px 8px -4px rgba(0,0,0,.4);
}
.eh-header .eh-brand-nav .eh-dropdown:hover .eh-dropdown-panel,
.eh-header .eh-brand-nav .eh-dropdown:focus-within .eh-dropdown-panel,
.eh-header .eh-brand-nav .eh-dropdown.is-open .eh-dropdown-panel {
  transform: translateY(0) scale(1);
}
/* Items get room to breathe and a red index rule on hover, rather than a flat
   background flash that read as an OS select menu. */
.eh-header .eh-dropdown-panel a {
  position: relative;
  padding: .62rem .9rem .62rem 1.15rem;
  font-size: .64rem;
  letter-spacing: .18em;
  color: rgba(var(--tnc-fg-rgb),.72);
  border-radius: 1px;
}
.eh-header .eh-dropdown-panel a::before {
  content: "";
  position: absolute;
  left: .45rem; top: 50%;
  width: 2px; height: 0;
  background: var(--tnc-red);
  transform: translateY(-50%);
  transition: height .18s cubic-bezier(0.16,1,0.3,1);
}
.eh-header .eh-dropdown-panel a:hover,
.eh-header .eh-dropdown-panel a:focus-visible {
  color: var(--tnc-fg);
  background: rgba(var(--tnc-fg-rgb),.045);
}
.eh-header .eh-dropdown-panel a:hover::before,
.eh-header .eh-dropdown-panel a:focus-visible::before { height: 58%; }

/* == Mobile sheet =========================================================───────────
   The submenu could never collapse: .eh-mob-group-links sets display:flex,
   which defeats the `hidden` attribute the toggle relies on. So the Firm group
   was permanently expanded and the toggle appeared to do nothing. */
.eh-mobile-overlay .eh-mob-group-links[hidden] { display: none; }

@media (max-width: 768px) {
  .eh-mobile-overlay {
    justify-content: flex-start;
    gap: 0;
    padding: 2.25rem 1.5rem calc(2rem + env(safe-area-inset-bottom));
    overflow-y: auto;
    text-align: center;
  }
  /* One rhythm for the whole sheet instead of a 2.5rem gap that pushed the
     last items off a short screen. */
  .eh-mobile-overlay .eh-mob-link,
  .eh-mobile-overlay .eh-mob-group { width: 100%; }
  .eh-mobile-overlay .eh-mob-link {
    display: block;
    padding: .95rem 0;
    font-size: clamp(1.5rem, 7vw, 2.1rem);
    border-bottom: 1px solid rgba(var(--tnc-fg-rgb),.09);
  }
  .eh-mobile-overlay .eh-mob-group {
    width: 100%;
    gap: 0;
    border-bottom: 1px solid rgba(var(--tnc-fg-rgb),.09);
  }
  .eh-mobile-overlay .eh-mob-group-toggle {
    width: 100%;
    justify-content: center;
    padding: .95rem 0;
    font-size: clamp(1.5rem, 7vw, 2.1rem);
  }
  .eh-mobile-overlay .eh-mob-group-links {
    gap: 0;
    padding: 0 0 .9rem;
  }
  .eh-mobile-overlay .eh-mob-group-links a {
    display: block;
    padding: .6rem 0;
    font-size: .72rem;
    letter-spacing: .2em;
    color: rgba(var(--tnc-fg-rgb),.6);
  }
}

/* The chrome had no box-sizing reset of its own, so `padding` on the mobile
   sheet was being added OUTSIDE its width: the sheet measured 390 + 48 and its
   rows ran ~24px past the right edge, which is what made the menu look
   off-centre. Scoped to the chrome so it cannot disturb page layout. */
.eh-header, .eh-header *,
.eh-mobile-overlay, .eh-mobile-overlay *,
.eh-search-panel, .eh-search-panel *,
.ef-footer, .ef-footer * { box-sizing: border-box; }

/* ── footer contact block ───────────────────────────────────────────────
   Copied from tnaado-media-next/css/chrome.css so the switchboard and the
   newsroom carry the same address treatment rather than two of them. */
.ef-footer .ef-contact {
  font-style: normal;
  display: flex;
  flex-direction: column;
  gap: .3rem;
  margin-top: 1rem;
}
.ef-footer .ef-contact__line,
.ef-footer .ef-contact__link {
  font-family: "JetBrains Mono", monospace;
  font-size: .64rem;
  letter-spacing: .1em;
  line-height: 1.5;
  color: rgba(var(--tnc-fg-rgb),.55);
}
.ef-footer .ef-contact__link { transition: color .2s; }
.ef-footer .ef-contact__link:hover { color: var(--tnc-red-text, #e8455a); }

/* == Local addendum for apps.tnaado.ca ======================================
   The newsroom's centre nav has no active state, because its three items are
   section destinations a visitor is rarely "on". Here they are three sibling
   pages and exactly one is always current, so it says so. scripts/sync-chrome
   .mjs writes `is-current` and `aria-current` from the page's own filename;
   this is only what those look like. */
.eh-header .eh-nav a.is-current {
  color: var(--tnc-fg);
  border-bottom: 1px solid var(--tnc-red);
}


/* ── The Labs mark signs itself ──────────────────────────────────────────
   Standing rule (Ethan, 2026-09-09): TNAADO Labs appears in a footer as its
   LOGO, never as typed text. The wordmark ships as red ink on transparent,
   so it is flattened and re-inked to match whatever it sits beside: white at
   the sibling link's alpha on ink, black at the same alpha in light theme.
   Height is 1.25em so it tracks the link text it sits in rather than being
   pinned to a pixel value that only suits one of the two places it appears.
   The name still reaches screen readers and anyone the image fails for,
   through the img's alt. */
.ef-labs-mark {
  display: inline-block;
  height: 1.25em;
  width: auto;
  vertical-align: -.22em;
  filter: brightness(0) invert(1);
  opacity: .78;
  transition: opacity .2s;
}
a:hover > .ef-labs-mark,
a:focus-visible > .ef-labs-mark { opacity: 1; }
[data-theme="light"] .ef-labs-mark { filter: brightness(0); opacity: .74; }
