/* FLOA — one stylesheet, no framework, no external requests.
   The GXM preview artifact serves under a strict CSP (default-src 'none',
   connect-src 'self'), so anything fetched from a CDN would simply not load. */

:root {
  /* Monochrome. Officiating is black and white; the site should be too, and it
     removes any question of what a client's brand colours are before they have any. */
  --ink: #0B0B0C;
  --ink-muted: #62646A;
  --ground: #FFFFFF;
  --ground-alt: #F2F2F3;
  --ground-deep: #0B0B0C;
  --hairline: #DCDCDE;
  --accent: #0B0B0C;
  --accent-dark: #000000;
  --measure: 68ch;
  --pad: clamp(1rem, 4vw, 2rem);
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--ground);
  -webkit-text-size-adjust: 100%;
}

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

a { color: var(--accent); }
a:focus-visible,
button:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: #fff; padding: .75rem 1rem;
}
.skip:focus { left: 0; }

.wrap { max-width: 68rem; margin: 0 auto; padding: 0 var(--pad); }
.prose { max-width: var(--measure); }
.policy { max-width: 50rem; }
.policy h2 { margin-top: 2rem; }
.policy p { max-width: var(--measure); }
.muted { color: var(--ink-muted); }

/* ---------- header ---------- */

.site-header {
  border-bottom: 1px solid var(--hairline);
  background: var(--ground);
  position: sticky; top: 0; z-index: 20;
}

.bar {
  max-width: 68rem; margin: 0 auto; padding: 1.75rem var(--pad);
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
}

.brand { min-width: 0; max-width: calc(100% - 3.6rem); display: flex; align-items: center; gap: .6rem; text-decoration: none; color: inherit; }

.brand-mark {
  background: var(--accent); color: #fff; font-weight: 700; letter-spacing: .04em;
  padding: .3rem .5rem; border-radius: 3px; font-size: .95rem;
}
.brand-name { font-weight: 700; font-size: 1.12rem; line-height: 1.2; max-width: 14rem; }
/* Square because the source is cropped to the crest, so the box is the mark with no
   margin of its own to space against the name. */
.brand-logo { display: block; width: 72px; height: 72px; flex-shrink: 0; }

.nav-toggle {
  margin-left: auto; display: block; width: 2.6rem; height: 2.4rem;
  background: none; border: 1px solid var(--hairline); border-radius: 4px; cursor: pointer;
}
.nav-toggle-bar,
.nav-toggle-bar::before,
.nav-toggle-bar::after {
  display: block; width: 1.1rem; height: 2px; background: var(--ink);
  margin: 0 auto; position: relative; content: "";
}
.nav-toggle-bar::before { position: absolute; top: -6px; }
.nav-toggle-bar::after  { position: absolute; top: 6px; }

#nav { display: none; width: 100%; }
#nav.open { display: block; }
#nav ul { list-style: none; margin: .5rem 0 0; padding: 0; display: flex; flex-direction: column; gap: .1rem; }
#nav a {
  display: block; padding: .6rem .2rem; text-decoration: none; color: var(--ink);
  font-size: 1.02rem; font-weight: 500; border-bottom: 1px solid var(--hairline);
}
#nav a[aria-current="page"] { color: var(--accent); font-weight: 600; }

@media (min-width: 1060px) {
  .nav-toggle { display: none; }
  #nav { display: block; width: auto; margin-left: auto; }
  #nav ul { flex-direction: row; gap: 1.25rem; margin: 0; }
  #nav a { border-bottom: 0; padding: .25rem 0; }
  #nav a[aria-current="page"] { box-shadow: inset 0 -2px 0 var(--accent); }
}

/* Keep the crest consistent with the footer, including while scrolling. */
.site-header.is-scrolled .bar { padding-top: .35rem; padding-bottom: .35rem; }
.site-header.is-scrolled .brand-name, .site-header.is-scrolled #nav a { font-size: .95rem; }
@media (prefers-reduced-motion: no-preference) {
  .bar { transition: padding .18s ease; }
  .brand-name, #nav a { transition: font-size .18s ease; }
}
@media (max-width: 380px) { .brand-name { font-size: 1rem; } }

/* ---------- sections ---------- */

section { padding: clamp(2rem, 5vw, 3.5rem) 0; }
section + section { border-top: 1px solid var(--hairline); }
section.alt { background: var(--ground-alt); }

h1 {
  font-size: clamp(1.9rem, 4.5vw, 2.7rem); line-height: 1.12;
  margin: 0 0 .75rem; letter-spacing: -.02em; text-wrap: balance;
}
h2 { font-size: clamp(1.3rem, 3vw, 1.7rem); margin: 0 0 .6rem; text-wrap: balance; }
h3 { font-size: 1.08rem; margin: 0 0 .4rem; }
p  { margin: 0 0 1rem; }

.lede { font-size: 1.12rem; color: var(--ink-muted); max-width: var(--measure); }

/* ---------- hero ---------- */

.hero {
  background: var(--ground-deep) url("../img/mesh.svg") repeat;
  background-size: 72px 72px;
  color: #fff;
  padding-block: clamp(2.5rem, 9vw, 5rem);
}
.hero h1 {
  color: #fff; max-width: 18ch;
  font-size: clamp(2rem, 7vw, 3.6rem); line-height: 1.05;
  letter-spacing: -0.02em; margin: 0 0 .75rem;
}
.hero .lede { color: rgba(255,255,255,.82); max-width: 42ch; font-size: clamp(1rem, 2.6vw, 1.2rem); }
/* Buttons carry their own colours. This rule used to reach them, and because
   `.hero a` outranks `.btn-primary` on specificity the primary button ended up with a
   white background from one rule and white text from the other. */
.hero a:not(.btn) { color: #fff; }

/* Four facts a stranger absorbs before deciding whether to read on. Numerals lead,
   because a figure stops a skimmer where a sentence does not. */
.facts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 1px; margin-top: clamp(1.75rem, 5vw, 2.75rem);
  background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.16);
}
.facts div { background: var(--ground-deep); padding: 1rem 1.1rem; }
.facts .value {
  display: block; font-size: clamp(1.5rem, 4.5vw, 2rem); font-weight: 700;
  line-height: 1.1; letter-spacing: -0.02em;
}
.facts .label { display: block; font-size: .9rem; color: rgba(255,255,255,.82); margin-top: .15rem; }
.facts .note { display: block; font-size: .74rem; color: rgba(255,255,255,.5); margin-top: .3rem; }

/* Partner cards use supplied or approved artwork only. A plain text mark keeps the
   other links visually balanced without imitating third-party branding. */
.partner-mark {
  display: flex; align-items: center; justify-content: flex-start;
  min-height: 4.75rem; margin-bottom: .75rem;
}
.partner-mark--image img {
  display: block; width: auto; max-width: 8rem; height: 4.75rem; object-fit: contain;
}
.partner-mark--text {
  color: var(--ink); font-size: clamp(1.15rem, 3vw, 1.45rem); font-weight: 800;
  letter-spacing: -.02em;
}

/* Sits between the hero and the cards: useful, and out of the way. */
.aside-note {
  border-left: 3px solid var(--ink); background: var(--ground-alt);
  padding: 1rem 1.15rem; margin-top: 0;
}
.aside-note h2 { margin: 0 0 .3rem; font-size: 1.02rem; }
.aside-note p { margin: 0; font-size: .94rem; }

.cta-row { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.5rem; }

.btn {
  display: inline-block; padding: .7rem 1.2rem; border-radius: 4px;
  text-decoration: none; font-weight: 600; font-size: .95rem; border: 2px solid transparent;
}
/* On the dark hero: solid white with near-black text, and a hairline ghost beside it.
   Colours are stated on .btn-* rather than inherited so a button is legible wherever it
   is placed, not only inside a hero. */
.btn-primary { background: #fff; color: var(--ink); border-color: #fff; }
.btn-primary:hover { background: #e8e8ea; border-color: #e8e8ea; color: var(--ink); }
.btn-outline { border-color: rgba(255,255,255,.55); color: #fff; background: transparent; }
.btn-outline:hover { border-color: #fff; background: rgba(255,255,255,.08); color: #fff; }

.btn-solid { background: var(--accent); color: #fff; }
.btn-solid:hover { background: var(--accent-dark); }

/* ---------- cards / lists ---------- */

.grid {
  display: grid; gap: 1rem; margin-top: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

.card {
  background: var(--ground); border: 1px solid var(--hairline);
  border-radius: 5px; padding: 1.15rem 1.25rem;
}
.card h3 { margin-top: 0; }
.card p:last-child { margin-bottom: 0; }

a.card { text-decoration: none; color: inherit; display: block; }
a.card:hover { border-color: var(--accent); }
a.card .go { color: var(--accent); font-weight: 600; font-size: .9rem; }

/* numbered steps — order is real information here */
ol.steps { list-style: none; counter-reset: step; margin: 1.5rem 0 0; padding: 0; }
ol.steps li {
  counter-increment: step; position: relative;
  padding: 0 0 1.25rem 3rem; border-left: 2px solid var(--hairline); margin-left: 1rem;
}
ol.steps li:last-child { border-left-color: transparent; padding-bottom: 0; }
ol.steps li::before {
  content: counter(step); position: absolute; left: -1.05rem; top: 0;
  width: 2rem; height: 2rem; border-radius: 50%;
  background: var(--accent); color: #fff;
  display: grid; place-items: center; font-size: .85rem; font-weight: 700;
}

ul.checks { list-style: none; margin: 1rem 0; padding: 0; }
ul.checks li { padding-left: 1.5rem; position: relative; margin-bottom: .55rem; }
ul.checks li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: .5rem; height: .5rem; background: var(--accent); border-radius: 50%;
}

/* ---------- FAQ ---------- */

details.faq {
  border: 1px solid var(--hairline); border-radius: 5px;
  padding: .9rem 1.1rem; margin-bottom: .6rem; background: var(--ground);
}
details.faq[open] { border-color: var(--accent); }
details.faq summary { cursor: pointer; font-weight: 600; }
details.faq summary::-webkit-details-marker { display: none; }
details.faq summary::after { content: " +"; color: var(--accent); }
details.faq[open] summary::after { content: " −"; }
details.faq p { margin: .75rem 0 0; }

/* ---------- announcements ---------- */

.empty {
  border: 1px dashed var(--hairline); border-radius: 5px;
  padding: 2rem 1.25rem; text-align: center; color: var(--ink-muted);
}

/* The announcement card block lives further down, under "announcement cards".
   The list-style rules that used to sit here were left behind when that card was
   introduced, and `article.post` outranks `.post`, so the card's own padding and
   date treatment never applied: every card rendered with 1.25rem 0, which put the
   text flush against its own left and right border. Deleted rather than reordered,
   because a duplicate selector at a higher specificity will win again the next time
   someone edits the card. */

/* ---------- leadership ---------- */

.person { border: 1px solid var(--hairline); border-radius: 5px; padding: 1rem 1.15rem; }
.person .role { font-size: .78rem; text-transform: uppercase; letter-spacing: .08em; color: var(--accent); font-weight: 700; }
.person .name { font-weight: 600; margin: .25rem 0 0; }

/* ---------- placeholder marker ---------- */

/* Anything still awaiting a fact from FLOA renders visibly unfinished, so a
   preview can never be mistaken for finished copy. */
.todo {
  background: #FFF8E1; border-left: 3px solid #C79100; color: #6B4E00;
  padding: .5rem .75rem; font-size: .9rem; border-radius: 0 3px 3px 0;
  display: block; margin: .4rem 0;
}
.todo::before { content: "Needs FLOA input: "; font-weight: 700; }

/* ---------- footer ---------- */

.site-footer { border-top: 1px solid var(--hairline); background: var(--ground-alt); margin-top: 2rem; }
/* The footer ran as one tall column on every width. Four columns across the top on a
   laptop, two on a tablet, one only on a phone, so it reads as a footer rather than as
   more page. */
.footer-inner {
  max-width: 68rem; margin: 0 auto; padding: 2.25rem var(--pad) 1.5rem;
  display: grid; gap: 1.75rem 2rem;
  grid-template-columns: 1fr;
}
@media (min-width: 560px) { .footer-inner { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 860px) { .footer-inner { grid-template-columns: 1.1fr repeat(3, minmax(8rem, 1fr)); gap: 2rem 2.5rem; } }

.footer-org { grid-column: 1 / -1; }
@media (min-width: 860px) { .footer-org { grid-column: auto; } }

.footer-name { font-weight: 700; margin: 0 0 .3rem; letter-spacing: -0.01em; }
/* The crest sits above the name it belongs to. Its surround is transparent, so it
   takes the footer's ground rather than carrying a white square onto it. */
.footer-crest { display: block; width: 72px; height: 72px; margin: .55rem 0 .7rem; }
.footer-inner p { margin: 0 0 .3rem; font-size: .88rem; }

/* The columns themselves live inside .footer-links, so it must not re-grid them. */
.footer-links { display: contents; }
.footer-links ul { list-style: none; margin: 0; padding: 0; }
.footer-links a { display: block; padding: .18rem 0; font-size: .94rem; font-weight: 600; text-decoration: none; color: var(--ink); }
.footer-links a:hover { text-decoration: underline; }

/* Meta sits on its own rule below everything, horizontal until there is no room. */
.footer-meta {
  grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: .5rem 1.25rem;
  align-items: center; justify-content: space-between;
  border-top: 1px solid var(--hairline); margin-top: .5rem; padding-top: 1rem;
}

.gxm-credit-wrap {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .72rem; color: var(--ink-muted);
}
.gxm-credit-wrap a { display: inline-flex; line-height: 0; }
.gxm-credit-wrap img { width: 50px; height: 22px; }


/* --- Scan block on the recruiting page -------------------------------------
   A labelled definition list a stranger can read in ten seconds. Stacks on
   phones, becomes two columns once there is room for the label to sit beside
   its answer. */
.scan { margin: 0; display: grid; gap: .35rem 1.25rem; }
.scan dt {
  font-weight: 700; font-size: .78rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted, #5a6472); padding-top: .15rem;
}
.scan dd { margin: 0 0 .6rem; }
.scan dd:last-child { margin-bottom: 0; }
@media (min-width: 700px) {
  .scan { grid-template-columns: 8.5rem 1fr; align-items: baseline; }
  .scan dd { margin-bottom: .35rem; }
}

/* Column headings. The layout itself lives with .footer-inner above; an earlier
   version re-declared .footer-links as its own grid here, which overrode the
   display:contents that promotes the columns into the footer grid and squeezed all
   three into one narrow cell. */
.footer-inner .footer-heading {
  font-weight: 750; font-size: 1rem; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-muted); margin: 0 0 .45rem;
}
.footer-col ul { list-style: none; margin: 0; padding: 0; }

/* Paragraph runs and bullet lists lifted out of Board-approved prose blocks. */
.prose-list { margin: 0 0 1rem 1.1rem; padding: 0; }
.prose-list li { margin: 0 0 .3rem; }

/* --- Season date spine -----------------------------------------------------
   The date and the label sit side by side once there is room, so the list scans
   as a calendar rather than as prose. Past dates dim instead of disappearing:
   a season that visibly started is more reassuring in June than a page that has
   quietly emptied itself. */
.season { list-style: none; margin: 1.5rem 0 0; padding: 0; }
.season li {
  display: grid; gap: .15rem 1.25rem;
  padding: .7rem 0; border-top: 1px solid var(--rule, #e3e7ec);
}
.season li:last-child { border-bottom: 1px solid var(--rule, #e3e7ec); }
.season time {
  font-variant-numeric: tabular-nums; font-size: .85rem; font-weight: 600;
  color: var(--muted, #5a6472); white-space: nowrap;
}
.season h3 { margin: 0 0 .15rem; font-size: 1rem; }
.season p { margin: 0; font-size: .92rem; }
.season li.past { opacity: .55; }
.season li.past time::after { content: " \00b7 passed"; font-weight: 400; }
@media (min-width: 720px) {
  .season li { grid-template-columns: 12rem 1fr; align-items: baseline; }
}
.source-note { margin-top: 1.25rem; font-size: .82rem; }

/* --- Motion, kept to what earns it ----------------------------------------
   Cards and buttons respond to a pointer so the page feels alive without
   anything moving on its own. All of it is inside the reduced-motion guard at
   the foot of this file. */
.card {
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.card:hover, .card:focus-within {
  transform: translateY(-2px);
  border-color: var(--ink);
  box-shadow: 0 6px 20px rgba(11,11,12,.09);
}

.btn { transition: transform .12s ease, background-color .15s ease, color .15s ease; }
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.facts div { transition: background-color .18s ease; }
.facts div:hover { background: #141416; }

.season li { transition: background-color .15s ease; }
.season li:hover { background: var(--ground-alt); }

/* Links earn an underline that grows rather than appearing. */
main a:not(.btn):not(.card) {
  text-decoration: underline; text-underline-offset: .18em;
  text-decoration-thickness: 1px; transition: text-decoration-thickness .12s ease;
}
main a:not(.btn):not(.card):hover { text-decoration-thickness: 2px; }
main a.card { text-decoration: none; }
main a.card:hover .go { text-decoration: underline; text-underline-offset: .18em; }

/* Public contact form */
.floa-form { max-width: 48rem; display: grid; gap: 1.4rem; margin-top: 1.75rem; }
.form-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.25rem; }
.form-field { min-width: 0; display: grid; gap: .45rem; }
.form-field label { font-size: .9rem; font-weight: 650; }
.form-field input, .form-field select, .form-field textarea {
  display: block; width: 100%; min-width: 0; padding: .85rem 1rem;
  border: 1px solid #a7a7ad; border-radius: 6px; background: var(--ground);
  color: var(--ink); font: inherit; line-height: 1.5;
}
.form-field textarea { min-height: 11rem; resize: vertical; }
.form-field :is(input, select, textarea):focus-visible {
  outline: 2px solid var(--ink); outline-offset: 3px;
}
.form-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 1rem; }
.form-status { flex: 1 1 16rem; font-size: .9rem; }
.form-status.is-warn { color: #8a2e12; }
.form-status.is-ok { color: #245b37; }
.form-actions button:disabled { opacity: .65; cursor: wait; }

/* One joined school directory, with compact counties sharing a column. */
.counties { list-style: none; padding: 0; margin: 2rem 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); background: var(--ground); border: 1px solid var(--hairline); border-radius: 12px; overflow: hidden; }
.counties > li { padding: 1.5rem; min-width: 0; }
.counties > li + li { border-left: 1px solid var(--hairline); }
.counties > .county-featured { grid-column: 1 / -1; border-bottom: 1px solid var(--hairline); }
.counties > .county-featured + li { border-left: 0; }
.counties h3 { margin: 0 0 1rem; font-size: 1.06rem; }
.county-schools { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem 1.5rem; }
.county-featured .county-schools { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.county-schools li { font-size: .94rem; line-height: 1.45; }
.county-subgroup + .county-subgroup { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--hairline); }
.county-subgroup h3 { margin-bottom: .55rem; }
@media (max-width: 800px) {
  .counties { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .county-featured .county-schools { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .counties > .county-compact { grid-column: 1 / -1; border-left: 0; border-top: 1px solid var(--hairline); display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
  .county-subgroup + .county-subgroup { margin: 0; padding: 0; border: 0; }
}
@media (max-width: 600px) {
  .counties, .county-featured .county-schools, .counties > .county-compact { grid-template-columns: 1fr; }
  .counties > li { padding: 1.25rem; }
  .counties > li + li { border-left: 0; border-top: 1px solid var(--hairline); }
  .counties > .county-featured { border-bottom: 0; }
  .county-subgroup + .county-subgroup { padding-top: 1rem; border-top: 1px solid var(--hairline); }
}
@media (max-width: 700px) {
  .form-row { grid-template-columns: 1fr; }
  .form-actions .btn { width: 100%; }
}

/* --- Responsive guards ----------------------------------------------------
   Long words in client-supplied copy are the usual cause of a phone scrolling
   sideways, and a table or a wide block is the other. */
body { overflow-x: hidden; }
h1, h2, h3, p, li, dd { overflow-wrap: break-word; }
.wrap > table, .prose > table { display: block; overflow-x: auto; max-width: 100%; }
@media (max-width: 480px) {
  .cta-row { flex-direction: column; align-items: stretch; }
  .cta-row .btn { text-align: center; }
}

/* Last in the file on purpose, so nothing added later escapes it. The old version
   suppressed transitions and animations but not the hover transforms above, which
   left cards and buttons still jumping for a reader who asked for stillness. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .card:hover, .card:focus-within, .btn:hover, .btn:active { transform: none !important; }
}

.footer-meta-links { display: flex; gap: 1rem; }
.footer-meta-links a { font-size: .78rem; color: var(--ink-muted); text-decoration: none; }
.footer-meta-links a:hover { text-decoration: underline; }

/* ---------- announcements ----------
   One card shape for every item, so a Board notice, a clinic date and a rules update
   all read the same way and nothing needs restyling when the next one is posted. The
   event block only renders when an item has a date, which is what keeps a rules
   bulletin from looking like a meeting. */
.posts { display: grid; gap: 1.5rem; margin-top: 1.75rem; }

.post {
  border: 1px solid var(--hairline); border-radius: 10px;
  padding: 1.5rem; background: var(--ground);
}
.post-head { display: flex; align-items: center; gap: .6rem; margin-bottom: .5rem; }
.post-head time {
  font-size: .78rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-muted);
}
.chip {
  font-size: .68rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  padding: .18rem .5rem; border: 1px solid var(--hairline); border-radius: 999px;
  color: var(--ink-muted);
}
.post h2, .post h3 { margin: 0 0 .4rem; font-size: 1.22rem; line-height: 1.25; letter-spacing: -0.01em; }
.post-summary { margin: 0 0 1rem; font-size: 1rem; color: var(--ink); }

/* The one piece a working official scans for. Kept out of the prose so it survives
   however long or short the body is. */
.post-event {
  margin: 0 0 1.1rem; padding: .85rem 1rem;
  background: var(--ground-alt); border-radius: 8px;
  display: grid; gap: .3rem;
}
.post-event > div { display: flex; gap: .6rem; }
.post-event dt {
  flex: 0 0 3.4rem; font-size: .72rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-muted); padding-top: .12rem;
}
.post-event dd { margin: 0; font-size: .95rem; font-weight: 600; }

.post-body p { margin: 0 0 .8rem; font-size: .95rem; }
.post-body p:last-child { margin-bottom: 0; }
.post-body .prose-list { margin: 0 0 .8rem; padding-left: 1.1rem; }
.post-body .prose-list li { font-size: .95rem; margin-bottom: .25rem; }

.post-links { margin: 1rem 0 0; display: flex; flex-wrap: wrap; gap: .75rem; }
.post-links a {
  font-size: .88rem; font-weight: 600; text-decoration: none;
  border-bottom: 1px solid currentColor; padding-bottom: 1px;
}

.post-by {
  margin-top: 1.15rem; padding-top: .85rem; border-top: 1px solid var(--hairline);
  display: flex; flex-wrap: wrap; gap: .3rem 1rem;
  font-size: .84rem; color: var(--ink-muted);
}
.post-by a { color: var(--ink-muted); text-decoration: none; }
.post-by a:hover { text-decoration: underline; }

@media (min-width: 700px) {
  .post { padding: 1.75rem 2rem; }
  .post-event > div { align-items: baseline; }
}

/* ---------- icons ----------
   Authored inline SVG rather than an icon font or a hosted sprite: managed-site
   artifacts run under a CSP with no external hosts, so anything fetched would simply
   not arrive. Sized in em so they track whatever text they sit beside, and stroked
   with currentColor so they inherit it. */
.icon { display: inline-block; vertical-align: -0.15em; flex: 0 0 auto; }

.fact-icon { display: block; color: var(--ink-muted); margin-bottom: .4rem; }
.card-icon { display: block; color: var(--ink-muted); margin-bottom: .6rem; }

/* The scan block is the page a stranger actually reads. The icon turns each row into
   a target the eye can land on instead of a wall of labels. */
.scan dt { display: flex; align-items: center; gap: .45rem; }
.scan-link {
  display: inline-block; font-weight: 600; text-decoration: none;
  border-bottom: 1px solid currentColor; padding-bottom: 1px;
  white-space: nowrap;
}
.scan dt .icon { color: var(--ink-muted); }

.checks li { display: flex; align-items: flex-start; gap: .6rem; }
.checks li .icon { margin-top: .18rem; color: var(--ink-muted); }
.checks li > span { flex: 1; }

.chip { display: inline-flex; align-items: center; gap: .3rem; }

.post-event dt { display: flex; align-items: center; gap: .35rem; }
.post-by .icon { vertical-align: -0.2em; margin-right: .2rem; color: var(--ink-muted); }

/* Bold is the cheapest scannability tool there is. Kept tight so a run of bolded
   openers reads as a list of answers rather than as shouting. */
.checks strong, .scan strong, .prose strong { font-weight: 700; }

.person-mail { display: flex; align-items: center; gap: .4rem; }
.person-mail .icon { color: var(--ink-muted); }

/* The chevron is the only thing telling a reader a closed row opens. It rotates on
   open so the control explains itself without a caption. */
.faq summary { display: flex; align-items: flex-start; gap: .55rem; }
.faq summary .icon { margin-top: .18rem; color: var(--ink-muted); transition: transform .15s ease; }
.faq[open] summary .icon { transform: rotate(90deg); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::marker { content: ""; }

/* ---------- GXM client preview bar ----------
   The shared component, matched to the Three Pillars preview: a thin dark bar fixed
   to the top with a 2px #d94d45 rule above it, and only the word GXM in that red.
   Understated on purpose. It sits on a client's own site during review and should
   read as GXM's scaffolding around the design, not as part of it.

   Values below are copied from that implementation rather than reinvented, so the
   two previews look like the same product. That copying is itself the argument for
   promoting this into the brand repo next to the footer credit. */
.gxm-preview-status {
  position: fixed; inset: 0 0 auto; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  height: 2rem; font-size: .7rem; letter-spacing: .035em;
  color: #fff; background: #090909; border-top: 2px solid #d94d45;
}
.gxm-preview-status__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: .75rem; width: min(100%, 80rem); padding-inline: 1rem;
}
.gxm-preview-status__label { white-space: nowrap; min-width: 0; }
.gxm-preview-status strong > span { color: #d94d45; }
.gxm-preview-status__nav { display: flex; align-items: center; gap: .35rem; flex-shrink: 0; }
.gxm-preview-status__nav a,
.gxm-preview-status__nav button {
  display: inline-flex; align-items: center; min-height: 1.55rem;
  padding-inline: .55rem; border-radius: .35rem;
  font: inherit; font-weight: 800; letter-spacing: inherit;
  color: #fff; background: none; border: 0; cursor: pointer; text-decoration: none;
}
.gxm-preview-status__nav a:hover, .gxm-preview-status__nav a:focus-visible,
.gxm-preview-status__nav button:hover, .gxm-preview-status__nav button:focus-visible {
  background: #9b7ed947; outline: none;
}

/* The bar is fixed, so the page needs the height back. */
body:has(.gxm-preview-status) { padding-top: 2rem; }

@media (max-width: 520px) {
  .gxm-preview-status__inner { gap: .25rem; padding-inline: .35rem; }
  .gxm-preview-status__review { display: none; }
  .gxm-preview-status__nav { gap: .1rem; }
  .gxm-preview-status__nav a, .gxm-preview-status__nav button {
    padding-inline: .35rem; font-size: .64rem;
  }
}

/* Review panel, GXM canonical v1.2.0, copied from docs/brand/preview-review/
   review.css in the gxm repo rather than hotlinked, so this site stays independent
   and the bytes stay reviewable.
   sha256 96d9439b6c4514fdc3687afc9a1308f51fea78b2b5c4eb7a7c4cde279f665de9 */
/* GXM client preview review panel, v1.2.0
 *
 * Canonical source: docs/brand/preview-review/review.css in the gxm repo.
 * Copy into a client repo; do not hotlink. Record the sha256 where you copy it.
 *
 * The bar itself is the shared .gxm-preview-status component and is NOT redefined
 * here, so a site can adopt the review panel without its bar drifting. This file is
 * only the panel the Review control opens.
 *
 * The panel deliberately uses the client's own tokens, falling back to neutral
 * values when a site does not define them. Only the bar is GXM's; the thing a client
 * types into should look like their site.
 */
.gxm-review-panel {
  position: fixed; top: 2rem; left: 0; right: 0; z-index: 59;
  background: var(--ground, #fff);
  color: var(--ink, #111);
  border-bottom: 1px solid var(--hairline, #e3e7ec);
  box-shadow: 0 12px 28px rgba(0, 0, 0, .14);
  /* vh on iOS is the height without the browser's own chrome, so the panel ran under
     Safari's toolbar and took the status line with it. dvh follows the toolbar. */
  max-height: calc(100vh - 2rem);
  max-height: calc(100dvh - 2rem);
  overflow-y: auto;
}
.gxm-review-panel__inner {
  max-width: 68rem; margin: 0 auto;
  padding: 1.5rem var(--pad, 1.25rem) calc(1rem + env(safe-area-inset-bottom, 0px));
}
.gxm-review-panel h2 { margin: 0 0 .35rem; font-size: 1.15rem; }
.gxm-review-intro { margin: 0; font-size: .92rem; color: var(--ink-muted, #5a6472); }

.gxm-review-panel fieldset {
  border: 0; border-top: 1px solid var(--hairline, #e3e7ec);
  margin: 1.25rem 0 0; padding: 1rem 0 0;
}
.gxm-review-panel legend {
  font-size: .72rem; font-weight: 800; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-muted, #5a6472); padding: 0;
}

.gxm-field { margin-top: .85rem; max-width: 46rem; }
.gxm-field label { display: block; font-size: .88rem; font-weight: 600; margin-bottom: .3rem; }
.gxm-field input, .gxm-field textarea, .gxm-field select {
  width: 100%; font: inherit; font-size: .92rem; padding: .5rem .6rem;
  border: 1px solid var(--hairline, #e3e7ec); border-radius: 6px;
  background: var(--ground, #fff); color: var(--ink, #111);
}
.gxm-field textarea { resize: vertical; }
.gxm-field input:focus, .gxm-field textarea:focus, .gxm-field select:focus {
  outline: 2px solid var(--ink, #111); outline-offset: 1px; border-color: var(--ink, #111);
}

/* Confirmations. A value the site already shows is a yes or a no, not a blank box:
   asking somebody to retype an address that already looks right is how that question
   gets skipped. The No is what opens somewhere to type.

   The two options are radios with their native control hidden rather than buttons,
   because a radio group is what a screen reader and a keyboard already understand,
   and reimplementing that with buttons gets it wrong. */
.gxm-confirm__q {
  margin: 0; font-size: .88rem; font-weight: 600; color: var(--ink, #111);
}
.gxm-confirm__note {
  margin: .25rem 0 0; font-size: .82rem; color: var(--ink-muted, #5a6472);
}
.gxm-confirm__value {
  display: block; margin: .35rem 0 0; padding: .4rem .6rem;
  border-left: 3px solid var(--hairline, #e3e7ec);
  font-size: .88rem; color: var(--ink, #111); white-space: pre-line;
}
/* An asset somebody is being asked to approve has to be on screen while they answer.
   Contained rather than stretched: a mark is whatever size it is. */
.gxm-confirm__figure { margin: .5rem 0 0; }
.gxm-confirm__figure img {
  display: block; width: auto; max-width: 100%; max-height: 8rem;
  padding: .75rem; border: 1px solid var(--hairline, #e3e7ec); border-radius: 8px;
  background: #fff;
}
.gxm-confirm__choice {
  display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .55rem;
}
.gxm-field .gxm-confirm__opt {
  position: relative; display: inline-flex; margin-bottom: 0;
}
.gxm-confirm__opt input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  margin: 0; padding: 0; border: 0; opacity: 0; cursor: pointer;
}
.gxm-confirm__opt span {
  display: block; padding: .4rem 1.15rem; border-radius: 999px;
  border: 1px solid var(--hairline, #e3e7ec);
  font-size: .88rem; font-weight: 600; line-height: 1.35;
  background: var(--ground, #fff); color: var(--ink-muted, #5a6472);
  -webkit-user-select: none; user-select: none;
}
.gxm-confirm__opt input:checked + span {
  background: var(--accent, #6f53a8); border-color: var(--accent, #6f53a8); color: #fff;
}
.gxm-confirm__opt input:focus-visible + span {
  outline: 2px solid var(--ink, #111); outline-offset: 2px;
}
.gxm-confirm__fix {
  margin-top: .65rem; padding-left: .8rem;
  border-left: 3px solid var(--accent, #6f53a8);
}
.gxm-confirm__fix[hidden] { display: none; }
.gxm-confirm__fix label {
  font-size: .84rem; font-weight: 600;
}
/* A second prompt under an upload, for somebody who cannot attach the thing being
   asked for and needs to say where it is instead. */
.gxm-confirm__fix-note { margin-top: .7rem; }

/* A question that asks someone to read something should hand them the thing. */
.gxm-field-links {
  display: flex; flex-wrap: wrap; gap: .75rem;
  margin: -.1rem 0 .45rem;
  font-size: .84rem;
}
.gxm-field-links a {
  color: var(--accent, #6f53a8);
  text-decoration: underline; text-underline-offset: 2px;
}
.gxm-field-links a:focus-visible {
  outline: 2px solid var(--ink, #111); outline-offset: 2px;
}

/* The name gate. Asked once, before the questions, so nothing is filed under nobody. */
.gxm-review-gate { max-width: 28rem; padding: .5rem 0 1rem; }
.gxm-review-gate p { margin: 0 0 .8rem; font-size: .92rem; color: var(--ink-muted, #5a6472); }
.gxm-review-gate input {
  width: 100%; font: inherit; font-size: .95rem; padding: .55rem .65rem;
  border: 1px solid var(--hairline, #e3e7ec); border-radius: 6px;
  background: var(--ground, #fff); color: var(--ink, #111);
}
.gxm-review-gate input[aria-invalid="true"] { border-color: #cc2020; }
.gxm-review-gate button {
  margin-top: .7rem; font: inherit; font-weight: 600; font-size: .9rem;
  padding: .5rem 1.1rem; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--accent, #6f53a8); color: #fff;
}
.gxm-review-who {
  font-size: .78rem; font-weight: 600; color: var(--ink-muted, #5a6472);
}

/* What the others said, under the question they said it about. Colour is per person in
   arrival order and comes from the client's own accent, so a shared review reads as one
   site rather than importing a second palette. */
.gxm-comments { list-style: none; margin: .55rem 0 0; padding: 0; }
.gxm-comment {
  margin-top: .4rem; padding: .45rem .6rem;
  border-left: 3px solid var(--accent, #6f53a8);
  border-radius: 0 6px 6px 0;
  background: color-mix(in srgb, var(--accent, #6f53a8) 7%, transparent);
  font-size: .86rem;
}
.gxm-comment__who { display: block; font-weight: 700; color: var(--ink, #111); }
.gxm-comment__text { display: block; margin-top: .15rem; color: var(--ink-muted, #5a6472); white-space: pre-wrap; }
/* Four bands off the one accent, so people are told apart without a new colour scheme. */
.gxm-who-0 { border-left-color: var(--accent, #6f53a8); }
.gxm-who-1 { border-left-color: color-mix(in srgb, var(--accent, #6f53a8) 65%, #111); }
.gxm-who-2 { border-left-color: color-mix(in srgb, var(--accent, #6f53a8) 55%, #fff); }
.gxm-who-3 { border-left-color: color-mix(in srgb, var(--accent, #6f53a8) 70%, #d94d45); }

/* Uploads. The control is a plain file input on purpose: it is the one a phone already
   knows how to fill from the camera roll, and a bespoke dropzone is worse on the device
   most of these arrive from. */
.gxm-field input[type="file"] {
  width: 100%; padding: .55rem;
  border: 1px dashed var(--hairline, #c9cfd8); border-radius: 6px;
  background: var(--ground, #fff); font: inherit; font-size: .88rem;
}
.gxm-field input[type="file"]:focus-visible {
  outline: 2px solid var(--ink, #111); outline-offset: 1px;
}
.gxm-upload-hint {
  margin: .3rem 0 0; font-size: .8rem; color: var(--ink-muted, #5a6472);
}
.gxm-upload-list {
  list-style: none; margin: .5rem 0 0; padding: 0;
  font-size: .84rem; color: var(--ink-muted, #5a6472);
}
.gxm-upload-list li { padding: .15rem 0; }
.gxm-upload-list li.is-ok { color: #1a7f37; font-weight: 600; }
.gxm-upload-list li.is-warn { color: #b26a00; font-weight: 600; }
.gxm-upload-list li.is-error { color: #cc2020; font-weight: 600; }

.gxm-review-section { margin-top: 1.4rem; }
.gxm-review-section__heading {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  margin: 0 0 .65rem;
}
.gxm-review-section__heading h3 { margin: 0; font-size: 1rem; }
.gxm-review-section__heading p { margin: 0; color: var(--ink-muted, #5a6472); font-size: .84rem; }
.gxm-review-settled {
  margin-top: 1.4rem; padding-top: 1rem;
  border-top: 1px solid var(--hairline, #e3e7ec);
}
.gxm-review-settled > summary { cursor: pointer; font-weight: 700; }
.gxm-review-settled > summary span { color: var(--ink-muted, #5a6472); font-weight: 500; }
.gxm-review-group[hidden] { display: none; }
.gxm-review-bucket { display: grid; gap: 0; }
.gxm-field.is-settled { border-left: 3px solid #2f855a; padding-left: .85rem; }
.gxm-comment.is-superseded {
  border-left-color: #b26a00;
  background: color-mix(in srgb, #b26a00 8%, var(--ground, #fff));
}
.gxm-comment.is-superseded .gxm-comment__who { color: #8a5100; }
.gxm-review-contact {
  margin: 1.5rem 0 0; padding: 1rem;
  border: 1px solid var(--hairline, #e3e7ec); border-radius: .65rem;
  background: var(--wash, #f7f8fa);
}
.gxm-review-contact h3 { margin: 0 0 .25rem; font-size: 1rem; }
.gxm-review-contact p { margin: .25rem 0; }
.gxm-review-contact__links { display: flex; flex-wrap: wrap; gap: .75rem; }
.gxm-review-contact__links a { font-weight: 700; }

/* Autosave means there is no button to anchor the panel, so the status line is the
   only thing telling a reviewer their typing is safe. It gets a fixed row of its own
   rather than being appended to the last field. */
/* Autosave has no button, so this line is the only thing telling somebody their typing
   is safe. It sticks to the bottom of the panel rather than sitting at the end of a
   long scroll, where it was only visible if you happened to reach the last question. */
.gxm-review-actions {
  position: sticky; bottom: 0; z-index: 1;
  display: flex; align-items: center; gap: .5rem;
  margin-top: 1.5rem; padding: .7rem 0 calc(.7rem + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--hairline, #e3e7ec);
  background: var(--ground, #fff);
}
.gxm-review-status { font-size: .86rem; color: var(--ink-muted, #5a6472); }
.gxm-review-status.is-ok { color: #1a7f37; font-weight: 600; }
.gxm-review-status.is-warn { color: #b26a00; font-weight: 600; }
.gxm-review-status.is-error { color: #cc2020; font-weight: 600; }

.gxm-preview-status__count {
  margin-left: .3rem; padding: 0 .3rem; border-radius: 999px;
  background: #d94d45; color: #fff; font-size: .62rem;
}

/* ---------- review panel, FLOA-local additions ----------
   Kept below the canonical v1.2.0 block rather than inside it, so the copied
   bytes stay byte-comparable against docs/brand/preview-review/review.css. */
.gxm-group-intro {
  margin: .6rem 0 0; max-width: 46rem;
  font-size: .88rem; color: var(--ink-muted, #5a6472);
}
.gxm-hint {
  margin: -.15rem 0 .35rem; max-width: 46rem;
  font-size: .82rem; line-height: 1.5; color: var(--ink-muted, #5a6472);
}

/* A four-column table inside a fixed panel on a phone is the one place this site
   is allowed to scroll sideways, and only within its own box. */
.gxm-table-wrap { margin-top: .9rem; overflow-x: auto; }
.gxm-table {
  border-collapse: collapse; width: 100%; min-width: 47rem; font-size: .86rem;
}
.gxm-table th, .gxm-table td {
  text-align: left; vertical-align: top;
  padding: .5rem .6rem; border-bottom: 1px solid var(--hairline, #e3e7ec);
}
.gxm-table th {
  font-size: .72rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-muted, #5a6472); white-space: nowrap;
}
.gxm-table th.num, .gxm-table td.num { text-align: right; white-space: nowrap; }
.gxm-table tr.is-suggested { background: var(--ground-alt, #f2f2f3); }
.gxm-domain { font-weight: 700; overflow-wrap: anywhere; }
.gxm-domain-context {
  margin-top: .9rem; padding: .85rem 1rem;
  border-left: 3px solid var(--accent, #d94d45); background: var(--ground-alt, #f2f2f3);
}
.gxm-domain-context h4 { margin: 0 0 .25rem; font-size: 1rem; }
.gxm-domain-context p { margin: 0; max-width: 52rem; font-size: .86rem; line-height: 1.5; }
.gxm-domain-recommendation {
  margin-top: .75rem; padding: .9rem 1rem; border: 1px solid rgba(217,77,69,.28);
  background: rgba(217,77,69,.06);
}
.gxm-domain-recommendation > strong {
  display: block; margin-bottom: .4rem; color: var(--accent-dark, #aa2f29);
  font-size: .78rem; letter-spacing: .05em; text-transform: uppercase;
}
.gxm-domain-recommendation p { margin: .15rem 0; max-width: 50rem; font-size: .85rem; line-height: 1.45; }
.gxm-domain-help { margin: .75rem 0 .25rem; max-width: 50rem; font-size: .84rem; line-height: 1.45; }
.gxm-domain-lookup { margin: .25rem 0 .75rem; font-size: .82rem; }
.gxm-domain-other { margin: .85rem 0; max-width: 38rem; }
.gxm-domain-other label { display: block; margin-bottom: .25rem; font-weight: 700; }
.gxm-domain-other textarea { width: 100%; }
.gxm-domain-kind, .gxm-domain-price, .gxm-domain-renewal {
  display: block; margin-top: .18rem; color: var(--ink-muted, #5a6472);
  font-size: .72rem; line-height: 1.35;
}
.gxm-domain-kind { font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.gxm-domain-vote-cell { width: 5.8rem; }
.gxm-domain-vote.gxm-field {
  display: flex; gap: .35rem; margin: 0; padding: 0; border: 0;
}
.gxm-domain-vote__option { position: relative; cursor: pointer; }
.gxm-domain-vote__option input {
  position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.gxm-domain-vote__option span {
  display: grid; place-items: center; width: 2.25rem; height: 2.1rem;
  border: 1px solid var(--hairline, #d7dce2); border-radius: 5px;
  background: var(--ground, #fff); filter: grayscale(1); opacity: .62;
}
.gxm-domain-vote__option:hover span,
.gxm-domain-vote__option input:focus-visible + span {
  border-color: var(--ink, #111827); opacity: 1;
}
.gxm-domain-vote__option input:checked + span {
  border-color: var(--accent, #d94d45); background: #fff4f3;
  box-shadow: 0 0 0 2px rgba(217,77,69,.18); filter: none; opacity: 1;
}
@media (max-width: 40rem) {
  .gxm-table-wrap { overflow: visible; }
  .gxm-table, .gxm-table tbody, .gxm-table tr, .gxm-table td { display: block; width: 100%; }
  .gxm-table { min-width: 0; }
  .gxm-table thead { display: none; }
  .gxm-table tr {
    padding: .8rem .65rem; border-bottom: 1px solid var(--hairline, #e3e7ec);
  }
  .gxm-table th, .gxm-table td { padding: .2rem 0; border: 0; }
  .gxm-table td:nth-child(3) { margin-top: .25rem; line-height: 1.45; }
  .gxm-domain-vote-cell { width: auto; margin-top: .45rem; }
  .gxm-domain-vote__option span { width: 2.75rem; height: 2.35rem; }
}
.gxm-tag {
  display: inline-block; margin-left: .4rem; padding: 0 .35rem;
  border-radius: 999px; background: #d94d45; color: #fff;
  font-size: .62rem; font-weight: 700; letter-spacing: .03em; white-space: nowrap;
}
.gxm-note { margin: .75rem 0 0; max-width: 46rem; font-size: .86rem; }
.gxm-note--quiet { color: var(--ink-muted, #5a6472); font-size: .8rem; }

/* Six association cards in the four-column tile grid left a ragged row of two.
   These carry an acronym, a legal name, an area and a sentence, so they want more
   width than a link tile anyway. */
.grid--assoc { grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); }

/* The source note sat under a grid and inherited its full width, which made one
   small line the longest measure on the page. */
.source-note { max-width: var(--measure); }

/* Five style="" attributes were the only thing standing between this site and a
   content policy with no inline exception in it. Managed-site artifacts serve under
   style-src 'self', which blocks a style attribute as readily as a <style> block, so
   these were being dropped on the preview and would have cost the policy an
   'unsafe-inline' to keep. Four margins are not worth that. */
.after-block { margin-top: 1.5rem; }
.footnote { margin-top: 1.25rem; font-size: .9rem; }
.footnote--wide { margin-top: 1.5rem; max-width: 68ch; }

/* ---------- hero photo ----------
   The hero was a wall of text on a dark ground with no visual anchor. One photo
   beside the headline is the whole change; the copy column keeps its measure and
   the facts strip stays full width underneath, because it reads as a rule across
   the bottom of the hero rather than as a column of it. */
.hero-grid { display: grid; gap: clamp(1.5rem, 4vw, 2.5rem); align-items: center; }
@media (min-width: 62rem) {
  .hero-grid { grid-template-columns: 1.15fr 1fr; }
}
.hero-copy { min-width: 0; }
.hero-media { margin: 0; min-width: 0; }
.hero-media img {
  display: block; width: 100%; height: auto; aspect-ratio: 4 / 3;
  object-fit: cover; border: 1px solid rgba(255,255,255,.16);
}

/* The empty state is deliberately a frame rather than a grey block. A grey block
   reads as a broken image; a labelled frame reads as a decision nobody has made
   yet, which is what it is. */
.hero-media__empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .4rem; text-align: center; padding: 1.5rem;
  aspect-ratio: 4 / 3;
  border: 2px dashed rgba(255,255,255,.28);
  background: rgba(255,255,255,.04);
}
.hero-media__icon { color: rgba(255,255,255,.45); line-height: 0; }
.hero-media__label {
  margin: 0; font-weight: 700; font-size: .95rem; color: rgba(255,255,255,.82);
}
.hero-media__hint {
  margin: 0; max-width: 26ch; font-size: .82rem; line-height: 1.45;
  color: rgba(255,255,255,.5);
}

/* Hidden spam field stays outside keyboard navigation. */
.contact-trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

.footer-inner .footer-name { font-size: 1.05rem; line-height: 1.35; }


.floa-form .form-hint, .floa-form small { margin: 0; color: var(--ink-muted); font-size: .85rem; }
.floa-form > .form-hint { margin-top: -1rem; }
#floa-turnstile { min-height: 65px; }
#floa-contact-status:focus { outline: 2px solid var(--hairline); outline-offset: 4px; }
