/* ==========================================================================
   Site-specific styles, layered on top of @etaia/web-app's own /css/etaia.css
   (loaded first — see stylesheets in server.js). Two kinds of rules live
   here:
   1. Deliberate overrides of a few shared components (a light header instead
      of the framework's current dark-gradient default, a filled secondary
      button instead of its outline style) — kept as an intentional site
      choice rather than adopted, see the restructuring plan.
   2. Rules for classes that only exist on this site (hero variants, the
      transparent-header mechanism, the checklist/team/info-grid layouts,
      the ecosystem/community landscape page) with no framework counterpart
      at all.
   ========================================================================== */

:root {
  --accent-lavender: #F2F0FE;   /* light indigo fill — secondary buttons, hero panel */
  --section-text-color: rgb(69, 79, 94);   /* body text inside .content sections */
}

/* .page-content is the <main> wrapper around every page's body (see
   layouts/main.handlebars) -- same light indigo as the secondary-button
   fill/hero panel above, just applied page-wide. */
.page-content {
  background-color: var(--accent-lavender);
}

/* .card-grid's own margin-top (etaia.css has none, it's usually the only
   thing in a section there) so a section's cards -- rendered after its
   `blocks` (see home.handlebars/section-block.handlebars) -- get the same
   spacing as .icon-list/.info-grid above when there's a block ahead of
   them (e.g. Home's "Get started..." intro item, then its Body of
   Knowledge/Catalog cards). */
.card-grid {
  margin-top: 1.5rem;
}

/* ---------------- overrides: light header (vs. the framework's dark-gradient
   default), a couple of small token/shape tweaks ---------------- */
.site-header {
  background: var(--paper);
  border-bottom: 1px solid var(--hairline);
  box-shadow: 0 2px 5px rgba(27,14,46,.06);
}

/* Desktop only (min-width matches etaia.css's own 720px mobile breakpoint):
   unscoped, these would win over etaia.css's own <720px rules purely by
   load order (same specificity) -- a 135px logo plus 3rem padding made the
   mobile header ~230px tall, which on the transparent-header home page
   covered the hero title entirely.
   - roomier header padding and a bigger logo than etaia.css's own 120px
   - more breathing room between the nav items (etaia.css's base is 15px;
     on mobile .site-header-right is a vertical panel spacing rows via
     padding/border-bottom instead, gap:0 by design) */
@media (min-width: 721px) {
  .site-header {
    padding: 3rem 3rem;
  }

  .logo {
    height: 135px;
  }

  .site-header-right {
    gap: 2rem;
  }

  /* Login sits clearly apart from the rest of the nav (after the outlined
     "Get involved", see site-header.handlebars). */
  .nav-login {
    margin-left: 3rem;
  }
}

/* "Get involved" in the signed-out header nav: outlined, not filled --
   fills on hover, like .btn-secondary. */
.site-header .nav-outline {
  background: transparent;
  color: var(--etaia-02);
  border: 1px solid var(--etaia-02);
}

.site-header .nav-outline:hover,
.site-header .nav-outline.is-active,
.site-header .nav-outline:focus-visible {
  background: var(--etaia-02);
  color: #ffffff;
}

/* Mobile: the collapsed nav panel is dark (see .nav-link below 720px). */
@media (max-width: 720px) {
  .site-header .nav-outline {
    color: #e6d9f5;
    border-color: #e6d9f5;
  }

  /* Login set apart from "Get involved" right above it in the vertical
     panel (desktop's margin-left equivalent). */
  .nav-login {
    margin-top: 1rem;
  }
}

/* Over a transparent header's dark hero photo: white outline/text. */
body.has-transparent-header .site-header-right > .nav-outline,
body.has-dark-header .site-header-right > .nav-outline {
  color: #ffffff;
  border-color: #ffffff;
}

body.has-transparent-header .site-header-right > .nav-outline:hover,
body.has-transparent-header .site-header-right > .nav-outline.is-active,
body.has-transparent-header .site-header-right > .nav-outline:focus-visible,
body.has-dark-header .site-header-right > .nav-outline:hover,
body.has-dark-header .site-header-right > .nav-outline.is-active,
body.has-dark-header .site-header-right > .nav-outline:focus-visible {
  background: #ffffff;
  color: var(--etaia-02);
}

/* Mobile: compact bar (etaia.css's 44px logo), side padding matching the
   page gutter. */
@media (max-width: 720px) {
  .site-header {
    padding: 0.75rem 1rem;
  }
}

nav a, nav a:visited {
  color: var(--etaia-02);
  text-decoration: none;
  font-weight: 600;
}

/* :not(.btn) -- same reasoning as the transparent-header override further
   down: the signed-out Login button is also an <a> inside <nav>, but it's
   a .btn.btn-secondary with its own complete look; this plain-nav-link
   hover doesn't belong on it. Gradient text on hover, no underline --
   ported from the live site's own nav (its astra-child theme's own
   style.css, not the base Astra theme's customizer CSS: `.site-navigation
   ul.main-header-menu li a:hover { background-image: linear-gradient(to
   right, #5C64C0, #A84AC4); -webkit-background-clip: text;
   -webkit-text-fill-color: transparent; }`, also applied there to the
   current-page menu item, not just :hover). #A84AC4/#5C64C0 are our own
   --etaia-01/--etaia-02 almost exactly -- this site's palette was clearly
   drawn from that same gradient, so reuse the tokens rather than the raw
   hex. text-decoration must stay explicit (not just omitted) -- see
   etaia.css's own .nav-link:hover underline, cascades per-property. */
nav a:not(.btn):hover,
nav a.nav-link.is-active {
  background-image: linear-gradient(to right, var(--etaia-02), var(--etaia-01));
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  text-decoration: none;
}

/* The framework's .nav-toggle (mobile hamburger) defaults to white, right
   for its own dark-gradient header -- wrong here on the light header above.
   Transparent-header pages restore white below, since there it sits over
   the same dark hero photo the framework's own header would have. */
.nav-toggle {
  color: var(--etaia-02);
}

.nav-toggle:hover {
  background: color-mix(in srgb, var(--etaia-02) 10%, transparent);
}

.nav-toggle[aria-expanded="true"] {
  background: color-mix(in srgb, var(--etaia-02) 16%, transparent);
}

.nav-toggle:focus-visible {
  outline-color: var(--etaia-01);
}

/* Below 720px, .site-header-right's collapsed panel always gets the
   framework's own dark-gradient background (see etaia.css), regardless of
   this site's light/transparent header -- the indigo nav-link color above
   was tuned for a light background and reads poorly there, so restore the
   framework's original light-on-dark text for that panel specifically. */
@media (max-width: 720px) {
  .nav-link, .nav-link:visited {
    color: #e6d9f5;
  }

  .nav-link:hover,
  .nav-link.is-active {
    color: #ffffff;
  }
}

.user-dropdown-item--danger {
  color: var(--accent-red);
}

.btn {
  border-radius: 10px;
}

.btn-secondary {
  background: var(--accent-lavender);
  color: var(--etaia-02);
  border-color: transparent;
}

.btn-secondary:hover,
.btn-secondary:focus-visible {
  background: var(--etaia-02);
  color: #ffffff;
}

/* etaia.css's `.site-header .btn-secondary` (white text/border) is tuned
   for the framework's own dark-gradient header and outranks the plain
   `.btn-secondary` override above on specificity (two classes vs one) --
   it was winning here too, on this site's light header, leaving the
   Login button's lavender fill with unreadable white-on-white text.
   Restore this site's own look at matching specificity. */
.site-header .btn-secondary {
  color: var(--etaia-02);
  border-color: transparent;
}

.site-header .btn-secondary:hover,
.site-header .btn-secondary:focus-visible {
  background: var(--etaia-02);
  color: #ffffff;
}

/* h2 (section titles -- "Our purpose", "Empowering industry...", etc.)
   currently has no font-size/line-height of its own in etaia.css, so it
   falls back to the plain browser default (~1.5em). The live site's own
   section titles use Elementor's heading widget at its "default" size --
   which, per its shipped CSS (widget-heading.min.css), sets no font-size
   either: it's Astra's own theme default h2 (`h2{font-size:1.7em;
   line-height:1.3}`) showing through untouched, just with the kit's own
   color/font-family layered on top (already matched -- see etaia.css's
   h2{color:var(--etaia-02)} and the global Poppins font-family). Bringing
   in the one piece that was still missing. */
h2 {
  font-size: 1.7em;
  line-height: 1.3;
  background-image: linear-gradient(to right, rgb(92, 100, 192), rgb(168, 74, 196));
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

/* A section's own heading (`<div class="container"><h2>{{heading}}</h2>`,
   see home.handlebars and friends) bigger than the generic h2 above --
   `> ` (direct child) only, so it doesn't also catch a nested h2 further
   down inside the same .container, e.g. .ecosystem-level-title (its own
   separate rule further down already sets its size).
   .grid-cell-heading (section-block.handlebars's "text"/"bullets" blocks)
   gets the exact same size -- it's the same title, just relocated into
   one of its own section's ```grid cells instead of staying the section's
   own top-of-page heading (e.g. "Our purpose", home.txt) -- a class match
   regardless of nesting depth, unlike `> ` above, since a grid cell is
   never a direct child of .container. */
.container > h2,
.grid-cell-heading {
  font-size: 3rem;
}

.content {
  color: var(--section-text-color);
}

/* A section's own `|variant` modifier (e.g. "## Our activities|black",
   contentParser.js's SECTION_HEADING_RE) -- `color` here is enough to
   cover body text/bullets/items too via inheritance (none of them set
   their own), since nothing else in .content does either. h2/h3 titles
   already use --etaia-01/02 (a mid-brightness violet/indigo, including
   the h2 gradient) -- readable on black as-is, left untouched. */
.content--black {
  background: #000000;
  color: #e5e5e5;
}

/* `|center` (e.g. "## Who is the association for?|center", about-us.txt):
   centers the section's own title (and its subtitle line, if any) -- the
   blocks below keep their own alignment. */
.content--center > .container > h2,
.content--center > .container > .subtitle {
  text-align: center;
}

/* `|photo` -- the live site's own "Our activities" background (About us,
   Elementor container dcb1bbc): a photo under its dark #0D0614 overlay at
   0.8 opacity (--e-global-color-astglobalcolor7, overlay-opacity:0.8),
   here with this site's own home banner photo. The overlay is a gradient
   layer stacked over the photo rather than a ::before, so the section's
   own content needs no z-index juggling. Same light text as |black. */
.content--photo {
  background:
    linear-gradient(rgba(13, 6, 20, .8), rgba(13, 6, 20, .8)),
    url('/assets/home_banner.jpg') center / cover no-repeat;
  color: #e5e5e5;
}

/* `|tiles` -- the live site's own "Our activities" cells (About us,
   Elementor containers 1963e68 + fee1291...): the ```grid's cells butt up
   against each other as bordered tiles (1px #FFFFFF1A rules, no gap,
   48px/32px/48px/24px padding) and each one fills with #6528F7
   (--e-global-color-astglobalcolor0) on hover, over a 0.3s background
   transition. */
.content--tiles .info-grid {
  gap: 0;
  border: solid rgba(255, 255, 255, .1);
  border-width: 1px 0 0 1px;
}

.content--tiles .info-grid > div {
  padding: 48px 32px 48px 24px;
  border-right: 1px solid rgba(255, 255, 255, .1);
  transition: background-color .3s;
}

.content--tiles .info-grid > div:hover {
  background-color: #6528F7;
}

/* A section's own trailing action (the `[label]{Anchor:href}` line in
   src/data/*.txt, e.g. "Our mission →") -- rendered as a real button
   instead of a plain text link with an arrow. */
.section-cta {
  margin-top: 1.5rem;
}

/* `|center` on an anchor line ("[join us]{Anchor:/join|center}" or
   "...}|center") -- that button row centered (anyCentered helper). */
.button-row--center {
  justify-content: center;
}

/* A cell's own *several* trailing anchor lines (e.g. ATRASS' "Find out
   more"/"Stay informed"/"Propose a talk", events.txt -- see `links`,
   contentParser.js) render as more than one button in the same row --
   a colored border on each, back from the plain `.btn-secondary` override
   above (an intentional site-wide choice to drop it elsewhere, see this
   file's own header comment), so a *row* of several buttons reads as a
   distinct set instead of blending into the surrounding text. */
.section-cta.button-row .btn {
  border-color: var(--etaia-02);
}

/* ---------------- hero variants ---------------- */
/* Two-column hero (text + photo) — used when a section.hero contains a
   .hero-inner (see home.handlebars). Falls back to plain stacked text
   above (h1/p/button-row directly in .container) when there's no photo. */
.hero-inner {
  display: flex;
  align-items: center;
  gap: 3rem;
}

.hero-inner .hero-text {
  flex: 1 1 480px;
  min-width: 0;
}

.hero-inner .hero-text p {
  max-width: none;
}

.hero-image {
  flex: 1 1 380px;
  border-radius: 16px;
  width: 100%;
  max-width: 480px;
  height: auto;
  object-fit: cover;
  box-shadow: 0 8px 28px rgba(27,14,46,.12);
}

@media (max-width: 800px) {
  .hero-inner {
    flex-direction: column;
  }

  .hero-image {
    max-width: 100%;
  }
}

/* Full-bleed photo banner hero — inner pages (About us, and other pages
   sharing the same "header" banner pattern: photo + dark tint + white
   title), one background-image per page set inline via style="...". */
.hero--banner {
  position: relative;
  padding: 7.8rem 0 4.8rem; /* +20% over the original 6.5rem/4rem */
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-color: var(--ink-soft);
}

.hero--banner::before {
  content: "";
  position: absolute;
  inset: 0;
  /* Same overlay as the live site's home hero: near-black #0D0614 (its
     --e-global-color-astglobalcolor7) at its --overlay-opacity of 0.5, on
     every banner, home included -- one consistent tint instead of the live
     site's per-page colors (`![violet](url)`'s variant class is a no-op,
     kept harmless). */
  background-color: #0D0614;
  opacity: .5;
}

/* `![violet](url)` banners (About us, Contact, Events, Our community,
   Get involved):
   the live site's violet overlay on those pages -- #5C62B9 (its
   --e-global-color-secondary) at the same 0.5 opacity (Get involved's own
   is 0.65 there, close enough to share this one rule). */
.hero--banner--violet::before {
  background-color: #5C62B9;
}

/* Interior pages' banners (hero-banner.handlebars, not home's own hero):
   one shared minimum height so every page's banner looks the same size
   whatever its content (title only, title + paragraph, buttons...);
   content stays vertically centered within it. */
.hero--page {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 435px;
}

.hero--banner .container {
  position: relative;
  text-align: center;
  /* Wider than the generic .container's own min(1080px, calc(100% - 2rem))
     cap -- the hero is a full-bleed photo banner, not a reading column of
     text, so it doesn't need that cap holding its own content back from
     the viewport's edges the way body copy does. */
  width: 80%;
}

.hero--banner h1 {
  color: #ffffff;
  /* +50% over etaia.css's own base .hero h1 (clamp(2rem, 3vw, 3rem)) --
     all three clamp values scaled by 1.5 so it still shrinks/grows the
     same way at every viewport width. Medium weight (500, @font-face
     below -- etaia.css only ships 400/600/700): finer than the default
     700 at this size, without going as thin as Light. */
  font-size: clamp(3rem, 4.5vw, 4.5rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.15;
}

/* Poppins Medium, for the hero title above -- not among etaia.css's own
   Poppins weights. Served from this app's public/res/. */
@font-face {
  font-display: swap;
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  src: url('/res/poppins-v24-latin-500.woff2') format('woff2');
}

.hero--banner p {
  color: #f2f0fe;
  /* etaia.css's own .hero p keeps a 720px max-width with zero left/right
     margin -- fine when left-aligned, but with .container centered above,
     a narrower paragraph needs its own box centered too, not just its
     text within a box still flush left. Dropped entirely (not just
     widened) now that .hero--banner .container itself is 80% of the
     viewport, not a fixed reading-column width -- a paragraph capped at
     720px inside it would leave a visibly unused gap on either side. */
  max-width: none;
  margin-left: auto;
  margin-right: auto;
}

.hero--banner .hero-actions {
  margin-top: 1.5rem;
}

/* Only the links wrapper carries both .hero-actions and .button-row (see
   hero-banner.handlebars) -- .button-row is the one with display:flex
   (etaia.css), so justify-content only has an effect there; the Login
   button's own bare .hero-actions div (a single, non-flex block) is
   already centered by .container's own text-align above. */
.hero--banner .button-row {
  justify-content: center;
}

@media (max-width: 640px) {
  .hero--banner {
    padding: 5.4rem 0 3.6rem; /* +20% over the original 4.5rem/3rem */
  }

  /* Full width minus the page gutter instead of 80% (a 312px column at
     390px), and a title size that fits a phone: the desktop clamp's 2.4rem
     floor split "Trustworthy"-length words awkwardly over many lines. */
  .hero--banner .container {
    width: calc(100% - 2rem);
  }

  .hero--banner h1 {
    font-size: 2.4rem;
    line-height: 1.2;
    overflow-wrap: break-word;
  }
}

/* Transparent header sharing the hero's own background — the same logic as
   https://www.trustworthy-ai-association.eu/ itself (its Astra theme's
   "transparent header" option: #masthead{position:absolute} taken out of
   flow so .main-header-bar{background:none} lets whatever's behind it show
   through, confirmed by inspecting its shipped CSS). Opt-in via
   body.has-transparent-header (set from a page's own render options, e.g.
   Home's `transparentHeader: true` in server.js) so every other page keeps
   the normal, in-flow, opaque .site-header unless it explicitly asks for
   this. Only meaningful paired with a .hero--banner (or similarly dark,
   full-bleed) section as that page's very first element in .page-content —
   .hero--banner's own 7.8rem/5.4rem top padding (see above) already
   comfortably clears .site-header's 63px height once it's lifted out of
   flow, so no extra padding is added here. */
body.has-transparent-header .site-header {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  background: transparent;
  border-bottom: none;
  box-shadow: none;
}

/* .hero--banner's own dark photo + overlay is behind the header now too
   (see above) -- the header's normal dark nav-link colors would be
   unreadable against it, so both switch to white here (header.handlebars
   also swaps in logo-etaia-light.svg for the same reason, conditioned on
   this same transparentHeader flag). Scoped to *direct* children of
   .site-header-right (the nav items and, when signed out, the Login button)
   only -- not `.site-header-right a` -- so it doesn't reach into the
   .user-dropdown panel nested inside .user-menu: that panel sits on its own
   opaque white background regardless of the hero photo behind the header,
   and forcing its links white there made them unreadable. */
/* :not(.btn) -- the signed-out Login button is also a direct child of
   .site-header-right, but it's a .btn-secondary (lavender fill, indigo
   text): forcing it white here left white text on a light lavender
   background, unreadable. A button carries its own complete look
   (background + text color as a pair); only plain nav-link text should
   switch to white for the dark photo behind a transparent header. */
body.has-transparent-header .site-header-right > a:not(.btn),
body.has-transparent-header .nav-toggle,
body.has-dark-header .site-header-right > a:not(.btn),
body.has-dark-header .nav-toggle {
  color: #ffffff;
}

body.has-transparent-header .site-header-right > a:not(.btn):hover,
body.has-transparent-header .site-header-right > a.nav-link.is-active,
body.has-dark-header .site-header-right > a:not(.btn):hover,
body.has-dark-header .site-header-right > a.nav-link.is-active {
  color: #f2f0fe;
}

body.has-transparent-header .nav-toggle:hover,
body.has-dark-header .nav-toggle:hover {
  background: rgba(255, 255, 255, .12);
}

body.has-transparent-header .nav-toggle[aria-expanded="true"],
body.has-dark-header .nav-toggle[aria-expanded="true"] {
  background: rgba(255, 255, 255, .2);
}

/* Dark header -- opt-in via body.has-dark-header (a page's own
   `darkHeader: true`, e.g. the intranet home in server.js): @etaia/web-app's
   own header look (etaia.css's .site-header gradient + shadow, white logo
   -- site-header.handlebars swaps it in on this same flag) instead of this
   site's light one, for a page with no hero banner to sit a transparent
   header on. Text/link colors are shared with .has-transparent-header
   above; this site's own header sizing (padding, logo) is kept. */
body.has-dark-header .site-header {
  background: linear-gradient(135deg, #3A1F57 0%, #4C1F7C 45%, #2C1148 100%);
  border-bottom: none;
  box-shadow: 0 2px 5px #0003;
}

/* An image that's the sole content of an .info-grid cell (e.g. Home's
   "Our purpose" -- a ```grid 2x1 fence with an image cell next to a
   bullet-list cell, see home.txt/section-block.handlebars) gets the same
   treatment .content-split-image used to (now removed -- this replaced
   that hardcoded, heading-specific layout with a generic ```grid fence):
   fills its cell, cover-cropped, rounded, with a soft shadow -- instead of
   .content-image's plain small-inline-picture default. */
.info-grid > div > p:only-child > img.content-image:only-child,
.info-grid > a > p:only-child > img.content-image:only-child {
  display: block;
  width: 100%;
  height: auto;
  margin: 0;
  border-radius: 16px;
  object-fit: cover;
}

/* A whole-cell link (a ```grid cell with an empty-label "[]{Anchor:href}"
   line, section-block.handlebars): the cell's own content, unchanged look
   (no link color/underline), with a slight lift on hover so it reads as
   clickable. */
.info-grid-cell-link {
  display: block;
  color: inherit;
  text-decoration: none;
  border-radius: 16px;
  transition: transform 0.2s, box-shadow 0.2s;
}

.info-grid-cell-link:hover,
.info-grid-cell-link:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 10px 24px rgba(27, 14, 46, 0.12);
}

.info-grid-cell-link h3 {
  color: var(--etaia-02);
}

/* ---------------- checklist / rich-text-like rendering ---------------- */
/* Checklist-style list (e.g. Home's "Our purpose") -- each <li> carries its
   own inline check-circle icon (Font Awesome solid's path, same markup
   trustworthy-ai-association.eu itself renders for this exact list via
   Elementor's icon-list widget, class names kept for parity) instead of a
   default bullet. The live widget instance itself has no color override at
   all (plain default black icon) -- deliberately deviating from it here:
   the icon is colored etaia-02 (indigo) instead, a per-site design choice. */
.icon-list {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.icon-list li {
  display: flex;
  align-items: flex-start;
  gap: 0.4rem;
}

.icon-list .e-font-icon-svg {
  flex: 0 0 auto;
  width: 1.15em;
  height: 1.15em;
  margin-top: 0.2em;
  fill: var(--etaia-02);
}

/* Rendered by md()/mdBlock() (see server.js) out of a src/data/*.txt text
   field's `[text](url)`/`![alt](url)`/`## `/`### ` markdown-like syntax --
   ported from the bok webapp's own equivalent, see .bok-external-icon/
   .bok-inspector-image/.bok-insp-subheading in bok/webapp/public/css/bok.css.
   (@etaia/web-app has since grown its own generic equivalent, richText()/
   .richtext-inline-* — migrating onto that instead of this parallel
   home-grown version is a good follow-up, out of scope for now.) */
.external-icon {
  width: 0.75em;
  height: 0.75em;
  margin-left: 3px;
  vertical-align: -0.05em;
}

.content-image {
  display: block;
  max-width: 100%;
  border-radius: 6px;
  margin: 0.4rem 0;
}

.content-subheading {
  margin: 1.2rem 0 0.4rem;
  color: var(--title-color);
}

.content-subheading:first-child {
  margin-top: 0;
}

h4.content-subheading {
  font-size: 1.05rem;
}

/* ---------------- team grid (About us — "Our team") ---------------- */
.team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1.5rem;
  margin-top: 1.5rem;
}

.team-member {
  text-align: center;
}

.team-photo {
  width: 140px;
  height: 140px;
  border-radius: 50%;
  overflow: hidden;
  margin: 0 auto 0.8rem;
  border: 2px solid var(--hairline);
}

.team-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.team-name {
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--text-color);
  margin: 0;
}

.team-role {
  color: var(--text-muted-color);
  font-size: 0.85rem;
  margin: 0.15rem 0 0;
}

/* ---------------- two-column info grid (About us — "Who is the
   association for?", "Our activities") ---------------- */
.info-grid {
  display: grid;
  /* --grid-cols: set inline by a ```grid COLSxROWS fence's own cell count
     (section-block.handlebars) -- a CSS custom property rather than
     grid-template-columns itself, so the actual property is still set by
     this class rule (defaults to 2 when absent) and the mobile media
     query below can still override it. An inline grid-template-columns
     would always win over any external rule, media query or not. */
  grid-template-columns: repeat(var(--grid-cols, 2), 1fr);
  gap: 2rem;
  margin-top: 1.5rem;
}

/* A single item (e.g. Home's "Get started..." -- one plain "Actionable
   resources..." item ahead of its ```card cards) would otherwise sit in
   just the left half of the fixed 2-column grid above, the right half
   empty -- span the full width instead. Only applied when there's
   actually one item (see home.handlebars), so a real 2+ item grid (About
   us's "Who is the association for?", Home's "Be part of...") keeps its
   columns. */
.info-grid--full {
  grid-template-columns: 1fr;
}

.info-grid h3 {
  margin: 0 0 0.4rem;
}

.info-grid p {
  line-height: 1.6;
  margin: 0;
}

.info-grid p + p {
  margin-top: 0.6rem;
}

@media (max-width: 640px) {
  .info-grid { grid-template-columns: 1fr; }
}

/* `## <heading>|divided` (e.g. Contact's "Contact us"): a ```grid's last
   cell alone in the right column, spanning two rows (e.g. the form), its
   earlier cells stacked on the left (e.g. address list, then map), split
   by a violet vertical rule -- a horizontal one once the grid stacks on
   mobile. A map cell fills the rest of its column's height. */
.content--divided .info-grid > * {
  grid-column: 1;
}

.content--divided .info-grid > :last-child:not(:first-child) {
  grid-column: 2;
  grid-row: 1 / span 2;
  border-left: 2px solid var(--etaia-01);
  padding-left: 2rem;
}

.content--divided .info-grid .google-map {
  height: 100%;
  min-height: 360px;
  margin-top: 0;
}

@media (max-width: 640px) {
  .content--divided .info-grid > :last-child:not(:first-child) {
    grid-column: 1;
    grid-row: auto;
    border-left: none;
    padding-left: 0;
    border-top: 2px solid var(--etaia-01);
    padding-top: 2rem;
  }
}

/* A ```grid cell's own `|variant` (a `### <heading>|variant` item, see
   contentParser.js's SUBITEM_HEADING_RE) -- `cta` is a gradient call-to-
   action panel, ported from the live production site's own "Engage with
   us" card next to "Join the pioneers..." (home.txt): centered white text
   on a radial violet/indigo gradient, confirmed against its shipped CSS
   (background-color #A84AC4 under a radial-gradient(at top left, #5C64C0
   45%, #994FC3 100%) overlay) -- approximated here with this site's own
   --etaia-02/--etaia-01 tokens (close to those two stops) rather than the
   live site's raw hex, same as the nav/h2 gradients elsewhere. */
.info-grid-cell--cta {
  padding: 2.5rem 2rem;
  border-radius: 10px;
  background: radial-gradient(at top left, var(--etaia-02), var(--etaia-01));
  color: #ffffff;
  text-align: center;
}

.info-grid-cell--cta h3 {
  color: #ffffff;
  font-size: 2rem;
}

.info-grid-cell--cta p {
  color: #ffffff;
}

/* .button-row's own `display: flex` positions its buttons by flexbox, not
   text-align (that only affects inline content) -- `justify-content`
   centers them to match the rest of this cell's own centered text. */
.info-grid-cell--cta .section-cta.button-row {
  justify-content: center;
}

/* Overrides both the generic .btn-secondary (filled lavender/indigo, see
   this file's own header comment) and .section-cta.button-row .btn's own
   border-color override above -- same specificity (4 classes each), so
   source order (this comes after) decides; a white pill button reading
   against the gradient instead, inverting to solid indigo on hover, same
   as the live site's own. */
.info-grid-cell--cta .section-cta.button-row .btn {
  background: #ffffff;
  color: var(--etaia-02);
  border-color: transparent;
}

.info-grid-cell--cta .section-cta.button-row .btn:hover,
.info-grid-cell--cta .section-cta.button-row .btn:focus-visible {
  background: var(--etaia-02);
  color: #ffffff;
}

/* ---------------- numbered row (```numbered fence, see
   section-block.handlebars) ----------------
   Ported from the live site's About us "Who is the association for?"
   block (Elementor container a884b63, post-2045.css): 4 columns (2 on
   tablet, 1 on phone), no gap -- each item's own right padding spaces
   them; a 1px top rule turning #6528F7 (its astglobalcolor0) on hover over
   0.3s; small uppercase letter-spaced number in that same violet, an 18px
   title in #5962BF (≈ our --etaia-02), 14px body text. The live rule is
   white (invisible on its white section) until hover -- a visible hairline
   here so the columns still read as separate at rest. */
.numbered {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin-top: 3rem;
}

.numbered-item {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 32px 64px 32px 0;
  border-top: 1px solid var(--hairline);
  transition: border-color 0.3s;
}

.numbered-item:hover {
  border-top-color: #6528F7;
}

.numbered-index {
  padding-bottom: 16px;
  color: #6528F7;
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 2px;
}

.numbered-title {
  margin: 0;
  color: var(--etaia-02);
  font-size: 18px;
}

.numbered-item p {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
}

@media (max-width: 1024px) {
  .numbered {
    grid-template-columns: repeat(2, 1fr);
  }

  .numbered-item {
    padding: 24px 24px 24px 0;
  }
}

@media (max-width: 640px) {
  .numbered {
    grid-template-columns: 1fr;
  }
}

/* ---------------- card variant: media (cover image) ---------------- */
.card--media {
  padding: 0;
  gap: 0;
  overflow: hidden;
}

.card--media .card-image {
  width: 100%;
  height: auto;
  display: block;
}

.card--media .card-media-body {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: 1.1rem 1.4rem 1.3rem;
}

/* ---------------- [hidden] fixes for shared toggle-driven components
   (site-extra.js), not yet backported to the framework ---------------- */
/* Same trap as .btn[hidden] in etaia.css: .search-clear's own `display: flex`
   otherwise beats the browser's default [hidden]{display:none}, so the
   table-explorer and ecosystem search boxes (both toggle this button's
   `hidden` attribute in site-extra.js) would never actually be able to hide
   it once shown. */
.search-clear[hidden] {
  display: none;
}

/* Same trap as .btn[hidden] above: .table-bulk-bar's own `display: flex`
   otherwise beats the browser's default [hidden]{display:none}, and
   data-table-explorer's row-selection bar relies on toggling exactly that
   attribute as rows get checked/unchecked. */
.table-bulk-bar[hidden] {
  display: none;
}

/* Shared by any ```<name> widget's own error/empty state (see the "widget"
   branch in section-block.handlebars) -- Our community's
   ecosystem-landscape is the one actually using these right now, kept
   generic rather than ecosystem-specific-named in case a future widget
   needs the same look (Events doesn't -- its ```event fences are authored
   content, not a widget, so there's no fetch to fail). */
.widget-error {
  color: var(--danger-color);
  font-weight: 600;
}

.widget-empty {
  color: var(--text-muted-color);
  margin-top: 1rem;
}

/* ---------------- events grid (see /events, ```event fences in
   events.txt, rendered via event-card.handlebars) -- image-beside-text,
   one per row, ported from the old site's src/pages/events.astro layout
   ---------------- */
.event-grid {
  display: grid;
  gap: 2rem;
  margin-top: 1.5rem;
}

.event-card {
  display: grid;
  grid-template-columns: 2fr 3fr;
  gap: 1.5rem;
  align-items: start;
  padding: 1.5rem;
  border: 1px solid var(--hairline);
  border-radius: 8px;
}

.event-card-image {
  width: 100%;
  border-radius: 4px;
  object-fit: cover;
}

.event-card-body h3 {
  margin: 0 0 0.4rem;
}

.event-card-date {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--text-muted-color);
  font-size: 0.9rem;
  margin: 0 0 0.6rem;
}

/* Shared by icon-calendar.handlebars/icon-clock.handlebars, wherever an
   event/session shows a date or time-of-day range next to one. */
.event-icon {
  width: 1em;
  height: 1em;
  flex-shrink: 0;
}

@media (max-width: 640px) {
  .event-card {
    grid-template-columns: 1fr;
  }
}

/* A recurring event's own individual sessions (see event-session.handlebars,
   e.g. ATRASS's monthly seminars) -- a compact row each, not a full
   .event-card, since there can be many. */
.event-sessions {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-top: 1rem;
}

.event-session {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  padding: 0.75rem 1rem;
  background: var(--paper-sunk);
  border-radius: 6px;
}

.event-session-logo {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex-shrink: 0;
}

.event-session-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
}

.event-session-title {
  font-weight: 600;
}

.event-session-date,
.event-session-time {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--text-muted-color);
  font-size: 0.9rem;
}

.event-session-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

/* ---------------- google map (see ```google-map widget, Contact page)
   ---------------- */
.google-map {
  display: block;
  width: 100%;
  height: 360px;
  margin-top: 1.5rem;
  border: 1px solid var(--hairline);
  border-radius: 8px;
}

/* ---------------- media video (see ```media-video widget, Onboarding page)
   -- 16:9 frame around media's own /embed player ---------------- */
.media-embed {
  aspect-ratio: 16 / 9;
  width: 100%;
  margin-top: 1.5rem;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  overflow: hidden;
  background: #000;
}

.media-embed iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* ---------------- note callout (see ```note fences, note-card.handlebars)
   -- ported from a specific highlighted-panel look on the live production
   site's own About us page (a white card on a white page background,
   distinguished mainly by its border and a lift-shadow on hover; here
   given a visible border instead, since a white-on-white border would be
   invisible against this site's own paper background too) ---------------- */
.note-grid {
  margin-top: 1.5rem;
}

.note-card {
  padding: 1.75rem 2rem;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: var(--paper);
  transition: box-shadow 0.15s ease;
}

.note-card:hover {
  box-shadow: 0 12px 32px -8px rgba(0, 0, 0, 0.16);
}

.note-card-title {
  margin: 0 0 0.8rem;
}

.note-card-title,
.note-card p {
  font-size: 0.85rem;
  font-weight: 400;
  letter-spacing: 0.1em;
}

.note-card p {
  color: var(--section-text-color);
  line-height: 1.6;
}

.note-card p + p {
  margin-top: 0.6rem;
}

/* ---------------- Working Groups (see /intranet, ```wg fences,
   wg-card.handlebars) ---------------- */
/* One WG per row rather than side-by-side (same stacked shape as
   .event-grid) -- a WG card carries enough text (mission, how it operates,
   co-chairs) that a multi-column grid left too little width per card. */
.wg-grid {
  display: grid;
  gap: 1.5rem;
  margin-top: 1.5rem;
}

.wg-card {
  position: relative;
  display: block;
  padding: 1.1rem 1.3rem;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  color: inherit;
  text-decoration: none;
}

a.wg-card:hover {
  border-color: var(--etaia-02);
}

.wg-card h3 {
  margin: 0 6rem 0.6rem 0;
  font-size: 1.05rem;
}

/* Co-chair avatars + the "open"/"restricted" padlock badge (see
   contentParser.js's parseWgFence), stacked together in the card's
   top-right corner for a compact card -- no name/role text on the card
   itself, just a hover tooltip on each avatar (see wg-card.handlebars). */
.wg-card-topright {
  position: absolute;
  top: 1rem;
  right: 1.3rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.wg-card-cochairs {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.wg-cochair-avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--paper);
  background: var(--paper-sunk);
}

.wg-cochair-avatar + .wg-cochair-avatar {
  margin-left: -1.2rem;
}

.wg-card-status {
  color: var(--text-muted-color);
}

.wg-status-icon {
  width: 1.1em;
  height: 1.1em;
}

.wg-card-section {
  margin-top: 0.6rem;
}

.wg-card-section h4 {
  margin: 0 0 0.2rem;
  font-size: 0.9rem;
}

.wg-card-section p {
  color: var(--section-text-color);
  line-height: 1.5;
}

.wg-card-section .icon-list {
  margin-top: 0.4rem;
  gap: 0.3rem;
}

/* Inside a WG card, a plain bullet instead of the site-wide check-circle
   (section-block.handlebars still renders the <svg>, just hidden here). */
.wg-card-section .icon-list .e-font-icon-svg {
  display: none;
}

.wg-card-section .icon-list li::before {
  content: "";
  flex: 0 0 auto;
  width: 0.45em;
  height: 0.45em;
  margin: 0.5em 0.15em 0 0.1em;
  border-radius: 50%;
  background: var(--etaia-02);
}

/* ---------------- ecosystem / community landscape (see /our-community,
   ecosystem.handlebars) ---------------- */

/* .table-filter-chip is normally an <a> (see data-table-explorer.handlebars)
   -- reused here on <button> elements for the activity-type filter, so undo
   the browser's own button chrome without touching that shared base rule. */
button.table-filter-chip {
  appearance: none;
  font: inherit;
  cursor: pointer;
}

.ecosystem-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.2rem;
  margin-top: 1.5rem;
  margin-bottom: 1.5rem;
}

.ecosystem-search {
  margin-bottom: 0;
}

.ecosystem-landscape {
  display: flex;
  align-items: stretch;
  gap: 1rem;
}

.ecosystem-levels {
  flex: 1;
  min-width: 0;
}

.ecosystem-level + .ecosystem-level {
  margin-top: 2rem;
}

/* The generic h2 {} gradient-text rule above (background-clip: text +
   -webkit-text-fill-color: transparent) applies to every h2, this one
   included -- its own `background`/`color` here override the *shorthand*-
   covered parts (background-clip reverts to border-box as a side effect of
   the `background` shorthand resetting it), but -webkit-text-fill-color
   isn't covered by either shorthand, so without resetting it explicitly
   here too, the bar's own white text stayed transparent in Chrome/Edge/
   Safari (WebKit prioritizes -webkit-text-fill-color over `color` once
   anything sets it to other than currentcolor) -- invisible on its own
   solid violet background. */
/* Violet title over a violet bottom rule (no fill). `background: none`
   also clears the site-wide h2 gradient-text (background-clip: text, see
   `h2` above), and -webkit-text-fill-color undoes its transparent fill. */
.ecosystem-level-title {
  margin: 0 0 1.1rem;
  padding: 0 0 0.5rem;
  background: none;
  border-bottom: 2px solid var(--etaia-01);
  color: var(--etaia-01);
  -webkit-text-fill-color: var(--etaia-01);
  font-size: 0.9rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.ecosystem-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 1rem;
}

.ecosystem-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  padding: 1rem 0.8rem;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: var(--paper);
  text-decoration: none;
  color: var(--text-color);
  text-align: center;
  transition: border-color .15s ease, box-shadow .15s ease;
}

/* .ecosystem-tile's own `display: flex` above otherwise beats the browser's
   default [hidden]{display:none} at equal specificity -- the search/activity
   filter (site-extra.js) relies on toggling exactly that attribute per tile,
   so without this every tile would stay visible regardless of the active
   filter (see .btn[hidden] in etaia.css for another case of this same trap). */
.ecosystem-tile[hidden] {
  display: none;
}

/* Hover feedback only on tiles that actually link out (an <a>, i.e. the
   member has a website) -- an unlinked <div> tile stays still. */
a.ecosystem-tile:hover {
  border-color: var(--etaia-02);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
}

.ecosystem-tile-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  overflow: hidden;
  flex-shrink: 0;
}

/* A member with no logo of its own (or whose logo failed to load, see the
   error handler in site-extra.js) shows the association's own mark instead --
   drawn in white, so it needs a fill of its own rather than .ecosystem-tile-
   logo's neutral one, plus a little breathing room since it's a wide
   wordmark, not an icon meant to fill a square. */
.ecosystem-tile-logo--fallback {
  padding: 10px;
}

.ecosystem-tile-logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.ecosystem-tile-name {
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.3;
}

.ecosystem-tile-badge {
  margin-top: -0.2rem;
}

.chip-neutral {
  background: var(--paper-sunk);
  color: var(--text-muted-color);
}

/* ---------------- footer (site-footer.handlebars) ----------------
   Overrides most of etaia.css's own .site-footer defaults (dark/centered/
   single-line) -- this one has real structure (brand+social, nav columns,
   a legal-links row, a colored copyright bar), ported from the live
   site's own footer. */
.site-footer.footer--rich {
  background: var(--paper);
  padding: 0;
  border-top: none;
  text-align: left;
  font-size: 1rem;
}

/* Same reasoning/value as .hero--banner's own .container override above --
   wider than the generic .container's min(1080px, calc(100% - 2rem)) cap.
   Matches both of this footer's own .container divs (footer-top and
   footer-legal, site-footer.handlebars). */
.site-footer.footer--rich .container {
  width: 80%;
}

.footer-top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 2.5rem;
  padding: 3rem 0;
}

.footer-brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.25rem;
}

.footer-logo {
  height: 48px;
  width: auto;
}

.footer-social {
  display: flex;
  gap: 1rem;
}

/* `:visited` explicitly -- same reasoning as .footer-nav/.footer-legal's
   own above (etaia.css's `.site-footer a:visited` otherwise wins once a
   visitor has actually followed one of these -- external, so a real
   visited URL, unlike most of this site's own internal links). svg below
   inherits this via `fill: currentColor`, so it'd otherwise go muted gray
   too, not just the icon's invisible <a> box. */
.footer-social a,
.footer-social a:visited {
  display: flex;
  color: var(--etaia-02);
}

.footer-social a:hover {
  color: var(--etaia-01);
}

.footer-social svg {
  width: 20px;
  height: 20px;
  fill: currentColor;
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 10rem;
}

.footer-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* `:visited` explicitly, not just plain `a` -- etaia.css's own `.site-footer
   a, .site-footer a:visited { color: var(--text-muted-color); }` targets
   :visited with higher specificity (class+element+pseudo-class) than a
   plain `.footer-nav a`/`.footer-legal a` (class+element) can match, so it
   wins regardless of load order once a visitor has actually been to one of
   these links -- back to this site's own indigo rather than silently
   falling back to the framework's muted gray. */
.footer-nav a,
.footer-nav a:visited,
.footer-legal a,
.footer-legal a:visited {
  color: var(--etaia-02);
  text-decoration: none;
  font-weight: 600;
}

.footer-nav a:hover,
.footer-legal a:hover {
  color: var(--etaia-01);
  text-decoration: underline;
}

/* Full-width lavender band behind the legal-links row -- its own wrapper,
   since .footer-legal itself is a width-capped .container. */
.footer-legal-band {
  background-color: var(--accent-lavender);
}

.footer-legal {
  padding: 0.9rem 0;
  font-size: 0.85rem;
}

/* Spread across the row's full width -- ported from the live site's own
   legal-links row (Elementor's "Justified" nav-menu alignment,
   .elementor-nav-menu__align-justify on that exact widget) -- rather than
   clustered to the left with a fixed gap. `gap` remains as the fallback
   once it wraps (<720px, one item per line -- space-between has nothing
   left to distribute there). */
.footer-legal ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
}

.footer-copyright {
  background: var(--etaia-02);
  padding: 1rem;
  text-align: center;
}

.footer-copyright p {
  margin: 0;
  color: var(--paper);
  font-size: 0.85rem;
}

@media (max-width: 720px) {
  .site-footer.footer--rich .container {
    width: calc(100% - 2rem);
  }

  .footer-top {
    flex-direction: column;
    gap: 2rem;
    padding: 2rem 0;
  }

  /* The three link columns read as one stacked list on a phone: same
     spacing between columns as between links inside one (desktop's 10rem
     column gap became 10rem of empty space between stacked groups), and
     taller rows for touch targets. */
  .footer-nav {
    flex-direction: column;
    gap: 0;
  }

  .footer-nav ul {
    gap: 0;
  }

  .footer-nav a {
    display: block;
    padding: 0.6rem 0;
  }

  .footer-legal ul {
    flex-direction: column;
    gap: 0;
  }

  .footer-legal a {
    display: block;
    padding: 0.4rem 0;
  }
}

/* Shared form primitives (join/contact/talk-proposal/atrass-subscribe widgets,
   section-block.handlebars) -- built on etaia.css's own .form-* styles. */
.form-required-note {
  font-size: 0.82rem;
  color: var(--text-muted-color);
}

/* Native forms (join/contact/talk-proposal/atrass-subscribe widgets,
   JotForm phase-out #84, Mailchimp phase-out #85). */
.join-form {
  max-width: 640px;
  margin: 2rem auto 0;
}

.join-form .asterisk,
.form-field .asterisk,
.form-label .asterisk {
  color: var(--accent-red);
}

.join-form .form-check {
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
  margin: 0.4rem 0;
}

/* Long legal text (e.g. the join consent paragraph) reads as one block of
   prose instead of a stretched two-column flex row. */
.join-form .form-check--block {
  display: block;
}

.join-form .form-check--block input[type='checkbox'] {
  display: inline-block;
  margin: 0 0.5em 0 0;
  vertical-align: baseline;
}

.join-form fieldset.form-field {
  border: 0;
  padding: 0;
  margin: 0.5rem 0 1rem;
}

.join-honeypot {
  position: absolute;
  left: -5000px;
}

.form-field-error {
  color: var(--accent-red);
  font-size: 0.85rem;
  margin: 0.25rem 0 0;
}

.form-success {
  max-width: 640px;
  margin: 2rem auto 0;
  padding: 1.5rem;
  border: 1px solid var(--success-color, #2e7d32);
  border-radius: 8px;
}

.form-error {
  max-width: 640px;
  margin: 2rem auto 0;
  padding: 1rem 1.5rem;
  border: 1px solid var(--accent-red);
  border-radius: 8px;
}

.form-status {
  font-size: 0.85rem;
  color: var(--text-muted-color);
  min-height: 1.2em;
}

.form-privacy {
  font-size: 0.85rem;
  color: var(--text-muted-color);
  margin-top: 1rem;
}
