/* Project Goals. Tokens first; dark values follow localsite's body.dark,
   a data-theme stamp, or the OS setting when localsite isn't loaded. */

.goals {
  --surface: #fcfcfb;
  --plane: #f9f9f7;
  --ink: #0b0b0b;
  --ink-2: #52514e;
  --muted: #6f6e69;
  --grid: #e1e0d9;
  --axis: #c3c2b7;
  --border: rgba(11, 11, 11, 0.10);
  --accent: #2a78d6;
  --accent-ink: #1c5cab;
  --accent-wash: rgba(42, 120, 214, 0.10);
  --series-1: #2a78d6;
  --series-2: #eb6834;
  --series-3: #1baf7a;
  /* hbar's inside option: a label over its bar and gray track. --bar-fill-alt is a burgundy
     for a second chart that shouldn't read as the first (Quality), and --bar-fill-green a
     jade green for a third (Analytics), each as muted as the blue. */
  --bar-label: var(--ink);
  --bar-fill: #a9cbf2;
  --bar-fill-alt: #dcaab7;
  --bar-fill-green: #a3d5b9;
  --bar-track: #e2e1db;
  --warn: #fab219;
  --critical: #d03b3b;
  --good: #0ca30c;
  --radius: 12px;
  --gap: 16px;
  --tab-hover: #000;
  color-scheme: light;
  background: transparent; /* the page's own background shows (view=center) */
  color: var(--ink);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", sans-serif;
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 16px 48px;
}
body.dark .goals, :root[data-theme="dark"] .goals {
  --surface: #1a1a19;
  --plane: #0d0d0d;
  --ink: #f0efec;
  --ink-2: #c3c2b7;
  --muted: #a3a29b;
  --grid: #2c2c2a;
  --axis: #383835;
  --border: rgba(255, 255, 255, 0.10);
  --accent: #3987e5;
  --accent-ink: #86b6ef;
  --accent-wash: rgba(57, 135, 229, 0.16);
  --series-1: #3987e5;
  --series-2: #d95926;
  --series-3: #199e70;
  --bar-label: #fff;
  --bar-fill: var(--series-1);
  --bar-fill-alt: #8f2442;
  --bar-fill-green: #2a8c61;
  --bar-track: #6e6e73;
  --tab-hover: #fff;
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body.standalone .goals {
    --surface: #1a1a19; --plane: #0d0d0d; --ink: #f0efec; --ink-2: #c3c2b7; --muted: #a3a29b;
    --grid: #2c2c2a; --axis: #383835; --border: rgba(255, 255, 255, 0.10);
    --accent: #3987e5; --accent-ink: #86b6ef; --accent-wash: rgba(57, 135, 229, 0.16);
    --series-1: #3987e5; --series-2: #d95926; --series-3: #199e70;
    --bar-label: #fff; --bar-fill: var(--series-1); --bar-fill-alt: #8f2442; --bar-fill-green: #2a8c61; --bar-track: #6e6e73;
    --tab-hover: #fff;
    color-scheme: dark;
  }
}
body.standalone { margin: 0; background: #f9f9f7; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) body.standalone { background: #0d0d0d; } }

.goals * { box-sizing: border-box; }
/* Links never break across lines ("Our Data Sources", citations), except in source notes (.goals-note). */
.goals a, .goals-credit a { white-space: nowrap; }
.goals a { color: var(--accent-ink); }
.goals-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

.goals-topinfo {
  margin: 12px 0 0; padding: 8px 12px; border-radius: 8px; font-size: 14px;
  background: var(--surface); border: 1px solid var(--border); color: var(--ink-2);
}
.goals-topinfo strong { color: var(--ink); }

.goals-hero { --pad-top: 40px; --pad-x: 0px; padding: var(--pad-top) var(--pad-x) 24px; }
.goals-eyebrow { margin: 0; color: var(--muted); font-size: 13px; letter-spacing: .08em; text-transform: uppercase; }
.goals-hero h1 { margin: 4px 0 8px; font-size: clamp(36px, 6vw, 56px); line-height: 1.05; letter-spacing: -0.02em; }
.goals-lede { margin: 0 0 20px; max-width: 62ch; color: var(--ink-2); font-size: 18px; }

.goals-ask {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px; box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}
.goals-ask textarea, .goals-console textarea {
  width: 100%; border: 0; resize: vertical; background: transparent; color: var(--ink);
  font: inherit; font-size: 17px; outline: none; min-height: 52px;
}
.goals-ask-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; border-top: 1px solid var(--grid); padding-top: 10px; }
.goals input, .goals select {
  font: inherit; font-size: 15px; color: var(--ink); background: var(--plane);
  border: 1px solid var(--border); border-radius: 8px; padding: 7px 10px;
}
.goals-ask-row input { width: 6.5em; }
/* Category dropdown: a drawn down arrow in place of the native one, which some
   browsers drop once the select has a background. */
#askCategory {
  appearance: none; -webkit-appearance: none; cursor: pointer; padding-right: 30px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%), linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-position: calc(100% - 16px) 55%, calc(100% - 11px) 55%;
  background-size: 5px 5px; background-repeat: no-repeat;
}
#askCategory:hover { border-color: var(--accent); }
.goals-btn {
  font: inherit; font-size: 15px; font-weight: 600; cursor: pointer;
  background: var(--accent); color: #fff; border: 0; border-radius: 8px; padding: 8px 16px;
}
.goals-btn:hover { filter: brightness(1.08); }
.goals-btn:focus-visible, .goals button:focus-visible, .goals select:focus-visible, .goals input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.goals-btn-ghost { background: transparent; color: var(--accent-ink); border: 1px solid var(--border); }
.goals-ask-row .goals-btn:first-of-type { margin-left: auto; }

.goals-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.goals-chips button {
  font: inherit; font-size: 14px; cursor: pointer; color: var(--ink-2);
  background: transparent; border: 1px solid var(--border); border-radius: 999px; padding: 4px 12px;
}
.goals-chips button:hover { background: var(--accent-wash); color: var(--ink); }

/* Services to search, under the lede: the 10 featured checkboxes, any others checked, then
   "More services", which opens the catalog by audience and category (goals.js). */
.goals-picks { border: 0; margin: -8px 0 16px; padding: 0; min-width: 0; }
/* Each checkbox takes an equal flex column (5 a row, fewer on phones), so the boxes line up. */
.goals-picks-row { --pick-cols: 5; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; font-size: 15px; }
.goals-picks-row .goals-pick { flex: 0 0 calc((100% - (var(--pick-cols) - 1) * 12px) / var(--pick-cols)); min-width: 0; }
@media (max-width: 640px) { .goals-picks-row { --pick-cols: 3; } }
@media (max-width: 420px) { .goals-picks-row { --pick-cols: 2; } }
.goals-picks-extras { display: contents; }
/* The box sits beside the first line of its name. */
.goals-pick { display: inline-flex; align-items: flex-start; gap: 6px; cursor: pointer; color: var(--ink-2); }
.goals-pick:hover { color: var(--ink); }
/* [type] outranks localsite's map-display.css, which scales every checkbox and adds a right margin. */
.goals-pick input[type="checkbox"] {
  flex: none; margin: calc((1lh - 16px) / 2) 0 0; padding: 0; width: 16px; height: 16px; transform: none;
  accent-color: var(--accent); cursor: inherit;
}
.goals-pick-off { cursor: default; opacity: 0.62; }
.goals-pick-off:hover { color: var(--ink-2); }
.goals-state {
  font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
  border: 1px solid var(--border); border-radius: 999px; padding: 0 6px; line-height: 16px;
}
.goals-more-link {
  font: inherit; font-size: 15px; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--accent-ink); text-decoration: underline; text-underline-offset: 3px;
}
.goals-more-link[aria-expanded="true"] { font-weight: 600; }
/* The Planned toggle, at the far right of More services' line. */
.goals-picks-planned { margin-left: auto; }
.goals-picks-more {
  margin-top: 12px; padding: 12px 14px; max-height: 60vh; overflow: auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
}
.goals-picks-done { margin: 12px 0 0; }
.goals-audiences { display: flex; flex-wrap: wrap; gap: 6px; }
.goals-audiences button {
  font: inherit; font-size: 13px; cursor: pointer; color: var(--ink-2);
  background: transparent; border: 1px solid var(--border); border-radius: 999px; padding: 3px 11px;
}
.goals-audiences button:hover { background: var(--accent-wash); color: var(--ink); }
.goals-audiences button[aria-pressed="true"] { background: var(--accent-wash); border-color: var(--accent); color: var(--ink); font-weight: 600; }
/* The Data tab's audiences, then its Details and Planned toggles at the far right. */
.goals-catalog-bar { display: flex; gap: 6px; align-items: flex-start; }
.goals-catalog-bar > .goals-audiences:last-child { margin-left: auto; flex: none; }
.goals-catalog-count { margin: 8px 0 10px; font-size: 13px; color: var(--muted); }
/* Columns rather than a grid, so short categories stack under long ones. */
.goals-catalog-grid { columns: 220px; column-gap: 24px; }
.goals-catalog-full { columns: 300px; }
.goals-catgroup { break-inside: avoid; padding-bottom: 14px; }
.goals-catgroup h4 { margin: 0 0 4px; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.goals-catgroup ul { list-style: none; margin: 0; padding: 0; }
.goals-catgroup li { margin: 4px 0; font-size: 14px; }
/* On the Data tab, a service's summary and publisher hang under its name: the item is indented
   by the box and its gap (16px + 6px), and the box is pulled back into that indent. */
.goals-catalog-full .goals-catgroup li { margin: 0 0 8px; padding-left: 22px; }
.goals-catalog-full .goals-pick { display: flex; margin-left: -22px; color: var(--ink); font-weight: 550; }
.goals-svc-sum, .goals-svc-pub { font-size: 13px; color: var(--ink-2); }
.goals-catalog-full .goals-svc-sum { display: block; }
.goals-catalog-full .goals-svc-pub { display: block; white-space: normal; }
.goals-sources-head { margin: 28px 0 4px; font-size: 18px; }

.goals-results { margin: 8px 0 32px; }
.goals-safety {
  border-left: 4px solid var(--critical); background: var(--surface); border-radius: 8px;
  padding: 12px 16px; margin-bottom: 16px;
}
.goals-safety strong { display: block; margin-bottom: 4px; }
.goals-answer { white-space: pre-wrap; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; }
.goals-answer:empty { display: none; }
.goals-flagsum { color: var(--ink-2); font-size: 14px; margin: 12px 0; }
.goals-cards { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.goals-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px 16px; display: flex; flex-direction: column; gap: 6px;
}
.goals-card h3 { margin: 0; font-size: 17px; line-height: 1.3; }
.goals-card .goals-meta { color: var(--ink-2); font-size: 14px; }
.goals-card .goals-cat { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
.goals-card .goals-flags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto; padding-top: 6px; }
.goals-flag {
  font-size: 12px; border-radius: 999px; padding: 2px 8px; border: 1px solid var(--border);
  color: var(--ink-2); display: inline-flex; align-items: center; gap: 4px;
}
.goals-flag::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--warn); }
.goals-flag.ok::before { background: var(--good); }
.goals-card .goals-actions { font-size: 13px; }
.goals-card .goals-actions button { font: inherit; background: none; border: 0; color: var(--accent-ink); cursor: pointer; padding: 0; text-decoration: underline; }
.goals-cite { color: var(--muted); font-size: 13px; }
.goals-card .goals-detail { font-size: 13px; }
/* A section per checked service after the directory's answer and cards. */
.goals-svc-results { display: grid; gap: 24px; margin-top: 24px; }
.goals-svc-results:empty { display: none; }
.goals-svc h3 { margin: 0 0 2px; font-size: 19px; }
.goals-svc-note { margin: 0 0 10px; font-size: 14px; color: var(--ink-2); }
.goals-svc-err .goals-svc-note { border-left: 3px solid var(--warn); padding-left: 10px; }
.goals-svc .goals-cite { margin: 8px 0 0; }

/* Agents tab: tools by purpose, each name loading the tool into "Try a tool". */
.goals-toolgroups { display: grid; gap: 12px 24px; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.goals-toolgroup h4 { margin: 0 0 6px; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.goals-toolgroup p { margin: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.goals-toolname {
  font: 13px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; cursor: pointer; color: var(--accent-ink);
  background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 2px 8px;
}
.goals-toolname:hover { border-color: var(--accent); }

.goals-tabs {
  display: flex; gap: 4px; border-bottom: 1px solid var(--grid);
  margin: 16px 0 0;
}
/* The left column: the tabs, cut off under the arrow when they don't fit. It
   reaches 1px down over the bar's bottom line, for the selected tab's underline. */
.goals-tabs-list { display: flex; gap: 4px; flex: 1 1 auto; min-width: 0; overflow: hidden; margin-bottom: -1px; }
.goals-tabs button {
  font: inherit; font-size: 15px; white-space: nowrap; cursor: pointer; color: var(--ink-2);
  background: none; border: 0; border-bottom: 2px solid transparent; padding: 10px 12px; margin-bottom: -1px;
}
.goals-tabs-list button { flex: none; margin-bottom: 0; }
.goals-tabs button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); font-weight: 600; }
.goals-tabs button[data-tab]:hover { color: var(--tab-hover); }
/* "More", after the tabs that fit, opens every tab as a list covering the window below the
   header (goals.js initMoreTabs). It's underlined while the selected tab is one it hides. */
.goals-tabs-list > .goals-tab-over { display: none; }
.goals-tabs .goals-tabs-more:hover { color: var(--tab-hover); }
.goals-tabs .goals-tabs-more.goals-more-current { color: var(--ink); border-bottom-color: var(--accent); font-weight: 600; }
.goals-more-menu {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1000; display: flex; flex-direction: column; overflow-y: auto;
  border-top: 1px solid var(--grid);
  /* --surface is see-through over the photo (goals-view-hero), so it's laid over the photo's solid page color. */
  background: linear-gradient(var(--surface), var(--surface)), var(--hero-page, var(--surface));
}
.goals-more-menu[hidden] { display: none; }
.goals-more-head { display: flex; align-items: center; justify-content: space-between; padding: 4px 4px 4px 16px; margin-bottom: 8px; border-bottom: 1px solid var(--grid); font-size: 13px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.goals-more-close { font: inherit; font-size: 24px; line-height: 1; cursor: pointer; color: var(--ink-2); background: none; border: 0; padding: 8px 12px; }
.goals-more-close:hover, .goals-more-close:focus-visible { color: var(--ink); }
/* Each tab a rounded tile, apart from the next; the selected one tinted and outlined in the accent. */
.goals-more-item {
  flex: none; font: inherit; font-size: 17px; text-align: left; cursor: pointer; color: var(--ink-2);
  margin: 0 12px 8px; padding: 15px 18px; border: 1px solid var(--border); border-radius: 14px;
  background: color-mix(in srgb, var(--ink) 4%, transparent);
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.goals-more-item:hover, .goals-more-item:focus-visible { color: var(--ink); background: var(--accent-wash); border-color: var(--accent); }
.goals-more-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.goals-more-item[aria-current="true"] { color: var(--ink); font-weight: 600; background: var(--accent-wash); border-color: var(--accent); }
/* Narrow windows, column down (goals.js syncPagesButton): the tabs would cover the voice widget's
   controls, so they hide and a menu button (vertical dots) at the lower left, in the controls' glass
   style and size, opens the list instead. */
.goals-tabs-paged #goalsMain > .goals-tabs { visibility: hidden; }
.goals-pages-btn {
  position: fixed; left: 10px; bottom: 16px; z-index: 3; display: grid; place-items: center; width: 38px; height: 38px; padding: 0;
  cursor: pointer; color: #f4f6fb; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(10, 12, 20, 0.5); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.goals-pages-btn:hover { background: rgba(10, 12, 20, 0.7); }
.goals-pages-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.goals-pages-btn[hidden] { display: none; }
.goals-pages-btn svg { width: 20px; height: 20px; fill: currentColor; } /* A vertical three-dot menu icon */
/* Short tab titles while the tabs bar is under 800px wide: Quality,
   without its .goals-tab-extra word. Under 500px also Plan,
   without its .goals-tab-extra-sm word. Under 600px, less space
   between the tabs. */
.goals-tabs { container-type: inline-size; }
@container (max-width: 799px) { .goals-tab-extra { display: none; } }
@container (max-width: 599px) { .goals-tabs button { padding-left: 7px; padding-right: 7px; } }
@container (max-width: 499px) { .goals-tab-extra-sm { display: none; } }
/* Top 10px of the tabs bar: drags #goalsMain down the window (goals.js), or up
   on the Goals tab (goals-main-raised), all but the top info line, which stays put. The strip itself isn't drawn. The
   page clips the dragged column at its bottom edge, so it slides out of view. */
.goals-tabs { position: relative; }
.goals-grip { position: absolute; top: 0; left: 0; right: 0; height: 10px; z-index: 1; cursor: ns-resize; touch-action: none; }
/* Triangle at the far right of the tabs bar: points up while the column is down
   (raise it), turned to point down once it's up (dock it). */
.goals-tabs .goals-main-arrow { flex: none; padding: 10px 13px; font-size: 12px; line-height: 1; color: var(--ink-2); border-bottom-color: transparent; opacity: 0.4; transition: opacity 0.15s; }
.goals-tabs .goals-main-arrow:hover, .goals-tabs .goals-main-arrow:focus-visible { color: var(--ink); opacity: 1; }
/* A wide triangle (goals.js), centered in a box one line tall. */
.goals-main-arrow > span { display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 12px; vertical-align: middle; transition: transform 0.25s ease; }
.goals-main-arrow svg { display: block; width: 15px; height: 8px; fill: currentColor; }
.goals:not(.goals-main-dropped) .goals-main-arrow > span { transform: rotate(180deg); }
.goals-main-dropped #goalsMain > :not(.goals-topinfo),
.goals-main-raised #goalsMain > :not(.goals-topinfo) { transform: translateY(var(--main-drop, 0px)); }
#goalsMain.goals-main-settle > :not(.goals-topinfo) { transition: transform 0.25s ease; }
.goals-main-dropped { overflow-y: clip; }
/* While the column is down, the bottom holder (Nearby tab cards) hides too. */
.goals-main-dropped #goalsBottom { display: none; }
/* Goals is the first tab (no tab= in the hash): the hero, ask results and
   top info line show only there. */
#goalsMain:not([data-tab="goals"]) > .goals-hero,
#goalsMain:not([data-tab="goals"]) > .goals-results,
#goalsMain:not([data-tab="goals"]) > .goals-topinfo { display: none; }
.goals-panel { padding: 24px 0; }
/* The plan (PLAN.md, loaded into #planDiv) gets the panels' padding alone, not
   localsite's .contentpadding too, and its lists run flush left without bullets. */
.goals-panel[data-panel="plan"] > .contentpadding { padding: 0; }
#planDiv ul { list-style: none; padding-left: 0; margin-left: 0; }
/* Task-list boxes ("- [x]", localsite's loadMarkdown): as on GitHub, the box hangs to the
   left and wrapped lines line up with the text. Showdown's inline margin assumes a bullet
   indent, which these flush lists don't have. */
#planDiv .task-list-item { padding-left: 1.35em; }
#planDiv .task-list-item input { margin: 0 0.5em 0.2em -1.35em !important; }
.goals-panel h2 { margin: 0 0 4px; font-size: 26px; letter-spacing: -0.01em; }
.goals-sub { margin: 0 0 20px; color: var(--ink-2); max-width: 75ch; }

.goals-objectives { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.goals-objective { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 18px; }
/* Objective number: white on a charcoal circle. Not localsite's .num class,
   which floats left in base.css. */
.goals-objective-num {
  position: relative; display: flex; align-items: center; justify-content: center;
  flex: none; width: 32px; height: 32px; padding: 0; border-radius: 50%;
  background: #3a3c40; color: #fff; text-align: center;
  font-size: 17px; font-weight: 650; line-height: 32px; font-variant-numeric: tabular-nums;
}
/* The number circle sits left of the card title. */
.goals-objective-head { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.goals-objective h3 { margin: 0; font-size: 18px; }
.goals-objective p { margin: 0 0 10px; color: var(--ink-2); font-size: 15px; }
.goals-objective button { font: inherit; font-size: 14px; background: none; border: 0; padding: 0; color: var(--accent-ink); cursor: pointer; }

/* Toy Data / Live Data dropdown, in the upper right of each panel that has
   both sources. Positioned rather than floated, so the h2 and intro below
   keep their full width and run under it. When the panel is under 480px wide
   it moves to the left, above the title, so it doesn't cover it. */
.goals-hero, .goals-split { position: relative; container-type: inline-size; }
.goals-source { position: absolute; top: 0; right: 0; z-index: 1; font-size: 14px; }
.goals-hero > .goals-source { top: var(--pad-top); right: var(--pad-x); }
@container (max-width: 479px) {
  .goals-hero > .goals-source, .goals-split > .goals-source { position: relative; inset: auto; display: block; width: fit-content; margin-bottom: 4px; }
}
.goals-source select {
  appearance: none; -webkit-appearance: none; font: inherit; cursor: pointer;
  color: var(--ink); background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px; padding: 5px 32px 5px 12px;
}
.goals-source select:hover { border-color: var(--accent); }
.goals-source select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.goals-source::after {
  content: ""; position: absolute; right: 13px; top: 50%; width: 6px; height: 6px; pointer-events: none;
  border-right: 2px solid var(--ink-2); border-bottom: 2px solid var(--ink-2); transform: translateY(-70%) rotate(45deg);
}
.goals-filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-bottom: 16px; font-size: 14px; color: var(--ink-2); }
.goals-filters label { display: flex; gap: 6px; align-items: center; }
.goals-filters label[hidden] { display: none; }
/* Each panel (every tab but Goals) has a main column and a side column of
   figures. goals.js moves the active panel's side column into #goalsAside, to
   the right of #goalsMain, on windows wider than 900px. A side column marked
   goals-side-bottom (the Community Data cards) moves into #goalsBottom, across the
   bottom, at any width. Gaps, not margins, space the columns and figures. */
.goals { display: flex; flex-direction: column; row-gap: var(--gap); }
/* At least the window's height below the localsite header (--fullscreen-height),
   so the footer starts below the fold on every tab and view. --header-h (set in
   goals.js) is where #goalsPage starts, below the header and the search filters.
   It replaces localsite's --fullscreen-height (base.css), which measures where
   #fullscreen starts, now the top of the window. */
body { --fullscreen-height: calc(100vh - var(--header-h, var(--headerbar-offset, 0px))); }
.goals { box-sizing: border-box; min-height: var(--fullscreen-height); }
/* #fullscreen: fixed over the whole window like the photos (.goals-bg), so it
   stays in place as the page scrolls, behind the header and search filters.
   It holds the photos, the Earth map once .showEarth opens it (localsite's
   placeEarthDisplay()) and the play button (base.css places both). It has no
   z-index of its own, so the photos stay beneath the page (z-index: -1) and the
   map and button above it, as in the page's flow. The page's search filters
   (#filterFieldsHolder, until they're fixed with their own z-index) are raised
   above the map. While the map or another layer covers the photos
   (goals-hero-covered, goals.js) they stop changing. view=center shows it only
   while it's covered. */
html #fullscreen { position: fixed; inset: 0; height: auto; box-sizing: border-box; }
/* The map's stack of circles in the upper right (zoom + and -, the close-X and the scroll circle, placed 22px down by
   base.css) goes 22px below where #goalsPage starts (--header-h), since #fullscreen's top is behind the header. */
html #fullscreen > #mainEarthDisplay .earth-zoom-controls { top: calc(var(--header-h, 0px) + 22px) !important; }
#filterFieldsHolder:not(.filterFieldsHolderFixed) { position: relative; z-index: 3; }
/* While the map's date picker is open (localsite.js adds .earthDateOpen), #fullscreen is raised above
   #goalsPage, so the expanded controls show over the page's column. The search filters stay above it. */
html.earthDateOpen #fullscreen { z-index: 2; }
html:not(.goals-view-hero) #fullscreen:not(.goals-hero-covered) { display: none; }
/* The play button's look is in localsite/css/base.css, with its icon font, so
   it's left out without localsite (standalone). */
body.standalone #earthPlayPauseButton { display: none; }
/* The localsite footer (#main-footer, position: relative) slides up over the
   fixed #fullscreen at the page's bottom edge, where the page clips a lowered
   column. It's raised above the map, the play button (z-index 102, base.css)
   and the photo credit, so they're covered there too. */
#main-footer { z-index: 103; }
/* The Earth map filters (#mainEarthFilters) in #earthFilterCatch, after the tabs (goals.js). While they show
   there, the tabs' content hides, with no tab highlighted. The catch has no box of its own around the filters'. */
.goals-filters-caught #goalsMain > .goals-hero,
.goals-filters-caught #goalsMain > .goals-results,
.goals-filters-caught #goalsMain .goals-panel,
.goals-filters-caught #goalsAside,
.goals-filters-caught #goalsBottom { display: none; }
/* The voice widget's keys panel (.claude-voice-keys, engine/claude-voice.js) goes after #earthFilterCatch while it's
   open, and the tabs' content steps aside for it too. */
#goalsMain:has(> .claude-voice-keys) > .goals-hero,
#goalsMain:has(> .claude-voice-keys) > .goals-results,
#goalsMain:has(> .claude-voice-keys) .goals-panel,
.goals:has(.claude-voice-keys) #goalsAside,
.goals:has(.claude-voice-keys) #goalsBottom { display: none; }
html.goals-view-hero #goalsMain > #earthFilterCatch { padding: 0; background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
#earthFilterCatch > #mainEarthFilters { margin-top: 0; padding: 0 !important; } /* Over the inline padding for under the map */
/* The page's empty space lets clicks through to #fullscreen beneath (the map),
   while its columns and their contents take them. */
.goals, .goals-row, #goalsMain { pointer-events: none; }
.goals > :not(.goals-row), .goals-row > :not(#goalsMain), #goalsMain > * { pointer-events: auto; }
.goals-side { display: grid; gap: var(--gap); align-content: start; }
.goals-side[hidden] { display: none; }
/* Round icon buttons: the close X at a right panel's upper right, and the icon that brings a closed
   one back, right of the tab's Live Data choice (goals.js initSideToggles). The X shows only while
   the side column is in #goalsAside, to the right; a closed one stays hidden at home. */
.goals-circle-btn {
  display: inline-grid; place-items: center; width: 30px; height: 30px; padding: 0; cursor: pointer;
  color: var(--ink-2); background: var(--surface); border: 1px solid var(--border); border-radius: 50%;
}
.goals-circle-btn:hover { color: var(--ink); border-color: var(--accent); background: var(--accent-wash); }
.goals-circle-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.goals-circle-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.goals-circle-btn[hidden], .goals-side.goals-side-shut, .goals-side-close { display: none; }
#goalsAside > .goals-side { position: relative; }
#goalsAside > .goals-side > .goals-side-close { display: inline-grid; position: absolute; top: 10px; right: 10px; z-index: 2; }
/* A side column without boxes sits 16px down and 20px in from the aside's corner over the photo, so its X goes out to 10px from that corner. */
html.goals-view-hero #goalsAside > .goals-side-plain > .goals-side-close { top: -6px; right: -10px; }
.goals-split > .goals-side-open { position: absolute; top: 0; right: 0; z-index: 1; }
/* The open icon's circle is as tall as the Live Data choice beside it. */
.goals-circle-btn.goals-side-open { width: 34px; height: 34px; }
.goals-side-open svg { width: 18px; height: 18px; stroke-width: 1.1; }
.goals-split:has(> .goals-side-open:not([hidden])) > .goals-source { right: 42px; }
.goals-side > h3 { margin: 0; }
/* A side column without its own boxes (the "Try a tool" console) gets the
   panel's spacing back in #goalsAside. */
#goalsAside > .goals-side-plain { margin: 24px 0; }
html.goals-view-hero #goalsAside > .goals-side-plain { margin: 16px 20px; }
@media (min-width: 901px) {
  .goals-row { display: flex; align-items: flex-start; column-gap: 28px; }
  #goalsMain { flex: 3 1 0; min-width: 0; }
  /* --aside-top lines the aside up with the top of the active panel. */
  .goals-aside { flex: 2 1 0; min-width: 0; margin-top: var(--aside-top, 0px); padding: 0; }
}
.goals-stats { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); margin-bottom: 16px; }
/* 5 (or 9, 13...) stats would leave one alone on a row of 4: cap at 3 columns. */
.goals-stats:has(> :last-child:nth-child(4n+5)) { grid-template-columns: repeat(auto-fill, minmax(max(140px, calc((100% - 24px) / 3)), 1fr)); }
/* Exactly 4 stats: 2 columns of 2 rows. */
.goals-stats:has(> :last-child:nth-child(4)) { grid-template-columns: repeat(auto-fill, minmax(max(140px, calc((100% - 12px) / 2)), 1fr)); }
.goals-stats:empty { display: none; }
.goals-stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; }
.goals-stat .v { font-size: 26px; font-weight: 650; line-height: 1.1; }
.goals-stat .l { font-size: 13px; color: var(--ink-2); }
.goals-fig { margin: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; }
.goals-fig figcaption { font-weight: 600; font-size: 15px; margin-bottom: 8px; }
.goals-chart { width: 100%; min-height: 120px; }
.goals-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.goals-chart text { fill: var(--ink-2); font: 12px system-ui, -apple-system, "Segoe UI", sans-serif; }
.goals-chart .val { fill: var(--ink); font-variant-numeric: tabular-nums; }
/* A label over its bar, the bar and the gray track behind it (hbar's inside option):
   dark text on light colors, or white on darker ones in dark mode. */
.goals-chart text.in { fill: var(--bar-label); }
.goals-chart .mark.mark-in { fill: var(--bar-fill); }
#qualityChart { --bar-fill: var(--bar-fill-alt); }
#importanceChart { --bar-fill: var(--bar-fill-green); }
.goals-chart .rest { fill: var(--bar-track); }
.goals-chart .grid { stroke: var(--grid); stroke-width: 1; }
.goals-chart .base { stroke: var(--axis); stroke-width: 1; }
.goals-chart .mark { fill: var(--series-1); }
.goals-chart .mark-2 { fill: var(--series-2); }
.goals-chart .mark:hover, .goals-chart .mark:focus, .goals-chart .hit:hover + .mark { filter: brightness(1.15); outline: none; }
.goals-chart .dot { fill: var(--series-1); stroke: var(--surface); stroke-width: 2; }
.goals-chart .dot.dim { fill: var(--axis); }
.goals-chart .whisker { stroke: var(--series-1); stroke-width: 2; stroke-linecap: round; }
.goals-chart .ref { stroke: var(--muted); stroke-width: 1; stroke-dasharray: 0; }
.goals-table-toggle { font: inherit; font-size: 13px; background: none; border: 0; color: var(--accent-ink); cursor: pointer; padding: 6px 0 0; }
.goals-table { width: 100%; border-collapse: collapse; font-size: 13px; margin-top: 8px; font-variant-numeric: tabular-nums; }
.goals-table th, .goals-table td { text-align: left; padding: 4px 6px; border-bottom: 1px solid var(--grid); }
.goals-table td.n { text-align: right; }
/* A "Source:" link (a long file path) wraps, over .goals a's nowrap, rather than widening its figure. */
.goals-note { color: var(--ink-2); font-size: 14px; margin: 8px 0 0; overflow-wrap: anywhere; }
.goals-note a { white-space: normal; }
/* A "Display ..." button for an outside API, and the URLs it calls. */
.goals-display:not(:empty) { margin-top: 12px; }
.goals-display-urls { font-size: 13px; color: var(--muted); }
.goals-defs { margin-top: 16px; font-size: 14px; color: var(--ink-2); }
.goals-defs summary { cursor: pointer; }
.goals-defs dt { font-weight: 600; color: var(--ink); margin-top: 8px; }
.goals-defs dd { margin: 0; }

.goals-code pre, .goals-out {
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 12px;
  overflow-x: auto; font: 13px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--ink);
}
.goals-code p { margin: 12px 0 4px; font-size: 14px; color: var(--ink-2); }
.goals-console textarea { font: 13px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; border: 1px solid var(--border); border-radius: 8px; padding: 10px; background: var(--surface); min-height: 80px; }
.goals-out { max-height: 420px; overflow: auto; white-space: pre-wrap; }
.goals-out:empty { display: none; }

/* Data sources under the Community Data heading: the first 3, then a
   "More Data Sources" link for the rest. */
.goals-sources { margin: 8px 0 0; font-size: 14px; color: var(--ink-2); }
.goals-sources-more { margin: 8px 0 0; padding: 0; }
.goals-sources ul { margin: 0; padding-left: 20px; }
.goals-sources li { margin: 4px 0; }

.goals-tip {
  position: fixed; z-index: 1000; pointer-events: none; max-width: 260px;
  background: #0b0b0b; color: #f0efec; border-radius: 8px; padding: 8px 10px; font: 13px/1.4 system-ui, sans-serif;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .2);
}
.goals-tip strong { display: block; font-size: 15px; }
body.dark .goals-tip { background: #f0efec; color: #0b0b0b; }

@media (max-width: 560px) {
  .goals-hero { --pad-top: 24px; }
  .goals-ask-row .goals-btn:first-of-type { margin-left: 0; }
  .goals-ask-row input, .goals-ask-row select { flex: 1; }
}

/* view=hero (default): photos fill the page behind the content, which sits on
   the left half over translucent panels. #view=center is the centered layout
   above. Light mode washes the photos with white; dark mode (body.dark, a
   data-theme stamp, or the OS setting when localsite isn't loaded) darkens them. */
html.goals-view-hero body {
  /* Light: the greyscale photo, mostly opaque over a mid grey, with a thin
     charcoal wash to darken it further. */
  --hero-page: #b3b5b5;
  --hero-img-filter: grayscale(1);
  --hero-img-opacity: 0.85;
  --hero-blend: normal;
  --hero-wash: rgba(24, 26, 30, 0.14);
  --hero-wash-narrow: rgba(24, 26, 30, 0.16);
  --hero-box: rgba(255, 255, 255, 0.78);
  --hero-card: rgba(255, 255, 255, 0.85);
  --hero-box-shadow: 0 1px 4px rgba(11, 11, 11, 0.10);
  --hero-credit: rgba(255, 255, 255, 0.85);
  --hero-credit-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  background: transparent;
}
html.goals-view-hero body.dark, html.goals-view-hero[data-theme="dark"] body {
  --hero-page: #0b0d10;
  --hero-card: initial; /* dark cards keep --surface */
  --hero-img-filter: none;
  --hero-img-opacity: 1;
  --hero-blend: normal;
  --hero-wash: linear-gradient(90deg, rgba(8, 10, 14, 0.88) 0%, rgba(8, 10, 14, 0.74) 42%, rgba(8, 10, 14, 0.28) 70%, rgba(8, 10, 14, 0.42) 100%);
  --hero-wash-narrow: rgba(8, 10, 14, 0.78);
  --aurora-blend: screen;
  --aurora-opacity: 0.85;
  --hero-box: rgba(10, 12, 16, 0.52);
  --hero-box-shadow: none;
  --hero-credit: rgba(255, 255, 255, 0.72);
  --hero-credit-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}
@media (prefers-color-scheme: dark) {
  html.goals-view-hero:not([data-theme="light"]) body.standalone {
    --hero-page: #0b0d10;
    --hero-card: initial; /* dark cards keep --surface */
    --hero-img-filter: none;
    --hero-img-opacity: 1;
    --hero-blend: normal;
    --hero-wash: linear-gradient(90deg, rgba(8, 10, 14, 0.88) 0%, rgba(8, 10, 14, 0.74) 42%, rgba(8, 10, 14, 0.28) 70%, rgba(8, 10, 14, 0.42) 100%);
    --hero-wash-narrow: rgba(8, 10, 14, 0.78);
    --aurora-blend: screen;
    --aurora-opacity: 0.85;
    --hero-box: rgba(10, 12, 16, 0.52);
    --hero-box-shadow: none;
    --hero-credit: rgba(255, 255, 255, 0.72);
    --hero-credit-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  }
}
.goals-bg, .goals-credit { display: none; }
html.goals-view-hero { background: #b3b5b5; }
html.goals-view-hero:has(> body.dark), html.goals-view-hero[data-theme="dark"] { background: #0b0d10; }
html.goals-view-hero .goals-bg {
  display: block; position: fixed; inset: 0; z-index: -1; overflow: hidden; isolation: isolate; background: var(--hero-page);
}
.goals-bg img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 1.6s ease; filter: var(--hero-img-filter, none);
}
.goals-bg img.on { opacity: var(--hero-img-opacity, 1); }
.goals-bg.goals-bg-instant img { transition: none; } /* The first photo (goals.js) */
/* The layer over the photo: a thin charcoal wash in light mode, a dark
   gradient (strongest behind the text on the left) in dark mode. */
.goals-bg::after { content: ""; position: absolute; inset: 0; background: var(--hero-wash); mix-blend-mode: var(--hero-blend, normal); }
@media (prefers-reduced-motion: reduce) { .goals-bg img { transition: none; } }
/* hero_atmosphere: true in the event's YAML (goals-bg-atmosphere, goals.js): three points of focus
   oscillate over the photo, each on its own slow path (--f1x/--f1y ... on .goals-bg). Around each one
   the photo is sharp and lit with a color that shifts slowly through teal, blue, violet, rose and mint
   (--f1c ...); elsewhere it's softly blurred and dimmed (.goals-focus) and stays grey in light mode.
   The color tints the greyscale photo in light mode and glows over it in dark mode. Both layers sit
   under the wash, so the text side stays as readable. Paused while the Earth map covers them. */
@property --f1x { syntax: "<percentage>"; inherits: true; initial-value: 72%; }
@property --f1y { syntax: "<percentage>"; inherits: true; initial-value: 30%; }
@property --f2x { syntax: "<percentage>"; inherits: true; initial-value: 58%; }
@property --f2y { syntax: "<percentage>"; inherits: true; initial-value: 74%; }
@property --f3x { syntax: "<percentage>"; inherits: true; initial-value: 22%; }
@property --f3y { syntax: "<percentage>"; inherits: true; initial-value: 52%; }
@property --f1c { syntax: "<color>"; inherits: true; initial-value: #2fbfc4; }
@property --f2c { syntax: "<color>"; inherits: true; initial-value: #9a74ff; }
@property --f3c { syntax: "<color>"; inherits: true; initial-value: #ff86b0; }
.goals-focus, .goals-aurora { display: none; }
.goals-bg-atmosphere {
  animation: goals-focus-1 41s ease-in-out infinite alternate, goals-focus-2 53s ease-in-out -20s infinite alternate,
    goals-focus-3 67s ease-in-out -35s infinite alternate, goals-focus-hues 72s linear infinite;
}
.goals-bg-atmosphere :is(.goals-focus, .goals-aurora) { display: block; position: absolute; inset: 0; pointer-events: none; }
/* Clear inside each point's circle, veiled outside all three (the masks multiply). */
.goals-bg-atmosphere .goals-focus {
  -webkit-backdrop-filter: blur(3px) brightness(0.86);
  backdrop-filter: blur(3px) brightness(0.86);
  --hole: transparent 0%, transparent 35%, #000 100%;
  -webkit-mask-image: radial-gradient(circle 26vmax at var(--f1x) var(--f1y), var(--hole)), radial-gradient(circle 22vmax at var(--f2x) var(--f2y), var(--hole)), radial-gradient(circle 18vmax at var(--f3x) var(--f3y), var(--hole));
  mask-image: radial-gradient(circle 26vmax at var(--f1x) var(--f1y), var(--hole)), radial-gradient(circle 22vmax at var(--f2x) var(--f2y), var(--hole)), radial-gradient(circle 18vmax at var(--f3x) var(--f3y), var(--hole));
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}
.goals-bg-atmosphere .goals-aurora {
  mix-blend-mode: var(--aurora-blend, color); opacity: var(--aurora-opacity, 0.8);
  background:
    radial-gradient(circle 30vmax at var(--f1x) var(--f1y), var(--f1c), color-mix(in srgb, var(--f1c) 40%, transparent) 45%, transparent 100%),
    radial-gradient(circle 26vmax at var(--f2x) var(--f2y), var(--f2c), color-mix(in srgb, var(--f2c) 40%, transparent) 45%, transparent 100%),
    radial-gradient(circle 22vmax at var(--f3x) var(--f3y), var(--f3c), color-mix(in srgb, var(--f3c) 40%, transparent) 45%, transparent 100%);
}
/* Mostly over the right side, where the photo shows beside the panels. */
@keyframes goals-focus-1 {
  0% { --f1x: 72%; --f1y: 30%; } 30% { --f1x: 86%; --f1y: 52%; } 65% { --f1x: 64%; --f1y: 66%; } 100% { --f1x: 82%; --f1y: 18%; }
}
@keyframes goals-focus-2 {
  0% { --f2x: 58%; --f2y: 74%; } 35% { --f2x: 76%; --f2y: 84%; } 70% { --f2x: 92%; --f2y: 62%; } 100% { --f2x: 66%; --f2y: 42%; }
}
@keyframes goals-focus-3 {
  0% { --f3x: 22%; --f3y: 52%; } 40% { --f3x: 48%; --f3y: 20%; } 75% { --f3x: 38%; --f3y: 82%; } 100% { --f3x: 54%; --f3y: 56%; }
}
@keyframes goals-focus-hues {
  0%, 100% { --f1c: #2fbfc4; --f2c: #9a74ff; --f3c: #ff86b0; }
  20% { --f1c: #4f8dff; --f2c: #ff86b0; --f3c: #52d99a; }
  40% { --f1c: #9a74ff; --f2c: #52d99a; --f3c: #2fbfc4; }
  60% { --f1c: #ff86b0; --f2c: #2fbfc4; --f3c: #4f8dff; }
  80% { --f1c: #52d99a; --f2c: #4f8dff; --f3c: #9a74ff; }
}
#fullscreen.goals-hero-covered .goals-bg-atmosphere { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .goals-bg-atmosphere { animation: none; } }
/* The AI zone (goals.js placeZone): while the tabs sit at the window's bottom, a see-through circle
   centered over them (the left column), in the space above them, with one brief question in large type. Its two rings pulse slowly,
   one swelling and one rippling outward, while the words stay still. A slight dark wash inside keeps the
   white words readable on any photo. The ring's color and pace follow the voice widget: blue-teal and
   slow while waiting, mint while listening, violet while thinking, rose while Claude speaks. */
#goalsPage > .goals-ai-area {
  position: fixed; left: var(--zone-left, 0px); width: var(--zone-w, 100%); top: var(--zone-top, 0px); height: var(--zone-h, 0px); z-index: 1;
  display: flex; align-items: center; justify-content: center; pointer-events: none;
}
#goalsPage > .goals-ai-area[hidden] { display: none; }
.goals-ai-zone {
  --zone-ring: rgba(150, 215, 255, 0.75); --zone-glow: rgba(90, 170, 255, 0.35); --zone-pace: 6s;
  pointer-events: auto; position: relative; box-sizing: border-box;
  width: var(--zone-d, 400px); height: var(--zone-d, 400px); padding: 6%; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.7em;
  font: inherit; color: #fff; text-align: center; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: radial-gradient(circle, rgba(8, 14, 26, 0.42) 0%, rgba(8, 14, 26, 0.30) 55%, rgba(8, 14, 26, 0.12) 72%, rgba(255, 255, 255, 0.06) 100%);
  -webkit-backdrop-filter: blur(1.5px); backdrop-filter: blur(1.5px);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6), 0 0 18px rgba(0, 0, 0, 0.45);
}
.goals-ai-zone::before, .goals-ai-zone::after {
  content: ""; position: absolute; inset: -1px; border-radius: 50%; pointer-events: none;
  border: 2px solid var(--zone-ring);
  box-shadow: 0 0 40px 6px var(--zone-glow), inset 0 0 40px 4px var(--zone-glow);
  transition: border-color 1.2s ease, box-shadow 1.2s ease;
  animation: goals-zone-swell var(--zone-pace) ease-in-out infinite;
}
.goals-ai-zone::after { box-shadow: 0 0 24px 2px var(--zone-glow); animation-name: goals-zone-ripple; animation-timing-function: ease-out; }
.goals-ai-zone[data-state="listening"] { --zone-ring: rgba(140, 240, 200, 0.9); --zone-glow: rgba(70, 220, 160, 0.40); --zone-pace: 2.6s; }
.goals-ai-zone[data-state="thinking"] { --zone-ring: rgba(195, 170, 255, 0.85); --zone-glow: rgba(150, 115, 255, 0.38); --zone-pace: 3.4s; }
.goals-ai-zone[data-state="speaking"] { --zone-ring: rgba(255, 180, 205, 0.85); --zone-glow: rgba(255, 120, 170, 0.36); --zone-pace: 3s; }
.goals-ai-zone:focus-visible { outline: 3px solid #fff; outline-offset: 8px; }
/* While the voice widget's large words show, the circle shrinks to 40% and glides to a clear spot
   (goals.js setZoneSmall: --zone-dx and --zone-dy move it from its place), with just the start of
   the next question. */
.goals-ai-zone { transition: width 0.9s ease, height 0.9s ease, transform 1.2s ease; }
.goals-ai-zone.goals-ai-small {
  width: calc(var(--zone-d, 400px) * 0.4); height: calc(var(--zone-d, 400px) * 0.4); padding: 4%;
  transform: translate(var(--zone-dx, 0px), var(--zone-dy, 0px));
}
.goals-ai-small .goals-ai-question { font-size: 21px; }
.goals-ai-small .goals-ai-hint { display: none; }
@media (prefers-reduced-motion: reduce) { .goals-ai-zone { transition: none; } }
@keyframes goals-zone-swell { 0%, 100% { transform: scale(1); opacity: 0.7; } 50% { transform: scale(1.035); opacity: 1; } }
@keyframes goals-zone-ripple { 0% { transform: scale(1); opacity: 0.55; } 100% { transform: scale(1.16); opacity: 0; } }
.goals-ai-question { font-size: clamp(24px, calc(var(--zone-d, 400px) * 0.075), 34px); line-height: 1.22; font-weight: 600; letter-spacing: -0.005em; }
.goals-ai-hint { font-size: clamp(17px, calc(var(--zone-d, 400px) * 0.042), 20px); line-height: 1.3; color: rgba(255, 255, 255, 0.9); }
/* While the tabs are up and the AI zone can show (goals-ai-ready, goals.js placeZone), a small circle
   like it rings the up/down arrow, which moves the column down to bring the zone into view. The ring
   is drawn on the triangle's own box, so the two share a center in every browser (Safari places a
   button's positioned children differently). */
.goals-ai-ready:not(.goals-main-dropped) .goals-main-arrow { opacity: 0.85; }
.goals-ai-ready:not(.goals-main-dropped) .goals-main-arrow > span { position: relative; }
.goals-ai-ready:not(.goals-main-dropped) .goals-main-arrow > span::before,
.goals-ai-ready:not(.goals-main-dropped) .goals-main-arrow > span::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 40px; height: 40px; margin: -20px 0 0 -20px;
  border-radius: 50%; pointer-events: none; box-sizing: border-box;
  border: 1.5px solid rgba(75, 150, 235, 0.85);
  box-shadow: 0 0 10px 1px rgba(90, 170, 255, 0.40), inset 0 0 8px rgba(90, 170, 255, 0.30);
  animation: goals-zone-swell 6s ease-in-out infinite;
}
.goals-ai-ready:not(.goals-main-dropped) .goals-main-arrow > span::after { box-shadow: 0 0 6px rgba(90, 170, 255, 0.35); animation: goals-zone-ripple 6s ease-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .goals-ai-ready:not(.goals-main-dropped) .goals-main-arrow > span::before { animation: none; }
  .goals-ai-ready:not(.goals-main-dropped) .goals-main-arrow > span::after { display: none; }
}
/* Balanced lines, so neither leaves a word alone on its last line. */
.goals-ai-question, .goals-ai-hint { text-wrap: balance; }
.goals-ai-hint:empty { display: none; }
@media (prefers-reduced-motion: reduce) { .goals-ai-zone::before, .goals-ai-zone::after { animation: none; } .goals-ai-zone::after { display: none; } }
/* No z-index, so it paints in page order: over #fullscreen (the photos), which comes before it, and behind
   the page's panels in #goalsPage, which come after it. */
html.goals-view-hero .goals-credit {
  display: block; position: fixed; right: 12px; bottom: 8px; margin: 0;
  font: 12px/1.4 system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--hero-credit); text-shadow: var(--hero-credit-shadow);
}
html.goals-view-hero .goals-credit a { color: inherit; }
/* Above the voice widget's controls (12px up and 38px tall, initFullscreenVoice() in localsite.js) when they show,
   and hidden while they open anything above their row (captions, typing, settings, the play pill: data-open). */
html.goals-view-hero body:has(.claude-voice-ui) .goals-credit { bottom: 80px; }
html.goals-view-hero body:has(.claude-voice-ui[data-open]) .goals-credit { visibility: hidden; }
/* The voice widget's floating words (.claude-voice-words, engine/claude-voice.js) fill #fullscreen, behind the
   page, so they show only while the tabs are down (goals-main-dropped), not hidden behind the panels above. */
body:has(#goalsPage:not(.goals-main-dropped)) #fullscreen > .claude-voice-words { visibility: hidden; }
/* The Earth map, or another layer over the photos (goals-hero-covered, goals.js), covers the credit too. */
html.goals-view-hero #fullscreen.goals-hero-covered ~ .goals-credit { visibility: hidden; }
/* Hidden on narrow windows, where it would crowd the page. The credit is fixed to the window, and the body
   around it is the window's width, so a media query measures it. (A container query would need
   container-type on the body, which would pin the fixed photos and credit to it.) */
@media (max-width: 600px) { html.goals-view-hero .goals-credit { display: none; } }

/* Light hero: the usual light tokens with see-through surfaces. */
html.goals-view-hero .goals {
  --surface: rgba(255, 255, 255, 0.72);
  --plane: transparent;
  background: transparent;
  max-width: none;
  margin: 0;
  padding: 24px max(16px, 4vw) 64px;
}
html.goals-view-hero body.dark .goals, html.goals-view-hero[data-theme="dark"] .goals {
  --surface: rgba(18, 20, 24, 0.62);
  --plane: transparent;
  --ink: #f4f3ef;
  --ink-2: #d4d3cc;
  --muted: #b3b2ab;
  --grid: rgba(255, 255, 255, 0.12);
  --axis: rgba(255, 255, 255, 0.24);
  --border: rgba(255, 255, 255, 0.14);
  --accent: #4b93ea;
  --accent-ink: #9cc4f2;
  --accent-wash: rgba(75, 147, 234, 0.20);
  --series-1: #4b93ea;
  --series-2: #e06a37;
  --series-3: #22b07f;
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  html.goals-view-hero:not([data-theme="light"]) body.standalone .goals {
    --surface: rgba(18, 20, 24, 0.62); --plane: transparent;
    --ink: #f4f3ef; --ink-2: #d4d3cc; --muted: #b3b2ab;
    --grid: rgba(255, 255, 255, 0.12); --axis: rgba(255, 255, 255, 0.24); --border: rgba(255, 255, 255, 0.14);
    --accent: #4b93ea; --accent-ink: #9cc4f2; --accent-wash: rgba(75, 147, 234, 0.20);
    --series-1: #4b93ea; --series-2: #e06a37; --series-3: #22b07f;
    color-scheme: dark;
  }
}
/* Fill the fullscreen area below the localsite header (--fullscreen-height)
   less the page's 24px top and 64px bottom padding, so on a tall window the
   spare space collects above the tabs. */
html.goals-view-hero #goalsMain {
  display: flex; flex-direction: column;
  min-height: calc(var(--fullscreen-height) - 88px);
}
html.goals-view-hero #goalsMain > :not([hidden]),
html.goals-view-hero .goals-aside,
html.goals-view-hero #goalsBottom > .goals-side-plain {
  background: var(--hero-box);
  box-shadow: var(--hero-box-shadow);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border-radius: 16px;
  padding: 16px 20px;
  margin: 0 0 12px;
}
html.goals-view-hero .goals-aside { padding: 0; }
/* Objective cards (#objectives) sit straight on the photo: nearly solid
   white in light mode. */
html.goals-view-hero .goals-objective { background: var(--hero-card, var(--surface)); box-shadow: var(--hero-box-shadow); }
html.goals-view-hero #goalsBottom > .goals-side-plain { margin: 0; }
html.goals-view-hero #goalsMain > .goals-tabs { margin-top: auto; }
/* No spare space above the tabs while #goalsAside or #goalsBottom shows, and
   no window-filling height while #goalsBottom shows (classes set in goals.js). */
html.goals-view-hero .goals-with-aside #goalsMain > .goals-tabs,
html.goals-view-hero .goals-with-bottom #goalsMain > .goals-tabs { margin-top: 0; }
html.goals-view-hero .goals-with-bottom #goalsMain { min-height: 0; }
/* #goalsBottom sits 85px above the bottom of #goalsPage (which fills the window below
   the header), or lower when the content above it is taller. */
#goalsPage.goals-with-bottom { padding-bottom: 85px; }
#goalsPage > #goalsBottom { margin-top: auto; }
html.goals-view-hero #goalsMain > .goals-hero { --pad-top: 32px; --pad-x: 28px; padding: var(--pad-top) var(--pad-x); }
@media (min-width: 901px) {
  html.goals-view-hero #goalsMain { flex: 0 0 min(780px, 50vw); }
  /* The Goals, Data and Plan tabs have no aside: their column is as wide as two
     of the three Community Data cards (.goals-objectives) across the bottom. */
  html.goals-view-hero #goalsMain:is([data-tab="goals"], [data-tab="data"], [data-tab="plan"]) { flex-basis: calc((200% - var(--gap)) / 3); }
  html.goals-view-hero .goals-aside { flex: 1 1 0; max-width: 780px; }
}
@media (max-width: 900px) {
  html.goals-view-hero .goals { padding: 16px 16px 64px; }
  html.goals-view-hero #goalsMain { min-height: calc(var(--fullscreen-height) - 80px); }
  .goals-bg::after { background: var(--hero-wash-narrow); }
}

/* An event's headerTitle with an earth icon, in place of the header logo
   (goals.js). It carries .showEarth, so a click opens the Earth display. */
.goals-header-title {
  display: flex; align-items: center; gap: 8px; cursor: pointer; white-space: nowrap;
  font: 550 22px/1.2 system-ui, -apple-system, "Segoe UI", sans-serif; letter-spacing: -0.01em;
}
.goals-header-title .material-icons { font-size: 34px; opacity: 0.7; }
/* The header title stands in for localsite's site and location titles too.
   !important outranks the inline display localsite's show() sets. */
html.goals-has-header-title #headerLocTitleHolder { display: none !important; }
/* The earth.nullschool.net iframe that .showEarth opens (#mainEarthDisplay
   #mainframe): 78vh, taller than the 65vh localsite's template gives iframes.
   In #fullscreen, as on this page, base.css has it fill #fullscreen instead. */
#mainEarthDisplay iframe { min-height: 78vh; }
.goals-header-title:hover .material-icons { opacity: 1; }
.goals-header-title:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; border-radius: 6px; }

/* localsite headerbar on this page: deep navy blue fading to dark charcoal,
   in place of
   localsite's #eee, whenever .dark mode is off. Text and icons
   lighten to stay readable. */
:root:not(.dark) body:not(.dark) .headerbar {
  background-color: #071f45;
  background-image: linear-gradient(100deg, #061a3d 0%, #082450 30%, #4a4d53 100%);
  border-bottom: 0;
  color: #fff;
}
:root:not(.dark) body:not(.dark) .headerbar a:link,
:root:not(.dark) body:not(.dark) .headerbar a:visited,
:root:not(.dark) body:not(.dark) .headerbar .material-icons,
:root:not(.dark) body:not(.dark) #headerSiteTitle,
:root:not(.dark) body:not(.dark) #headerLocTitle { color: #fff; }
:root:not(.dark) body:not(.dark) .headerbar a:link:hover,
:root:not(.dark) body:not(.dark) .headerbar a:visited:hover { color: #b9cdf0; }
/* The header's earth icon (header_icon: earth, localsite base.css), softer than the white title until hovered. */
:root:not(.dark) body:not(.dark) #headerLogo .headerEarthIcon { color: #eee; opacity: .7; }
:root:not(.dark) body:not(.dark) #headerLogo a:hover .headerEarthIcon { color: #fff; opacity: 1; }
