/* marola map (MIP-0005), styled per DESIGN.md. Plain CSS, mobile first, no framework; Inter is
 * self-hosted under vendor/fonts. Third-party origins: Mapbox (base map) and NASA GIBS (satellite layers). The five
 * score tokens and the two flow ramps are data and stay. */
@font-face { font-family: "Inter"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url(vendor/fonts/inter-latin-wght-normal.woff2) format("woff2"); }
:root {
  --c70: #1b9e77;   /* ≥70 good */
  --c40: #e6ab02;   /* 40-69 fair */
  --c1:  #d95f02;   /* 1-39 poor */
  --c0:  #d7191c;   /* 0 / water unfit */
  --cna: #8c8c8c;   /* no data */
  --ink: #111820;
  --muted: #56606c;      /* 6.3:1 on white, 5.8:1 on --surface */
  --bg: #ffffff;
  --surface: #f3f5f7;
  --line: #e1e5ea;
  --line-strong: #cbd2da; /* control borders */
  --sea: #cfe6f1;         /* the map before its tiles load: the base map's water */
  /* flow ramps (flow.js), calm to strong, after Windy's muted scales; the score dots sit on top
   * with a ring and a number, so a field colour is never read as a score */
  --flow-wind-0: #5b6db3; --flow-wind-1: #4a94a9; --flow-wind-2: #4d9a6e; --flow-wind-3: #8fa64a;
  --flow-wind-4: #b5904a; --flow-wind-5: #a8566a;
  --flow-wave-0: #2f5a9e; --flow-wave-1: #4a63b8; --flow-wave-2: #6b55b3; --flow-wave-3: #9150a8;
  --flow-wave-4: #b4508c; --flow-wave-5: #c86e6e;
  /* the NASA GIBS layers' keys, drawn after GIBS's own palettes: MUR SST, then its anomaly */
  --sst-0: #3b1d73; --sst-1: #2f5fb3; --sst-2: #33a3c8; --sst-3: #6cc46a; --sst-4: #f0d23c; --sst-5: #d9452b;
  --anom-cold: #2b5cb8; --anom-mid: #f4f4f4; --anom-warm: #c8322b;
  /* what floats over the map is frosted white glass, readable over the light base map and the fields */
  --glass: rgb(255 255 255 / .9); --glass-hover: rgb(17 24 32 / .06); --glass-line: rgb(17 24 32 / .12);
  --glass-ink: #111820; --glass-muted: #56606c; --glass-unfit: #c0262d;
  --accent: #1b5fc1;      /* the one accent: links, primary fill, focus, the "you" marker (6.1:1) */
  --accent-hover: #164e9e;
  --accent-soft: #e9f0fb; /* selected toggles */
  --emergency: #c0262d;   /* the emergency button's phone icon, nothing else */
  --shadow-float: 0 1px 2px rgb(17 24 32 / .06), 0 8px 24px -6px rgb(17 24 32 / .16);
  --r-control: 8px;
  --r-panel: 12px;
  --sans: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* type scale; each size's tracking follows Inter's dynamic metrics,
   * -0.0223 + 0.185 * e^(-0.1745 * px) em. letter-spacing inherits as a length, so a rule that sets
   * a size sets its tracking too. */
  --fs-11: 11px; --fs-12: 12px; --fs-13: 13px; --fs-14: 14px; --fs-15: 15px; --fs-17: 17px; --fs-18: 18px;
  --fs-19: 19px; --fs-20: 20px; --fs-21: 21px; --fs-22: 22px; --fs-24: 24px; --fs-28: 28px;
  --fs-display: clamp(36px, 5vw + 12px, 56px);
  --tr-11: .005em; --tr-12: 0em; --tr-13: -.003em; --tr-14: -.006em; --tr-15: -.009em; --tr-17: -.013em;
  --tr-18: -.014em; --tr-19: -.016em; --tr-20: -.017em; --tr-21: -.018em; --tr-22: -.018em; --tr-24: -.02em;
  --tr-28: -.021em; --tr-display: -.022em;
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  font: 400 var(--fs-15)/1.5 var(--sans); letter-spacing: var(--tr-15); font-kerning: normal;
  color: var(--ink); background: var(--bg);
  display: flex; flex-direction: column; min-height: 100vh;
  -webkit-text-size-adjust: 100%; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
}
#app { display: contents; }
h1, h2, h3 { text-rendering: optimizeLegibility; text-wrap: balance; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--accent-hover); }
::selection { background: var(--accent-soft); }
b, strong { font-weight: 600; }
small { font-size: var(--fs-13); letter-spacing: var(--tr-13); }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ic { width: 16px; height: 16px; flex: none; vertical-align: -3px; fill: none; stroke: currentColor;
  stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.ic { color: var(--accent); }
.score, .dist, .hourbar label, .card dd, .list li::before, .legend { font-variant-numeric: tabular-nums; }

/* utility strip: sections, language, the repo. Plain links, not pills: they are navigation */
.sitenav { display: flex; flex-wrap: wrap; gap: 4px 20px; align-items: center;
  min-height: 40px; padding: 4px 24px; background: var(--surface); border-bottom: 1px solid var(--line);
  font-size: var(--fs-13); letter-spacing: var(--tr-13); }
.sitenav > a { color: var(--ink); text-decoration: none; font-weight: 500; }
.sitenav > a:hover { color: var(--accent); }
.sitenav > a[aria-current="page"] { color: var(--accent); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 6px; }
/* a section with no page yet is muted text, so it does not read as a link */
.sitenav span, .about-body span[aria-disabled] { color: var(--muted); cursor: default; }
.sitenav i, .about-body span[aria-disabled] i { font-style: normal; font-size: var(--fs-12); letter-spacing: var(--tr-12); color: var(--muted); margin-left: 2px; }
.sitenav i::before, .about-body span[aria-disabled] i::before { content: "("; }
.sitenav i::after, .about-body span[aria-disabled] i::after { content: ")"; }
/* the repo link, #498: static on purpose, no live star count (that would be a request to api.github.com) */
.sitenav .gh { display: inline-flex; align-items: center; gap: 6px; color: var(--ink); text-decoration: none; font-weight: 500; }
.sitenav .gh span { color: inherit; cursor: pointer; }
.sitenav .gh:hover { color: var(--accent); }
.gh svg { width: 15px; height: 15px; flex: none; }
.sitenav .gh .gh-owner { color: var(--muted); font-weight: 400; }
.gh-star { display: inline-flex; align-items: center; gap: 4px; padding-left: 8px; border-left: 1px solid var(--line-strong); }
.gh-star svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linejoin: round; }
.gh:hover .gh-star svg { fill: currentColor; }
/* marola's LinkedIn, beside the language toggle; Lucide's old brand glyph, drawn like .ic */
.sitenav .li { display: inline-flex; align-items: center; gap: 6px; color: var(--ink); text-decoration: none; font-weight: 500; text-transform: none; }
.sitenav .li:hover { color: var(--accent); }
.li-mark { width: 14px; height: 14px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
/* the language toggle pairs with the repo link (MIP-0054 §5.8) */
.sitenav .lang { margin-left: auto; }
.lang-icon { width: 14px; height: 14px; margin: 0 4px 0 6px; flex: none; fill: none; stroke: var(--muted); stroke-width: 1.2; }
.lang button, .lang a { text-transform: none; }
/* the static pages switch language with two plain links; they look like the map page's buttons */
.lang a { display: inline-flex; align-items: center; min-height: 24px; padding: 0 8px; border: 1px solid transparent; border-radius: 6px; color: var(--muted); text-decoration: none; font-size: var(--fs-12); letter-spacing: var(--tr-12); font-weight: 500; }
.lang a:hover { background: rgb(255 255 255 / .6); color: var(--ink); }
.lang a[aria-current="true"] { background: var(--bg); border: 1px solid var(--line); color: var(--ink); box-shadow: 0 1px 2px rgb(17 24 32 / .08); }

/* header: wordmark and what the page does at left, the controls at right */
.bar {
  display: flex; align-items: center; gap: 12px 24px; flex-wrap: wrap;
  padding: 12px 24px; background: var(--bg);
}
.brand { display: flex; align-items: baseline; gap: 4px 16px; flex-wrap: wrap; min-width: 0; }
.bar h1 {
  display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: var(--fs-22); font-weight: 650; line-height: 1.2; letter-spacing: var(--tr-22); white-space: nowrap;
}
.bar h1 svg { width: 22px; height: 22px; color: var(--accent); flex: none; align-self: center; }
.tagline { margin: 0; font-size: var(--fs-14); letter-spacing: var(--tr-14); line-height: 1.4; color: var(--muted); max-width: 60ch; }
.controls { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-left: auto; }
.controls:empty { display: none; }

/* One control everywhere: 36 px, 8 px radius, a 1px border. Selected toggles take the soft
 * accent; the one primary action per surface (chat) takes the accent fill. */
select, button, .pill, .controls > a {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font: inherit; font-size: var(--fs-14); letter-spacing: var(--tr-14); font-weight: 500; line-height: 1.2; min-height: 36px; padding: 0 12px;
  border: 1px solid var(--line-strong); border-radius: var(--r-control);
  background: var(--bg); color: var(--ink); cursor: pointer; text-decoration: none; white-space: nowrap;
}
select { display: inline-block; padding: 0 8px 0 12px; }
#area { text-transform: none; font-weight: 600; letter-spacing: .02em; }
select:hover, button:hover, .pill:hover, .controls > a:hover { background: var(--surface); border-color: #b4bec9; }
button:active { transform: translateY(1px); }
button[aria-pressed="true"], button[aria-expanded="true"] {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
/* segmented groups (day, language): a gray track, the picked segment raised in white */
.segmented, .lang { display: inline-flex; align-items: center; gap: 2px; padding: 2px; min-height: 36px;
  border-radius: var(--r-control); background: var(--surface); border: 1px solid var(--line); }
.lang { min-height: 30px; }
.segmented button, .lang button { min-height: 30px; padding: 0 10px; border-color: transparent; background: transparent;
  border-radius: 6px; color: var(--muted); }
.lang button { min-height: 24px; padding: 0 8px; font-size: var(--fs-12); letter-spacing: var(--tr-12); }
.segmented button:hover, .lang button:hover { background: rgb(255 255 255 / .6); border-color: transparent; color: var(--ink); }
.segmented button.on, .lang button[aria-pressed="true"] {
  background: var(--bg); border-color: var(--line); color: var(--ink); box-shadow: 0 1px 2px rgb(17 24 32 / .08); }
.segmented button small { font-size: var(--fs-12); letter-spacing: var(--tr-12); color: var(--muted); font-weight: 400; }

/* hour slider + legend */
.hourbar {
  display: flex; align-items: center; gap: 8px 24px; flex-wrap: wrap;
  padding: 8px 24px; background: var(--bg); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  font-size: var(--fs-13); letter-spacing: var(--tr-13); line-height: 1.4; color: var(--muted);
}
.hourbar label { min-width: 12rem; font-weight: 500; color: var(--ink); }
.hourbar input[type=range] { flex: 1 1 12rem; min-width: 8rem; max-width: 28rem; margin: 0; accent-color: var(--accent); }
.legend { display: inline-flex; align-items: center; gap: 4px 14px; flex-wrap: wrap; margin-left: auto; }
.legend b { font-weight: 500; color: var(--ink); }
.legend i { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; vertical-align: 1px; }
.c70 { background: var(--c70); } .c40 { background: var(--c40); } .c1 { background: var(--c1); }
.c0 { background: var(--c0); } .cna { background: var(--cna); }

/* the map fills what is left */
.main { position: relative; flex: 1 1 auto; min-height: 60vh; }
#map { position: absolute; inset: 0; background: var(--sea); }
/* the open list would cover the layer panel */
@media (min-width: 641px) {
  /* the open card would cover the layer rail, and the open list the zoom buttons and the key */
  .main:has(.card:not([hidden])) .flow { right: calc(min(26rem, calc(100vw - 24px)) + 24px); }
  .main:has(.list:not([hidden])) .flowkeys { left: calc(min(22rem, 90vw) + 24px); }
  .main:has(.list:not([hidden])) .maplibregl-ctrl-top-left { left: calc(min(22rem, 90vw) + 12px); }
}

/* the layer rail, Windy-style: top right of the map; it scrolls if the map is too short for it.
 * The padding keeps the buttons' shadows inside the scroll box. */
.flow { position: absolute; z-index: 900; top: 12px; right: 12px; max-height: calc(100% - 24px); overflow-y: auto; scrollbar-width: none; padding: 2px 6px 8px; margin: -2px -6px 0 0; display: flex; flex-direction: column; align-items: flex-end;
  gap: 8px; font-size: var(--fs-12); letter-spacing: var(--tr-12); color: var(--glass-muted); }
.flow .layers { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.flow .layers .sep { width: 20px; height: 1px; margin: 2px 0; background: var(--glass-line); }
.flow .layers button { display: flex; align-items: center; justify-content: center; width: 36px; min-height: 36px; padding: 0;
  border: 1px solid var(--glass-line); border-radius: 50%; background: var(--glass); color: var(--glass-ink);
  box-shadow: var(--shadow-float); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.flow .layers button .ic { width: 18px; height: 18px; }
/* icons only; the word stays for screen readers and as the title */
.flow .layers button > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.flow .layers button:hover { background: var(--bg); border-color: var(--line-strong); color: var(--accent); }
.flow .layers button .ic { color: inherit; }
.flow .layers button.soon { opacity: .45; cursor: not-allowed; }
.flow .layers button.soon:hover { background: var(--glass); color: var(--glass-ink); }
.flow .layers button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }
.flowkeys { position: absolute; z-index: 900; left: 12px; bottom: 40px; font-size: var(--fs-12); letter-spacing: var(--tr-12); color: var(--glass-muted); }
.flowkey [data-when] { white-space: nowrap; }
.flowkey { display: grid; gap: 4px; width: 13rem; margin: 0; padding: 8px 10px; line-height: 1.35;
  background: var(--glass); border: 1px solid var(--glass-line); border-radius: var(--r-control);
  box-shadow: var(--shadow-float); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.flowkey .ramp { display: block; height: 8px; border-radius: 4px; }
.ramp.wind { background: linear-gradient(90deg, var(--flow-wind-0), var(--flow-wind-1), var(--flow-wind-2), var(--flow-wind-3), var(--flow-wind-4), var(--flow-wind-5)); }
.ramp.sst { background: linear-gradient(90deg, var(--sst-0), var(--sst-1), var(--sst-2), var(--sst-3), var(--sst-4), var(--sst-5)); }
.ramp.anomaly { background: linear-gradient(90deg, var(--anom-cold), var(--anom-mid), var(--anom-warm)); }
.ramp.waves { background: linear-gradient(90deg, var(--flow-wave-0), var(--flow-wave-1), var(--flow-wave-2), var(--flow-wave-3), var(--flow-wave-4), var(--flow-wave-5)); }
.flowkey .ends { display: flex; justify-content: space-between; font-variant-numeric: tabular-nums; color: var(--glass-ink); }
.flowkey .dots { display: flex; flex-wrap: wrap; gap: 2px 10px; color: var(--glass-ink); }
.flowkey .dots i { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 5px; vertical-align: 1px; }
.flowkey .dots .wpoint { display: inline-block; width: 12px; height: 12px; background: none; border-radius: 0; margin-right: 5px; vertical-align: -1px; }
.map-note { position: absolute; z-index: 900; top: 12px; right: 12px; max-width: min(24rem, calc(100% - 24px)); margin: 0;
  padding: 12px 16px; background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-panel);
  box-shadow: var(--shadow-float); font-size: var(--fs-14); letter-spacing: var(--tr-14); }

/* panels float over the map, so they are the one place with elevation */
.list, .card {
  position: absolute; z-index: 1000; background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--r-panel); box-shadow: var(--shadow-float); overflow: auto; overscroll-behavior: contain;
}
.list { top: 12px; left: 12px; bottom: 12px; width: min(22rem, 90vw); padding: 4px 0; }
.list ol { margin: 0; padding: 0; list-style: none; counter-reset: rank; }
.list li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 10px;
  padding: 10px 16px; border-top: 1px solid var(--line); cursor: pointer; font-size: var(--fs-14); letter-spacing: var(--tr-14); font-weight: 500; line-height: 1.4;
}
.list li:first-child { border-top: 0; }
.list li::before { content: counter(rank); counter-increment: rank; min-width: 1.5em; text-align: right; font-size: var(--fs-12); letter-spacing: var(--tr-12); font-weight: 400; color: var(--muted); }
.list li:hover { background: var(--surface); }
.list .score {
  display: inline-block; min-width: 2.4em; padding: 1px 6px; text-align: center;
  color: #fff; border-radius: 999px; font-size: var(--fs-12); letter-spacing: var(--tr-12); line-height: 1.5; font-weight: 600;
}
.list .dist { margin-left: auto; font-size: var(--fs-13); letter-spacing: var(--tr-13); font-weight: 400; color: var(--muted); }
.list .water { flex-basis: 100%; padding-left: calc(1.5em + 10px); font-size: var(--fs-12); letter-spacing: var(--tr-12); font-weight: 400; color: var(--muted); }
.list .water.unfit { color: var(--c0); font-weight: 600; }

.card { right: 12px; bottom: 12px; width: min(26rem, calc(100vw - 24px)); max-height: calc(100% - 24px); padding: 20px 24px 16px; }
.card h2 { margin: 0 40px 12px 0; font-size: var(--fs-20); font-weight: 650; line-height: 1.25; letter-spacing: var(--tr-20); }
.card .close { position: absolute; top: 14px; right: 14px; }
.card .headline { margin: 16px 0 12px; padding-top: 16px; border-top: 1px solid var(--line); font-size: var(--fs-15); letter-spacing: var(--tr-15); }
.card .headline .score { color: #fff; border-radius: 999px; padding: 2px 8px; margin-right: 4px; font-size: var(--fs-13); letter-spacing: var(--tr-13); font-weight: 600; }
.card dl { margin: 0; display: grid; grid-template-columns: 6.5rem 1fr; gap: 8px 16px; font-size: var(--fs-14); letter-spacing: var(--tr-14); }
.card dt { font-size: var(--fs-13); letter-spacing: var(--tr-13); color: var(--muted); }
.card dd { margin: 0; max-width: 65ch; }
.card dd small { color: var(--muted); }
.card ul { margin: 0; padding-left: 1rem; }
.card li { margin: 0 0 2px; }
.card .unfit { color: var(--c0); font-weight: 600; }
.card .improper { color: var(--c0); }
.card .proper { color: #137a5c; }
.card .past { color: var(--muted); }

.footer { padding: 12px 24px 16px; font-size: var(--fs-13); letter-spacing: var(--tr-13); line-height: 1.55; color: var(--muted); background: var(--surface); border-top: 1px solid var(--line); }
.footer p { margin: 4px 0; max-width: 75ch; }
.footer .lore { font-size: var(--fs-15); letter-spacing: var(--tr-15); color: var(--ink); }
/* the lore and the score note fold behind compact controls (#59); open, they take the pressed look */
.folds { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
/* tight padding, the label never wraps; a phone gets bigger ones further down */
.footer .fold { min-height: 32px; padding: 0 8px 0 7px; gap: 6px; font-size: var(--fs-13); letter-spacing: var(--tr-13); white-space: nowrap; }
/* not built yet: reads as a control, muted, and does nothing (no pressed look, no press nudge) */
.insta.soon, .insta.soon:hover { color: var(--muted); background: var(--bg); border-color: var(--line-strong); cursor: default; }
.insta.soon .ic { color: var(--muted); }
.footer .fold.soon, .footer .fold.soon:hover { color: var(--muted); background: var(--bg); border-color: var(--line-strong); cursor: default; }
.footer .fold.soon:active { transform: none; }
.footer .vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.fold .pm { position: relative; width: 10px; height: 10px; flex: none; }
.fold .pm::before, .fold .pm::after { content: ""; position: absolute; left: 0; top: 4px; width: 10px; height: 2px; border-radius: 1px; background: currentColor; }
.fold .pm::after { transform: rotate(90deg); }
.fold[aria-expanded="true"] .pm::after { transform: rotate(180deg); } /* lies on the bar: [+] turns into [−] */
.footer .fold-panel { margin: 10px 0 2px; }
/* 840 px and up: the status at left, the toggles at right on its line; the status wraps before they do.
 * Measured on the longest real status (salvador, pt-BR): from 840 px it keeps >= 400 px and <= 3 lines;
 * narrower, it turns into a sliver, so the toggles drop to their own row under it. */
@media (min-width: 840px) {
  .footbar { display: flex; align-items: center; justify-content: space-between; gap: 8px 24px; }
  .footbar #status { flex: 1 1 auto; min-width: 0; max-width: none; margin: 0; }
  .footbar .folds { flex: none; flex-wrap: nowrap; margin-top: 0; }
}
/* Lowercase house style, except names marola did not choose: providers, the agency's verbatim
 * PRÓPRIA/IMPRÓPRIA verdict (MIP-0001), beaches, and literal text in <code> (a file name; an
 * EIP-55 address, whose letter case is its checksum). Containers are exempted because app.js emits
 * beach names as bare text nodes. */
body { text-transform: lowercase; }
.src, .water, .unfit, .maplibregl-ctrl-attrib,
.list li, .card h2, .maplibregl-popup .head, .about-body code, .dir, .flowkey, .member { text-transform: none; }

/* The contact form (contact.html): a static form that FormSubmit forwards by email; plain controls. */
.contact { display: grid; gap: 12px; max-width: 520px; }
.contact label { display: grid; gap: 4px; }
.contact input, .contact textarea { font: inherit; text-transform: none; padding: 8px 10px; color: var(--ink); background: var(--bg); border: 1px solid var(--line-strong); border-radius: var(--r-control); }
.contact textarea { resize: vertical; }
.contact input:focus-visible, .contact textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.contact button { justify-self: start; }
.bar h1 { text-transform: lowercase; }

.nojs { padding: 32px; max-width: 65ch; }

/* about / support: a reading column */
.about { display: block; flex: none; padding: 64px 24px 96px; border-top: 1px solid var(--line); }
.about-body { max-width: 40rem; margin: 0 auto; font-size: var(--fs-17); line-height: 1.6; letter-spacing: var(--tr-17); }
.about-body h2 { margin: 72px 0 16px; font-size: var(--fs-28); font-weight: 650; line-height: 1.15; letter-spacing: var(--tr-28); }
.about-body h2:first-child { margin: 0 0 20px; font-size: var(--fs-display); font-weight: 700; line-height: 1.05; letter-spacing: var(--tr-display); }
.about-body .lede { margin: 0 0 40px; font-size: var(--fs-21); font-weight: 400; line-height: 1.45; letter-spacing: var(--tr-21); color: var(--muted); }
.about-body h3 { margin: 32px 0 8px; font-size: var(--fs-17); font-weight: 600; line-height: 1.4; letter-spacing: var(--tr-17); }
.about-body p, .about-body li { text-wrap: pretty; }
.about-body p { margin: 0 0 16px; }
.about-body ol, .about-body ul { margin: 0 0 16px; padding-left: 1.25rem; }
.about-body li { margin: 0 0 8px; }
.about-body figure { margin: 40px 0; }
.about-body figure img { display: block; width: 100%; height: auto; border-radius: var(--r-panel); }
.about-body figcaption { margin-top: 12px; font-size: var(--fs-13); line-height: 1.5; letter-spacing: var(--tr-13); color: var(--muted); }
.about-body blockquote { margin: 24px 0; padding-left: 16px; border-left: 2px solid var(--line-strong);
  font-size: var(--fs-19); line-height: 1.5; letter-spacing: var(--tr-19); color: var(--ink); }
.about-body blockquote > :last-child { margin-bottom: 0; }
.about-body blockquote cite, .about-body blockquote footer { font-size: var(--fs-13); font-style: normal; letter-spacing: var(--tr-13); color: var(--muted); }
.about-body blockquote footer { margin-top: 8px; }
.about-body code { font-size: var(--fs-15); letter-spacing: var(--tr-15); padding: 1px 5px; border-radius: 4px; background: var(--surface); }
html:not(:lang(en)) article.about-body:lang(en), html:lang(en) article.about-body:lang(pt) { display: none; }
/* news.html: a release card (`::: release` in a post) */
.about-body .release { margin: 32px 0 40px; padding: 20px 24px; border: 1px solid var(--line); border-radius: var(--r-panel); background: var(--surface); }
.about-body .release-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin: 0 0 12px; }
.about-body .release-tag { padding: 2px 10px; border-radius: 999px; background: var(--accent); color: #fff; font-size: var(--fs-15); font-weight: 600; letter-spacing: var(--tr-15); text-decoration: none; text-transform: none; font-variant-numeric: tabular-nums; }
.about-body .release-tag:hover { color: #fff; background: var(--accent-hover); }
.about-body .release-head time { font-size: var(--fs-14); color: var(--muted); }
.about-body .release ul { margin-bottom: 12px; font-size: var(--fs-15); }
.about-body .release-links { margin: 0; font-size: var(--fs-14); color: var(--muted); }
/* news.html: the next post of the same language, below the previous one */
article.about-body:lang(pt) + article.about-body:lang(pt), article.about-body:lang(en) + article.about-body:lang(en) { margin-top: 120px; }
/* members.html: one row per person; the GitHub avatar, copied into img/members/, or initials */
.about-body .members { list-style: none; margin: 0 0 40px; padding: 0; border-top: 1px solid var(--line); }
.about-body .member { display: grid; grid-template-columns: 48px 1fr; column-gap: 16px; align-items: center;
  margin: 0; padding: 16px 0; border-bottom: 1px solid var(--line); }
.member-mark { grid-row: 1 / span 4; width: 48px; height: 48px; border-radius: 50%; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent); font-size: var(--fs-15); font-weight: 600; letter-spacing: var(--tr-15); }
img.member-mark { display: block; object-fit: cover; border: 1px solid var(--line); }
.about-body .member > :not(.member-mark) { grid-column: 2; }
.member-name { font-weight: 600; }
.member-aff, .member-role, .member-links { font-size: var(--fs-14); line-height: 1.45; letter-spacing: var(--tr-14); color: var(--muted); }
.member-links { display: flex; flex-wrap: wrap; gap: 4px 16px; font-variant-numeric: tabular-nums; }
/* The empty slot is the width the address will take (0x + 40 hex digits). */
.addr:empty { display: inline-block; width: 42ch; max-width: 100%; padding: 0 .4rem; vertical-align: middle;
  border: 1px dashed var(--line-strong); border-radius: 6px; }
.addr:empty::before { content: "not published yet"; color: var(--muted); }
html:lang(pt) .addr:empty::before { content: "ainda não publicado"; }

/* Mapbox GL's controls and popups in DESIGN.md's control and panel shapes */
.maplibregl-map { font: inherit; }
.maplibregl-ctrl-group { border: 1px solid var(--glass-line); border-radius: var(--r-control) !important; box-shadow: var(--shadow-float) !important;
  overflow: hidden; background: var(--glass) !important; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.maplibregl-ctrl-group button + button { border-top-color: var(--glass-line) !important; }
.maplibregl-ctrl-group button:hover { background: var(--glass-hover) !important; }
.maplibregl-ctrl-group button { min-height: 0; border-radius: 0; }
.maplibregl-ctrl-attrib { font-size: var(--fs-11); letter-spacing: var(--tr-11); }
.maplibregl-popup { font-size: var(--fs-13); letter-spacing: var(--tr-13); font-variant-numeric: tabular-nums; pointer-events: none; }
.maplibregl-popup-content { padding: 8px 12px; color: var(--glass-ink); background: var(--glass); border: 1px solid var(--glass-line);
  border-radius: var(--r-control); box-shadow: var(--shadow-float); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.maplibregl-popup .unfit, .maplibregl-popup .improper { color: var(--glass-unfit); }
.maplibregl-popup .facilities, .maplibregl-popup .past { color: var(--glass-muted); }
.maplibregl-popup .ic { color: var(--accent); }
.maplibregl-popup-tip { display: none; }

/* beach dots + hover aspects (MIP-0009) */
.maplibregl-marker.wave { cursor: pointer; line-height: 0; }
.maplibregl-marker.wave:hover, .maplibregl-marker.wave:focus-visible { z-index: 2; }
.maplibregl-marker.wave.selected { z-index: 3; }
.wave svg { display: block; overflow: visible; }
/* The marker dot takes its band colour from a class, because the CSP allows no inline style. */
.wave .dot.f-c70 { fill: var(--c70); } .wave .dot.f-c40 { fill: var(--c40); } .wave .dot.f-c1 { fill: var(--c1); }
.wave .dot.f-c0 { fill: var(--c0); } .wave .dot.f-cna { fill: var(--cna); }
.wave text { font-family: var(--sans); }
/* fading the whole element left a past dot almost invisible over the sea */
.wave.past circle + circle { fill-opacity: .45; stroke-dasharray: 2 1.5; }
/* the visitor: the beach dot's shape, smaller */
.here { width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--bg); cursor: default; background: var(--accent); }
/* a water-sampling point: a drop in its band colour, ringed like a beach dot so it reads on any base map */
.maplibregl-marker.wpoint { width: 18px; height: 18px; line-height: 0; background: none; cursor: default; }
.wpoint svg { display: block; width: 100%; height: 100%; overflow: visible; stroke-linejoin: round; }
.wpoint .rim { fill: none; stroke: var(--ink); stroke-width: 4.5; }
.wpoint .fill { stroke: var(--bg); stroke-width: 2; }
.wpoint.c70 .fill { fill: var(--c70); } .wpoint.c0 .fill { fill: var(--c0); } .wpoint.cna .fill { fill: var(--cna); }
/* on the water layer the sampling points are the data: the beach dots step back */
.layer-water .maplibregl-marker.wave { opacity: .4; }
.no-beaches .maplibregl-marker.wave { display: none; }
.layer-water .maplibregl-marker.wpoint { width: 22px; height: 22px; z-index: 4; }
.maplibregl-popup.aspects .maplibregl-popup-content { padding: 10px 12px; line-height: 1.4; width: max-content; max-width: 22rem; white-space: normal; }
.aspects .head { font-weight: 600; margin-bottom: 6px; }
/* auto columns wrap only what does not fit (nowrap clips the right column in pt-BR); width: max-content
 * above because the tooltip sits in a zero-width pane */
.aspects .grid { display: grid; grid-template-columns: auto auto; gap: 3px 16px; }
.aspects .grid .wide { grid-column: 1 / -1; }
.aspects .unfit { color: var(--c0); font-weight: 600; }
.wdot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin: 0 5px 0 4px; vertical-align: 1px; }
.aspects .facilities { color: var(--muted); }
.legend .wave-key { color: var(--muted); }
.legend .wave-key svg { width: 12px; height: 12px; vertical-align: -1px; margin-right: 6px; }
/* in the card the head repeats the h2, and a 390 px card cannot fit one line per reading */
.card .aspects { margin: 0; font-size: var(--fs-13); letter-spacing: var(--tr-13); }
.card .aspects .head { display: none; }
.card .aspects .grid { gap: 4px 12px; }

@media (prefers-reduced-motion: no-preference) {
  select, button, .list li, .sitenav a { transition: background-color .15s ease-out, border-color .15s ease-out, color .15s ease-out, transform .1s ease-out; }
  /* a footer panel fades in under its toggle and closes at once; the plus turns with it */
  .fold .pm::after { transition: transform .15s cubic-bezier(.23, 1, .32, 1); }
  .footer .fold-panel { transition: opacity .15s ease-out, transform .15s cubic-bezier(.23, 1, .32, 1); }
  @starting-style { .footer .fold-panel { opacity: 0; transform: translateY(-4px); } }
  .sos-panel { transition: opacity .15s ease-out, transform .15s cubic-bezier(.23, 1, .32, 1); }
  @starting-style { .sos-panel { opacity: 0; transform: translateY(-4px); } }
}

/* Emergency numbers (#76): a map control in white glass, top centre, clear of the zoom buttons
 * and the layer rail; only its icon is red, so it never reads as a score. */
.sos, .sos-panel { position: absolute; z-index: 1001; left: 0; right: 0; margin: 0 auto; }
.sos { top: 12px; width: fit-content; min-height: 32px; padding: 0 10px; gap: 6px; font-size: var(--fs-13); letter-spacing: var(--tr-13);
  background: var(--glass); border-color: var(--glass-line); color: var(--glass-ink); box-shadow: var(--shadow-float);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.sos .ic { width: 14px; height: 14px; color: var(--emergency); }
.sos:hover { background: var(--bg); border-color: var(--line-strong); }
.sos[aria-expanded="true"] { background: var(--bg); border-color: var(--line-strong); color: var(--glass-ink); }
.sos-panel { top: 52px; width: min(18rem, calc(100% - 24px)); background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--r-panel); box-shadow: var(--shadow-float);
  max-height: calc(100% - 64px); overflow-y: auto; overscroll-behavior: contain; }
.sos-panel header { display: flex; align-items: center; justify-content: space-between; padding: 8px 8px 0 16px; }
.sos-panel h2 { margin: 0; font-size: var(--fs-15); letter-spacing: var(--tr-15); font-weight: 600; }
.sos-panel > p { margin: 0 16px 8px; font-size: var(--fs-13); letter-spacing: var(--tr-13); color: var(--muted); }
.sos-panel ul { margin: 0; padding: 0; list-style: none; }
.sos-panel a { display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 4px 16px;
  border-top: 1px solid var(--line); color: var(--ink); text-decoration: none; font-size: var(--fs-14); letter-spacing: var(--tr-14); line-height: 1.35; }
.sos-panel a:hover { background: var(--surface); color: var(--ink); }
.sos-panel a b { flex: none; min-width: 2.25em; font-weight: 650; font-variant-numeric: tabular-nums; }
.sos-panel .sos-note { margin: 0; padding: 8px 16px 12px; border-top: 1px solid var(--line); font-size: var(--fs-12); letter-spacing: var(--tr-12); color: var(--muted); }

/* Chat widget: MIP-0033 §5.2. */
.chat-toggle {
  position: fixed; right: 16px; bottom: 16px; z-index: 900;
  min-height: 40px; padding: 0 16px; border-radius: 999px; box-shadow: var(--shadow-float);
}
.chat-toggle, #chat-form button { background: var(--accent); border-color: var(--accent); color: #fff; }
.chat-toggle:hover, #chat-form button:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
.chat-panel {
  position: fixed; right: 16px; bottom: 68px; z-index: 900;
  width: min(24rem, calc(100vw - 32px)); max-height: min(30rem, calc(100vh - 6rem));
  display: flex; flex-direction: column;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-panel); box-shadow: var(--shadow-float);
}
.chat-panel header { display: flex; align-items: center; justify-content: space-between; padding: 12px 12px 12px 16px; border-bottom: 1px solid var(--line); }
.chat-panel h2 { margin: 0; font-size: var(--fs-15); letter-spacing: var(--tr-15); font-weight: 600; }
/* the two close buttons are the shared control as a 32 px square */
.chat-panel header button, .card .close, .sos-panel header button { width: 32px; height: 32px; min-height: 0; padding: 0; font-size: var(--fs-18); letter-spacing: var(--tr-18); line-height: 1;
  border-color: transparent; color: var(--muted); }
.chat-panel header button:hover, .card .close:hover, .sos-panel header button:hover { color: var(--ink); }
.chat-log { flex: 1; overflow-y: auto; padding: 12px 16px; min-height: 6rem; font-size: var(--fs-14); letter-spacing: var(--tr-14); }
.chat-msg { margin: 0 0 8px; padding: 8px 12px; border-radius: 10px; max-width: 90%; white-space: pre-wrap; }
.chat-msg.user { background: var(--accent-soft); margin-left: auto; }
.chat-msg.assistant { background: var(--surface); }
.chat-msg.pending { color: var(--muted); }
.chat-offline { margin: 0 16px 8px; color: var(--c0); font-size: var(--fs-13); letter-spacing: var(--tr-13); }
#chat-form { display: flex; gap: 8px; padding: 12px; border-top: 1px solid var(--line); }
#chat-input { flex: 1; min-width: 0; min-height: 36px; padding: 0 12px; border: 1px solid var(--line-strong); border-radius: var(--r-control); font: inherit; font-size: var(--fs-14); letter-spacing: var(--tr-14); }

@media (max-width: 640px) {
  /* one row on a phone: a wrapped second row clipped the LinkedIn and GitHub icons. The strip scrolls
   * sideways on the narrowest screens instead of wrapping; the icons keep their aria-label. The gaps
   * and the language padding are tight so the pt-BR strip (the longest) fits 375 px and up without
   * scrolling: scripts/nav_measure.sh measures it in a real browser (not part of just quality). */
  .sitenav { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding: 4px 12px; gap: 4px 6px; }
  .sitenav > * { flex: none; }
  .lang button, .lang a { padding: 0 4px; }
  /* sections with no page yet would take a second row on a phone for nothing to tap */
  .sitenav > span { display: none; }
  /* a sixth link wraps the strip onto a second row; on a phone the members page is reached from about.html */
  .sitenav > a[href$="members.html"] { display: none; }
  /* the studies link goes the same way: about links it */
  .sitenav > a[href$="/studies"] { display: none; }
  /* research and contribute too: about.html ("quem faz") links both */
  .sitenav > a[href*="marola-research"] { display: none; }
  .sitenav .gh .gh-name, .sitenav .gh .gh-star, .sitenav .li .li-name { display: none; }
  .lang-icon { display: none; }
  .bar { padding: 12px 16px; gap: 10px; }
  .bar h1 { font-size: var(--fs-20); letter-spacing: var(--tr-20); }
  .tagline { font-size: var(--fs-13); letter-spacing: var(--tr-13); }
  /* one row on a phone: the day buttons drop their dates, the actions and the Instagram pill keep
   * only their icon (the label stays for screen readers) */
  .controls { margin-left: 0; width: 100%; flex-wrap: nowrap; gap: 6px; }
  .controls select { flex: none; min-width: 0; padding: 0 2px 0 8px; }
  .controls .segmented { flex: 1 1 auto; min-width: 0; }
  .controls .segmented button { flex: 1; min-width: 0; padding: 0 6px; overflow: hidden; }
  .controls .segmented button small { display: none; }
  .controls > button, .controls > .insta { flex: none; width: 36px; padding: 0; }
  .controls > button .ic, .controls > .insta .ic { width: 18px; height: 18px; }
  .controls > button > span, .controls > .insta > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .hourbar { padding: 8px 16px; gap: 6px 12px; }
  .hourbar label { min-width: 0; flex: none; }
  .hourbar input[type=range] { flex: 1 1 0; min-width: 6rem; max-width: none; }
  .legend { margin-left: 0; gap: 4px 12px; }
  .flow { top: 8px; right: 8px; gap: 6px; }
  .flow .layers { gap: 4px; }
  .flow .layers button { width: 32px; min-height: 32px; }
  .flow .layers button .ic { width: 16px; height: 16px; }
  .flowkeys { left: 8px; bottom: 36px; }
  .flowkey { width: 7.5rem; padding: 6px 8px; font-size: var(--fs-11); letter-spacing: var(--tr-11); }
  .flowkey > span:last-child { display: none; } /* the caption; the about page explains the field */
  .list { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 55%; }
  .card { left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 62%; padding: 16px 16px 12px; }
  .card h2 { font-size: var(--fs-18); letter-spacing: var(--tr-18); }
  .card dl { grid-template-columns: 5.5rem 1fr; }
  .legend .wave-key { display: none; } /* no hover on touch, and it clips at 390 px */
  .chat-panel { right: 8px; left: 8px; width: auto; bottom: 64px; }
  .sos { top: 8px; }
  /* a bottom sheet, like the card, so the numbers sit under the thumb */
  .sos-panel { top: auto; bottom: 8px; width: calc(100% - 16px); max-height: calc(100% - 56px); }
  .footer { padding: 12px 16px 16px; }
  /* a 10 px plus on a 32 px control went unnoticed on a phone (#68): a 44 px target and a filled badge */
  .folds { gap: 8px; }
  .footer .fold { min-height: 44px; padding: 0 14px 0 10px; gap: 8px; font-size: var(--fs-15); letter-spacing: var(--tr-15); }
  .fold .pm { width: 20px; height: 20px; border-radius: 50%; background: var(--accent); color: var(--bg); }
  .fold .pm::before, .fold .pm::after { left: 5px; top: 9px; }
  .footer .fold.soon .pm { background: var(--muted); }
  .about { padding: 40px 16px 72px; }
  .about-body h2 { margin-top: 56px; font-size: var(--fs-24); letter-spacing: var(--tr-24); }
  .about-body .lede { font-size: var(--fs-19); letter-spacing: var(--tr-19); }
}
/* the smallest phones: "tomorrow" still has to fit beside "today" */
@media (max-width: 359px) {
  .controls { gap: 4px; }
  .controls > button { width: 32px; }
  .controls .segmented button { padding: 0 2px; font-size: var(--fs-12); letter-spacing: var(--tr-12); }
}
