/* ============================================================
   CRONAH — styles.css
   Token system: deep-forest dark theme. The page sits on top of the
   3D earth rendered by globe.js into #globe-canvas. The hero and the
   map section are transparent so the globe shows through sharp.

   GLASS CONTRACT (landing page only — body.glass-page, see the GLASS
   THEME block at the end of this file): every other landing section
   is translucent glass over the globe. That is affordable because
   globe.js treats those sections as "soft" windows: it renders at
   half resolution and a capped frame rate while only glass is on
   screen — invisible through a 26px blur. The base rules below keep
   the original opaque surfaces, which is what every page other than
   index.html still uses, and what the landing page falls back to
   when backdrop-filter is unsupported.

   The greens from the brand palette carry the light-on-dark roles:
   leaf green for structure and accents, a pale green for filled
   CTAs. Three type roles.
   Modes: body[data-mode="b2b"] / body[data-mode="b2c"]
   ============================================================ */

:root {
  /* Tells the browser to render its own chrome (scrollbars, date
     pickers, autofill, select dropdowns) dark. Set here rather than
     per-page so admin.html, profile.html and event.html get it too. */
  color-scheme: dark;

  /* --- Forest substrate: what everything is layered on --- */
  --space-0: #08170e;  /* deepest black-green — matches globe.js clear color. Nudged a touch lighter than pure black so the sky doesn't read as flat void; stars still sit far above this in brightness. */
  --space-1: #0c1e13;  /* panel base */
  --space-2: #13291a;  /* raised panel (cards, inputs, modals) */

  /* Color tokens */
  --ink:   #e7f0e4;  /* primary text — off-white with a green cast */
  --pine:  #bcd6a4;  /* leaf green — accents, headings, data highlights */
  --leaf:  #d3e8b0;  /* lighter leaf green — hover borders, emphasis */
  --moss:  #a0bda4;  /* muted secondary text (8.7:1 on the section base, 7.6:1 on --space-2) */
  --mist:  rgba(160, 214, 140, 0.07);  /* faint green wash over the substrate */
  --paper: rgba(12, 30, 19, 0.76);     /* translucent panel surface */
  --line:  rgba(160, 214, 140, 0.20);  /* hairline borders */

  /* Text/icon color for anything sitting ON a filled accent surface.
     --ink is light now, so filled buttons need their own inverse. */
  --ink-invert: #071309;

  /* Pale leaf-green accent — reserved for buttons and filled interactive
     elements. Kept light enough that --ink-invert (dark) text on top
     still has strong contrast. */
  --sage-accent:        #cfe9ae;
  --sage-accent-bright: #ddf2c2;

  /* Per-mode accent (JS-free: driven by attribute selectors below) */
  --accent: var(--sage-accent);

  /* Type roles */
  --font-display: "Fraunces", Georgia, serif;
  --font-body: "Public Sans", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  --radius: 14px;
  --maxw: 1120px;
}

body[data-mode="b2c"] { --accent: var(--sage-accent); }

/* ---------- Reset & base ---------- */
*, *::before, *::after { box-sizing: border-box; }
/* The hidden attribute must ALWAYS win, no matter what display
   value any other rule sets. Fixes modals/images appearing when
   they shouldn't. */
[hidden] { display: none !important; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--ink);
  /* The gradient is the fallback sky: if WebGL, Three.js or globe.js
     is unavailable the canvas stays empty and this is what shows.
     When the globe IS running it paints over this. */
  background:
    radial-gradient(1200px 800px at 78% 8%, rgba(54, 122, 72, 0.32), transparent 62%),
    radial-gradient(900px 700px at 12% 82%, rgba(78, 128, 84, 0.22), transparent 60%),
    var(--space-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Replaces the flow space the header gave up when it became fixed.
     shared.js measures the real header and writes --header-h on <html>,
     re-measuring on resize and whenever the header itself changes height
     (it wraps to two rows on narrow screens, and the Admin button
     appearing can change that). The literals here are only the no-JS
     fallback: roughly a one-row header, and two rows on phones. */
  padding-top: var(--header-h, 64px);
}
@media (max-width: 640px) {
  body { padding-top: var(--header-h, 112px); }
}

/* ---------- 3D earth background (globe.js) ----------
   Fixed behind everything, never interactive. All page content is
   lifted onto its own stacking context above it. */
#globe-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  display: block;
  pointer-events: none;
  /* Fades in once globe.js has a first frame, so there's no flash of
     an unpainted black canvas over the gradient. */
  opacity: 0;
  transition: opacity 1.2s ease;
}
.globe-on #globe-canvas { opacity: 1; }

/* Only static, in-flow content needs lifting: a positioned element with
   z-index 0 (the canvas) paints above non-positioned block content, so
   <main> and <footer> would otherwise disappear behind the globe.

   Do NOT add the fixed overlays (.back-to-top, .cookie-bar,
   .modal-backdrop) to this list. `body > .thing` outranks `.thing`, so
   it overrode their own `position: fixed` with `relative` — which
   dropped the back-to-top into the flow after the footer (leaving a gap
   below it) and would have rendered the modals in-flow, behind the
   header, instead of as overlays. They are all already fixed with a
   z-index far above the canvas and need nothing from here.

   .site-header is likewise absent on purpose: it sets its own
   `position: fixed` and z-index, and a rule here would fight it. */
body > main,
body > footer { position: relative; z-index: 1; }
img { max-width: 100%; display: block; }
a { color: var(--ink); font-weight: 600; text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.12;
  margin: 0 0 0.5em;
  letter-spacing: -0.01em;
}
h1 { font-size: clamp(2.2rem, 5vw, 3.6rem); }
h2 { font-size: clamp(1.7rem, 3.4vw, 2.4rem); }
h3 { font-size: 1.2rem; }

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--moss);
  margin: 0 0 1rem;
}

/* Mode visibility — the whole switch mechanic in two rules */
body[data-mode="b2b"] [data-only="b2c"] { display: none !important; }
body[data-mode="b2c"] [data-only="b2b"] { display: none !important; }

/* Content cross-fade on mode change (added/removed by JS) */
main { transition: opacity 0.18s ease; }
main.is-switching { opacity: 0; }

/* Keyboard focus */
:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 0.72rem 1.4rem;
  border-radius: 999px;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: transform 0.12s ease, background 0.15s ease, color 0.15s ease;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }
.btn-primary { background: var(--accent); color: var(--ink-invert); }
.btn-primary:hover { background: var(--sage-accent-bright); }
.btn-ghost { background: rgba(160, 214, 140, 0.06); color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { border-color: var(--accent); background: rgba(160, 214, 140, 0.12); }
.btn-outline { background: rgba(160, 214, 140, 0.06); color: var(--ink); border-color: var(--line); }
.btn-outline:hover { border-color: var(--accent); color: var(--ink); background: rgba(160, 214, 140, 0.12); }
.btn-wide { width: 100%; }

/* ---------- Header ----------
   Fixed, not sticky. Sticky already pins to the top, but it stays part
   of the normal flow, which leaves it exposed to anything that shifts
   that flow — a wrapped row changing height mid-scroll, the mobile
   browser's own toolbar collapsing and moving the visual viewport under
   it. Fixed takes it out of the flow entirely, so it is pinned to the
   viewport and cannot be partly scrolled off under any of those.

   The cost is that it no longer reserves its own space, so <body> has
   to reserve it instead — see the --header-h rule below. */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1200;
  /* Solid, not translucent+blurred. A backdrop-filter here would make
     the browser re-blur a full-width strip of an animating WebGL canvas
     on every single frame — it was one of the main causes of scroll
     jank. The globe shows through the hero above it instead. */
  background: #0a1c12;
  border-bottom: 1px solid var(--line);
}
.header-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0.7rem 1.25rem;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 0.55rem; color: var(--ink); }
.brand:hover { text-decoration: none; }
.brand-mark {
  width: 26px; height: 26px;
  border-radius: 50% 50% 50% 4px;   /* leaf-shaped dot */
  background: linear-gradient(135deg, var(--leaf), var(--pine));
}
.brand-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: 0.01em;
}

/* The B2B/B2C switch */
.mode-switch {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr; /* equal halves — the thumb is 50%, so they always align */
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px;
  margin-inline: auto;
}
.mode-btn {
  position: relative;
  z-index: 2;
  border: 0;
  background: transparent;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.88rem;
  padding: 0.45rem 1.2rem;
  border-radius: 999px;
  color: var(--moss);
  cursor: pointer;
  text-align: center;
  white-space: nowrap;
  transition: color 0.2s ease;
}
.mode-btn[aria-selected="true"] { color: var(--ink-invert); }
.mode-thumb {
  position: absolute;
  z-index: 1;
  top: 4px; bottom: 4px; left: 4px;
  width: calc(50% - 4px);
  background: var(--accent);
  border-radius: 999px;
  transition: transform 0.25s cubic-bezier(0.35, 0, 0.2, 1), background 0.25s ease;
}
body[data-mode="b2c"] .mode-thumb { transform: translateX(100%); }

.header-nav { display: flex; align-items: center; gap: 1.1rem; }
.header-nav > a { color: var(--ink); font-weight: 500; font-size: 0.92rem; }
.header-nav > a:hover { text-decoration: none; }
/* .header-nav > a above is more specific than .btn-primary alone (an
   extra element selector beats the class-only rule), so it was
   silently overriding the Admin link's text color with --ink — cream
   text on the cream .btn-primary fill, unreadable. Restore the
   inverted color for any filled button that lives in the nav. */
.header-nav > a.btn-primary { color: var(--ink-invert); }

/* ---------- Account dropdown ----------
   Anchored to the account button. Signed out the button opens the auth
   modal; signed in it toggles this menu, so reaching the dashboard is a
   deliberate second click rather than something that happens by
   accident. [hidden] wins over display:grid via the global rule. */
/* ---------- Language switch ----------
   Same pill shell as the B2B/B2C switch so they read as a family, but
   smaller and with circular flags instead of labels. The inactive flag
   is desaturated and dimmed rather than hidden, so it's obvious it can
   be clicked. */
.lang-switch {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: 999px;
  flex-shrink: 0;
  position: relative;
  /* Extra breathing room on top of the nav's own gap, so this reads as
     its own group rather than crowding whatever sits right before it
     (Sign out / Account). */
  margin-left: 0.5rem;
}
/* Thin divider to the left, echoing the one already used between
   header-nav links, so the language switch reads as a separate
   control rather than another nav item. */
.header-nav > .lang-switch::before {
  content: "";
  position: absolute;
  left: -0.75rem;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 1.2rem;
  background: var(--line);
}
.lang-btn {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  cursor: pointer;
  line-height: 0;
  opacity: 0.42;
  filter: saturate(0.35);
  transition: opacity 0.18s ease, filter 0.18s ease, transform 0.15s ease;
}
.lang-btn:hover { opacity: 0.8; filter: saturate(0.8); }
.lang-btn[aria-pressed="true"] {
  opacity: 1;
  filter: none;
  box-shadow: 0 0 0 2px var(--accent);
}
.lang-btn:active { transform: scale(0.92); }
.lang-btn .flag {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: block;
}
/* The white band of the Bulgarian flag would vanish into a light
   surface; a hairline keeps the disc readable on any background. */
.lang-btn .flag circle,
.lang-btn .flag { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25); }

@media (max-width: 640px) {
  .lang-btn { width: 24px; height: 24px; }
  .lang-btn .flag { width: 18px; height: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .lang-btn { transition: none; }
}

.account-menu { position: relative; }

#account-btn[aria-haspopup="menu"]::after {
  content: "";
  display: inline-block;
  width: 0.4em;
  height: 0.4em;
  margin-left: 0.5em;
  vertical-align: 0.12em;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translate(-0.06em, -0.06em);
  transition: transform 0.18s ease;
}
#account-btn[aria-expanded="true"]::after {
  transform: rotate(-135deg) translate(-0.12em, -0.12em);
}

.account-dropdown {
  position: absolute;
  top: calc(100% + 0.55rem);
  right: 0;
  z-index: 1300;
  min-width: 11.5rem;
  display: grid;
  gap: 0.15rem;
  padding: 0.4rem;
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6);
  animation: account-menu-in 0.16s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes account-menu-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

.account-menu-item {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0.55rem 0.7rem;
  border: 0;
  border-radius: 8px;
  background: none;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.account-menu-item:hover {
  background: rgba(160, 214, 140, 0.10);
  text-decoration: none;
}
/* The phone-only Admin mirror. Hidden at every width except the
   narrow header, where the standalone Admin button is swapped out
   for it — see the PHONES block at the end of this file. */
.account-menu-admin { display: none; }

.account-menu-signout { color: #ff9b8a; }
.account-menu-signout:hover { background: rgba(255, 155, 138, 0.12); }

/* ---------- Section menu (hamburger) ----------
   Reuses the account dropdown's shell so the two menus in the header
   look and behave like one component. The bars morph into an X while
   the menu is open, which is the only state indicator the button has
   besides aria-expanded. */
.nav-menu { position: relative; flex-shrink: 0; margin-left: 0.25rem; }
.nav-menu-btn {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--mist);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.nav-menu-btn:hover { border-color: var(--accent); background: rgba(160, 214, 140, 0.14); }
.nav-menu-bars {
  display: grid;
  gap: 4px;
  width: 18px;
}
.nav-menu-bars > span {
  display: block;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.22s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.14s ease;
}
/* Open state: top and bottom bars rotate into a cross, middle fades.
   translateY matches the 6px pitch (2px bar + 4px gap). */
.nav-menu-btn[aria-expanded="true"] .nav-menu-bars > span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-menu-btn[aria-expanded="true"] .nav-menu-bars > span:nth-child(2) { opacity: 0; }
.nav-menu-btn[aria-expanded="true"] .nav-menu-bars > span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.nav-menu-dropdown {
  position: absolute;
  top: calc(100% + 0.55rem);
  right: 0;
  z-index: 1300;
  min-width: 11.5rem;
  display: grid;
  gap: 0.15rem;
  padding: 0.4rem;
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 18px 44px rgba(3, 10, 6, 0.6);
  animation: account-menu-in 0.16s cubic-bezier(0.16, 1, 0.3, 1);
}
.nav-menu-item {
  display: block;
  padding: 0.55rem 0.7rem;
  border-radius: 8px;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ink);
}
.nav-menu-item:hover {
  background: rgba(160, 214, 140, 0.12);
  color: var(--leaf);
  text-decoration: none;
}
/* The nav's own underline-on-hover rule targets direct children of
   .header-nav; these links are nested, so they need nothing to opt out. */

@media (prefers-reduced-motion: reduce) {
  .nav-menu-dropdown { animation: none; }
  .nav-menu-bars > span { transition: none; }
}

@media (max-width: 640px) {
  .account-dropdown { min-width: 10rem; }
}

@media (prefers-reduced-motion: reduce) {
  .account-dropdown { animation: none; }
  #account-btn::after { transition: none; }
}

/* ---------- Hero ----------
   Deliberately transparent: this is where the globe is at its
   furthest and the starfield is fully visible, so nothing sits
   between the visitor and it except the text itself. The text gets
   its own local scrim instead of a full-width panel. */
.hero {
  position: relative;
  background: transparent;
  border-bottom: 0;
  min-height: 88vh;
  display: flex;
  align-items: center;
}

/* ---------- Hero foliage ----------
   Two SVG leaf clusters in the top-right and bottom-left corners.
   Kept strictly decorative: absolutely positioned, never interactive,
   and clipped by the hero so a leaf can't spill over the impact strip.
   contain: paint stops the browser repainting the rest of the hero
   when the globe animates behind it. */
.hero-foliage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  contain: paint;
}
.hero-foliage-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.hero-foliage-svg {
  position: absolute;
  width: clamp(240px, 36vw, 560px);
  height: auto;
  /* Softens the edges into the sky so the cluster reads as depth of
     field rather than a sticker pasted on the corner. */
  filter: drop-shadow(0 8px 26px rgba(3, 10, 6, 0.7));
}
.hero-foliage-tr { top: 0; right: 0; }
.hero-foliage-bl { bottom: 0; left: 0; }

/* Everything in .hero-inner must sit above the leaves. */
.hero-inner { position: relative; z-index: 1; }

@media (max-width: 640px) {
  /* One cluster only on a phone — two would crowd the headline. */
  .hero-foliage-bl { display: none; }
  .hero-foliage-svg { width: clamp(190px, 52vw, 300px); opacity: 0.72; }
}
.hero-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 5.5rem 1.25rem 4.5rem;
  width: 100%;
}
.hero h1 {
  max-width: 17ch;
  text-shadow: 0 2px 30px rgba(3, 10, 6, 0.9), 0 1px 3px rgba(3, 10, 6, 0.8);
}
.hero-lead {
  max-width: 56ch;
  font-size: 1.08rem;
  color: #c2d2c2;
  text-shadow: 0 1px 16px rgba(3, 10, 6, 0.95);
}
.hero .eyebrow { text-shadow: 0 1px 12px rgba(3, 10, 6, 0.9); }
.hero-actions { display: flex; gap: 0.8rem; flex-wrap: wrap; margin-top: 1.6rem; }

/* ---------- Impact strip ---------- */
.impact {
  background:
    linear-gradient(180deg, rgba(160, 214, 140, 0.09), rgba(160, 214, 140, 0.02)),
    #0b1c12;
  color: var(--ink);
  border-block: 1px solid var(--line);
}
.impact-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 2.2rem 1.25rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
}
.impact-num {
  display: block;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 700;
  color: var(--pine);
}
.impact-label { font-size: 0.88rem; color: var(--moss); }

/* ---------- Sections ----------
   Text-heavy sections get a translucent scrim so copy stays readable
   over the earth; the map section deliberately doesn't, because
   that's where the globe has flown in and should be seen. */
.section {
  padding: 4.5rem 0;
  /* Opaque base. Non-landing pages keep this; the landing page
     overrides it with glass in the GLASS THEME block at the end of
     this file, paired with globe.js rendering at half resolution
     behind the blur. */
  background: #0a1c12;
  border-block: 1px solid rgba(160, 214, 140, 0.08);
}
.section-tinted { background: #0d2115; border-block: 1px solid var(--line); }
.section-inner { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem; }
.section-lead { max-width: 58ch; color: var(--moss); }

/* The About section is the one deliberate exception to the opaque rule.
   Fully solid sections back to back made the middle of the page feel
   stiff, so this one lets the earth through as a soft shape behind the
   copy. The trick to keeping it readable is doing the darkening inside
   the filter — brightness() crushes the planet's highlights (ice and
   cloud tops are the bright bits that would otherwise wash out text)
   before the overlay goes on, rather than relying on opacity alone.
   Measured worst case (a pure-white polar-ice pixel sitting directly
   behind a paragraph, before the blur averages it down): 6.0:1 for
   body text, 12.7:1 for headings. Comfortably past WCAG AA, so the
   earth can be left brighter than a first guess would allow.

   globe.js knows about this section: it keeps rendering while #about is
   on screen, but at half resolution, which nobody can tell through a
   40px blur. */
#about.section-tinted {
  background: rgba(10, 28, 18, 0.70);
  backdrop-filter: blur(40px) brightness(0.45) saturate(1.7);
  -webkit-backdrop-filter: blur(40px) brightness(0.45) saturate(1.7);
}
/* No backdrop-filter support: stay opaque rather than unreadable. */
@supports not (backdrop-filter: blur(1px)) {
  #about.section-tinted { background: #0d2115; }
}

/* ---------- About carousel ----------
   Three cards, one on screen at a time, with a labelled arrow on each
   side naming the card it leads to. Two things make this safe to ship:

   1. Everything that collapses the three cards into one stage is gated
      behind .js-ready. Without JS the cards simply stack down the page
      in normal flow and the arrows and dots never appear — the same
      no-JS contract .reveal already uses.
   2. The cards are stacked absolutely and the stage's height is set in
      pixels by app.js from whichever card is showing. Sizing the stage
      to the tallest card instead would have left the short first card
      as a mostly-empty box; letting it size naturally would snap the
      page. An explicit height transitions, so the card grows or
      shrinks into place. */
.about-carousel {
  margin-top: 2rem;
  display: grid;
  gap: 1.25rem;
}
.about-nav,
.about-dots { display: none; }

.js-ready .about-carousel {
  grid-template-columns: minmax(8rem, 11rem) minmax(0, 1fr) minmax(8rem, 11rem);
  align-items: center;
  column-gap: 1.75rem;
  row-gap: 1.75rem;
}
.js-ready .about-stage {
  position: relative;
  transition: height 0.38s cubic-bezier(0.16, 1, 0.3, 1);
}
.js-ready .about-card {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

.about-card {
  background: rgba(19, 41, 26, 0.55);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2.25rem 2.5rem;
  text-align: center;
  /* The card is the only thing in the stage that repaints on a switch. */
  contain: layout paint;
}
.about-card h3 {
  font-size: clamp(1.3rem, 2.4vw, 1.7rem);
  color: var(--pine);
  margin-bottom: 0.8rem;
}
/* Centred text still needs a measure — a 90-character line is hard to
   track back from at any alignment. margin-inline centres the column
   itself now that it no longer starts at the card's left edge. */
.about-card p {
  color: var(--moss);
  max-width: 62ch;
  margin: 0 auto;
}

/* Only the incoming card animates; the outgoing one is simply dropped.
   Re-adding .is-active restarts the animation, which is why this needs
   no JS beyond the class toggle. */
.js-ready .about-card:not(.is-active) {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.js-ready .about-card.is-active { animation: about-card-in 0.38s cubic-bezier(0.16, 1, 0.3, 1); }
.js-ready .about-stage[data-dir="prev"] .about-card.is-active { animation-name: about-card-in-rev; }
@keyframes about-card-in {
  from { opacity: 0; transform: translateX(26px); }
  to { opacity: 1; transform: none; }
}
@keyframes about-card-in-rev {
  from { opacity: 0; transform: translateX(-26px); }
  to { opacity: 1; transform: none; }
}

.js-ready .about-nav {
  display: grid;
  justify-items: center;
  gap: 0.7rem;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--moss);
  cursor: pointer;
  text-align: center;
}
.about-nav-arrow {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--mist);
  color: var(--ink);
  font-size: 1.15rem;
  line-height: 1;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
.about-nav:hover .about-nav-arrow {
  border-color: var(--accent);
  background: rgba(160, 214, 140, 0.14);
  color: var(--leaf);
}
.about-nav-prev:hover .about-nav-arrow { transform: translateX(-2px); }
.about-nav-next:hover .about-nav-arrow { transform: translateX(2px); }
.about-nav:active .about-nav-arrow { transform: scale(0.94); }
/* Body font, sentence case. These labels are whole section titles —
   "Why paid work, not volunteering" set in uppercase mono like the rest
   of the site's micro-labels ran to four dense lines and read as noise
   rather than as a destination. */
.about-nav-label {
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.35;
  transition: color 0.15s ease;
}
.about-nav:hover .about-nav-label { color: var(--leaf); }
.about-nav:focus-visible { outline: none; }
.about-nav:focus-visible .about-nav-arrow {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

.js-ready .about-dots {
  display: flex;
  grid-column: 1 / -1;
  justify-content: center;
  gap: 0.45rem;
}
.about-dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(160, 214, 140, 0.28);
  cursor: pointer;
  transition: width 0.22s ease, background 0.15s ease;
}
.about-dot:hover { background: rgba(160, 214, 140, 0.5); }
.about-dot[aria-current="true"] { width: 24px; background: var(--accent); }

@media (max-width: 860px) {
  /* Card spans the full width; the two arrows sit under it side by side
     so the labels keep their room instead of being squeezed into
     margins that no longer exist.

     Every item is placed explicitly. The source order is prev → stage →
     next, so with auto-placement the full-width stage couldn't fit
     beside prev and got pushed to its own row *below* it — leaving the
     back arrow stranded above the card and the forward arrow below it.
     Naming rows and columns is what keeps the visual order (card, then
     the two arrows, then the dots) independent of the DOM order that
     the desktop three-column layout needs. */
  .js-ready .about-carousel {
    grid-template-columns: 1fr 1fr;
    column-gap: 1rem;
    row-gap: 1.25rem;
  }
  .js-ready .about-stage    { grid-column: 1 / -1; grid-row: 1; }
  .js-ready .about-nav-prev { grid-column: 1;      grid-row: 2; }
  .js-ready .about-nav-next { grid-column: 2;      grid-row: 2; }
  .js-ready .about-dots     { grid-column: 1 / -1; grid-row: 3; }
  /* Arrows point outward from the card they sit under. */
  .js-ready .about-nav-prev { justify-self: start; }
  .js-ready .about-nav-next { justify-self: end; }
  .js-ready .about-nav { max-width: 100%; }
  .about-nav-label { max-width: 15ch; }
  .about-card { padding: 1.75rem 1.5rem; }
}
@media (max-width: 560px) {
  .about-nav-arrow { width: 42px; height: 42px; }
  .about-nav-label { font-size: 0.78rem; }
}

@media (prefers-reduced-motion: reduce) {
  /* The card still swaps and the stage still resizes to fit it — both
     just happen instantly instead of animating. */
  .js-ready .about-card.is-active { animation: none !important; }
  .js-ready .about-stage { transition: none !important; }
  .about-nav-arrow { transition: none; }
  .about-nav:hover .about-nav-arrow,
  .about-nav:active .about-nav-arrow { transform: none; }
}

/* The map section is the destination of the globe's flight — let it
   show through around the map panel instead of covering it up. */
#map.section {
  background:
    linear-gradient(180deg, #0a1c12 0%, rgba(10, 28, 18, 0.30) 26%,
                            rgba(10, 28, 18, 0.30) 74%, #0a1c12 100%);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.25rem;
  margin-top: 2rem;
}
.card {
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  contain: layout paint;
  transition: border-color 0.15s ease, transform 0.15s ease, background 0.15s ease;
}
.card:hover { border-color: var(--leaf); transform: translateY(-2px); background: #17331f; }
.card p { margin-bottom: 0; color: var(--moss); font-size: 0.95rem; }

.steps {
  list-style: none;
  counter-reset: step;
  padding: 0;
  margin: 2rem 0 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.25rem;
}
.step { counter-increment: step; position: relative; padding-top: 2.4rem; }
.step::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  top: 0; left: 0;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--pine);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.15rem 0.6rem;
  background: var(--space-2);
}
.step p { color: var(--moss); font-size: 0.95rem; }

/* ---------- Heatmap placeholder ----------
   Sits directly in front of the globe once it has flown in over
   Bulgaria, so it carries a ring of light to separate the two. */
.heatmap {
  position: relative;
  margin-top: 2rem;
  height: 420px;
  border-radius: var(--radius);
  border: 1px solid rgba(160, 214, 140, 0.35);
  overflow: hidden;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(3, 10, 6, 0.6);
  background:
    radial-gradient(circle, rgba(160, 214, 140, 0.16) 1.2px, transparent 1.6px) 0 0 / 22px 22px,
    linear-gradient(180deg, #0d2014, #122b1a);
}
.heatmap-badge {
  position: absolute;
  top: 12px; left: 12px;
  z-index: 3;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--ink);
  background: rgba(11, 26, 16, 0.88);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.3rem 0.6rem;
}
.hm-marker {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 2;
}
.hm-dot {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--leaf);
  box-shadow: 0 0 0 6px rgba(211, 232, 176, 0.45);
  animation: pulse 2.4s ease-out infinite;
}
.hm-marker[data-intensity="high"] .hm-dot { background: var(--pine); box-shadow: 0 0 0 9px rgba(160, 214, 140, 0.40); }
.hm-label {
  position: absolute;
  top: 100%; left: 50%;
  transform: translateX(-50%);
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--ink);
  background: rgba(11, 26, 16, 0.85);
  border-radius: 4px;
  padding: 0 0.35rem;
  white-space: nowrap;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(160, 214, 140, 0.35); }
  70%  { box-shadow: 0 0 0 16px rgba(160, 214, 140, 0); }
  100% { box-shadow: 0 0 0 0 rgba(160, 214, 140, 0); }
}
.heatmap-legend {
  list-style: none;
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding: 0;
  margin: 1rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--moss);
}
.heatmap-legend .swatch {
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 50%;
  margin-right: 0.4rem;
}

/* ---------- Action split & forms ---------- */
.section-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3rem;
  align-items: start;
}
.panel-form {
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
}
.panel-form h3 { margin-bottom: 1.2rem; }
.panel-form label {
  display: block;
  font-weight: 600;
  font-size: 0.88rem;
  margin: 1rem 0 0.35rem;
}
.panel-form input,
.panel-form select,
.panel-form textarea,
#auth-form input {
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: #0a1c12;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  padding: 0.65rem 0.8rem;
}
/* Native pickers (date, select) render their own chrome — force the
   dark scheme so they don't come back white on a dark form. */
.panel-form input,
.panel-form select,
.panel-form textarea,
#auth-form input { color-scheme: dark; }
.panel-form input::placeholder,
.panel-form textarea::placeholder { color: #7f9683; }
.panel-form input:focus,
.panel-form select:focus,
.panel-form textarea:focus,
#auth-form input:focus {
  outline: none;
  border-color: var(--leaf);
  background: #0c2114;
}
.panel-form .btn { margin-top: 1.4rem; }
.optional { font-weight: 400; color: var(--moss); }
.field-hint { font-size: 0.8rem; color: var(--moss); margin: 0.3rem 0 0; }

/* Honeypot — visually removed, still in the DOM for bots */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px;
  opacity: 0;
}

.form-status { min-height: 1.2em; font-size: 0.88rem; margin: 0.8rem 0 0; }
.form-status.ok { color: var(--pine); font-weight: 600; }
.form-status.err { color: #ff9b8a; font-weight: 600; }

/* ---------- Footer ---------- */
.site-footer {
  background: #05120a;
  color: var(--ink);
  margin-top: 0;
  border-top: 1px solid var(--line);
}
.footer-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  /* The brand block gets the room it needs and no more; the two link
     columns are a fixed width so they sit next to each other on the
     right instead of drifting apart across a 2fr gap. */
  padding: 3.5rem 1.25rem 2.25rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  column-gap: 4rem;
  row-gap: 2.5rem;
  align-items: start;
}

.footer-brand { max-width: 34ch; }
.footer-brand .brand { margin-bottom: 0.9rem; }
.footer-tag { font-size: 0.92rem; color: var(--moss); margin: 0 0 0.6rem; }
.footer-place {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--moss);
  margin: 0;
}

/* Both link columns share one layout so their baselines line up. */
.footer-col {
  display: grid;
  gap: 0.65rem;
  justify-items: start;
  min-width: 8.5rem;
}
.footer-heading {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--moss);
  margin: 0 0 0.15rem;
}
.footer-col a,
.footer-col .footer-legal-btn {
  color: var(--ink);
  font-size: 0.92rem;
  font-weight: 500;
  line-height: 1.3;
  white-space: nowrap;
}

/* Bottom bar — the copyright and strapline used to be jammed into the
   right-hand column, which is what made the legal links wrap raggedly. */
.footer-bar {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 1.25rem 1.25rem 2.25rem;
  border-top: 1px solid rgba(160, 214, 140, 0.10);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 2rem;
  justify-content: space-between;
  align-items: baseline;
}
.footer-legal { font-size: 0.8rem; color: var(--moss); margin: 0; }

/* ---------- Account modal ---------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(3, 10, 6, 0.88);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
/* The hidden attribute must always win, even over display:flex above */
.modal-backdrop[hidden] { display: none; }
/* Lock page scroll only while the modal is open (class set by JS) */
body.modal-open { overflow: hidden; }
.modal {
  position: relative;
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem;
  width: min(420px, 100%);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.7);
}
.modal-close {
  position: absolute;
  top: 0.8rem; right: 0.9rem;
  border: 0;
  background: transparent;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--moss);
  cursor: pointer;
}
.auth-tabs {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}
.auth-tab {
  flex: 1;
  border: 1px solid var(--line);
  background: rgba(160, 214, 140, 0.06);
  border-radius: 999px;
  padding: 0.5rem;
  font: inherit;
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--moss);
  cursor: pointer;
}
.auth-tab.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--ink-invert);
}
#auth-form label {
  display: block;
  font-weight: 600;
  font-size: 0.88rem;
  margin: 1rem 0 0.35rem;
}
.role-choice {
  border: 0;
  padding: 0;
  margin: 0.4rem 0 0;
}
.role-choice legend {
  font-weight: 600;
  font-size: 0.88rem;
  padding: 0;
  margin-bottom: 0.4rem;
}
.role-options { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
.role-option { position: relative; display: block; cursor: pointer; margin: 0; }
.role-option input {
  position: absolute;
  opacity: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}
.role-option span {
  display: block;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  padding: 0.6rem 0.7rem;
  font-weight: 600;
  font-size: 0.88rem;
  text-align: center;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.role-option small {
  display: block;
  font-weight: 400;
  font-size: 0.72rem;
  color: var(--moss);
  margin-top: 0.15rem;
}
.role-option input:checked + span {
  border-color: var(--accent);
  background: var(--mist);
}
.role-option input:focus-visible + span {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}
#auth-form .btn { margin-top: 1.4rem; }
.auth-divider {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin: 1.2rem 0;
  color: var(--moss);
  font-size: 0.8rem;
}
.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--line);
}
.btn-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  background: rgba(160, 214, 140, 0.07);
  color: var(--ink);
  border-color: var(--line);
}
.btn-google:hover { border-color: var(--accent); }

.auth-note { font-size: 0.8rem; color: var(--moss); margin-top: 1.2rem; }
.auth-note code { font-family: var(--font-mono); font-size: 0.78rem; }

/* ---------- Profile page ---------- */
.profile-page {
  max-width: 880px;
  margin: 0 auto;
  padding: 3rem 1.25rem 4rem;
}
.profile-state { text-align: center; padding: 4rem 0; }
.profile-state .btn { margin-top: 1rem; }
.profile-state .section-lead { margin-inline: auto; }
.profile-header-nav a { display: inline !important; } /* keep visible on mobile */
/* Only the "← Back to…" link is anchored next to the logo — everything
   else (Team admin, Sign out, language switch) is a right-aligned
   utility cluster. The nav stretches to fill the header, and auto
   margin on the back-link pushes the rest to the far right edge,
   regardless of which of those items happen to be [hidden]. */
.profile-header-nav { flex: 1; }
.profile-header-nav > a:first-child { margin-right: auto; }

.profile-heading { margin-bottom: 2rem; }
.profile-heading h1 { font-size: clamp(1.9rem, 4vw, 2.6rem); margin-bottom: 0; }

.profile-grid {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 1.5rem;
  align-items: start;
}
.profile-card {
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem;
}
.profile-card h2 { font-size: 1.25rem; }
.profile-identity { text-align: center; }

.avatar-wrap {
  width: 128px; height: 128px;
  margin: 0 auto 1rem;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid var(--space-2);
  box-shadow: 0 0 0 2px var(--line);
  background: var(--space-2);
  display: flex;
  align-items: center;
  justify-content: center;
}
.avatar-wrap img { width: 100%; height: 100%; object-fit: cover; }
.avatar-fallback {
  font-family: var(--font-display);
  font-size: 3rem;
  font-weight: 700;
  color: var(--pine);
}
.profile-email {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--moss);
  margin: 0 0 0.6rem;
  word-break: break-all;
}
.role-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  margin-bottom: 1.2rem;
  background: var(--pine);
  color: var(--ink-invert);
}
.role-badge[data-role="worker"] { background: var(--accent); color: var(--ink-invert); }
.role-badge:empty { display: none; }
.avatar-upload-label { display: inline-block; cursor: pointer; }

.profile-card form label {
  display: block;
  font-weight: 600;
  font-size: 0.88rem;
  margin: 1rem 0 0.35rem;
}
.profile-card form input,
.profile-card form textarea {
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: #0a1c12;
  color-scheme: dark;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  padding: 0.65rem 0.8rem;
}
.profile-card form input:focus,
.profile-card form textarea:focus {
  outline: none;
  border-color: var(--leaf);
}
.profile-card form .btn { margin-top: 1.2rem; }
.profile-divider {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 2rem 0;
}

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

/* When Leaflet takes over the heatmap panel, drop the dot-grid bg */
.heatmap-live { background: #0b1c11; }
.heatmap-live .heatmap-badge { z-index: 1000; }

/* OpenStreetMap only ships a light tile set. Rather than swap tile
   providers, invert the tile pane so the map sits in the dark theme
   without glaring against the globe behind it. The filter is scoped
   to the tiles only, so markers, popups and controls keep their own
   colors. */
.leaflet-tile-pane {
  filter: invert(1) hue-rotate(185deg) brightness(0.85);
}
.leaflet-container { background: #0b1c11 !important; }
.leaflet-control-attribution {
  background: rgba(11, 26, 16, 0.85) !important;
  color: #a0bda4 !important;
}
.leaflet-control-attribution a { color: #bcd6a4 !important; }
.leaflet-bar a {
  background: #13291a !important;
  color: #e7f0e4 !important;
  border-bottom-color: rgba(160, 214, 140, 0.2) !important;
}
.leaflet-bar a:hover { background: #1a3a24 !important; }
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
  background: #13291a !important;
  color: #e7f0e4 !important;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6) !important;
}

/* CRITICAL: Leaflet uses internal z-indexes up to ~1000. Isolating
   each map's stacking context traps those values inside the panel,
   so maps can never float above the header, modal, or anything else. */
.heatmap, .event-map, .admin-map {
  position: relative;
  isolation: isolate;
  z-index: 0;
  contain: layout paint;
}
.hm-popup { font-family: var(--font-body); }
.hm-popup strong { display: block; margin-bottom: 0.2rem; }
.hm-popup-status {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--moss);
  margin-bottom: 0.3rem;
}
.hm-popup a { font-weight: 600; }

/* ---------- Event page ---------- */
.event-page {
  max-width: 760px;
  margin: 0 auto;
  padding: 3rem 1.25rem 4rem;
}
.event-meta { display: flex; gap: 0.6rem; flex-wrap: wrap; margin: 1rem 0 1.5rem; }
.event-chip {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  background: var(--pine);
  color: var(--ink-invert);
}
.event-chip-quiet { background: var(--mist); color: var(--ink); border: 1px solid var(--line); }
.event-description {
  font-size: 1.05rem;
  color: var(--moss);
  max-width: 60ch;
  margin-bottom: 2rem;
  white-space: pre-line; /* respects paragraph breaks the team types */
}
.event-map {
  height: 320px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  overflow: hidden;
  margin-top: 1.5rem;
  background: #0b1c11;
}
.event-cta {
  margin-top: 2.5rem;
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem;
}
.event-cta h2 { font-size: 1.35rem; }
.event-cta .btn { margin-top: 0.6rem; }

/* ---------- Admin panel ---------- */
.admin-howto {
  background: var(--mist);
  border: 1px solid var(--line);
  border-left: 4px solid var(--leaf);
  border-radius: 10px;
  padding: 1.2rem 1.5rem;
  margin-bottom: 1.5rem;
  font-size: 0.92rem;
}
.admin-howto ol { margin: 0.5rem 0; padding-left: 1.3rem; }
.admin-howto li { margin: 0.25rem 0; }
.admin-howto p { margin: 0.5rem 0 0; color: var(--moss); }
.place-search-row { display: flex; gap: 0.5rem; }
.place-search-row input { flex: 1; }
.place-search-row .btn { flex-shrink: 0; }

.admin-page {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 3rem 1.25rem 4rem;
}
.admin-grid {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 1.5rem;
  align-items: start;
}
.admin-map {
  height: 300px;
  border-radius: 10px;
  border: 1.5px solid var(--line);
  overflow: hidden;
  margin-top: 0.35rem;
  background: #0b1c11;
  cursor: crosshair;
}
.coords-readout {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--ink);
  margin: 0.5rem 0 0;
}
.coords-label { color: var(--moss); }
.check-row {
  display: flex !important;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.2rem !important;
  cursor: pointer;
}
.check-row input {
  width: auto !important;
  accent-color: var(--pine);
  transform: scale(1.2);
}
.admin-form-actions { display: flex; gap: 0.6rem; align-items: center; }
.btn-small { padding: 0.35rem 0.85rem; font-size: 0.82rem; }
.btn-danger { color: #ff9b8a; }
.btn-danger:hover { border-color: #ff9b8a; color: #ff9b8a; }

/* ---------- Admin dashboard: KPI cards + recent activity ---------- */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin-bottom: 1rem;
}
.dash-card {
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem 1.4rem;
  transition: border-color 0.15s ease, transform 0.2s ease;
}
.dash-card:hover { border-color: var(--leaf); transform: translateY(-2px); }
.dash-num {
  display: block;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 700;
  color: var(--pine);
}
.dash-label { font-size: 0.82rem; color: var(--moss); }

.activity-list { list-style: none; padding: 0; margin: 1rem 0 0; }
.activity-item {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line);
}
.activity-item.is-handled { opacity: 0.5; }
.activity-badge { flex-shrink: 0; }
.activity-info { flex: 1; display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }

@media (max-width: 720px) {
  .dash-grid { grid-template-columns: repeat(2, 1fr); }
  .activity-item { flex-wrap: wrap; }
}

.event-list { list-style: none; padding: 0; margin: 1rem 0 0; }
.event-list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line);
}
.event-list-item.is-inactive { opacity: 0.55; }
.event-list-meta {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--moss);
  margin-top: 0.15rem;
}
.event-list-actions { display: flex; gap: 0.4rem; flex-shrink: 0; }
.event-list-empty { color: var(--moss); padding: 1rem 0; }

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

/* ---------- Admin panel: mobile optimization ---------- */
@media (max-width: 640px) {
  .admin-page { padding: 1.6rem 0.9rem 3rem; }
  .admin-howto { padding: 1rem 1.1rem; font-size: 0.88rem; }
  .admin-page .profile-card { padding: 1.3rem; }
  .admin-map { height: 260px; }

  /* Event rows stack: name on top, action buttons in a row below */
  .event-list-item {
    flex-direction: column;
    align-items: stretch;
    gap: 0.7rem;
  }
  .event-list-actions {
    width: 100%;
    flex-wrap: wrap;
  }
  .event-list-actions .btn {
    flex: 1 1 calc(50% - 0.4rem);
    text-align: center;
  }

  /* Finger-sized touch targets */
  .btn-small { padding: 0.55rem 0.9rem; font-size: 0.88rem; }
  .admin-form-actions { flex-wrap: wrap; }
  .admin-form-actions .btn { flex: 1 1 auto; text-align: center; }
  .place-search-row .btn { padding-inline: 1rem; }
  .coords-readout { font-size: 0.78rem; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ---------- Responsive ---------- */
@media (max-width: 900px) {
  .section-split, .card-grid { grid-template-columns: 1fr; }
  .steps { grid-template-columns: repeat(2, 1fr); }
  .impact-inner { grid-template-columns: 1fr; gap: 1.2rem; }
  .footer-inner { grid-template-columns: 1fr 1fr; column-gap: 2rem; }
  .footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  .header-inner { justify-content: space-between; }
  .mode-switch { order: 3; width: 100%; }
  /* Direct children only — the account dropdown is inside .header-nav
     and its links must stay visible. */
  .header-nav > a { display: none; }      /* keep only Account on tiny screens */
  .header-nav > a#admin-link:not([hidden]) { display: inline-block; } /* admins always see it */
  .steps { grid-template-columns: 1fr; }
  .heatmap { height: 340px; }
}

/* ---------- Cookie consent banner ---------- */
.cookie-bar {
  position: fixed;
  left: 1rem; right: 1rem; bottom: 1rem;
  z-index: 2500;
  max-width: 720px;
  margin: 0 auto;
  background: rgba(12, 30, 19, 0.96);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.1rem 1.3rem;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.7);
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
}
.cookie-bar p { margin: 0; font-size: 0.85rem; max-width: 46ch; color: var(--moss); }
.cookie-bar-actions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.cookie-bar-link { color: var(--pine); font-size: 0.82rem; font-weight: 600; }
.cookie-bar .btn-small { padding: 0.5rem 1rem; font-size: 0.82rem; }
.cookie-bar .btn-outline { border-color: rgba(231, 240, 228, 0.35); color: var(--ink); }
.cookie-bar .btn-outline:hover { border-color: var(--leaf); color: var(--leaf); }
@media (max-width: 560px) {
  .cookie-bar { flex-direction: column; align-items: stretch; }
  .cookie-bar-actions { justify-content: flex-end; }
}

/* ---------- FAQ accordion (details/summary, no JS needed) ---------- */
.faq-list { display: grid; gap: 0.75rem; margin-top: 2rem; }
.faq-item {
  background: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.3rem 1.25rem;
  /* Opening or hovering an item shouldn't force the browser to
     re-evaluate layout and paint for the whole FAQ list. */
  contain: layout paint;
}
.faq-item summary {
  cursor: pointer;
  list-style: none;
  padding: 1rem 0;
  font-weight: 600;
  font-size: 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+";
  font-family: var(--font-mono);
  font-size: 1.2rem;
  color: var(--pine);
  flex-shrink: 0;
  transition: transform 0.15s ease;
}
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p { margin: 0 0 1.1rem; color: var(--moss); }

/* ---------- Legal modal: draft notice banner ---------- */
.legal-draft-notice {
  background: rgba(201, 130, 42, 0.12);
  border: 1px solid rgba(201, 130, 42, 0.35);
  border-left: 4px solid #d9933b;
  border-radius: 10px;
  padding: 1rem 1.25rem;
  margin-bottom: 2rem;
  font-size: 0.9rem;
  color: #e8c493;
}
.legal-draft-notice strong { display: block; margin-bottom: 0.2rem; }
/* Only shown to Bulgarian readers — the drafts themselves stay English
   until a lawyer produces the BG versions. */
.legal-lang-note { display: none; margin-top: 0.5rem; font-style: italic; }
html[lang="bg"] .legal-lang-note { display: block; }

/* ---------- Pricing hint on B2B service cards ---------- */
.pricing-note {
  display: block;
  margin-top: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  color: var(--moss);
}


/* ---------- GDPR consent row + forgot password link ---------- */
.consent-row { font-size: 0.82rem; align-items: flex-start !important; }
.consent-row span a { font-weight: 600; }
.auth-forgot {
  display: inline-block;
  margin-top: 0.5rem;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 0.82rem;
  color: var(--ink);
  cursor: pointer;
}
.auth-forgot:hover { text-decoration: underline; }

/* ---------- Footer legal row ---------- */
.footer-legal-btn {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  text-align: left;
  color: var(--ink);
  cursor: pointer;
}
.footer-legal-btn:hover { text-decoration: underline; }

/* Inline text-link-styled buttons (used where legal content opens as a
   popup instead of navigating — keeps the <a>-like look with a <button>
   semantics so it doesn't behave like a real link). */
.inline-link-btn {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: inherit;
  font-weight: 600;
  color: var(--pine);
  cursor: pointer;
  text-decoration: none;
}
.inline-link-btn:hover { text-decoration: underline; }

/* ---------- Legal popup modal ---------- */
.modal-legal { width: min(680px, 100%); max-height: 82vh; overflow-y: auto; }
.legal-modal-body h3 { font-size: 1.1rem; margin-top: 1.6rem; margin-bottom: 0.4rem; }
.legal-modal-body p, .legal-modal-body li { color: var(--moss); font-size: 0.95rem; }
.legal-modal-body ul { padding-left: 1.2rem; }
.legal-modal-body code { font-family: var(--font-mono); font-size: 0.85em; }

/* ============================================================
   ANIMATIONS & INTERACTIONS
   The .js-ready gate matters: .reveal only starts hidden once
   shared.js has confirmed it's running and will actually reveal
   it. Without JS, .reveal content is fully visible by default —
   no permanently-invisible sections if a script fails to load.
   ============================================================ */

/* Anchored sections shouldn't land partly under the fixed header.
   Derived from the measured header rather than hardcoded per
   breakpoint, so the hamburger menu's jumps stay correct at any width
   and in either language. */
section[id] { scroll-margin-top: calc(var(--header-h, 84px) + 12px); }

/* ---------- Scroll reveal ---------- */
.js-ready .reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.6s ease, transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.js-ready .reveal.reveal-visible {
  opacity: 1;
  transform: none;
}
/* Staggered children inside a reveal group get a small delay ladder */
.js-ready .reveal-group > * { transition-delay: calc(var(--reveal-index, 0) * 70ms); }

/* ---------- Header: shadow + shrink on scroll ---------- */
.site-header {
  transition: box-shadow 0.25s ease, background 0.25s ease;
}
.site-header.is-scrolled {
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
  background: rgba(8, 23, 14, 0.9);
}

/* ---------- Nav underline hover ---------- */
.header-nav > a, .footer-nav a {
  position: relative;
}
.header-nav > a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: -3px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
  transition: right 0.2s ease;
}
.header-nav > a:hover::after { right: 0; }

/* ---------- Brand mark: gentle breathing pulse ---------- */
.js-ready .brand-mark {
  animation: brand-breathe 4.5s ease-in-out infinite;
}
@keyframes brand-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.08); }
}

/* ---------- Buttons: press feedback ---------- */
.btn:active { transform: translateY(0) scale(0.96); }
.mode-btn { transition: color 0.2s ease, transform 0.15s ease; }
.mode-btn:active { transform: scale(0.95); }

/* ---------- Cards: richer hover ---------- */
.card {
  transition: border-color 0.15s ease, transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.5);
}

/* ---------- FAQ items: hover lift ---------- */
.faq-item { transition: border-color 0.15s ease, transform 0.15s ease; }
.faq-item:hover { border-color: var(--leaf); }

/* ---------- Modal: pop-in on open (CSS animations replay whenever
   an element goes from display:none to displayed, so no JS needed) ---------- */
.modal-backdrop:not([hidden]) { animation: modal-fade 0.18s ease; }
.modal-backdrop:not([hidden]) .modal { animation: modal-pop 0.24s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes modal-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes modal-pop {
  from { opacity: 0; transform: translateY(12px) scale(0.97); }
  to { opacity: 1; transform: none; }
}

/* ---------- Cookie bar: slide up on entrance ---------- */
.cookie-bar { animation: cookie-slide-up 0.35s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes cookie-slide-up {
  from { opacity: 0; transform: translateY(24px); }
  to { opacity: 1; transform: none; }
}

/* ---------- Mode content cross-fade, upgraded ---------- */
main.is-switching { opacity: 0; transform: translateY(6px); }
main { transition: opacity 0.22s ease, transform 0.22s ease; }

/* ---------- Impact numbers: little pop when their count-up finishes ---------- */
.impact-num.is-counted { animation: count-pop 0.4s ease; }
@keyframes count-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.12); }
  100% { transform: scale(1); }
}

/* ---------- Back to top ---------- */
.back-to-top {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: rgba(19, 41, 26, 0.92);
  color: var(--ink);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.55);
  /* Hidden until the header has scrolled out of view, and it fades back
     out on the way to the top. shared.js toggles .is-visible from the
     same rAF-coalesced scroll handler that drives the header shadow, so
     this costs no extra listener. The button stays in the DOM
     throughout — fading rather than display:none keeps the transition
     alive in both directions. */
  opacity: 0;
  pointer-events: none;
  transform: translateY(10px) scale(0.9);
  display: grid;
  place-items: center;
  transition: opacity 0.22s ease,
              transform 0.22s cubic-bezier(0.16, 1, 0.3, 1),
              background 0.15s ease, color 0.15s ease;
  z-index: 40;
}
.back-to-top.is-visible {
  opacity: 1;
  pointer-events: auto;
  transform: none;
}
.back-to-top.is-visible:hover {
  background: var(--accent);
  color: var(--ink-invert);
  transform: translateY(-2px);
}
.back-to-top:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (max-width: 560px) {
  .back-to-top { right: 1rem; bottom: 1rem; width: 40px; height: 40px; }
}

/* ---------- Respect reduced motion: kill everything above ---------- */
@media (prefers-reduced-motion: reduce) {
  .js-ready .reveal { opacity: 1 !important; transform: none !important; }
  /* globe.js already renders a single still frame in this mode; make
     sure the canvas doesn't fade either. */
  #globe-canvas { transition: none !important; }
  .brand-mark { animation: none !important; }
  .modal-backdrop:not([hidden]),
  .modal-backdrop:not([hidden]) .modal,
  .cookie-bar,
  .impact-num.is-counted {
    animation: none !important;
  }
  /* Still appears and disappears at the same scroll point — it just
     snaps instead of sliding, and never carries a transform. */
  .back-to-top { transition: none !important; transform: none !important; }
  .back-to-top.is-visible:hover { transform: none !important; }
}

/* ============================================================
   GLASS THEME — landing page only (body.glass-page on index.html).
   Every major surface between the hero and the bottom of the footer
   becomes translucent glass so the globe shows through the whole
   page. Kept affordable by three rules:
   1. globe.js treats all glass sections as "soft" windows — half
      render resolution and a capped frame rate while only glass is
      on screen. Nobody can tell through the blur.
   2. Raised elements INSIDE a glass section (cards, forms, FAQ
      items) use plain rgba surfaces, never their own
      backdrop-filter — nested blurs multiply compositor cost for
      no visible gain.
   3. #map keeps its own mostly-transparent gradient (no blur):
      it's the destination of the globe's flight and must stay sharp.
   #about keeps its original, contrast-measured recipe — the rule
   below deliberately loses to #about.section-tinted on specificity.
   ============================================================ */

body.glass-page .site-header {
  background: rgba(10, 28, 18, 0.62);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
}
body.glass-page .site-header.is-scrolled {
  background: rgba(8, 23, 14, 0.70);
}

body.glass-page #services,
body.glass-page #faq,
body.glass-page #action {
  background: rgba(10, 28, 18, 0.55);
  -webkit-backdrop-filter: blur(26px) brightness(0.52) saturate(1.5);
  backdrop-filter: blur(26px) brightness(0.52) saturate(1.5);
}

body.glass-page .impact {
  background:
    linear-gradient(180deg, rgba(160, 214, 140, 0.09), rgba(160, 214, 140, 0.02)),
    rgba(11, 28, 18, 0.50);
  -webkit-backdrop-filter: blur(26px) brightness(0.52) saturate(1.5);
  backdrop-filter: blur(26px) brightness(0.52) saturate(1.5);
}

body.glass-page .site-footer {
  background: rgba(5, 18, 10, 0.58);
  -webkit-backdrop-filter: blur(26px) brightness(0.48) saturate(1.5);
  backdrop-filter: blur(26px) brightness(0.48) saturate(1.5);
}

/* Raised surfaces inside glass sections: translucent, no blur. */
body.glass-page .card,
body.glass-page .faq-item { background: rgba(19, 41, 26, 0.55); }
body.glass-page .card:hover { background: rgba(23, 52, 33, 0.75); }
body.glass-page .step::before { background: rgba(19, 41, 26, 0.75); }
body.glass-page .panel-form { background: rgba(19, 41, 26, 0.62); }
body.glass-page .panel-form input,
body.glass-page .panel-form select,
body.glass-page .panel-form textarea {
  background: rgba(10, 28, 18, 0.72);
}
body.glass-page .panel-form input:focus,
body.glass-page .panel-form select:focus,
body.glass-page .panel-form textarea:focus {
  background: rgba(12, 33, 20, 0.88);
}

/* No backdrop-filter → glass would be unreadable noise. Fall back to
   the original opaque surfaces. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  body.glass-page .site-header,
  body.glass-page #services,
  body.glass-page #faq,
  body.glass-page #action { background: #0a1c12; }
  body.glass-page .impact {
    background:
      linear-gradient(180deg, rgba(160, 214, 140, 0.09), rgba(160, 214, 140, 0.02)),
      #0b1c12;
  }
  body.glass-page .site-footer { background: #05120a; }
}

/* Users who ask the OS for less transparency get the opaque look. */
@media (prefers-reduced-transparency: reduce) {
  body.glass-page .site-header,
  body.glass-page #services,
  body.glass-page #faq,
  body.glass-page #action {
    background: #0a1c12;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body.glass-page .impact {
    background:
      linear-gradient(180deg, rgba(160, 214, 140, 0.09), rgba(160, 214, 140, 0.02)),
      #0b1c12;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body.glass-page .site-footer {
    background: #05120a;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* ============================================================
   PHONES — final pass
   Deliberately the last block in the file. Several of the rules here
   override declarations that appear late (section[id]'s scroll-margin
   in the animations block, the glass surfaces below it), so they have
   to come after those to win on cascade order rather than by being
   inflated with extra selectors.
   ============================================================ */

@media (max-width: 720px) {
  /* ---- Hero ----
     The globe passes directly behind the headline at this width and
     there is no room to move the copy off it, so the copy brings its
     own scrim. It lives inside .hero-inner's stacking context, which
     means it covers the canvas but still paints under the text. The
     text-shadows stay: they carry the edges where the scrim has faded
     out. */
  .hero { min-height: 82vh; }
  .hero-inner { padding: 3.5rem 1.15rem 3rem; }
  .hero-inner::before {
    content: "";
    position: absolute;
    inset: -1.5rem -1rem;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(118% 78% at 34% 48%,
                rgba(8, 23, 14, 0.94) 0%,
                rgba(8, 23, 14, 0.87) 38%,
                rgba(8, 23, 14, 0.58) 68%,
                rgba(8, 23, 14, 0) 100%);
  }
  .hero-lead { font-size: 1rem; }
  .hero-actions { gap: 0.6rem; }

  /* ---- Vertical rhythm ----
     4.5rem of section padding is a desktop measure; on a phone it just
     means more scrolling between one screen of text and the next. */
  .section { padding: 3rem 0; }
  .section-inner { padding: 0 1.15rem; }
  .impact-inner { padding: 1.8rem 1.15rem; }
}

@media (max-width: 640px) {
  /* ---- Header ----
     The tight spot on the whole site: brand, account, language and menu
     all want a share of a ~360px line. "My account" was breaking
     mid-label and doubling the header's height, which is what pushed
     the mode switch onto a third row. */
  .header-inner {
    justify-content: space-between;
    gap: 0.6rem;
    padding: 0.55rem 0.9rem;
  }
  .header-nav {
    gap: 0.5rem;
    flex-wrap: wrap;          /* degrade gracefully rather than overflow */
    justify-content: flex-end;
  }
  .header-nav .btn {
    padding: 0.5rem 0.85rem;
    font-size: 0.85rem;
    white-space: nowrap;      /* the actual fix for the wrapped label */
  }
  .brand-name { font-size: 1.1rem; }
  .brand-mark { width: 22px; height: 22px; }
  .mode-switch { order: 3; width: 100%; margin-inline: 0; }
  .mode-btn { font-size: 0.82rem; padding: 0.45rem 0.5rem; }
  .nav-menu { margin-left: 0; }
  .nav-menu-btn { width: 36px; height: 36px; }
  .lang-switch { margin-left: 0.15rem; }
  /* The divider before the language switch costs horizontal space the
     row can't spare, and the row's own wrapping already separates the
     groups visually. */
  .header-nav > .lang-switch::before { display: none; }
  /* Back up from 24px: still small, but a usable touch target. */
  .lang-btn { width: 28px; height: 28px; }
  .lang-btn .flag { width: 21px; height: 21px; }

  /* ---- Surfaces: give the text back the width the padding was taking ---- */
  .card { padding: 1.25rem; }
  .faq-item { padding: 0.3rem 1rem; }
  .panel-form { padding: 1.4rem; }
  .modal { padding: 1.5rem 1.25rem; }
  .about-card { padding: 1.5rem 1.15rem; }
  .section-split { gap: 1.75rem; }

  /* ---- Footer: two columns of links is one too many here ---- */
  .footer-inner {
    grid-template-columns: 1fr;
    row-gap: 1.75rem;
    padding: 2.5rem 1.15rem 1.75rem;
  }
  .footer-col a,
  .footer-col .footer-legal-btn { white-space: normal; }

  /* Admin moves out of the header row and into the account dropdown.
     [hidden] still wins over both of these via the global
     [hidden] { display: none !important } rule, so a non-admin sees
     neither. */
  .header-nav > a#admin-link:not([hidden]) { display: none; }
  .account-menu-admin:not([hidden]) { display: block; }
}
