/**
 * @file
 * NYSFHC 2026 Watch page: per-tile lock badge, the session modal shown when
 * a tile is clicked, and the hero column alignment override.
 */

/* Hero columns: each column sizes to its own content, not to its neighbour.
 *
 * The hero grid is not declared here — it lives in the node body's inline
 * <style> block (mirrored in ../nysfhc-watch-body.reference.html) as
 * `.nysfhc-watch .nw-hero-cols{display:grid;grid-template-columns:2fr 1fr;
 * gap:1.5rem;align-items:stretch;}`. Under `stretch` the syllabus <aside> in
 * the 1fr column is stretched to the height of the taller 2fr column (video +
 * countdown + description) and, being a column flexbox with no filler, shows a
 * tall empty panel below its buttons.
 *
 * Why the extra `.nw-hero` in the selector: that body <style> block renders
 * inside <body>, so it comes AFTER this stylesheet in document order and wins
 * any same-specificity tie. A plain `.nysfhc-watch .nw-hero-cols` here is
 * (0,2,0) — an exact tie — and would never apply. Naming the `.nw-hero`
 * ancestor makes this (0,3,0), which lands the override without !important.
 * Same class of trap as the `p.nw-modal-alt` rule at the bottom of this file.
 *
 * Scoped to the desktop breakpoint to match the body's own boundary: at
 * max-width:820px the body collapses the grid to `grid-template-columns:1fr`,
 * where every item is alone in its row track and align-items is a no-op.
 *
 * `start` rather than the requested `flex-start`: this is a grid container, and
 * while `flex-start` is spec'd to behave as `start` outside flex layout, the
 * grid keyword is the accurate one here. Identical rendering.
 */
@media (min-width: 821px) {
  .nysfhc-watch .nw-hero .nw-hero-cols {
    align-items: start;
  }
}

/* Lock badge on session tiles (top-right, clears the Day One/Two tags). */
.nysfhc-watch .nw-thumb .nw-lock,
.nysfhc-watch .nw-featured-poster .nw-lock {
  position: absolute;
  top: .5rem;
  right: .5rem;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: rgba(0, 0, 0, .7);
  border-radius: 4px;
}
.nysfhc-watch .nw-lock-svg {
  width: 16px;
  height: 16px;
  display: block;
}

/* Session modal. */
.nysfhc-watch .nw-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background: rgba(0, 0, 0, .7);
}
.nysfhc-watch .nw-modal-overlay[hidden] {
  display: none;
}
.nysfhc-watch .nw-modal {
  position: relative;
  width: 100%;
  max-width: 420px;
  background: #181d26;
  color: #f5f7fa;
  border: 1px solid #2a323d;
  border-radius: 12px;
  /* Top padding clears the close button so a wrapped heading can't run under it. */
  padding: 2.75rem 1.75rem 1.75rem;
  text-align: center;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .5);
}
/* Video modal (?preview=, registrants). Wider than the copy modal, with a
 * 16:9 player. Both selectors are deliberately over-specific: `.nysfhc-watch
 * .nw-modal` below is (0,2,0) and `.nysfhc-watch .nw-modal h2` is (0,2,1), so a
 * plain `.nw-modal-wide` / `.nw-modal-video-title` would lose on max-width and
 * font-size and the modal would silently stay 420px wide. Same trap as the
 * `p.nw-modal-alt` rule at the bottom of this file. */
.nysfhc-watch .nw-modal.nw-modal-wide {
  max-width: 860px;
}
.nysfhc-watch .nw-modal-video {
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: 8px;
  overflow: hidden;
}
.nysfhc-watch .nw-modal-video iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}
/* Left-aligned and smaller than the copy modal's centred heading: a session
 * title is a sentence, not a two-word label, and it sits above the video.
 *
 * padding-right reserves the close chip's footprint. The modal's 2.75rem of top
 * padding is what keeps the SHORT centred headings clear of the chip, and it is
 * not enough here: a left-aligned title starts at that padding edge, so its
 * first line sits alongside the chip rather than below it. Measured at 375px,
 * 11 of the 20 session titles ran under the chip by up to 28px without this.
 * The chip is 44px wide at right:.5rem, i.e. 52px of the modal's width, and the
 * modal's own right padding covers 28px of that — 2.5rem clears the rest with
 * room to spare, at every width and for a title of any length. */
.nysfhc-watch .nw-modal h2.nw-modal-video-title {
  margin: 0 0 .75rem;
  padding-right: 2.5rem;
  font-size: 1.05rem;
  line-height: 1.35;
  text-align: left;
}

/* Close control. Patrons reported not finding it as a bare grey glyph, so it is
 * a solid 44x44 chip: dark surface, white "x", and a #6b7787 rim that carries
 * the 3:1 boundary contrast against the #181d26 modal (WCAG 2.1 1.4.11) — the
 * near-black surface alone is only 1.18:1 against the modal and would read as a
 * hole rather than a button. Same values at every breakpoint. */
.nysfhc-watch .nw-modal-close {
  position: absolute;
  top: .5rem;
  right: .5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: #07090b;
  border: 1px solid #6b7787;
  border-radius: 50%;
  color: #ffffff;
  font-size: 30px;
  font-weight: 400;
  line-height: 1;
  cursor: pointer;
}
.nysfhc-watch .nw-modal-close:hover,
.nysfhc-watch .nw-modal-close:focus-visible {
  background: #2a323d;
  border-color: #ffffff;
}
.nysfhc-watch .nw-modal-close:focus-visible {
  outline: 2px solid #ffd34f;
  outline-offset: 2px;
}
.nysfhc-watch .nw-modal-icon {
  width: 44px;
  height: 44px;
  margin: 0 auto .75rem;
  color: #ffd34f;
}
.nysfhc-watch .nw-modal-icon .nw-lock-svg {
  width: 44px;
  height: 44px;
}
.nysfhc-watch .nw-modal h2 {
  margin: 0 0 .5rem;
  font-size: 1.3rem;
}
.nysfhc-watch .nw-modal p {
  margin: 0 0 1rem;
  color: #c7cfda;
  font-size: .92rem;
  line-height: 1.5;
}
.nysfhc-watch .nw-modal p:last-child {
  margin-bottom: 0;
}
.nysfhc-watch .nw-modal a:not(.nw-modal-btn) {
  color: #ffd34f;
}
.nysfhc-watch .nw-modal-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: .8rem 1.6rem;
  border-radius: 8px;
  font-weight: 600;
  text-decoration: none;
  background: #ffd34f;
  color: #1a1a1a;
  transition: filter .15s ease;
}
.nysfhc-watch .nw-modal-btn:hover {
  filter: brightness(1.08);
}
/* "Already registered? Sign in", under the Register button. Patrons reported it
 * was too small to read.
 *
 * The selector has to name `p` as well as the class: `.nysfhc-watch .nw-modal p`
 * above is (0,2,1) and outranks a bare `.nysfhc-watch .nw-modal-alt` at (0,2,0),
 * so the old rule here never applied at all — neither its .85rem nor its
 * margin-top. The line was rendering at the .92rem inherited from the `p` rule
 * with no space above it. Qualifying with `p` (0,3,1) is what makes these
 * declarations take effect. */
.nysfhc-watch .nw-modal p.nw-modal-alt {
  margin-top: .9rem;
  font-size: 18px;
  font-weight: 500;
}

/* A session tile that links to its own page (?preview=).
 *
 * The overlay anchor covers the whole card, so the card has to establish a
 * positioning context. `.nysfhc-watch .nw-card` is declared in the node body's
 * inline <style>, which renders after this stylesheet and therefore wins any
 * same-specificity tie — so this is qualified with the class JS adds to reach
 * (0,3,0) and actually apply. Same trap as the hero rule at the top.
 *
 * The focus ring is on the anchor but drawn around the card, which is what a
 * keyboard user needs to see: the whole tile is the target, not a strip of it.
 */
.nysfhc-watch .nw-card.nw-card-linked {
  position: relative;
}
.nysfhc-watch .nw-card-link {
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: 10px;
  /* No text and no background: the card underneath is the visible affordance. */
  font-size: 0;
  text-indent: -9999px;
}
.nysfhc-watch .nw-card-link:focus-visible {
  outline: 3px solid #ffd34f;
  outline-offset: 2px;
}

/* Track filter above the on-demand grid, under its heading.
 *
 * Buttons, not links: they filter what is already on the page rather than
 * navigating, and aria-pressed carries the state. ?track= is updated with
 * replaceState so the view stays shareable without adding history entries.
 *
 * The margin is on the BOTTOM now because the row moved above the grid
 * (buildTrackFilter, 2026-09-08). The section's own h3 supplies the space
 * above; a leftover margin-top here would double it.
 */
.nysfhc-watch .nw-tracks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  /* 1.75rem = 28px of clear air before the first row of tiles (Matt, 2026-09-08,
   * asking for a minimum of 8px). Measured at 1280 and 375 after the change, not
   * assumed: the pills wrap to two rows at 375 and the figure below is from the
   * LAST row to the grid, which is the gap that actually reads as tight. */
  margin: 0 0 1.75rem;
}
.nysfhc-watch .nw-track-pill {
  padding: .45rem .95rem;
  border: 1px solid #6b7787;
  border-radius: 999px;
  background: transparent;
  /* Measured against the page's #0e1116 ground: #dfe5ec text is 14.91:1, and
   * the #6b7787 rim is 4.15:1 — comfortably over the 3:1 a real control's
   * boundary needs (WCAG 2.1 1.4.11). Same rim colour as the modal close chip,
   * which was picked for exactly this reason. */
  color: #dfe5ec;
  font-size: .85rem;
  /* 500, not 600: tried in the inspector against the coloured rims and it
   * reads better (Matt, 2026-09-25). */
  font-weight: 500;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.nysfhc-watch .nw-track-pill:hover {
  border-color: #ffd34f;
  color: #ffd34f;
}
.nysfhc-watch .nw-track-pill:focus-visible {
  outline: 2px solid #ffd34f;
  outline-offset: 2px;
}
/* Selected: filled, because a border change alone is not a state a colour-blind
 * user can rely on. #1a1a1a on #ffd34f is 12.17:1. */
.nysfhc-watch .nw-track-pill.is-on {
  background: #ffd34f;
  border-color: #ffd34f;
  color: #1a1a1a;
}

/* THIS is what makes the filter actually filter. Without it the pills looked
 * like they did nothing: the JS was setting the hidden attribute on exactly the
 * right cards and ?track= was updating, but the tiles stayed on screen.
 *
 * `hidden` is not a style, it relies on the browser's own [hidden]{display:none}
 * — and ANY author rule setting display beats a UA rule, whatever the
 * specificity. The node body's inline <style> declares
 * `.nysfhc-watch .nw-card { display: flex }`, so every card was flex, hidden or
 * not. Measured in a browser against the live page: hidden attribute on 14 of
 * 20 cards, computed display `flex` on all 20.
 *
 * !important rather than leaning on this selector being one step more specific:
 * that inline block is content staff can edit, and a later
 * `.nw-grid .nw-card { display: flex }` in it would tie on specificity and win
 * on source order. The modal overlay carries the same guard, for the same
 * reason — see .nw-modal-overlay[hidden] above. Any new "hide this thing"
 * behaviour on this page needs its own [hidden] rule here. */
.nysfhc-watch .nw-card[hidden] {
  display: none !important;
}

/* Hero slots — the authored blocks applyHeroSlots() chooses between.
 *
 * Same reason as the rule above, and the reason it is written here at all: the
 * node body's inline <style> sets display on things in this page, and an author
 * rule beats the browser's [hidden]{display:none} whatever the specificity. A
 * slot toggled with .hidden would stay on screen and the hero would show two
 * states at once. !important because that inline block is content someone can
 * edit, and a later rule there would tie on specificity and win on source
 * order.
 *
 * The width/height pair matters as much as the display: the iframe is promoted
 * from data-src only when its slot is chosen, and a bare <iframe> inherits no
 * size, so without this the livestream would land as a 300x150 box in the
 * corner of a 16:9 well. .nw-hero-media already supplies the aspect ratio. */
.nysfhc-watch .nw-hero-slot[hidden] {
  display: none !important;
}
.nysfhc-watch .nw-hero-slot {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.nysfhc-watch .nw-hero-slot > iframe,
.nysfhc-watch .nw-hero-slot > .nw-hero-embed {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* The livestream in the hero (?preview=live).
 *
 * .nw-hero-media already carries aspect-ratio:16/9, position:relative and
 * overflow:hidden from the node body's own <style>, so the iframe just fills
 * it — the padding-top ratio wrapper the Vimeo embed snippet ships with is not
 * needed here and would nest a second aspect box inside the first. */
.nysfhc-watch .nw-hero-embed {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Session tile artwork: the real title slides, replacing the grey placeholders.
 *
 * 20 of the 21 tiles were placeholders when this was written; only 7 carried
 * the blue NYG&B title slide. These images are each session's own title card,
 * pulled from its Vimeo recording (Big Y's came from Matt, since Vimeo had
 * never generated one for it), normalised to 640x360 — twice the widest a tile
 * renders, so it stays sharp on a 2x screen.
 *
 * WHY THIS IS AN OVERRIDE AND NOT A FIX TO THE NODE BODY. Each tile's image is
 * an inline background-image in the body of node 173667. Changing it there is
 * the right end state and would delete these rules — but a content edit to the
 * live legacy site is always HELD for a named approver, and no single
 * find/replace covers 20 different URLs, so that route meant ~20 held changes
 * rather than one deploy.
 *
 * The selector matches the OLD filename inside that inline style, which makes
 * this self-cancelling: the day someone updates the node body, these rules
 * stop matching and the body's own images take over. Nothing to remember.
 * `!important` is what beats an inline declaration; nothing else does.
 */
/* From Vermont to Erie County, New York: Cluster Research Reveals a  */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-mattson-vermont-erie"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/from-vermont-to-erie-county-new-york-cluster-research.jpg") !important;
}
/* Jewish New York Networks: Synagogues, Landsmanshaftn, and Burial S */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-genung-jewish-networks"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/jewish-new-york-networks-synagogues-landsmanshaftn-and.jpg") !important;
}
/* Sir William Johnson and the Loyalists of the Mohawk Valley, NY */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-poster-mattson-johnson-loyalists"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/sir-william-johnson-and-the-loyalists-of-the-mohawk.jpg") !important;
}
/* They Were All Born in New York: Migration of New Yorkers to Michig */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-lyttle-michigan"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/they-were-all-born-in-new-york-migration-of-new.jpg") !important;
}
/* Yo soy boricua, pa'que tú lo sepas: Puerto Ricans in NYC and the H */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-poster-rivera-boricua-en"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/yo-soy-boricua-pa-que-tu-lo-sepas-puerto-ricans-in-nyc.jpg") !important;
}
/* Yo soy boricua, pa'que tú lo sepas: Puertorriqueños en Nueva York  */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-rivera-boricua-es"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/yo-soy-boricua-pa-que-tu-lo-sepas-puertorriquenos-en.jpg") !important;
}
/* Best Practices for Using and Analyzing New York Land Records */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-poster-pauley-land-records"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/best-practices-for-using-and-analyzing-new-york-land.jpg") !important;
}
/* Big Y and Discover Made Simple */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-cloud-bigy"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/big-y-and-discover-made-simple.jpg") !important;
}
/* City Directories: Search Tool Then and Now */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-poster-miller-city-directories"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/city-directories-search-tool-then-and-now.jpg") !important;
}
/* Legal Barriers and Pathways for Women in New York: A Genealogical  */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-khuda-legal-barriers"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/legal-barriers-and-pathways-for-women-in-new-york-a.jpg") !important;
}
/* The Evidence Ladder: Reconstructing Enslaved Families When Records */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-poster-berry-enslaved-families"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/the-evidence-ladder-reconstructing-enslaved-families.jpg") !important;
}
/* The Oblong: A Brief History */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-poster-osullivan-oblong"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/the-oblong-a-brief-history.jpg") !important;
}
/* Tracking County Lines: Researching New York County Boundary Change */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-pauley-county-lines"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/tracking-county-lines-researching-new-york-county.jpg") !important;
}
/* 1776–1789: Exploring 'American' British Loyalist Claims for New Yo */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-paschke-loyalist-claims"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/1776-1789-exploring-american-british-loyalist-claims.jpg") !important;
}
/* Conscription, Conflict, and Class: The Civil War Draft Riots in Ne */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-strauss-draft-riots"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/conscription-conflict-and-class-the-civil-war-draft.jpg") !important;
}
/* More than Paperwork: Genealogical Value in New York Government Doc */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-hoffman-govt-documents"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/more-than-paperwork-genealogical-value-in-new-york.jpg") !important;
}
/* New York State Archives Records: A Focus on 19th and 20th Century  */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-wilcox-state-archives"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/new-york-state-archives-records-a-focus-on-19th-and.jpg") !important;
}
/* Parsing the Ocean Voyage: Tracking Emigrants from Europe to the US */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-garber-ocean-voyage"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/parsing-the-ocean-voyage-tracking-emigrants-from.jpg") !important;
}
/* Recovering NY Synagogue Records to Unlock Family History Mysteries */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-poster-kowitt-synagogue-records"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/recovering-ny-synagogue-records-to-unlock-family.jpg") !important;
}
/* Sugar Houses and the Jersey: Prisons During the American Revolutio */
.nysfhc-watch .nw-thumb[style*="nysfhc-2026-thumb-osullivan-sugar-houses"] {
  background-image: url("/modules/custom/nygb_base/img/sessions/sugar-houses-and-the-jersey-prisons-during-the.jpg") !important;
}

/* Paula Williams's session was withdrawn on 2026-09-03 and a rule here hid its
 * tile from the listing. Her recording arrived on 2026-09-08 and the session is
 * back, so that rule is gone: leaving a `display:none` keyed on her artwork in
 * this file is the kind of thing that hides a tile nobody can then explain.
 *
 * The tile it used to match is gone too — her card in the node body now points
 * at the module's own title card, not at the old nysfhc-2026-thumb-williams-dna
 * upload, so the selector would not have matched anything either way. Removed
 * because it was misleading, not because it was firing. */
/* ── The September 9 layout (?preview=ondemand) ────────────────────────────────
 *
 * applyOnDemandLayout() lifts .nw-hero-cols — countdown, conference blurb,
 * syllabus panel — out of the hero and re-parents it into a
 * .nw-hero.nw-hero-tail block at the foot of the page, leaving the <h1> behind
 * as a title band. These rules are the spacing that move needs, and they are
 * the reason the JS only adds .nw-ondemand once the move has actually happened:
 * applied to a hero that still holds its cols they would crush it.
 *
 * SPECIFICITY, AGAIN. Everything here has to out-rank the node body's inline
 * <style> block, which renders inside <body> and therefore comes after this
 * file in document order and wins every same-specificity tie. The body declares
 * `.nysfhc-watch .nw-hero` (0,2,0), so `.nysfhc-watch.nw-ondemand .nw-hero` at
 * (0,3,0) is what lands — the same trap as the hero-cols rule at the top of
 * this file and the [hidden] rules above. Do not "simplify" these selectors.
 */

/* The hero is now just the title. Its authored padding-bottom was holding up a
 * 16:9 video well and a column of paragraphs; under an h1 alone it is a gap. */
.nysfhc-watch.nw-ondemand .nw-hero {
  padding-bottom: .35rem;
}

/* And at the foot of the page it is a block in its own right: separated from
 * the livestream grid above by a rule and real space, and given back the top
 * padding the h1 used to provide from inside it. */
.nysfhc-watch.nw-ondemand .nw-hero.nw-hero-tail {
  margin-top: 2.75rem;
  /* Clear air above the livestream/countdown box, which is the first thing in
   * this block (Matt, 2026-09-08, minimum 8px). 2.75rem = 44px measured from the
   * block's top border to the top of the black box. */
  padding-top: 2.75rem;
  padding-bottom: 2rem;
  border-top: 1px solid #262d38;
}

/* "View conference details": equal air above and below (Matt, 2026-09-08).
 *
 * It was 40px above and 80px below. Neither number is in this stylesheet — the
 * button sits in an authored paragraph whose INLINE style is
 * `margin:2.5rem 0 1rem`, and below that the wrapper's own `padding: 0 0 4rem`
 * adds 64px more. 40 above, 16 + 64 = 80 below.
 *
 * So both halves have to move, and the inline margin needs !important because
 * nothing else outranks an inline declaration. The class is put on that
 * paragraph by applyOnDemandLayout() rather than matched with :has(), so this
 * does not depend on the paragraph staying the only <p> directly inside an
 * .nw-inner — that is content, and content changes.
 *
 * Result: 2.5rem above, and 2.5rem below once the wrapper's bottom padding is
 * cut to match. Scoped to the on-demand layout, which is the page being
 * launched; ?preview=live keeps the authored spacing it has always had. */
.nysfhc-watch.nw-ondemand .nw-details-wrap {
  margin-bottom: 0 !important;
}
.nysfhc-watch.nw-ondemand {
  padding-bottom: 2.5rem;
}

/* ── The livestream gate ───────────────────────────────────────────────────
 * What a NON-REGISTRANT sees in the hero once the stream is live, in place of
 * the player they cannot have.
 *
 * It exists because the alternative was worse than nothing. Before this, a
 * logged-out visitor kept the countdown, which reaches zero and is replaced by
 * "The livestream is starting…" — permanently, since the tick clears its own
 * interval. For the whole two days the page promised a stream that would never
 * appear, to exactly the people most likely to be arriving for the first time,
 * and offered them no way to register or sign in.
 *
 * Sign in leads for an anonymous visitor and Register leads for someone already
 * signed in, because during the conference most people hitting this are
 * registrants who simply are not logged in — see showLivestreamGate().
 *
 * Contrast, measured against BOTH ends of the panel's gradient rather than one
 * (WCAG 2.1 AA): button label #1a1a1a on --accent 12.17:1; --muted body text
 * 6.21:1 and 7.50:1; --accent link 10.94:1 and 13.22:1; the lock, being
 * non-text and needing only 3:1, the same as the link. Worst case 6.21:1.
 * Re-measure if any of these colours move. */
.nysfhc-watch .nw-gate {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1.4rem;
  background: linear-gradient(160deg, #1b2430, #0e1116);
  border-radius: 10px;
}
.nysfhc-watch .nw-gate-icon {
  color: var(--accent);
  width: 46px;
  height: 46px;
  margin-bottom: 1rem;
}
.nysfhc-watch .nw-gate-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}
.nysfhc-watch .nw-gate-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: .75rem 2.1rem;
  border-radius: 8px;
  font-weight: 600;
  font-size: 1rem;
  text-decoration: none;
  background: var(--accent);
  color: #1a1a1a;
  transition: filter .15s ease;
}
.nysfhc-watch .nw-gate-btn:hover {
  filter: brightness(1.08);
}
.nysfhc-watch .nw-gate-line {
  margin: 1rem 0 0;
  font-size: .88rem;
  color: var(--muted);
  line-height: 1.5;
  max-width: 40ch;
}
/* Its own line, not a trailing clause: the sentence explains, the link acts,
 * and running them together buries the second action at the end of prose. */
.nysfhc-watch .nw-gate-line a {
  display: block;
  margin-top: .35rem;
  color: var(--accent);
  text-decoration: underline;
}
@media (max-width: 600px) {
  .nysfhc-watch .nw-gate {
    padding: 1rem;
  }
  .nysfhc-watch .nw-gate-icon {
    width: 34px;
    height: 34px;
    margin-bottom: .7rem;
  }
  .nysfhc-watch .nw-gate-btn {
    padding: .6rem 1.5rem;
    font-size: .9rem;
  }
  .nysfhc-watch .nw-gate-line {
    font-size: .78rem;
    margin-top: .7rem;
  }
}

/* ── Track tags, the livestream divider, and the featured keynote (2026-09-25) ──
 *
 * Tag colours are from the NYG&B style guide (Ky's), one per track, orange
 * among them at Matt's request. Yellow is deliberately NOT one: this page
 * already uses yellow for the selected filter pill and the presenter names,
 * and a yellow chip would read as either. Measured (WCAG 2.1 AA), chip text
 * #001531 on each fill, and each fill against the card panel #181d26:
 *   People of NY     Orange          #ff9900   8.52:1   7.89:1
 *   Methods & Tools  Light Blue      #44c4f3   9.06:1   8.40:1
 *   Records          Brand Blue tint #9bbcdd   9.23:1   8.56:1
 * The chip names its track in words, so the colour is never the only cue. */
/* At the FOOT of the card (Matt, 2026-09-25): the body grows to fill the card
 * and the chip takes the slack above it, so chips line up along the bottom of
 * a row however long each description runs. */
.nysfhc-watch .nw-card-body {
  flex: 1 1 auto;
}
.nysfhc-watch .nw-tags {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem;
  margin-top: auto;
}
.nysfhc-watch .nw-tag {
  margin: 0;
  padding: .12rem .5rem;
  border-radius: 999px;
  background: #9bbcdd;
  color: #001531;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .02em;
  line-height: 1.4;
}
/* The tallest card in a row has no slack to spend: this, plus the body's own
 * .3rem gap, keeps its chip off the last line of the description. */
.nysfhc-watch .nw-card-body > .nw-desc {
  margin-bottom: .45rem;
}
/* "New": the livestream recordings' own category, and the first filter pill.
 * NYG&B Yellow #ffd400 — the brand's signal colour, and the one the subject
 * tracks leave free — with the chips' #001531 text: 12.74:1, and 11.81:1
 * against the card panel. As an outline pill on the #0e1116 page ground, 13.21:1. */
.nysfhc-watch .nw-tag.nw-tag-new {
  background: #ffd400;
  text-transform: uppercase;
  letter-spacing: .06em;
}
.nysfhc-watch .nw-track-pill[data-key="new"] {
  --tag: #ffd400;
}
/* The keynote's presenter, under the caption heading the featured video
 * rewrites. Qualified to (0,3,1) to beat the caption's own muted `p` rule.
 * --accent on the hero's darkest ground: 10.94:1. */
.nysfhc-watch .nw-hero-caption p.nw-featured-presenter {
  margin: 0 0 .7rem;
  color: var(--accent);
  font-size: .95rem;
  font-weight: 600;
}
.nysfhc-watch .nw-tag[data-track="people"],
.nysfhc-watch .nw-track-pill[data-key="people"] {
  --tag: #ff9900;
  background: #ff9900;
}
.nysfhc-watch .nw-tag[data-track="methods"],
.nysfhc-watch .nw-track-pill[data-key="methods"] {
  --tag: #44c4f3;
  background: #44c4f3;
}
.nysfhc-watch .nw-tag[data-track="records"],
.nysfhc-watch .nw-track-pill[data-key="records"] {
  --tag: #9bbcdd;
  background: #9bbcdd;
}

/* The track filter pills wear the chips' colours, so the row of pills is the
 * key to the cards. "All" (data-key="") keeps its neutral outline.
 *
 * Unselected: an outline in the track's colour, white text, no fill (Matt,
 * 2026-09-25 — dark text on three filled pills in a row read poorly). White on
 * the #0e1116 ground is 19.1:1; each rim is 8.8:1 or better against it, far
 * over the 3:1 a control's boundary needs. Selected: filled, the chips' #001531
 * text (8.52:1 or better). Outline versus solid is a change a colour-blind
 * reader sees as readily as anyone, and aria-pressed says it to a screen
 * reader. (A check mark was tried here and taken out at Matt's request.)
 * (0,4,0) specificity, to beat both the neutral .is-on and :hover rules. */
.nysfhc-watch .nw-track-pill[data-key]:not([data-key=""]) {
  background: transparent;
  border: 2px solid var(--tag);
  /* One px less each way than the base pill, whose rim is 1px, so a 2px rim
   * leaves every pill in the row the same height as "All". */
  padding: calc(.45rem - 1px) calc(.95rem - 1px);
  color: #fff;
}
.nysfhc-watch .nw-track-pill[data-key]:not([data-key=""]):hover {
  border-color: var(--tag);
  color: #fff;
  background: rgba(255, 255, 255, .08);
}
.nysfhc-watch .nw-track-pill[data-key]:not([data-key=""]).is-on {
  background: var(--tag);
  border-color: var(--tag);
  color: #001531;
}

/* Between the livestream recordings (first) and the on-demand tiles. A grid
 * item spanning every column, so it is a full row at any width. Decorative —
 * #3a4452 on the #0e1116 ground — since the order, not the line, carries the
 * grouping. */
.nysfhc-watch .nw-grid-divider {
  grid-column: 1 / -1;
  height: 1px;
  margin: .9rem 0;
  background: #3a4452;
}
.nysfhc-watch .nw-grid-divider[hidden] {
  display: none !important;
}

/* The keynote in the hero, for anyone not registered: its title card, a play
 * mark and the tiles' lock, clicking through to the Register / Sign in modal.
 * A <button>, so it is focusable and announces itself; the reset below strips
 * the browser's button chrome. .nw-hero-media supplies the 16:9 box. */
.nysfhc-watch .nw-featured-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: #0d3f7a center / cover no-repeat;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.nysfhc-watch .nw-featured-poster:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}
.nysfhc-watch .nw-featured-play {
  width: 78px;
  height: 78px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .62);
  position: relative;
  transition: transform .15s ease, background .15s ease;
}
.nysfhc-watch .nw-featured-play::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-35%, -50%);
  border-style: solid;
  border-width: 15px 0 15px 25px;
  border-color: transparent transparent transparent #fff;
}
.nysfhc-watch .nw-featured-poster:hover .nw-featured-play {
  transform: scale(1.06);
  background: rgba(0, 0, 0, .75);
}
@media (max-width: 600px) {
  .nysfhc-watch .nw-featured-play {
    width: 56px;
    height: 56px;
  }
  .nysfhc-watch .nw-featured-play::after {
    border-width: 11px 0 11px 18px;
  }
}

/* No flash of the authored hero copy (Matt, 2026-09-25). The node body's
 * "The livestream has ended." is plain HTML, so it paints before
 * nysfhc_watch.js — which loads at the foot of the page — swaps in the keynote.
 * Until the script marks the root .nw-ready, the hero box shows its empty
 * black 16:9 well instead. visibility, not display, so the box keeps its size
 * and nothing below it jumps when the content arrives. If the script never
 * runs the box stays empty, which Matt preferred to the stale message. */
.nysfhc-watch:not(.nw-ready) .nw-hero-media > * {
  visibility: hidden;
}
